def func(self, scope, args): args = args[0] for i in xrange(len(args)): n = args[i] if not types.is_number(n): raise LispException("argument %d of %s must be number, was %s" % (i + 1, func.__name__, types.type_name(n))) return types.py_to_type(m.reduce_num(reducer, *(n.value for n in args)))
def parse_sig(self, scope, fn, args, signature): if signature == "*": return args out = [] rest = False sigs = signature.split(" ") if sigs[-1] in ["&", "@&"]: rest = sigs[-1] sigs = sigs[:-1] else: if len(sigs) != len(args): raise LispException("%s takes %d arguments, %d given" % (fn, len(sigs), len(args))) for sig in sigs: if not len(args): raise LispException("%s takes %s%d arguments, %d given" % (fn, "at least " if rest else "", len(sigs) + 1, len(out))) if "callable" in sig: sig = sig.replace("callable", "function|macro|primitive") arg = args[0] args = args[1:] if sig[0] == "@": sig = sig[1:] arg = self.rt.eval(scope, arg) if sig != "any": matched = False for t in sig.split("|"): if t.islower(): test = getattr(types, "is_%s" % t) if test(arg): matched = True else: if match_class([arg.__class__], t): matched = True if not matched: raise LispException("argument %d of %s must be %s, was %s" % (len(out) + 1, fn, sig, types.type_name(arg))) out.append(arg) if rest and not len(args): raise LispException("%s takes %s%d arguments, %d given" % (fn, "at least " if rest else "", len(sigs) + 1, len(out))) if rest == "@&": out.append(map(lambda x: self.rt.eval(scope, x), args)) elif rest == "&": out.append(args) return out
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
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
def macro(self, scope, args): sig = list(args[0]) body = types.mklist(args[1]) for arg in sig: if not types.is_symbol(arg): raise LispException("argument 1 of lambda must be a list of symbols, found %s" % types.type_name(arg)) return types.mkmacro(sig, body, scope)