not working
This commit is contained in:
@@ -7,6 +7,7 @@ using Syntax.Diagnostics;
|
|||||||
using Syntax.Parsing;
|
using Syntax.Parsing;
|
||||||
using Syntax.Tokenization;
|
using Syntax.Tokenization;
|
||||||
using Syntax.Typing;
|
using Syntax.Typing;
|
||||||
|
using Binder = Syntax.Typing.Binder;
|
||||||
|
|
||||||
const string BIN_DIR = "bin";
|
const string BIN_DIR = "bin";
|
||||||
const string BIN_INT_DIR = "bin-int";
|
const string BIN_INT_DIR = "bin-int";
|
||||||
@@ -25,8 +26,7 @@ Directory.CreateDirectory(BIN_DIR);
|
|||||||
Directory.CreateDirectory(BIN_INT_DIR);
|
Directory.CreateDirectory(BIN_INT_DIR);
|
||||||
|
|
||||||
var diagnostics = new List<Diagnostic>();
|
var diagnostics = new List<Diagnostic>();
|
||||||
var compilationUnits = new List<CompilationUnit>();
|
var syntaxTrees = new List<SyntaxTree>();
|
||||||
var sourceTexts = new Dictionary<CompilationUnit, SourceText>();
|
|
||||||
|
|
||||||
foreach (var file in args)
|
foreach (var file in args)
|
||||||
{
|
{
|
||||||
@@ -45,13 +45,12 @@ foreach (var file in args)
|
|||||||
var tokenizeResult = Tokenizer.Tokenize(sourceText, out var tokenizerDiagnostics);
|
var tokenizeResult = Tokenizer.Tokenize(sourceText, out var tokenizerDiagnostics);
|
||||||
diagnostics.AddRange(tokenizerDiagnostics);
|
diagnostics.AddRange(tokenizerDiagnostics);
|
||||||
|
|
||||||
var compilationUnit = Parser.ParseFile(tokenizeResult, out var parseDiagnostics);
|
var syntaxTree = Parser.ParseFile(tokenizeResult, file, out var parseDiagnostics);
|
||||||
diagnostics.AddRange(parseDiagnostics);
|
diagnostics.AddRange(parseDiagnostics);
|
||||||
|
|
||||||
if (compilationUnit != null)
|
if (syntaxTree != null)
|
||||||
{
|
{
|
||||||
compilationUnits.Add(compilationUnit);
|
syntaxTrees.Add(syntaxTree);
|
||||||
sourceTexts[compilationUnit] = sourceText;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -59,14 +58,17 @@ foreach (var file in args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var definitionTable = new DefinitionTable(compilationUnits);
|
var definitionTable = new DefinitionTable(syntaxTrees);
|
||||||
|
|
||||||
foreach (var compilationUnit in compilationUnits)
|
var boundSyntaxTrees = new List<BoundSyntaxTree>();
|
||||||
|
|
||||||
|
foreach (var syntaxTree in syntaxTrees)
|
||||||
{
|
{
|
||||||
TypeChecker.Check(compilationUnit, definitionTable, out var typeCheckerDiagnostics);
|
boundSyntaxTrees.Add(Binder.Bind(syntaxTree, definitionTable));
|
||||||
diagnostics.AddRange(typeCheckerDiagnostics);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var boundDefinitionTable = new BoundDefinitionTable(boundSyntaxTrees);
|
||||||
|
|
||||||
foreach (var diagnostic in diagnostics)
|
foreach (var diagnostic in diagnostics)
|
||||||
{
|
{
|
||||||
Console.Error.WriteLine(diagnostic.FormatANSI());
|
Console.Error.WriteLine(diagnostic.FormatANSI());
|
||||||
@@ -79,16 +81,16 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro
|
|||||||
|
|
||||||
var objectFiles = new List<string>();
|
var objectFiles = new List<string>();
|
||||||
|
|
||||||
foreach (var compilationUnit in compilationUnits)
|
foreach (var boundSyntaxTree in boundSyntaxTrees)
|
||||||
{
|
{
|
||||||
var relativeFilePath = Path.GetRelativePath(Environment.CurrentDirectory, sourceTexts[compilationUnit].Path);
|
var relativeFilePath = Path.GetRelativePath(Environment.CurrentDirectory, boundSyntaxTree.FilePath);
|
||||||
var outputPath = Path.Combine(BIN_INT_DIR, "program", relativeFilePath);
|
var outputPath = Path.Combine(BIN_INT_DIR, "program", relativeFilePath);
|
||||||
|
|
||||||
var outputDirectory = Path.GetDirectoryName(outputPath);
|
var outputDirectory = Path.GetDirectoryName(outputPath);
|
||||||
Debug.Assert(!string.IsNullOrWhiteSpace(outputDirectory));
|
Debug.Assert(!string.IsNullOrWhiteSpace(outputDirectory));
|
||||||
Directory.CreateDirectory(outputDirectory);
|
Directory.CreateDirectory(outputDirectory);
|
||||||
|
|
||||||
var ssa = QBEGenerator.Emit(compilationUnit, definitionTable);
|
var ssa = QBEGenerator.Emit(boundSyntaxTree, boundDefinitionTable);
|
||||||
var ssaPath = Path.ChangeExtension(outputPath, "ssa");
|
var ssaPath = Path.ChangeExtension(outputPath, "ssa");
|
||||||
File.WriteAllText(ssaPath, ssa);
|
File.WriteAllText(ssaPath, ssa);
|
||||||
|
|
||||||
|
|||||||
@@ -2,23 +2,23 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Syntax;
|
using Syntax;
|
||||||
using Syntax.Parsing;
|
|
||||||
using Syntax.Parsing.Node;
|
using Syntax.Parsing.Node;
|
||||||
using Syntax.Tokenization;
|
using Syntax.Tokenization;
|
||||||
using Syntax.Typing;
|
using Syntax.Typing;
|
||||||
|
using Syntax.Typing.BoundNode;
|
||||||
|
|
||||||
namespace Generation.QBE;
|
namespace Generation.QBE;
|
||||||
|
|
||||||
public static class QBEGenerator
|
public static class QBEGenerator
|
||||||
{
|
{
|
||||||
private static CompilationUnit _compilationUnit = null!;
|
private static BoundSyntaxTree _syntaxTree = null!;
|
||||||
private static DefinitionTable _definitionTable = null!;
|
private static BoundDefinitionTable _definitionTable = null!;
|
||||||
|
|
||||||
private static StringBuilder _builder = new();
|
private static StringBuilder _builder = new();
|
||||||
private static List<CStringLiteral> _cStringLiterals = [];
|
private static List<CStringLiteral> _cStringLiterals = [];
|
||||||
private static Stack<string> _breakLabels = [];
|
private static Stack<string> _breakLabels = [];
|
||||||
private static Stack<string> _continueLabels = [];
|
private static Stack<string> _continueLabels = [];
|
||||||
private static Queue<(AnonymousFuncNode Func, string Name)> _anonymousFunctions = [];
|
private static Queue<(BoundAnonymousFuncNode Func, string Name)> _anonymousFunctions = [];
|
||||||
private static Stack<Variable> _variables = [];
|
private static Stack<Variable> _variables = [];
|
||||||
private static Stack<int> _variableScopes = [];
|
private static Stack<int> _variableScopes = [];
|
||||||
private static int _variableIndex;
|
private static int _variableIndex;
|
||||||
@@ -27,9 +27,9 @@ public static class QBEGenerator
|
|||||||
private static int _cStringLiteralIndex;
|
private static int _cStringLiteralIndex;
|
||||||
private static bool _codeIsReachable = true;
|
private static bool _codeIsReachable = true;
|
||||||
|
|
||||||
public static string Emit(CompilationUnit compilationUnit, DefinitionTable definitionTable)
|
public static string Emit(BoundSyntaxTree syntaxTree, BoundDefinitionTable definitionTable)
|
||||||
{
|
{
|
||||||
_compilationUnit = compilationUnit;
|
_syntaxTree = syntaxTree;
|
||||||
_definitionTable = definitionTable;
|
_definitionTable = definitionTable;
|
||||||
|
|
||||||
_builder = new StringBuilder();
|
_builder = new StringBuilder();
|
||||||
@@ -51,8 +51,8 @@ public static class QBEGenerator
|
|||||||
_builder.AppendLine();
|
_builder.AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var funcDef in _compilationUnit.Definitions.OfType<LocalFuncDefinitionNode>())
|
foreach (var funcDef in _syntaxTree.Definitions.OfType<BoundLocalFuncDefinitionNode>())
|
||||||
{
|
{
|
||||||
EmitFuncDefinition(FuncName(funcDef), funcDef.Parameters, funcDef.ReturnType, funcDef.Body, funcDef.Exported);
|
EmitFuncDefinition(FuncName(funcDef), funcDef.Parameters, funcDef.ReturnType, funcDef.Body, funcDef.Exported);
|
||||||
_builder.AppendLine();
|
_builder.AppendLine();
|
||||||
}
|
}
|
||||||
@@ -86,19 +86,19 @@ public static class QBEGenerator
|
|||||||
return $"$cstring{++_cStringLiteralIndex}";
|
return $"$cstring{++_cStringLiteralIndex}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string FuncName(IFuncSignature funcDef)
|
private static string FuncName(IBoundFuncSignature funcDef)
|
||||||
{
|
{
|
||||||
return funcDef switch
|
return funcDef switch
|
||||||
{
|
{
|
||||||
ExternFuncDefinitionNode externFuncDefinition => $"${externFuncDefinition.CallName}",
|
BoundExternFuncDefinitionNode externFuncDefinition => $"${externFuncDefinition.CallName}",
|
||||||
LocalFuncDefinitionNode localFuncDefinition => localFuncDefinition.Exported
|
BoundLocalFuncDefinitionNode localFuncDefinition => localFuncDefinition.Exported
|
||||||
? $"${localFuncDefinition.Name}"
|
? $"${localFuncDefinition.Name}"
|
||||||
: $"${localFuncDefinition.Namespace}_{localFuncDefinition.Name}",
|
: $"${localFuncDefinition.Namespace}_{localFuncDefinition.Name}",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(funcDef))
|
_ => throw new ArgumentOutOfRangeException(nameof(funcDef))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string StructName(StructDefinitionNode structDef)
|
private static string StructName(BoundStructDefinitionNode structDef)
|
||||||
{
|
{
|
||||||
return $":{structDef.Namespace}_{structDef.Name}";
|
return $":{structDef.Namespace}_{structDef.Name}";
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,7 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int OffsetOf(StructDefinitionNode structDefinition, string member)
|
private static int OffsetOf(BoundStructDefinitionNode structDefinition, string member)
|
||||||
{
|
{
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
|
|
||||||
@@ -318,7 +318,7 @@ public static class QBEGenerator
|
|||||||
return type is NubStructType or NubFixedArrayType;
|
return type is NubStructType or NubFixedArrayType;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitFuncDefinition(string name, List<FuncParameter> parameters, NubType returnType, BlockNode body, bool exported)
|
private static void EmitFuncDefinition(string name, List<BoundFuncParameter> parameters, NubType returnType, BoundBlockNode body, bool exported)
|
||||||
{
|
{
|
||||||
_variables.Clear();
|
_variables.Clear();
|
||||||
_variableScopes.Clear();
|
_variableScopes.Clear();
|
||||||
@@ -429,7 +429,7 @@ public static class QBEGenerator
|
|||||||
|
|
||||||
EmitBlock(body, parameterVars);
|
EmitBlock(body, parameterVars);
|
||||||
|
|
||||||
if (body.Statements.LastOrDefault() is not ReturnNode)
|
if (body.Statements.LastOrDefault() is not BoundReturnNode)
|
||||||
{
|
{
|
||||||
if (returnType is NubVoidType)
|
if (returnType is NubVoidType)
|
||||||
{
|
{
|
||||||
@@ -440,7 +440,7 @@ public static class QBEGenerator
|
|||||||
_builder.AppendLine("}");
|
_builder.AppendLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitStructDefinition(StructDefinitionNode structDefinition)
|
private static void EmitStructDefinition(BoundStructDefinitionNode structDefinition)
|
||||||
{
|
{
|
||||||
_builder.Append($"type {StructName(structDefinition)} = {{ ");
|
_builder.Append($"type {StructName(structDefinition)} = {{ ");
|
||||||
foreach (var structDefinitionField in structDefinition.Fields)
|
foreach (var structDefinitionField in structDefinition.Fields)
|
||||||
@@ -476,41 +476,41 @@ public static class QBEGenerator
|
|||||||
_builder.AppendLine("}");
|
_builder.AppendLine("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitStatement(StatementNode statement)
|
private static void EmitStatement(BoundStatementNode statement)
|
||||||
{
|
{
|
||||||
switch (statement)
|
switch (statement)
|
||||||
{
|
{
|
||||||
case ArrayIndexAssignmentNode arrayIndexAssignment:
|
case BoundArrayIndexAssignmentNode arrayIndexAssignment:
|
||||||
EmitArrayIndexAssignment(arrayIndexAssignment);
|
EmitArrayIndexAssignment(arrayIndexAssignment);
|
||||||
break;
|
break;
|
||||||
case BreakNode:
|
case BoundBreakNode:
|
||||||
EmitBreak();
|
EmitBreak();
|
||||||
break;
|
break;
|
||||||
case ContinueNode:
|
case BoundContinueNode:
|
||||||
EmitContinue();
|
EmitContinue();
|
||||||
break;
|
break;
|
||||||
case DereferenceAssignmentNode dereferenceAssignment:
|
case BoundDereferenceAssignmentNode dereferenceAssignment:
|
||||||
EmitDereferenceAssignment(dereferenceAssignment);
|
EmitDereferenceAssignment(dereferenceAssignment);
|
||||||
break;
|
break;
|
||||||
case IfNode ifStatement:
|
case BoundIfNode ifStatement:
|
||||||
EmitIf(ifStatement);
|
EmitIf(ifStatement);
|
||||||
break;
|
break;
|
||||||
case MemberAssignmentNode memberAssignment:
|
case BoundMemberAssignmentNode memberAssignment:
|
||||||
EmitMemberAssignment(memberAssignment);
|
EmitMemberAssignment(memberAssignment);
|
||||||
break;
|
break;
|
||||||
case ReturnNode @return:
|
case BoundReturnNode @return:
|
||||||
EmitReturn(@return);
|
EmitReturn(@return);
|
||||||
break;
|
break;
|
||||||
case StatementExpressionNode statementExpression:
|
case BoundStatementExpressionNode statementExpression:
|
||||||
EmitExpression(statementExpression.Expression);
|
EmitExpression(statementExpression.Expression);
|
||||||
break;
|
break;
|
||||||
case VariableDeclarationNode variableDeclaration:
|
case BoundVariableDeclarationNode variableDeclaration:
|
||||||
EmitVariableDeclaration(variableDeclaration);
|
EmitVariableDeclaration(variableDeclaration);
|
||||||
break;
|
break;
|
||||||
case VariableAssignmentNode variableAssignment:
|
case BoundVariableAssignmentNode variableAssignment:
|
||||||
EmitVariableAssignment(variableAssignment);
|
EmitVariableAssignment(variableAssignment);
|
||||||
break;
|
break;
|
||||||
case WhileNode whileStatement:
|
case BoundWhileNode whileStatement:
|
||||||
EmitWhile(whileStatement);
|
EmitWhile(whileStatement);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -518,7 +518,7 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitArrayIndexAssignment(ArrayIndexAssignmentNode arrayIndexAssignment)
|
private static void EmitArrayIndexAssignment(BoundArrayIndexAssignmentNode arrayIndexAssignment)
|
||||||
{
|
{
|
||||||
var array = EmitUnwrap(EmitExpression(arrayIndexAssignment.ArrayIndexAccess.Array));
|
var array = EmitUnwrap(EmitExpression(arrayIndexAssignment.ArrayIndexAccess.Array));
|
||||||
var index = EmitUnwrap(EmitExpression(arrayIndexAssignment.ArrayIndexAccess.Index));
|
var index = EmitUnwrap(EmitExpression(arrayIndexAssignment.ArrayIndexAccess.Index));
|
||||||
@@ -554,7 +554,7 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitBlock(BlockNode block, List<Variable>? variables = null)
|
private static void EmitBlock(BoundBlockNode block, List<Variable>? variables = null)
|
||||||
{
|
{
|
||||||
_variableScopes.Push(_variables.Count);
|
_variableScopes.Push(_variables.Count);
|
||||||
if (variables != null)
|
if (variables != null)
|
||||||
@@ -591,14 +591,14 @@ public static class QBEGenerator
|
|||||||
_codeIsReachable = false;
|
_codeIsReachable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitDereferenceAssignment(DereferenceAssignmentNode dereferenceAssignment)
|
private static void EmitDereferenceAssignment(BoundDereferenceAssignmentNode dereferenceAssignment)
|
||||||
{
|
{
|
||||||
var pointer = EmitUnwrap(EmitExpression(dereferenceAssignment.Dereference.Expression));
|
var pointer = EmitUnwrap(EmitExpression(dereferenceAssignment.Dereference.Expression));
|
||||||
var value = EmitUnwrap(EmitExpression(dereferenceAssignment.Value));
|
var value = EmitUnwrap(EmitExpression(dereferenceAssignment.Value));
|
||||||
EmitCopy(dereferenceAssignment.Value.Type, value, pointer);
|
EmitCopy(dereferenceAssignment.Value.Type, value, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitIf(IfNode ifStatement)
|
private static void EmitIf(BoundIfNode ifStatement)
|
||||||
{
|
{
|
||||||
var trueLabel = LabelName();
|
var trueLabel = LabelName();
|
||||||
var falseLabel = LabelName();
|
var falseLabel = LabelName();
|
||||||
@@ -622,7 +622,7 @@ public static class QBEGenerator
|
|||||||
_builder.AppendLine(endLabel);
|
_builder.AppendLine(endLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitMemberAssignment(MemberAssignmentNode memberAssignment)
|
private static void EmitMemberAssignment(BoundMemberAssignmentNode memberAssignment)
|
||||||
{
|
{
|
||||||
var structType = memberAssignment.MemberAccess.Expression.Type as NubStructType;
|
var structType = memberAssignment.MemberAccess.Expression.Type as NubStructType;
|
||||||
Debug.Assert(structType != null);
|
Debug.Assert(structType != null);
|
||||||
@@ -640,7 +640,7 @@ public static class QBEGenerator
|
|||||||
EmitCopy(memberAssignment.Value.Type, value, pointer);
|
EmitCopy(memberAssignment.Value.Type, value, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitReturn(ReturnNode @return)
|
private static void EmitReturn(BoundReturnNode @return)
|
||||||
{
|
{
|
||||||
if (@return.Value.HasValue)
|
if (@return.Value.HasValue)
|
||||||
{
|
{
|
||||||
@@ -653,21 +653,21 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVariableDeclaration(VariableDeclarationNode variableDeclaration)
|
private static void EmitVariableDeclaration(BoundVariableDeclarationNode variableDeclaration)
|
||||||
{
|
{
|
||||||
var tmp = VarName();
|
var tmp = VarName();
|
||||||
_builder.AppendLine($" {tmp} =l alloc8 {SizeOf(variableDeclaration.Type)}");
|
_builder.AppendLine($" {tmp} =l alloc8 {SizeOf(variableDeclaration.Type)}");
|
||||||
_variables.Push(new Variable(variableDeclaration.Name, new Val(tmp, variableDeclaration.Type)));
|
_variables.Push(new Variable(variableDeclaration.Name, new Val(tmp, variableDeclaration.Type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVariableAssignment(VariableAssignmentNode variableAssignment)
|
private static void EmitVariableAssignment(BoundVariableAssignmentNode variableAssignment)
|
||||||
{
|
{
|
||||||
var value = EmitUnwrap(EmitExpression(variableAssignment.Value));
|
var value = EmitUnwrap(EmitExpression(variableAssignment.Value));
|
||||||
var variable = _variables.Single(x => x.Name == variableAssignment.Identifier.Name);
|
var variable = _variables.Single(x => x.Name == variableAssignment.Identifier.Name);
|
||||||
EmitCopy(variableAssignment.Value.Type, value, variable.Val.Name);
|
EmitCopy(variableAssignment.Value.Type, value, variable.Val.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitWhile(WhileNode whileStatement)
|
private static void EmitWhile(BoundWhileNode whileStatement)
|
||||||
{
|
{
|
||||||
var conditionLabel = LabelName();
|
var conditionLabel = LabelName();
|
||||||
var iterationLabel = LabelName();
|
var iterationLabel = LabelName();
|
||||||
@@ -688,35 +688,35 @@ public static class QBEGenerator
|
|||||||
_breakLabels.Pop();
|
_breakLabels.Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitExpression(ExpressionNode expression)
|
private static Val EmitExpression(BoundExpressionNode expression)
|
||||||
{
|
{
|
||||||
return expression switch
|
return expression switch
|
||||||
{
|
{
|
||||||
AddressOfNode addressOf => EmitAddressOf(addressOf),
|
BoundAddressOfNode addressOf => EmitAddressOf(addressOf),
|
||||||
AnonymousFuncNode anonymousFunc => EmitAnonymousFunc(anonymousFunc),
|
BoundAnonymousFuncNode anonymousFunc => EmitAnonymousFunc(anonymousFunc),
|
||||||
ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
BoundArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
||||||
ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
BoundArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
||||||
BinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
|
BoundBinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
|
||||||
DereferenceNode dereference => EmitDereference(dereference),
|
BoundDereferenceNode dereference => EmitDereference(dereference),
|
||||||
FixedArrayInitializerNode fixedArrayInitializer => EmitFixedArrayInitializer(fixedArrayInitializer),
|
BoundFixedArrayInitializerNode fixedArrayInitializer => EmitFixedArrayInitializer(fixedArrayInitializer),
|
||||||
FuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
|
BoundFuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
|
||||||
IdentifierNode identifier => EmitIdentifier(identifier),
|
BoundIdentifierNode identifier => EmitIdentifier(identifier),
|
||||||
LiteralNode literal => EmitLiteral(literal),
|
BoundLiteralNode literal => EmitLiteral(literal),
|
||||||
StructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
|
BoundStructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
|
||||||
UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
|
BoundUnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
|
||||||
MemberAccessNode memberAccess => EmitMemberAccess(memberAccess),
|
BoundMemberAccessNode memberAccess => EmitMemberAccess(memberAccess),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitAnonymousFunc(AnonymousFuncNode anonymousFunc)
|
private static Val EmitAnonymousFunc(BoundAnonymousFuncNode anonymousFunc)
|
||||||
{
|
{
|
||||||
var name = $"$anon_func{++_anonymousFuncIndex}";
|
var name = $"$anon_func{++_anonymousFuncIndex}";
|
||||||
_anonymousFunctions.Enqueue((anonymousFunc, name));
|
_anonymousFunctions.Enqueue((anonymousFunc, name));
|
||||||
return new Val(name, anonymousFunc.Type, ValKind.Func);
|
return new Val(name, anonymousFunc.Type, ValKind.Func);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string EmitArrayIndexPointer(ArrayIndexAccessNode arrayIndexAccess)
|
private static string EmitArrayIndexPointer(BoundArrayIndexAccessNode arrayIndexAccess)
|
||||||
{
|
{
|
||||||
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Array));
|
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Array));
|
||||||
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
|
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
|
||||||
@@ -736,7 +736,7 @@ public static class QBEGenerator
|
|||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
private static Val EmitArrayIndexAccess(BoundArrayIndexAccessNode arrayIndexAccess)
|
||||||
{
|
{
|
||||||
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
@@ -768,7 +768,7 @@ public static class QBEGenerator
|
|||||||
_builder.AppendLine(notOobLabel);
|
_builder.AppendLine(notOobLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitArrayInitializer(ArrayInitializerNode arrayInitializer)
|
private static Val EmitArrayInitializer(BoundArrayInitializerNode arrayInitializer)
|
||||||
{
|
{
|
||||||
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
|
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
|
||||||
var elementSize = SizeOf(arrayInitializer.ElementType);
|
var elementSize = SizeOf(arrayInitializer.ElementType);
|
||||||
@@ -789,7 +789,7 @@ public static class QBEGenerator
|
|||||||
return new Val(arrayPointer, arrayInitializer.Type);
|
return new Val(arrayPointer, arrayInitializer.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitDereference(DereferenceNode dereference)
|
private static Val EmitDereference(BoundDereferenceNode dereference)
|
||||||
{
|
{
|
||||||
var result = EmitUnwrap(EmitExpression(dereference.Expression));
|
var result = EmitUnwrap(EmitExpression(dereference.Expression));
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
@@ -797,23 +797,23 @@ public static class QBEGenerator
|
|||||||
return new Val(outputName, dereference.Type);
|
return new Val(outputName, dereference.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitAddressOf(AddressOfNode addressOf)
|
private static Val EmitAddressOf(BoundAddressOfNode addressOf)
|
||||||
{
|
{
|
||||||
switch (addressOf.Expression)
|
switch (addressOf.Expression)
|
||||||
{
|
{
|
||||||
case ArrayIndexAccessNode arrayIndexAccess:
|
case BoundArrayIndexAccessNode arrayIndexAccess:
|
||||||
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
||||||
return new Val(pointer, addressOf.Type);
|
return new Val(pointer, addressOf.Type);
|
||||||
case DereferenceNode dereference:
|
case BoundDereferenceNode dereference:
|
||||||
return EmitExpression(dereference.Expression);
|
return EmitExpression(dereference.Expression);
|
||||||
case IdentifierNode identifier:
|
case BoundIdentifierNode identifier:
|
||||||
if (identifier.Namespace.HasValue)
|
if (identifier.Namespace.HasValue)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("There is nothing to address in another namespace");
|
throw new NotSupportedException("There is nothing to address in another namespace");
|
||||||
}
|
}
|
||||||
|
|
||||||
return _variables.Single(x => x.Name == identifier.Name).Val;
|
return _variables.Single(x => x.Name == identifier.Name).Val;
|
||||||
case MemberAccessNode memberAccess:
|
case BoundMemberAccessNode memberAccess:
|
||||||
var ptr = EmitMemberAccessPointer(memberAccess);
|
var ptr = EmitMemberAccessPointer(memberAccess);
|
||||||
return new Val(ptr, addressOf.Type);
|
return new Val(ptr, addressOf.Type);
|
||||||
default:
|
default:
|
||||||
@@ -821,7 +821,7 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitBinaryExpression(BinaryExpressionNode binaryExpression)
|
private static Val EmitBinaryExpression(BoundBinaryExpressionNode binaryExpression)
|
||||||
{
|
{
|
||||||
var left = EmitUnwrap(EmitExpression(binaryExpression.Left));
|
var left = EmitUnwrap(EmitExpression(binaryExpression.Left));
|
||||||
var right = EmitUnwrap(EmitExpression(binaryExpression.Right));
|
var right = EmitUnwrap(EmitExpression(binaryExpression.Right));
|
||||||
@@ -1035,9 +1035,9 @@ public static class QBEGenerator
|
|||||||
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types {binaryExpression.Left.Type} and {binaryExpression.Right.Type} not supported");
|
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types {binaryExpression.Left.Type} and {binaryExpression.Right.Type} not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitIdentifier(IdentifierNode identifier)
|
private static Val EmitIdentifier(BoundIdentifierNode identifier)
|
||||||
{
|
{
|
||||||
if (_definitionTable.LookupFunc(identifier.Namespace.Or(_compilationUnit.Namespace), identifier.Name).TryGetValue(out var func))
|
if (_definitionTable.LookupFunc(identifier.Namespace.Or(_syntaxTree.Namespace), identifier.Name).TryGetValue(out var func))
|
||||||
{
|
{
|
||||||
return new Val(FuncName(func), identifier.Type, ValKind.Func);
|
return new Val(FuncName(func), identifier.Type, ValKind.Func);
|
||||||
}
|
}
|
||||||
@@ -1050,7 +1050,7 @@ public static class QBEGenerator
|
|||||||
throw new UnreachableException();
|
throw new UnreachableException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitLiteral(LiteralNode literal)
|
private static Val EmitLiteral(BoundLiteralNode literal)
|
||||||
{
|
{
|
||||||
if (literal.Type.IsInteger)
|
if (literal.Type.IsInteger)
|
||||||
{
|
{
|
||||||
@@ -1092,7 +1092,7 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitStructInitializer(StructInitializerNode structInitializer)
|
private static Val EmitStructInitializer(BoundStructInitializerNode structInitializer)
|
||||||
{
|
{
|
||||||
var structDefinition = _definitionTable.LookupStruct(structInitializer.StructType.Namespace, structInitializer.StructType.Name).GetValue();
|
var structDefinition = _definitionTable.LookupStruct(structInitializer.StructType.Namespace, structInitializer.StructType.Name).GetValue();
|
||||||
|
|
||||||
@@ -1127,7 +1127,7 @@ public static class QBEGenerator
|
|||||||
return new Val(output, structInitializer.StructType);
|
return new Val(output, structInitializer.StructType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitUnaryExpression(UnaryExpressionNode unaryExpression)
|
private static Val EmitUnaryExpression(BoundUnaryExpressionNode unaryExpression)
|
||||||
{
|
{
|
||||||
var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand));
|
var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand));
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
@@ -1174,7 +1174,7 @@ public static class QBEGenerator
|
|||||||
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
|
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string EmitMemberAccessPointer(MemberAccessNode memberAccess)
|
private static string EmitMemberAccessPointer(BoundMemberAccessNode memberAccess)
|
||||||
{
|
{
|
||||||
var item = EmitUnwrap(EmitExpression(memberAccess.Expression));
|
var item = EmitUnwrap(EmitExpression(memberAccess.Expression));
|
||||||
switch (memberAccess.Expression.Type)
|
switch (memberAccess.Expression.Type)
|
||||||
@@ -1204,7 +1204,7 @@ public static class QBEGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitMemberAccess(MemberAccessNode memberAccess)
|
private static Val EmitMemberAccess(BoundMemberAccessNode memberAccess)
|
||||||
{
|
{
|
||||||
var pointer = EmitMemberAccessPointer(memberAccess);
|
var pointer = EmitMemberAccessPointer(memberAccess);
|
||||||
|
|
||||||
@@ -1213,7 +1213,7 @@ public static class QBEGenerator
|
|||||||
return new Val(output, memberAccess.Type);
|
return new Val(output, memberAccess.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitFixedArrayInitializer(FixedArrayInitializerNode fixedArrayInitializer)
|
private static Val EmitFixedArrayInitializer(BoundFixedArrayInitializerNode fixedArrayInitializer)
|
||||||
{
|
{
|
||||||
var totalSize = SizeOf(fixedArrayInitializer.Type);
|
var totalSize = SizeOf(fixedArrayInitializer.Type);
|
||||||
var outputName = VarName();
|
var outputName = VarName();
|
||||||
@@ -1230,7 +1230,7 @@ public static class QBEGenerator
|
|||||||
return new Val(outputName, fixedArrayInitializer.Type);
|
return new Val(outputName, fixedArrayInitializer.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Val EmitFuncCall(FuncCallNode funcCall)
|
private static Val EmitFuncCall(BoundFuncCallNode funcCall)
|
||||||
{
|
{
|
||||||
var funcType = (NubFuncType)funcCall.Expression.Type;
|
var funcType = (NubFuncType)funcCall.Expression.Type;
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
using Common;
|
using Common;
|
||||||
using Syntax.Parsing;
|
using Syntax.Parsing;
|
||||||
using Syntax.Parsing.Node;
|
using Syntax.Parsing.Node;
|
||||||
|
using Syntax.Typing;
|
||||||
|
using Syntax.Typing.BoundNode;
|
||||||
|
|
||||||
namespace Syntax;
|
namespace Syntax;
|
||||||
|
|
||||||
public class DefinitionTable
|
public class DefinitionTable
|
||||||
{
|
{
|
||||||
private readonly IEnumerable<CompilationUnit> _compilationUnits;
|
private readonly IEnumerable<SyntaxTree> _syntaxTrees;
|
||||||
|
|
||||||
public DefinitionTable(IEnumerable<CompilationUnit> compilationUnits)
|
public DefinitionTable(IEnumerable<SyntaxTree> syntaxTrees)
|
||||||
{
|
{
|
||||||
_compilationUnits = compilationUnits;
|
_syntaxTrees = syntaxTrees;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<IFuncSignature> LookupFunc(string @namespace, string name)
|
public Optional<IFuncSignature> LookupFunc(string @namespace, string name)
|
||||||
{
|
{
|
||||||
var definition = _compilationUnits
|
var definition = _syntaxTrees
|
||||||
.Where(c => c.Namespace == @namespace)
|
.Where(c => c.Namespace == @namespace)
|
||||||
.SelectMany(c => c.Definitions)
|
.SelectMany(c => c.Definitions)
|
||||||
.OfType<IFuncSignature>()
|
.OfType<IFuncSignature>()
|
||||||
@@ -26,7 +28,7 @@ public class DefinitionTable
|
|||||||
|
|
||||||
public Optional<StructDefinitionNode> LookupStruct(string @namespace, string name)
|
public Optional<StructDefinitionNode> LookupStruct(string @namespace, string name)
|
||||||
{
|
{
|
||||||
var definition = _compilationUnits
|
var definition = _syntaxTrees
|
||||||
.Where(c => c.Namespace == @namespace)
|
.Where(c => c.Namespace == @namespace)
|
||||||
.SelectMany(c => c.Definitions)
|
.SelectMany(c => c.Definitions)
|
||||||
.OfType<StructDefinitionNode>()
|
.OfType<StructDefinitionNode>()
|
||||||
@@ -37,8 +39,47 @@ public class DefinitionTable
|
|||||||
|
|
||||||
public IEnumerable<StructDefinitionNode> GetStructs()
|
public IEnumerable<StructDefinitionNode> GetStructs()
|
||||||
{
|
{
|
||||||
return _compilationUnits
|
return _syntaxTrees
|
||||||
.SelectMany(c => c.Definitions)
|
.SelectMany(c => c.Definitions)
|
||||||
.OfType<StructDefinitionNode>();
|
.OfType<StructDefinitionNode>();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BoundDefinitionTable
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<BoundSyntaxTree> _syntaxTrees;
|
||||||
|
|
||||||
|
public BoundDefinitionTable(IEnumerable<BoundSyntaxTree> syntaxTrees)
|
||||||
|
{
|
||||||
|
_syntaxTrees = syntaxTrees;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<IBoundFuncSignature> LookupFunc(string @namespace, string name)
|
||||||
|
{
|
||||||
|
var definition = _syntaxTrees
|
||||||
|
.Where(c => c.Namespace == @namespace)
|
||||||
|
.SelectMany(c => c.Definitions)
|
||||||
|
.OfType<IBoundFuncSignature>()
|
||||||
|
.SingleOrDefault(f => f.Name == name);
|
||||||
|
|
||||||
|
return Optional.OfNullable(definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<BoundStructDefinitionNode> LookupStruct(string @namespace, string name)
|
||||||
|
{
|
||||||
|
var definition = _syntaxTrees
|
||||||
|
.Where(c => c.Namespace == @namespace)
|
||||||
|
.SelectMany(c => c.Definitions)
|
||||||
|
.OfType<BoundStructDefinitionNode>()
|
||||||
|
.SingleOrDefault(f => f.Name == name);
|
||||||
|
|
||||||
|
return Optional.OfNullable(definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BoundStructDefinitionNode> GetStructs()
|
||||||
|
{
|
||||||
|
return _syntaxTrees
|
||||||
|
.SelectMany(c => c.Definitions)
|
||||||
|
.OfType<BoundStructDefinitionNode>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
using Syntax.Parsing.Node;
|
|
||||||
|
|
||||||
namespace Syntax.Parsing;
|
|
||||||
|
|
||||||
public class CompilationUnit(string @namespace, List<DefinitionNode> definitions)
|
|
||||||
{
|
|
||||||
public string Namespace { get; } = @namespace;
|
|
||||||
public List<DefinitionNode> Definitions { get; } = definitions;
|
|
||||||
}
|
|
||||||
@@ -4,20 +4,9 @@ using Syntax.Typing;
|
|||||||
|
|
||||||
namespace Syntax.Parsing.Node;
|
namespace Syntax.Parsing.Node;
|
||||||
|
|
||||||
public abstract record ExpressionNode(IEnumerable<Token> Tokens) : Node(Tokens)
|
public abstract record ExpressionNode(IEnumerable<Token> Tokens) : Node(Tokens);
|
||||||
{
|
|
||||||
private NubType? _type;
|
|
||||||
public NubType Type
|
|
||||||
{
|
|
||||||
get => _type ?? throw new Exception("Tried to access expression type before type was populated");
|
|
||||||
set => _type = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract record LValueNode(IEnumerable<Token> Tokens) : ExpressionNode(Tokens);
|
public abstract record LValueNode(IEnumerable<Token> Tokens) : ExpressionNode(Tokens);
|
||||||
|
|
||||||
public record DereferenceNode(IEnumerable<Token> Tokens, ExpressionNode Expression) : LValueNode(Tokens);
|
|
||||||
|
|
||||||
public record BinaryExpressionNode(IEnumerable<Token> Tokens, ExpressionNode Left, BinaryExpressionOperator Operator, ExpressionNode Right) : ExpressionNode(Tokens);
|
public record BinaryExpressionNode(IEnumerable<Token> Tokens, ExpressionNode Left, BinaryExpressionOperator Operator, ExpressionNode Right) : ExpressionNode(Tokens);
|
||||||
|
|
||||||
public enum BinaryExpressionOperator
|
public enum BinaryExpressionOperator
|
||||||
@@ -52,3 +41,4 @@ public record FixedArrayInitializerNode(IEnumerable<Token> Tokens, NubType Eleme
|
|||||||
public record LiteralNode(IEnumerable<Token> Tokens, string Literal, LiteralKind Kind) : ExpressionNode(Tokens);
|
public record LiteralNode(IEnumerable<Token> Tokens, string Literal, LiteralKind Kind) : ExpressionNode(Tokens);
|
||||||
public record MemberAccessNode(IEnumerable<Token> Tokens, ExpressionNode Expression, string Member) : LValueNode(Tokens);
|
public record MemberAccessNode(IEnumerable<Token> Tokens, ExpressionNode Expression, string Member) : LValueNode(Tokens);
|
||||||
public record StructInitializerNode(IEnumerable<Token> Tokens, NubStructType StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(Tokens);
|
public record StructInitializerNode(IEnumerable<Token> Tokens, NubStructType StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(Tokens);
|
||||||
|
public record DereferenceNode(IEnumerable<Token> Tokens, ExpressionNode Expression) : LValueNode(Tokens);
|
||||||
@@ -15,7 +15,7 @@ public static class Parser
|
|||||||
private static IEnumerable<Token> _tokens = [];
|
private static IEnumerable<Token> _tokens = [];
|
||||||
private static int _index;
|
private static int _index;
|
||||||
|
|
||||||
public static CompilationUnit? ParseFile(IEnumerable<Token> tokens, out IEnumerable<Diagnostic> diagnostics)
|
public static SyntaxTree? ParseFile(IEnumerable<Token> tokens, string filePath, out IEnumerable<Diagnostic> diagnostics)
|
||||||
{
|
{
|
||||||
_tokens = tokens;
|
_tokens = tokens;
|
||||||
_namespace = null!;
|
_namespace = null!;
|
||||||
@@ -46,7 +46,7 @@ public static class Parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
diagnostics = _diagnostics;
|
diagnostics = _diagnostics;
|
||||||
return new CompilationUnit(_namespace, definitions);
|
return new SyntaxTree(filePath, _namespace, definitions);
|
||||||
}
|
}
|
||||||
catch (ParseException ex)
|
catch (ParseException ex)
|
||||||
{
|
{
|
||||||
|
|||||||
5
src/Syntax/Parsing/SyntaxTree.cs
Normal file
5
src/Syntax/Parsing/SyntaxTree.cs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
using Syntax.Parsing.Node;
|
||||||
|
|
||||||
|
namespace Syntax.Parsing;
|
||||||
|
|
||||||
|
public record SyntaxTree(string FilePath, string Namespace, List<DefinitionNode> Definitions);
|
||||||
400
src/Syntax/Typing/Binder.cs
Normal file
400
src/Syntax/Typing/Binder.cs
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
using Common;
|
||||||
|
using Syntax.Parsing;
|
||||||
|
using Syntax.Parsing.Node;
|
||||||
|
using Syntax.Typing.BoundNode;
|
||||||
|
using UnaryExpressionNode = Syntax.Parsing.Node.UnaryExpressionNode;
|
||||||
|
|
||||||
|
namespace Syntax.Typing;
|
||||||
|
|
||||||
|
public static class Binder
|
||||||
|
{
|
||||||
|
private static SyntaxTree _syntaxTree = null!;
|
||||||
|
private static DefinitionTable _definitionTable = null!;
|
||||||
|
|
||||||
|
private static Dictionary<string, NubType> _variables = new();
|
||||||
|
|
||||||
|
public static BoundSyntaxTree Bind(SyntaxTree syntaxTree, DefinitionTable definitionTable)
|
||||||
|
{
|
||||||
|
_syntaxTree = syntaxTree;
|
||||||
|
_definitionTable = definitionTable;
|
||||||
|
var definitions = new List<BoundDefinitionNode>();
|
||||||
|
|
||||||
|
foreach (var definition in syntaxTree.Definitions)
|
||||||
|
{
|
||||||
|
definitions.Add(BindDefinition(definition));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundSyntaxTree(syntaxTree.FilePath, syntaxTree.Namespace, definitions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundDefinitionNode BindDefinition(DefinitionNode node)
|
||||||
|
{
|
||||||
|
return node switch
|
||||||
|
{
|
||||||
|
ExternFuncDefinitionNode definition => BindExternFuncDefinition(definition),
|
||||||
|
LocalFuncDefinitionNode definition => BindLocalFuncDefinition(definition),
|
||||||
|
StructDefinitionNode definition => BindStruct(definition),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundStructDefinitionNode BindStruct(StructDefinitionNode node)
|
||||||
|
{
|
||||||
|
var structFields = new List<BoundStructField>();
|
||||||
|
|
||||||
|
foreach (var structField in node.Fields)
|
||||||
|
{
|
||||||
|
var value = Optional.Empty<BoundExpressionNode>();
|
||||||
|
|
||||||
|
if (structField.Value.HasValue)
|
||||||
|
{
|
||||||
|
value = BindExpression(structField.Value.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
structFields.Add(new BoundStructField(structField.Name, structField.Type, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundStructDefinitionNode(node.Tokens, node.Documentation, node.Namespace, node.Name, structFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundExternFuncDefinitionNode BindExternFuncDefinition(ExternFuncDefinitionNode node)
|
||||||
|
{
|
||||||
|
var parameters = new List<BoundFuncParameter>();
|
||||||
|
|
||||||
|
foreach (var parameter in node.Parameters)
|
||||||
|
{
|
||||||
|
parameters.Add(new BoundFuncParameter(parameter.Name, parameter.Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundExternFuncDefinitionNode(node.Tokens, node.Documentation, node.Namespace, node.Name, node.CallName, parameters, node.ReturnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundLocalFuncDefinitionNode BindLocalFuncDefinition(LocalFuncDefinitionNode node)
|
||||||
|
{
|
||||||
|
_variables.Clear();
|
||||||
|
|
||||||
|
var parameters = new List<BoundFuncParameter>();
|
||||||
|
|
||||||
|
foreach (var parameter in node.Parameters)
|
||||||
|
{
|
||||||
|
parameters.Add(new BoundFuncParameter(parameter.Name, parameter.Type));
|
||||||
|
_variables[parameter.Name] = parameter.Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
var body = BindBlock(node.Body);
|
||||||
|
|
||||||
|
return new BoundLocalFuncDefinitionNode(node.Tokens, node.Documentation, node.Namespace, node.Name, parameters, body, node.ReturnType, node.Exported);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundBlockNode BindBlock(BlockNode node)
|
||||||
|
{
|
||||||
|
var statements = new List<BoundStatementNode>();
|
||||||
|
|
||||||
|
foreach (var statement in node.Statements)
|
||||||
|
{
|
||||||
|
statements.Add(BindStatement(statement));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundBlockNode(node.Tokens, statements);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundStatementNode BindStatement(StatementNode node)
|
||||||
|
{
|
||||||
|
return node switch
|
||||||
|
{
|
||||||
|
ArrayIndexAssignmentNode statement => BindArrayIndex(statement),
|
||||||
|
BreakNode statement => BindBreak(statement),
|
||||||
|
ContinueNode statement => BindContinue(statement),
|
||||||
|
DereferenceAssignmentNode statement => BindDereferenceAssignment(statement),
|
||||||
|
IfNode statement => BindIf(statement),
|
||||||
|
MemberAssignmentNode statement => BindMemberAssignment(statement),
|
||||||
|
ReturnNode statement => BindReturn(statement),
|
||||||
|
StatementExpressionNode statement => BindStatementExpression(statement),
|
||||||
|
VariableAssignmentNode statement => BindVariableAssignment(statement),
|
||||||
|
VariableDeclarationNode statement => BindVariableDeclaration(statement),
|
||||||
|
WhileNode statement => BindWhile(statement),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundArrayIndexAssignmentNode BindArrayIndex(ArrayIndexAssignmentNode statement)
|
||||||
|
{
|
||||||
|
return new BoundArrayIndexAssignmentNode(statement.Tokens, BindArrayIndexAccess(statement.ArrayIndexAccess), BindExpression(statement.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundBreakNode BindBreak(BreakNode statement)
|
||||||
|
{
|
||||||
|
return new BoundBreakNode(statement.Tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundContinueNode BindContinue(ContinueNode statement)
|
||||||
|
{
|
||||||
|
return new BoundContinueNode(statement.Tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundDereferenceAssignmentNode BindDereferenceAssignment(DereferenceAssignmentNode statement)
|
||||||
|
{
|
||||||
|
return new BoundDereferenceAssignmentNode(statement.Tokens, BindDereference(statement.Dereference), BindExpression(statement.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundIfNode BindIf(IfNode statement)
|
||||||
|
{
|
||||||
|
var elseStatement = Optional.Empty<Variant<BoundIfNode, BoundBlockNode>>();
|
||||||
|
|
||||||
|
if (statement.Else.HasValue)
|
||||||
|
{
|
||||||
|
elseStatement = statement.Else.Value.Match<Variant<BoundIfNode, BoundBlockNode>>
|
||||||
|
(
|
||||||
|
elseIf => BindIf(elseIf),
|
||||||
|
@else => BindBlock(@else)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundIfNode(statement.Tokens, BindExpression(statement.Condition), BindBlock(statement.Body), elseStatement);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundMemberAssignmentNode BindMemberAssignment(MemberAssignmentNode statement)
|
||||||
|
{
|
||||||
|
return new BoundMemberAssignmentNode(statement.Tokens, BindMemberAccess(statement.MemberAccess), BindExpression(statement.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundReturnNode BindReturn(ReturnNode statement)
|
||||||
|
{
|
||||||
|
var value = Optional.Empty<BoundExpressionNode>();
|
||||||
|
|
||||||
|
if (statement.Value.HasValue)
|
||||||
|
{
|
||||||
|
value = BindExpression(statement.Value.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundReturnNode(statement.Tokens, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundStatementExpressionNode BindStatementExpression(StatementExpressionNode statement)
|
||||||
|
{
|
||||||
|
return new BoundStatementExpressionNode(statement.Tokens, BindExpression(statement.Expression));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundVariableAssignmentNode BindVariableAssignment(VariableAssignmentNode statement)
|
||||||
|
{
|
||||||
|
return new BoundVariableAssignmentNode(statement.Tokens, BindIdentifier(statement.Identifier), BindExpression(statement.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundVariableDeclarationNode BindVariableDeclaration(VariableDeclarationNode statement)
|
||||||
|
{
|
||||||
|
_variables[statement.Name] = statement.Type;
|
||||||
|
return new BoundVariableDeclarationNode(statement.Tokens, statement.Name, statement.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundWhileNode BindWhile(WhileNode statement)
|
||||||
|
{
|
||||||
|
return new BoundWhileNode(statement.Tokens, BindExpression(statement.Condition), BindBlock(statement.Body));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundExpressionNode BindExpression(ExpressionNode node)
|
||||||
|
{
|
||||||
|
return node switch
|
||||||
|
{
|
||||||
|
AddressOfNode expression => BindAddressOf(expression),
|
||||||
|
AnonymousFuncNode expression => BindAnonymousFunc(expression),
|
||||||
|
ArrayIndexAccessNode expression => BindArrayIndexAccess(expression),
|
||||||
|
ArrayInitializerNode expression => BindArrayInitializer(expression),
|
||||||
|
BinaryExpressionNode expression => BindBinaryExpression(expression),
|
||||||
|
DereferenceNode expression => BindDereference(expression),
|
||||||
|
FixedArrayInitializerNode expression => BindFixedArrayInitializer(expression),
|
||||||
|
FuncCallNode expression => BindFuncCall(expression),
|
||||||
|
IdentifierNode expression => BindIdentifier(expression),
|
||||||
|
LiteralNode expression => BindLiteral(expression),
|
||||||
|
MemberAccessNode expression => BindMemberAccess(expression),
|
||||||
|
StructInitializerNode expression => BindStructInitializer(expression),
|
||||||
|
UnaryExpressionNode expression => BindUnaryExpression(expression),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundAddressOfNode BindAddressOf(AddressOfNode expression)
|
||||||
|
{
|
||||||
|
var inner = (BoundLValueNode)BindExpression(expression.Expression);
|
||||||
|
return new BoundAddressOfNode(expression.Tokens, new NubPointerType(inner.Type), inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundAnonymousFuncNode BindAnonymousFunc(AnonymousFuncNode expression)
|
||||||
|
{
|
||||||
|
var parameters = new List<BoundFuncParameter>();
|
||||||
|
var parameterTypes = new List<NubType>();
|
||||||
|
|
||||||
|
foreach (var parameter in expression.Parameters)
|
||||||
|
{
|
||||||
|
var boundParameter = new BoundFuncParameter(parameter.Name, parameter.Type);
|
||||||
|
parameters.Add(boundParameter);
|
||||||
|
parameterTypes.Add(boundParameter.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
var body = BindBlock(expression.Body);
|
||||||
|
|
||||||
|
return new BoundAnonymousFuncNode(expression.Tokens, new NubFuncType(expression.ReturnType, parameterTypes), parameters, body, expression.ReturnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression)
|
||||||
|
{
|
||||||
|
var boundArray = BindExpression(expression.Array);
|
||||||
|
var elementType = ((NubArrayType)boundArray.Type).ElementType;
|
||||||
|
return new BoundArrayIndexAccessNode(expression.Tokens, elementType, boundArray, BindExpression(expression.Index));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundArrayInitializerNode BindArrayInitializer(ArrayInitializerNode expression)
|
||||||
|
{
|
||||||
|
return new BoundArrayInitializerNode(expression.Tokens, new NubArrayType(expression.ElementType), BindExpression(expression.Capacity), expression.ElementType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundBinaryExpressionNode BindBinaryExpression(BinaryExpressionNode expression)
|
||||||
|
{
|
||||||
|
var boundLeft = BindExpression(expression.Left);
|
||||||
|
var boundRight = BindExpression(expression.Right);
|
||||||
|
return new BoundBinaryExpressionNode(expression.Tokens, boundLeft.Type, boundLeft, expression.Operator, boundRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundDereferenceNode BindDereference(DereferenceNode expression)
|
||||||
|
{
|
||||||
|
var boundExpression = BindExpression(expression.Expression);
|
||||||
|
var dereferencedType = ((NubPointerType)boundExpression.Type).BaseType;
|
||||||
|
return new BoundDereferenceNode(expression.Tokens, dereferencedType, boundExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundFixedArrayInitializerNode BindFixedArrayInitializer(FixedArrayInitializerNode expression)
|
||||||
|
{
|
||||||
|
return new BoundFixedArrayInitializerNode(expression.Tokens, new NubArrayType(expression.ElementType), expression.ElementType, expression.Capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundFuncCallNode BindFuncCall(FuncCallNode expression)
|
||||||
|
{
|
||||||
|
var boundExpression = BindExpression(expression.Expression);
|
||||||
|
|
||||||
|
var returnType = ((NubFuncType)boundExpression.Type).ReturnType;
|
||||||
|
|
||||||
|
var parameters = new List<BoundExpressionNode>();
|
||||||
|
|
||||||
|
foreach (var parameter in expression.Parameters)
|
||||||
|
{
|
||||||
|
parameters.Add(BindExpression(parameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundIdentifierNode BindIdentifier(IdentifierNode expression)
|
||||||
|
{
|
||||||
|
NubType? type = null;
|
||||||
|
|
||||||
|
var definition = _definitionTable.LookupFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name);
|
||||||
|
if (definition.HasValue)
|
||||||
|
{
|
||||||
|
type = new NubFuncType(definition.Value.ReturnType, definition.Value.Parameters.Select(p => p.Type).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == null && !expression.Namespace.HasValue)
|
||||||
|
{
|
||||||
|
type = _variables[expression.Name];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Diagnostics not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundLiteralNode BindLiteral(LiteralNode expression)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Literal requires context");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundMemberAccessNode BindMemberAccess(MemberAccessNode expression)
|
||||||
|
{
|
||||||
|
var boundExpression = BindExpression(expression.Expression);
|
||||||
|
|
||||||
|
NubType? type = null;
|
||||||
|
|
||||||
|
switch (boundExpression.Type)
|
||||||
|
{
|
||||||
|
case NubArrayType:
|
||||||
|
{
|
||||||
|
if (expression.Member == "count")
|
||||||
|
{
|
||||||
|
type = NubPrimitiveType.I64;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NubStructType structType:
|
||||||
|
{
|
||||||
|
var defOpt = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
|
||||||
|
if (!defOpt.TryGetValue(out var definition))
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Diagnostics not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
var field = definition.Fields.FirstOrDefault(f => f.Name == expression.Member);
|
||||||
|
if (field == null)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Diagnostics not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
type = field.Type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Diagnostics not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundStructInitializerNode BindStructInitializer(StructInitializerNode expression)
|
||||||
|
{
|
||||||
|
var initializers = new Dictionary<string, BoundExpressionNode>();
|
||||||
|
|
||||||
|
foreach (var (member, initializer) in expression.Initializers)
|
||||||
|
{
|
||||||
|
initializers[member] = BindExpression(initializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundStructInitializerNode(expression.Tokens, expression.StructType, expression.StructType, initializers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BoundUnaryExpressionNode BindUnaryExpression(UnaryExpressionNode expression)
|
||||||
|
{
|
||||||
|
var boundOperand = BindExpression(expression.Operand);
|
||||||
|
|
||||||
|
NubType? type = null;
|
||||||
|
|
||||||
|
switch (expression.Operator)
|
||||||
|
{
|
||||||
|
case UnaryExpressionOperator.Negate:
|
||||||
|
{
|
||||||
|
if (boundOperand.Type.IsNumber)
|
||||||
|
{
|
||||||
|
type = boundOperand.Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UnaryExpressionOperator.Invert:
|
||||||
|
{
|
||||||
|
type = new NubPrimitiveType(PrimitiveTypeKind.Bool);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Diagnostics not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BoundUnaryExpressionNode(expression.Tokens, type, expression.Operator, boundOperand);
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/Syntax/Typing/BoundNode/Definition.cs
Normal file
33
src/Syntax/Typing/BoundNode/Definition.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using Common;
|
||||||
|
using Syntax.Tokenization;
|
||||||
|
|
||||||
|
namespace Syntax.Typing.BoundNode;
|
||||||
|
|
||||||
|
public abstract record BoundDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace) : BoundNode(Tokens);
|
||||||
|
|
||||||
|
public record BoundFuncParameter(string Name, NubType Type)
|
||||||
|
{
|
||||||
|
public override string ToString() => $"{Name}: {Type}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IBoundFuncSignature
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
public List<BoundFuncParameter> Parameters { get; }
|
||||||
|
public NubType ReturnType { get; }
|
||||||
|
|
||||||
|
public string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public record BoundLocalFuncDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace, string Name, List<BoundFuncParameter> Parameters, BoundBlockNode Body, NubType ReturnType, bool Exported) : BoundDefinitionNode(Tokens, Documentation, Namespace), IBoundFuncSignature
|
||||||
|
{
|
||||||
|
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public record BoundExternFuncDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace, string Name, string CallName, List<BoundFuncParameter> Parameters, NubType ReturnType) : BoundDefinitionNode(Tokens, Documentation, Namespace), IBoundFuncSignature
|
||||||
|
{
|
||||||
|
public override string ToString() => $"{Name}({string.Join(", ", Parameters.Select(p => p.ToString()))}){": " + ReturnType}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public record BoundStructField(string Name, NubType Type, Optional<BoundExpressionNode> Value);
|
||||||
|
public record BoundStructDefinitionNode(IEnumerable<Token> Tokens, Optional<string> Documentation, string Namespace, string Name, List<BoundStructField> Fields) : BoundDefinitionNode(Tokens, Documentation, Namespace);
|
||||||
21
src/Syntax/Typing/BoundNode/Expression.cs
Normal file
21
src/Syntax/Typing/BoundNode/Expression.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using Common;
|
||||||
|
using Syntax.Parsing.Node;
|
||||||
|
using Syntax.Tokenization;
|
||||||
|
|
||||||
|
namespace Syntax.Typing.BoundNode;
|
||||||
|
|
||||||
|
public abstract record BoundExpressionNode(IEnumerable<Token> Tokens, NubType Type) : BoundNode(Tokens);
|
||||||
|
public abstract record BoundLValueNode(IEnumerable<Token> Tokens, NubType Type) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundBinaryExpressionNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Left, BinaryExpressionOperator Operator, BoundExpressionNode Right) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundUnaryExpressionNode(IEnumerable<Token> Tokens, NubType Type, UnaryExpressionOperator Operator, BoundExpressionNode Operand) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundFuncCallNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression, List<BoundExpressionNode> Parameters) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundIdentifierNode(IEnumerable<Token> Tokens, NubType Type, Optional<string> Namespace, string Name) : BoundLValueNode(Tokens, Type);
|
||||||
|
public record BoundArrayInitializerNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Capacity, NubType ElementType) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundArrayIndexAccessNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Array, BoundExpressionNode Index) : BoundLValueNode(Tokens, Type);
|
||||||
|
public record BoundAnonymousFuncNode(IEnumerable<Token> Tokens, NubType Type, List<BoundFuncParameter> Parameters, BoundBlockNode Body, NubType ReturnType) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundAddressOfNode(IEnumerable<Token> Tokens, NubType Type, BoundLValueNode Expression) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundFixedArrayInitializerNode(IEnumerable<Token> Tokens, NubType Type, NubType ElementType, int Capacity) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundLiteralNode(IEnumerable<Token> Tokens, NubType Type, string Literal, LiteralKind Kind) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundMemberAccessNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression, string Member) : BoundLValueNode(Tokens, Type);
|
||||||
|
public record BoundStructInitializerNode(IEnumerable<Token> Tokens, NubType Type, NubStructType StructType, Dictionary<string, BoundExpressionNode> Initializers) : BoundExpressionNode(Tokens, Type);
|
||||||
|
public record BoundDereferenceNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression) : BoundLValueNode(Tokens, Type);
|
||||||
6
src/Syntax/Typing/BoundNode/Node.cs
Normal file
6
src/Syntax/Typing/BoundNode/Node.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
using Syntax.Tokenization;
|
||||||
|
|
||||||
|
namespace Syntax.Typing.BoundNode;
|
||||||
|
|
||||||
|
public abstract record BoundNode(IEnumerable<Token> Tokens);
|
||||||
|
public record BoundBlockNode(IEnumerable<Token> Tokens, List<BoundStatementNode> Statements) : BoundNode(Tokens);
|
||||||
17
src/Syntax/Typing/BoundNode/Statement.cs
Normal file
17
src/Syntax/Typing/BoundNode/Statement.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using Common;
|
||||||
|
using Syntax.Tokenization;
|
||||||
|
|
||||||
|
namespace Syntax.Typing.BoundNode;
|
||||||
|
|
||||||
|
public record BoundStatementNode(IEnumerable<Token> Tokens) : BoundNode(Tokens);
|
||||||
|
public record BoundStatementExpressionNode(IEnumerable<Token> Tokens, BoundExpressionNode Expression) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundReturnNode(IEnumerable<Token> Tokens, Optional<BoundExpressionNode> Value) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundMemberAssignmentNode(IEnumerable<Token> Tokens, BoundMemberAccessNode MemberAccess, BoundExpressionNode Value) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundIfNode(IEnumerable<Token> Tokens, BoundExpressionNode Condition, BoundBlockNode Body, Optional<Variant<BoundIfNode, BoundBlockNode>> Else) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundDereferenceAssignmentNode(IEnumerable<Token> Tokens, BoundDereferenceNode Dereference, BoundExpressionNode Value) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundVariableAssignmentNode(IEnumerable<Token> Tokens, BoundIdentifierNode Identifier, BoundExpressionNode Value) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundVariableDeclarationNode(IEnumerable<Token> Tokens, string Name, NubType Type) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundContinueNode(IEnumerable<Token> Tokens) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundBreakNode(IEnumerable<Token> Tokens) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundArrayIndexAssignmentNode(IEnumerable<Token> Tokens, BoundArrayIndexAccessNode ArrayIndexAccess, BoundExpressionNode Value) : BoundStatementNode(Tokens);
|
||||||
|
public record BoundWhileNode(IEnumerable<Token> Tokens, BoundExpressionNode Condition, BoundBlockNode Body) : BoundStatementNode(Tokens);
|
||||||
5
src/Syntax/Typing/BoundSyntaxTree.cs
Normal file
5
src/Syntax/Typing/BoundSyntaxTree.cs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
using Syntax.Typing.BoundNode;
|
||||||
|
|
||||||
|
namespace Syntax.Typing;
|
||||||
|
|
||||||
|
public record BoundSyntaxTree(string FilePath, string Namespace, List<BoundDefinitionNode> Definitions);
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user