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 StringBuilder _builder;
private readonly LabelFactory _labelFactory;
private readonly Stack<(string StartLabel, string EndLabel)> _loops;
public Generator(List<DefinitionNode> definitions)
{
@@ -19,6 +20,7 @@ public class Generator
_builder = new StringBuilder();
_labelFactory = new LabelFactory();
_symbolTable = new SymbolTable(_labelFactory);
_loops = [];
foreach (var globalVariableDefinition in definitions.OfType<GlobalVariableDefinitionNode>())
{
@@ -213,6 +215,12 @@ public class Generator
case ArrayIndexAssignmentNode arrayIndexAssignment:
GenerateArrayIndexAssignment(arrayIndexAssignment, func);
break;
case BreakNode:
GenerateBreak();
break;
case ContinueNode:
GenerateContinue();
break;
case FuncCallStatementNode funcCallStatement:
GenerateFuncCall(funcCallStatement.FuncCall, func);
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)
{
GenerateExpression(arrayIndexAssignment.Value, func);
@@ -303,11 +321,14 @@ public class Generator
{
var startLabel = _labelFactory.Create();
var endLabel = _labelFactory.Create();
_builder.AppendLine($"{startLabel}:");
GenerateExpression(whileStatement.Condition, func);
_builder.AppendLine(" cmp rax, 0");
_builder.AppendLine($" je {endLabel}");
_loops.Push((startLabel, endLabel));
GenerateBlock(whileStatement.Body, func);
_loops.Pop();
_builder.AppendLine($" jmp {startLabel}");
_builder.AppendLine($"{endLabel}:");
}
@@ -627,25 +648,25 @@ public class Generator
GenerateExpression(index, func);
_builder.AppendLine(" push rax");
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
_builder.AppendLine(" mov rcx, [rax]");
_builder.AppendLine(" cmp rcx, rcx");
_builder.AppendLine(" cmp rdx, rcx");
if (ZeroBasedIndexing)
{
_builder.AppendLine(" jge array_out_of_bounds");
_builder.AppendLine(" cmp rcx, 0");
_builder.AppendLine(" cmp rdx, 0");
}
else
{
_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(" inc rcx");
_builder.AppendLine(" shl rcx, 3");
_builder.AppendLine(" add rax, rcx");
_builder.AppendLine(" inc rdx");
_builder.AppendLine(" shl rdx, 3");
_builder.AppendLine(" add rax, rdx");
}
}

View File

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

View File

@@ -16,6 +16,8 @@ public enum Symbol
If,
Else,
While,
Break,
Continue,
Semicolon,
Colon,
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.If => ParseIf(),
Symbol.While => ParseWhile(),
Symbol.Break => ParseBreak(),
Symbol.Continue => ParseContinue(),
_ => throw new Exception($"Unexpected symbol {symbol.Symbol}")
};
}
@@ -233,6 +235,18 @@ public class Parser
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)
{
var left = ParsePrimaryExpression();

View File

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

View File

@@ -1,5 +1,20 @@
import "core";
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;
}
}