Exemplo n.º 1
0
  def cond(self, scope, args):
    for i in xrange(len(args)):
      sexp = args[i]
      if not types.is_list(sexp):
        raise LispException("argument %d of cond must be list, is %s" %
                            (i + 1, types.type_name(sexp)))
      if types.is_nil(sexp) or types.is_nil(sexp.cdr):
        raise LispException("argument %d of cond must have a length of >= 2" % (i + 1))
    for rule in args:
      test = self.rt.eval(scope, rule.car)
      if test != types.true and test != types.false:
        raise LispException("expr %s does not evaluate to a boolean" % repr(rule.car))
      if test == types.true:
        for sexp in rule.cdr:
          rv = self.rt.eval(scope, sexp)
        return rv

    return types.nil
Exemplo n.º 2
0
Arquivo: rt.py Projeto: bodil/lolisp
 def eval(self, scope, exp):
   """
   If exp is a list, execute it as a function call.
   If exp is a symbol, resolve it.
   Else, return it as is.
   """
   if types.is_list(exp) and not types.is_nil(exp):
     return self.execute(scope, exp)
   elif types.is_symbol(exp):
     return self.lookup(scope, exp)
   else:
     return exp
Exemplo n.º 3
0
  def _unquote(self, scope, sexp):
    if types.is_list(sexp) and not types.is_nil(sexp):
      if types.is_symbol(sexp.car) and sexp.car.value == "unquote":
        return self.rt.eval(scope, sexp.cdr.car)

      out = types.nil
      for el in sexp:
        if is_splice(el):
          for splice in self.rt.eval(scope, el.cdr.car):
            out = types.conj(out, splice)
        else:
          out = types.conj(out, self._unquote(scope, el))
      return out
    else:
      return sexp
Exemplo n.º 4
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.º 5
0
Arquivo: load.py Projeto: bodil/lolisp
def load(stream):
  stack = []
  top = types.nil
  last = None
  lexer = Lexer(stream)

  for token in lexer:
    if token["type"] == "lparen":
      stack.append(top)
      if last and last["type"] in ["quote", "unquote", "unquote-splice", "deref"]:
        top = types.cons(last["type"], types.nil)
      else:
        top = types.nil
    elif token["type"] == "rparen":
      if len(stack) == 0:
        raise ParserError("rparen without matching lparen", token)
      if not types.is_nil(top) and top.car in ["quote", "unquote", "unquote-splice", "deref"]:
        func = types.mksymbol(top.car)
        sym = top.cdr
        sym = types.cons(sym, types.nil)
        top = types.cons(func, sym)
      top = types.conj(stack.pop(), top)
    elif token["type"] in ["quote", "unquote"]:
      pass
    elif token["type"] == "deref":
      if last and last["type"] == "unquote":
        token["type"] = "unquote-splice"
    else:
      if last and last["type"] in ["quote", "unquote", "unquote-splice", "deref"]:
        sexp = types.cons(types.token_to_type(token), types.nil)
        sexp = types.cons(types.mksymbol(last["type"]), sexp)
        top = types.conj(top, sexp)
      else:
        top = types.conj(top, types.token_to_type(token))
    last = token

  if len(stack):
    raise ParserError("lparen without matching rparen", last)

  return top
Exemplo n.º 6
0
def is_splice(sexp):
  return (not types.is_nil(sexp)) and types.is_list(sexp) and types.is_symbol(sexp.car) and sexp.car.value == "unquote-splice"
Exemplo n.º 7
0
 def cdr(self, scope, args):
   if types.is_nil(args[0]):
     return types.nil
   return args[0].cdr