This commit is contained in:
nub31
2025-05-17 19:23:08 +02:00
parent 007a4f03ac
commit df8557be86
7 changed files with 107 additions and 115 deletions

View File

@@ -11,5 +11,5 @@ global func main(argc: i64, argv: i64) {
text = &text text = &text
} }
printf("%s\n", x.text^) printf("%s\n", x.text)
} }

View File

@@ -508,26 +508,56 @@ public class Generator
private string GenerateExpression(ExpressionNode expression) private string GenerateExpression(ExpressionNode expression)
{ {
switch (expression) return expression switch
{ {
case BinaryExpressionNode binaryExpression: AddressOfNode addressOf => GenerateAddressOf(addressOf),
return GenerateBinaryExpression(binaryExpression); BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
case CastNode cast: CastNode cast => GenerateCast(cast),
return GenerateCast(cast); DereferenceNode dereference => GenerateDereference(dereference),
case FuncCallExpressionNode funcCallExpression: FuncCallExpressionNode funcCallExpression => GenerateExpressionFuncCall(funcCallExpression),
return GenerateExpressionFuncCall(funcCallExpression); IdentifierNode identifier => GenerateIdentifier(identifier),
case IdentifierNode identifier: LiteralNode literal => GenerateLiteral(literal),
return GenerateIdentifier(identifier); StructInitializerNode structInitializer => GenerateStructInitializer(structInitializer),
case LiteralNode literal: UnaryExpressionNode unaryExpression => GenerateUnaryExpression(unaryExpression),
return GenerateLiteral(literal); StructFieldAccessorNode structMemberAccessor => GenerateStructFieldAccessor(structMemberAccessor),
case StructInitializerNode structInitializer: _ => throw new ArgumentOutOfRangeException(nameof(expression))
return GenerateStructInitializer(structInitializer); };
case UnaryExpressionNode unaryExpression: }
return GenerateUnaryExpression(unaryExpression);
case StructFieldAccessorNode structMemberAccessor: private string GenerateDereference(DereferenceNode dereference)
return GenerateStructFieldAccessor(structMemberAccessor); {
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: default:
throw new ArgumentOutOfRangeException(nameof(expression)); throw new ArgumentOutOfRangeException();
} }
} }
@@ -1314,37 +1344,6 @@ public class Generator
break; 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: default:
{ {
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();

View File

@@ -0,0 +1,6 @@
namespace Nub.Lang.Frontend.Parsing;
public class AddressOfNode(ExpressionNode expression) : ExpressionNode
{
public ExpressionNode Expression { get; } = expression;
}

View File

@@ -0,0 +1,6 @@
namespace Nub.Lang.Frontend.Parsing;
public class DereferenceNode(ExpressionNode expression) : ExpressionNode
{
public ExpressionNode Expression { get; } = expression;
}

View File

@@ -362,7 +362,7 @@ public class Parser
case Symbol.Ampersand: case Symbol.Ampersand:
{ {
var expression = ParsePrimaryExpression(); var expression = ParsePrimaryExpression();
return new UnaryExpressionNode(UnaryExpressionOperator.AddressOf, expression); return new AddressOfNode(expression);
} }
case Symbol.Minus: case Symbol.Minus:
{ {
@@ -408,10 +408,6 @@ public class Parser
{ {
var field = ExpectIdentifier(); var field = ExpectIdentifier();
result = new StructFieldAccessorNode(result, field.Value); result = new StructFieldAccessorNode(result, field.Value);
if (TryExpectSymbol(Symbol.Caret))
{
result = new UnaryExpressionNode(UnaryExpressionOperator.Dereference, result);
}
} while (TryExpectSymbol(Symbol.Period)); } while (TryExpectSymbol(Symbol.Period));
return result; 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); return new IdentifierNode(identifier.Value);
} }

View File

@@ -8,8 +8,6 @@ public class UnaryExpressionNode(UnaryExpressionOperator @operator, ExpressionNo
public enum UnaryExpressionOperator public enum UnaryExpressionOperator
{ {
AddressOf,
Dereference,
Negate, Negate,
Invert Invert
} }

View File

@@ -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) private NubType TypeCheckFuncCall(FuncCall funcCall)
{ {
var localFuncDef = _definitions.OfType<LocalFuncDefinitionNode>().FirstOrDefault(f => f.Name == funcCall.Name); var localFuncDef = _definitions.OfType<LocalFuncDefinitionNode>().FirstOrDefault(f => f.Name == funcCall.Name);
@@ -239,47 +250,46 @@ public class TypeChecker
private NubType TypeCheckExpression(ExpressionNode expression) private NubType TypeCheckExpression(ExpressionNode expression)
{ {
NubType resultType; var resultType = expression switch
switch (expression)
{ {
case LiteralNode literal: AddressOfNode addressOf => TypeCheckAddressOf(addressOf),
resultType = literal.LiteralType; LiteralNode literal => literal.LiteralType,
break; IdentifierNode identifier => TypeCheckIdentifier(identifier),
case IdentifierNode identifier: BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
if (!_variables.TryGetValue(identifier.Identifier, out var varType)) CastNode cast => TypeCheckCast(cast),
{ DereferenceNode dereference => TypeCheckDereference(dereference),
throw new TypeCheckingException($"Variable '{identifier.Identifier}' is not defined"); FuncCallExpressionNode funcCallExpr => TypeCheckFuncCall(funcCallExpr.FuncCall),
} StructInitializerNode structInit => TypeCheckStructInitializer(structInit),
UnaryExpressionNode unaryExpression => TypeCheckUnaryExpression(unaryExpression),
resultType = varType; StructFieldAccessorNode fieldAccess => TypeCheckStructFieldAccess(fieldAccess),
break; _ => throw new TypeCheckingException($"Unsupported expression type: {expression.GetType().Name}")
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}");
}
expression.Type = resultType; expression.Type = resultType;
return 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) private NubType TypeCheckBinaryExpression(BinaryExpressionNode binaryExpr)
{ {
var leftType = TypeCheckExpression(binaryExpr.Left); var leftType = TypeCheckExpression(binaryExpr.Left);
@@ -382,24 +392,6 @@ public class TypeChecker
switch (unaryExpression.Operator) 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: case UnaryExpressionOperator.Negate:
{ {
if (operandType.Equals(NubPrimitiveType.I8) || if (operandType.Equals(NubPrimitiveType.I8) ||