From df8557be8620cfa8c1827f60af23589b4ed732e9 Mon Sep 17 00:00:00 2001 From: nub31 Date: Sat, 17 May 2025 19:23:08 +0200 Subject: [PATCH] ... --- example/program.nub | 2 +- src/compiler/Nub.Lang/Backend/Generator.cs | 97 +++++++++--------- .../Frontend/Parsing/AddressOfNode.cs | 6 ++ .../Frontend/Parsing/DereferenceNode.cs | 6 ++ .../Nub.Lang/Frontend/Parsing/Parser.cs | 11 +-- .../Frontend/Parsing/UnaryExpressionNode.cs | 2 - .../Nub.Lang/Frontend/Typing/TypeChecker.cs | 98 +++++++++---------- 7 files changed, 107 insertions(+), 115 deletions(-) create mode 100644 src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs create mode 100644 src/compiler/Nub.Lang/Frontend/Parsing/DereferenceNode.cs diff --git a/example/program.nub b/example/program.nub index c3b2345..68a1406 100644 --- a/example/program.nub +++ b/example/program.nub @@ -11,5 +11,5 @@ global func main(argc: i64, argv: i64) { text = &text } - printf("%s\n", x.text^) + printf("%s\n", x.text) } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Backend/Generator.cs b/src/compiler/Nub.Lang/Backend/Generator.cs index 384bed5..c642581 100644 --- a/src/compiler/Nub.Lang/Backend/Generator.cs +++ b/src/compiler/Nub.Lang/Backend/Generator.cs @@ -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(); diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs new file mode 100644 index 0000000..2f02e3d --- /dev/null +++ b/src/compiler/Nub.Lang/Frontend/Parsing/AddressOfNode.cs @@ -0,0 +1,6 @@ +namespace Nub.Lang.Frontend.Parsing; + +public class AddressOfNode(ExpressionNode expression) : ExpressionNode +{ + public ExpressionNode Expression { get; } = expression; +} \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/DereferenceNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/DereferenceNode.cs new file mode 100644 index 0000000..4bb6097 --- /dev/null +++ b/src/compiler/Nub.Lang/Frontend/Parsing/DereferenceNode.cs @@ -0,0 +1,6 @@ +namespace Nub.Lang.Frontend.Parsing; + +public class DereferenceNode(ExpressionNode expression) : ExpressionNode +{ + public ExpressionNode Expression { get; } = expression; +} \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs b/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs index be4eed2..197a9b7 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs @@ -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); } diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/UnaryExpressionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/UnaryExpressionNode.cs index c0583a6..7a49d5e 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/UnaryExpressionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/UnaryExpressionNode.cs @@ -8,8 +8,6 @@ public class UnaryExpressionNode(UnaryExpressionOperator @operator, ExpressionNo public enum UnaryExpressionOperator { - AddressOf, - Dereference, Negate, Invert } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Typing/TypeChecker.cs b/src/compiler/Nub.Lang/Frontend/Typing/TypeChecker.cs index 107f613..2b18ce8 100644 --- a/src/compiler/Nub.Lang/Frontend/Typing/TypeChecker.cs +++ b/src/compiler/Nub.Lang/Frontend/Typing/TypeChecker.cs @@ -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().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) ||