""" sample use: l.eval(("seq", ("set", "n", 7), ("set", "f", 1), ("while", (">", "n", 1), ("seq", ("set", "f", ("*", "f", "n")), ("set", "n", ("-", "n", 1)))), ("print", "f"))) 5040 """ import functools, operator arith = { "+": operator.add, "-": operator.sub, "*": operator.mul, "/": operator.truediv, "%": operator.mod, "^": operator.pow, "and": operator.and_, "or": operator.or_, "xor": operator.xor } compa = { "==": operator.eq, "<": operator.lt, ">": operator.gt, "!=": operator.ne, "<=": operator.le, ">=": operator.ge } mem = {} def reduce(f, vals): v = vals[0] for x in vals[1:]: v = f(v, x) return v def eval(form): if type(form) == int or type(form) == float: return form if type(form) == str: if form in mem: return mem[form] else: raise ValueError("unknown variable " + form) if type(form) == tuple: if form == (): raise ValueError("empty") op = form[0] if op in arith: return reduce(arith[op], tuple((eval(f) for f in form[1:]))) if op in compa: return compa[op](eval(form[1]), eval(form[2])) if op == "neg": v = eval(form[1]) if type(v) == bool: return not v if type(v) == int: return - v raise ValueError("wrong type for neg") if op == "set": mem[form[1]] = eval(form[2]) return mem[form[1]] if op == "seq": v = 0 for f in form[1:]: v = eval(f) return v if op == "print": v = eval(form[1]) print(v) return v if op == "if": if eval(form[1]): return eval(form[2]) else: return eval(form[3]) if op == "while": v = 0 while eval(form[1]): v = eval(form[2]) return v if op == "read": while True: return readvalue() raise ValueError("unknown " + str(form)) def readvalue(): while True: x = input("? ") if x: break if x == "true": return True if x == "false": return False if x.isdecimal(): return int(x) return x f1 = ("*", 3, 4, 5) f2 = ("*", ("+", 1, 2), ("*", 2, 2), ("+", 1, ("*", 2, 2))) f3 = ("<", f1, f2) f4 = ("set", "x", f2) f5 = ("seq", ("set", "x", 17), ("set", "y", 3), ("print", "x"), ("*", "x", "y"))