From 22c38c4554ba46cf1aec0fced3b61fa977f4c5e4 Mon Sep 17 00:00:00 2001 From: Jorge Gorbe Date: Mon, 13 Jan 2014 14:48:03 +0100 Subject: [PATCH] simplified cond and the eval loop --- lisp0.py | 70 +++++++++++++++++++------------------------------------- 1 file changed, 23 insertions(+), 47 deletions(-) diff --git a/lisp0.py b/lisp0.py index edce63a..80c4760 100644 --- a/lisp0.py +++ b/lisp0.py @@ -83,12 +83,18 @@ class Environment: # helper lisp-list functions +def find(pred, l): + while not is_nil(l): + x = car(l) + if pred(x): return x + l = cdr(l) + return Value.NIL + def foldl(func, initial, l): result = initial - cur = l - while not is_nil(cur): - result = func(result, car(cur)) - cur = cdr(cur) + while not is_nil(l): + result = func(result, car(l)) + l = cdr(l) return result def foldr(func, initial, l): @@ -126,19 +132,9 @@ def lisp_quote(args, env): assert(is_nil(cdr(args))) return car(args) +# empty function used as a marker, the code is inlined into lisp_eval def lisp_cond(args, env): - while not is_nil(args): - c = car(args) - assert(is_pair(c)) - if is_true(lisp_eval(car(c), env)): - actions = cdr(c) - while not is_nil(actions): - result = lisp_eval(car(actions), env) - actions = cdr(actions) - return result - args = cdr(args) - return Value.NIL - + pass def quasiquote_expression(expr, env): """returns a tuple with: @@ -250,14 +246,11 @@ global_env = Environment() # in order to optimize tail calls def lisp_eval(e, env): """evals an expression""" - result = None - ended = False - while not ended: - # print "eval: %s"%str(e) - if is_symbol(e): - result = env[e.v] - ended = True - elif is_pair(e): + while True: + if e is None: return Value.NIL + elif is_symbol(e): return env[e.v] + elif not is_pair(e): return e + else: f = lisp_eval(car(e), env) args = cdr(e) # inlined body of the apply function @@ -266,26 +259,14 @@ def lisp_eval(e, env): if type(f) == types.FunctionType: # TEST: special case for cond, the old lisp_cond function is only used as a marker, but evaluated inline if f == lisp_cond: - action = None - while not is_nil(args): - c = car(args) - assert(is_pair(c)) - if is_true(lisp_eval(car(c), env)): - action = cadr(c) - break - args = cdr(args) - if action is not None: - e = action - else: - result = Value.NIL - ended = True + satisfied = find(lambda x: is_true(lisp_eval(car(x), env)), args) + if not is_nil(satisfied): + e = cadr(satisfied) else: - result = f(args, env) - ended = True + return f(args, env) + elif f.t == "macro": - expansion = lisp_apply(f.v, args, env) - #print "macro expansion:", expansion - e = expansion + e = lisp_apply(f.v, args, env) else: formals, body, environment = f.v new_env = Environment(environment) @@ -303,11 +284,6 @@ def lisp_eval(e, env): e = body env = new_env - else: - result = e - ended = True - # print "result: %s"%result - return result def lisp_apply(f, args, env): """applies an argument list to a function or special form""" -- 2.34.1