This commit is contained in:
nub31
2025-05-04 20:52:24 +02:00
parent 6755342cdb
commit 2e7249fc87
10 changed files with 123 additions and 83 deletions

View File

@@ -1,9 +1,5 @@
let SYS_WRITE = 1;
let STD_OUT = 1;
let STD_ERR = 2;
func print(msg: string) { func print(msg: string) {
syscall(SYS_WRITE, STD_OUT, msg, str_len(msg)); syscall(1, 1, msg, str_len(msg));
} }
func print(value: int64) { func print(value: int64) {

View File

@@ -17,11 +17,6 @@ public class Generator
public string Generate() public string Generate()
{ {
foreach (var externFuncDefinition in _definitions.OfType<ExternFuncDefinitionNode>())
{
GenerateExternFuncDefinition(externFuncDefinition);
}
foreach (var funcDefinition in _definitions.OfType<LocalFuncDefinitionNode>()) foreach (var funcDefinition in _definitions.OfType<LocalFuncDefinitionNode>())
{ {
GenerateFuncDefinition(funcDefinition); GenerateFuncDefinition(funcDefinition);
@@ -30,12 +25,40 @@ public class Generator
return _builder.ToString(); return _builder.ToString();
} }
private void GenerateExternFuncDefinition(ExternFuncDefinitionNode externFuncDefinition) private string QbeTypeName(NubType type)
{ {
if (type.Equals(NubType.Int64))
{
return "l";
}
if (type.Equals(NubType.Int32))
{
return "w";
}
if (type.Equals(NubType.String))
{
return "l";
}
throw new Exception($"Invalid qbe type {type}");
} }
private void GenerateFuncDefinition(LocalFuncDefinitionNode node) private void GenerateFuncDefinition(LocalFuncDefinitionNode node)
{ {
var parameters = node.Parameters.Select(p => $"{QbeTypeName(p.Type)} %{p.Name}");
_builder.Append("function ");
if (node.ReturnType.HasValue)
{
_builder.Append($"{QbeTypeName(node.ReturnType.Value)} ");
}
_builder.Append(node.Name);
_builder.AppendLine($"({string.Join(", ", parameters)}) {{");
_builder.AppendLine("@start");
GenerateBlock(node.Body, _symbolTable.ResolveLocalFunc(node.Name, node.Parameters.Select(x => x.Type).ToList()));
_builder.AppendLine("}");
} }
private void GenerateBlock(BlockNode block, LocalFuncDef func) private void GenerateBlock(BlockNode block, LocalFuncDef func)
@@ -65,9 +88,6 @@ public class Generator
case ReturnNode @return: case ReturnNode @return:
GenerateReturn(@return, func); GenerateReturn(@return, func);
break; break;
case SyscallStatementNode syscallStatement:
GenerateSyscall(syscallStatement.Syscall, func);
break;
case VariableAssignmentNode variableAssignment: case VariableAssignmentNode variableAssignment:
GenerateVariableAssignment(variableAssignment, func); GenerateVariableAssignment(variableAssignment, func);
break; break;
@@ -132,9 +152,6 @@ public class Generator
case StructMemberAccessorNode structMemberAccessor: case StructMemberAccessorNode structMemberAccessor:
GenerateStructMemberAccessor(structMemberAccessor, func); GenerateStructMemberAccessor(structMemberAccessor, func);
break; break;
case SyscallExpressionNode syscallExpression:
GenerateSyscall(syscallExpression.Syscall, func);
break;
default: default:
throw new ArgumentOutOfRangeException(nameof(expression)); throw new ArgumentOutOfRangeException(nameof(expression));
} }
@@ -163,8 +180,4 @@ public class Generator
private void GenerateFuncCall(FuncCall funcCall, LocalFuncDef func) private void GenerateFuncCall(FuncCall funcCall, LocalFuncDef func)
{ {
} }
private void GenerateSyscall(Syscall syscall, LocalFuncDef func)
{
}
} }

View File

@@ -9,6 +9,8 @@ public class SymbolTable
var externFuncDefs = new List<ExternFuncDef>(); var externFuncDefs = new List<ExternFuncDef>();
var localFuncDefs = new List<LocalFuncDef>(); var localFuncDefs = new List<LocalFuncDef>();
var strings = new List<string>();
foreach (var node in program) foreach (var node in program)
{ {
switch (node) switch (node)
@@ -29,7 +31,7 @@ public class SymbolTable
var parameters = localFuncDefinitionNode.Parameters.Select(parameter => new Variable(parameter.Name, parameter.Type)).ToList(); var parameters = localFuncDefinitionNode.Parameters.Select(parameter => new Variable(parameter.Name, parameter.Type)).ToList();
var localVariables = new List<Variable>(); var localVariables = new List<Variable>();
FindVariables(localFuncDefinitionNode.Body); Search(localFuncDefinitionNode.Body);
localFuncDefs.Add(new LocalFuncDef localFuncDefs.Add(new LocalFuncDef
{ {
@@ -40,27 +42,97 @@ public class SymbolTable
}); });
break; break;
void FindVariables(BlockNode blockNode) void Search(BlockNode blockNode)
{ {
foreach (var statement in blockNode.Statements) foreach (var statement in blockNode.Statements)
{ {
switch (statement) switch (statement)
{ {
case FuncCallStatementNode funcCallStatementNode:
{
foreach (var parameter in funcCallStatementNode.FuncCall.Parameters)
{
FindStrings(parameter);
}
break;
}
case IfNode ifNode: case IfNode ifNode:
{ {
FindVariables(ifNode.Body); SearchIf(ifNode);
break;
}
case ReturnNode returnNode:
{
if (returnNode.Value.HasValue)
{
FindStrings(returnNode.Value.Value);
}
break; break;
} }
case WhileNode whileNode: case WhileNode whileNode:
{ {
FindVariables(whileNode.Body); FindStrings(whileNode.Condition);
Search(whileNode.Body);
break; break;
} }
case VariableAssignmentNode variableAssignmentNode: case VariableAssignmentNode variableAssignmentNode:
{ {
FindStrings(variableAssignmentNode.Value);
localVariables.Add(new Variable(variableAssignmentNode.Name, variableAssignmentNode.Value.Type)); localVariables.Add(new Variable(variableAssignmentNode.Name, variableAssignmentNode.Value.Type));
break; break;
} }
case VariableReassignmentNode variableReassignmentNode:
{
FindStrings(variableReassignmentNode.Value);
break;
}
}
}
}
void SearchIf(IfNode ifNode)
{
FindStrings(ifNode.Condition);
Search(ifNode.Body);
if (ifNode.Else.HasValue)
{
ifNode.Else.Value.Match(SearchIf, Search);
}
}
void FindStrings(ExpressionNode expressionNode)
{
switch (expressionNode)
{
case BinaryExpressionNode binaryExpressionNode:
{
FindStrings(binaryExpressionNode.Left);
FindStrings(binaryExpressionNode.Right);
break;
}
case FuncCallExpressionNode funcCallExpressionNode:
{
foreach (var parameter in funcCallExpressionNode.FuncCall.Parameters)
{
FindStrings(parameter);
}
break;
}
case LiteralNode literalNode:
{
if (literalNode.LiteralType.Equals(NubType.String))
{
strings.Add(literalNode.Literal);
}
break;
}
case StructInitializerNode structInitializerNode:
{
foreach (var initializer in structInitializerNode.Initializers)
{
FindStrings(initializer.Value);
}
break;
} }
} }
} }
@@ -76,18 +148,31 @@ public class SymbolTable
} }
} }
return new SymbolTable(externFuncDefs, localFuncDefs); return new SymbolTable(strings, externFuncDefs, localFuncDefs);
} }
private readonly List<string> _strings;
private readonly List<ExternFuncDef> _externFuncDefs; private readonly List<ExternFuncDef> _externFuncDefs;
private readonly List<LocalFuncDef> _localFuncDefs; private readonly List<LocalFuncDef> _localFuncDefs;
private SymbolTable(List<ExternFuncDef> externFuncDefs, List<LocalFuncDef> localFuncDefs) private SymbolTable(List<string> strings, List<ExternFuncDef> externFuncDefs, List<LocalFuncDef> localFuncDefs)
{ {
_strings = strings;
_externFuncDefs = externFuncDefs; _externFuncDefs = externFuncDefs;
_localFuncDefs = localFuncDefs; _localFuncDefs = localFuncDefs;
} }
public int ResolveString(string value)
{
var index = _strings.IndexOf(value);
if (index == -1)
{
throw new Exception("String not found: " + value);
}
return index;
}
public FuncDef ResolveFunc(string name, List<NubType> parameters) public FuncDef ResolveFunc(string name, List<NubType> parameters)
{ {
var matching = _externFuncDefs.Concat<FuncDef>(_localFuncDefs).Where(funcDef => funcDef.SignatureMatches(name, parameters)).ToArray(); var matching = _externFuncDefs.Concat<FuncDef>(_localFuncDefs).Where(funcDef => funcDef.SignatureMatches(name, parameters)).ToArray();

View File

@@ -160,11 +160,6 @@ public class Parser
ExpectSymbol(Symbol.Semicolon); ExpectSymbol(Symbol.Semicolon);
if (identifier.Value == "syscall")
{
return new SyscallStatementNode(new Syscall(parameters));
}
return new FuncCallStatementNode(new FuncCall(identifier.Value, parameters)); return new FuncCallStatementNode(new FuncCall(identifier.Value, parameters));
} }
case Symbol.Assign: case Symbol.Assign:
@@ -422,11 +417,6 @@ public class Parser
TryExpectSymbol(Symbol.Comma); TryExpectSymbol(Symbol.Comma);
} }
if (identifier.Value == "syscall")
{
return new SyscallExpressionNode(new Syscall(parameters));
}
return new FuncCallExpressionNode(new FuncCall(identifier.Value, parameters)); return new FuncCallExpressionNode(new FuncCall(identifier.Value, parameters));
} }
} }

View File

@@ -1,6 +0,0 @@
namespace Nub.Lang.Frontend.Parsing;
public class Syscall(List<ExpressionNode> parameters)
{
public List<ExpressionNode> Parameters { get; } = parameters;
}

View File

@@ -1,6 +0,0 @@
namespace Nub.Lang.Frontend.Parsing;
public class SyscallExpressionNode(Syscall syscall) : ExpressionNode
{
public Syscall Syscall { get; } = syscall;
}

View File

@@ -1,6 +0,0 @@
namespace Nub.Lang.Frontend.Parsing;
public class SyscallStatementNode(Syscall syscall) : StatementNode
{
public Syscall Syscall { get; } = syscall;
}

View File

@@ -99,9 +99,6 @@ public class ExpressionTyper
case ReturnNode returnNode: case ReturnNode returnNode:
PopulateReturn(returnNode); PopulateReturn(returnNode);
break; break;
case SyscallStatementNode syscall:
PopulateSyscallStatement(syscall);
break;
case VariableAssignmentNode variableAssignment: case VariableAssignmentNode variableAssignment:
PopulateVariableAssignment(variableAssignment); PopulateVariableAssignment(variableAssignment);
break; break;
@@ -138,14 +135,6 @@ public class ExpressionTyper
} }
} }
private void PopulateSyscallStatement(SyscallStatementNode syscall)
{
foreach (var parameter in syscall.Syscall.Parameters)
{
PopulateExpression(parameter);
}
}
private void PopulateReturn(ReturnNode returnNode) private void PopulateReturn(ReturnNode returnNode)
{ {
if (returnNode.Value.HasValue) if (returnNode.Value.HasValue)
@@ -193,9 +182,6 @@ public class ExpressionTyper
case StructMemberAccessorNode structMemberAccessor: case StructMemberAccessorNode structMemberAccessor:
GenerateStructMemberAccessorNode(structMemberAccessor); GenerateStructMemberAccessorNode(structMemberAccessor);
break; break;
case SyscallExpressionNode syscall:
PopulateSyscallExpression(syscall);
break;
default: default:
throw new ArgumentOutOfRangeException(nameof(expression)); throw new ArgumentOutOfRangeException(nameof(expression));
} }
@@ -315,16 +301,6 @@ public class ExpressionTyper
structMemberAccessor.Type = tmp.Type; structMemberAccessor.Type = tmp.Type;
} }
private void PopulateSyscallExpression(SyscallExpressionNode syscall)
{
foreach (var parameter in syscall.Syscall.Parameters)
{
PopulateExpression(parameter);
}
syscall.Type = new NubType("int64", []);
}
private class Variable(string name, NubType type) private class Variable(string name, NubType type)
{ {
public string Name { get; } = name; public string Name { get; } = name;

View File

@@ -13,11 +13,8 @@ public sealed class NubType
public static NubType Int64 => new("int64", []); public static NubType Int64 => new("int64", []);
public static NubType Int32 => new("int32", []); public static NubType Int32 => new("int32", []);
public static NubType Int16 => new("int16", []);
public static NubType Int8 => new("int8", []);
public static NubType Bool => new("bool", []); public static NubType Bool => new("bool", []);
public static NubType String => new("string", []); public static NubType String => new("string", []);
public static NubType Array(NubType innerType) => new("array", [innerType]);
public override bool Equals(object? obj) public override bool Equals(object? obj)
{ {

View File

@@ -50,7 +50,8 @@ internal static class Program
var generator = new Generator(definitions); var generator = new Generator(definitions);
var asm = generator.Generate(); var asm = generator.Generate();
File.WriteAllText(output, asm); // File.WriteAllText(output, asm);
Console.WriteLine(asm);
return 0; return 0;
} }