From d372f1cca2ae357feb2d4524087dd15646356faa Mon Sep 17 00:00:00 2001 From: mryouse Date: Wed, 11 May 2022 03:01:27 +0000 Subject: refactor: only evaluate expressions as needed --- runner.py | 33 ++++++++++++++++++++------------- tokens.py | 37 ++++++++++++++++++++++++++++--------- 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(): -- cgit v1.2.3