aboutsummaryrefslogtreecommitdiff
path: root/src/primitives.c
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-06-20 18:12:25 +0800
committerMistivia <i@mistivia.com>2025-06-20 18:12:25 +0800
commit3cef9f993de2e0380c859d0e0ec88c07bfc3635f (patch)
tree7f98824d36d545ed90dd4adc34a3e3d2c7cfc1ff /src/primitives.c
parentad580b3401deb4a41ee3a8f17824d136ee5cf38d (diff)
finish function
Diffstat (limited to 'src/primitives.c')
-rw-r--r--src/primitives.c55
1 files changed, 52 insertions, 3 deletions
diff --git a/src/primitives.c b/src/primitives.c
index 25be771..2a28677 100644
--- a/src/primitives.c
+++ b/src/primitives.c
@@ -1,4 +1,5 @@
#include "primitives.h"
+#include "interp.h"
#include "sexp.h"
SExpRef primitive_if(Interp *interp, SExpRef args) {
@@ -189,9 +190,57 @@ error:
return new_error(interp, "function: syntax error.\n");
}
+static SExpRef build_function_env(Interp *interp, SExpRef func, SExpRef args) {
+ SExpRef param = REF(func)->func.args;
+ SExpRef iparam = param;
+ SExpRef iargs = args;
+ SExpRef env = new_env(interp);
+ while (!NILP(iparam)) {
+ if (VALTYPE(iparam) == kSymbolSExp) {
+ SExpRef 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);
+ 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));
+ REF(binding)->binding.next = REF(env)->env.bindings;
+ REF(env)->env.bindings = binding;
+ iargs = CDR(iargs);
+ iparam = CDR(iparam);
+ }
+ if (!NILP(iargs)) return new_error(interp, "funcall: wrong argument number.\n");
+ return env;
+}
+
+SExpRef primitive_funcall(Interp *interp, SExpRef args) {
+ if (lisp_length(interp, args) < 1) goto error;
+ args = lisp_eval_args(interp, args);
+ if (ERRORP(args)) return args;
+ return lisp_apply(interp, CAR(args), CDR(args));
+error:
+ return new_error(interp, "funcall: syntax error.\n");
+}
+
+SExpRef primitive_quote(Interp *interp, SExpRef args) {
+ if (lisp_length(interp, args) != 1) return new_error(interp, "quote: syntax error.\n");
+ return CAR(args);
+}
+
+SExpRef primitive_apply(Interp *interp, SExpRef args) {
+ 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));
+error:
+ return new_error(interp, "apply: syntax error.\n");
+}
+
// TODO:
-// - funcall
-// - apply
-// - defvar
// - defmacro
// - macroexpand-1