...
This commit is contained in:
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user