aboutsummaryrefslogtreecommitdiff
path: root/src/interp.c
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-06-20 15:11:20 +0800
committerMistivia <i@mistivia.com>2025-06-20 15:11:20 +0800
commit815b972460fb83267a719f82afd79c2abaac80cd (patch)
tree7dac972705ead6fc29520a9cb91982ef6b0e5c7f /src/interp.c
parentf09b34f95134972ecb907dbef0a697f4fcc1abaf (diff)
defun
Diffstat (limited to 'src/interp.c')
-rw-r--r--src/interp.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/interp.c b/src/interp.c
index 016f3a4..38e9d2d 100644
--- a/src/interp.c
+++ b/src/interp.c
@@ -15,6 +15,8 @@
void PrimitiveEntry_show(PrimitiveEntry self, FILE *fp) { }
VECTOR_IMPL(PrimitiveEntry);
+SExpRef unbound = {-1};
+
void Interp_init(Interp *self) {
self->errmsg_buf = malloc(BUFSIZE);
SExpVector_init(&self->objs);
@@ -46,6 +48,9 @@ void Interp_init(Interp *self) {
Interp_add_primitive(self, "setq", primitive_setq);
Interp_add_primitive(self, "let", primitive_let);
Interp_add_primitive(self, "while", primitive_while);
+ Interp_add_primitive(self, "lambda", primitive_lambda);
+ Interp_add_primitive(self, "function", primitive_function);
+ Interp_add_primitive(self, "defun", primitive_defun);
Interp_add_userfunc(self, "car", builtin_car);
Interp_add_userfunc(self, "list", builtin_list);
@@ -62,7 +67,7 @@ void Interp_init(Interp *self) {
void Interp_add_userfunc(Interp *interp, const char *name, LispUserFunc fn) {
SExpRef userfunc = new_userfunc(interp, fn);
- lisp_setfun(interp, name, userfunc);
+ lisp_defun(interp, name, userfunc);
}
void Interp_free(Interp *self) {
@@ -211,7 +216,7 @@ const char* lisp_to_string(Interp *interp, SExpRef val) {
return sb.buf;
}
-void lisp_setfun(Interp *interp, const char *name, SExpRef val) {
+void lisp_defun(Interp *interp, const char *name, SExpRef val) {
SExpRef binding = REF(interp->top_level)->env.bindings;
while (REF(binding)->type != kNilSExp) {
if (strcmp(name, REF(REF(binding)->binding.name)->str) == 0) {
@@ -249,12 +254,15 @@ SExpRef lisp_lookup(Interp *interp, const char *name) {
SExpRef binding = REF(env)->env.bindings;
while (REF(binding)->type != kNilSExp) {
if (strcmp(name, REF(REF(binding)->binding.name)->str) == 0) {
- return REF(binding)->binding.value;
+ SExpRef ret = REF(binding)->binding.value;
+ if (ret.idx < 0) goto notfound;
+ return ret;
}
binding = REF(binding)->binding.next;
}
env = REF(env)->env.parent;
}
+notfound:
return new_error(interp, "Unbound variable: %s.\n", name);
}
@@ -401,6 +409,15 @@ SExpRef new_env(Interp *interp) {
return ret;
}
+SExpRef new_lambda(Interp *interp, SExpRef param, SExpRef body, SExpRef env) {
+ SExpRef ret = new_sexp(interp);
+ REF(ret)->type = kFuncSExp;
+ REF(ret)->func.args = param;
+ REF(ret)->func.body = body;
+ REF(ret)->func.env = env;
+ return ret;
+}
+
SExpRef new_binding(Interp *interp, SExpRef sym, SExpRef val) {
SExpRef ret = new_sexp(interp);
REF(ret)->type = kBindingSExp;