diff options
| -rw-r--r-- | runner.py | 33 | ||||
| -rw-r--r-- | tokens.py | 37 | 
2 files changed, 48 insertions, 22 deletions
| @@ -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") @@ -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(): | 
