Beispiel #1
0
 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)