def __call__(self, scope, *args): # if scope.has_key("recur") and scope["recur"] == self: # This is recursion, don't create a new scope # local = scope # else: # Calling scope -> creating scope -> local scope # Clone creation scope so its parent can be set to calling scope creation = Scope() creation.bindings = self.scope.bindings creation.parent = scope # Create a new scope local = Scope(creation) # Bind `recur` to self (to alow for recursion from anonymous functions) local["recur"] = self # Bind each argument to a binding bi = ai = 0 bindings = self.bindings.data[:-1] while bi != len(bindings) and ai != len(bindings): # Optional argument if bindings[bi] == Symbol("?"): if ai >= len(args): if bindings[bi + 1].__class__ == List: # A default value is supplied local[bindings[bi + 1].car().data] = bindings[bi + 1].cdr().car().evaluate(local) else: # Nothing supplied for this optional and no default value local[bindings[bi + 1].data] = List([]) ai -= 1 bi += 1 else: if bindings[bi + 1].__class__ == List: # A default value is supplied, replace with just the symbol local[bindings[bi + 1].car().data] = args[ai].evaluate(scope) else: local[bindings[bi + 1].data] = args[ai].evaluate(scope) bi += 1 # continue # Rest argument elif bindings[bi] == Symbol("&"): if ai == len(args): # raise TypeError("expected at least %d arguments, got %d" % (bi + 1, ai)) local[bindings[bi + 1].data] = List([]) else: local[bindings[bi + 1].data] = List([x.evaluate(scope) for x in args[ai:]] + [[]]) break # Normal argument else: # Too many or too few arguments if bi >= len(bindings) or ai >= len(args): raise TypeError("expected %d arguments, got %d" % (len(bindings), len(args))) local[bindings[bi].data] = args[ai].evaluate(scope) ai += 1 bi += 1 # Evaluate each expression in the body (in local function scope) for expression in self.body[:-1]: expression.evaluate(local) # Return the evaluated last expression return self.body[-1].evaluate(local)