aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormryouse2022-06-09 23:26:49 +0000
committermryouse2022-06-09 23:26:49 +0000
commit5da9b0bb7362be01639892acfac1c98c2b3b8b0b (patch)
tree5d22f9473d8a4fa4eda913f48b5bf13b1e86c255
parentd8d42ddebd92b9c0211f7ae452d4c3d70c4684ec (diff)
bugfix: can't rely on the symbol name when symbols can be passed as arguments
-rw-r--r--interpreter.py149
1 files changed, 94 insertions, 55 deletions
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)