#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 alignedtypedef 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<<T_S8 | 1<<T_S16 | 1<<T_S32 | 1<<T_S64))#define is_nt_uint(nt) ((1<<(nt)) & (1<<T_U8 | 1<<T_U16 | 1<<T_U32 | 1<<T_U64 | 1<<T_P32 | 1<<T_P64)) // doesn't lead to other values#define leafp(a) (((a)&TAG_NONLEAF_MASK) != TAG_NONLEAF_MASK) #define ANYARGS -10000 #define BUILTIN(lname, cname) \ sl_rd(1, 2) \ sl_nonnull(1) \ sl_v fn_builtin_##cname(sl_v *args, int nargs) #define BUILTIN_FN(l, c, attr) attr BUILTIN(l, c);#include "builtin_fns.h"#undef BUILTIN_FN /* UNBOXED * integers: ...|xxxxxxxx|xxxxxxxx|xxxxxxxx|tttt0100| * runes: ...|xxxxxxxx|xxxxxxxx|xxxxxxxx|11111100| */#define TAG_UBNUM_SHIFT (TAG_BITS+1)#define isubnum(x) ((tagext(x) & ((1<<TAG_UBNUM_SHIFT)-1)) == (0<<TAG_BITS | TAG_UNBOXED))#define ubnumtype(x) ((tagext(x)>>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#endifextern 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 errorint 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);
#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<<T_S8 | 1<<T_S16 | 1<<T_S32 | 1<<T_S64))
#define is_nt_uint(nt) ((1<<(nt)) & (1<<T_U8 | 1<<T_U16 | 1<<T_U32 | 1<<T_U64 | 1<<T_P32 | 1<<T_P64))
// doesn't lead to other values
#define leafp(a) (((a)&TAG_NONLEAF_MASK) != TAG_NONLEAF_MASK)
#define ANYARGS -10000
#define BUILTIN(lname, cname) \
sl_rd(1, 2) \
sl_nonnull(1) \
sl_v fn_builtin_##cname(sl_v *args, int nargs)
#define BUILTIN_FN(l, c, attr) attr BUILTIN(l, c);
#include "builtin_fns.h"
#undef BUILTIN_FN
/* UNBOXED
* integers: ...|xxxxxxxx|xxxxxxxx|xxxxxxxx|tttt0100|
* runes: ...|xxxxxxxx|xxxxxxxx|xxxxxxxx|11111100|
*/
#define TAG_UBNUM_SHIFT (TAG_BITS+1)
#define isubnum(x) ((tagext(x) & ((1<<TAG_UBNUM_SHIFT)-1)) == (0<<TAG_BITS | TAG_UNBOXED))
#define ubnumtype(x) ((tagext(x)>>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);