From 5da9b0bb7362be01639892acfac1c98c2b3b8b0b Mon Sep 17 00:00:00 2001 From: mryouse Date: Thu, 9 Jun 2022 23:26:49 +0000 Subject: bugfix: can't rely on the symbol name when symbols can be passed as arguments --- interpreter.py | 149 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 94 insertions(+), 55 deletions(-) (limited to 'interpreter.py') diff --git a/interpreter.py b/interpreter.py index 67a6682..299dde8 100644 --- a/interpreter.py +++ b/interpreter.py @@ -169,82 +169,121 @@ def interpretEq(symbol, args, env): GLOBALS.register("eq?", Builtin(interpretEq, 2)) -def interpretComparison(symbol, args, env): +def interpretGreaterThan(symbol, args, env): left = evaluate(args[0], env) if not (isinstance(left, Int) or isinstance(left, Float)): raise InterpretPanic(symbol, "first argument must be a :number", left) right = evaluate(args[1], env) if not (isinstance(right, Int) or isinstance(right, Float)): raise InterpretPanic(symbol, "second argument must be a :number", right) + return Bool(left.value > right.value) - if symbol.name == ">": - return Bool(left.value > right.value) - elif symbol.name == ">=": - return Bool(left.value >= right.value) - elif symbol.name == "<": - return Bool(left.value < right.value) - elif symbol.name == "<=": - return Bool(left.value <= right.value) - -GLOBALS.register(">", Builtin(interpretComparison, 2)) -GLOBALS.register(">=", Builtin(interpretComparison, 2)) -GLOBALS.register("<", Builtin(interpretComparison, 2)) -GLOBALS.register("<=", Builtin(interpretComparison, 2)) - -def interpretTerm(symbol, args, env): +GLOBALS.register(">", Builtin(interpretGreaterThan, 2)) + +def interpretGreaterThanEqual(symbol, args, env): + left = evaluate(args[0], env) + if not (isinstance(left, Int) or isinstance(left, Float)): + raise InterpretPanic(symbol, "first argument must be a :number", left) + right = evaluate(args[1], env) + if not (isinstance(right, Int) or isinstance(right, Float)): + raise InterpretPanic(symbol, "second argument must be a :number", right) + return Bool(left.value >= right.value) + +GLOBALS.register(">=", Builtin(interpretGreaterThanEqual, 2)) + +def interpretLessThan(symbol, args, env): + left = evaluate(args[0], env) + if not (isinstance(left, Int) or isinstance(left, Float)): + raise InterpretPanic(symbol, "first argument must be a :number", left) + right = evaluate(args[1], env) + if not (isinstance(right, Int) or isinstance(right, Float)): + raise InterpretPanic(symbol, "second argument must be a :number", right) + return Bool(left.value < right.value) + +GLOBALS.register("<", Builtin(interpretLessThan, 2)) + +def interpretLessThanEqual(symbol, args, env): + left = evaluate(args[0], env) + if not (isinstance(left, Int) or isinstance(left, Float)): + raise InterpretPanic(symbol, "first argument must be a :number", left) + right = evaluate(args[1], env) + if not (isinstance(right, Int) or isinstance(right, Float)): + raise InterpretPanic(symbol, "second argument must be a :number", right) + return Bool(left.value <= right.value) + +GLOBALS.register("<=", Builtin(interpretLessThanEqual, 2)) + +def interpretAddition(symbol, args, env): if len(args) < 1: raise InterpretPanic(symbol, "requires at least one argument") - res = None + res = 0 for arg in args: ev = evaluate(arg, env) if not (isinstance(ev, Int) or isinstance(ev, Float)): raise InterpretPanic(symbol, "argument must be a :number", ev) - if res is None: - res = ev.value - elif symbol.name == "+": - res += ev.value - elif symbol.name == "-": - res -= ev.value + res += ev.value if isinstance(res, float): return Float(res) else: return Int(res) -GLOBALS.register("+", Builtin(interpretTerm)) -GLOBALS.register("-", Builtin(interpretTerm)) - -def interpretFactor(symbol, args, env): - if symbol.name == "/": - num = evaluate(args[0], env) - if not (isinstance(num, Int) or isinstance(num, Float)): - raise InterpretPanic(symbol, "numerator must be a :number", num) - denom = evaluate(args[1], env) - if not (isinstance(denom, Int) or isinstance(denom, Float)): - raise InterpretPanic(symbol, "denominator must be a :number", denom) - ret = num.value / denom.value - if int(ret) == ret: - return Int(int(ret)) - else: - return Float(ret) +GLOBALS.register("+", Builtin(interpretAddition)) + +def interpretSubtraction(symbol, args, env): + if len(args) < 1: + raise InterpretPanic(symbol, "requires at least one argument") + first = evaluate(args[0], env) + if not (isinstance(first, Int) or isinstance(first, Float)): + raise InterpretPanic(symbol, "argument must be a :number", first) + if len(args) == 1: + res = -first.value else: - if len(args) < 2: - raise InterpretPanic(symbol, "requires at least two arguments") - first = evaluate(args[0], env) - if not (isinstance(first, Int) or isinstance(first, Float)): - raise InterpretPanic(symbol, "argument must be a :number", first) res = first.value - for arg in args[1:]: - tmp = evaluate(arg, env) - if not (isinstance(tmp, Int) or isinstance(tmp, Float)): - raise InterpretPanic(symbol, "argument must be a :number", tmp) - res = res * tmp.value - if isinstance(res, float): - return Float(res) - else: - return Int(res) + for arg in args[1:]: + ev = evaluate(arg, env) + if not (isinstance(ev, Int) or isinstance(ev, Float)): + raise InterpretPanic(symbol, "argument must be a :number", ev) + res -= ev.value + if isinstance(res, float): + return Float(res) + else: + return Int(res) + +GLOBALS.register("-", Builtin(interpretSubtraction)) + +def interpretMultiplication(symbol, args, env): + if len(args) < 2: + raise InterpretPanic(symbol, "requires at least two arguments") + first = evaluate(args[0], env) + if not (isinstance(first, Int) or isinstance(first, Float)): + raise InterpretPanic(symbol, "argument must be a :number", first) + res = first.value + for arg in args[1:]: + tmp = evaluate(arg, env) + if not (isinstance(tmp, Int) or isinstance(tmp, Float)): + raise InterpretPanic(symbol, "argument must be a :number", tmp) + res = res * tmp.value + if isinstance(res, float): + return Float(res) + else: + return Int(res) + +GLOBALS.register("*", Builtin(interpretMultiplication)) + +def interpretDivision(symbol, args, env): + num = evaluate(args[0], env) + if not (isinstance(num, Int) or isinstance(num, Float)): + raise InterpretPanic(symbol, "numerator must be a :number", num) + denom = evaluate(args[1], env) + if not (isinstance(denom, Int) or isinstance(denom, Float)): + raise InterpretPanic(symbol, "denominator must be a :number", denom) + ret = num.value / denom.value + if int(ret) == ret: + return Int(int(ret)) + else: + return Float(ret) -GLOBALS.register("*", Builtin(interpretFactor)) -GLOBALS.register("/", Builtin(interpretFactor, 2)) +GLOBALS.register("/", Builtin(interpretDivision, 2)) def interpretNot(symbol, args, env): res = evaluate(args[0], env) -- cgit v1.2.3