[nucl] add a proto-repl without eval step

This commit is contained in:
Daniel Kochmański 2025-05-28 13:01:17 +02:00
parent 3db21bec37
commit 7426a3cfed

View file

@ -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();