/* eval3.c Copyright (C) 1991-2007 Codemist Ltd */ /* * Interpreter (part 3). * Implementations of special forms (interpreted versions). * */ /* * This code may be used and modified, and redistributed in binary * or source form, subject to the "CCL Public License", which should * accompany it. This license is a variant on the BSD license, and thus * permits use of code derived from this in either open and commercial * projects: but it does require that updates to this code be made * available back to the originators of the package. * Before merging other code in with this or linking this code * with other packages or libraries please check that the license terms * of the other material are compatible with those of this. */ /* Signature: 3e7f958c 13-Apr-2008 */ #include "headers.h" #ifndef COMMON static Lisp_Object plus_fn(Lisp_Object args, Lisp_Object env) { Lisp_Object nil = C_nil; Lisp_Object r; if (!consp(args)) return fixnum_of_int(0); /* (plus) => 0 */ stackcheck2(0, args, env); push2(args, env); r = qcar(args); r = eval(r, env); pop2(env, args); errexit(); args = qcdr(args); while (consp(args)) { Lisp_Object w; push3(env, args, r); w = qcar(args); w = eval(w, env); pop(r); errexitn(2); if (is_fixnum(r) && is_fixnum(w)) { int32_t c = int_of_fixnum(r) + int_of_fixnum(w); int32_t w1 = c & fix_mask; if (w1 == 0 || w1 == fix_mask) r = fixnum_of_int(c); else r = plus2(r, w); } else r = plus2(r, w); errexitn(2); pop2(args, env); args = qcdr(args); } return onevalue(r); } static Lisp_Object times_fn(Lisp_Object args, Lisp_Object env) { Lisp_Object nil = C_nil; Lisp_Object r; if (!consp(args)) return fixnum_of_int(1); /* (times) => 1 */ stackcheck2(0, args, env); push2(args, env); r = qcar(args); r = eval(r, env); pop2(env, args); errexit(); args = qcdr(args); while (consp(args)) { Lisp_Object w; push3(env, args, r); w = qcar(args); w = eval(w, env); pop(r); errexitn(2); r = times2(r, w); pop2(args, env); errexit(); args = qcdr(args); } return onevalue(r); } static Lisp_Object list_fn(Lisp_Object args, Lisp_Object env) { Lisp_Object nil = C_nil; Lisp_Object w1, w2, w3, r = nil; /* * I am going to write out the cases of list with 0, 1, 2 or 3 * args specially here, since I expect them to be the more common ones * and I am generally jumpy about performance. It seems a bit nasty * to get to an interpreted call to list anyway. */ if (!consp(args)) return onevalue(nil); /* (list) */ w1 = qcar(args); args = qcdr(args); if (!consp(args)) /* (list w1) */ { w1 = eval(w1, env); errexit(); w1 = ncons(w1); errexit(); return onevalue(w1); } w2 = qcar(args); args = qcdr(args); if (!consp(args)) /* (list w1 w2) */ { push2(env, w2); w1 = eval(w1, env); errexitn(2); w2 = stack[0]; stack[0] = w1; w2 = eval(w2, stack[-1]); errexitn(2); w1 = list2(stack[0], w2); popv(2); errexit(); return onevalue(w1); } w3 = qcar(args); args = qcdr(args); if (!is_cons(args)) /* (list w1 w2 w3) */ { push3(env, w2, w3); w1 = eval(w1, env); errexitn(3); w2 = stack[-1]; stack[-1] = w1; w2 = eval(w2, stack[-2]); errexitn(3); w3 = stack[0]; stack[0] = w2; w3 = eval(w3, stack[-2]); errexitn(3); w3 = ncons(w3); errexitn(3); w1 = list2star(stack[-1], stack[0], w3); popv(3); errexit(); return onevalue(w1); } push4(args, env, w1, w2); w3 = eval(w3, env); errexitn(4); push(w3); w2 = eval(stack[-1], stack[-3]); errexitn(5); stack[-1] = w2; w1 = eval(stack[-2], stack[-3]); errexitn(5); r = ncons(w1); errexitn(5); pop2(w3, w2); r = list2star(w3, w2, r); errexitn(3); pop3(w1, env, args); while (consp(args)) { Lisp_Object w; push3(env, args, r); w = qcar(args); w = eval(w, env); pop(r); errexitn(2); r = cons(w, r); pop2(args, env); errexit(); args = qcdr(args); } return onevalue(nreverse(r)); } static Lisp_Object liststar_fn(Lisp_Object args, Lisp_Object env) { Lisp_Object nil = C_nil; Lisp_Object r = nil; if (!consp(args)) return aerror("list*"); do { Lisp_Object w; push3(env, args, r); w = qcar(args); w = eval(w, env); pop(r); errexitn(2); r = cons(w, r); pop2(args, env); errexit(); args = qcdr(args); } while (consp(args)); args = qcar(r); r = qcdr(r); while (r != nil) { Lisp_Object c = r; r = qcdr(r); qcdr(c) = args; args = c; } return onevalue(args); } #endif #define BODY_LET 0 #define BODY_COMPILER_LET 1 #define BODY_PROG 2 #ifdef COMMON static Lisp_Object macrolet_fn(Lisp_Object args, Lisp_Object env) { Lisp_Object d, nil = C_nil; if (!consp(args)) return onevalue(nil); stackcheck2(0, args, env); d = qcar(args); /* The bunch of definitions */ while (consp(d)) { Lisp_Object w = qcar(d); /* w = (name bvl ...) */ if (consp(w) && consp(qcdr(w))) { /* * Here I need to call (expand-definer