def execute(self, scope, sexp): if types.is_atomic(sexp): return self.eval(scope, sexp) if types.is_nil(sexp): return sexp func = self.eval(scope, sexp.car) args = list(sexp.cdr) if types.is_primitive(func): return self.invoke(scope, func, args) if types.is_macro(func): return self.eval(scope, self.invoke(scope, func, args)) if types.is_function(func): return self.invoke(scope, func, (self.eval(scope, arg) for arg in args)) raise LispException("%s is not callable" % repr(func), sexp)
def invoke(self, scope, func, args, tailrec = False): args = list(args) if types.is_primitive(func): return func.invoke(scope, args) try: rest = list((i.value for i in func.sig)).index("&") except ValueError: rest = -1 if len(args) != len(func.sig): raise LispException("%s takes %d arguments, %d given" % (types.type_name(func), len(func.sig), len(args))) else: if len(args) < rest: raise LispException("%s takes at least %d arguments, %d given" % (types.type_name(func), rest, len(args))) closure = scope if tailrec else Scope(func, func.scope) for i in xrange(len(args)): if func.sig[i].value == "&": closure.define(func.sig[rest+1].value, types.mklist(args[rest:])) rest = -1 break else: closure.define(func.sig[i].value, args[i]) if rest >= 0: closure.define(func.sig[rest+1].value, types.nil) rv = types.nil for sexp in func.value: rv = self.execute(closure, sexp) return rv