WIP: dev #1
@@ -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,36 +118,63 @@ 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),
|
||||||
32 => "float",
|
NodeTypeUInt intType => CTypeUInt(intType, variableName),
|
||||||
64 => "double",
|
NodeTypePointer ptr => CType(ptr.To) + "*" + (variableName != null ? $" {variableName}" : ""),
|
||||||
},
|
NodeTypeString => "struct string" + (variableName != null ? $" {variableName}" : ""),
|
||||||
NodeTypePointer type => $"{CType(type.To)}*",
|
NodeTypeFunc fn => CTypeFunc(fn, variableName),
|
||||||
NodeTypeSInt type => type.Width switch
|
|
||||||
{
|
|
||||||
8 => "byte",
|
|
||||||
16 => "short",
|
|
||||||
32 => "int",
|
|
||||||
64 => "long",
|
|
||||||
},
|
|
||||||
NodeTypeUInt type => type.Width switch
|
|
||||||
{
|
|
||||||
8 => "unsigned byte",
|
|
||||||
16 => "unsigned short",
|
|
||||||
32 => "unsigned int",
|
|
||||||
64 => "unsigned long",
|
|
||||||
},
|
|
||||||
NodeTypeString => "struct string",
|
|
||||||
NubTypeVoid => "void",
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string CTypeSInt(NodeTypeSInt intType, string? varName)
|
||||||
|
{
|
||||||
|
var cType = intType.Width switch
|
||||||
|
{
|
||||||
|
8 => "char",
|
||||||
|
16 => "short",
|
||||||
|
32 => "int",
|
||||||
|
64 => "long long",
|
||||||
|
};
|
||||||
|
|
||||||
|
return cType + (varName != null ? $" {varName}" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CTypeUInt(NodeTypeUInt intType, string? varName)
|
||||||
|
{
|
||||||
|
var cType = intType.Width switch
|
||||||
|
{
|
||||||
|
8 => "unsigned char",
|
||||||
|
16 => "unsigned short",
|
||||||
|
32 => "unsigned int",
|
||||||
|
64 => "unsigned long long",
|
||||||
|
};
|
||||||
|
|
||||||
|
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})";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class IndentedTextWriter
|
internal class IndentedTextWriter
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user