This commit is contained in:
nub31
2025-09-09 17:44:57 +02:00
parent 5a54d26fd0
commit e02399e102
9 changed files with 143 additions and 126 deletions

View File

@@ -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)
}

View File

@@ -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,

View File

@@ -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");

View File

@@ -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,8 +1087,6 @@ 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;
@@ -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}");
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)