From 1cc8d30ee36d90795d1227951c79bbd3e15af792 Mon Sep 17 00:00:00 2001 From: nub31 Date: Sat, 17 May 2025 18:51:51 +0200 Subject: [PATCH] ... --- example/program.nub | 13 ++++- src/compiler/Nub.Lang/Backend/Generator.cs | 56 +++++++++++-------- .../Nub.Lang/Frontend/Parsing/Parser.cs | 18 ++++-- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/example/program.nub b/example/program.nub index 2198745..c3b2345 100644 --- a/example/program.nub +++ b/example/program.nub @@ -1,6 +1,15 @@ import c +struct Test { + text: ^string +} + global func main(argc: i64, argv: i64) { - x = "TEST" - printf("%s\n", ^&x) + text = "test" + + x = new Test { + text = &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 d5fe8c0..384bed5 100644 --- a/src/compiler/Nub.Lang/Backend/Generator.cs +++ b/src/compiler/Nub.Lang/Backend/Generator.cs @@ -220,6 +220,10 @@ public class Generator return definition.Fields.Sum(f => QbeTypeSize(f.Type)); } + case NubPointerType: + { + return 8; + } default: { throw new NotImplementedException(); @@ -254,6 +258,8 @@ public class Generator _builder.AppendLine($"({string.Join(", ", parameterStrings)}) {{"); _builder.AppendLine("@start"); + _builder.AppendLine(" # Variable allocation"); + foreach (var parameter in node.Parameters) { var parameterName = parameter.Name; @@ -278,23 +284,35 @@ public class Generator break; } - _variables.Add(parameter.Name, new Variable + var pointerLabel = GenName(); + _builder.AppendLine($" %{pointerLabel} ={SQT(parameter.Type)} alloc8 {QbeTypeSize(parameter.Type)}"); + _builder.AppendLine($" storel %{parameterName}, %{pointerLabel}"); + + + _variables[parameter.Name] = new Variable { - Identifier = $"%{parameterName}", + Pointer = $"%{pointerLabel}", Type = parameter.Type - }); + }; } + _builder.AppendLine(" # End variable allocation"); + _builder.AppendLine(); + GenerateBlock(node.Body); if (node.Body.Statements.Last() is not ReturnNode) { if (!node.ReturnType.HasValue && node.Name == "main") { + _builder.AppendLine(); + _builder.AppendLine(" # Implicit return for main"); _builder.AppendLine(" ret 0"); } else if (!node.ReturnType.HasValue) { + _builder.AppendLine(); + _builder.AppendLine(" # Implicit return"); _builder.AppendLine(" ret"); } } @@ -456,9 +474,13 @@ public class Generator private void GenerateVariableAssignment(VariableAssignmentNode variableAssignment) { var result = GenerateExpression(variableAssignment.Value); + var pointerLabel = GenName(); + _builder.AppendLine($" %{pointerLabel} ={SQT(variableAssignment.Value.Type)} alloc8 {QbeTypeSize(variableAssignment.Value.Type)}"); + _builder.AppendLine($" storel {result}, %{pointerLabel}"); + _variables[variableAssignment.Name] = new Variable { - Identifier = result, + Pointer = $"%{pointerLabel}", Type = variableAssignment.Value.Type }; } @@ -1180,7 +1202,10 @@ public class Generator private string GenerateIdentifier(IdentifierNode identifier) { - return _variables[identifier.Identifier].Identifier; + var variable = _variables[identifier.Identifier]; + var outputLabel = GenName(); + _builder.AppendLine($" %{outputLabel} ={SQT(identifier.Type)} load{SQT(identifier.Type)} {variable.Pointer}"); + return $"%{outputLabel}"; } private string GenerateLiteral(LiteralNode literal) @@ -1317,23 +1342,8 @@ public class Generator } case UnaryExpressionOperator.Dereference: { - // Handle dereference operator (assuming operand is a pointer) - // This would load the value from the address stored in the operand - if (unaryExpression.Type is NubPrimitiveType primitiveType) - { - _builder.AppendLine($" %{outputLabel} ={SQT(primitiveType)} load{SQT(primitiveType)} {operand}"); - return $"%{outputLabel}"; - } - - if (unaryExpression.Type is NubStructType structType) - { - // For struct types, we'd need to handle differently - // This is a simplified version - _builder.AppendLine($" %{outputLabel} =l copy {operand}"); - return $"%{outputLabel}"; - } - - break; + _builder.AppendLine($" %{outputLabel} ={SQT(unaryExpression.Type)} load{SQT(unaryExpression.Type)} {operand}"); + return $"%{outputLabel}"; } default: { @@ -1397,7 +1407,7 @@ public class Generator private class Variable { - public required string Identifier { get; init; } + public required string Pointer { get; init; } public required NubType Type { get; init; } } } \ 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 c4d4bf4..be4eed2 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/Parser.cs @@ -359,11 +359,6 @@ public class Parser return new StructInitializerNode(type, initializers); } - case Symbol.Caret: - { - var expression = ParsePrimaryExpression(); - return new UnaryExpressionNode(UnaryExpressionOperator.Dereference, expression); - } case Symbol.Ampersand: { var expression = ParsePrimaryExpression(); @@ -413,6 +408,10 @@ 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; @@ -435,6 +434,11 @@ public class Parser } } + if (TryExpectSymbol(Symbol.Caret)) + { + return new UnaryExpressionNode(UnaryExpressionOperator.Dereference, new IdentifierNode(identifier.Value)); + } + return new IdentifierNode(identifier.Value); } @@ -452,8 +456,10 @@ public class Parser private NubType ParseType() { + var pointer = TryExpectSymbol(Symbol.Caret); var name = ExpectIdentifier().Value; - return NubType.Parse(name); + var type = NubType.Parse(name); + return pointer ? new NubPointerType(type) : type; } private Token ExpectToken()