...
This commit is contained in:
@@ -11,5 +11,5 @@ global func main(argc: i64, argv: i64) {
|
||||
text = &text
|
||||
}
|
||||
|
||||
printf("%s\n", x.text^)
|
||||
printf("%s\n", x.text)
|
||||
}
|
||||
@@ -508,26 +508,56 @@ public class Generator
|
||||
|
||||
private string GenerateExpression(ExpressionNode expression)
|
||||
{
|
||||
switch (expression)
|
||||
return expression switch
|
||||
{
|
||||
case BinaryExpressionNode binaryExpression:
|
||||
return GenerateBinaryExpression(binaryExpression);
|
||||
case CastNode cast:
|
||||
return GenerateCast(cast);
|
||||
case FuncCallExpressionNode funcCallExpression:
|
||||
return GenerateExpressionFuncCall(funcCallExpression);
|
||||
case IdentifierNode identifier:
|
||||
return GenerateIdentifier(identifier);
|
||||
case LiteralNode literal:
|
||||
return GenerateLiteral(literal);
|
||||
case StructInitializerNode structInitializer:
|
||||
return GenerateStructInitializer(structInitializer);
|
||||
case UnaryExpressionNode unaryExpression:
|
||||
return GenerateUnaryExpression(unaryExpression);
|
||||
case StructFieldAccessorNode structMemberAccessor:
|
||||
return GenerateStructFieldAccessor(structMemberAccessor);
|
||||
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
||||
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
||||
CastNode cast => GenerateCast(cast),
|
||||
DereferenceNode dereference => GenerateDereference(dereference),
|
||||
FuncCallExpressionNode funcCallExpression => GenerateExpressionFuncCall(funcCallExpression),
|
||||
IdentifierNode identifier => GenerateIdentifier(identifier),
|
||||
LiteralNode literal => GenerateLiteral(literal),
|
||||
StructInitializerNode structInitializer => GenerateStructInitializer(structInitializer),
|
||||
UnaryExpressionNode unaryExpression => GenerateUnaryExpression(unaryExpression),
|
||||
StructFieldAccessorNode structMemberAccessor => GenerateStructFieldAccessor(structMemberAccessor),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||
};
|
||||
}
|
||||
|
||||
private string GenerateDereference(DereferenceNode dereference)
|
||||
{
|
||||
var result = GenerateExpression(dereference.Expression);
|
||||
var outputLabel = GenName();
|
||||
_builder.AppendLine($" %{outputLabel} ={SQT(dereference.Type)} load{SQT(dereference.Type)} {result}");
|
||||
return $"%{outputLabel}";
|
||||
}
|
||||
|
||||
private string GenerateAddressOf(AddressOfNode addressOf)
|
||||
{
|
||||
var result = GenerateExpression(addressOf.Expression);
|
||||
var outputLabel = GenName();
|
||||
switch (addressOf.Expression.Type)
|
||||
{
|
||||
case NubPointerType:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.String }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U64 }:
|
||||
_builder.AppendLine($" %{outputLabel} =l alloc8 8");
|
||||
_builder.AppendLine($" storel {result}, %{outputLabel}");
|
||||
return $"%{outputLabel}";
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U32 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I16 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U16 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I8 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U8 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
|
||||
_builder.AppendLine($" %{outputLabel} =l alloc8 4");
|
||||
_builder.AppendLine($" storew {result}, %{outputLabel}");
|
||||
return $"%{outputLabel}";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(expression));
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1314,37 +1344,6 @@ public class Generator
|
||||
|
||||
break;
|
||||
}
|
||||
case UnaryExpressionOperator.AddressOf:
|
||||
{
|
||||
switch (unaryExpression.Operand.Type)
|
||||
{
|
||||
case NubPointerType:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.String }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U64 }:
|
||||
_builder.AppendLine($" %{outputLabel} =l alloc8 8");
|
||||
_builder.AppendLine($" storel {operand}, %{outputLabel}");
|
||||
return $"%{outputLabel}";
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U32 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I16 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U16 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.I8 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.U8 }:
|
||||
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
|
||||
_builder.AppendLine($" %{outputLabel} =l alloc8 4");
|
||||
_builder.AppendLine($" storew {operand}, %{outputLabel}");
|
||||
return $"%{outputLabel}";
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
case UnaryExpressionOperator.Dereference:
|
||||
{
|
||||
_builder.AppendLine($" %{outputLabel} ={SQT(unaryExpression.Type)} load{SQT(unaryExpression.Type)} {operand}");
|
||||
return $"%{outputLabel}";
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
6
src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs
Normal file
6
src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Nub.Lang.Frontend.Parsing;
|
||||
|
||||
public class AddressOfNode(ExpressionNode expression) : ExpressionNode
|
||||
{
|
||||
public ExpressionNode Expression { get; } = expression;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Nub.Lang.Frontend.Parsing;
|
||||
|
||||
public class DereferenceNode(ExpressionNode expression) : ExpressionNode
|
||||
{
|
||||
public ExpressionNode Expression { get; } = expression;
|
||||
}
|
||||
@@ -362,7 +362,7 @@ public class Parser
|
||||
case Symbol.Ampersand:
|
||||
{
|
||||
var expression = ParsePrimaryExpression();
|
||||
return new UnaryExpressionNode(UnaryExpressionOperator.AddressOf, expression);
|
||||
return new AddressOfNode(expression);
|
||||
}
|
||||
case Symbol.Minus:
|
||||
{
|
||||
@@ -408,10 +408,6 @@ public class Parser
|
||||
{
|
||||
var field = ExpectIdentifier();
|
||||
result = new StructFieldAccessorNode(result, field.Value);
|
||||
if (TryExpectSymbol(Symbol.Caret))
|
||||
{
|
||||
result = new UnaryExpressionNode(UnaryExpressionOperator.Dereference, result);
|
||||
}
|
||||
} while (TryExpectSymbol(Symbol.Period));
|
||||
|
||||
return result;
|
||||
@@ -434,11 +430,6 @@ public class Parser
|
||||
}
|
||||
}
|
||||
|
||||
if (TryExpectSymbol(Symbol.Caret))
|
||||
{
|
||||
return new UnaryExpressionNode(UnaryExpressionOperator.Dereference, new IdentifierNode(identifier.Value));
|
||||
}
|
||||
|
||||
return new IdentifierNode(identifier.Value);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@ public class UnaryExpressionNode(UnaryExpressionOperator @operator, ExpressionNo
|
||||
|
||||
public enum UnaryExpressionOperator
|
||||
{
|
||||
AddressOf,
|
||||
Dereference,
|
||||
Negate,
|
||||
Invert
|
||||
}
|
||||
@@ -130,6 +130,17 @@ public class TypeChecker
|
||||
}
|
||||
}
|
||||
|
||||
private NubType TypeCheckDereference(DereferenceNode dereference)
|
||||
{
|
||||
TypeCheckExpression(dereference.Expression);
|
||||
if (dereference.Expression.Type is not NubPointerType nubPointerType)
|
||||
{
|
||||
throw new TypeCheckingException($"Cannot dereference a non-pointer type {dereference.Expression.Type}");
|
||||
}
|
||||
|
||||
return nubPointerType.BaseType;
|
||||
}
|
||||
|
||||
private NubType TypeCheckFuncCall(FuncCall funcCall)
|
||||
{
|
||||
var localFuncDef = _definitions.OfType<LocalFuncDefinitionNode>().FirstOrDefault(f => f.Name == funcCall.Name);
|
||||
@@ -239,47 +250,46 @@ public class TypeChecker
|
||||
|
||||
private NubType TypeCheckExpression(ExpressionNode expression)
|
||||
{
|
||||
NubType resultType;
|
||||
|
||||
switch (expression)
|
||||
var resultType = expression switch
|
||||
{
|
||||
case LiteralNode literal:
|
||||
resultType = literal.LiteralType;
|
||||
break;
|
||||
case IdentifierNode identifier:
|
||||
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
||||
{
|
||||
throw new TypeCheckingException($"Variable '{identifier.Identifier}' is not defined");
|
||||
}
|
||||
|
||||
resultType = varType;
|
||||
break;
|
||||
case BinaryExpressionNode binaryExpr:
|
||||
resultType = TypeCheckBinaryExpression(binaryExpr);
|
||||
break;
|
||||
case CastNode cast:
|
||||
resultType = TypeCheckCast(cast);
|
||||
break;
|
||||
case FuncCallExpressionNode funcCallExpr:
|
||||
resultType = TypeCheckFuncCall(funcCallExpr.FuncCall);
|
||||
break;
|
||||
case StructInitializerNode structInit:
|
||||
resultType = TypeCheckStructInitializer(structInit);
|
||||
break;
|
||||
case UnaryExpressionNode unaryExpression:
|
||||
resultType = TypeCheckUnaryExpression(unaryExpression);
|
||||
break;
|
||||
case StructFieldAccessorNode fieldAccess:
|
||||
resultType = TypeCheckStructFieldAccess(fieldAccess);
|
||||
break;
|
||||
default:
|
||||
throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}");
|
||||
}
|
||||
AddressOfNode addressOf => TypeCheckAddressOf(addressOf),
|
||||
LiteralNode literal => literal.LiteralType,
|
||||
IdentifierNode identifier => TypeCheckIdentifier(identifier),
|
||||
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
|
||||
CastNode cast => TypeCheckCast(cast),
|
||||
DereferenceNode dereference => TypeCheckDereference(dereference),
|
||||
FuncCallExpressionNode funcCallExpr => TypeCheckFuncCall(funcCallExpr.FuncCall),
|
||||
StructInitializerNode structInit => TypeCheckStructInitializer(structInit),
|
||||
UnaryExpressionNode unaryExpression => TypeCheckUnaryExpression(unaryExpression),
|
||||
StructFieldAccessorNode fieldAccess => TypeCheckStructFieldAccess(fieldAccess),
|
||||
_ => throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}")
|
||||
};
|
||||
|
||||
expression.Type = resultType;
|
||||
return resultType;
|
||||
}
|
||||
|
||||
private NubType TypeCheckIdentifier(IdentifierNode identifier)
|
||||
{
|
||||
if (!_variables.TryGetValue(identifier.Identifier, out var varType))
|
||||
{
|
||||
throw new TypeCheckingException($"Variable '{identifier.Identifier}' is not defined");
|
||||
}
|
||||
|
||||
return varType;
|
||||
}
|
||||
|
||||
private NubType TypeCheckAddressOf(AddressOfNode addressOf)
|
||||
{
|
||||
TypeCheckExpression(addressOf.Expression);
|
||||
if (addressOf.Expression is not (IdentifierNode or StructFieldAccessorNode))
|
||||
{
|
||||
throw new TypeCheckingException($"Cannot take the address of {addressOf.Expression.Type}");
|
||||
}
|
||||
|
||||
return new NubPointerType(addressOf.Expression.Type);
|
||||
}
|
||||
|
||||
private NubType TypeCheckBinaryExpression(BinaryExpressionNode binaryExpr)
|
||||
{
|
||||
var leftType = TypeCheckExpression(binaryExpr.Left);
|
||||
@@ -382,24 +392,6 @@ public class TypeChecker
|
||||
|
||||
switch (unaryExpression.Operator)
|
||||
{
|
||||
case UnaryExpressionOperator.AddressOf:
|
||||
{
|
||||
if (unaryExpression.Operand is not (IdentifierNode or StructFieldAccessorNode))
|
||||
{
|
||||
throw new TypeCheckingException($"Cannot take the address of {unaryExpression.Operand.GetType().Name}");
|
||||
}
|
||||
|
||||
return new NubPointerType(operandType);
|
||||
}
|
||||
case UnaryExpressionOperator.Dereference:
|
||||
{
|
||||
if (operandType is not NubPointerType nubPointerType)
|
||||
{
|
||||
throw new TypeCheckingException($"Cannot dereference a non-pointer type {operandType}");
|
||||
}
|
||||
|
||||
return nubPointerType.BaseType;
|
||||
}
|
||||
case UnaryExpressionOperator.Negate:
|
||||
{
|
||||
if (operandType.Equals(NubPrimitiveType.I8) ||
|
||||
|
||||
Reference in New Issue
Block a user