WIP: dev #1

Draft
nub31 wants to merge 103 commits from dev into master
4 changed files with 110 additions and 44 deletions
Showing only changes of commit 26d365cf4f - Show all commits

View File

@@ -23,16 +23,16 @@ public sealed class Generator(List<NodeDefinition> nodes)
foreach (var node in nodes.OfType<NodeDefinitionFunc>()) foreach (var node in nodes.OfType<NodeDefinitionFunc>())
{ {
var parameters = node.Parameters.Select(x => $"{CType(x.Type)} {x.Name.Ident}"); var parameters = node.Parameters.Select(x => CType(x.Type, x.Name.Ident));
writer.WriteLine($"{CType(node.ReturnType)} {node.Name.Ident}({string.Join(", ", parameters)});"); writer.WriteLine($"{CType(node.ReturnType, node.Name.Ident)}({string.Join(", ", parameters)});");
} }
writer.WriteLine(); writer.WriteLine();
foreach (var node in nodes.OfType<NodeDefinitionFunc>()) foreach (var node in nodes.OfType<NodeDefinitionFunc>())
{ {
var parameters = node.Parameters.Select(x => $"{CType(x.Type)} {x.Name.Ident}"); var parameters = node.Parameters.Select(x => CType(x.Type, x.Name.Ident));
writer.WriteLine($"{CType(node.ReturnType)} {node.Name.Ident}({string.Join(", ", parameters)})"); writer.WriteLine($"{CType(node.ReturnType, node.Name.Ident)}({string.Join(", ", parameters)})");
writer.WriteLine("{"); writer.WriteLine("{");
using (writer.Indent()) using (writer.Indent())
{ {
@@ -56,6 +56,9 @@ public sealed class Generator(List<NodeDefinition> nodes)
case NodeStatementFuncCall statement: case NodeStatementFuncCall statement:
EmitStatementFuncCall(statement); EmitStatementFuncCall(statement);
break; break;
case NodeStatementReturn statement:
EmitStatementReturn(statement);
break;
} }
} }
@@ -78,6 +81,12 @@ public sealed class Generator(List<NodeDefinition> nodes)
writer.WriteLine($"{name}({string.Join(", ", parameterValues)});"); writer.WriteLine($"{name}({string.Join(", ", parameterValues)});");
} }
private void EmitStatementReturn(NodeStatementReturn statement)
{
var value = EmitExpression(statement.Value);
writer.WriteLine($"return {value};");
}
private string EmitExpression(NodeExpression node) private string EmitExpression(NodeExpression node)
{ {
return node switch return node switch
@@ -109,35 +118,62 @@ public sealed class Generator(List<NodeDefinition> nodes)
return expression.Value.Ident; return expression.Value.Ident;
} }
private static string CType(NodeType node) private static string CType(NodeType type, string? variableName = null)
{ {
return node switch return type switch
{ {
NodeTypeCustom type => $"struct {type.Name.Ident}", NodeTypeVoid => "void" + (variableName != null ? $" {variableName}" : ""),
NodeTypeFloat type => type.Width switch NodeTypeBool => "bool" + (variableName != null ? $" {variableName}" : ""),
NodeTypeSInt intType => CTypeSInt(intType, variableName),
NodeTypeUInt intType => CTypeUInt(intType, variableName),
NodeTypePointer ptr => CType(ptr.To) + "*" + (variableName != null ? $" {variableName}" : ""),
NodeTypeString => "struct string" + (variableName != null ? $" {variableName}" : ""),
NodeTypeFunc fn => CTypeFunc(fn, variableName),
};
}
private static string CTypeSInt(NodeTypeSInt intType, string? varName)
{ {
32 => "float", var cType = intType.Width switch
64 => "double",
},
NodeTypePointer type => $"{CType(type.To)}*",
NodeTypeSInt type => type.Width switch
{ {
8 => "byte", 8 => "char",
16 => "short", 16 => "short",
32 => "int", 32 => "int",
64 => "long", 64 => "long long",
}, };
NodeTypeUInt type => type.Width switch
return cType + (varName != null ? $" {varName}" : "");
}
private static string CTypeUInt(NodeTypeUInt intType, string? varName)
{ {
8 => "unsigned byte", var cType = intType.Width switch
{
8 => "unsigned char",
16 => "unsigned short", 16 => "unsigned short",
32 => "unsigned int", 32 => "unsigned int",
64 => "unsigned long", 64 => "unsigned long long",
},
NodeTypeString => "struct string",
NubTypeVoid => "void",
_ => throw new ArgumentOutOfRangeException(nameof(node))
}; };
return cType + (varName != null ? $" {varName}" : "");
}
private static string CTypeFunc(NodeTypeFunc fn, string? varName)
{
var returnType = CType(fn.ReturnType);
var parameters = string.Join(", ", fn.Parameters.Select(p => CType(p)));
if (string.IsNullOrEmpty(parameters))
{
parameters = "void";
}
if (varName != null)
{
return $"{returnType} (*{varName})({parameters})";
}
return $"{returnType} (*)({parameters})";
} }
} }

View File

@@ -64,6 +64,12 @@ public sealed class Parser(List<Token> tokens)
return new NodeStatementBlock(TokensFrom(startIndex), statements); return new NodeStatementBlock(TokensFrom(startIndex), statements);
} }
if (TryExpectKeyword(Keyword.Return))
{
var value = ParseExpression();
return new NodeStatementReturn(TokensFrom(startIndex), value);
}
var expression = ParseExpression(); var expression = ParseExpression();
var parameters = new List<NodeExpression>(); var parameters = new List<NodeExpression>();
@@ -111,14 +117,32 @@ public sealed class Parser(List<Token> tokens)
return new NodeTypePointer(TokensFrom(startIndex), to); return new NodeTypePointer(TokensFrom(startIndex), to);
} }
if (TryExpectKeyword(Keyword.Func))
{
var parameters = new List<NodeType>();
ExpectSymbol(Symbol.OpenParen);
while (!TryExpectSymbol(Symbol.CloseParen))
{
parameters.Add(ParseType());
}
ExpectSymbol(Symbol.Colon);
var returnType = ParseType();
return new NodeTypeFunc(TokensFrom(startIndex), parameters, returnType);
}
if (TryExpectIdent(out var ident)) if (TryExpectIdent(out var ident))
{ {
switch (ident.Ident) switch (ident.Ident)
{ {
case "void": case "void":
return new NubTypeVoid(TokensFrom(startIndex)); return new NodeTypeVoid(TokensFrom(startIndex));
case "string": case "string":
return new NodeTypeString(TokensFrom(startIndex)); return new NodeTypeString(TokensFrom(startIndex));
case "bool":
return new NodeTypeBool(TokensFrom(startIndex));
case "i8": case "i8":
return new NodeTypeSInt(TokensFrom(startIndex), 8); return new NodeTypeSInt(TokensFrom(startIndex), 8);
case "i16": case "i16":
@@ -135,10 +159,6 @@ public sealed class Parser(List<Token> tokens)
return new NodeTypeUInt(TokensFrom(startIndex), 32); return new NodeTypeUInt(TokensFrom(startIndex), 32);
case "u64": case "u64":
return new NodeTypeUInt(TokensFrom(startIndex), 64); return new NodeTypeUInt(TokensFrom(startIndex), 64);
case "f32":
return new NodeTypeFloat(TokensFrom(startIndex), 32);
case "f64":
return new NodeTypeFloat(TokensFrom(startIndex), 64);
default: default:
return new NodeTypeCustom(TokensFrom(startIndex), ident); return new NodeTypeCustom(TokensFrom(startIndex), ident);
} }
@@ -272,8 +292,7 @@ public abstract class Node(List<Token> tokens)
public abstract class NodeDefinition(List<Token> tokens) : Node(tokens); public abstract class NodeDefinition(List<Token> tokens) : Node(tokens);
public sealed class NodeDefinitionFunc(List<Token> tokens, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeStatement body, NodeType returnType) public sealed class NodeDefinitionFunc(List<Token> tokens, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeStatement body, NodeType returnType) : NodeDefinition(tokens)
: NodeDefinition(tokens)
{ {
public readonly TokenIdent Name = name; public readonly TokenIdent Name = name;
public readonly List<Param> Parameters = parameters; public readonly List<Param> Parameters = parameters;
@@ -300,6 +319,11 @@ public sealed class NodeStatementFuncCall(List<Token> tokens, NodeExpression fun
public readonly List<NodeExpression> Parameters = parameters; public readonly List<NodeExpression> Parameters = parameters;
} }
internal class NodeStatementReturn(List<Token> tokens, NodeExpression value) : NodeStatement(tokens)
{
public readonly NodeExpression Value = value;
}
public abstract class NodeExpression(List<Token> tokens) : Node(tokens); public abstract class NodeExpression(List<Token> tokens) : Node(tokens);
public sealed class NodeExpressionIntLiteral(List<Token> tokens, TokenIntLiteral value) : NodeExpression(tokens) public sealed class NodeExpressionIntLiteral(List<Token> tokens, TokenIntLiteral value) : NodeExpression(tokens)
@@ -324,7 +348,7 @@ public sealed class NodeExpressionIdent(List<Token> tokens, TokenIdent value) :
public abstract class NodeType(List<Token> tokens) : Node(tokens); public abstract class NodeType(List<Token> tokens) : Node(tokens);
public sealed class NubTypeVoid(List<Token> tokens) : NodeType(tokens); public sealed class NodeTypeVoid(List<Token> tokens) : NodeType(tokens);
public sealed class NodeTypeUInt(List<Token> tokens, int width) : NodeType(tokens) public sealed class NodeTypeUInt(List<Token> tokens, int width) : NodeType(tokens)
{ {
@@ -336,10 +360,7 @@ public sealed class NodeTypeSInt(List<Token> tokens, int width) : NodeType(token
public readonly int Width = width; public readonly int Width = width;
} }
public sealed class NodeTypeFloat(List<Token> tokens, int width) : NodeType(tokens) public sealed class NodeTypeBool(List<Token> tokens) : NodeType(tokens);
{
public readonly int Width = width;
}
public sealed class NodeTypeString(List<Token> tokens) : NodeType(tokens); public sealed class NodeTypeString(List<Token> tokens) : NodeType(tokens);
@@ -352,3 +373,9 @@ public sealed class NodeTypePointer(List<Token> tokens, NodeType to) : NodeType(
{ {
public readonly NodeType To = to; public readonly NodeType To = to;
} }
public sealed class NodeTypeFunc(List<Token> tokens, List<NodeType> parameters, NodeType returnType) : NodeType(tokens)
{
public readonly List<NodeType> Parameters = parameters;
public readonly NodeType ReturnType = returnType;
}

View File

@@ -1,11 +1,12 @@
using Compiler; using Compiler;
const string contents = """ const string contents = """
func main(): void { func main(): i32 {
do_something("test") do_something("test")
return 69
} }
func do_something(text: string): void { func do_something(text: string): func(i32 u32): void {
} }
"""; """;

View File

@@ -279,6 +279,7 @@ public sealed class Tokenizer(string contents)
"func" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Func), "func" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Func),
"let" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Let), "let" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Let),
"if" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.If), "if" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.If),
"return" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Return),
"true" => new TokenBoolLiteral(line, startColumn, column - startColumn, true), "true" => new TokenBoolLiteral(line, startColumn, column - startColumn, true),
"false" => new TokenBoolLiteral(line, startColumn, column - startColumn, false), "false" => new TokenBoolLiteral(line, startColumn, column - startColumn, false),
_ => new TokenIdent(line, startColumn, column - startColumn, value) _ => new TokenIdent(line, startColumn, column - startColumn, value)
@@ -397,6 +398,7 @@ public enum Keyword
Func, Func,
Let, Let,
If, If,
Return,
} }
public sealed class TokenKeyword(int line, int column, int length, Keyword keyword) : Token(line, column, length) public sealed class TokenKeyword(int line, int column, int length, Keyword keyword) : Token(line, column, length)