Exemplo n.º 1
0
Arquivo: rt.py Projeto: bodil/lolisp
  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)
Exemplo n.º 2
0
Arquivo: rt.py Projeto: bodil/lolisp
  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