Strings
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Nub.Lang.Frontend.Parsing;
|
|
||||||
|
|
||||||
public class Syscall(List<ExpressionNode> parameters)
|
|
||||||
{
|
|
||||||
public List<ExpressionNode> Parameters { get; } = parameters;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Nub.Lang.Frontend.Parsing;
|
|
||||||
|
|
||||||
public class SyscallExpressionNode(Syscall syscall) : ExpressionNode
|
|
||||||
{
|
|
||||||
public Syscall Syscall { get; } = syscall;
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Nub.Lang.Frontend.Parsing;
|
|
||||||
|
|
||||||
public class SyscallStatementNode(Syscall syscall) : StatementNode
|
|
||||||
{
|
|
||||||
public Syscall Syscall { get; } = syscall;
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user