diff --git a/src/c/nucl.c b/src/c/nucl.c index 63cbba9b2..41c7a4aa5 100644 --- a/src/c/nucl.c +++ b/src/c/nucl.c @@ -82,7 +82,7 @@ void smoke_bytecodes (void) cl_object ecl_make_nucl_stream(FILE *f); -/* -- Lali-ho I/O starts here ----------------------------------------------- */ +/* -- Since now on we will often use the stack, so here are some operators - */ /* GC won't catch pointers from constexpr symbols unless registered as root. */ static cl_object nucl_fp = ecl_cast_ptr(cl_object,&(ecl_constexpr_symbol(ecl_stp_special, "*FP*", ECL_NIL))); @@ -129,6 +129,8 @@ nucl_stack_pop(void) return ECL_STACK_POP_UNSAFE(frame->frame.env); } +/* And constructors */ + cl_object nucl_alloc_base_string(cl_index s) { @@ -221,6 +223,8 @@ nucl_stack_to_hexnum(void) return ecl_make_fixnum((cl_fixnum)acc); } +/* -- Lali-ho I/O starts here ----------------------------------------------- */ + cl_object nucl_write_cstr(cl_object strm, const char *s) { @@ -286,7 +290,10 @@ nucl_write_object(cl_object strm, cl_object self) switch (t) { case t_character: nucl_write_cstr(strm, "#\\"); - si_write_char(strm, self); + if(ECL_CHAR_CODE(self) == '\n') + nucl_write_cstr(strm, "Newline"); + else + si_write_char(strm, self); break; case t_fixnum: nucl_write_fixnum(strm, self); @@ -361,7 +368,7 @@ nucl_readtable_get(cl_object self, cl_fixnum ch) return self->readtable.table+ch; } -static cl_object +static void default_reader(int narg, cl_object strm, cl_object ch) { /* This reader reads either a token (symbol) or a number (fixnum). Common Lisp @@ -378,14 +385,28 @@ default_reader(int narg, cl_object strm, cl_object ch) break; case cat_terminating: si_unread_char(strm, ch); - return ECL_NIL; + return; case cat_whitespace: - return ECL_NIL; + return; default: ecl_internal_error("Expecting too much, aren't we?"); } } - return ECL_NIL; +} + +static void +limited_reader(cl_object strm, cl_object delim) +{ + cl_object object; + do { + object = nucl_accept(strm, delim); + if(Null(object)) + ecl_internal_error("Unexpected end of file"); + else if(ecl_eql(object, delim)) + break; + else + nucl_stack_push(object); + } while(1); } static cl_object @@ -397,21 +418,8 @@ comment_reader(int narg, cl_object strm, cl_object c) static cl_object lparen_reader(int narg, cl_object strm, cl_object c) { - open_nucl_frame(frame); - cl_object object; - cl_object delim = ECL_CODE_CHAR(')'); - do { - object = nucl_accept(strm, delim); - if(Null(object)) - ecl_internal_error("Unexpected end of file"); - else if(ecl_eql(object, delim)) - break; - else - nucl_stack_push(object); - } while(1); - object = nucl_stack_to_list(); - close_nucl_frame(frame); - return object; + limited_reader(strm, ECL_CODE_CHAR(')')); + return nucl_stack_to_list(); } static cl_object @@ -526,8 +534,8 @@ skip_whitespace(cl_object strm, cl_object delim) struct ecl_readtable_entry *entry = NULL; cl_object ch = ECL_NIL; do { - ch = si_read_char(strm, delim); - if (Null(ch) || ecl_eql(ch, delim)) return ch; + ch = si_read_char(strm, ECL_UNBOUND); + if (ch == ECL_UNBOUND || ecl_eql(ch, delim)) return ch; entry = nucl_readtable_get(rtable, ECL_CHAR_CODE(ch)); if (entry->syntax_type != cat_whitespace) { return ch; @@ -543,7 +551,8 @@ nucl_accept(cl_object strm, cl_object delim) cl_object ch = ECL_NIL; cl_object result = ECL_NIL; ch = skip_whitespace(strm, delim); - if (Null(ch) || ecl_eql(delim, ch)) { + if (ch == ECL_UNBOUND || ecl_eql(delim, ch)) { + close_nucl_frame(frame); return ch; } entry = nucl_readtable_get(rtable, ECL_CHAR_CODE(ch)); @@ -552,9 +561,10 @@ nucl_accept(cl_object strm, cl_object delim) /* Here's some nuance -- if the first constituent character has an associated dispatch function, then we use it instead of a default reader. In our case this always happens. */ - result = Null(entry->dispatch) - ? default_reader(2, strm, ch) - : _ecl_funcall3(entry->dispatch, strm, ch); + if(Null(entry->dispatch)) + default_reader(2, strm, ch); + else + result = _ecl_funcall3(entry->dispatch, strm, ch); break; case cat_terminating: result = _ecl_funcall3(entry->dispatch, strm, ch); @@ -566,8 +576,6 @@ nucl_accept(cl_object strm, cl_object delim) return result; } -/* -- Lali-ho I/O ends here ------------------------------------------------- */ - void smoke_stream (void) { @@ -597,14 +605,34 @@ smoke_accept (void) printf("\n"); } -int main() { +/* -- Forth-like dictionary ------------------------------------------------- */ + +/* Our dictionary is based on symbols. Each symbol in a dictionary has a name + and a value. */ + +void nucl_repl (void) +{ + cl_object ostrm = ecl_make_nucl_stream(stdout); + cl_object istrm = ecl_make_nucl_stream(stdin); + cl_object result = ECL_NIL; + cl_object delim = ECL_CODE_CHAR('\n'); + init_nucl_reader(); + do { + nucl_write_cstr(ostrm, "nucl> "); + do { result = nucl_accept(istrm, delim); } while (ecl_eql(result,delim)); + if (result==ECL_UNBOUND) { + nucl_write_cstr(ostrm, "... exit\n"); + break; + } + nucl_write_cstr(ostrm, "... "); + nucl_write_object(ostrm, result); + nucl_write_cstr(ostrm, "\n"); + } while(1); +} + +void nucl_test (void) +{ cl_env_ptr the_env = ecl_core.first_env; - ecl_boot(); - ecl_add_module(ecl_module_process); - ecl_add_module(ecl_module_stacks); - - printf("Hello ECL! %p\n", the_env); - printf("\n[:handler t :restart t] -----------------------\n"); ECL_CATCH_BEGIN(the_env, ecl_ct_resume_tag); { ecl_call_with_handler(_nucl_extinguisher, _nucl_flamethrower); @@ -619,7 +647,6 @@ int main() { nucl_flamethrower(0); printf("-----------------------------------------------\n\n"); - /* Just install the handler. */ cl_object handlers = ecl_cons_stack(_nucl_extinguisher, ECL_NIL); ECL_SETQ(the_env, ECL_SIGNAL_HANDLERS, handlers); @@ -627,14 +654,23 @@ int main() { smoke_bytecodes(); printf("-----------------------------------------------\n\n"); - /* printf("\n[:stream t] --------------------------------\n"); */ - /* smoke_stream(); */ - /* printf("-----------------------------------------------\n\n"); */ + printf("\n[:stream t] --------------------------------\n"); + smoke_stream(); + printf("-----------------------------------------------\n\n"); printf("\n[:accept t] --------------------------------\n"); smoke_accept(); printf("-----------------------------------------------\n\n"); +} +int main() { + cl_env_ptr the_env = ecl_core.first_env; + ecl_boot(); + ecl_add_module(ecl_module_process); + ecl_add_module(ecl_module_stacks); + + printf("Hello ECL! %p\n", the_env); + nucl_repl(); printf("Good bye ECL! %p\n", the_env); ecl_halt();