🐐 Dict
This commit is contained in:
@@ -5,7 +5,7 @@ from fractions import Fraction
|
||||
from rply.token import BaseBox
|
||||
|
||||
from centvrion.errors import CentvrionError
|
||||
from centvrion.values import Val, ValInt, ValStr, ValBool, ValList, ValNul, ValFunc, ValFrac
|
||||
from centvrion.values import Val, ValInt, ValStr, ValBool, ValList, ValDict, ValNul, ValFunc, ValFrac
|
||||
|
||||
NUMERALS = {
|
||||
"I": 1,
|
||||
@@ -136,6 +136,14 @@ def make_string(val, magnvm=False, svbnvlla=False) -> str:
|
||||
elif isinstance(val, ValList):
|
||||
inner = ' '.join(make_string(i, magnvm, svbnvlla) for i in val.value())
|
||||
return f"[{inner}]"
|
||||
elif isinstance(val, ValDict):
|
||||
def _key_val(k):
|
||||
return ValStr(k) if isinstance(k, str) else ValInt(k)
|
||||
inner = ', '.join(
|
||||
f"{make_string(_key_val(k), magnvm, svbnvlla)} VT {make_string(v, magnvm, svbnvlla)}"
|
||||
for k, v in val.value().items()
|
||||
)
|
||||
return "{" + inner + "}"
|
||||
else:
|
||||
raise CentvrionError(f"Cannot display {val!r}")
|
||||
|
||||
@@ -272,6 +280,32 @@ class DataRangeArray(Node):
|
||||
return vtable, ValList([ValInt(i) for i in range(from_int, to_int)])
|
||||
|
||||
|
||||
class DataDict(Node):
|
||||
def __init__(self, pairs) -> None:
|
||||
self.pairs = pairs
|
||||
|
||||
def __eq__(self, other):
|
||||
return type(self) == type(other) and self.pairs == other.pairs
|
||||
|
||||
def __repr__(self) -> str:
|
||||
pair_strs = ', '.join(f"({k!r}, {v!r})" for k, v in self.pairs)
|
||||
return f"Dict([{pair_strs}])"
|
||||
|
||||
def print(self):
|
||||
items = ", ".join(f"{k.print()} VT {v.print()}" for k, v in self.pairs)
|
||||
return "TABVLA {" + items + "}"
|
||||
|
||||
def _eval(self, vtable):
|
||||
d = {}
|
||||
for key_node, val_node in self.pairs:
|
||||
vtable, key = key_node.eval(vtable)
|
||||
vtable, val = val_node.eval(vtable)
|
||||
if not isinstance(key, (ValStr, ValInt)):
|
||||
raise CentvrionError("Dict keys must be strings or integers")
|
||||
d[key.value()] = val
|
||||
return vtable, ValDict(d)
|
||||
|
||||
|
||||
class String(Node):
|
||||
def __init__(self, value) -> None:
|
||||
self.value = value
|
||||
@@ -469,8 +503,15 @@ class DesignaIndex(Node):
|
||||
if self.id.name not in vtable:
|
||||
raise CentvrionError(f"Undefined variable: {self.id.name}")
|
||||
target = vtable[self.id.name]
|
||||
if isinstance(target, ValDict):
|
||||
if not isinstance(index, (ValStr, ValInt)):
|
||||
raise CentvrionError("Dict key must be a string or integer")
|
||||
d = dict(target.value())
|
||||
d[index.value()] = val
|
||||
vtable[self.id.name] = ValDict(d)
|
||||
return vtable, ValNul()
|
||||
if not isinstance(target, ValList):
|
||||
raise CentvrionError(f"{self.id.name} is not an array")
|
||||
raise CentvrionError(f"{self.id.name} is not an array or dict")
|
||||
i = index.value()
|
||||
lst = list(target.value())
|
||||
if i < 1 or i > len(lst):
|
||||
@@ -756,6 +797,14 @@ class ArrayIndex(Node):
|
||||
def _eval(self, vtable):
|
||||
vtable, array = self.array.eval(vtable)
|
||||
vtable, index = self.index.eval(vtable)
|
||||
if isinstance(array, ValDict):
|
||||
if not isinstance(index, (ValStr, ValInt)):
|
||||
raise CentvrionError("Dict key must be a string or integer")
|
||||
k = index.value()
|
||||
d = array.value()
|
||||
if k not in d:
|
||||
raise CentvrionError(f"Key not found in dict")
|
||||
return vtable, d[k]
|
||||
if not isinstance(array, ValList):
|
||||
raise CentvrionError("Cannot index a non-array value")
|
||||
if isinstance(index, ValInt):
|
||||
@@ -879,8 +928,11 @@ class PerStatement(Node):
|
||||
|
||||
def _eval(self, vtable):
|
||||
vtable, array = self.data_list.eval(vtable)
|
||||
if isinstance(array, ValDict):
|
||||
keys = [ValStr(k) if isinstance(k, str) else ValInt(k) for k in array.value().keys()]
|
||||
array = ValList(keys)
|
||||
if not isinstance(array, ValList):
|
||||
raise CentvrionError("PER requires an array")
|
||||
raise CentvrionError("PER requires an array or dict")
|
||||
variable_name = self.variable_name.name
|
||||
last_val = ValNul()
|
||||
for item in array:
|
||||
@@ -1027,9 +1079,14 @@ class BuiltIn(Node):
|
||||
true_count = sum(1 for p in items if p.value())
|
||||
return vtable, ValBool(true_count > len(items) / 2)
|
||||
case "LONGITVDO":
|
||||
if isinstance(params[0], (ValList, ValStr)):
|
||||
if isinstance(params[0], (ValList, ValStr, ValDict)):
|
||||
return vtable, ValInt(len(params[0].value()))
|
||||
raise CentvrionError("LONGITVDO requires an array or string")
|
||||
raise CentvrionError("LONGITVDO requires an array, string, or dict")
|
||||
case "CLAVES":
|
||||
if not isinstance(params[0], ValDict):
|
||||
raise CentvrionError("CLAVES requires a dict")
|
||||
keys = [ValStr(k) if isinstance(k, str) else ValInt(k) for k in params[0].value().keys()]
|
||||
return vtable, ValList(keys)
|
||||
case "EVERRO":
|
||||
print("\033[2J\033[H", end="", flush=True)
|
||||
return vtable, ValNul()
|
||||
|
||||
Reference in New Issue
Block a user