2004-07-16 02:26:21 -04:00
|
|
|
#include "factor.h"
|
|
|
|
|
2005-01-01 19:30:57 -05:00
|
|
|
INLINE void execute(F_WORD* word)
|
|
|
|
{
|
2005-09-16 02:39:33 -04:00
|
|
|
((XT)(word->xt))(word);
|
2005-01-01 19:30:57 -05:00
|
|
|
}
|
2004-07-16 02:26:21 -04:00
|
|
|
|
2006-06-27 03:40:07 -04:00
|
|
|
INLINE void push_callframe(void)
|
2006-05-17 14:55:46 -04:00
|
|
|
{
|
2006-06-27 03:40:07 -04:00
|
|
|
cs += CELLS * 3;
|
|
|
|
put(cs - CELLS * 2,callframe);
|
|
|
|
put(cs - CELLS,callframe_scan);
|
|
|
|
put(cs,callframe_end);
|
|
|
|
}
|
|
|
|
|
|
|
|
INLINE void set_callframe(CELL quot)
|
|
|
|
{
|
|
|
|
F_ARRAY *untagged = (F_ARRAY*)UNTAG(quot);
|
|
|
|
type_check(QUOTATION_TYPE,quot);
|
|
|
|
callframe = quot;
|
|
|
|
callframe_scan = AREF(untagged,0);
|
|
|
|
callframe_end = AREF(untagged,array_capacity(untagged));
|
|
|
|
}
|
2006-05-17 14:55:46 -04:00
|
|
|
|
2006-06-27 03:40:07 -04:00
|
|
|
void call(CELL quot)
|
|
|
|
{
|
2006-05-17 14:55:46 -04:00
|
|
|
if(quot == F)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* tail call optimization */
|
|
|
|
if(callframe_scan < callframe_end)
|
2006-06-27 03:40:07 -04:00
|
|
|
push_callframe();
|
2006-05-17 14:55:46 -04:00
|
|
|
|
2006-06-27 03:40:07 -04:00
|
|
|
set_callframe(quot);
|
2006-05-17 14:55:46 -04:00
|
|
|
}
|
|
|
|
|
2006-02-13 02:46:07 -05:00
|
|
|
/* Called from platform_run() */
|
2006-02-13 16:00:21 -05:00
|
|
|
void handle_error(void)
|
2004-07-16 02:26:21 -04:00
|
|
|
{
|
2005-09-20 20:18:01 -04:00
|
|
|
if(throwing)
|
2004-11-06 15:51:17 -05:00
|
|
|
{
|
2004-11-09 12:29:25 -05:00
|
|
|
if(thrown_keep_stacks)
|
|
|
|
{
|
|
|
|
ds = thrown_ds;
|
2006-05-14 23:09:47 -04:00
|
|
|
rs = thrown_rs;
|
2004-11-09 12:29:25 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
fix_stacks();
|
|
|
|
|
2004-11-06 15:51:17 -05:00
|
|
|
dpush(thrown_error);
|
|
|
|
/* Notify any 'catch' blocks */
|
2006-06-27 03:40:07 -04:00
|
|
|
push_callframe();
|
|
|
|
set_callframe(userenv[BREAK_ENV]);
|
2005-09-20 20:18:01 -04:00
|
|
|
throwing = false;
|
2004-11-06 15:51:17 -05:00
|
|
|
}
|
2006-02-13 02:46:07 -05:00
|
|
|
}
|
|
|
|
|
2006-02-23 02:09:34 -05:00
|
|
|
void run(void)
|
2006-02-13 02:46:07 -05:00
|
|
|
{
|
|
|
|
CELL next;
|
2004-10-31 14:36:42 -05:00
|
|
|
|
2004-07-16 02:26:21 -04:00
|
|
|
for(;;)
|
|
|
|
{
|
2006-05-17 14:55:46 -04:00
|
|
|
if(callframe_scan == callframe_end)
|
2004-07-16 02:26:21 -04:00
|
|
|
{
|
2006-02-13 16:00:21 -05:00
|
|
|
if(cs_bot - cs == CELLS)
|
2006-02-13 02:46:07 -05:00
|
|
|
return;
|
|
|
|
|
2006-05-17 14:55:46 -04:00
|
|
|
callframe_end = get(cs);
|
|
|
|
callframe_scan = get(cs - CELLS);
|
|
|
|
callframe = get(cs - CELLS * 2);
|
|
|
|
cs -= CELLS * 3;
|
2004-07-16 02:26:21 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2006-05-17 14:55:46 -04:00
|
|
|
next = get(callframe_scan);
|
|
|
|
callframe_scan += CELLS;
|
2004-07-16 02:26:21 -04:00
|
|
|
|
2006-05-18 01:08:09 -04:00
|
|
|
switch(TAG(next))
|
2005-08-03 23:56:28 -04:00
|
|
|
{
|
|
|
|
case WORD_TYPE:
|
2005-01-01 19:30:57 -05:00
|
|
|
execute(untag_word_fast(next));
|
2005-08-03 23:56:28 -04:00
|
|
|
break;
|
|
|
|
case WRAPPER_TYPE:
|
|
|
|
dpush(untag_wrapper_fast(next)->object);
|
|
|
|
break;
|
|
|
|
default:
|
2004-08-12 17:36:36 -04:00
|
|
|
dpush(next);
|
2005-08-03 23:56:28 -04:00
|
|
|
break;
|
|
|
|
}
|
2004-07-16 02:26:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-13 16:00:21 -05:00
|
|
|
void run_toplevel(void)
|
2006-02-13 02:46:07 -05:00
|
|
|
{
|
2006-02-23 02:09:34 -05:00
|
|
|
SETJMP(stack_chain->toplevel);
|
|
|
|
handle_error();
|
|
|
|
run();
|
2006-02-13 02:46:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Called by compiled callbacks after nest_stacks() and boxing registers */
|
2006-02-14 23:23:08 -05:00
|
|
|
void run_callback(CELL quot)
|
2006-02-13 02:46:07 -05:00
|
|
|
{
|
|
|
|
call(quot);
|
2006-02-23 02:09:34 -05:00
|
|
|
platform_run();
|
2006-02-13 02:46:07 -05:00
|
|
|
}
|
|
|
|
|
2004-07-16 02:26:21 -04:00
|
|
|
/* XT of deferred words */
|
2005-01-01 19:30:57 -05:00
|
|
|
void undefined(F_WORD* word)
|
2004-07-16 02:26:21 -04:00
|
|
|
{
|
2006-05-25 23:25:00 -04:00
|
|
|
general_error(ERROR_UNDEFINED_WORD,tag_word(word),F,true);
|
2004-07-16 02:26:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* XT of compound definitions */
|
2005-01-01 19:30:57 -05:00
|
|
|
void docol(F_WORD* word)
|
2004-07-16 02:26:21 -04:00
|
|
|
{
|
2005-03-05 14:45:23 -05:00
|
|
|
call(word->def);
|
2004-09-28 00:24:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* pushes word parameter */
|
2005-01-01 19:30:57 -05:00
|
|
|
void dosym(F_WORD* word)
|
2004-09-28 00:24:36 -04:00
|
|
|
{
|
2005-03-05 14:45:23 -05:00
|
|
|
dpush(word->def);
|
2004-07-16 02:26:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_execute(void)
|
|
|
|
{
|
2005-01-01 19:30:57 -05:00
|
|
|
execute(untag_word(dpop()));
|
2004-07-16 02:26:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_call(void)
|
|
|
|
{
|
2004-08-23 01:13:09 -04:00
|
|
|
call(dpop());
|
2004-07-16 02:26:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_ifte(void)
|
|
|
|
{
|
2006-05-18 01:08:09 -04:00
|
|
|
ds -= CELLS * 3;
|
2006-07-24 01:22:11 -04:00
|
|
|
call(get(ds + CELLS) == F ? get(ds + CELLS * 3) : get(ds + CELLS * 2));
|
2004-07-16 02:26:21 -04:00
|
|
|
}
|
|
|
|
|
2005-06-12 03:38:57 -04:00
|
|
|
void primitive_dispatch(void)
|
|
|
|
{
|
2005-09-11 20:46:55 -04:00
|
|
|
F_ARRAY *a = untag_array_fast(dpop());
|
2005-06-12 03:38:57 -04:00
|
|
|
F_FIXNUM n = untag_fixnum_fast(dpop());
|
2005-09-11 20:46:55 -04:00
|
|
|
call(get(AREF(a,n)));
|
2005-06-12 03:38:57 -04:00
|
|
|
}
|
|
|
|
|
2004-07-16 02:26:21 -04:00
|
|
|
void primitive_getenv(void)
|
|
|
|
{
|
2005-04-25 21:39:34 -04:00
|
|
|
F_FIXNUM e = untag_fixnum_fast(dpeek());
|
2004-08-20 18:48:08 -04:00
|
|
|
drepl(userenv[e]);
|
2004-07-16 02:26:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_setenv(void)
|
|
|
|
{
|
2005-04-25 21:39:34 -04:00
|
|
|
F_FIXNUM e = untag_fixnum_fast(dpop());
|
2004-07-16 02:26:21 -04:00
|
|
|
CELL value = dpop();
|
2004-08-20 18:48:08 -04:00
|
|
|
userenv[e] = value;
|
2004-07-16 02:26:21 -04:00
|
|
|
}
|
2006-07-07 00:07:18 -04:00
|
|
|
|
|
|
|
void primitive_exit(void)
|
|
|
|
{
|
|
|
|
exit(to_fixnum(dpop()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_os_env(void)
|
|
|
|
{
|
|
|
|
char *name, *value;
|
|
|
|
|
|
|
|
maybe_gc(0);
|
|
|
|
|
|
|
|
name = pop_char_string();
|
|
|
|
value = getenv(name);
|
|
|
|
if(value == NULL)
|
|
|
|
dpush(F);
|
|
|
|
else
|
|
|
|
box_char_string(getenv(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_eq(void)
|
|
|
|
{
|
2006-07-24 01:22:11 -04:00
|
|
|
CELL lhs = dpop();
|
|
|
|
CELL rhs = dpeek();
|
|
|
|
drepl((lhs == rhs) ? T : F);
|
2006-07-07 00:07:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_millis(void)
|
|
|
|
{
|
|
|
|
maybe_gc(0);
|
|
|
|
dpush(tag_bignum(s48_long_long_to_bignum(current_millis())));
|
|
|
|
}
|
|
|
|
|
|
|
|
void fatal_error(char* msg, CELL tagged)
|
|
|
|
{
|
|
|
|
fprintf(stderr,"Fatal error: %s %ld\n",msg,tagged);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void critical_error(char* msg, CELL tagged)
|
|
|
|
{
|
|
|
|
fprintf(stderr,"Critical error: %s %ld\n",msg,tagged);
|
|
|
|
factorbug();
|
|
|
|
}
|
|
|
|
|
|
|
|
void early_error(CELL error)
|
|
|
|
{
|
|
|
|
if(userenv[BREAK_ENV] == F)
|
|
|
|
{
|
|
|
|
/* Crash at startup */
|
|
|
|
fprintf(stderr,"Error during startup: ");
|
|
|
|
print_obj(error);
|
|
|
|
fprintf(stderr,"\n");
|
|
|
|
factorbug();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void throw_error(CELL error, bool keep_stacks)
|
|
|
|
{
|
|
|
|
early_error(error);
|
|
|
|
|
|
|
|
throwing = true;
|
|
|
|
thrown_error = error;
|
|
|
|
thrown_keep_stacks = keep_stacks;
|
|
|
|
thrown_ds = ds;
|
|
|
|
thrown_rs = rs;
|
|
|
|
|
|
|
|
/* Return to run() method */
|
|
|
|
LONGJMP(stack_chain->toplevel,1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_throw(void)
|
|
|
|
{
|
|
|
|
throw_error(dpop(),true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_die(void)
|
|
|
|
{
|
|
|
|
factorbug();
|
|
|
|
}
|
|
|
|
|
|
|
|
void general_error(F_ERRORTYPE error, CELL arg1, CELL arg2, bool keep_stacks)
|
|
|
|
{
|
|
|
|
throw_error(make_array_4(userenv[ERROR_ENV],
|
|
|
|
tag_fixnum(error),arg1,arg2),keep_stacks);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* It is not safe to access 'ds' from a signal handler, so we just not
|
|
|
|
touch it */
|
|
|
|
void signal_error(int signal)
|
|
|
|
{
|
|
|
|
general_error(ERROR_SIGNAL,tag_fixnum(signal),F,false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void type_error(CELL type, CELL tagged)
|
|
|
|
{
|
|
|
|
general_error(ERROR_TYPE,tag_fixnum(type),tagged,true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void init_compiler(CELL size)
|
|
|
|
{
|
|
|
|
compiling.base = compiling.here = (CELL)(alloc_bounded_block(size)->start);
|
|
|
|
if(compiling.base == 0)
|
|
|
|
fatal_error("Cannot allocate code heap",size);
|
|
|
|
compiling.limit = compiling.base + size;
|
|
|
|
last_flush = compiling.base;
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_compiled_offset(void)
|
|
|
|
{
|
|
|
|
box_unsigned_cell(compiling.here);
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_set_compiled_offset(void)
|
|
|
|
{
|
|
|
|
CELL offset = unbox_unsigned_cell();
|
|
|
|
compiling.here = offset;
|
|
|
|
if(compiling.here >= compiling.limit)
|
|
|
|
{
|
|
|
|
fprintf(stderr,"Code space exhausted\n");
|
|
|
|
factorbug();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_add_literal(void)
|
|
|
|
{
|
|
|
|
CELL object = dpeek();
|
|
|
|
CELL offset = literal_top;
|
|
|
|
put(literal_top,object);
|
|
|
|
literal_top += CELLS;
|
|
|
|
if(literal_top >= literal_max)
|
|
|
|
critical_error("Too many compiled literals",literal_top);
|
|
|
|
drepl(tag_cell(offset));
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_flush_icache(void)
|
|
|
|
{
|
|
|
|
flush_icache((void*)last_flush,compiling.here - last_flush);
|
|
|
|
last_flush = compiling.here;
|
|
|
|
}
|
|
|
|
|
|
|
|
void collect_literals(void)
|
|
|
|
{
|
|
|
|
CELL i;
|
|
|
|
for(i = compiling.base; i < literal_top; i += CELLS)
|
|
|
|
copy_handle((CELL*)i);
|
|
|
|
}
|