#pragma once #include "inc/sl.h" #include "inc/ios.h" #include "inc/htable_h.h" HTPROT(ptrhash) // all allocations on the heap are 8-byte aligned typedef u64int sl_aligned; #if defined(BITS64) #define FIXNUM_BITS (64-TAG_BITS) #define UNBOXED_BITS (64-TAG_EXT_BITS) #define T_FIXNUM T_S64 #define PRIdFIXNUM PRId64 #else #define FIXNUM_BITS (32-TAG_BITS) #define UNBOXED_BITS (32-TAG_EXT_BITS) #define T_FIXNUM T_S32 #define PRIdFIXNUM PRId32 #endif #define FIXNUM_MAX (sl_fx)(+((sl_v)1<<(FIXNUM_BITS-1))-1) #define FIXNUM_MIN (sl_fx)(-((sl_v)1<<(FIXNUM_BITS-1))-0) #define fixnum_neg(x) ( \ i64 = -(s64int)(numval(x)), \ sl_unlikely(i64 == INT64_MIN) \ ? mk_bignum(uvtomp((u64int)INT64_MAX+1, nil)) \ : (sl_likely(fits_fixnum(i64)) \ ? fixnum(i64) \ : mk_bignum(vtomp(i64, nil))) \ ) #define is_nt_sint(nt) ((1<<(nt)) & (1<>TAG_UBNUM_SHIFT) & 0xf) #if BYTE_ORDER == LITTLE_ENDIAN #define ubnumptr(v, nt) ((u8int*)&(v)) #elif BYTE_ORDER == BIG_ENDIAN #define ubnumptr(v, nt) ((u8int*)&(v)+sizeof(v)-unboxedtypes[nt]->size) #else #error invalid endian #endif extern const sl_type *unboxedtypes[T_UNBOXED_NUM]; extern sl_v unboxedtypesyms[T_UNBOXED_NUM]; #define fn_bcode(f) (ptr(sl_fn, f)->bcode) #define fn_vals(f) (ptr(sl_fn, f)->vals) #define fn_env(f) (ptr(sl_fn, f)->env) #define fn_name(f) (ptr(sl_fn, f)->name) #define fn_maxstack(f) (ptr(sl_fn, f)->maxstack) #define SL_TRY \ sl_exctx _ctx; int l__tr, l__ca; \ _ctx.osp = sl.sp - sl.stack; _ctx.frame = sl.curr_frame; \ _ctx.rs = sl.rs; _ctx.prev = sl.exctx; \ _ctx.ngchnd = slvm.ngchandles; sl.exctx = &_ctx; \ if(sl_likely(!sl_setjmp(_ctx.buf))) \ for(l__tr = 1; l__tr; l__tr = 0, (void)(sl.exctx = sl.exctx->prev)) #define SL_CATCH_INC \ l__ca = 0, sl.lasterror = sl_nil, sl.throwing_frame = 0, \ sl.sp = sl.stack + _ctx.osp, sl.curr_frame = _ctx.frame #define SL_CATCH \ else \ for(l__ca = 1; l__ca; SL_CATCH_INC) #define SL_CATCH_NO_INC \ else \ for(l__ca = 1; l__ca;) #if BYTE_ORDER == LITTLE_ENDIAN && defined(MEM_UNALIGNED_ACCESS) #define GET_S32(a) *(const s32int*)(a) #define GET_S16(a) *(const s16int*)(a) #else #define GET_S32(a) (s32int)((a)[0]<<0 | (a)[1]<<8 | (a)[2]<<16 | (u32int)(a)[3]<<24) #define GET_S16(a) (s16int)((a)[0]<<0 | (a)[1]<<8) #endif typedef struct Tbl Tbl; typedef struct sl_pid sl_pid; #if defined(__plan9__) #pragma incomplete Tbl #pragma incomplete sl_pid #endif typedef struct sl_exctx sl_exctx; typedef struct sl_readstate sl_readstate; struct sl_readstate { sl_v io; sl_v tokval; sl_v macro; u32int toktype; u32int bq; u32int ags; bool ws; ios_loc loc0; ios_loc loc; ios_loc errloc; sl_readstate *prev; sl_readstate *termrs; sl_htable backrefs; sl_htable gensyms; int termlen; int termwidth; char term[32]; char buf[256]; }; struct sl_exctx { sl_readstate *rs; struct sl_exctx *prev; sl_jmp_buf buf; usize osp; usize frame; int ngchnd; }; struct sl_proc { sl_v *sp; usize curr_frame; // saved execution state for an unwind target sl_exctx *exctx; usize throwing_frame; // active frame when exception was thrown sl_v lasterror; sl_readstate *rs; u32int *consflags; sl_v *stack; sl_v *stackend; u32int nstack; // everything related to printing struct { ios *f; u32int label; sl_fx base; sl_fx ptr_base; sl_fx length; sl_fx level; sl_fx width; sl_fx p_level; sl_fx rmargin; ssize x, y; sl_htable conses; bool pretty; bool princ; bool circle; bool radix; bool ptr_radix; bool syntax_sugar; bool fnname; }pr; // caller PC void *cpc; // temporary mpint for arith mpint *mptemp; // auto gensym index u32int ags; // current random state, NIL at first sl_v randstate; // extra data used by random logic void *randstatectx; sl_v readtable; }; struct sl_vm { u8int *curheap; u8int *lim; usize malloc_pressure; sl_cv **finalizers; usize nfinalizers; usize maxfinalizers; Tbl *symbols; u32int gensym_ctr; // two static buffers for gensym printing so there can be two // gensym names available at a time, mostly for compare() char gsname[2][16]; int gsnameno; int ngchandles; int maxgchandles; sl_v **gchandles; usize gccalls; sl_htable *reverse_dlsym_lookup; sl_htable *types; u8int *fromspace; u8int *tospace; uintptr heapsize; // bytes bool exiting; bool grew; sl_pid *pids; int pidupdates; }; char *uint2str(char *dest, usize len, u64int num, int base) sl_nonnull(1) sl_returns_nonnull sl_wr(1, 2); typedef enum { FORK_CLEAR_ENV = 1<<0, }sl_enum_flags fork_flags; // return error code, #bytes read/writted in *nread/*nwritten // these wrappers retry operations until success or a fatal error int sys_read(int fd, u8int *buf, usize n, usize *nread) sl_fd_rd(1) sl_wr(2, 3) sl_wr(4) sl_nonnull(2, 4); int sys_write(int fd, const void *buf, usize n, usize *nwritten) sl_fd_wr(1) sl_rd(2, 3) sl_wr(4) sl_nonnull(2, 4); int sys_open(const char *fname, ios_flags flags, usize mode) sl_cstr(1) sl_nonnull(1); void sys_fd_setup(int fd) sl_fd(1); int sys_rename(const char *old, const char *new) sl_cstr(1) sl_cstr(2) sl_nonnull(1, 2); soffset sys_seek(int fd, soffset offset, int whence) sl_fd(1); int sys_close(int fd) sl_fd(1); int sys_mkdir(const char *path, usize mode) sl_cstr(1) sl_nonnull(1); int sys_dup(int oldfd, int newfd) sl_fd(1); int sys_exec(const char *path, char *const argv[], char *env[]) sl_nonnull(1, 2); int sys_pipe(int fd[2], bool rd, bool wr); char *sys_find_program(const char *p) sl_cstr(1) sl_nonnull(1); int sys_postnote(int pid, const char *note, const char *sig) sl_cstr(2) sl_cstr(3) sl_nonnull(2, 3); char *sys_getcwd(void); int sys_chdir(int fd, const char *dir); int sys_fork(fork_flags flags); void bcc_init(void); void compress_init(void); void math_init(void); void sys_init(void); void random_init(void); void sl_savestate(sl_exctx *_ctx) sl_nonnull(1); void sl_restorestate(sl_exctx *_ctx) sl_nonnull(1); void free_readstate(sl_readstate *rs) sl_nonnull(1); _Noreturn void slmain(const u8int *boot, int bootsz, int argc, char **argv) sl_rd(1, 2) sl_rd(4, 3) sl_nonnull(1, 4); sl_v sl_list(sl_v *args, int nargs, bool star) sl_hotfn sl_nonnull(1); sl_v sl_do_trycatch(void); int sl_process_args(sl_v *args, int nreq, int nargs, const sl_v *keys, int nkeys, sl_v *values); int sl_process_keys(sl_v kwtable, int nreq, int nkw, int nopt, usize bp, int nargs, int va); sl_v sl_vm_applyn(int n) sl_hotfn; sl_v sl_vm_apply_cl(int nargs) sl_hotfn; int sl_load_system_image(sl_v ios); int sl_init(usize heapsize); _Noreturn void sl_exit(const char *status, int code) sl_cstr(1);