🐐 First order functions

This commit is contained in:
2026-04-21 18:12:15 +02:00
parent db5b7bf144
commit 693054491f
18 changed files with 407 additions and 46 deletions

View File

@@ -144,6 +144,8 @@ def make_string(val, magnvm=False, svbnvlla=False) -> str:
for k, v in val.value().items()
)
return "{" + inner + "}"
elif isinstance(val, ValFunc):
return "FVNCTIO"
else:
raise CentvrionError(f"Cannot display {val!r}")
@@ -577,6 +579,31 @@ class Defini(Node):
return vtable, ValNul()
class Fvnctio(Node):
def __init__(self, parameters: list[ID], statements: list[Node]) -> None:
self.parameters = parameters
self.statements = statements
def __eq__(self, other):
return (type(self) == type(other)
and self.parameters == other.parameters
and self.statements == other.statements)
def __repr__(self) -> str:
parameter_string = f"parameters([{rep_join(self.parameters)}])"
statements_string = f"statements([{rep_join(self.statements)}])"
fvn_string = rep_join([parameter_string, statements_string])
return f"Fvnctio({fvn_string})"
def print(self):
params = ", ".join(p.print() for p in self.parameters)
body = "\n".join(s.print() for s in self.statements)
return f"FVNCTIO ({params}) VT {{\n{body}\n}}"
def _eval(self, vtable):
return vtable, ValFunc(self.parameters, self.statements)
class Redi(Node):
def __init__(self, values: list[Node]) -> None:
self.values = values
@@ -954,32 +981,36 @@ class PerStatement(Node):
class Invoca(Node):
def __init__(self, name, parameters) -> None:
self.name = name
def __init__(self, callee, parameters) -> None:
self.callee = callee
self.parameters = parameters
def __eq__(self, other):
return type(self) == type(other) and self.name == other.name and self.parameters == other.parameters
return (type(self) == type(other)
and self.callee == other.callee
and self.parameters == other.parameters)
def __repr__(self) -> str:
parameters_string = f"parameters([{rep_join(self.parameters)}])"
invoca_string = rep_join([self.name, parameters_string])
invoca_string = rep_join([self.callee, parameters_string])
return f"Invoca({invoca_string})"
def print(self):
args = ", ".join(p.print() for p in self.parameters)
return f"INVOCA {self.name.print()} ({args})"
return f"INVOCA {self.callee.print()} ({args})"
def _eval(self, vtable):
params = [p.eval(vtable)[1] for p in self.parameters]
if self.name.name not in vtable:
raise CentvrionError(f"Undefined function: {self.name.name}")
func = vtable[self.name.name]
vtable, func = self.callee.eval(vtable)
if not isinstance(func, ValFunc):
raise CentvrionError(f"{self.name.name} is not a function")
callee_desc = (self.callee.name
if isinstance(self.callee, ID) else "expression")
raise CentvrionError(f"{callee_desc} is not a function")
if len(params) != len(func.params):
callee_desc = (self.callee.name
if isinstance(self.callee, ID) else "FVNCTIO")
raise CentvrionError(
f"{self.name.name} expects {len(func.params)} argument(s), got {len(params)}"
f"{callee_desc} expects {len(func.params)} argument(s), got {len(params)}"
)
func_vtable = vtable.copy()
for i, param in enumerate(func.params):