aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormryouse2022-05-11 03:01:27 +0000
committermryouse2022-05-11 03:01:27 +0000
commitd372f1cca2ae357feb2d4524087dd15646356faa (patch)
tree909b7e7848e1d36527e947fc74519d545239125e
parent99a327a942028ec33e746a7ffbb2a3731cb4a370 (diff)
refactor: only evaluate expressions as needed
-rw-r--r--runner.py33
-rw-r--r--tokens.py37
2 files changed, 48 insertions, 22 deletions
diff --git a/runner.py b/runner.py
index 1023473..7de2666 100644
--- a/runner.py
+++ b/runner.py
@@ -7,6 +7,25 @@ def peek(inp):
return None
return inp[0]
+def evaluate_expression(expr):
+ if not expr.symbol.name in STD:
+ raise Exception(f"no such symbol: {expr.symbol.name}")
+ this_func = STD[expr.symbol.name]
+
+ # try to match the signature
+ in_sig = expr.in_sig()
+ if in_sig in this_func:
+ ret = this_func[expr.in_sig()].impl(*(expr.args))
+ return ret
+
+ # evaluate inner expressions, if possible/necessary
+ for idx, arg in enumerate(expr.args):
+ if arg.type_ == NebType.EXPR:
+ expr.args[idx] = evaluate_expression(arg)
+ return evaluate_expression(expr)
+
+ raise Exception(f"'{expr.symbol.name}' called with unknown signature: '{expr.in_sig()}'")
+
def evaluate(items, pop):
nxt = peek(items)
if nxt is None:
@@ -19,19 +38,7 @@ def evaluate(items, pop):
this_func = STD[nxt.name]
return evaluate(items[1:], this_func[list(this_func.keys())[0]].impl) # TODO show all
elif isinstance(nxt, NebExpression):
- if not nxt.symbol.name in STD:
- raise Exception(f"no such symbol: {nxt.symbol.name}")
- this_func = STD[nxt.symbol.name]
-
- # evaluate inner expressions
- for idx, arg in enumerate(nxt.args):
- if isinstance(arg, NebExpression):
- nxt.args[idx] = evaluate([arg], pop)
-
- if nxt.maybe_sig() not in this_func:
- raise Exception(f"'{nxt.symbol.name}' called with unknown signature: '{nxt.maybe_sig()}'")
- ret = this_func[nxt.maybe_sig()].impl(*(nxt.args))
- return evaluate(items[1:], ret)
+ return evaluate(items[1:], evaluate_expression(nxt))
else:
raise Exception("expected a literal or an expression")
diff --git a/tokens.py b/tokens.py
index 38e669c..cc8e7a7 100644
--- a/tokens.py
+++ b/tokens.py
@@ -40,10 +40,12 @@ class NebSeparator():
pass
class NebOpen(NebSeparator):
- pass
+ def __str__(self):
+ return "("
class NebClose(NebSeparator):
- pass
+ def __str__(self):
+ return ")"
class NebSymbol(NebToken):
@@ -51,21 +53,38 @@ class NebSymbol(NebToken):
super().__init__(NebType.SYMBOL)
self.name = name
+ def __str__(self):
+ return f"'{self.name}"
+
class NebExpression(NebToken):
def __init__(self, symbol, args):
super().__init__(NebType.EXPR)
self.symbol = symbol
self.args = args
+ self.returns = None
+
+ def set_returns(self, returns):
+ self.returns = returns
- def maybe_sig(self):
- out = []
+ def __str__(self):
+ out = f"({self.symbol}"
for arg in self.args:
- if isinstance(arg, NebLiteral):
- out.append(":" + arg.type_.name.lower())
- else:
- raise Exception("expressions must have a list of literals") #TODO not true
- return " ".join(out)
+ out += f" {arg}"
+ out += f") <{self.type_}> -> <{self.out_sig()}>"
+ return out
+
+ def in_sig(self):
+ return " ".join(f":{arg.type_.name.lower()}" for arg in self.args)
+
+ def out_sig(self):
+ if self.returns is None:
+ return "?"
+ else:
+ return ":" + self.returns.lower()
+
+ def sig(self):
+ return (self.in_sig() + " > " + self.out_sig()).strip()
class NebFunction():