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
}
printf("%s\n", x.text^)
printf("%s\n", x.text)
}

View File

@@ -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();

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:
{
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);
}

View File

@@ -8,8 +8,6 @@ public class UnaryExpressionNode(UnaryExpressionOperator @operator, ExpressionNo
public enum UnaryExpressionOperator
{
AddressOf,
Dereference,
Negate,
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)
{
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) ||