This commit is contained in:
nub31
2025-10-21 20:47:00 +02:00
parent 4a01fbc306
commit e3f819411c
6 changed files with 74 additions and 125 deletions

View File

@@ -100,23 +100,19 @@ public record UnaryExpressionNode(List<Token> Tokens, NubType Type, UnaryOperato
public record FuncCallNode(List<Token> Tokens, NubType Type, ExpressionNode Expression, List<ExpressionNode> Parameters) : RValueExpressionNode(Tokens, Type); public record FuncCallNode(List<Token> Tokens, NubType Type, ExpressionNode Expression, List<ExpressionNode> Parameters) : RValueExpressionNode(Tokens, Type);
public record LValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : LValueExpressionNode(Tokens, Type); public record VariableIdentifierNode(List<Token> Tokens, NubType Type, string Name) : LValueExpressionNode(Tokens, Type);
public record RValueIdentifierNode(List<Token> Tokens, NubType Type, string Name) : RValueExpressionNode(Tokens, Type);
public record FuncIdentifierNode(List<Token> Tokens, NubType Type, string Module, string Name, string? ExternSymbol) : RValueExpressionNode(Tokens, Type); public record FuncIdentifierNode(List<Token> Tokens, NubType Type, string Module, string Name, string? ExternSymbol) : RValueExpressionNode(Tokens, Type);
public record ArrayInitializerNode(List<Token> Tokens, NubType Type, ExpressionNode Capacity, NubType ElementType) : RValueExpressionNode(Tokens, Type); public record ArrayInitializerNode(List<Token> Tokens, NubType Type, ExpressionNode Capacity, NubType ElementType) : LValueExpressionNode(Tokens, Type);
public record ArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type); public record ArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
public record ConstArrayIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
public record SliceIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type); public record SliceIndexAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, ExpressionNode Index) : LValueExpressionNode(Tokens, Type);
public record AddressOfNode(List<Token> Tokens, NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Tokens, Type); public record AddressOfNode(List<Token> Tokens, NubType Type, LValueExpressionNode LValue) : RValueExpressionNode(Tokens, Type);
public record StructFieldAccessNode(List<Token> Tokens, NubType Type, LValueExpressionNode Target, string Field) : LValueExpressionNode(Tokens, Type); public record StructFieldAccessNode(List<Token> Tokens, NubType Type, ExpressionNode Target, string Field) : LValueExpressionNode(Tokens, Type);
public record StructInitializerNode(List<Token> Tokens, NubStructType StructType, Dictionary<string, ExpressionNode> Initializers) : LValueExpressionNode(Tokens, StructType); public record StructInitializerNode(List<Token> Tokens, NubStructType StructType, Dictionary<string, ExpressionNode> Initializers) : LValueExpressionNode(Tokens, StructType);

View File

@@ -109,7 +109,7 @@ public sealed class TypeChecker
{ {
foreach (var parameter in node.Prototype.Parameters) foreach (var parameter in node.Prototype.Parameters)
{ {
CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type), VariableKind.RValue)); CurrentScope.DeclareVariable(new Variable(parameter.Name, ResolveType(parameter.Type)));
} }
var prototype = CheckFuncPrototype(node.Prototype); var prototype = CheckFuncPrototype(node.Prototype);
@@ -211,7 +211,7 @@ public sealed class TypeChecker
throw new TypeCheckerException(Diagnostic.Error($"Cannot infer type of variable {statement.Name}").At(statement).Build()); throw new TypeCheckerException(Diagnostic.Error($"Cannot infer type of variable {statement.Name}").At(statement).Build());
} }
CurrentScope.DeclareVariable(new Variable(statement.Name, type, VariableKind.LValue)); CurrentScope.DeclareVariable(new Variable(statement.Name, type));
return new VariableDeclarationNode(statement.Tokens, statement.Name, assignmentNode, type); return new VariableDeclarationNode(statement.Tokens, statement.Name, assignmentNode, type);
} }
@@ -248,7 +248,6 @@ public sealed class TypeChecker
LocalIdentifierSyntax expression => CheckLocalIdentifier(expression), LocalIdentifierSyntax expression => CheckLocalIdentifier(expression),
ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression), ModuleIdentifierSyntax expression => CheckModuleIdentifier(expression),
BoolLiteralSyntax expression => CheckBoolLiteral(expression), BoolLiteralSyntax expression => CheckBoolLiteral(expression),
ConstArrayInitializerSyntax expression => CheckConstArrayInitializer(expression),
StringLiteralSyntax expression => CheckStringLiteral(expression, expectedType), StringLiteralSyntax expression => CheckStringLiteral(expression, expectedType),
IntLiteralSyntax expression => CheckIntLiteral(expression, expectedType), IntLiteralSyntax expression => CheckIntLiteral(expression, expectedType),
FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType), FloatLiteralSyntax expression => CheckFloatLiteral(expression, expectedType),
@@ -284,13 +283,6 @@ public sealed class TypeChecker
throw new TypeCheckerException(Diagnostic.Error($"Cannot convert {result.Type} to {expectedType}").At(node).Build()); throw new TypeCheckerException(Diagnostic.Error($"Cannot convert {result.Type} to {expectedType}").At(node).Build());
} }
private ArrayInitializerNode CheckConstArrayInitializer(ConstArrayInitializerSyntax expression)
{
var elementType = ResolveType(expression.ElementType);
var type = new NubArrayType(elementType);
return new ArrayInitializerNode(expression.Tokens, type, new IntLiteralNode([], new NubIntType(false, 64), expression.Capacity), elementType);
}
private FloatToIntBuiltinNode CheckFloatToInt(FloatToIntBuiltinSyntax expression) private FloatToIntBuiltinNode CheckFloatToInt(FloatToIntBuiltinSyntax expression)
{ {
var value = CheckExpression(expression.Value); var value = CheckExpression(expression.Value);
@@ -334,8 +326,6 @@ public sealed class TypeChecker
return target.Type switch return target.Type switch
{ {
NubArrayType arrayType => new ArrayIndexAccessNode(expression.Tokens, arrayType.ElementType, target, index), NubArrayType arrayType => new ArrayIndexAccessNode(expression.Tokens, arrayType.ElementType, target, index),
NubConstArrayType constArrayType => new ConstArrayIndexAccessNode(expression.Tokens, constArrayType.ElementType, target, index),
NubSliceType sliceType => new SliceIndexAccessNode(expression.Tokens, sliceType.ElementType, target, index),
_ => throw new TypeCheckerException(Diagnostic.Error($"Cannot use array indexer on type {target.Type}").At(expression).Build()) _ => throw new TypeCheckerException(Diagnostic.Error($"Cannot use array indexer on type {target.Type}").At(expression).Build())
}; };
} }
@@ -576,12 +566,7 @@ public sealed class TypeChecker
var scopeIdent = CurrentScope.LookupVariable(expression.Name); var scopeIdent = CurrentScope.LookupVariable(expression.Name);
if (scopeIdent != null) if (scopeIdent != null)
{ {
return scopeIdent.Kind switch return new VariableIdentifierNode(expression.Tokens, 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()
};
} }
var module = _importedModules[CurrentScope.Module]; var module = _importedModules[CurrentScope.Module];
@@ -686,12 +671,7 @@ public sealed class TypeChecker
.Build()); .Build());
} }
if (target is not LValueExpressionNode lValueTarget) return new StructFieldAccessNode(expression.Tokens, field.Type, target, expression.Member);
{
throw new TypeCheckerException(Diagnostic.Error("Struct field access is not an lvalue (this should never happen)").At(expression.Target).Build());
}
return new StructFieldAccessNode(expression.Tokens, field.Type, lValueTarget, expression.Member);
} }
default: default:
{ {
@@ -894,13 +874,7 @@ public sealed class TypeChecker
} }
} }
public enum VariableKind public record Variable(string Name, NubType Type);
{
LValue,
RValue
}
public record Variable(string Name, NubType Type, VariableKind Kind);
public class Scope(string module, Scope? parent = null) public class Scope(string module, Scope? parent = null)
{ {

View File

@@ -191,7 +191,7 @@ public class Generator
{ {
var target = EmitLValue(assignmentNode.Target); var target = EmitLValue(assignmentNode.Target);
var value = EmitExpression(assignmentNode.Value); var value = EmitExpression(assignmentNode.Value);
_builder.BuildStore(value, target); _builder.BuildStore(Unbox(value), target);
} }
private void EmitBreak(BreakNode breakNode) private void EmitBreak(BreakNode breakNode)
@@ -223,7 +223,7 @@ public class Generator
else else
{ {
var returnValue = EmitExpression(returnNode.Value); var returnValue = EmitExpression(returnNode.Value);
_builder.BuildRet(returnValue); _builder.BuildRet(Unbox(returnValue));
} }
} }
@@ -247,7 +247,7 @@ public class Generator
if (variableDeclarationNode.Assignment != null) if (variableDeclarationNode.Assignment != null)
{ {
var initValue = EmitExpression(variableDeclarationNode.Assignment); var initValue = EmitExpression(variableDeclarationNode.Assignment);
_builder.BuildStore(initValue, alloca); _builder.BuildStore(Unbox(initValue), alloca);
} }
_namedValues[variableDeclarationNode.Name] = alloca; _namedValues[variableDeclarationNode.Name] = alloca;
@@ -258,18 +258,17 @@ public class Generator
throw new NotImplementedException(); throw new NotImplementedException();
} }
private LLVMValueRef EmitExpression(ExpressionNode expressionNode) private Box EmitExpression(ExpressionNode expressionNode)
{ {
switch (expressionNode) switch (expressionNode)
{ {
case LValueExpressionNode lvalue: case LValueExpressionNode lvalue:
{ {
var value = EmitLValue(lvalue); return new Box(EmitLValue(lvalue), true);
return _builder.BuildLoad2(MapType(lvalue.Type), value);
} }
case RValueExpressionNode rvalue: case RValueExpressionNode rvalue:
{ {
return EmitRValue(rvalue); return new Box(EmitRValue(rvalue), false);
} }
default: default:
{ {
@@ -283,12 +282,12 @@ public class Generator
return lValueNode switch return lValueNode switch
{ {
ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode), ArrayIndexAccessNode arrayIndexAccessNode => EmitArrayIndexAccess(arrayIndexAccessNode),
ConstArrayIndexAccessNode constArrayIndexAccessNode => EmitConstArrayIndexAccess(constArrayIndexAccessNode), ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
DereferenceNode dereferenceNode => EmitDereference(dereferenceNode), DereferenceNode dereferenceNode => EmitDereference(dereferenceNode),
LValueIdentifierNode lValueIdentifierNode => EmitLValueIdentifier(lValueIdentifierNode),
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceIndexAccess(sliceIndexAccessNode), SliceIndexAccessNode sliceIndexAccessNode => EmitSliceIndexAccess(sliceIndexAccessNode),
StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode), StructFieldAccessNode structFieldAccessNode => EmitStructFieldAccess(structFieldAccessNode),
StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode), StructInitializerNode structInitializerNode => EmitStructInitializer(structInitializerNode),
VariableIdentifierNode variableIdentifierNode => _namedValues[variableIdentifierNode.Name],
_ => throw new ArgumentOutOfRangeException(nameof(lValueNode)) _ => throw new ArgumentOutOfRangeException(nameof(lValueNode))
}; };
} }
@@ -298,7 +297,6 @@ public class Generator
return rValueNode switch return rValueNode switch
{ {
AddressOfNode addressOfNode => EmitAddressOf(addressOfNode), AddressOfNode addressOfNode => EmitAddressOf(addressOfNode),
ArrayInitializerNode arrayInitializerNode => EmitArrayInitializer(arrayInitializerNode),
BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode), BinaryExpressionNode binaryExpressionNode => EmitBinaryExpression(binaryExpressionNode),
BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode), BoolLiteralNode boolLiteralNode => EmitBoolLiteral(boolLiteralNode),
ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode), ConvertFloatNode convertFloatNode => EmitConvertFloat(convertFloatNode),
@@ -310,7 +308,6 @@ public class Generator
FuncCallNode funcCallNode => EmitFuncCall(funcCallNode), FuncCallNode funcCallNode => EmitFuncCall(funcCallNode),
FuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(funcIdentifierNode), FuncIdentifierNode funcIdentifierNode => EmitFuncIdentifier(funcIdentifierNode),
IntLiteralNode intLiteralNode => EmitIntLiteral(intLiteralNode), IntLiteralNode intLiteralNode => EmitIntLiteral(intLiteralNode),
RValueIdentifierNode rValueIdentifierNode => EmitRValueIdentifier(rValueIdentifierNode),
SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode), SizeBuiltinNode sizeBuiltinNode => EmitSizeBuiltin(sizeBuiltinNode),
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode), StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
UIntLiteralNode uIntLiteralNode => EmitUIntLiteral(uIntLiteralNode), UIntLiteralNode uIntLiteralNode => EmitUIntLiteral(uIntLiteralNode),
@@ -327,13 +324,13 @@ public class Generator
var target = EmitExpression(arrayIndexAccessNode.Target); var target = EmitExpression(arrayIndexAccessNode.Target);
var index = EmitExpression(arrayIndexAccessNode.Index); var index = EmitExpression(arrayIndexAccessNode.Index);
return _builder.BuildGEP2(elementType, target, [index]); return _builder.BuildGEP2(elementType, Unbox(target), [Unbox(index)]);
} }
private LLVMValueRef EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode) private LLVMValueRef EmitArrayInitializer(ArrayInitializerNode arrayInitializerNode)
{ {
var capacity = EmitExpression(arrayInitializerNode.Capacity); var capacity = EmitExpression(arrayInitializerNode.Capacity);
return _builder.BuildArrayAlloca(MapType(arrayInitializerNode.ElementType), capacity); return _builder.BuildArrayAlloca(MapType(arrayInitializerNode.ElementType), Unbox(capacity));
} }
private LLVMValueRef EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode) private LLVMValueRef EmitBinaryExpression(BinaryExpressionNode binaryExpressionNode)
@@ -347,24 +344,24 @@ public class Generator
{ {
return binaryExpressionNode.Operator switch return binaryExpressionNode.Operator switch
{ {
BinaryOperator.Plus => _builder.BuildAdd(left, right), BinaryOperator.Plus => _builder.BuildAdd(Unbox(left), Unbox(right)),
BinaryOperator.Minus => _builder.BuildSub(left, right), BinaryOperator.Minus => _builder.BuildSub(Unbox(left), Unbox(right)),
BinaryOperator.Multiply => _builder.BuildMul(left, right), BinaryOperator.Multiply => _builder.BuildMul(Unbox(left), Unbox(right)),
BinaryOperator.Divide => _builder.BuildSDiv(left, right), BinaryOperator.Divide => _builder.BuildSDiv(Unbox(left), Unbox(right)),
BinaryOperator.Modulo => _builder.BuildSRem(left, right), BinaryOperator.Modulo => _builder.BuildSRem(Unbox(left), Unbox(right)),
BinaryOperator.Equal => _builder.BuildICmp(LLVMIntPredicate.LLVMIntEQ, left, right), BinaryOperator.Equal => _builder.BuildICmp(LLVMIntPredicate.LLVMIntEQ, Unbox(left), Unbox(right)),
BinaryOperator.NotEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntNE, left, right), BinaryOperator.NotEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntNE, Unbox(left), Unbox(right)),
BinaryOperator.LessThan => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSLT, left, right), BinaryOperator.LessThan => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSLT, Unbox(left), Unbox(right)),
BinaryOperator.LessThanOrEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSLE, left, right), BinaryOperator.LessThanOrEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSLE, Unbox(left), Unbox(right)),
BinaryOperator.GreaterThan => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSGT, left, right), BinaryOperator.GreaterThan => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSGT, Unbox(left), Unbox(right)),
BinaryOperator.GreaterThanOrEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSGE, left, right), BinaryOperator.GreaterThanOrEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntSGE, Unbox(left), Unbox(right)),
BinaryOperator.BitwiseAnd => _builder.BuildAnd(left, right), BinaryOperator.BitwiseAnd => _builder.BuildAnd(Unbox(left), Unbox(right)),
BinaryOperator.BitwiseOr => _builder.BuildOr(left, right), BinaryOperator.BitwiseOr => _builder.BuildOr(Unbox(left), Unbox(right)),
BinaryOperator.BitwiseXor => _builder.BuildXor(left, right), BinaryOperator.BitwiseXor => _builder.BuildXor(Unbox(left), Unbox(right)),
BinaryOperator.LeftShift => _builder.BuildShl(left, right), BinaryOperator.LeftShift => _builder.BuildShl(Unbox(left), Unbox(right)),
BinaryOperator.RightShift => _builder.BuildAShr(left, right), BinaryOperator.RightShift => _builder.BuildAShr(Unbox(left), Unbox(right)),
_ => throw new NotSupportedException($"Binary operator {binaryExpressionNode.Operator} not supported for int") _ => throw new NotSupportedException($"Binary operator {binaryExpressionNode.Operator} not supported for int")
}; };
@@ -374,18 +371,18 @@ public class Generator
{ {
return binaryExpressionNode.Operator switch return binaryExpressionNode.Operator switch
{ {
BinaryOperator.Plus => _builder.BuildFAdd(left, right), BinaryOperator.Plus => _builder.BuildFAdd(Unbox(left), Unbox(right)),
BinaryOperator.Minus => _builder.BuildFSub(left, right), BinaryOperator.Minus => _builder.BuildFSub(Unbox(left), Unbox(right)),
BinaryOperator.Multiply => _builder.BuildFMul(left, right), BinaryOperator.Multiply => _builder.BuildFMul(Unbox(left), Unbox(right)),
BinaryOperator.Divide => _builder.BuildFDiv(left, right), BinaryOperator.Divide => _builder.BuildFDiv(Unbox(left), Unbox(right)),
BinaryOperator.Modulo => _builder.BuildFRem(left, right), BinaryOperator.Modulo => _builder.BuildFRem(Unbox(left), Unbox(right)),
BinaryOperator.Equal => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOEQ, left, right), BinaryOperator.Equal => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOEQ, Unbox(left), Unbox(right)),
BinaryOperator.NotEqual => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealONE, left, right), BinaryOperator.NotEqual => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealONE, Unbox(left), Unbox(right)),
BinaryOperator.LessThan => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOLT, left, right), BinaryOperator.LessThan => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOLT, Unbox(left), Unbox(right)),
BinaryOperator.LessThanOrEqual => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOLE, left, right), BinaryOperator.LessThanOrEqual => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOLE, Unbox(left), Unbox(right)),
BinaryOperator.GreaterThan => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOGT, left, right), BinaryOperator.GreaterThan => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOGT, Unbox(left), Unbox(right)),
BinaryOperator.GreaterThanOrEqual => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOGE, left, right), BinaryOperator.GreaterThanOrEqual => _builder.BuildFCmp(LLVMRealPredicate.LLVMRealOGE, Unbox(left), Unbox(right)),
_ => throw new NotSupportedException($"Binary operator {binaryExpressionNode.Operator} not supported for float") _ => throw new NotSupportedException($"Binary operator {binaryExpressionNode.Operator} not supported for float")
}; };
@@ -395,10 +392,10 @@ public class Generator
{ {
return binaryExpressionNode.Operator switch return binaryExpressionNode.Operator switch
{ {
BinaryOperator.LogicalAnd => _builder.BuildAnd(left, right), BinaryOperator.LogicalAnd => _builder.BuildAnd(Unbox(left), Unbox(right)),
BinaryOperator.LogicalOr => _builder.BuildOr(left, right), BinaryOperator.LogicalOr => _builder.BuildOr(Unbox(left), Unbox(right)),
BinaryOperator.Equal => _builder.BuildICmp(LLVMIntPredicate.LLVMIntEQ, left, right), BinaryOperator.Equal => _builder.BuildICmp(LLVMIntPredicate.LLVMIntEQ, Unbox(left), Unbox(right)),
BinaryOperator.NotEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntNE, left, right), BinaryOperator.NotEqual => _builder.BuildICmp(LLVMIntPredicate.LLVMIntNE, Unbox(left), Unbox(right)),
_ => throw new NotSupportedException($"Binary operator {binaryExpressionNode.Operator} not supported for bool") _ => throw new NotSupportedException($"Binary operator {binaryExpressionNode.Operator} not supported for bool")
}; };
} }
@@ -411,16 +408,6 @@ public class Generator
return LLVMValueRef.CreateConstInt(LLVMTypeRef.Int1, boolLiteralNode.Value ? 1ul : 0ul); return LLVMValueRef.CreateConstInt(LLVMTypeRef.Int1, boolLiteralNode.Value ? 1ul : 0ul);
} }
private LLVMValueRef EmitConstArrayIndexAccess(ConstArrayIndexAccessNode constArrayIndexAccessNode)
{
var arrayType = (NubConstArrayType)constArrayIndexAccessNode.Target.Type;
var target = EmitExpression(constArrayIndexAccessNode.Target);
var index = EmitExpression(constArrayIndexAccessNode.Index);
return _builder.BuildGEP2(MapType(arrayType), target, [LLVMValueRef.CreateConstInt(LLVMTypeRef.Int64, 0), index]);
}
private LLVMValueRef EmitConvertFloat(ConvertFloatNode convertFloatNode) private LLVMValueRef EmitConvertFloat(ConvertFloatNode convertFloatNode)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -459,8 +446,8 @@ public class Generator
private LLVMValueRef EmitFuncCall(FuncCallNode funcCallNode) private LLVMValueRef EmitFuncCall(FuncCallNode funcCallNode)
{ {
var function = EmitExpression(funcCallNode.Expression); var function = EmitExpression(funcCallNode.Expression);
var args = funcCallNode.Parameters.Select(EmitExpression).ToArray(); var args = funcCallNode.Parameters.Select(x => Unbox(EmitExpression(x))).ToArray();
return _builder.BuildCall2(MapType(funcCallNode.Expression.Type), function, args); return _builder.BuildCall2(MapType(funcCallNode.Expression.Type), Unbox(function), args);
} }
private LLVMValueRef EmitFuncIdentifier(FuncIdentifierNode funcIdentifierNode) private LLVMValueRef EmitFuncIdentifier(FuncIdentifierNode funcIdentifierNode)
@@ -478,16 +465,6 @@ public class Generator
throw new NotImplementedException(); throw new NotImplementedException();
} }
private LLVMValueRef EmitLValueIdentifier(LValueIdentifierNode lValueIdentifierNode)
{
return _namedValues[lValueIdentifierNode.Name];
}
private LLVMValueRef EmitRValueIdentifier(RValueIdentifierNode rValueIdentifierNode)
{
return _builder.BuildLoad2(MapType(rValueIdentifierNode.Type), _namedValues[rValueIdentifierNode.Name], rValueIdentifierNode.Name);
}
private LLVMValueRef EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode) private LLVMValueRef EmitSizeBuiltin(SizeBuiltinNode sizeBuiltinNode)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
@@ -506,7 +483,7 @@ public class Generator
private LLVMValueRef EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode) private LLVMValueRef EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)
{ {
var type = (NubStructType)structFieldAccessNode.Target.Type; var type = (NubStructType)structFieldAccessNode.Target.Type;
var target = EmitLValue(structFieldAccessNode.Target); var target = EmitLValue((LValueExpressionNode)structFieldAccessNode.Target);
var fieldIndex = type.Fields.FindIndex(x => x.Name == structFieldAccessNode.Field); var fieldIndex = type.Fields.FindIndex(x => x.Name == structFieldAccessNode.Field);
return _builder.BuildStructGEP2(MapType(structFieldAccessNode.Target.Type), target, (uint)fieldIndex); return _builder.BuildStructGEP2(MapType(structFieldAccessNode.Target.Type), target, (uint)fieldIndex);
} }
@@ -522,7 +499,7 @@ public class Generator
var fieldIndex = structInitializerNode.StructType.Fields.FindIndex(x => x.Name == initializer.Key); var fieldIndex = structInitializerNode.StructType.Fields.FindIndex(x => x.Name == initializer.Key);
var fieldPtr = _builder.BuildStructGEP2(type, ptr, (uint)fieldIndex); var fieldPtr = _builder.BuildStructGEP2(type, ptr, (uint)fieldIndex);
_builder.BuildStore(value, fieldPtr); _builder.BuildStore(Unbox(value), fieldPtr);
} }
return ptr; return ptr;
@@ -538,10 +515,22 @@ public class Generator
var operand = EmitExpression(unaryExpressionNode.Operand); var operand = EmitExpression(unaryExpressionNode.Operand);
return unaryExpressionNode.Operator switch return unaryExpressionNode.Operator switch
{ {
UnaryOperator.Negate when unaryExpressionNode.Operand.Type is NubIntType => _builder.BuildNeg(operand), UnaryOperator.Negate when unaryExpressionNode.Operand.Type is NubIntType => _builder.BuildNeg(Unbox(operand)),
UnaryOperator.Negate when unaryExpressionNode.Operand.Type is NubFloatType => _builder.BuildFNeg(operand), UnaryOperator.Negate when unaryExpressionNode.Operand.Type is NubFloatType => _builder.BuildFNeg(Unbox(operand)),
UnaryOperator.Invert => _builder.BuildNot(operand), UnaryOperator.Invert => _builder.BuildNot(Unbox(operand)),
_ => throw new NotImplementedException($"Unary operator {unaryExpressionNode.Operator} not implemented") _ => throw new NotImplementedException($"Unary operator {unaryExpressionNode.Operator} not implemented")
}; };
} }
private LLVMValueRef Unbox(Box box)
{
if (box.LValue)
{
return _builder.BuildLoad2(box.Value.TypeOf, box.Value);
}
return box.Value;
}
private record Box(LLVMValueRef Value, bool LValue);
} }

View File

@@ -530,21 +530,12 @@ public sealed class Parser
return expr; return expr;
} }
private ExpressionSyntax ParseArrayInitializer(int startIndex) private ArrayInitializerSyntax ParseArrayInitializer(int startIndex)
{ {
if (TryExpectIntLiteral(out var intLiteral)) var capacity = ParseExpression();
{ ExpectSymbol(Symbol.CloseBracket);
ExpectSymbol(Symbol.CloseBracket); var type = ParseType();
var type = ParseType(); return new ArrayInitializerSyntax(GetTokens(startIndex), capacity, type);
return new ConstArrayInitializerSyntax(GetTokens(startIndex), Convert.ToInt64(intLiteral.Value, intLiteral.Base), type);
}
else
{
var capacity = ParseExpression();
ExpectSymbol(Symbol.CloseBracket);
var type = ParseType();
return new ArrayInitializerSyntax(GetTokens(startIndex), capacity, type);
}
} }
private StructInitializerSyntax ParseStructInitializer(int startIndex) private StructInitializerSyntax ParseStructInitializer(int startIndex)

View File

@@ -88,8 +88,6 @@ public record ModuleIdentifierSyntax(List<Token> Tokens, string Module, string N
public record ArrayInitializerSyntax(List<Token> Tokens, ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens); public record ArrayInitializerSyntax(List<Token> Tokens, ExpressionSyntax Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);
public record ConstArrayInitializerSyntax(List<Token> Tokens, long Capacity, TypeSyntax ElementType) : ExpressionSyntax(Tokens);
public record ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens); public record ArrayIndexAccessSyntax(List<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);
public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens); public record AddressOfSyntax(List<Token> Tokens, ExpressionSyntax Target) : ExpressionSyntax(Tokens);

View File

@@ -1,5 +1,6 @@
.build/out: main.nub .build/out: main.nub
nubc main.nub nubc main.nub
clang -o .build/out .build/main.ll
clean: clean:
@rm -r .build 2>/dev/null || true @rm -r .build 2>/dev/null || true