diff options
Diffstat (limited to 'interpreter.py')
| -rw-r--r-- | interpreter.py | 28 | 
1 files changed, 28 insertions, 0 deletions
| diff --git a/interpreter.py b/interpreter.py index fd327f9..9a375d0 100644 --- a/interpreter.py +++ b/interpreter.py @@ -1,5 +1,6 @@  from parser import Expr +ENVIRONMENT = {}  def interpret(exprs):      ret = None @@ -10,6 +11,13 @@ def interpret(exprs):  def evaluate(expr):      if isinstance(expr, Expr.Literal):          return expr.value +    elif isinstance(expr, Expr.Symbol): +        # defined symbols will evaluate to their expression, +        # undefined will return their own name +        # TODO this is bad +        if not expr.name in ENVIRONMENT: +            raise Exception(f"no such symbol: {expr}") +        return interpretEnv(expr, ENVIRONMENT[expr.name])      elif expr.symbol.name == "not":          return interpretNot(expr)      elif expr.symbol.name in ("*", "/"): @@ -33,6 +41,11 @@ def evaluate(expr):      elif expr.symbol.name == "print":          return interpretPrint(expr) +    # global variables +    elif expr.symbol.name == "def": +        return interpretDef(expr) + +      else:          raise Exception(f"unable to evaluate: {expr}") @@ -160,3 +173,18 @@ def interpretPrint(expr):          raise Exception("'print' takes zero or one argument")      return None  # print returns nothing + +def interpretDef(expr): +    if len(expr.args) != 2: +        raise Exception("'def' requires a name and an expression") +    if not isinstance(expr.args[0], Expr.Symbol): +        raise Exception("'def' requires a string literal as a name") +    name = expr.args[0].name  # NOTE: we are not evaluating the name!! +    if not isinstance(name, str): +        raise Exception("'def' requires a string literal as a name") + +    ENVIRONMENT[name] = expr.args[1] +    return None + +def interpretEnv(expr, env_expr): +    return evaluate(env_expr)  # TODO more than this | 
