...
This commit is contained in:
@@ -59,7 +59,7 @@ var cFilePath = Path.Combine(".build", "out.c");
|
||||
|
||||
File.WriteAllText(cFilePath, c);
|
||||
|
||||
using var process = Process.Start("gcc", ["-ffreestanding", "-nostartfiles", "-c", "-o", Path.Combine(".build", "out.o"), cFilePath]);
|
||||
using var process = Process.Start("gcc", ["-ffreestanding", "-nostartfiles", "-std=c23", "-g", "-c", "-o", Path.Combine(".build", "out.o"), cFilePath]);
|
||||
|
||||
process.WaitForExit();
|
||||
|
||||
|
||||
@@ -1,54 +1,56 @@
|
||||
using NubLang.Syntax;
|
||||
|
||||
namespace NubLang.Ast;
|
||||
|
||||
public abstract record Node;
|
||||
public abstract record Node(List<Token> Tokens);
|
||||
|
||||
#region Definitions
|
||||
|
||||
public abstract record DefinitionNode(string Module, string Name) : Node;
|
||||
public abstract record DefinitionNode(List<Token> Tokens, string Module, string Name) : Node(Tokens);
|
||||
|
||||
public record FuncParameterNode(string Name, NubType Type) : Node;
|
||||
public record FuncParameterNode(List<Token> Tokens, string Name, NubType Type) : Node(Tokens);
|
||||
|
||||
public record FuncSignatureNode(List<FuncParameterNode> Parameters, NubType ReturnType) : Node;
|
||||
public record FuncSignatureNode(List<Token> Tokens, List<FuncParameterNode> Parameters, NubType ReturnType) : Node(Tokens);
|
||||
|
||||
public record FuncNode(string Module, string Name, string? ExternSymbol, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Module, Name);
|
||||
public record FuncNode(List<Token> Tokens, string Module, string Name, string? ExternSymbol, FuncSignatureNode Signature, BlockNode? Body) : DefinitionNode(Tokens, Module, Name);
|
||||
|
||||
public record StructFieldNode(string Name, NubType Type, ExpressionNode? Value) : Node;
|
||||
public record StructFieldNode(List<Token> Tokens, string Name, NubType Type, ExpressionNode? Value) : Node(Tokens);
|
||||
|
||||
public record StructFuncNode(string Name, FuncSignatureNode Signature, BlockNode Body) : Node;
|
||||
public record StructFuncNode(List<Token> Tokens, string Name, FuncSignatureNode Signature, BlockNode Body) : Node(Tokens);
|
||||
|
||||
public record StructNode(string Module, string Name, List<StructFieldNode> Fields, List<StructFuncNode> Functions) : DefinitionNode(Module, Name);
|
||||
public record StructNode(List<Token> Tokens, string Module, string Name, List<StructFieldNode> Fields, List<StructFuncNode> Functions) : DefinitionNode(Tokens, Module, Name);
|
||||
|
||||
public record GlobalVariableNode(string Module, string Name, ExpressionNode Value) : DefinitionNode(Module, Name);
|
||||
public record GlobalVariableNode(List<Token> Tokens, string Module, string Name, ExpressionNode Value) : DefinitionNode(Tokens, Module, Name);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Statements
|
||||
|
||||
public abstract record StatementNode : Node;
|
||||
public abstract record StatementNode(List<Token> Tokens) : Node(Tokens);
|
||||
|
||||
public abstract record TerminalStatementNode : StatementNode;
|
||||
public abstract record TerminalStatementNode(List<Token> Tokens) : StatementNode(Tokens);
|
||||
|
||||
public record BlockNode(List<StatementNode> Statements) : StatementNode;
|
||||
public record BlockNode(List<Token> Tokens, List<StatementNode> Statements) : StatementNode(Tokens);
|
||||
|
||||
public record StatementFuncCallNode(FuncCallNode FuncCall) : StatementNode;
|
||||
public record StatementFuncCallNode(List<Token> Tokens, FuncCallNode FuncCall) : StatementNode(Tokens);
|
||||
|
||||
public record StatementStructFuncCallNode(StructFuncCallNode StructFuncCall) : StatementNode;
|
||||
public record StatementStructFuncCallNode(List<Token> Tokens, StructFuncCallNode StructFuncCall) : StatementNode(Tokens);
|
||||
|
||||
public record ReturnNode(ExpressionNode? Value) : TerminalStatementNode;
|
||||
public record ReturnNode(List<Token> Tokens, ExpressionNode? Value) : TerminalStatementNode(Tokens);
|
||||
|
||||
public record AssignmentNode(LValueExpressionNode Target, ExpressionNode Value) : StatementNode;
|
||||
public record AssignmentNode(List<Token> Tokens, LValueExpressionNode Target, ExpressionNode Value) : StatementNode(Tokens);
|
||||
|
||||
public record IfNode(ExpressionNode Condition, BlockNode Body, Variant<IfNode, BlockNode>? Else) : StatementNode;
|
||||
public record IfNode(List<Token> Tokens, ExpressionNode Condition, BlockNode Body, Variant<IfNode, BlockNode>? Else) : StatementNode(Tokens);
|
||||
|
||||
public record VariableDeclarationNode(string Name, ExpressionNode? Assignment, NubType Type) : StatementNode;
|
||||
public record VariableDeclarationNode(List<Token> Tokens, string Name, ExpressionNode? Assignment, NubType Type) : StatementNode(Tokens);
|
||||
|
||||
public record ContinueNode : TerminalStatementNode;
|
||||
public record ContinueNode(List<Token> Tokens) : TerminalStatementNode(Tokens);
|
||||
|
||||
public record BreakNode : TerminalStatementNode;
|
||||
public record BreakNode(List<Token> Tokens) : TerminalStatementNode(Tokens);
|
||||
|
||||
public record WhileNode(ExpressionNode Condition, BlockNode Body) : StatementNode;
|
||||
public record WhileNode(List<Token> Tokens, ExpressionNode Condition, BlockNode Body) : StatementNode(Tokens);
|
||||
|
||||
public record DeferNode(StatementNode Statement) : StatementNode;
|
||||
public record DeferNode(List<Token> Tokens, StatementNode Statement) : StatementNode(Tokens);
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -82,58 +84,58 @@ public enum BinaryOperator
|
||||
BitwiseOr
|
||||
}
|
||||
|
||||
public abstract record ExpressionNode(NubType Type) : Node;
|
||||
public abstract record ExpressionNode(List<Token> Tokens, NubType Type) : Node(Tokens);
|
||||
|
||||
public abstract record LValueExpressionNode(NubType Type) : ExpressionNode(Type);
|
||||
public abstract record LValueExpressionNode(List<Token> Tokens, NubType Type) : ExpressionNode(Tokens, Type);
|
||||
|
||||
public abstract record RValueExpressionNode(NubType Type) : ExpressionNode(Type);
|
||||
public abstract record RValueExpressionNode(List<Token> Tokens, NubType Type) : ExpressionNode(Tokens, Type);
|
||||
|
||||
public record StringLiteralNode(NubType Type, string Value) : RValueExpressionNode(Type);
|
||||
public record StringLiteralNode(List<Token> Tokens, NubType Type, string Value) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record CStringLiteralNode(NubType Type, string Value) : RValueExpressionNode(Type);
|
||||
public record CStringLiteralNode(List<Token> Tokens, NubType Type, string Value) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record IntLiteralNode(NubType Type, long Value) : RValueExpressionNode(Type);
|
||||
public record IntLiteralNode(List<Token> Tokens, NubType Type, long Value) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record UIntLiteralNode(NubType Type, ulong Value) : RValueExpressionNode(Type);
|
||||
public record UIntLiteralNode(List<Token> Tokens, NubType Type, ulong Value) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record Float32LiteralNode(NubType Type, float Value) : RValueExpressionNode(Type);
|
||||
public record Float32LiteralNode(List<Token> Tokens, NubType Type, float Value) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record Float64LiteralNode(NubType Type, double Value) : RValueExpressionNode(Type);
|
||||
public record Float64LiteralNode(List<Token> Tokens, NubType Type, double Value) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record BoolLiteralNode(NubType Type, bool Value) : RValueExpressionNode(Type);
|
||||
public record BoolLiteralNode(List<Token> Tokens, NubType Type, bool Value) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record BinaryExpressionNode(NubType Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right) : RValueExpressionNode(Type);
|
||||
public record BinaryExpressionNode(List<Token> Tokens, NubType Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record UnaryExpressionNode(NubType Type, UnaryOperator Operator, ExpressionNode Operand) : RValueExpressionNode(Type);
|
||||
public record UnaryExpressionNode(List<Token> Tokens, NubType Type, UnaryOperator Operator, ExpressionNode Operand) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record FuncCallNode(NubType Type, ExpressionNode Expression, List<ExpressionNode> Parameters) : RValueExpressionNode(Type);
|
||||
public record FuncCallNode(List<Token> Tokens, NubType Type, ExpressionNode Expression, List<ExpressionNode> Parameters) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record StructFuncCallNode(NubType Type, string Module, string StructName, string FuncName, ExpressionNode StructExpression, List<ExpressionNode> Parameters) : RValueExpressionNode(Type);
|
||||
public record StructFuncCallNode(List<Token> Tokens, NubType Type, string Module, string StructName, string FuncName, ExpressionNode StructExpression, List<ExpressionNode> Parameters) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record LValueIdentifierNode(NubType Type, string Name) : LValueExpressionNode(Type);
|
||||
public record LValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record RValueIdentifierNode(NubType Type, string Name) : RValueExpressionNode(Type);
|
||||
public record RValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record FuncIdentifierNode(NubType Type, string Module, string Name, string? ExternSymbol) : RValueExpressionNode(Type);
|
||||
public record FuncIdentifierNode(List<Token> Tokens, NubType Type, string Module, string Name, string? ExternSymbol) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ArrayInitializerNode(NubType Type, ExpressionNode Capacity, NubType ElementType) : RValueExpressionNode(Type);
|
||||
public record ArrayInitializerNode(List<Token> Tokens, NubType Type, ExpressionNode Capacity, NubType ElementType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ArrayIndexAccessNode(NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Type);
|
||||
public record ArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record AddressOfNode(NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Type);
|
||||
public record AddressOfNode(List<Token> Tokens, NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record StructFieldAccessNode(NubType Type, ExpressionNode Target, string Field) : LValueExpressionNode(Type);
|
||||
public record StructFieldAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, string Field) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record StructInitializerNode(NubStructType StructType, Dictionary<string, ExpressionNode> Initializers) : RValueExpressionNode(StructType);
|
||||
public record StructInitializerNode(List<Token> Tokens, NubStructType StructType, Dictionary<string, ExpressionNode> Initializers) : RValueExpressionNode(Tokens, StructType);
|
||||
|
||||
public record DereferenceNode(NubType Type, ExpressionNode Target) : LValueExpressionNode(Type);
|
||||
public record DereferenceNode(List<Token> Tokens, NubType Type, ExpressionNode Target) : LValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ConvertIntNode(NubType Type, ExpressionNode Value, NubIntType ValueType, NubIntType TargetType) : RValueExpressionNode(Type);
|
||||
public record ConvertIntNode(List<Token> Tokens, NubType Type, ExpressionNode Value, NubIntType ValueType, NubIntType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record ConvertFloatNode(NubType Type, ExpressionNode Value, NubFloatType ValueType, NubFloatType TargetType) : RValueExpressionNode(Type);
|
||||
public record ConvertFloatNode(List<Token> Tokens, NubType Type, ExpressionNode Value, NubFloatType ValueType, NubFloatType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record SizeBuiltinNode(NubType Type, NubType TargetType) : RValueExpressionNode(Type);
|
||||
public record SizeBuiltinNode(List<Token> Tokens, NubType Type, NubType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
public record FloatToIntBuiltinNode(NubType Type, ExpressionNode Value, NubFloatType ValueType, NubIntType TargetType) : RValueExpressionNode(Type);
|
||||
public record FloatToIntBuiltinNode(List<Token> Tokens, NubType Type, ExpressionNode Value, NubFloatType ValueType, NubIntType TargetType) : RValueExpressionNode(Tokens, Type);
|
||||
|
||||
#endregion
|
||||
@@ -160,7 +160,7 @@ public sealed class TypeChecker
|
||||
var fields = node.Fields.Select(CheckStructField).ToList();
|
||||
var functions = node.Functions.Select(CheckStructFunc).ToList();
|
||||
|
||||
return new StructNode(CurrentScope.Module, node.Name, fields, functions);
|
||||
return new StructNode(node.Tokens, CurrentScope.Module, node.Name, fields, functions);
|
||||
}
|
||||
|
||||
private StructFuncNode CheckStructFunc(StructFuncSyntax function)
|
||||
@@ -173,7 +173,7 @@ public sealed class TypeChecker
|
||||
_funcReturnTypes.Push(ResolveType(function.Signature.ReturnType));
|
||||
var body = CheckBlock(function.Body);
|
||||
_funcReturnTypes.Pop();
|
||||
return new StructFuncNode(function.Name, CheckFuncSignature(function.Signature), body);
|
||||
return new StructFuncNode(function.Tokens, function.Name, CheckFuncSignature(function.Signature), body);
|
||||
}
|
||||
|
||||
private StructFieldNode CheckStructField(StructFieldSyntax field)
|
||||
@@ -184,7 +184,7 @@ public sealed class TypeChecker
|
||||
value = CheckExpression(field.Value, ResolveType(field.Type));
|
||||
}
|
||||
|
||||
return new StructFieldNode(field.Name, ResolveType(field.Type), value);
|
||||
return new StructFieldNode(field.Tokens, field.Name, ResolveType(field.Type), value);
|
||||
}
|
||||
|
||||
private FuncNode CheckFuncDefinition(FuncSyntax node)
|
||||
@@ -207,7 +207,7 @@ public sealed class TypeChecker
|
||||
{
|
||||
if (signature.ReturnType is NubVoidType)
|
||||
{
|
||||
body.Statements.Add(new ReturnNode(null));
|
||||
body.Statements.Add(new ReturnNode(node.Tokens.Skip(node.Tokens.Count - 1).ToList(), null));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -221,12 +221,12 @@ public sealed class TypeChecker
|
||||
_funcReturnTypes.Pop();
|
||||
}
|
||||
|
||||
return new FuncNode(CurrentScope.Module, node.Name, node.ExternSymbol, signature, body);
|
||||
return new FuncNode(node.Tokens, CurrentScope.Module, node.Name, node.ExternSymbol, signature, body);
|
||||
}
|
||||
|
||||
private GlobalVariableNode CheckGlobalVariable(GlobalVariableSyntax node)
|
||||
{
|
||||
return new GlobalVariableNode(CurrentScope.Module, node.Name, CheckExpression(node.Value));
|
||||
return new GlobalVariableNode(node.Tokens, CurrentScope.Module, node.Name, CheckExpression(node.Value));
|
||||
}
|
||||
|
||||
private AssignmentNode CheckAssignment(AssignmentSyntax statement)
|
||||
@@ -238,7 +238,7 @@ public sealed class TypeChecker
|
||||
}
|
||||
|
||||
var value = CheckExpression(statement.Value, lValue.Type);
|
||||
return new AssignmentNode(lValue, value);
|
||||
return new AssignmentNode(statement.Tokens, lValue, value);
|
||||
}
|
||||
|
||||
private IfNode CheckIf(IfSyntax statement)
|
||||
@@ -251,7 +251,7 @@ public sealed class TypeChecker
|
||||
elseStatement = statement.Else.Value.Match<Variant<IfNode, BlockNode>>(elif => CheckIf(elif), el => CheckBlock(el));
|
||||
}
|
||||
|
||||
return new IfNode(condition, body, elseStatement);
|
||||
return new IfNode(statement.Tokens, condition, body, elseStatement);
|
||||
}
|
||||
|
||||
private ReturnNode CheckReturn(ReturnSyntax statement)
|
||||
@@ -263,7 +263,7 @@ public sealed class TypeChecker
|
||||
value = CheckExpression(statement.Value, _funcReturnTypes.Peek());
|
||||
}
|
||||
|
||||
return new ReturnNode(value);
|
||||
return new ReturnNode(statement.Tokens, value);
|
||||
}
|
||||
|
||||
private StatementNode CheckStatementExpression(StatementExpressionSyntax statement)
|
||||
@@ -272,8 +272,8 @@ public sealed class TypeChecker
|
||||
|
||||
return expression switch
|
||||
{
|
||||
FuncCallNode funcCall => new StatementFuncCallNode(funcCall),
|
||||
StructFuncCallNode structFuncCall => new StatementStructFuncCallNode(structFuncCall),
|
||||
FuncCallNode funcCall => new StatementFuncCallNode(statement.Tokens, funcCall),
|
||||
StructFuncCallNode structFuncCall => new StatementStructFuncCallNode(statement.Tokens, structFuncCall),
|
||||
_ => throw new TypeCheckerException(Diagnostic.Error("Expressions statements can only be function calls").At(statement).Build())
|
||||
};
|
||||
}
|
||||
@@ -301,14 +301,14 @@ public sealed class TypeChecker
|
||||
|
||||
CurrentScope.DeclareVariable(new Variable(statement.Name, type, VariableKind.LValue));
|
||||
|
||||
return new VariableDeclarationNode(statement.Name, assignmentNode, type);
|
||||
return new VariableDeclarationNode(statement.Tokens, statement.Name, assignmentNode, type);
|
||||
}
|
||||
|
||||
private WhileNode CheckWhile(WhileSyntax statement)
|
||||
{
|
||||
var condition = CheckExpression(statement.Condition, new NubBoolType());
|
||||
var body = CheckBlock(statement.Body);
|
||||
return new WhileNode(condition, body);
|
||||
return new WhileNode(statement.Tokens, condition, body);
|
||||
}
|
||||
|
||||
private FuncSignatureNode CheckFuncSignature(FuncSignatureSyntax statement)
|
||||
@@ -316,10 +316,10 @@ public sealed class TypeChecker
|
||||
var parameters = new List<FuncParameterNode>();
|
||||
foreach (var parameter in statement.Parameters)
|
||||
{
|
||||
parameters.Add(new FuncParameterNode(parameter.Name, ResolveType(parameter.Type)));
|
||||
parameters.Add(new FuncParameterNode(parameter.Tokens, parameter.Name, ResolveType(parameter.Type)));
|
||||
}
|
||||
|
||||
return new FuncSignatureNode(parameters, ResolveType(statement.ReturnType));
|
||||
return new FuncSignatureNode(statement.Tokens, parameters, ResolveType(statement.ReturnType));
|
||||
}
|
||||
|
||||
private ExpressionNode CheckExpression(ExpressionSyntax node, NubType? expectedType = null)
|
||||
@@ -343,7 +343,7 @@ public sealed class TypeChecker
|
||||
MemberAccessSyntax expression => CheckMemberAccess(expression),
|
||||
StructInitializerSyntax expression => CheckStructInitializer(expression, expectedType),
|
||||
InterpretBuiltinSyntax expression => CheckExpression(expression.Target) with { Type = ResolveType(expression.Type) },
|
||||
SizeBuiltinSyntax expression => new SizeBuiltinNode(new NubIntType(false, 64), ResolveType(expression.Type)),
|
||||
SizeBuiltinSyntax expression => new SizeBuiltinNode(node.Tokens, new NubIntType(false, 64), ResolveType(expression.Type)),
|
||||
FloatToIntBuiltinSyntax expression => CheckFloatToInt(expression),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(node))
|
||||
};
|
||||
@@ -357,7 +357,7 @@ public sealed class TypeChecker
|
||||
{
|
||||
if (sourceIntType.Signed == targetIntType.Signed && sourceIntType.Width < targetIntType.Width)
|
||||
{
|
||||
return new ConvertIntNode(targetIntType, result, sourceIntType, targetIntType);
|
||||
return new ConvertIntNode(node.Tokens, targetIntType, result, sourceIntType, targetIntType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ public sealed class TypeChecker
|
||||
{
|
||||
if (sourceFloatType.Width < targetFloatType.Width)
|
||||
{
|
||||
return new ConvertFloatNode(targetFloatType, result, sourceFloatType, targetFloatType);
|
||||
return new ConvertFloatNode(node.Tokens, targetFloatType, result, sourceFloatType, targetFloatType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ public sealed class TypeChecker
|
||||
.Build());
|
||||
}
|
||||
|
||||
return new FloatToIntBuiltinNode(targetIntType, value, sourceFloatType, targetIntType);
|
||||
return new FloatToIntBuiltinNode(expression.Tokens, targetIntType, value, sourceFloatType, targetIntType);
|
||||
}
|
||||
|
||||
private AddressOfNode CheckAddressOf(AddressOfSyntax expression)
|
||||
@@ -404,7 +404,7 @@ public sealed class TypeChecker
|
||||
}
|
||||
|
||||
var type = new NubPointerType(target.Type);
|
||||
return new AddressOfNode(type, lvalue);
|
||||
return new AddressOfNode(expression.Tokens, type, lvalue);
|
||||
}
|
||||
|
||||
private ArrayIndexAccessNode CheckArrayIndexAccess(ArrayIndexAccessSyntax expression)
|
||||
@@ -416,7 +416,7 @@ public sealed class TypeChecker
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Cannot use array indexer on type {target.Type}").At(expression).Build());
|
||||
}
|
||||
|
||||
return new ArrayIndexAccessNode(arrayType.ElementType, target, index);
|
||||
return new ArrayIndexAccessNode(expression.Tokens, arrayType.ElementType, target, index);
|
||||
}
|
||||
|
||||
private ArrayInitializerNode CheckArrayInitializer(ArrayInitializerSyntax expression)
|
||||
@@ -424,7 +424,7 @@ public sealed class TypeChecker
|
||||
var elementType = ResolveType(expression.ElementType);
|
||||
var type = new NubArrayType(elementType);
|
||||
var capacity = CheckExpression(expression.Capacity);
|
||||
return new ArrayInitializerNode(type, capacity, elementType);
|
||||
return new ArrayInitializerNode(expression.Tokens, type, capacity, elementType);
|
||||
}
|
||||
|
||||
private BinaryExpressionNode CheckBinaryExpression(BinaryExpressionSyntax expression, NubType? expectedType)
|
||||
@@ -469,7 +469,7 @@ public sealed class TypeChecker
|
||||
|
||||
var right = CheckExpression(expression.Right, left.Type);
|
||||
|
||||
return new BinaryExpressionNode(new NubBoolType(), left, op, right);
|
||||
return new BinaryExpressionNode(expression.Tokens, new NubBoolType(), left, op, right);
|
||||
}
|
||||
case BinaryOperatorSyntax.GreaterThan:
|
||||
case BinaryOperatorSyntax.GreaterThanOrEqual:
|
||||
@@ -488,7 +488,7 @@ public sealed class TypeChecker
|
||||
|
||||
var right = CheckExpression(expression.Right, left.Type);
|
||||
|
||||
return new BinaryExpressionNode(new NubBoolType(), left, op, right);
|
||||
return new BinaryExpressionNode(expression.Tokens, new NubBoolType(), left, op, right);
|
||||
}
|
||||
case BinaryOperatorSyntax.LogicalAnd:
|
||||
case BinaryOperatorSyntax.LogicalOr:
|
||||
@@ -505,7 +505,7 @@ public sealed class TypeChecker
|
||||
|
||||
var right = CheckExpression(expression.Right, left.Type);
|
||||
|
||||
return new BinaryExpressionNode(new NubBoolType(), left, op, right);
|
||||
return new BinaryExpressionNode(expression.Tokens, new NubBoolType(), left, op, right);
|
||||
}
|
||||
case BinaryOperatorSyntax.Plus:
|
||||
{
|
||||
@@ -513,7 +513,7 @@ public sealed class TypeChecker
|
||||
if (left.Type is NubIntType or NubFloatType or NubStringType or NubCStringType)
|
||||
{
|
||||
var right = CheckExpression(expression.Right, left.Type);
|
||||
return new BinaryExpressionNode(left.Type, left, op, right);
|
||||
return new BinaryExpressionNode(expression.Tokens, left.Type, left, op, right);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
@@ -537,7 +537,7 @@ public sealed class TypeChecker
|
||||
|
||||
var right = CheckExpression(expression.Right, left.Type);
|
||||
|
||||
return new BinaryExpressionNode(left.Type, left, op, right);
|
||||
return new BinaryExpressionNode(expression.Tokens, left.Type, left, op, right);
|
||||
}
|
||||
case BinaryOperatorSyntax.LeftShift:
|
||||
case BinaryOperatorSyntax.RightShift:
|
||||
@@ -556,7 +556,7 @@ public sealed class TypeChecker
|
||||
|
||||
var right = CheckExpression(expression.Right, left.Type);
|
||||
|
||||
return new BinaryExpressionNode(left.Type, left, op, right);
|
||||
return new BinaryExpressionNode(expression.Tokens, left.Type, left, op, right);
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -580,7 +580,7 @@ public sealed class TypeChecker
|
||||
.Build());
|
||||
}
|
||||
|
||||
return new UnaryExpressionNode(operand.Type, UnaryOperator.Negate, operand);
|
||||
return new UnaryExpressionNode(expression.Tokens, operand.Type, UnaryOperator.Negate, operand);
|
||||
}
|
||||
case UnaryOperatorSyntax.Invert:
|
||||
{
|
||||
@@ -593,7 +593,7 @@ public sealed class TypeChecker
|
||||
.Build());
|
||||
}
|
||||
|
||||
return new UnaryExpressionNode(operand.Type, UnaryOperator.Invert, operand);
|
||||
return new UnaryExpressionNode(expression.Tokens, operand.Type, UnaryOperator.Invert, operand);
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -610,7 +610,7 @@ public sealed class TypeChecker
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Cannot dereference non-pointer type {target.Type}").At(expression).Build());
|
||||
}
|
||||
|
||||
return new DereferenceNode(pointerType.BaseType, target);
|
||||
return new DereferenceNode(expression.Tokens, pointerType.BaseType, target);
|
||||
}
|
||||
|
||||
private FuncCallNode CheckFuncCall(FuncCallSyntax expression)
|
||||
@@ -647,7 +647,7 @@ public sealed class TypeChecker
|
||||
parameters.Add(parameterExpression);
|
||||
}
|
||||
|
||||
return new FuncCallNode(funcType.ReturnType, accessor, parameters);
|
||||
return new FuncCallNode(expression.Tokens, funcType.ReturnType, accessor, parameters);
|
||||
}
|
||||
|
||||
private StructFuncCallNode CheckMemberFuncCall(MemberFuncCallSyntax expression)
|
||||
@@ -691,7 +691,7 @@ public sealed class TypeChecker
|
||||
parameters.Add(parameterExpression);
|
||||
}
|
||||
|
||||
return new StructFuncCallNode(function.ReturnType, structType.Module, structType.Name, expression.Name, target, parameters);
|
||||
return new StructFuncCallNode(expression.Tokens, function.ReturnType, structType.Module, structType.Name, expression.Name, target, parameters);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
@@ -708,8 +708,8 @@ public sealed class TypeChecker
|
||||
{
|
||||
return scopeIdent.Kind switch
|
||||
{
|
||||
VariableKind.LValue => new LValueIdentifierNode(scopeIdent.Type, expression.Name),
|
||||
VariableKind.RValue => new RValueIdentifierNode(scopeIdent.Type, expression.Name),
|
||||
VariableKind.LValue => new LValueIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name),
|
||||
VariableKind.RValue => new RValueIdentifierNode(expression.Tokens, scopeIdent.Type, expression.Name),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
@@ -722,7 +722,7 @@ public sealed class TypeChecker
|
||||
{
|
||||
var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType));
|
||||
return new FuncIdentifierNode(type, CurrentScope.Module, expression.Name, function.ExternSymbol);
|
||||
return new FuncIdentifierNode(expression.Tokens, type, CurrentScope.Module, expression.Name, function.ExternSymbol);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic.Error($"Symbol {expression.Name} not found").At(expression).Build());
|
||||
@@ -760,7 +760,7 @@ public sealed class TypeChecker
|
||||
{
|
||||
var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList();
|
||||
var type = new NubFuncType(parameters, ResolveType(function.Signature.ReturnType));
|
||||
return new FuncIdentifierNode(type, expression.Module, expression.Name, function.ExternSymbol);
|
||||
return new FuncIdentifierNode(expression.Tokens, type, expression.Module, expression.Name, function.ExternSymbol);
|
||||
}
|
||||
|
||||
throw new TypeCheckerException(Diagnostic
|
||||
@@ -773,9 +773,9 @@ public sealed class TypeChecker
|
||||
{
|
||||
return expectedType switch
|
||||
{
|
||||
NubCStringType => new CStringLiteralNode(expectedType, expression.Value),
|
||||
NubStringType => new StringLiteralNode(expectedType, expression.Value),
|
||||
_ => new CStringLiteralNode(new NubCStringType(), expression.Value)
|
||||
NubCStringType => new CStringLiteralNode(expression.Tokens, expectedType, expression.Value),
|
||||
NubStringType => new StringLiteralNode(expression.Tokens, expectedType, expression.Value),
|
||||
_ => new CStringLiteralNode(expression.Tokens, new NubCStringType(), expression.Value)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -784,35 +784,35 @@ public sealed class TypeChecker
|
||||
if (expectedType is NubIntType intType)
|
||||
{
|
||||
return intType.Signed
|
||||
? new IntLiteralNode(intType, Convert.ToInt64(expression.Value, expression.Base))
|
||||
: new UIntLiteralNode(intType, Convert.ToUInt64(expression.Value, expression.Base));
|
||||
? new IntLiteralNode(expression.Tokens, intType, Convert.ToInt64(expression.Value, expression.Base))
|
||||
: new UIntLiteralNode(expression.Tokens, intType, Convert.ToUInt64(expression.Value, expression.Base));
|
||||
}
|
||||
|
||||
if (expectedType is NubFloatType floatType)
|
||||
{
|
||||
return floatType.Width switch
|
||||
{
|
||||
32 => new Float32LiteralNode(floatType, Convert.ToSingle(Convert.ToInt64(expression.Value, expression.Base))),
|
||||
64 => new Float64LiteralNode(floatType, Convert.ToDouble(Convert.ToInt64(expression.Value, expression.Base))),
|
||||
32 => new Float32LiteralNode(expression.Tokens, floatType, Convert.ToSingle(Convert.ToInt64(expression.Value, expression.Base))),
|
||||
64 => new Float64LiteralNode(expression.Tokens, floatType, Convert.ToDouble(Convert.ToInt64(expression.Value, expression.Base))),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
var type = new NubIntType(true, 64);
|
||||
return new IntLiteralNode(type, Convert.ToInt64(expression.Value, expression.Base));
|
||||
return new IntLiteralNode(expression.Tokens, type, Convert.ToInt64(expression.Value, expression.Base));
|
||||
}
|
||||
|
||||
private ExpressionNode CheckFloatLiteral(FloatLiteralSyntax expression, NubType? expectedType)
|
||||
{
|
||||
var type = expectedType as NubFloatType ?? new NubFloatType(64);
|
||||
return type.Width == 32
|
||||
? new Float32LiteralNode(type, Convert.ToSingle(expression.Value))
|
||||
: new Float64LiteralNode(type, Convert.ToDouble(expression.Value));
|
||||
? new Float32LiteralNode(expression.Tokens, type, Convert.ToSingle(expression.Value))
|
||||
: new Float64LiteralNode(expression.Tokens, type, Convert.ToDouble(expression.Value));
|
||||
}
|
||||
|
||||
private BoolLiteralNode CheckBoolLiteral(BoolLiteralSyntax expression)
|
||||
{
|
||||
return new BoolLiteralNode(new NubBoolType(), expression.Value);
|
||||
return new BoolLiteralNode(expression.Tokens, new NubBoolType(), expression.Value);
|
||||
}
|
||||
|
||||
private ExpressionNode CheckMemberAccess(MemberAccessSyntax expression)
|
||||
@@ -831,7 +831,7 @@ public sealed class TypeChecker
|
||||
.Build());
|
||||
}
|
||||
|
||||
return new StructFieldAccessNode(field.Type, target, expression.Member);
|
||||
return new StructFieldAccessNode(expression.Tokens, field.Type, target, expression.Member);
|
||||
}
|
||||
default:
|
||||
{
|
||||
@@ -902,7 +902,7 @@ public sealed class TypeChecker
|
||||
.Build());
|
||||
}
|
||||
|
||||
return new StructInitializerNode(structType, initializers);
|
||||
return new StructInitializerNode(expression.Tokens, structType, initializers);
|
||||
}
|
||||
|
||||
private BlockNode CheckBlock(BlockSyntax node)
|
||||
@@ -937,7 +937,7 @@ public sealed class TypeChecker
|
||||
}
|
||||
}
|
||||
|
||||
return new BlockNode(statements);
|
||||
return new BlockNode(node.Tokens, statements);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -947,14 +947,14 @@ public sealed class TypeChecker
|
||||
{
|
||||
AssignmentSyntax assignmentStmt => CheckAssignment(assignmentStmt),
|
||||
BlockSyntax blockStmt => CheckBlock(blockStmt),
|
||||
BreakSyntax => new BreakNode(),
|
||||
ContinueSyntax => new ContinueNode(),
|
||||
BreakSyntax => new BreakNode(statement.Tokens),
|
||||
ContinueSyntax => new ContinueNode(statement.Tokens),
|
||||
IfSyntax ifStmt => CheckIf(ifStmt),
|
||||
ReturnSyntax retStmt => CheckReturn(retStmt),
|
||||
StatementExpressionSyntax stmtExpr => CheckStatementExpression(stmtExpr),
|
||||
VariableDeclarationSyntax varDeclStmt => CheckVariableDeclaration(varDeclStmt),
|
||||
WhileSyntax whileStmt => CheckWhile(whileStmt),
|
||||
DeferSyntax defer => new DeferNode(CheckStatement(defer.Statement)),
|
||||
DeferSyntax defer => new DeferNode(statement.Tokens, CheckStatement(defer.Statement)),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(statement))
|
||||
};
|
||||
}
|
||||
@@ -1142,7 +1142,7 @@ public sealed class TypeChecker
|
||||
CurrentScope.DeclareVariable(new Variable("this", structType, VariableKind.RValue));
|
||||
var fields = templateDef.Fields.Select(CheckStructField).ToList();
|
||||
var functions = templateDef.Functions.Select(CheckStructFunc).ToList();
|
||||
Definitions.Add(new StructNode(structTemplate.Module, mangledName, fields, functions));
|
||||
Definitions.Add(new StructNode(templateDef.Tokens, structTemplate.Module, mangledName, fields, functions));
|
||||
_checkedTemplateStructs.Add($"{structTemplate.Module}.{mangledName}");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using NubLang.Ast;
|
||||
using NubLang.Syntax;
|
||||
|
||||
namespace NubLang.Generation;
|
||||
|
||||
@@ -105,45 +106,45 @@ public class Generator
|
||||
|
||||
public string Emit()
|
||||
{
|
||||
var header = """
|
||||
typedef __builtin_va_list va_list;
|
||||
const string header = """
|
||||
typedef __builtin_va_list va_list;
|
||||
|
||||
#define va_start(ap, last) __builtin_va_start(ap, last)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
||||
#define va_start(ap, last) __builtin_va_start(ap, last)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
||||
|
||||
#define NULL ((void*)0)
|
||||
#define NULL ((void*)0)
|
||||
|
||||
typedef unsigned long size_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef unsigned long size_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef signed char i8;
|
||||
typedef unsigned short u16;
|
||||
typedef signed short i16;
|
||||
typedef unsigned int u32;
|
||||
typedef signed int i32;
|
||||
typedef unsigned long long u64;
|
||||
typedef signed long long i64;
|
||||
typedef unsigned char u8;
|
||||
typedef signed char i8;
|
||||
typedef unsigned short u16;
|
||||
typedef signed short i16;
|
||||
typedef unsigned int u32;
|
||||
typedef signed int i32;
|
||||
typedef unsigned long long u64;
|
||||
typedef signed long long i64;
|
||||
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
#define I8_C(x) x
|
||||
#define U8_C(x) x##U
|
||||
#define I8_C(x) x
|
||||
#define U8_C(x) x##U
|
||||
|
||||
#define I16_C(x) x
|
||||
#define U16_C(x) x##U
|
||||
#define I16_C(x) x
|
||||
#define U16_C(x) x##U
|
||||
|
||||
#define I32_C(x) x
|
||||
#define U32_C(x) x##U
|
||||
#define I32_C(x) x
|
||||
#define U32_C(x) x##U
|
||||
|
||||
#define I64_C(x) x##LL
|
||||
#define U64_C(x) x##ULL
|
||||
""";
|
||||
#define I64_C(x) x##LL
|
||||
#define U64_C(x) x##ULL
|
||||
""";
|
||||
|
||||
foreach (var structType in _structTypes)
|
||||
{
|
||||
@@ -165,6 +166,7 @@ public class Generator
|
||||
|
||||
foreach (var funcNode in _definitions.OfType<FuncNode>())
|
||||
{
|
||||
EmitLine(funcNode.Tokens);
|
||||
appendNewLine = true;
|
||||
var parameters = funcNode.Signature.Parameters.Count != 0
|
||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
@@ -183,6 +185,7 @@ public class Generator
|
||||
{
|
||||
foreach (var structFuncNode in structNode.Functions)
|
||||
{
|
||||
EmitLine(structFuncNode.Tokens);
|
||||
var parameters = structFuncNode.Signature.Parameters.Count != 0
|
||||
? string.Join(", ", structFuncNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
: "void";
|
||||
@@ -198,6 +201,7 @@ public class Generator
|
||||
{
|
||||
if (funcNode.Body == null) continue;
|
||||
|
||||
EmitLine(funcNode.Tokens);
|
||||
var parameters = funcNode.Signature.Parameters.Count != 0
|
||||
? string.Join(", ", funcNode.Signature.Parameters.Select(x => MapNameWithType(x.Type, x.Name)))
|
||||
: "void";
|
||||
@@ -232,6 +236,7 @@ public class Generator
|
||||
|
||||
private void EmitStatement(StatementNode statementNode)
|
||||
{
|
||||
EmitLine(statementNode.Tokens);
|
||||
switch (statementNode)
|
||||
{
|
||||
case AssignmentNode assignmentNode:
|
||||
@@ -272,6 +277,16 @@ public class Generator
|
||||
}
|
||||
}
|
||||
|
||||
private void EmitLine(List<Token> tokens)
|
||||
{
|
||||
if (tokens.Count >= 1)
|
||||
{
|
||||
var file = tokens[0].Span.FilePath;
|
||||
var line = tokens[0].Span.Start.Line;
|
||||
_writer.WriteLine($"#line {line} \"{file}\"");
|
||||
}
|
||||
}
|
||||
|
||||
private void EmitAssignment(AssignmentNode assignmentNode)
|
||||
{
|
||||
var target = EmitExpression(assignmentNode.Target);
|
||||
@@ -294,18 +309,14 @@ public class Generator
|
||||
_deferStack.Peek().Add(deferNode);
|
||||
}
|
||||
|
||||
private void EmitIf(IfNode ifNode)
|
||||
private void EmitIf(IfNode ifNode, bool elseIf = false)
|
||||
{
|
||||
var condition = EmitExpression(ifNode.Condition);
|
||||
_writer.WriteLine($"if ({condition})");
|
||||
_writer.WriteLine($"{(elseIf ? "else" : "")} if ({condition})");
|
||||
EmitBlock(ifNode.Body);
|
||||
ifNode.Else?.Match
|
||||
(
|
||||
elseIfNode =>
|
||||
{
|
||||
_writer.Write("else ");
|
||||
EmitIf(elseIfNode);
|
||||
},
|
||||
elseIfNode => EmitIf(elseIfNode, true),
|
||||
elseNode =>
|
||||
{
|
||||
_writer.WriteLine("else");
|
||||
|
||||
Reference in New Issue
Block a user