def eval_eq(ast, env): assert_exp_length(ast, 3) if type(evaluate(ast[1], env)) == list or type(evaluate(ast[2], env)) == list: return False else: return evaluate(ast[1], env) == evaluate(ast[2], env)
def cons(ast, env): assert_exp_length(ast, 2) first = evaluate(ast[0], env) rest = assert_list(ast[1], env) return [first] + rest
def cond(ast, env): assert_exp_length(ast, 3) if evaluate(ast[0], env): return evaluate(ast[1], env) else: return evaluate(ast[2], env)
def head(ast, env): assert_exp_length(ast, 1) rest = assert_list(ast[0], env) if len(rest) > 0: return rest[0] else: raise LispError("Can't get head of empty list.")
def tail(ast, env): assert_exp_length(ast, 1) rest = assert_list(ast[0], env) if len(rest) > 1: return rest[1:] else: return []
def eval_rhead(ast, env): assert_exp_length(ast, 2) ls = evaluate(ast[1], env) if not is_list(ls): raise LispError('The argument of rhead should be a list.') elif len(ls) == 0: raise LispError('And empty list has no reverse head.') return ls[-1]
def eval_print(ast, env): """Allow Slow Loris to use the Python print to standard out""" assert_exp_length(ast, 3) s = evaluate(ast[1], env) if type(s) == str and len(s) > 0 and s[0] == '"' and s[-1] == '"': print(s[1:-1]) else: print(s) return evaluate(ast[2], env)
def eval_print(ast, env): """Allow Slow Loris to use the Python print to standard out""" assert_exp_length(ast, 3) s = evaluate(ast[1], env) if type(s) == str and len(s) > 0 and s[0] == '"' and s[-1] == '"': print(s[1: -1]) else: print(s) return evaluate(ast[2], env)
def eq(ast, env): assert_exp_length(ast, 2) a = evaluate(ast[0], env) if not is_atom(a): return False b = evaluate(ast[1], env) if not is_atom(b): return False return a == b
def source(ast, env): assert_exp_length(ast, 1) symbol = ast[0] assert_symbol(symbol) if symbol in forms: return "<form/%s>" % symbol else: val = env.lookup(symbol) if is_closure(val): return "(lambda %s %s)" % (unparse(val.params), unparse(val.body)) else: return val
def evaluate(ast, env): """Evaluate an Abstract Syntax Tree in the specified environment.""" if is_boolean(ast): return ast elif is_integer(ast): return ast elif ast[0] in ['+', '-', '*', '/']: return eval_math(ast, env) elif is_list(ast): if ast[0] == "atom": return is_atom(evaluate(ast[1], env)) #return is_atom(ast[1]) elif ast[0] == "quote": return ast[1] elif ast[0] == "eq": assert_exp_length(ast, 3) v1 = evaluate(ast[1], env) v2 = evaluate(ast[2], env) if not is_atom(v1) or not is_atom(v2): return False else: return (v1 == v2)
def eval_lambda(ast, env): assert_exp_length(ast, 3) if not is_list(ast[1]): raise LispError('non-list: %s' % unparse(ast[1])) return Closure(env, ast[1], ast[2])
def eval_if(ast, env): assert_exp_length(ast, 4) return evaluate(ast[2] if evaluate(ast[1], env) else ast[3], env)
def eval_eq(ast, env): assert_exp_length(ast, 3) args = [evaluate(x, env) for x in ast[1:]] return is_atom(args[0]) and args[0] == args[1]
def eval_atom(ast, env): assert_exp_length(ast, 2) return is_atom(evaluate(ast[1], env))
def eval_exit(ast): assert_exp_length(ast, 1) exit()
def eval_tail(ast, env): assert_exp_length(ast, 2) args = [evaluate(x, env) for x in ast[1:]] return args[0][1:]
def eval_atom(ast, env): assert_exp_length(ast, 2) return type(evaluate(ast[1], env)) != list
def eval_cons(ast, env): assert_exp_length(ast, 3) ls = evaluate(ast[2], env) if not is_list(ls): raise LispError('The second argument of cons should be a list.') return [evaluate(ast[1], env)] + ls
def eval_quote(ast, env): """Evaluate a quoted list""" assert_exp_length(ast, 2) return ast[1]
def eval_cons(ast, env): assert_exp_length(ast, 3) args = [evaluate(x, env) for x in ast[1:]] return [args[0]] + args[1]
def eval_set(ast, env): assert_exp_length(ast, 3) env.set_overwrite(ast[1], evaluate(ast[2], env)) return ast[1]
def eval_head(ast, env): assert_exp_length(ast, 2) args = [evaluate(x, env) for x in ast[1:]] if len(args[0]) == 0: raise LispError('empty list') return args[0][0]
def evaluate(ast, env): """Evaluate an Abstract Syntax Tree in the specified environment.""" print ast, env.variables # otherwise, it will be a function op = ast[0] args = ast[1:] # Simple Evaluation # quote evaluation if op == "quote": assert_exp_length(args, 1) return evaluate(args[0], env) # atom function if op == "atom": assert_exp_length(args, 1) return is_atom(evaluate(args[0], env)) # arithematic evaluation if op in ['+', '-', '*', '/', 'mod', '>']: assert_exp_length(args, 2) arg1 = evaluate(args[0], env) arg2 = evaluate(args[1], env) if not (is_integer(arg1) and is_integer(arg2)): raise LispError("Arguments of arithmetic operator should be numbers") return eval_arithmetic(op, arg1, arg2) # define evaluation if op == "define": try: assert_exp_length(args, 2) except LispError: raise LispError("Wrong number of arguments") var_name = args[0] var_value = evaluate(args[1], env) if not is_symbol(var_name): raise LispError("non-symbol: %s" % var_name) env.set(var_name, var_value) return var_name # equal evaluation if op == "eq": eval_arg1 = evaluate(args[0], env) eval_arg2 = evaluate(args[1], env) return is_atom(eval_arg1) and is_atom(eval_arg2) and eval_arg1 == eval_arg2 # Complex Evaluation # if evaluation if op == "if": assert_exp_length(args, 3) eval_predicate = evaluate(args[0], env) if eval_predicate: return evaluate(args[1], env) else: return evaluate(args[2], env) if op == 'lambda': try: assert_exp_length(args, 2) except LispError: raise LispError("number of arguments") print len(args) lambda_params = args[0] lambda_body = args[1] return Closure(env, lambda_params, lambda_body) if is_closure(op): closure = op assert_exp_length(args, len(closure.params)) new_env = Environment(closure.env.variables.copy()) for n, param in enumerate(closure.params): new_env.set(param, evaluate(args[n], new_env)) return evaluate(closure.body, new_env) # fundamental if is_symbol(ast): print 'is_symbol' try: return evaluate(env.lookup(ast), env) except: if len(ast) == 1: raise LispError("undefined: %s" % ast[0]) else: raise LispError("not a function: %s" % ast[0]) if is_atom(ast): print 'is_atom' return ast if is_list(ast): print 'is_list' return evaluate(map(lambda inner_ast: evaluate(inner_ast, env), ast), env)
def eval_empty(ast, env): assert_exp_length(ast, 2) args = [evaluate(x, env) for x in ast[1:]] return (len(args[0]) == 0)
def eval_quote(ast, env): assert_exp_length(ast, 2) return ast[1]
def eval_empty(ast, env): assert_exp_length(ast, 2) ls = evaluate(ast[1], env) if not is_list(ls): raise LispError('The argument of empty should be a list.') return len(ls) == 0
def empty(ast, env): assert_exp_length(ast, 1) rest = assert_list(ast[0], env) return len(rest) == 0
def guard(ast, env): assert_exp_length(ast, 2) a = assert_int(ast[0], env) b = assert_int(ast[1], env) return op(a, b)