# 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):
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:
# 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
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)
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"""