From 2e6d259ea9ff4333dd6f6ffe2d38f322a38798ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Tue, 3 Jun 2025 21:35:47 +0200 Subject: [PATCH] [nucl] words operate directly on the stack In the first sketch they operated on stack frames, but this approach was flawed because a) leaving things on the stack above frame prevented it from growing leading to an internal error, b) closing the frame wiped all values deposited on the stack that were above the frame base. --- src/c/nucl.c | 68 ++++++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/src/c/nucl.c b/src/c/nucl.c index 87176dbc2..58d7d890a 100644 --- a/src/c/nucl.c +++ b/src/c/nucl.c @@ -858,24 +858,21 @@ nucl_append_dictionary(cl_object symbol, cl_object value) /* -- Default words --------------------------------------------------------- */ -cl_object nucl_word_print_frame(int narg) { - cl_object frame = nucl_stack_frame(); - cl_index ssize = nucl_stack_size(); - cl_object size = ecl_make_fixnum(ssize); - nucl_write_cstr("["); - nucl_write_object(size); - nucl_write_cstr("] "); - loop_across_frame_fifo(elt, frame) { +cl_object nucl_word_print_dictionary(int narg) { + cl_env_ptr the_env = ecl_core.first_env; + cl_object dict = ECL_SYM_VAL(the_env, nucl_dt); + loop_across_stack_fifo(elt, dict) { nucl_write_object(elt); nucl_write_cstr(" "); - } end_loop_across_frame(); - return size; + } end_loop_across_stack(); + return ECL_NIL; } cl_object nucl_word_print_stack(int narg) { const cl_env_ptr the_env = ecl_process_env(); - cl_index ssize = nucl_stack_size(); - cl_object size = ecl_make_fixnum(ECL_STACK_INDEX(the_env)); + cl_index ssize = ECL_STACK_INDEX(the_env); + /* the stack always has 0 at the beginning */ + cl_object size = ecl_make_fixnum(ssize); cl_object *ptr; nucl_write_cstr("["); nucl_write_object(size); @@ -889,24 +886,15 @@ cl_object nucl_word_print_stack(int narg) { return size; } -cl_object nucl_word_print_dictionary(int narg) { - cl_env_ptr the_env = ecl_core.first_env; - cl_object dict = ECL_SYM_VAL(the_env, nucl_dt); - loop_across_stack_fifo(elt, dict) { - nucl_write_object(elt); - nucl_write_cstr(" "); - } end_loop_across_stack(); - return ECL_NIL; -} - -/* FIXME manipulate directly the stack. */ cl_object nucl_word_pop_print(int narg) { - cl_index ssize = nucl_stack_size(); - if(ssize == 0) { + const cl_env_ptr the_env = ecl_process_env(); + cl_index ssize = ECL_STACK_INDEX(the_env); + /* INV the first element 0 is always present. */ + if(ssize <= 1) { nucl_write_cstr("error: stack underflow"); return ECL_NIL; } else { - cl_object elt = nucl_stack_pop(); + cl_object elt = ECL_STACK_POP_UNSAFE(the_env); nucl_write_object(elt); nucl_write_cstr(" "); return elt; @@ -914,11 +902,8 @@ cl_object nucl_word_pop_print(int narg) { } cl_object nucl_word_test(int narg) { - cl_env_ptr the_env = ecl_core.first_env; - cl_object elt = ecl_make_fixnum(ECL_STACK_INDEX(the_env)); - nucl_write_object(elt); - nucl_write_cstr(" "); - return elt; + nucl_write_cstr("Test call\n"); + return ECL_NIL; } ecl_def_function(_nucl_word_ps, nucl_word_print_stack, static, const); @@ -938,10 +923,10 @@ static const cl_object _nucl_sym_fed = make_dict_entry(";", ECL_UNBOUND); static cl_object nucl_dictionary_default_entries[] = { _nucl_sym_def, _nucl_sym_fed, - make_dict_entry(",", _nucl_word_tt), - make_dict_entry(".", _nucl_word_dp), - make_dict_entry(".S", _nucl_word_ps), make_dict_entry(".D", _nucl_word_pd), + make_dict_entry(".S", _nucl_word_ps), + make_dict_entry(".", _nucl_word_dp), + make_dict_entry(",", _nucl_word_tt), NULL, }; @@ -1059,8 +1044,10 @@ cl_object nucl_process_token (cl_object token) cl_object nucl_process_command () { - cl_object result = limited_reader(ECL_CODE_CHAR('\n')); - cl_object command; + cl_object result, command; + if (Null(get_definition_p())) open_nucl_frame(); + + result = limited_reader(ECL_CODE_CHAR('\n')); /* Processing of the command is straightforward. First we clean up the stack frame by moving it to a list, and then we process individual entries until. Complete definitions are not pushed back onto the stack, only words. */ @@ -1077,8 +1064,12 @@ cl_object nucl_process_command () /* Now if we are in not in a middle of the definition compile anonymous word from the current stack and call it. Otherwise leave the stack be. */ if(Null(get_definition_p())) { + const cl_env_ptr the_env = ecl_process_env(); + struct ecl_stack_frame aux_frame[1]; + cl_object frame = ecl_cast_ptr(cl_object, aux_frame); cl_object word = nucl_compile_definition(); - cl_object frame = nucl_stack_frame(); + close_nucl_frame(); + ecl_stack_frame_open(the_env, frame, 0); ecl_interpret(frame, ECL_NIL, word); } return result; @@ -1093,8 +1084,6 @@ void nucl_repl (void) init_nucl_reader(); init_nucl_dictionary(); init_nucl_dictionary_entries(); - - cl_object frame = open_nucl_frame(); /* top level frame */ do { if(Null(get_definition_p())) nucl_write_cstr("nucl> "); @@ -1104,7 +1093,6 @@ void nucl_repl (void) if(Null(get_definition_p())) nucl_write_cstr("... ok\n"); } while(result != ECL_EOF); - close_nucl_frame(); nucl_write_cstr("... bye\n"); }