...
This commit is contained in:
@@ -23,11 +23,12 @@ func main(args: []cstring): i64
|
||||
age = "23"
|
||||
}
|
||||
|
||||
puts(x.name.last)
|
||||
test(x&)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func test(test: u32)
|
||||
func test(human: ^Human)
|
||||
{
|
||||
puts(human^.name.last)
|
||||
}
|
||||
@@ -7,7 +7,7 @@ public static class GCC
|
||||
public static async Task<bool> Assemble(string asmPath, string outPath)
|
||||
{
|
||||
using var process = new Process();
|
||||
process.StartInfo = new ProcessStartInfo("gcc", ["-xassembler", "-c", "-o", outPath, asmPath])
|
||||
process.StartInfo = new ProcessStartInfo("gcc", ["-xassembler", "-g", "-c", "-o", outPath, asmPath])
|
||||
{
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
|
||||
@@ -99,7 +99,7 @@ for (var i = 0; i < typedSyntaxTrees.Count; i++)
|
||||
Directory.CreateDirectory(outFileDir);
|
||||
}
|
||||
|
||||
var generator = new QBEGenerator(syntaxTree, typedDefinitionTable);
|
||||
var generator = new QBEGenerator(syntaxTree, typedDefinitionTable, options.Files[i].Path);
|
||||
var ssa = generator.Emit();
|
||||
|
||||
var ssaFilePath = Path.ChangeExtension(outFileName, "ssa");
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using NubLang.Tokenization;
|
||||
@@ -11,6 +10,7 @@ public class QBEGenerator
|
||||
{
|
||||
private readonly TypedSyntaxTree _syntaxTree;
|
||||
private readonly TypedDefinitionTable _definitionTable;
|
||||
private readonly string _sourceFileName;
|
||||
private readonly QBEWriter _writer;
|
||||
|
||||
private readonly List<CStringLiteral> _cStringLiterals = [];
|
||||
@@ -23,10 +23,11 @@ public class QBEGenerator
|
||||
private int _stringLiteralIndex;
|
||||
private bool _codeIsReachable = true;
|
||||
|
||||
public QBEGenerator(TypedSyntaxTree syntaxTree, TypedDefinitionTable definitionTable)
|
||||
public QBEGenerator(TypedSyntaxTree syntaxTree, TypedDefinitionTable definitionTable, string sourceFileName)
|
||||
{
|
||||
_syntaxTree = syntaxTree;
|
||||
_definitionTable = definitionTable;
|
||||
_sourceFileName = sourceFileName;
|
||||
_writer = new QBEWriter();
|
||||
}
|
||||
|
||||
@@ -42,6 +43,8 @@ public class QBEGenerator
|
||||
_stringLiteralIndex = 0;
|
||||
_codeIsReachable = true;
|
||||
|
||||
_writer.WriteLine($"dbgfile \"{_sourceFileName}\"");
|
||||
|
||||
foreach (var structDef in _definitionTable.GetStructs())
|
||||
{
|
||||
EmitStructTypeDefinition(structDef);
|
||||
@@ -260,39 +263,22 @@ public class QBEGenerator
|
||||
}
|
||||
}
|
||||
|
||||
private bool EmitTryCreateWithoutCopy(ExpressionNode source, [NotNullWhen(true)] out string? destination)
|
||||
private string EmitCreateCopy(ExpressionNode source)
|
||||
{
|
||||
switch (source)
|
||||
// Allowlist for types which are safe to not copy
|
||||
if (source is ArrayInitializerNode or StructInitializerNode or ConvertToInterfaceNode or LiteralNode)
|
||||
{
|
||||
case ArrayInitializerNode:
|
||||
case StructInitializerNode:
|
||||
case LiteralNode { Kind: LiteralKind.String }:
|
||||
{
|
||||
destination = EmitExpression(source);
|
||||
return true;
|
||||
}
|
||||
return EmitExpression(source);
|
||||
}
|
||||
|
||||
destination = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private string EmitCreateCopyOrInitialize(ExpressionNode source)
|
||||
{
|
||||
// If the source is a value which is not used yet such as an array/struct/interface initializer or literal, we can skip copying
|
||||
if (EmitTryCreateWithoutCopy(source, out var uncopiedValue))
|
||||
{
|
||||
return uncopiedValue;
|
||||
}
|
||||
|
||||
var value = EmitExpression(source);
|
||||
|
||||
// Simple types are passed in registers and therefore always copied
|
||||
if (source.Type.IsSimpleType(out _, out var complexType))
|
||||
{
|
||||
// Simple types are passed in registers and are therefore always copied
|
||||
return value;
|
||||
return EmitExpression(source);
|
||||
}
|
||||
|
||||
// For the rest, we figure out the size of the type and shallow copy them
|
||||
var value = EmitExpression(source);
|
||||
var size = complexType switch
|
||||
{
|
||||
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
|
||||
@@ -474,6 +460,12 @@ public class QBEGenerator
|
||||
|
||||
private void EmitStatement(StatementNode statement)
|
||||
{
|
||||
var tokens = statement.Tokens.ToArray();
|
||||
if (tokens.Length != 0)
|
||||
{
|
||||
_writer.WriteLine($"dbgloc {tokens[0].FileSpan.Span.Start.Line}");
|
||||
}
|
||||
|
||||
switch (statement)
|
||||
{
|
||||
case AssignmentNode assignment:
|
||||
@@ -589,6 +581,12 @@ public class QBEGenerator
|
||||
|
||||
private string EmitExpression(ExpressionNode expression)
|
||||
{
|
||||
var tokens = expression.Tokens.ToArray();
|
||||
if (tokens.Length != 0)
|
||||
{
|
||||
_writer.WriteLine($"dbgloc {tokens[0].FileSpan.Span.Start.Line}");
|
||||
}
|
||||
|
||||
return expression switch
|
||||
{
|
||||
ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
||||
@@ -616,7 +614,13 @@ public class QBEGenerator
|
||||
|
||||
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
||||
{
|
||||
return EmitLoad(arrayIndexAccess.Type, EmitAddressOfArrayIndexAccess(arrayIndexAccess));
|
||||
var address = EmitAddressOfArrayIndexAccess(arrayIndexAccess);
|
||||
if (arrayIndexAccess.Type is StructTypeNode)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
return EmitLoad(arrayIndexAccess.Type, address);
|
||||
}
|
||||
|
||||
private void EmitArrayBoundsCheck(string array, string index)
|
||||
@@ -666,7 +670,13 @@ public class QBEGenerator
|
||||
|
||||
private string EmitDereference(DereferenceNode dereference)
|
||||
{
|
||||
return EmitLoad(dereference.Type, EmitExpression(dereference.Expression));
|
||||
var address = EmitExpression(dereference.Expression);
|
||||
if (dereference.Type is StructTypeNode)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
return EmitLoad(dereference.Type, address);
|
||||
}
|
||||
|
||||
private string EmitAddressOf(AddressOfNode addressOf)
|
||||
@@ -901,10 +911,12 @@ public class QBEGenerator
|
||||
private string EmitVariableIdent(VariableIdentNode variableIdent)
|
||||
{
|
||||
var address = EmitAddressOfVariableIdent(variableIdent);
|
||||
if (variableIdent.Type is StructTypeNode)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
return variableIdent.Type.IsSimpleType(out _, out _)
|
||||
? EmitLoad(variableIdent.Type, address)
|
||||
: address;
|
||||
return EmitLoad(variableIdent.Type, address);
|
||||
}
|
||||
|
||||
private string EmitFuncParameterIdent(FuncParameterIdentNode funcParameterIdent)
|
||||
@@ -1075,13 +1087,11 @@ public class QBEGenerator
|
||||
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccess)
|
||||
{
|
||||
var address = EmitAddressOfStructFieldAccess(structFieldAccess);
|
||||
|
||||
// Inline structs should not be loaded
|
||||
if (structFieldAccess.Type is StructTypeNode)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
return EmitLoad(structFieldAccess.Type, address);
|
||||
}
|
||||
|
||||
@@ -1096,7 +1106,7 @@ public class QBEGenerator
|
||||
|
||||
foreach (var parameter in structFuncCall.Parameters)
|
||||
{
|
||||
var copy = EmitCreateCopyOrInitialize(parameter);
|
||||
var copy = EmitCreateCopy(parameter);
|
||||
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
|
||||
}
|
||||
|
||||
@@ -1138,7 +1148,7 @@ public class QBEGenerator
|
||||
|
||||
foreach (var parameter in interfaceFuncCall.Parameters)
|
||||
{
|
||||
var copy = EmitCreateCopyOrInitialize(parameter);
|
||||
var copy = EmitCreateCopy(parameter);
|
||||
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
|
||||
}
|
||||
|
||||
@@ -1248,7 +1258,7 @@ public class QBEGenerator
|
||||
|
||||
foreach (var parameter in funcCall.Parameters)
|
||||
{
|
||||
var copy = EmitCreateCopyOrInitialize(parameter);
|
||||
var copy = EmitCreateCopy(parameter);
|
||||
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
namespace NubLang.TypeChecking.Node;
|
||||
using NubLang.Tokenization;
|
||||
|
||||
public abstract record DefinitionNode : Node;
|
||||
namespace NubLang.TypeChecking.Node;
|
||||
|
||||
public record FuncParameterNode(string Name, TypeNode Type) : Node;
|
||||
public abstract record DefinitionNode(IEnumerable<Token> Tokens) : Node(Tokens);
|
||||
|
||||
public record FuncSignatureNode(IReadOnlyList<FuncParameterNode> Parameters, TypeNode ReturnType) : Node;
|
||||
public record FuncParameterNode(string Name, TypeNode Type, IEnumerable<Token> Tokens) : Node(Tokens);
|
||||
|
||||
public record LocalFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : DefinitionNode;
|
||||
public record FuncSignatureNode(IReadOnlyList<FuncParameterNode> Parameters, TypeNode ReturnType, IEnumerable<Token> Tokens) : Node(Tokens);
|
||||
|
||||
public record ExternFuncNode(string Name, string CallName, FuncSignatureNode Signature) : DefinitionNode;
|
||||
public record LocalFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body, IEnumerable<Token> Tokens) : DefinitionNode(Tokens);
|
||||
|
||||
public record StructFieldNode(int Index, string Name, TypeNode Type, Optional<ExpressionNode> Value) : Node;
|
||||
public record ExternFuncNode(string Name, string CallName, FuncSignatureNode Signature, IEnumerable<Token> Tokens) : DefinitionNode(Tokens);
|
||||
|
||||
public record StructFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : Node;
|
||||
public record StructFieldNode(int Index, string Name, TypeNode Type, Optional<ExpressionNode> Value, IEnumerable<Token> Tokens) : Node(Tokens);
|
||||
|
||||
public record StructNode(string Name, StructTypeNode Type, IReadOnlyList<StructFieldNode> Fields, IReadOnlyList<StructFuncNode> Functions, IReadOnlyList<InterfaceTypeNode> InterfaceImplementations) : DefinitionNode;
|
||||
public record StructFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body, IEnumerable<Token> Tokens) : Node(Tokens);
|
||||
|
||||
public record InterfaceFuncNode(string Name, FuncSignatureNode Signature) : Node;
|
||||
public record StructNode(string Name, StructTypeNode Type, IReadOnlyList<StructFieldNode> Fields, IReadOnlyList<StructFuncNode> Functions, IReadOnlyList<InterfaceTypeNode> InterfaceImplementations, IEnumerable<Token> Tokens) : DefinitionNode(Tokens);
|
||||
|
||||
public record InterfaceNode(string Name, IReadOnlyList<InterfaceFuncNode> Functions) : DefinitionNode;
|
||||
public record InterfaceFuncNode(string Name, FuncSignatureNode Signature, IEnumerable<Token> Tokens) : Node(Tokens);
|
||||
|
||||
public record InterfaceNode(string Name, IReadOnlyList<InterfaceFuncNode> Functions, IEnumerable<Token> Tokens) : DefinitionNode(Tokens);
|
||||
@@ -30,45 +30,45 @@ public enum BinaryOperator
|
||||
BitwiseOr
|
||||
}
|
||||
|
||||
public abstract record ExpressionNode(TypeNode Type) : Node;
|
||||
public abstract record ExpressionNode(TypeNode Type, IEnumerable<Token> Tokens) : Node(Tokens);
|
||||
|
||||
public abstract record LValueExpressionNode(TypeNode Type) : RValueExpressionNode(Type);
|
||||
public abstract record RValueExpressionNode(TypeNode Type) : ExpressionNode(Type);
|
||||
public abstract record LValueExpressionNode(TypeNode Type, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
public abstract record RValueExpressionNode(TypeNode Type, IEnumerable<Token> Tokens) : ExpressionNode(Type, Tokens);
|
||||
|
||||
public record BinaryExpressionNode(TypeNode Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right) : RValueExpressionNode(Type);
|
||||
public record BinaryExpressionNode(TypeNode Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record UnaryExpressionNode(TypeNode Type, UnaryOperator Operator, ExpressionNode Operand) : RValueExpressionNode(Type);
|
||||
public record UnaryExpressionNode(TypeNode Type, UnaryOperator Operator, ExpressionNode Operand, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record FuncCallNode(TypeNode Type, ExpressionNode Expression, IReadOnlyList<ExpressionNode> Parameters) : RValueExpressionNode(Type);
|
||||
public record FuncCallNode(TypeNode Type, ExpressionNode Expression, IReadOnlyList<ExpressionNode> Parameters, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record StructFuncCallNode(TypeNode Type, string Name, StructTypeNode StructType, ExpressionNode StructExpression, IReadOnlyList<ExpressionNode> Parameters) : RValueExpressionNode(Type);
|
||||
public record StructFuncCallNode(TypeNode Type, string Name, StructTypeNode StructType, ExpressionNode StructExpression, IReadOnlyList<ExpressionNode> Parameters, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record InterfaceFuncCallNode(TypeNode Type, string Name, InterfaceTypeNode InterfaceType, ExpressionNode InterfaceExpression, IReadOnlyList<ExpressionNode> Parameters) : RValueExpressionNode(Type);
|
||||
public record InterfaceFuncCallNode(TypeNode Type, string Name, InterfaceTypeNode InterfaceType, ExpressionNode InterfaceExpression, IReadOnlyList<ExpressionNode> Parameters, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record VariableIdentNode(TypeNode Type, string Name) : LValueExpressionNode(Type);
|
||||
public record VariableIdentNode(TypeNode Type, string Name, IEnumerable<Token> Tokens) : LValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record FuncParameterIdentNode(TypeNode Type, string Name) : RValueExpressionNode(Type);
|
||||
public record FuncParameterIdentNode(TypeNode Type, string Name, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record LocalFuncIdentNode(TypeNode Type, string Name) : RValueExpressionNode(Type);
|
||||
public record LocalFuncIdentNode(TypeNode Type, string Name, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record ExternFuncIdentNode(TypeNode Type, string Name) : RValueExpressionNode(Type);
|
||||
public record ExternFuncIdentNode(TypeNode Type, string Name, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record ArrayInitializerNode(TypeNode Type, ExpressionNode Capacity, TypeNode ElementType) : RValueExpressionNode(Type);
|
||||
public record ArrayInitializerNode(TypeNode Type, ExpressionNode Capacity, TypeNode ElementType, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record ArrayIndexAccessNode(TypeNode Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Type);
|
||||
public record ArrayIndexAccessNode(TypeNode Type, ExpressionNode Target, ExpressionNode Index, IEnumerable<Token> Tokens) : LValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record AddressOfNode(TypeNode Type, LValueExpressionNode LValue) : RValueExpressionNode(Type);
|
||||
public record AddressOfNode(TypeNode Type, LValueExpressionNode LValue, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record LiteralNode(TypeNode Type, string Value, LiteralKind Kind) : RValueExpressionNode(Type);
|
||||
public record LiteralNode(TypeNode Type, string Value, LiteralKind Kind, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record StructFieldAccessNode(TypeNode Type, StructTypeNode StructType, ExpressionNode Target, string Field) : LValueExpressionNode(Type);
|
||||
public record StructFieldAccessNode(TypeNode Type, StructTypeNode StructType, ExpressionNode Target, string Field, IEnumerable<Token> Tokens) : LValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record StructInitializerNode(StructTypeNode StructType, Dictionary<string, ExpressionNode> Initializers) : RValueExpressionNode(StructType);
|
||||
public record StructInitializerNode(StructTypeNode StructType, Dictionary<string, ExpressionNode> Initializers, IEnumerable<Token> Tokens) : RValueExpressionNode(StructType, Tokens);
|
||||
|
||||
public record DereferenceNode(TypeNode Type, ExpressionNode Expression) : RValueExpressionNode(Type);
|
||||
public record DereferenceNode(TypeNode Type, ExpressionNode Expression, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record ConvertToInterfaceNode(TypeNode Type, InterfaceTypeNode InterfaceType, StructTypeNode StructType, ExpressionNode Implementation) : RValueExpressionNode(Type);
|
||||
public record ConvertToInterfaceNode(TypeNode Type, InterfaceTypeNode InterfaceType, StructTypeNode StructType, ExpressionNode Implementation, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record ConvertIntNode(TypeNode Type, ExpressionNode Value, IntTypeNode ValueType, IntTypeNode TargetType) : RValueExpressionNode(Type);
|
||||
public record ConvertIntNode(TypeNode Type, ExpressionNode Value, IntTypeNode ValueType, IntTypeNode TargetType, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
public record ConvertFloatNode(TypeNode Type, ExpressionNode Value, FloatTypeNode ValueType, FloatTypeNode TargetType) : RValueExpressionNode(Type);
|
||||
public record ConvertFloatNode(TypeNode Type, ExpressionNode Value, FloatTypeNode ValueType, FloatTypeNode TargetType, IEnumerable<Token> Tokens) : RValueExpressionNode(Type, Tokens);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
namespace NubLang.TypeChecking.Node;
|
||||
using NubLang.Tokenization;
|
||||
|
||||
public abstract record Node;
|
||||
namespace NubLang.TypeChecking.Node;
|
||||
|
||||
public record TypedSyntaxTree(IReadOnlyList<DefinitionNode> Definitions) : Node;
|
||||
public abstract record Node(IEnumerable<Token> Tokens);
|
||||
|
||||
public record BlockNode(IReadOnlyList<StatementNode> Statements) : Node;
|
||||
public record TypedSyntaxTree(IReadOnlyList<DefinitionNode> Definitions);
|
||||
|
||||
public record BlockNode(IReadOnlyList<StatementNode> Statements, IEnumerable<Token> Tokens) : Node(Tokens);
|
||||
@@ -1,19 +1,21 @@
|
||||
namespace NubLang.TypeChecking.Node;
|
||||
using NubLang.Tokenization;
|
||||
|
||||
public record StatementNode : Node;
|
||||
namespace NubLang.TypeChecking.Node;
|
||||
|
||||
public record StatementExpressionNode(ExpressionNode Expression) : StatementNode;
|
||||
public record StatementNode(IEnumerable<Token> Tokens) : Node(Tokens);
|
||||
|
||||
public record ReturnNode(Optional<ExpressionNode> Value) : StatementNode;
|
||||
public record StatementExpressionNode(ExpressionNode Expression, IEnumerable<Token> Tokens) : StatementNode(Tokens);
|
||||
|
||||
public record AssignmentNode(LValueExpressionNode Target, ExpressionNode Value) : StatementNode;
|
||||
public record ReturnNode(Optional<ExpressionNode> Value, IEnumerable<Token> Tokens) : StatementNode(Tokens);
|
||||
|
||||
public record IfNode(ExpressionNode Condition, BlockNode Body, Optional<Variant<IfNode, BlockNode>> Else) : StatementNode;
|
||||
public record AssignmentNode(LValueExpressionNode Target, ExpressionNode Value, IEnumerable<Token> Tokens) : StatementNode(Tokens);
|
||||
|
||||
public record VariableDeclarationNode(string Name, Optional<ExpressionNode> Assignment, TypeNode Type) : StatementNode;
|
||||
public record IfNode(ExpressionNode Condition, BlockNode Body, Optional<Variant<IfNode, BlockNode>> Else, IEnumerable<Token> Tokens) : StatementNode(Tokens);
|
||||
|
||||
public record ContinueNode : StatementNode;
|
||||
public record VariableDeclarationNode(string Name, Optional<ExpressionNode> Assignment, TypeNode Type, IEnumerable<Token> Tokens) : StatementNode(Tokens);
|
||||
|
||||
public record BreakNode : StatementNode;
|
||||
public record ContinueNode(IEnumerable<Token> Tokens) : StatementNode(Tokens);
|
||||
|
||||
public record WhileNode(ExpressionNode Condition, BlockNode Body) : StatementNode;
|
||||
public record BreakNode(IEnumerable<Token> Tokens) : StatementNode(Tokens);
|
||||
|
||||
public record WhileNode(ExpressionNode Condition, BlockNode Body, IEnumerable<Token> Tokens) : StatementNode(Tokens);
|
||||
@@ -66,10 +66,10 @@ public sealed class TypeChecker
|
||||
|
||||
foreach (var function in node.Functions)
|
||||
{
|
||||
functions.Add(new InterfaceFuncNode(function.Name, CheckFuncSignature(function.Signature)));
|
||||
functions.Add(new InterfaceFuncNode(function.Name, CheckFuncSignature(function.Signature), function.Tokens));
|
||||
}
|
||||
|
||||
return new InterfaceNode(node.Name, functions);
|
||||
return new InterfaceNode(node.Name, functions, node.Tokens);
|
||||
}
|
||||
|
||||
private StructNode CheckStructDefinition(StructSyntax node)
|
||||
@@ -85,7 +85,7 @@ public sealed class TypeChecker
|
||||
value = CheckExpression(field.Value.Value, CheckType(field.Type));
|
||||
}
|
||||
|
||||
structFields.Add(new StructFieldNode(field.Index, field.Name, CheckType(field.Type), value));
|
||||
structFields.Add(new StructFieldNode(field.Index, field.Name, CheckType(field.Type), value, field.Tokens));
|
||||
}
|
||||
|
||||
var funcs = new List<StructFuncNode>();
|
||||
@@ -104,7 +104,7 @@ public sealed class TypeChecker
|
||||
var body = CheckBlock(func.Body, scope);
|
||||
_funcReturnTypes.Pop();
|
||||
|
||||
funcs.Add(new StructFuncNode(func.Name, CheckFuncSignature(func.Signature), body));
|
||||
funcs.Add(new StructFuncNode(func.Name, CheckFuncSignature(func.Signature), body, func.Tokens));
|
||||
}
|
||||
|
||||
var interfaceImplementations = new List<InterfaceTypeNode>();
|
||||
@@ -135,12 +135,12 @@ public sealed class TypeChecker
|
||||
interfaceImplementations.Add(interfaceType);
|
||||
}
|
||||
|
||||
return new StructNode(node.Name, GetStructType(node), structFields, funcs, interfaceImplementations);
|
||||
return new StructNode(node.Name, GetStructType(node), structFields, funcs, interfaceImplementations, node.Tokens);
|
||||
}
|
||||
|
||||
private ExternFuncNode CheckExternFuncDefinition(ExternFuncSyntax node)
|
||||
{
|
||||
return new ExternFuncNode(node.Name, node.CallName, CheckFuncSignature(node.Signature));
|
||||
return new ExternFuncNode(node.Name, node.CallName, CheckFuncSignature(node.Signature), node.Tokens);
|
||||
}
|
||||
|
||||
private LocalFuncNode CheckLocalFuncDefinition(LocalFuncSyntax node)
|
||||
@@ -157,7 +157,7 @@ public sealed class TypeChecker
|
||||
var body = CheckBlock(node.Body, scope);
|
||||
_funcReturnTypes.Pop();
|
||||
|
||||
return new LocalFuncNode(node.Name, signature, body);
|
||||
return new LocalFuncNode(node.Name, signature, body, node.Tokens);
|
||||
}
|
||||
|
||||
private StatementNode CheckStatement(StatementSyntax node)
|
||||
@@ -165,8 +165,8 @@ public sealed class TypeChecker
|
||||
return node switch
|
||||
{
|
||||
AssignmentSyntax statement => CheckAssignment(statement),
|
||||
BreakSyntax => new BreakNode(),
|
||||
ContinueSyntax => new ContinueNode(),
|
||||
BreakSyntax => new BreakNode(node.Tokens),
|
||||
ContinueSyntax => new ContinueNode(node.Tokens),
|
||||
IfSyntax statement => CheckIf(statement),
|
||||
ReturnSyntax statement => CheckReturn(statement),
|
||||
StatementExpressionSyntax statement => CheckStatementExpression(statement),
|
||||
@@ -185,7 +185,7 @@ public sealed class TypeChecker
|
||||
}
|
||||
|
||||
var value = CheckExpression(statement.Value, target.Type);
|
||||
return new AssignmentNode(targetLValue, value);
|
||||
return new AssignmentNode(targetLValue, value, statement.Tokens);
|
||||
}
|
||||
|
||||
private IfNode CheckIf(IfSyntax statement)
|
||||
@@ -201,7 +201,7 @@ public sealed class TypeChecker
|
||||
);
|
||||
}
|
||||
|
||||
return new IfNode(CheckExpression(statement.Condition, new BoolTypeNode()), CheckBlock(statement.Body), elseStatement);
|
||||
return new IfNode(CheckExpression(statement.Condition, new BoolTypeNode()), CheckBlock(statement.Body), elseStatement, statement.Tokens);
|
||||
}
|
||||
|
||||
private ReturnNode CheckReturn(ReturnSyntax statement)
|
||||
@@ -213,12 +213,12 @@ public sealed class TypeChecker
|
||||
value = CheckExpression(statement.Value.Value, _funcReturnTypes.Peek());
|
||||
}
|
||||
|
||||
return new ReturnNode(value);
|
||||
return new ReturnNode(value, statement.Tokens);
|
||||
}
|
||||
|
||||
private StatementExpressionNode CheckStatementExpression(StatementExpressionSyntax statement)
|
||||
{
|
||||
return new StatementExpressionNode(CheckExpression(statement.Expression));
|
||||
return new StatementExpressionNode(CheckExpression(statement.Expression), statement.Tokens);
|
||||
}
|
||||
|
||||
private VariableDeclarationNode CheckVariableDeclaration(VariableDeclarationSyntax statement)
|
||||
@@ -259,12 +259,12 @@ public sealed class TypeChecker
|
||||
|
||||
Scope.Declare(new Identifier(statement.Name, type, IdentifierKind.Variable));
|
||||
|
||||
return new VariableDeclarationNode(statement.Name, assignment, type);
|
||||
return new VariableDeclarationNode(statement.Name, assignment, type, statement.Tokens);
|
||||
}
|
||||
|
||||
private WhileNode CheckWhile(WhileSyntax statement)
|
||||
{
|
||||
return new WhileNode(CheckExpression(statement.Condition, new BoolTypeNode()), CheckBlock(statement.Body));
|
||||
return new WhileNode(CheckExpression(statement.Condition, new BoolTypeNode()), CheckBlock(statement.Body), statement.Tokens);
|
||||
}
|
||||
|
||||
private ExpressionNode CheckExpression(ExpressionSyntax node, TypeNode? expectedType = null)
|
||||
@@ -293,14 +293,14 @@ public sealed class TypeChecker
|
||||
|
||||
if (result.Type is StructTypeNode structType && expectedType is InterfaceTypeNode interfaceType)
|
||||
{
|
||||
return new ConvertToInterfaceNode(interfaceType, interfaceType, structType, result);
|
||||
return new ConvertToInterfaceNode(interfaceType, interfaceType, structType, result, node.Tokens);
|
||||
}
|
||||
|
||||
if (result.Type is IntTypeNode sourceIntType && expectedType is IntTypeNode targetIntType)
|
||||
{
|
||||
if (sourceIntType.Signed == targetIntType.Signed && sourceIntType.Width < targetIntType.Width)
|
||||
{
|
||||
return new ConvertIntNode(targetIntType, result, sourceIntType, targetIntType);
|
||||
return new ConvertIntNode(targetIntType, result, sourceIntType, targetIntType, node.Tokens);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ public sealed class TypeChecker
|
||||
{
|
||||
if (sourceFloatType.Width < targetFloatType.Width)
|
||||
{
|
||||
return new ConvertFloatNode(targetFloatType, result, sourceFloatType, targetFloatType);
|
||||
return new ConvertFloatNode(targetFloatType, result, sourceFloatType, targetFloatType, node.Tokens);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,21 +324,21 @@ public sealed class TypeChecker
|
||||
throw new TypeCheckerException(Diagnostic.Error("Cannot take address of rvalue").Build());
|
||||
}
|
||||
|
||||
return new AddressOfNode(new PointerTypeNode(inner.Type), lValueInner);
|
||||
return new AddressOfNode(new PointerTypeNode(inner.Type), lValueInner, expression.Tokens);
|
||||
}
|
||||
|
||||
private ArrayIndexAccessNode CheckArrayIndexAccess(ArrayIndexAccessSyntax expression)
|
||||
{
|
||||
var boundArray = CheckExpression(expression.Target);
|
||||
var elementType = ((ArrayTypeNode)boundArray.Type).ElementType;
|
||||
return new ArrayIndexAccessNode(elementType, boundArray, CheckExpression(expression.Index, new IntTypeNode(false, 64)));
|
||||
return new ArrayIndexAccessNode(elementType, boundArray, CheckExpression(expression.Index, new IntTypeNode(false, 64)), expression.Tokens);
|
||||
}
|
||||
|
||||
private ArrayInitializerNode CheckArrayInitializer(ArrayInitializerSyntax expression)
|
||||
{
|
||||
var capacity = CheckExpression(expression.Capacity, new IntTypeNode(false, 64));
|
||||
var type = new ArrayTypeNode(CheckType(expression.ElementType));
|
||||
return new ArrayInitializerNode(type, capacity, CheckType(expression.ElementType));
|
||||
return new ArrayInitializerNode(type, capacity, CheckType(expression.ElementType), expression.Tokens);
|
||||
}
|
||||
|
||||
private BinaryExpressionNode CheckBinaryExpression(BinaryExpressionSyntax expression)
|
||||
@@ -392,14 +392,14 @@ public sealed class TypeChecker
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
return new BinaryExpressionNode(resultingType, boundLeft, op, boundRight);
|
||||
return new BinaryExpressionNode(resultingType, boundLeft, op, boundRight, expression.Tokens);
|
||||
}
|
||||
|
||||
private DereferenceNode CheckDereference(DereferenceSyntax expression)
|
||||
{
|
||||
var boundExpression = CheckExpression(expression.Expression);
|
||||
var dereferencedType = ((PointerTypeNode)boundExpression.Type).BaseType;
|
||||
return new DereferenceNode(dereferencedType, boundExpression);
|
||||
return new DereferenceNode(dereferencedType, boundExpression, expression.Tokens);
|
||||
}
|
||||
|
||||
private FuncCallNode CheckFuncCall(FuncCallSyntax expression)
|
||||
@@ -425,7 +425,7 @@ public sealed class TypeChecker
|
||||
parameters.Add(CheckExpression(parameter, expectedType));
|
||||
}
|
||||
|
||||
return new FuncCallNode(funcType.ReturnType, boundExpression, parameters);
|
||||
return new FuncCallNode(funcType.ReturnType, boundExpression, parameters, expression.Tokens);
|
||||
}
|
||||
|
||||
private ExpressionNode CheckDotFuncCall(DotFuncCallSyntax expression)
|
||||
@@ -460,7 +460,7 @@ public sealed class TypeChecker
|
||||
}
|
||||
|
||||
var returnType = CheckType(function.Signature.ReturnType);
|
||||
return new InterfaceFuncCallNode(returnType, expression.Name, interfaceType, thisParameter, parameters);
|
||||
return new InterfaceFuncCallNode(returnType, expression.Name, interfaceType, thisParameter, parameters, expression.Tokens);
|
||||
}
|
||||
|
||||
if (thisParameter.Type is StructTypeNode structType)
|
||||
@@ -491,7 +491,7 @@ public sealed class TypeChecker
|
||||
}
|
||||
|
||||
var returnType = CheckType(function.Signature.ReturnType);
|
||||
return new StructFuncCallNode(returnType, expression.Name, structType, thisParameter, parameters);
|
||||
return new StructFuncCallNode(returnType, expression.Name, structType, thisParameter, parameters, expression.Tokens);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Cannot call dot function on type {thisParameter.Type}").Build());
|
||||
@@ -504,8 +504,8 @@ public sealed class TypeChecker
|
||||
{
|
||||
return identifier.Kind switch
|
||||
{
|
||||
IdentifierKind.Variable => new VariableIdentNode(identifier.Type, identifier.Name),
|
||||
IdentifierKind.FunctionParameter => new FuncParameterIdentNode(identifier.Type, identifier.Name),
|
||||
IdentifierKind.Variable => new VariableIdentNode(identifier.Type, identifier.Name, expression.Tokens),
|
||||
IdentifierKind.FunctionParameter => new FuncParameterIdentNode(identifier.Type, identifier.Name, expression.Tokens),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
@@ -523,7 +523,7 @@ public sealed class TypeChecker
|
||||
var returnType = CheckType(localFunc.Signature.ReturnType);
|
||||
var parameterTypes = localFunc.Signature.Parameters.Select(p => CheckType(p.Type)).ToList();
|
||||
var type = new FuncTypeNode(parameterTypes, returnType);
|
||||
return new LocalFuncIdentNode(type, expression.Name);
|
||||
return new LocalFuncIdentNode(type, expression.Name, expression.Tokens);
|
||||
}
|
||||
|
||||
var externFuncs = _definitionTable.LookupExternFunc(expression.Name).ToArray();
|
||||
@@ -539,7 +539,7 @@ public sealed class TypeChecker
|
||||
var returnType = CheckType(externFunc.Signature.ReturnType);
|
||||
var parameterTypes = externFunc.Signature.Parameters.Select(p => CheckType(p.Type)).ToList();
|
||||
var type = new FuncTypeNode(parameterTypes, returnType);
|
||||
return new ExternFuncIdentNode(type, expression.Name);
|
||||
return new ExternFuncIdentNode(type, expression.Name, expression.Tokens);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic.Error($"No identifier with the name {expression.Name} exists").Build());
|
||||
@@ -556,7 +556,7 @@ public sealed class TypeChecker
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
return new LiteralNode(type, expression.Value, expression.Kind);
|
||||
return new LiteralNode(type, expression.Value, expression.Kind, expression.Tokens);
|
||||
}
|
||||
|
||||
private StructFieldAccessNode CheckStructFieldAccess(StructFieldAccessSyntax expression)
|
||||
@@ -586,7 +586,7 @@ public sealed class TypeChecker
|
||||
|
||||
var field = fields[0];
|
||||
|
||||
return new StructFieldAccessNode(CheckType(field.Type), structType, boundExpression, expression.Member);
|
||||
return new StructFieldAccessNode(CheckType(field.Type), structType, boundExpression, expression.Member, expression.Tokens);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,7 +644,7 @@ public sealed class TypeChecker
|
||||
initializers[field] = CheckExpression(initializer, CheckType(fields[0].Type));
|
||||
}
|
||||
|
||||
return new StructInitializerNode(structType, initializers);
|
||||
return new StructInitializerNode(structType, initializers, expression.Tokens);
|
||||
}
|
||||
|
||||
private UnaryExpressionNode CheckUnaryExpression(UnaryExpressionSyntax expression)
|
||||
@@ -687,7 +687,7 @@ public sealed class TypeChecker
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(expression.Operator), expression.Operator, null)
|
||||
};
|
||||
|
||||
return new UnaryExpressionNode(type, op, boundOperand);
|
||||
return new UnaryExpressionNode(type, op, boundOperand, expression.Tokens);
|
||||
}
|
||||
|
||||
private FuncSignatureNode CheckFuncSignature(FuncSignatureSyntax node)
|
||||
@@ -696,10 +696,10 @@ public sealed class TypeChecker
|
||||
|
||||
foreach (var parameter in node.Parameters)
|
||||
{
|
||||
parameters.Add(new FuncParameterNode(parameter.Name, CheckType(parameter.Type)));
|
||||
parameters.Add(new FuncParameterNode(parameter.Name, CheckType(parameter.Type), parameter.Tokens));
|
||||
}
|
||||
|
||||
return new FuncSignatureNode(parameters, CheckType(node.ReturnType));
|
||||
return new FuncSignatureNode(parameters, CheckType(node.ReturnType), node.Tokens);
|
||||
}
|
||||
|
||||
private BlockNode CheckBlock(BlockSyntax node, Scope? scope = null)
|
||||
@@ -715,7 +715,7 @@ public sealed class TypeChecker
|
||||
|
||||
_scopes.Pop();
|
||||
|
||||
return new BlockNode(statements);
|
||||
return new BlockNode(statements, node.Tokens);
|
||||
}
|
||||
|
||||
private TypeNode CheckType(TypeSyntax node)
|
||||
|
||||
Reference in New Issue
Block a user