Files
centvrion/ast_nodes.py
NikolajDanger 912c46ab7c
2022-06-08 13:08:19 +02:00

383 lines
11 KiB
Python

import random
import roman
from rply.token import BaseBox
NUMERALS = [
("I", 1),
("V", 5),
("X", 10),
("L", 50),
("C", 100),
("D", 500),
("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 ')
if format_string != "":
format_string = f"\n {format_string}\n"
return format_string
# TODO: Magnum
def num_to_int(n):
return roman.fromRoman(n)
def make_string(n):
if isinstance(n, str):
return n
elif isinstance(n, int):
return roman.toRoman(n)
elif isinstance(n, list):
return f"[{' '.join([make_string(i) for i in n])}]"
else:
raise Exception(n)
class ExpressionStatement(BaseBox):
def __init__(self, expression) -> None:
self.expression = expression
def __repr__(self) -> str:
return self.expression.__repr__()
def eval(self, vtable, ftable, modules):
self.expression.eval(vtable.copy(), ftable.copy(), modules)
return vtable, ftable
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}])"
def eval(self, vtable, ftable, modules):
content = [i.eval(vtable, ftable, modules) for i in self.content]
return content
class DataRangeArray(BaseBox):
def __init__(self, from_value, to_value) -> None:
self.from_value = from_value
self.to_value = to_value
def __repr__(self) -> str:
content_string = rep_join([self.from_value, self.to_value])
return f"RangeArray([{content_string}])"
def eval(self, vtable, ftable, modules):
content = list(range(self.from_value.eval(), self.to_value.eval()))
return content
class String(BaseBox):
def __init__(self, value) -> None:
self.value = value
def __repr__(self):
return f"String({self.value})"
def eval(self, *_):
return self.value
class Numeral(BaseBox):
def __init__(self, value) -> None:
self.value = value
def __repr__(self):
return f"Numeral({self.value})"
def eval(self, *_):
return num_to_int(self.value)
class Bool(BaseBox):
def __init__(self, value) -> None:
self.value = value
def __repr__(self):
return f"Bool({self.value})"
def eval(self, *_):
return self.value
class ModuleCall(BaseBox):
def __init__(self, module_name) -> None:
self.module_name = 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})"
def eval(self, vtable, *_):
return vtable[self.name]
class Designa(BaseBox):
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, ftable, modules):
vtable[self.id.name] = self.value.eval(
vtable.copy(), ftable.copy(), modules
)
return vtable, ftable
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["ERUMPE"] = 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_MINUS":
return left < right
case "KEYWORD_PLUS":
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["ERUMPE"]:
break
if vtable["ERUMPE"]:
vtable["ERUMPE"] = 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["ERUMPE"]:
break
if vtable["ERUMPE"]:
vtable["ERUMPE"] = 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 "AUDI_NUMERUS":
return num_to_int(input())
case "DICE":
print(' '.join(make_string(i) for i in parameters))
return None
case "ERUMPE":
vtable["ERUMPE"] = True
return None
case "FORTIS_NUMERUS":
# TODO: 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 __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 = {"ERUMPE": False}
ftable = {}
modules = [module.module_name for module in self.modules]
for statement in self.statements:
vtable, ftable = statement.eval(vtable, ftable, modules)