From 0c8434f6786936fea5e638736e9ddd0fd0314fd0 Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 19 May 2022 03:55:12 +0000 Subject: support for global variables --- interpreter.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) 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 -- cgit v1.2.3