Fix array access

This commit is contained in:
nub31
2025-01-30 18:47:25 +01:00
parent 9625c21148
commit a81d7939ba
8 changed files with 71 additions and 8 deletions

View File

@@ -12,6 +12,7 @@ public class Generator
private readonly SymbolTable _symbolTable; private readonly SymbolTable _symbolTable;
private readonly StringBuilder _builder; private readonly StringBuilder _builder;
private readonly LabelFactory _labelFactory; private readonly LabelFactory _labelFactory;
private readonly Stack<(string StartLabel, string EndLabel)> _loops;
public Generator(List<DefinitionNode> definitions) public Generator(List<DefinitionNode> definitions)
{ {
@@ -19,6 +20,7 @@ public class Generator
_builder = new StringBuilder(); _builder = new StringBuilder();
_labelFactory = new LabelFactory(); _labelFactory = new LabelFactory();
_symbolTable = new SymbolTable(_labelFactory); _symbolTable = new SymbolTable(_labelFactory);
_loops = [];
foreach (var globalVariableDefinition in definitions.OfType<GlobalVariableDefinitionNode>()) foreach (var globalVariableDefinition in definitions.OfType<GlobalVariableDefinitionNode>())
{ {
@@ -213,6 +215,12 @@ public class Generator
case ArrayIndexAssignmentNode arrayIndexAssignment: case ArrayIndexAssignmentNode arrayIndexAssignment:
GenerateArrayIndexAssignment(arrayIndexAssignment, func); GenerateArrayIndexAssignment(arrayIndexAssignment, func);
break; break;
case BreakNode:
GenerateBreak();
break;
case ContinueNode:
GenerateContinue();
break;
case FuncCallStatementNode funcCallStatement: case FuncCallStatementNode funcCallStatement:
GenerateFuncCall(funcCallStatement.FuncCall, func); GenerateFuncCall(funcCallStatement.FuncCall, func);
break; break;
@@ -239,6 +247,16 @@ public class Generator
} }
} }
private void GenerateBreak()
{
_builder.AppendLine($" jmp {_loops.Peek().EndLabel}");
}
private void GenerateContinue()
{
_builder.AppendLine($" jmp {_loops.Peek().StartLabel}");
}
private void GenerateArrayIndexAssignment(ArrayIndexAssignmentNode arrayIndexAssignment, LocalFunc func) private void GenerateArrayIndexAssignment(ArrayIndexAssignmentNode arrayIndexAssignment, LocalFunc func)
{ {
GenerateExpression(arrayIndexAssignment.Value, func); GenerateExpression(arrayIndexAssignment.Value, func);
@@ -303,11 +321,14 @@ public class Generator
{ {
var startLabel = _labelFactory.Create(); var startLabel = _labelFactory.Create();
var endLabel = _labelFactory.Create(); var endLabel = _labelFactory.Create();
_builder.AppendLine($"{startLabel}:"); _builder.AppendLine($"{startLabel}:");
GenerateExpression(whileStatement.Condition, func); GenerateExpression(whileStatement.Condition, func);
_builder.AppendLine(" cmp rax, 0"); _builder.AppendLine(" cmp rax, 0");
_builder.AppendLine($" je {endLabel}"); _builder.AppendLine($" je {endLabel}");
_loops.Push((startLabel, endLabel));
GenerateBlock(whileStatement.Body, func); GenerateBlock(whileStatement.Body, func);
_loops.Pop();
_builder.AppendLine($" jmp {startLabel}"); _builder.AppendLine($" jmp {startLabel}");
_builder.AppendLine($"{endLabel}:"); _builder.AppendLine($"{endLabel}:");
} }
@@ -627,25 +648,25 @@ public class Generator
GenerateExpression(index, func); GenerateExpression(index, func);
_builder.AppendLine(" push rax"); _builder.AppendLine(" push rax");
GenerateIdentifier(identifier, func); GenerateIdentifier(identifier, func);
_builder.AppendLine(" pop rcx"); _builder.AppendLine(" pop rdx");
// rcx now holds the length of the array which we can use to check bounds // rcx now holds the length of the array which we can use to check bounds
_builder.AppendLine(" mov rcx, [rax]"); _builder.AppendLine(" mov rcx, [rax]");
_builder.AppendLine(" cmp rcx, rcx"); _builder.AppendLine(" cmp rdx, rcx");
if (ZeroBasedIndexing) if (ZeroBasedIndexing)
{ {
_builder.AppendLine(" jge array_out_of_bounds"); _builder.AppendLine(" jge array_out_of_bounds");
_builder.AppendLine(" cmp rcx, 0"); _builder.AppendLine(" cmp rdx, 0");
} }
else else
{ {
_builder.AppendLine(" jg array_out_of_bounds"); _builder.AppendLine(" jg array_out_of_bounds");
_builder.AppendLine(" cmp rcx, 1"); _builder.AppendLine(" cmp rdx, 1");
} }
_builder.AppendLine(" jl array_out_of_bounds"); _builder.AppendLine(" jl array_out_of_bounds");
_builder.AppendLine(" inc rcx"); _builder.AppendLine(" inc rdx");
_builder.AppendLine(" shl rcx, 3"); _builder.AppendLine(" shl rdx, 3");
_builder.AppendLine(" add rax, rcx"); _builder.AppendLine(" add rax, rdx");
} }
} }

View File

@@ -13,6 +13,8 @@ public class Lexer
["if"] = Symbol.If, ["if"] = Symbol.If,
["else"] = Symbol.Else, ["else"] = Symbol.Else,
["while"] = Symbol.While, ["while"] = Symbol.While,
["break"] = Symbol.Break,
["continue"] = Symbol.Continue,
["return"] = Symbol.Return, ["return"] = Symbol.Return,
["new"] = Symbol.New, ["new"] = Symbol.New,
}; };

View File

@@ -16,6 +16,8 @@ public enum Symbol
If, If,
Else, Else,
While, While,
Break,
Continue,
Semicolon, Semicolon,
Colon, Colon,
OpenParen, OpenParen,

View File

@@ -0,0 +1,3 @@
namespace Nub.Lang.Frontend.Parsing;
public class BreakNode : StatementNode;

View File

@@ -0,0 +1,3 @@
namespace Nub.Lang.Frontend.Parsing;
public class ContinueNode : StatementNode;

View File

@@ -178,6 +178,8 @@ public class Parser
Symbol.Let => ParseVariableAssignment(), Symbol.Let => ParseVariableAssignment(),
Symbol.If => ParseIf(), Symbol.If => ParseIf(),
Symbol.While => ParseWhile(), Symbol.While => ParseWhile(),
Symbol.Break => ParseBreak(),
Symbol.Continue => ParseContinue(),
_ => throw new Exception($"Unexpected symbol {symbol.Symbol}") _ => throw new Exception($"Unexpected symbol {symbol.Symbol}")
}; };
} }
@@ -233,6 +235,18 @@ public class Parser
return new WhileNode(condition, body); return new WhileNode(condition, body);
} }
private BreakNode ParseBreak()
{
ExpectSymbol(Symbol.Semicolon);
return new BreakNode();
}
private ContinueNode ParseContinue()
{
ExpectSymbol(Symbol.Semicolon);
return new ContinueNode();
}
private ExpressionNode ParseExpression(int precedence = 0) private ExpressionNode ParseExpression(int precedence = 0)
{ {
var left = ParsePrimaryExpression(); var left = ParsePrimaryExpression();

View File

@@ -86,6 +86,9 @@ public class ExpressionTyper
case ArrayIndexAssignmentNode arrayIndexAssignment: case ArrayIndexAssignmentNode arrayIndexAssignment:
PopulateArrayIndexAssignment(arrayIndexAssignment); PopulateArrayIndexAssignment(arrayIndexAssignment);
break; break;
case BreakNode:
case ContinueNode:
break;
case FuncCallStatementNode funcCall: case FuncCallStatementNode funcCall:
PopulateFuncCallStatement(funcCall); PopulateFuncCallStatement(funcCall);
break; break;

View File

@@ -1,5 +1,20 @@
import "core"; import "core";
func main() { func main() {
println(69); let some_string = "test";
println(some_string);
let some_array = new Array<int64>(2);
some_array[1] = 1;
some_array[2] = 2;
let i = 1;
println(some_array[1]);
println(some_array[2]);
while i <= arr_size(some_array) {
println(some_array[i]);
i = i + 1;
}
} }