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>())
{
var parameters = node.Parameters.Select(x => $"{CType(x.Type)} {x.Name.Ident}");
writer.WriteLine($"{CType(node.ReturnType)} {node.Name.Ident}({string.Join(", ", parameters)});");
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();
foreach (var node in nodes.OfType<NodeDefinitionFunc>())
{
var parameters = node.Parameters.Select(x => $"{CType(x.Type)} {x.Name.Ident}");
writer.WriteLine($"{CType(node.ReturnType)} {node.Name.Ident}({string.Join(", ", parameters)})");
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("{");
using (writer.Indent())
{
@@ -56,6 +56,9 @@ public sealed class Generator(List<NodeDefinition> nodes)
case NodeStatementFuncCall statement:
EmitStatementFuncCall(statement);
break;
case NodeStatementReturn statement:
EmitStatementReturn(statement);
break;
}
}
@@ -78,6 +81,12 @@ public sealed class Generator(List<NodeDefinition> nodes)
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)
{
return node switch
@@ -109,36 +118,63 @@ public sealed class Generator(List<NodeDefinition> nodes)
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}",
NodeTypeFloat type => type.Width switch
{
32 => "float",
64 => "double",
},
NodeTypePointer type => $"{CType(type.To)}*",
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))
NodeTypeVoid => "void" + (variableName != null ? $" {variableName}" : ""),
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)
{
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

View File

@@ -64,6 +64,12 @@ public sealed class Parser(List<Token> tokens)
return new NodeStatementBlock(TokensFrom(startIndex), statements);
}
if (TryExpectKeyword(Keyword.Return))
{
var value = ParseExpression();
return new NodeStatementReturn(TokensFrom(startIndex), value);
}
var expression = ParseExpression();
var parameters = new List<NodeExpression>();
@@ -111,14 +117,32 @@ public sealed class Parser(List<Token> tokens)
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))
{
switch (ident.Ident)
{
case "void":
return new NubTypeVoid(TokensFrom(startIndex));
return new NodeTypeVoid(TokensFrom(startIndex));
case "string":
return new NodeTypeString(TokensFrom(startIndex));
case "bool":
return new NodeTypeBool(TokensFrom(startIndex));
case "i8":
return new NodeTypeSInt(TokensFrom(startIndex), 8);
case "i16":
@@ -135,10 +159,6 @@ public sealed class Parser(List<Token> tokens)
return new NodeTypeUInt(TokensFrom(startIndex), 32);
case "u64":
return new NodeTypeUInt(TokensFrom(startIndex), 64);
case "f32":
return new NodeTypeFloat(TokensFrom(startIndex), 32);
case "f64":
return new NodeTypeFloat(TokensFrom(startIndex), 64);
default:
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 sealed class NodeDefinitionFunc(List<Token> tokens, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeStatement body, NodeType returnType)
: NodeDefinition(tokens)
public sealed class NodeDefinitionFunc(List<Token> tokens, TokenIdent name, List<NodeDefinitionFunc.Param> parameters, NodeStatement body, NodeType returnType) : NodeDefinition(tokens)
{
public readonly TokenIdent Name = name;
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;
}
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 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 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)
{
@@ -336,10 +360,7 @@ public sealed class NodeTypeSInt(List<Token> tokens, int width) : NodeType(token
public readonly int Width = width;
}
public sealed class NodeTypeFloat(List<Token> tokens, int width) : NodeType(tokens)
{
public readonly int Width = width;
}
public sealed class NodeTypeBool(List<Token> tokens) : NodeType(tokens);
public sealed class NodeTypeString(List<Token> tokens) : NodeType(tokens);
@@ -351,4 +372,10 @@ public sealed class NodeTypeCustom(List<Token> tokens, TokenIdent name) : NodeTy
public sealed class NodeTypePointer(List<Token> tokens, NodeType to) : NodeType(tokens)
{
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;
const string contents = """
func main(): void {
func main(): i32 {
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),
"let" => new TokenKeyword(line, startColumn, column - startColumn, Keyword.Let),
"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),
"false" => new TokenBoolLiteral(line, startColumn, column - startColumn, false),
_ => new TokenIdent(line, startColumn, column - startColumn, value)
@@ -397,6 +398,7 @@ public enum Keyword
Func,
Let,
If,
Return,
}
public sealed class TokenKeyword(int line, int column, int length, Keyword keyword) : Token(line, column, length)