Fix array access
This commit is contained in:
@@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ public enum Symbol
|
|||||||
If,
|
If,
|
||||||
Else,
|
Else,
|
||||||
While,
|
While,
|
||||||
|
Break,
|
||||||
|
Continue,
|
||||||
Semicolon,
|
Semicolon,
|
||||||
Colon,
|
Colon,
|
||||||
OpenParen,
|
OpenParen,
|
||||||
|
|||||||
3
Nub.Lang/Nub.Lang/Frontend/Parsing/BreakNode.cs
Normal file
3
Nub.Lang/Nub.Lang/Frontend/Parsing/BreakNode.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Nub.Lang.Frontend.Parsing;
|
||||||
|
|
||||||
|
public class BreakNode : StatementNode;
|
||||||
3
Nub.Lang/Nub.Lang/Frontend/Parsing/ContinueNode.cs
Normal file
3
Nub.Lang/Nub.Lang/Frontend/Parsing/ContinueNode.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Nub.Lang.Frontend.Parsing;
|
||||||
|
|
||||||
|
public class ContinueNode : StatementNode;
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user