diff options
Diffstat (limited to 'src/primitives.c')
| -rw-r--r-- | src/primitives.c | 142 |
1 files changed, 89 insertions, 53 deletions
diff --git a/src/primitives.c b/src/primitives.c index 8958842..1cee577 100644 --- a/src/primitives.c +++ b/src/primitives.c @@ -3,10 +3,12 @@ #include "sexp.h" SExpRef primitive_if(Interp *interp, SExpRef args) { + SExpRef cond, tb, fb; + if (lisp_length(interp, args) != 3) goto error; - SExpRef cond = CAR(args); - SExpRef tb = CADR(args); - SExpRef fb = CADDR(args); + cond = CAR(args); + tb = CADR(args); + fb = CADDR(args); cond = EVAL(cond); if (ERRORP(cond)) return cond; if (TRUEP(cond)) return EVAL(tb); @@ -17,14 +19,16 @@ error: } SExpRef primitive_cond(Interp *interp, SExpRef args) { + SExpRef pair, condition, exp, iter; + if (lisp_length(interp, args) < 1) goto error; - SExpRef iter = args; + iter = args; while (!NILP(iter)) { - SExpRef pair = CAR(iter); + pair = CAR(iter); if (!lisp_check_list(interp, pair)) goto error; if (lisp_length(interp, pair) != 2) goto error; - SExpRef condition = CAR(pair); - SExpRef exp = CADR(pair); + condition = CAR(pair); + exp = CADR(pair); condition = EVAL(condition); if (ERRORP(condition)) return condition; if (TRUEP(condition)) return EVAL(exp); @@ -38,6 +42,7 @@ error: SExpRef primitive_progn(Interp *interp, SExpRef args) { SExpRef iter = args; SExpRef ret; + while (!NILP(iter)) { ret = EVAL(CAR(iter)); if (ERRORP(ret)) return ret; @@ -47,11 +52,13 @@ SExpRef primitive_progn(Interp *interp, SExpRef args) { } SExpRef primitive_setq(Interp *interp, SExpRef args) { + SExpRef name, exp, value; + if (lisp_length(interp, args) != 2) goto error; - SExpRef name = CAR(args); - SExpRef exp = CADR(args); + name = CAR(args); + exp = CADR(args); if (REF(name)->type != kSymbolSExp) goto error; - SExpRef value = EVAL(exp); + value = EVAL(exp); if (ERRORP(value)) return value; return lisp_setq(interp, REF(name)->str, value); error: @@ -65,6 +72,7 @@ static const char *binding_name(Interp *interp, SExpRef binding) { static bool is_binding_repeat(Interp *interp, SExpRef sym, SExpRef env) { SExpRef binding = REF(env)->env.bindings; + while (!NILP(binding)) { if (strcmp(REF(sym)->str, binding_name(interp, binding)) == 0) return true; binding = REF(binding)->binding.next; @@ -73,40 +81,43 @@ static bool is_binding_repeat(Interp *interp, SExpRef sym, SExpRef env) { } SExpRef primitive_let(Interp *interp, SExpRef args) { + SExpRef binding, iter, bindings, env, x, + val, body, ret, exp; + if (lisp_length(interp, args) < 1) goto error; - SExpRef bindings = CAR(args); - SExpRef env = new_env(interp); + bindings = CAR(args); + env = new_env(interp); REF(env)->env.parent = CAR(interp->stack); - SExpRef iter = bindings; + iter = bindings; while (!NILP(iter)) { - SExpRef x = CAR(iter); + x = CAR(iter); if (!lisp_check_list(interp, x)) goto error; if (lisp_length(interp, x) != 2) goto error; if (REF(CAR(x))->type != kSymbolSExp) goto error; if (is_binding_repeat(interp, CAR(x), env)) goto error; - SExpRef binding = new_binding(interp, CAR(x), NIL); + binding = new_binding(interp, CAR(x), NIL); REF(binding)->binding.next = REF(env)->env.bindings; REF(env)->env.bindings = binding; iter = CDR(iter); } interp->stack = CONS(env, interp->stack); - SExpRef ret = NIL; + ret = NIL; iter = bindings; while (!NILP(iter)) { - SExpRef x = CAR(iter); - SExpRef val = EVAL(CADR(x)); + x = CAR(iter); + val = EVAL(CADR(x)); if (REF(val)->type == kErrSExp) goto end; ret = lisp_setq(interp, REF(CAR(x))->str, val); if (ERRORP(ret)) goto end; iter = CDR(iter); } - SExpRef body = CDR(args); + body = CDR(args); iter = body; while (!NILP(iter)) { - SExpRef exp = CAR(iter); + exp = CAR(iter); ret = EVAL(exp); if (REF(ret)->type == kErrSExp) goto end; iter = CDR(iter); @@ -120,17 +131,19 @@ error: } SExpRef primitive_while(Interp *interp, SExpRef args) { + SExpRef ret, pred, body, cond, iter, x; + if (lisp_length(interp, args) < 2) goto error; - SExpRef ret = NIL; - SExpRef pred = CAR(args); - SExpRef body = CDR(args); + ret = NIL; + pred = CAR(args); + body = CDR(args); while (1) { - SExpRef cond = EVAL(pred); + cond = EVAL(pred); if (ERRORP(cond)) return cond; if (!TRUEP(cond)) return ret; - SExpRef iter = body; + iter = body; while (!NILP(iter)) { - SExpRef x = CAR(iter); + x = CAR(iter); ret = EVAL(x); if (ERRORP(ret)) return ret; iter = CDR(iter); @@ -141,40 +154,46 @@ error: } SExpRef primitive_lambda(Interp *interp, SExpRef args) { + SExpRef env, param, body; + if (lisp_length(interp, args) < 2) goto error; - SExpRef env = CAR(interp->stack); - SExpRef param = CAR(args); - SExpRef body = CDR(args); + env = CAR(interp->stack); + param = CAR(args); + body = CDR(args); return new_lambda(interp, param, body, env); error: return new_error(interp, "lambda: syntax error.\n"); } SExpRef primitive_defun(Interp *interp, SExpRef args) { + SExpRef name, param, body, function; + if (lisp_length(interp, args) < 3) goto error; if (CAR(interp->stack).idx != interp->top_level.idx) { return new_error(interp, "defun: functions can only be defined in top level.\n"); } - SExpRef name = CAR(args); + name = CAR(args); if (VALTYPE(name) != kSymbolSExp) goto error; - SExpRef param = CADR(args); - SExpRef body = CDDR(args); - SExpRef function = new_lambda(interp, param, body, interp->top_level); + param = CADR(args); + body = CDDR(args); + function = new_lambda(interp, param, body, interp->top_level); lisp_defun(interp, REF(name)->str, function); return name; error: return new_error(interp, "defun: syntax error.\n"); } SExpRef primitive_defmacro(Interp *interp, SExpRef args) { + SExpRef param, name, body, macro; + if (lisp_length(interp, args) < 3) goto error; if (CAR(interp->stack).idx != interp->top_level.idx) { return new_error(interp, "defmacro: macros can only be defined in top level.\n"); } - SExpRef name = CAR(args); + name = CAR(args); if (VALTYPE(name) != kSymbolSExp) goto error; - SExpRef param = CADR(args); - SExpRef body = CDDR(args); - SExpRef macro = new_macro(interp, param, body); + param = CADR(args); + body = CDDR(args); + macro = new_macro(interp, param, body); lisp_defun(interp, REF(name)->str, macro); return name; error: @@ -182,14 +201,16 @@ error: } SExpRef primitive_defvar(Interp *interp, SExpRef args) { + SExpRef name, exp, val; + if (lisp_length(interp, args) != 2) goto error; if (CAR(interp->stack).idx != interp->top_level.idx) { return new_error(interp, "defvar: functions can only be defined in top level.\n"); } - SExpRef name = CAR(args); + name = CAR(args); if (VALTYPE(name) != kSymbolSExp) goto error; - SExpRef exp = CADR(args); - SExpRef val = EVAL(exp); + exp = CADR(args); + val = EVAL(exp); if (ERRORP(val)) return val; lisp_defvar(interp, REF(name)->str, val); return name; @@ -210,19 +231,21 @@ static SExpRef build_function_env(Interp *interp, SExpRef func, SExpRef args) { SExpRef iparam = param; SExpRef iargs = args; SExpRef env = new_env(interp); + SExpRef binding, name; + while (!NILP(iparam)) { if (VALTYPE(iparam) == kSymbolSExp) { - SExpRef binding = new_binding(interp, iparam, iargs); + binding = new_binding(interp, iparam, iargs); REF(binding)->binding.next = REF(env)->env.bindings; REF(env)->env.bindings = binding; return env; } - SExpRef name = CAR(iparam); + name = CAR(iparam); if (VALTYPE(name) != kSymbolSExp) { return new_error(interp, "function syntax error: parameter must be a symbol.\n"); } if (NILP(iargs)) return new_error(interp, "funcall: wrong argument number.\n"); - SExpRef binding = new_binding(interp, name, CAR(iargs)); + binding = new_binding(interp, name, CAR(iargs)); REF(binding)->binding.next = REF(env)->env.bindings; REF(env)->env.bindings = binding; iargs = CDR(iargs); @@ -247,10 +270,12 @@ SExpRef primitive_quote(Interp *interp, SExpRef args) { } SExpRef primitive_macroexpand1(Interp *interp, SExpRef args) { + SExpRef macro; + if (lisp_length(interp, args) != 1) goto error; args = CAR(args); if (VALTYPE(CAR(args)) != kSymbolSExp) goto error; - SExpRef macro = lisp_lookup_func(interp, REF(CAR(args))->str); + macro = lisp_lookup_func(interp, REF(CAR(args))->str); if (VALTYPE(macro) != kMacroSExp) goto error; return lisp_macroexpand1(interp, macro, CDR(args)); error: @@ -258,11 +283,16 @@ error: } SExpRef primitive_apply(Interp *interp, SExpRef args) { + SExpRef ret; + if (lisp_length(interp, args) != 2) goto error; args = lisp_eval_args(interp, args); if (ERRORP(args)) return args; if (!lisp_check_list(interp, CADR(args))) goto error; - return lisp_apply(interp, CAR(args), CADR(args)); + PUSH_REG(args); + ret = lisp_apply(interp, CAR(args), CADR(args)); + POP_REG(); + return ret; error: return new_error(interp, "apply: syntax error.\n"); } @@ -271,6 +301,8 @@ static SExpRef quasi_on_list(Interp *interp, SExpRef lst); static SExpRef quasi_impl(Interp *interp, SExpRef obj, bool *slicing); static SExpRef quasi_impl(Interp *interp, SExpRef obj, bool *slicing) { + SExpRef lst; + *slicing = false; if (VALTYPE(obj) != kPairSExp) return obj; if (VALTYPE(CAR(obj)) == kSymbolSExp @@ -282,7 +314,7 @@ static SExpRef quasi_impl(Interp *interp, SExpRef obj, bool *slicing) { } if (VALTYPE(CAR(obj)) == kSymbolSExp && strcmp("slicing-unquote", REF(CAR(obj))->str) == 0) { - SExpRef lst = EVAL(CADR(obj)); + lst = EVAL(CADR(obj)); if (ERRORP(lst)) return lst; if (lisp_length(interp, obj) != 2) { return new_error(interp, "slicing-unquote: syntax error.\n"); @@ -298,14 +330,16 @@ static SExpRef quasi_impl(Interp *interp, SExpRef obj, bool *slicing) { static SExpRef quasi_on_list(Interp *interp, SExpRef lst) { SExpRef newlst = NIL; + SExpRef iter, j, x, newx; + bool slicing; - SExpRef iter = lst; + iter = lst; while (!NILP(iter)) { - SExpRef x = CAR(iter); - SExpRef newx = quasi_impl(interp, x, &slicing); + x = CAR(iter); + newx = quasi_impl(interp, x, &slicing); if (ERRORP(newx)) return newx; if (slicing) { - SExpRef j = newx; + j = newx; while (!NILP(j)) { newlst = CONS(CAR(j), newlst); j = CDR(j); @@ -320,17 +354,18 @@ static SExpRef quasi_on_list(Interp *interp, SExpRef lst) { } SExpRef primitive_quasi(Interp *interp, SExpRef args) { + SExpRef ret; if (lisp_length(interp, args) != 1) return new_error(interp, "quasiquote: syntax error.\n"); bool slicing; - SExpRef ret = quasi_impl(interp, CAR(args), &slicing); + ret = quasi_impl(interp, CAR(args), &slicing); if (slicing) return new_error(interp, "quasiquote: syntax error.\n"); return ret; } SExpRef primitive_and(Interp *interp, SExpRef args) { - if (lisp_length(interp, args) < 1) return new_error(interp, "and: syntax error.\n"); SExpRef ret; SExpRef i = args; + if (lisp_length(interp, args) < 1) return new_error(interp, "and: syntax error.\n"); while (!NILP(i)) { ret = EVAL(CAR(i)); if (!TRUEP(ret)) return ret; @@ -340,9 +375,10 @@ SExpRef primitive_and(Interp *interp, SExpRef args) { } SExpRef primitive_or(Interp *interp, SExpRef args) { - if (lisp_length(interp, args) < 1) return new_error(interp, "or: syntax error.\n"); SExpRef ret; SExpRef i = args; + + if (lisp_length(interp, args) < 1) return new_error(interp, "or: syntax error.\n"); while (!NILP(i)) { ret = EVAL(CAR(i)); if (TRUEP(ret)) return ret; |
