From bdf82f99e758cac1e8a8497d19c5c3517954bd9c Mon Sep 17 00:00:00 2001 From: nub31 Date: Mon, 5 May 2025 22:55:15 +0200 Subject: [PATCH] ... --- example/program.nub | 20 +++--- src/compiler/Nub.Lang/Backend/Generator.cs | 71 ++++++++++++++++--- .../Frontend/Parsing/StructDefinitionNode.cs | 4 +- .../Parsing/StructMemberAccessorNode.cs | 4 +- .../Frontend/Typing/ExpressionTyper.cs | 20 +++--- 5 files changed, 85 insertions(+), 34 deletions(-) diff --git a/example/program.nub b/example/program.nub index 927fca6..2a0f552 100644 --- a/example/program.nub +++ b/example/program.nub @@ -1,12 +1,14 @@ import "c"; -global func main() { - let x = true; - while x { - if (true) { - puts("level 1"); - } - puts("level 2"); - break; - } +struct Human { + age: int64; + name: string; } + +global func main() { + printName(); +} + +func printName(human: Human) { + puts(human.name); +} \ 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 4786246..654f50b 100644 --- a/src/compiler/Nub.Lang/Backend/Generator.cs +++ b/src/compiler/Nub.Lang/Backend/Generator.cs @@ -8,7 +8,7 @@ public class Generator private readonly List _definitions; private readonly StringBuilder _builder = new(); private readonly Dictionary _prefixIndexes = new(); - private readonly Dictionary _variables = new(); + private readonly Dictionary _variables = new(); private readonly List _strings = []; private readonly Stack _breakLabels = new(); private readonly Stack _continueLabels = new(); @@ -21,9 +21,16 @@ public class Generator public string Generate() { + foreach (var structDefinition in _definitions.OfType()) + { + GenerateStructDefinition(structDefinition); + _builder.AppendLine(); + } + foreach (var funcDefinition in _definitions.OfType()) { GenerateFuncDefinition(funcDefinition); + _builder.AppendLine(); } for (var i = 0; i < _strings.Count; i++) @@ -47,13 +54,22 @@ public class Generator return "w"; } - throw new Exception($"Invalid qbe type {type}"); + return $":{type.Name}"; } private void GenerateFuncDefinition(LocalFuncDefinitionNode node) { _variables.Clear(); - var parameters = node.Parameters.Select(p => $"{QbeTypeName(p.Type)} %{p.Name}"); + + foreach (var parameter in node.Parameters) + { + _variables.Add(parameter.Name, new Variable + { + Identifier = $"%{parameter.Name}", + Type = parameter.Type + }); + } + if (node.Global) { _builder.Append("export "); @@ -68,7 +84,7 @@ public class Generator _builder.Append('$'); _builder.Append(node.Name); - _builder.AppendLine($"({string.Join(", ", parameters)}) {{"); + _builder.AppendLine($"({string.Join(", ", node.Parameters.Select(p => $"{QbeTypeName(p.Type)} %{p.Name}"))}) {{"); _builder.AppendLine("@start"); GenerateBlock(node.Body); if (!node.ReturnType.HasValue) @@ -79,6 +95,12 @@ public class Generator _builder.AppendLine("}"); } + private void GenerateStructDefinition(StructDefinitionNode structDefinition) + { + var fields = structDefinition.Fields.Select(f => QbeTypeName(f.Type)); + _builder.AppendLine($"type :{structDefinition.Name} = {{ {string.Join(", ", fields)} }}"); + } + private void GenerateBlock(BlockNode block) { foreach (var statement in block.Statements.Where(_ => _codeIsReachable)) @@ -167,6 +189,7 @@ public class Generator GenerateBlock ); } + _builder.AppendLine($"@{endLabel}"); } @@ -185,12 +208,22 @@ public class Generator private void GenerateVariableAssignment(VariableAssignmentNode variableAssignment) { - _variables[variableAssignment.Name] = GenerateExpression(variableAssignment.Value); + var result = GenerateExpression(variableAssignment.Value); + _variables[variableAssignment.Name] = new Variable + { + Identifier = result, + Type = variableAssignment.Value.Type + }; } private void GenerateVariableReassignment(VariableReassignmentNode variableReassignment) { - _variables[variableReassignment.Name] = GenerateExpression(variableReassignment.Value); + var result = GenerateExpression(variableReassignment.Value); + _variables[variableReassignment.Name] = new Variable + { + Identifier = result, + Type = variableReassignment.Value.Type + }; } private void GenerateWhile(WhileNode whileStatement) @@ -198,7 +231,7 @@ public class Generator var conditionLabel = GenName("loop_condition"); var iterationLabel = GenName("loop_iteration"); var endLabel = GenName("loop_end"); - + _breakLabels.Push(endLabel); _continueLabels.Push(conditionLabel); @@ -209,7 +242,7 @@ public class Generator var result = GenerateExpression(whileStatement.Condition); _builder.AppendLine($" jnz {result}, @{iterationLabel}, @{endLabel}"); _builder.AppendLine($"@{endLabel}"); - + _continueLabels.Pop(); _breakLabels.Pop(); } @@ -237,7 +270,16 @@ public class Generator private string GenerateStructMemberAccessor(StructMemberAccessorNode structMemberAccessor) { - throw new NotImplementedException(); + var type = _variables.First(x => x.Key == structMemberAccessor.Fields[0]).Value.Type; + var def = _definitions.OfType().FirstOrDefault(s => s.Name == type.Name); + if (def == null) + { + throw new Exception("def is null"); + } + + throw new NotImplementedException("Not finished yet"); + + return $"load{QbeTypeName(structMemberAccessor.Type)} "; } private string GenerateBinaryExpression(BinaryExpressionNode binaryExpression) @@ -247,7 +289,7 @@ public class Generator private string GenerateIdentifier(IdentifierNode identifier) { - return _variables[identifier.Identifier]; + return _variables[identifier.Identifier].Identifier; } private string GenerateLiteral(LiteralNode literal) @@ -300,4 +342,11 @@ public class Generator _prefixIndexes[prefix] = index + 1; return $"{prefix}_{index}"; } -} \ No newline at end of file + + private class Variable + { + public required string Identifier { get; init; } + public required NubType Type { get; init; } + } +} + diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/StructDefinitionNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/StructDefinitionNode.cs index cb7fd0a..dca6eab 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/StructDefinitionNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/StructDefinitionNode.cs @@ -1,7 +1,7 @@ namespace Nub.Lang.Frontend.Parsing; -public class StructDefinitionNode(string name, List members) : DefinitionNode +public class StructDefinitionNode(string name, List fields) : DefinitionNode { public string Name { get; } = name; - public List Members { get; } = members; + public List Fields { get; } = fields; } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Parsing/StructMemberAccessorNode.cs b/src/compiler/Nub.Lang/Frontend/Parsing/StructMemberAccessorNode.cs index a265b62..b06eb72 100644 --- a/src/compiler/Nub.Lang/Frontend/Parsing/StructMemberAccessorNode.cs +++ b/src/compiler/Nub.Lang/Frontend/Parsing/StructMemberAccessorNode.cs @@ -1,6 +1,6 @@ namespace Nub.Lang.Frontend.Parsing; -public class StructMemberAccessorNode(List members) : ExpressionNode +public class StructMemberAccessorNode(List fields) : ExpressionNode { - public List Members { get; } = members; + public List Fields { get; } = fields; } \ No newline at end of file diff --git a/src/compiler/Nub.Lang/Frontend/Typing/ExpressionTyper.cs b/src/compiler/Nub.Lang/Frontend/Typing/ExpressionTyper.cs index adc73c2..fd358a0 100644 --- a/src/compiler/Nub.Lang/Frontend/Typing/ExpressionTyper.cs +++ b/src/compiler/Nub.Lang/Frontend/Typing/ExpressionTyper.cs @@ -43,7 +43,7 @@ public class ExpressionTyper foreach (var @class in _structDefinitions) { - foreach (var variable in @class.Members) + foreach (var variable in @class.Fields) { if (variable.Value.HasValue) { @@ -265,37 +265,37 @@ public class ExpressionTyper // TODO: Fix this ugly ass code private void GenerateStructMemberAccessorNode(StructMemberAccessorNode structMemberAccessor) { - var variable = _variables.FirstOrDefault(v => v.Name == structMemberAccessor.Members[0]); + var variable = _variables.FirstOrDefault(v => v.Name == structMemberAccessor.Fields[0]); if (variable == null) { - throw new Exception($"Variable {structMemberAccessor.Members[0]} is not defined"); + throw new Exception($"Variable {structMemberAccessor.Fields[0]} is not defined"); } var definition = _structDefinitions.FirstOrDefault(sd => sd.Name == variable.Type.Name); if (definition == null) { - throw new Exception($"Struct {structMemberAccessor.Members[0]} is not defined"); + throw new Exception($"Struct {structMemberAccessor.Fields[0]} is not defined"); } - for (var i = 1; i < structMemberAccessor.Members.Count - 1; i++) + for (var i = 1; i < structMemberAccessor.Fields.Count - 1; i++) { - var member = definition.Members.FirstOrDefault(m => m.Name == structMemberAccessor.Members[i]); + var member = definition.Fields.FirstOrDefault(m => m.Name == structMemberAccessor.Fields[i]); if (member == null) { - throw new Exception($"Member {structMemberAccessor.Members[i]} does not exist on struct {definition.Name}"); + throw new Exception($"Member {structMemberAccessor.Fields[i]} does not exist on struct {definition.Name}"); } definition = _structDefinitions.FirstOrDefault(sd => sd.Name == member.Type.Name); if (definition == null) { - throw new Exception($"Struct {structMemberAccessor.Members[i]} is not defined"); + throw new Exception($"Struct {structMemberAccessor.Fields[i]} is not defined"); } } - var tmp = definition.Members.FirstOrDefault(m => m.Name == structMemberAccessor.Members.Last()); + var tmp = definition.Fields.FirstOrDefault(m => m.Name == structMemberAccessor.Fields.Last()); if (tmp == null) { - throw new Exception($"Member {structMemberAccessor.Members.Last()} does not exist on struct {definition.Name}"); + throw new Exception($"Member {structMemberAccessor.Fields.Last()} does not exist on struct {definition.Name}"); } structMemberAccessor.Type = tmp.Type;