aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interpreter.py28
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