From 8a50278f0fe0a279a3e24381406ae7fd8a0444e9 Mon Sep 17 00:00:00 2001 From: nub31 Date: Thu, 30 Jan 2025 13:37:38 +0100 Subject: [PATCH] while loops working --- Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs | 18 ++++++++++- Nub.Lang/Nub.Lang/Frontend/Lexing/Lexer.cs | 3 +- .../Nub.Lang/Frontend/Lexing/SymbolToken.cs | 1 + Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs | 32 ++++++++----------- .../Nub.Lang/Frontend/Parsing/WhileNode.cs | 7 ++++ .../Frontend/Typing/ExpressionTyper.cs | 9 ++++++ input/program.nub | 20 +++--------- 7 files changed, 54 insertions(+), 36 deletions(-) create mode 100644 Nub.Lang/Nub.Lang/Frontend/Parsing/WhileNode.cs diff --git a/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs b/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs index 0f45b5c..668fdbb 100644 --- a/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs +++ b/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs @@ -222,6 +222,9 @@ public class Generator case VariableReassignmentNode variableReassignment: GenerateVariableReassignment(variableReassignment, func); break; + case WhileNode whileStatement: + GenerateWhile(whileStatement, func); + break; default: throw new ArgumentOutOfRangeException(nameof(statement)); } @@ -278,6 +281,19 @@ public class Generator _builder.AppendLine($" mov [rbp - {variable.Offset}], rax"); } + private void GenerateWhile(WhileNode whileStatement, LocalFunc func) + { + var startLabel = _labelFactory.Create(); + var endLabel = _labelFactory.Create(); + _builder.AppendLine($"{startLabel}:"); + GenerateExpression(whileStatement.Condition, func); + _builder.AppendLine(" cmp rax, 0"); + _builder.AppendLine($" je {endLabel}"); + GenerateBlock(whileStatement.Body, func); + _builder.AppendLine($" jmp {startLabel}"); + _builder.AppendLine($"{endLabel}:"); + } + private void GenerateExpression(ExpressionNode expression, LocalFunc func) { switch (expression) @@ -366,7 +382,7 @@ public class Generator case DelegateType: throw new NotSupportedException($"Comparison on type {type.GetType().Name} is not supported"); case PrimitiveType: - _builder.AppendLine(" cmp rax, rax"); + _builder.AppendLine(" cmp rax, rbx"); break; case StringType: _builder.AppendLine(" mov rdi, rax"); diff --git a/Nub.Lang/Nub.Lang/Frontend/Lexing/Lexer.cs b/Nub.Lang/Nub.Lang/Frontend/Lexing/Lexer.cs index 021b47f..3d551ba 100644 --- a/Nub.Lang/Nub.Lang/Frontend/Lexing/Lexer.cs +++ b/Nub.Lang/Nub.Lang/Frontend/Lexing/Lexer.cs @@ -8,11 +8,12 @@ public class Lexer { ["func"] = Symbol.Func, ["extern"] = Symbol.Extern, - ["return"] = Symbol.Return, ["import"] = Symbol.Import, ["let"] = Symbol.Let, ["if"] = Symbol.If, ["else"] = Symbol.Else, + ["while"] = Symbol.While, + ["return"] = Symbol.Return, }; private static readonly Dictionary Chians = new() diff --git a/Nub.Lang/Nub.Lang/Frontend/Lexing/SymbolToken.cs b/Nub.Lang/Nub.Lang/Frontend/Lexing/SymbolToken.cs index 90a1b9f..b9ee726 100644 --- a/Nub.Lang/Nub.Lang/Frontend/Lexing/SymbolToken.cs +++ b/Nub.Lang/Nub.Lang/Frontend/Lexing/SymbolToken.cs @@ -15,6 +15,7 @@ public enum Symbol Let, If, Else, + While, Semicolon, Colon, OpenParen, diff --git a/Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs b/Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs index 1950127..3eb4492 100644 --- a/Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs +++ b/Nub.Lang/Nub.Lang/Frontend/Parsing/Parser.cs @@ -163,25 +163,14 @@ public class Parser } case SymbolToken symbol: { - switch (symbol.Symbol) + return symbol.Symbol switch { - case Symbol.Return: - { - return ParseReturn(); - } - case Symbol.Let: - { - return ParseVariableAssignment(); - } - case Symbol.If: - { - return ParseIf(); - } - default: - { - throw new Exception($"Unexpected symbol {symbol.Symbol}"); - } - } + Symbol.Return => ParseReturn(), + Symbol.Let => ParseVariableAssignment(), + Symbol.If => ParseIf(), + Symbol.While => ParseWhile(), + _ => throw new Exception($"Unexpected symbol {symbol.Symbol}") + }; } default: { @@ -228,6 +217,13 @@ public class Parser return new IfNode(condition, body, elseStatement); } + private WhileNode ParseWhile() + { + var condition = ParseExpression(); + var body = ParseBlock(); + return new WhileNode(condition, body); + } + private ExpressionNode ParseExpression(int precedence = 0) { var left = ParsePrimaryExpression(); diff --git a/Nub.Lang/Nub.Lang/Frontend/Parsing/WhileNode.cs b/Nub.Lang/Nub.Lang/Frontend/Parsing/WhileNode.cs new file mode 100644 index 0000000..cc26d33 --- /dev/null +++ b/Nub.Lang/Nub.Lang/Frontend/Parsing/WhileNode.cs @@ -0,0 +1,7 @@ +namespace Nub.Lang.Frontend.Parsing; + +public class WhileNode(ExpressionNode condition, BlockNode body) : StatementNode +{ + public ExpressionNode Condition { get; } = condition; + public BlockNode Body { get; } = body; +} \ No newline at end of file diff --git a/Nub.Lang/Nub.Lang/Frontend/Typing/ExpressionTyper.cs b/Nub.Lang/Nub.Lang/Frontend/Typing/ExpressionTyper.cs index f0c3d6e..64c2b2d 100644 --- a/Nub.Lang/Nub.Lang/Frontend/Typing/ExpressionTyper.cs +++ b/Nub.Lang/Nub.Lang/Frontend/Typing/ExpressionTyper.cs @@ -101,6 +101,9 @@ public class ExpressionTyper case VariableReassignmentNode variableReassignment: PopulateVariableReassignment(variableReassignment); break; + case WhileNode whileStatement: + PopulateWhileStatement(whileStatement); + break; default: throw new ArgumentOutOfRangeException(nameof(statement)); } @@ -155,6 +158,12 @@ public class ExpressionTyper PopulateExpression(variableReassignment.Value); } + private void PopulateWhileStatement(WhileNode whileStatement) + { + PopulateExpression(whileStatement.Condition); + PopulateBlock(whileStatement.Body); + } + private void PopulateExpression(ExpressionNode expression) { switch (expression) diff --git a/input/program.nub b/input/program.nub index 78e91c6..b239cc7 100644 --- a/input/program.nub +++ b/input/program.nub @@ -1,21 +1,9 @@ import "core"; -let KB = 1024; -let MB = KB * 1024; -let GB = MB * 1024; -let TB = GB * 1024; - func main() { - println("test"); - println(true); - - if strlen("1") == 1 { - println("1"); - } else if false { - println("2"); - } else if true { - println("3"); - } else { - println("4"); + let i = 1; + while i <= 10 { + println("uwu"); + i = i + 1; } }