From 046b9b0c87e260985aa2ac9f21dd6203a95c88a1 Mon Sep 17 00:00:00 2001 From: Alexander Rosenberg Date: Sun, 19 Jul 2026 02:45:15 -0700 Subject: [PATCH] Fix lexical and dynamic binding --- lisp/kernel.gl | 3 ++- src/lisp.c | 25 ++++++++++++++++--------- src/stack.c | 4 ++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/lisp/kernel.gl b/lisp/kernel.gl index f2ef857..0807424 100644 --- a/lisp/kernel.gl +++ b/lisp/kernel.gl @@ -4,7 +4,8 @@ (print print-circular) -(let ((print-circular nil)) +(let ((print-circular nil) + (b t)) (test)) (print print-circular) diff --git a/src/lisp.c b/src/lisp.c index 0e55848..64e1bc3 100644 --- a/src/lisp.c +++ b/src/lisp.c @@ -135,20 +135,27 @@ DEFSPECIAL(let, "let", (LispVal * bindings, LispVal *body), "(bindings &rest body)", "") { CHECK_LISTP(bindings); StackFrame *stack_ref = LISP_STACK_REF(); - LispVal *lexenv = Vlexical_environment; DOLIST(binding, bindings) { - if (SYMBOLP(binding)) { - lexenv = CONS(binding, CONS(Qnil, lexenv)); - } else if (CONSP(binding) && list_length_eq(binding, 2)) { - lexenv = CONS( - FIRST(binding), - CONS(Feval(SECOND(binding), Vlexical_environment), lexenv)); - } else { + if (CONSP(binding) && list_length_eq(binding, 2)) { + if (!SYMBOLP(XCAR(binding))) { + // TODO better error + abort(); + } + RPLACA(XCDR(binding), Feval(SECOND(binding), Vlexical_environment)); + } else if (!SYMBOLP(binding)) { // TODO better error abort(); } } - push_dynamic_binding(Qlexical_environment, lexenv); + push_copy_lexenv(); + DOLIST(binding, bindings) { + // we already checked that all bindings are well formed + if (SYMBOLP(binding)) { + new_lexical_variable(binding, Qnil); + } else { + new_lexical_variable(FIRST(binding), SECOND(binding)); + } + } return UNWIND_AND_RETURN(stack_ref, Fprogn(body)); } diff --git a/src/stack.c b/src/stack.c index e5b3335..f592668 100644 --- a/src/stack.c +++ b/src/stack.c @@ -252,7 +252,7 @@ void set_lexical_variable(LispVal *name, LispVal *value) { abort(); } if (DYNAMIC_SYMBOL_P(name)) { - SET_SYMBOL_VALUE(name, value); + push_dynamic_binding(name, value); } else { Vlexical_environment = Fplist_put(Vlexical_environment, name, value); } @@ -265,7 +265,7 @@ void new_lexical_variable(LispVal *name, LispVal *value) { abort(); } if (DYNAMIC_SYMBOL_P(name)) { - SET_SYMBOL_VALUE(name, value); + push_dynamic_binding(name, value); } else { Vlexical_environment = CONS(name, CONS(value, Vlexical_environment)); }