/* Callstack top pointer */ CELL cs; /* TAGGED currently executing quotation */ CELL callframe; /* UNTAGGED currently executing word in quotation */ CELL callframe_scan; /* UNTAGGED end of quotation */ CELL callframe_end; #define USER_ENV 32 typedef enum { CELL_SIZE_ENV = 1, /* sizeof(CELL) */ NLX_VECTOR_ENV, /* non-local exit hook, used by library only */ NAMESTACK_ENV, /* used by library only */ GLOBAL_ENV, BREAK_ENV, CATCHSTACK_ENV, /* used by library only */ CPU_ENV, BOOT_ENV, CALLCC_1_ENV, /* used by library only */ ARGS_ENV, OS_ENV, ERROR_ENV, /* a marker consed onto kernel errors */ IN_ENV, OUT_ENV, GEN_ENV, /* set to gen_count */ IMAGE_ENV /* image name */ } F_ENVTYPE; /* TAGGED user environment data; see getenv/setenv prims */ DLLEXPORT CELL userenv[USER_ENV]; /* macros for reading/writing memory, useful when working around C's type system */ INLINE CELL get(CELL where) { return *((CELL*)where); } INLINE void put(CELL where, CELL what) { *((CELL*)where) = what; } INLINE u16 cget(CELL where) { return *((u16*)where); } INLINE void cput(CELL where, u16 what) { *((u16*)where) = what; } INLINE CELL align8(CELL a) { return (a + 7) & ~7; } /* Canonical T object. It's just a word */ CELL T; INLINE CELL tag_header(CELL cell) { return RETAG(cell << TAG_BITS,OBJECT_TYPE); } INLINE CELL untag_header(CELL cell) { /* if((cell & TAG_MASK) != OBJECT_TYPE) critical_error("Corrupt object header",cell); */ return cell >> TAG_BITS; } INLINE CELL tag_object(void* cell) { return RETAG(cell,OBJECT_TYPE); } INLINE CELL object_type(CELL tagged) { return untag_header(get(UNTAG(tagged))); } INLINE CELL type_of(CELL tagged) { if(tagged == F) return F_TYPE; else if(TAG(tagged) == FIXNUM_TYPE) return FIXNUM_TYPE; else return object_type(tagged); } #define DEFPUSHPOP(prefix,ptr) \ INLINE CELL prefix##pop(void) \ { \ CELL value = get(ptr); \ ptr -= CELLS; \ return value; \ } \ INLINE void prefix##push(CELL tagged) \ { \ ptr += CELLS; \ put(ptr,tagged); \ } \ INLINE void prefix##repl(CELL tagged) \ { \ put(ptr,tagged); \ } \ INLINE CELL prefix##peek() \ { \ return get(ptr); \ } DEFPUSHPOP(d,ds) DEFPUSHPOP(r,rs) void call(CELL quot); void handle_error(); void interpreter_loop(void); void interpreter(void); DLLEXPORT void run_callback(CELL quot); void run(void); void run_toplevel(void); void undefined(F_WORD *word); void docol(F_WORD *word); void dosym(F_WORD *word); void primitive_execute(void); void primitive_call(void); void primitive_ifte(void); void primitive_dispatch(void); void primitive_getenv(void); void primitive_setenv(void); void primitive_exit(void); void primitive_os_env(void); void primitive_eq(void); void primitive_millis(void); void primitive_type(void); void primitive_tag(void); void primitive_slot(void); void primitive_set_slot(void); void primitive_clone(void); /* Runtime errors */ typedef enum { ERROR_EXPIRED = 0, ERROR_IO, ERROR_UNDEFINED_WORD, ERROR_TYPE, ERROR_DIVIDE_BY_ZERO, ERROR_SIGNAL, ERROR_NEGATIVE_ARRAY_SIZE, ERROR_C_STRING, ERROR_FFI, ERROR_HEAP_SCAN, ERROR_UNDEFINED_SYMBOL, ERROR_USER_INTERRUPT, ERROR_DS_UNDERFLOW, ERROR_DS_OVERFLOW, ERROR_RS_UNDERFLOW, ERROR_RS_OVERFLOW, ERROR_CS_UNDERFLOW, ERROR_CS_OVERFLOW, ERROR_MEMORY, ERROR_OBJECTIVE_C } F_ERRORTYPE; /* Are we throwing an error? */ /* XXX Why is this volatile? The resulting executable crashes when compiled under gcc on windows otherwise. Proper fix pending */ volatile bool throwing; /* When throw_error throws an error, it sets this global and longjmps back to the top-level. */ CELL thrown_error; CELL thrown_native_stack_trace; CELL thrown_keep_stacks; /* Since longjmp restores registers, we must save all these values. */ CELL thrown_ds; CELL thrown_rs; void fatal_error(char* msg, CELL tagged); void critical_error(char* msg, CELL tagged); void throw_error(CELL error, bool keep_stacks); void early_error(CELL error); void general_error(F_ERRORTYPE error, CELL arg1, CELL arg2, bool keep_stacks); void memory_protection_error(CELL addr, int signal); void signal_error(int signal); void type_error(CELL type, CELL tagged); void divide_by_zero_error(void); void memory_error(void); void primitive_throw(void); void primitive_die(void); INLINE void type_check(CELL type, CELL tagged) { if(type_of(tagged) != type) type_error(type,tagged); }