🐐 Array indexing
This commit is contained in:
@@ -102,6 +102,15 @@ Arrays are defined using square brackets (`[]`) and commas (`,`). An array of in
|
||||
DESIGNA x VT [I VSQVE X]
|
||||
```
|
||||
|
||||
Individual elements can be accessed by index using square brackets. Indexing is 1-based, so `I` refers to the first element:
|
||||
|
||||
```
|
||||
DESIGNA x VT [(I, II, III)]
|
||||
DICE(x[I])
|
||||
|
||||
> I
|
||||
```
|
||||
|
||||
## Conditionals
|
||||
### SI/TVNC
|
||||
If-then statements are denoted with the keywords `SI` (if) and `TVNC` (then). Thus, the code
|
||||
|
||||
@@ -342,6 +342,24 @@ class UnaryMinus(Node):
|
||||
return vtable, ValInt(-val.value())
|
||||
|
||||
|
||||
class ArrayIndex(Node):
|
||||
def __init__(self, array, index) -> None:
|
||||
self.array = array
|
||||
self.index = index
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"ArrayIndex({self.array!r}, {self.index!r})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
vtable, array = self.array.eval(vtable)
|
||||
vtable, index = self.index.eval(vtable)
|
||||
i = index.value()
|
||||
lst = array.value()
|
||||
if i < 1 or i > len(lst):
|
||||
raise IndexError(f"Index {i} out of range for array of length {len(lst)}")
|
||||
return vtable, lst[i - 1]
|
||||
|
||||
|
||||
class SiStatement(Node):
|
||||
def __init__(self, test, statements, else_part) -> None:
|
||||
self.test = test
|
||||
|
||||
@@ -16,6 +16,7 @@ class Parser():
|
||||
('left', ["SYMBOL_PLUS", "SYMBOL_MINUS"]),
|
||||
('left', ["SYMBOL_TIMES", "SYMBOL_DIVIDE"]),
|
||||
('right', ["UMINUS"]),
|
||||
('left', ["INDEX"]),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -194,6 +195,10 @@ class Parser():
|
||||
def range_array(tokens):
|
||||
return ast_nodes.DataRangeArray(tokens[1], tokens[3])
|
||||
|
||||
@self.pg.production('expression : expression SYMBOL_LBRACKET expression SYMBOL_RBRACKET', precedence='INDEX')
|
||||
def array_index(tokens):
|
||||
return ast_nodes.ArrayIndex(tokens[0], tokens[2])
|
||||
|
||||
# ids
|
||||
@self.pg.production('ids : SYMBOL_LPARENS id_list')
|
||||
def ids(tokens):
|
||||
|
||||
16
tests.py
16
tests.py
@@ -5,7 +5,7 @@ from unittest.mock import patch
|
||||
from parameterized import parameterized
|
||||
|
||||
from centvrion.ast_nodes import (
|
||||
Bool, BinOp, BuiltIn, DataArray, DataRangeArray, Defini,
|
||||
ArrayIndex, Bool, BinOp, BuiltIn, DataArray, DataRangeArray, Defini,
|
||||
Designa, DumStatement, Erumpe, ExpressionStatement, ID,
|
||||
Invoca, ModuleCall, Nullus, Numeral, PerStatement,
|
||||
Program, Redi, SiStatement, String, UnaryMinus,
|
||||
@@ -231,6 +231,8 @@ error_tests = [
|
||||
("DEFINI f (x, y) VT { REDI(x) }\nINVOCA f (I)", TypeError), # too few args
|
||||
("DEFINI f () VT { REDI(I) }\nINVOCA f (I)", TypeError), # args to zero-param function
|
||||
("SI NVLLVS TVNC { DESIGNA r VT I }", TypeError), # NVLLVS cannot be used as boolean
|
||||
("[(I, II)][III]", IndexError), # index too high
|
||||
("[(I, II)][-I]", IndexError), # negative index
|
||||
]
|
||||
|
||||
class TestErrors(unittest.TestCase):
|
||||
@@ -604,17 +606,17 @@ class TestEtAvt(unittest.TestCase):
|
||||
|
||||
|
||||
# --- Array indexing ---
|
||||
# Indexing is 0-based; NVLLVS serves as index 0
|
||||
# Indexing is 1-based; I is the first element
|
||||
|
||||
array_index_tests = [
|
||||
# basic indexing
|
||||
("[(I, II, III)][NVLLVS]", None, ValInt(1)), # index 0 → first element
|
||||
("[(I, II, III)][I]", None, ValInt(2)), # index 1 → second element
|
||||
("[(I, II, III)][II]", None, ValInt(3)), # index 2 → third element
|
||||
("[(I, II, III)][I]", None, ValInt(1)), # first element
|
||||
("[(I, II, III)][II]", None, ValInt(2)), # second element
|
||||
("[(I, II, III)][III]", None, ValInt(3)), # third element
|
||||
# index into a variable
|
||||
("DESIGNA a VT [(X, XX, XXX)]\na[I]", None, ValInt(20)),
|
||||
("DESIGNA a VT [(X, XX, XXX)]\na[II]", None, ValInt(20)), # second element
|
||||
# index into range array
|
||||
("[I VSQVE V][II]", None, ValInt(3)),
|
||||
("[I VSQVE V][II]", None, ValInt(2)), # second element of [1,2,3,4]
|
||||
]
|
||||
|
||||
class TestArrayIndex(unittest.TestCase):
|
||||
|
||||
Reference in New Issue
Block a user