🐐 Reviving this old project. Mainly adding tests and fixing bugs.
This commit is contained in:
@@ -3,458 +3,506 @@ import random
|
||||
|
||||
from rply.token import BaseBox
|
||||
|
||||
from centvrion.values import Val, ValInt, ValStr, ValBool, ValList, ValNul, ValFunc
|
||||
|
||||
NUMERALS = {
|
||||
"I": 1,
|
||||
"IV": 4,
|
||||
"V": 5,
|
||||
"IX": 9,
|
||||
"X": 10,
|
||||
"XL": 40,
|
||||
"L": 50,
|
||||
"XC": 90,
|
||||
"C": 100,
|
||||
"CD": 400,
|
||||
"D": 500,
|
||||
"CM": 900,
|
||||
"M": 1000
|
||||
"I": 1,
|
||||
"IV": 4,
|
||||
"V": 5,
|
||||
"IX": 9,
|
||||
"X": 10,
|
||||
"XL": 40,
|
||||
"L": 50,
|
||||
"XC": 90,
|
||||
"C": 100,
|
||||
"CD": 400,
|
||||
"D": 500,
|
||||
"CM": 900,
|
||||
"M": 1000
|
||||
}
|
||||
|
||||
def rep_join(l):
|
||||
format_string = ',\n'.join(
|
||||
[repr(i) if not isinstance(i, str) else i for i in l]
|
||||
).replace('\n', '\n ')
|
||||
format_string = ',\n'.join(
|
||||
[repr(i) if not isinstance(i, str) else i for i in l]
|
||||
).replace('\n', '\n ')
|
||||
|
||||
if format_string != "":
|
||||
format_string = f"\n {format_string}\n"
|
||||
if format_string != "":
|
||||
format_string = f"\n {format_string}\n"
|
||||
|
||||
return format_string
|
||||
return format_string
|
||||
|
||||
def single_num_to_int(i, m):
|
||||
if i[-1] == "_":
|
||||
if not m:
|
||||
raise Exception(
|
||||
"Cannot calculate numbers above 3999 without 'MAGNVM' module"
|
||||
)
|
||||
if i[-1] == "_":
|
||||
if not m:
|
||||
raise ValueError(
|
||||
"Cannot calculate numbers above 3999 without 'MAGNVM' module"
|
||||
)
|
||||
|
||||
if i[0] != "I":
|
||||
raise Exception(
|
||||
"Cannot use 'I' with thousands operator, use 'M' instead"
|
||||
)
|
||||
if i[0] != "I":
|
||||
raise ValueError(
|
||||
"Cannot use 'I' with thousands operator, use 'M' instead"
|
||||
)
|
||||
|
||||
return 1000 * single_num_to_int(i[:-1], m)
|
||||
else:
|
||||
return NUMERALS[i]
|
||||
return 1000 * single_num_to_int(i[:-1], m)
|
||||
else:
|
||||
return NUMERALS[i]
|
||||
|
||||
def num_to_int(n, m):
|
||||
chars = re.findall(r"[IVXLCDM]_*", n)
|
||||
if ''.join(chars) != n:
|
||||
raise Exception("Invalid numeral", n)
|
||||
nums = [single_num_to_int(i, m) for i in chars]
|
||||
new_nums = nums.copy()
|
||||
for x, num in enumerate(nums[:-3]):
|
||||
if all(num == nums[x+i] for i in range(0,4)):
|
||||
raise Exception(n, "is not a valid roman numeral")
|
||||
chars = re.findall(r"[IVXLCDM]_*", n)
|
||||
if ''.join(chars) != n:
|
||||
raise ValueError("Invalid numeral", n)
|
||||
nums = [single_num_to_int(i, m) for i in chars]
|
||||
new_nums = nums.copy()
|
||||
for x, num in enumerate(nums[:-3]):
|
||||
if all(num == nums[x+i] for i in range(0,4)):
|
||||
raise ValueError(n, "is not a valid roman numeral")
|
||||
|
||||
while True:
|
||||
for x, num in enumerate(nums[:-1]):
|
||||
if num < nums[x+1]:
|
||||
if (not nums[x+1] % 5) and (num in [nums[x+1]/5, nums[x+1]/10]):
|
||||
new_nums[x] = nums[x+1] - num
|
||||
new_nums[x+1] = 0
|
||||
break
|
||||
else:
|
||||
raise Exception(n, "is not a valid roman numeral")
|
||||
|
||||
if new_nums != nums:
|
||||
nums = [i for i in new_nums if i != 0]
|
||||
new_nums = nums
|
||||
while True:
|
||||
for x, num in enumerate(nums[:-1]):
|
||||
if num < nums[x+1]:
|
||||
if (not nums[x+1] % 5) and (num in [nums[x+1]/5, nums[x+1]/10]):
|
||||
new_nums[x] = nums[x+1] - num
|
||||
new_nums[x+1] = 0
|
||||
break
|
||||
else:
|
||||
break
|
||||
raise ValueError(n, "is not a valid roman numeral")
|
||||
|
||||
if nums != sorted(nums)[::-1]:
|
||||
raise Exception(n, "is not a valid roman numeral")
|
||||
if new_nums != nums:
|
||||
nums = [i for i in new_nums if i != 0]
|
||||
new_nums = nums.copy()
|
||||
else:
|
||||
break
|
||||
|
||||
return sum(nums)
|
||||
if nums != sorted(nums)[::-1]:
|
||||
raise Exception(n, "is not a valid roman numeral")
|
||||
|
||||
return sum(nums)
|
||||
|
||||
def int_to_num(n, m):
|
||||
if n > 3999:
|
||||
if not m:
|
||||
raise Exception(
|
||||
"Cannot display numbers above 3999 without 'MAGNVM' module"
|
||||
)
|
||||
thousands_chars = re.findall(r"[IVXLCDM]_*", int_to_num(n//1000, m))
|
||||
thousands = ''.join([
|
||||
"M" if i == "I" else i+"_"
|
||||
for i in thousands_chars
|
||||
])
|
||||
if n > 3999:
|
||||
if not m:
|
||||
raise ValueError(
|
||||
"Cannot display numbers above 3999 without 'MAGNVM' module"
|
||||
)
|
||||
thousands_chars = re.findall(r"[IVXLCDM]_*", int_to_num(n//1000, m))
|
||||
thousands = ''.join([
|
||||
"M" if i == "I" else i+"_"
|
||||
for i in thousands_chars
|
||||
])
|
||||
|
||||
return thousands + int_to_num(n % 1000, m)
|
||||
else:
|
||||
nums = []
|
||||
while n > 0:
|
||||
for num, i in list(NUMERALS.items())[::-1]:
|
||||
if n >= i:
|
||||
nums.append(num)
|
||||
n -= i
|
||||
break
|
||||
return thousands + int_to_num(n % 1000, m)
|
||||
else:
|
||||
nums = []
|
||||
while n > 0:
|
||||
for num, i in list(NUMERALS.items())[::-1]:
|
||||
if n >= i:
|
||||
nums.append(num)
|
||||
n -= i
|
||||
break
|
||||
|
||||
return ''.join(nums)
|
||||
return ''.join(nums)
|
||||
|
||||
def make_string(n, m):
|
||||
if isinstance(n, str):
|
||||
return n
|
||||
elif isinstance(n, int):
|
||||
return int_to_num(n, m)
|
||||
elif isinstance(n, list):
|
||||
return f"[{' '.join([make_string(i, m) for i in n])}]"
|
||||
else:
|
||||
raise Exception(n)
|
||||
def make_string(val, magnvm=False):
|
||||
if isinstance(val, ValStr):
|
||||
return val.value()
|
||||
elif isinstance(val, ValInt):
|
||||
return int_to_num(val.value(), magnvm)
|
||||
elif isinstance(val, ValBool):
|
||||
return "VERVS" if val.value() else "FALSVS"
|
||||
elif isinstance(val, ValNul):
|
||||
return "NVLLVS"
|
||||
elif isinstance(val, ValList):
|
||||
inner = ' '.join(make_string(i, magnvm) for i in val.value())
|
||||
return f"[{inner}]"
|
||||
else:
|
||||
raise TypeError(f"Cannot display {val!r}")
|
||||
|
||||
class ExpressionStatement(BaseBox):
|
||||
def __init__(self, expression) -> None:
|
||||
self.expression = expression
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return self.expression.__repr__()
|
||||
class Node(BaseBox):
|
||||
def eval(self, vtable):
|
||||
return self._eval(vtable.copy())
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
self.expression.eval(vtable.copy(), ftable.copy(), modules)
|
||||
return vtable, ftable
|
||||
def _eval(self, vtable):
|
||||
raise NotImplementedError
|
||||
|
||||
class DataArray(BaseBox):
|
||||
def __init__(self, content) -> None:
|
||||
self.content = content
|
||||
|
||||
def __repr__(self) -> str:
|
||||
content_string = rep_join(self.content)
|
||||
return f"Array([{content_string}])"
|
||||
class ExpressionStatement(Node):
|
||||
def __init__(self, expression) -> None:
|
||||
self.expression = expression
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
content = [i.eval(vtable, ftable, modules) for i in self.content]
|
||||
return content
|
||||
def __repr__(self) -> str:
|
||||
return self.expression.__repr__()
|
||||
|
||||
class DataRangeArray(BaseBox):
|
||||
def __init__(self, from_value, to_value) -> None:
|
||||
self.from_value = from_value
|
||||
self.to_value = to_value
|
||||
def _eval(self, vtable):
|
||||
return self.expression.eval(vtable)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
content_string = rep_join([self.from_value, self.to_value])
|
||||
return f"RangeArray([{content_string}])"
|
||||
|
||||
def eval(self, *_):
|
||||
content = list(range(self.from_value.eval(), self.to_value.eval()))
|
||||
return content
|
||||
class DataArray(Node):
|
||||
def __init__(self, content) -> None:
|
||||
self.content = content
|
||||
|
||||
class String(BaseBox):
|
||||
def __init__(self, value) -> None:
|
||||
self.value = value
|
||||
def __repr__(self) -> str:
|
||||
content_string = rep_join(self.content)
|
||||
return f"Array([{content_string}])"
|
||||
|
||||
def __repr__(self):
|
||||
return f"String({self.value})"
|
||||
def _eval(self, vtable):
|
||||
vals = []
|
||||
for item in self.content:
|
||||
vtable, val = item.eval(vtable)
|
||||
vals.append(val)
|
||||
return vtable, ValList(vals)
|
||||
|
||||
def eval(self, *_):
|
||||
return self.value
|
||||
|
||||
class Numeral(BaseBox):
|
||||
def __init__(self, value) -> None:
|
||||
self.value = value
|
||||
class DataRangeArray(Node):
|
||||
def __init__(self, from_value, to_value) -> None:
|
||||
self.from_value = from_value
|
||||
self.to_value = to_value
|
||||
|
||||
def __repr__(self):
|
||||
return f"Numeral({self.value})"
|
||||
def __repr__(self) -> str:
|
||||
content_string = rep_join([self.from_value, self.to_value])
|
||||
return f"RangeArray([{content_string}])"
|
||||
|
||||
def eval(self, *args):
|
||||
return num_to_int(self.value, "MAGNVM" in args[2])
|
||||
def _eval(self, vtable):
|
||||
vtable, from_val = self.from_value.eval(vtable)
|
||||
vtable, to_val = self.to_value.eval(vtable)
|
||||
return vtable, ValList([ValInt(i) for i in range(from_val.value(), to_val.value())])
|
||||
|
||||
class Bool(BaseBox):
|
||||
def __init__(self, value) -> None:
|
||||
self.value = value
|
||||
|
||||
def __repr__(self):
|
||||
return f"Bool({self.value})"
|
||||
class String(Node):
|
||||
def __init__(self, value) -> None:
|
||||
self.value = value
|
||||
|
||||
def __repr__(self):
|
||||
return f"String({self.value})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
return vtable, ValStr(self.value)
|
||||
|
||||
|
||||
class Numeral(Node):
|
||||
def __init__(self, value) -> None:
|
||||
self.value = value
|
||||
|
||||
def __repr__(self):
|
||||
return f"Numeral({self.value})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
return vtable, ValInt(num_to_int(self.value, "MAGNVM" in vtable["#modules"]))
|
||||
|
||||
|
||||
class Bool(Node):
|
||||
def __init__(self, value) -> None:
|
||||
self.value = value
|
||||
|
||||
def __repr__(self):
|
||||
return f"Bool({self.value})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
return vtable, ValBool(self.value)
|
||||
|
||||
def eval(self, *_):
|
||||
return self.value
|
||||
|
||||
class ModuleCall(BaseBox):
|
||||
def __init__(self, module_name) -> None:
|
||||
self.module_name = module_name
|
||||
def __init__(self, module_name) -> None:
|
||||
self.module_name = module_name
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.module_name}"
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.module_name}"
|
||||
|
||||
class ID(BaseBox):
|
||||
def __init__(self, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"ID({self.name})"
|
||||
class ID(Node):
|
||||
def __init__(self, name: str) -> None:
|
||||
self.name = name
|
||||
|
||||
def eval(self, vtable, *_):
|
||||
return vtable[self.name]
|
||||
def __repr__(self) -> str:
|
||||
return f"ID({self.name})"
|
||||
|
||||
class Designa(BaseBox):
|
||||
def __init__(self, variable: ID, value) -> None:
|
||||
self.id = variable
|
||||
self.value = value
|
||||
def _eval(self, vtable):
|
||||
return vtable, vtable[self.name]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
id_string = repr(self.id).replace('\n', '\n ')
|
||||
value_string = repr(self.value).replace('\n', '\n ')
|
||||
return f"Designa(\n {id_string},\n {value_string}\n)"
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
vtable[self.id.name] = self.value.eval(
|
||||
vtable.copy(), ftable.copy(), modules
|
||||
class Designa(Node):
|
||||
def __init__(self, variable: ID, value) -> None:
|
||||
self.id = variable
|
||||
self.value = value
|
||||
|
||||
def __repr__(self) -> str:
|
||||
id_string = repr(self.id).replace('\n', '\n ')
|
||||
value_string = repr(self.value).replace('\n', '\n ')
|
||||
return f"Designa(\n {id_string},\n {value_string}\n)"
|
||||
|
||||
def _eval(self, vtable):
|
||||
vtable, val = self.value.eval(vtable)
|
||||
vtable[self.id.name] = val
|
||||
return vtable, ValNul()
|
||||
|
||||
|
||||
class Defini(Node):
|
||||
def __init__(self, name, parameters, statements) -> None:
|
||||
self.name = name
|
||||
self.parameters = parameters
|
||||
self.statements = statements
|
||||
|
||||
def __repr__(self) -> str:
|
||||
parameter_string = f"parameters([{rep_join(self.parameters)}])"
|
||||
statements_string = f"statements([{rep_join(self.statements)}])"
|
||||
def_string = rep_join(
|
||||
[f"{repr(self.name)}", parameter_string, statements_string]
|
||||
)
|
||||
return f"Defini({def_string})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
vtable[self.name.name] = ValFunc(self.parameters, self.statements)
|
||||
return vtable, ValNul()
|
||||
|
||||
|
||||
class Redi(Node):
|
||||
def __init__(self, values) -> None:
|
||||
self.values = values
|
||||
|
||||
def __repr__(self) -> str:
|
||||
values_string = f"[{rep_join(self.values)}]"
|
||||
return f"Redi({values_string})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
vals = []
|
||||
for v in self.values:
|
||||
vtable, val = v.eval(vtable)
|
||||
vals.append(val)
|
||||
if len(vals) == 1:
|
||||
vtable["#return"] = vals[0]
|
||||
else:
|
||||
vtable["#return"] = ValList(vals)
|
||||
return vtable, ValNul()
|
||||
|
||||
|
||||
class Erumpe(Node):
|
||||
def __repr__(self) -> str:
|
||||
return "Erumpe()"
|
||||
|
||||
def _eval(self, vtable):
|
||||
vtable["#break"] = True
|
||||
return vtable, ValNul()
|
||||
|
||||
|
||||
class Nullus(Node):
|
||||
def __repr__(self) -> str:
|
||||
return "Nullus()"
|
||||
|
||||
def _eval(self, vtable):
|
||||
return vtable, ValNul()
|
||||
|
||||
|
||||
class BinOp(Node):
|
||||
def __init__(self, left, right, op) -> None:
|
||||
self.left = left
|
||||
self.right = right
|
||||
self.op = op
|
||||
|
||||
def __repr__(self) -> str:
|
||||
binop_string = rep_join([self.left, self.right, self.op])
|
||||
return f"BinOp({binop_string})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
vtable, left = self.left.eval(vtable)
|
||||
vtable, right = self.right.eval(vtable)
|
||||
lv, rv = left.value(), right.value()
|
||||
match self.op:
|
||||
case "SYMBOL_PLUS":
|
||||
return vtable, ValInt(lv + rv)
|
||||
case "SYMBOL_MINUS":
|
||||
return vtable, ValInt(lv - rv)
|
||||
case "SYMBOL_TIMES":
|
||||
return vtable, ValInt(lv * rv)
|
||||
case "SYMBOL_DIVIDE":
|
||||
# TODO: Fractio
|
||||
return vtable, ValInt(lv // rv)
|
||||
case "KEYWORD_MINVS":
|
||||
return vtable, ValBool(lv < rv)
|
||||
case "KEYWORD_PLVS":
|
||||
return vtable, ValBool(lv > rv)
|
||||
case "KEYWORD_EST":
|
||||
return vtable, ValBool(lv == rv)
|
||||
case "KEYWORD_ET":
|
||||
return vtable, ValBool(bool(lv) and bool(rv))
|
||||
case "KEYWORD_AVT":
|
||||
return vtable, ValBool(bool(lv) or bool(rv))
|
||||
case _:
|
||||
raise Exception(self.op)
|
||||
|
||||
|
||||
class SiStatement(Node):
|
||||
def __init__(self, test, statements, else_part) -> None:
|
||||
self.test = test
|
||||
self.statements = statements
|
||||
self.else_part = else_part
|
||||
|
||||
def __repr__(self) -> str:
|
||||
test = repr(self.test)
|
||||
statements = f"statements([{rep_join(self.statements)}])"
|
||||
else_part = f"statements([{rep_join(self.else_part) if self.else_part else ''}])"
|
||||
si_string = rep_join([test, statements, else_part])
|
||||
return f"Si({si_string})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
vtable, cond = self.test.eval(vtable)
|
||||
last_val = ValNul()
|
||||
if cond:
|
||||
for statement in self.statements:
|
||||
vtable, last_val = statement.eval(vtable)
|
||||
elif self.else_part:
|
||||
for statement in self.else_part:
|
||||
vtable, last_val = statement.eval(vtable)
|
||||
return vtable, last_val
|
||||
|
||||
|
||||
class DumStatement(Node):
|
||||
def __init__(self, test, statements) -> None:
|
||||
self.test = test
|
||||
self.statements = statements
|
||||
|
||||
def __repr__(self) -> str:
|
||||
test = repr(self.test)
|
||||
statements = f"statements([{rep_join(self.statements)}])"
|
||||
dum_string = rep_join([test, statements])
|
||||
return f"Dum({dum_string})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
last_val = ValNul()
|
||||
vtable, cond = self.test.eval(vtable)
|
||||
while not cond:
|
||||
for statement in self.statements:
|
||||
vtable, val = statement.eval(vtable)
|
||||
if vtable["#break"]:
|
||||
break
|
||||
last_val = val
|
||||
if vtable["#break"]:
|
||||
vtable["#break"] = False
|
||||
break
|
||||
vtable, cond = self.test.eval(vtable)
|
||||
return vtable, last_val
|
||||
|
||||
|
||||
class PerStatement(Node):
|
||||
def __init__(self, data_list, variable_name, statements) -> None:
|
||||
self.data_list = data_list
|
||||
self.variable_name = variable_name
|
||||
self.statements = statements
|
||||
|
||||
def __repr__(self) -> str:
|
||||
test = repr(self.data_list)
|
||||
variable_name = repr(self.variable_name)
|
||||
statements = f"statements([{rep_join(self.statements)}])"
|
||||
dum_string = rep_join([test, variable_name, statements])
|
||||
return f"Per({dum_string})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
vtable, array = self.data_list.eval(vtable)
|
||||
variable_name = self.variable_name.name
|
||||
last_val = ValNul()
|
||||
for item in array:
|
||||
vtable[variable_name] = item
|
||||
for statement in self.statements:
|
||||
vtable, val = statement.eval(vtable)
|
||||
if vtable["#break"]:
|
||||
break
|
||||
last_val = val
|
||||
if vtable["#break"]:
|
||||
vtable["#break"] = False
|
||||
break
|
||||
return vtable, last_val
|
||||
|
||||
|
||||
class Invoca(Node):
|
||||
def __init__(self, name, parameters) -> None:
|
||||
self.name = name
|
||||
self.parameters = parameters
|
||||
|
||||
def __repr__(self) -> str:
|
||||
parameters_string = f"parameters([{rep_join(self.parameters)}])"
|
||||
invoca_string = rep_join([self.name, parameters_string])
|
||||
return f"Invoca({invoca_string})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
params = [p.eval(vtable)[1] for p in self.parameters]
|
||||
func = vtable[self.name.name]
|
||||
if len(params) != len(func.params):
|
||||
raise TypeError(
|
||||
f"{self.name.name} expects {len(func.params)} argument(s), got {len(params)}"
|
||||
)
|
||||
func_vtable = vtable.copy()
|
||||
for i, param in enumerate(func.params):
|
||||
func_vtable[param.name] = params[i]
|
||||
func_vtable["#return"] = None
|
||||
for statement in func.body:
|
||||
func_vtable, _ = statement.eval(func_vtable)
|
||||
if func_vtable["#return"] is not None:
|
||||
return vtable, func_vtable["#return"]
|
||||
return vtable, ValNul()
|
||||
|
||||
|
||||
class BuiltIn(Node):
|
||||
def __init__(self, builtin, parameters) -> None:
|
||||
self.builtin = builtin
|
||||
self.parameters = parameters
|
||||
|
||||
def __repr__(self) -> str:
|
||||
parameter_string = f"parameters([{rep_join(self.parameters)}])"
|
||||
builtin_string = rep_join([self.builtin, parameter_string])
|
||||
return f"Builtin({builtin_string})"
|
||||
|
||||
def _eval(self, vtable):
|
||||
params = [p.eval(vtable)[1] for p in self.parameters]
|
||||
magnvm = "MAGNVM" in vtable["#modules"]
|
||||
|
||||
match self.builtin:
|
||||
case "AVDI_NVMERVS":
|
||||
return vtable, ValInt(num_to_int(input(), magnvm))
|
||||
case "AVDI":
|
||||
return vtable, ValStr(input())
|
||||
case "DICE":
|
||||
print_string = ' '.join(
|
||||
make_string(i, magnvm) for i in params
|
||||
)
|
||||
return vtable, ftable
|
||||
print(print_string)
|
||||
return vtable, ValStr(print_string)
|
||||
case "ERVMPE":
|
||||
vtable["#break"] = True
|
||||
return vtable, ValNul()
|
||||
case "FORTIS_NVMERVS":
|
||||
if "FORS" not in vtable["#modules"]:
|
||||
raise ValueError(
|
||||
"Cannot use 'FORTIS_NVMERVS' without module 'FORS'"
|
||||
)
|
||||
return vtable, ValInt(random.randint(params[0].value(), params[1].value()))
|
||||
case "FORTIS_ELECTIONIS":
|
||||
if "FORS" not in vtable["#modules"]:
|
||||
raise ValueError(
|
||||
"Cannot use 'FORTIS_ELECTIONIS' without module 'FORS'"
|
||||
)
|
||||
return vtable, params[0].value()[random.randint(0, len(params[0].value()) - 1)]
|
||||
case "LONGITVDO":
|
||||
return vtable, ValInt(len(params[0].value()))
|
||||
case _:
|
||||
raise NotImplementedError(self.builtin)
|
||||
|
||||
class Defini(BaseBox):
|
||||
def __init__(self, name, parameters, statements) -> None:
|
||||
self.name = name
|
||||
self.parameters = parameters
|
||||
self.statements = statements
|
||||
|
||||
def __repr__(self) -> str:
|
||||
parameter_string = f"parameters([{rep_join(self.parameters)}])"
|
||||
statements_string = f"statements([{rep_join(self.statements)}])"
|
||||
def_string = rep_join(
|
||||
[f"{repr(self.name)}", parameter_string, statements_string]
|
||||
)
|
||||
return f"Defini({def_string})"
|
||||
|
||||
def eval(self, vtable, ftable, _):
|
||||
ftable[self.name.name] = (
|
||||
self.parameters, self.statements
|
||||
)
|
||||
return vtable, ftable
|
||||
|
||||
class Redi(BaseBox):
|
||||
def __init__(self, values) -> None:
|
||||
self.values = values
|
||||
|
||||
def __repr__(self) -> str:
|
||||
values_string = f"[{rep_join(self.values)}]"
|
||||
return f"Redi({values_string})"
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
values = [
|
||||
i.eval(vtable.copy(), ftable.copy(), modules)
|
||||
for i in self.values
|
||||
]
|
||||
if len(values) == 1:
|
||||
vtable["REDI"] = values[0]
|
||||
else:
|
||||
vtable["REDI"] = values
|
||||
return vtable, ftable
|
||||
|
||||
class Erumpe(BaseBox):
|
||||
def __repr__(self) -> str:
|
||||
return "Erumpe()"
|
||||
|
||||
def eval(self, vtable, ftable, _):
|
||||
vtable["ERVMPE"] = True
|
||||
return vtable, ftable
|
||||
|
||||
class Nullus(BaseBox):
|
||||
def __repr__(self) -> str:
|
||||
return "Nullus()"
|
||||
|
||||
def eval(self, *_):
|
||||
return 0
|
||||
|
||||
class BinOp(BaseBox):
|
||||
def __init__(self, left, right, op) -> None:
|
||||
self.left = left
|
||||
self.right = right
|
||||
self.op = op
|
||||
|
||||
def __repr__(self) -> str:
|
||||
binop_string = rep_join([self.left, self.right, self.op])
|
||||
return f"BinOp({binop_string})"
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
left = self.left.eval(vtable.copy(), ftable.copy(), modules)
|
||||
right = self.right.eval(vtable.copy(), ftable.copy(), modules)
|
||||
match self.op:
|
||||
case "SYMBOL_PLUS":
|
||||
return left + right
|
||||
case "SYMBOL_MINUS":
|
||||
return left - right
|
||||
case "SYMBOL_TIMES":
|
||||
return left * right
|
||||
case "SYMBOL_DIVIDE":
|
||||
# TODO: Fractio
|
||||
return left // right
|
||||
case "KEYWORD_MINVS":
|
||||
return left < right
|
||||
case "KEYWORD_PLVS":
|
||||
return left > right
|
||||
case "KEYWORD_EST":
|
||||
return left == right
|
||||
case _:
|
||||
raise Exception(self.op)
|
||||
|
||||
class SiStatement(BaseBox):
|
||||
def __init__(self, test, statements, else_part) -> None:
|
||||
self.test = test
|
||||
self.statements = statements
|
||||
self.else_part = else_part
|
||||
|
||||
def __repr__(self) -> str:
|
||||
test = repr(self.test)
|
||||
statements = f"statements([{rep_join(self.statements)}])"
|
||||
else_part = f"statements([{rep_join(self.else_part)}])"
|
||||
si_string = rep_join([test, statements, else_part])
|
||||
return f"Si({si_string})"
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
if self.test.eval(vtable, ftable, modules):
|
||||
for statement in self.statements:
|
||||
vtable, ftable = statement.eval(
|
||||
vtable, ftable, modules
|
||||
)
|
||||
else:
|
||||
for statement in self.else_part:
|
||||
vtable, ftable = statement.eval(
|
||||
vtable, ftable, modules
|
||||
)
|
||||
|
||||
return vtable, ftable
|
||||
|
||||
class DumStatement(BaseBox):
|
||||
def __init__(self, test, statements) -> None:
|
||||
self.test = test
|
||||
self.statements = statements
|
||||
|
||||
def __repr__(self) -> str:
|
||||
test = repr(self.test)
|
||||
statements = f"statements([{rep_join(self.statements)}])"
|
||||
dum_string = rep_join([test, statements])
|
||||
return f"Dum({dum_string})"
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
while not self.test.eval(vtable, ftable, modules):
|
||||
for statement in self.statements:
|
||||
vtable, ftable = statement.eval(
|
||||
vtable, ftable, modules
|
||||
)
|
||||
if vtable["ERVMPE"]:
|
||||
break
|
||||
|
||||
if vtable["ERVMPE"]:
|
||||
vtable["ERVMPE"] = False
|
||||
break
|
||||
|
||||
return vtable, ftable
|
||||
|
||||
class PerStatement(BaseBox):
|
||||
def __init__(self, data_list, variable_name, statements) -> None:
|
||||
self.data_list = data_list
|
||||
self.variable_name = variable_name
|
||||
self.statements = statements
|
||||
|
||||
def __repr__(self) -> str:
|
||||
test = repr(self.data_list)
|
||||
variable_name = repr(self.variable_name)
|
||||
statements = f"statements([{rep_join(self.statements)}])"
|
||||
dum_string = rep_join([test, variable_name, statements])
|
||||
return f"Per({dum_string})"
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
data_array = self.data_list.eval(vtable, ftable, modules)
|
||||
variable_name = self.variable_name.name
|
||||
for i in data_array:
|
||||
vtable[variable_name] = i
|
||||
for statement in self.statements:
|
||||
vtable, ftable = statement.eval(
|
||||
vtable, ftable, modules
|
||||
)
|
||||
if vtable["ERVMPE"]:
|
||||
break
|
||||
|
||||
if vtable["ERVMPE"]:
|
||||
vtable["ERVMPE"] = False
|
||||
break
|
||||
|
||||
return vtable, ftable
|
||||
|
||||
class Invoca(BaseBox):
|
||||
def __init__(self, name, parameters) -> None:
|
||||
self.name = name
|
||||
self.parameters = parameters
|
||||
|
||||
def __repr__(self) -> str:
|
||||
parameters_string = f"parameters([{rep_join(self.parameters)}])"
|
||||
invoca_string = rep_join([self.name, parameters_string])
|
||||
return f"Invoca({invoca_string})"
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
parameters = [
|
||||
i.eval(vtable.copy(), ftable.copy(), modules)
|
||||
for i in self.parameters
|
||||
]
|
||||
vtable_copy = vtable.copy()
|
||||
function = ftable[self.name.name]
|
||||
for i, parameter in enumerate(function[0]):
|
||||
vtable_copy[parameter.name] = parameters[i]
|
||||
|
||||
vtable_copy["REDI"] = None
|
||||
for statement in function[1]:
|
||||
statement.eval(vtable_copy, ftable, modules)
|
||||
if vtable_copy["REDI"] is not None:
|
||||
return vtable_copy["REDI"]
|
||||
|
||||
class BuiltIn(BaseBox):
|
||||
def __init__(self, builtin, parameters) -> None:
|
||||
self.builtin = builtin
|
||||
self.parameters = parameters
|
||||
|
||||
def __repr__(self) -> str:
|
||||
parameter_string = f"parameters([{rep_join(self.parameters)}])"
|
||||
builtin_string = rep_join([self.builtin, parameter_string])
|
||||
return f"Builtin({builtin_string})"
|
||||
|
||||
def eval(self, vtable, ftable, modules):
|
||||
parameters = [
|
||||
i.eval(vtable.copy(), ftable.copy(), modules)
|
||||
for i in self.parameters
|
||||
]
|
||||
|
||||
match self.builtin:
|
||||
case "AVDI_NVMERVS":
|
||||
return num_to_int(input(), "MAGNVM" in modules)
|
||||
case "DICE":
|
||||
print(' '.join(
|
||||
make_string(i, "MAGNVM" in modules) for i in parameters)
|
||||
)
|
||||
return None
|
||||
case "ERVMPE":
|
||||
vtable["ERVMPE"] = True
|
||||
return None
|
||||
case "FORTIS_NVMERVS":
|
||||
if "FORS" not in modules:
|
||||
raise Exception(
|
||||
"Cannot use 'FORTIS_NVMERVS' without module 'FORS'"
|
||||
)
|
||||
return random.randint(parameters[0], parameters[1])
|
||||
case _:
|
||||
raise Exception(self.builtin)
|
||||
|
||||
class Program(BaseBox):
|
||||
def __init__(self, module_calls: list[ModuleCall], statements) -> None:
|
||||
self.modules = module_calls
|
||||
self.statements = statements
|
||||
def __init__(self, module_calls: list[ModuleCall], statements) -> None:
|
||||
self.modules = module_calls
|
||||
self.statements = statements
|
||||
|
||||
def __repr__(self) -> str:
|
||||
modules_string = f"modules([{rep_join(self.modules)}])"
|
||||
statements_string = f"statements([{rep_join(self.statements)}])"
|
||||
return f"{modules_string},\n{statements_string}"
|
||||
def __repr__(self) -> str:
|
||||
modules_string = f"modules([{rep_join(self.modules)}])"
|
||||
statements_string = f"statements([{rep_join(self.statements)}])"
|
||||
return f"{modules_string},\n{statements_string}"
|
||||
|
||||
def eval(self, *_):
|
||||
vtable = {"ERVMPE": False}
|
||||
ftable = {}
|
||||
modules = [module.module_name for module in self.modules]
|
||||
|
||||
for statement in self.statements:
|
||||
vtable, ftable = statement.eval(vtable, ftable, modules)
|
||||
def eval(self, *_):
|
||||
vtable = {
|
||||
"#break": False,
|
||||
"#return": None,
|
||||
"#modules": [m.module_name for m in self.modules],
|
||||
}
|
||||
last_val = ValNul()
|
||||
for statement in self.statements:
|
||||
vtable, last_val = statement.eval(vtable)
|
||||
return last_val
|
||||
|
||||
Reference in New Issue
Block a user