shithub: sl

Download patch

ref: 5ac5ac2d64c4aeed30d6f9a23eaa8dda7d295e47
parent: 9e0a991374ed0bb6fc8b2a7ca83e5607f77c17ac
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Fri Mar 7 01:04:56 EST 2025

take things out of Sl; add Slg for vm globals

--- a/src/builtins.c
+++ b/src/builtins.c
@@ -102,9 +102,9 @@
 	}
 	if(iscprim(a)){
 		cv = ptr(a);
-		if(cp_class(cv) == sl.bytetype)
+		if(cp_class(cv) == sl_bytetype)
 			return fixnum(1);
-		if(cp_class(cv) == sl.runetype)
+		if(cp_class(cv) == sl_runetype)
 			return fixnum(runelen(*(Rune*)cp_data(cv)));
 	}
 	if(iscvalue(a) && cv_class(ptr(a))->eltype != nil)
@@ -193,7 +193,7 @@
 	sl_gc_handle(&lst);
 	const char *k = nil;
 	sl_sym *v;
-	while(Tnext(sl.symtab, &k, (void**)&v)){
+	while(Tnext(slg.symbols, &k, (void**)&v)){
 		if(v->binding != UNBOUND && (v->flags & FLAG_KEYWORD) == 0)
 			lst = mk_cons(tagptr(v, TAG_SYM), lst);
 	}
--- a/src/cvalues.c
+++ b/src/cvalues.c
@@ -20,12 +20,12 @@
 void
 add_finalizer(csl_v *cv)
 {
-	if(sl.nfinalizers == sl.maxfinalizers){
-		sl.maxfinalizers *= 2;
-		sl.finalizers = MEM_REALLOC(sl.finalizers, sl.maxfinalizers*sizeof(sl.finalizers));
-		assert(sl.finalizers != nil);
+	if(slg.nfinalizers == slg.maxfinalizers){
+		slg.maxfinalizers *= 2;
+		slg.finalizers = MEM_REALLOC(slg.finalizers, slg.maxfinalizers*sizeof(slg.finalizers));
+		assert(slg.finalizers != nil);
 	}
-	sl.finalizers[sl.nfinalizers++] = cv;
+	slg.finalizers[slg.nfinalizers++] = cv;
 }
 
 // remove dead objects from finalization list in-place
@@ -32,13 +32,13 @@
 void
 sweep_finalizers(void)
 {
-	csl_v **lst = sl.finalizers;
-	usize n = 0, ndel = 0, l = sl.nfinalizers;
+	csl_v **lst = slg.finalizers;
+	usize n = 0, ndel = 0, l = slg.nfinalizers;
 	csl_v *tmp;
 #define SWAP_sf(a, b) (tmp = a, a = b, b = tmp, 1)
 	if(l == 0)
 		return;
-	bool exiting = sl.exiting;
+	bool exiting = slg.exiting;
 	do{
 		tmp = lst[n];
 		if(isforwarded((sl_v)tmp)){
@@ -55,9 +55,8 @@
 		}
 	}while((n < l-ndel) && SWAP_sf(lst[n], lst[n+ndel]));
 
-	sl.nfinalizers -= ndel;
-
-	sl.malloc_pressure = 0;
+	slg.nfinalizers -= ndel;
+	slg.malloc_pressure = 0;
 }
 
 // compute the size of the metadata object for a cvalue
@@ -97,9 +96,9 @@
 		return cprim(type, sz);
 
 	bool str = false;
-	if(type->eltype == sl.bytetype){
+	if(type->eltype == sl_bytetype){
 		if(sz == 0)
-			return sl.the_empty_string;
+			return sl_emptystr;
 		sz++;
 		str = true;
 	}
@@ -112,13 +111,13 @@
 		if(!nofinalize && type->vtable != nil && type->vtable->finalize != nil)
 			add_finalizer(pcv);
 	}else{
-		if(sl.malloc_pressure > ALLOC_LIMIT_TRIGGER)
+		if(slg.malloc_pressure > ALLOC_LIMIT_TRIGGER)
 			sl_gc(false);
 		pcv = alloc_words(CVALUE_NWORDS);
 		pcv->type = type;
 		pcv->data = MEM_ALLOC(sz);
 		cv_autorelease(pcv);
-		sl.malloc_pressure += sz;
+		slg.malloc_pressure += sz;
 	}
 	if(str)
 		((char*)pcv->data)[--sz] = '\0';
@@ -152,8 +151,8 @@
 cvalue_string(usize sz)
 {
 	if(sz == 0)
-		return sl.the_empty_string;
-	return cvalue(sl.stringtype, sz);
+		return sl_emptystr;
+	return cvalue(sl_stringtype, sz);
 }
 
 sl_v
@@ -160,8 +159,8 @@
 cvalue_static_cstring(const char *str)
 {
 	if(*str == 0)
-		return sl.the_empty_string;
-	return cvalue_from_ref(sl.stringtype, (char*)str, strlen(str));
+		return sl_emptystr;
+	return cvalue_from_ref(sl_stringtype, (char*)str, strlen(str));
 }
 
 sl_v
@@ -238,8 +237,8 @@
 			PUSH(fixnum(0)); \
 			args = sl.sp-1; \
 		} \
-		sl_v cp = cprim(sl.typenam##type, sizeof(ctype)); \
-		cvalue_##ctype##_init(sl.typenam##type, args[0], cp_data(ptr(cp))); \
+		sl_v cp = cprim(sl_##typenam##type, sizeof(ctype)); \
+		cvalue_##ctype##_init(sl_##typenam##type, args[0], cp_data(ptr(cp))); \
 		return cp; \
 	}
 
@@ -246,7 +245,7 @@
 #define num_ctor_ctor(typenam, ctype, tag) \
 	sl_v mk_##typenam(ctype n) \
 	{ \
-		sl_v cp = cprim(sl.typenam##type, sizeof(ctype)); \
+		sl_v cp = cprim(sl_##typenam##type, sizeof(ctype)); \
 		*(ctype*)cp_data(ptr(cp)) = n; \
 		return cp; \
 	}
@@ -294,8 +293,8 @@
 		PUSH(fixnum(0));
 		args = sl.sp-1;
 	}
-	sl_v cv = cvalue(sl.mptype, sizeof(mpint*));
-	cvalue_mp_init(sl.mptype, args[0], cvalue_data(cv));
+	sl_v cv = cvalue(sl_mptype, sizeof(mpint*));
+	cvalue_mp_init(sl_mptype, args[0], cvalue_data(cv));
 	return cv;
 }
 
@@ -303,7 +302,7 @@
 sl_v
 mk_mp(mpint *n)
 {
-	sl_v cv = cvalue(sl.mptype, sizeof(mpint*));
+	sl_v cv = cvalue(sl_mptype, sizeof(mpint*));
 	*(mpint**)cvalue_data(cv) = n;
 	return cv;
 }
@@ -529,7 +528,7 @@
 	if(iscvalue(v)){
 		csl_v *pcv = ptr(v);
 		sl_ios *x = value2c(sl_ios*, v);
-		if(cv_class(pcv) == sl.iostreamtype && x->bm == bm_mem){
+		if(cv_class(pcv) == sl_iostreamtype && x->bm == bm_mem){
 			*pdata = x->buf;
 			*psz = x->size;
 			return;
@@ -603,7 +602,7 @@
 	if(t->vtable != nil && t->vtable->relocate != nil)
 		t->vtable->relocate(v, ncv);
 	forward(v, ncv);
-	if(sl.exiting)
+	if(slg.exiting)
 		cv_autorelease(ptr(ncv));
 	return ncv;
 }
@@ -791,13 +790,13 @@
 	csl_v *cv;
 	cv = MEM_CALLOC(CVALUE_NWORDS-1, sizeof(*cv));
 	assert(cv != nil);
-	cv->type = sl.builtintype;
+	cv->type = sl_builtintype;
 	cv->cbuiltin = f;
 
 	sl_v sym = symbol(name, false);
 	sl_sym *s = ptr(sym);
 	s->binding = tagptr(cv, TAG_CVALUE);
-	ptrhash_put(&sl.reverse_dlsym_lookup_table, cv, (void*)sym);
+	ptrhash_put(&slg.reverse_dlsym_lookup, cv, (void*)sym);
 
 	return s->binding;
 }
@@ -821,8 +820,8 @@
 
 #define mk_primtype(name, ctype) \
 	do{ \
-		sl.name##type = get_type(sl_##name##sym); \
-		sl.name##type->init = cvalue_##ctype##_init; \
+		sl_##name##type = get_type(sl_##name##sym); \
+		sl_##name##type->init = cvalue_##ctype##_init; \
 	}while(0)
 
 #define RETURN_NUM_AS(var, type) return(mk_##type(var))
@@ -1304,10 +1303,10 @@
 void
 cvalues_init(void)
 {
-	htable_new(&sl.TypeTable, 256);
-	htable_new(&sl.reverse_dlsym_lookup_table, 256);
+	htable_new(&slg.types, 256);
+	htable_new(&slg.reverse_dlsym_lookup, 256);
 
-	sl.builtintype = define_opaque_type(sl_builtinsym, sizeof(builtin_t), nil, nil);
+	sl_builtintype = define_opaque_type(sl_builtinsym, sizeof(builtin_t), nil, nil);
 
 	ctor_cv_intern(s8, T_S8, s8int);
 	ctor_cv_intern(u8, T_U8, u8int);
@@ -1344,11 +1343,11 @@
 	mk_primtype(double, double);
 
 	ctor_cv_intern(bignum, T_MP, mpint*);
-	sl.mptype = get_type(sl_bignumsym);
-	sl.mptype->init = cvalue_mp_init;
-	sl.mptype->vtable = &mp_vtable;
+	sl_mptype = get_type(sl_bignumsym);
+	sl_mptype->init = cvalue_mp_init;
+	sl_mptype->vtable = &mp_vtable;
 
-	sl.stringtype = get_type(symbol_value(sl_stringtypesym));
-	sl.the_empty_string = cvalue_from_ref(sl.stringtype, (char*)"", 0);
-	sl.runestringtype = get_type(symbol_value(sl_runestringtypesym));
+	sl_stringtype = get_type(symbol_value(sl_stringtypesym));
+	sl_emptystr = cvalue_from_ref(sl_stringtype, (char*)"", 0);
+	sl_runestringtype = get_type(symbol_value(sl_runestringtypesym));
 }
--- a/src/equal.c
+++ b/src/equal.c
@@ -85,7 +85,7 @@
 		if(isfixnum(b))
 			return (sl_fx)a < (sl_fx)b ? fixnum(-1) : fixnum(1);
 		if(iscprim(b)){
-			if(cp_class(ptr(b)) == sl.runetype)
+			if(cp_class(ptr(b)) == sl_runetype)
 				return fixnum(1);
 			return fixnum(numeric_compare(a, b, eq, true, false));
 		}
@@ -106,10 +106,10 @@
 			return bounded_vector_compare(a, b, bound, eq);
 		break;
 	case TAG_CPRIM:
-		if(cp_class(ptr(a)) == sl.runetype){
-			if(!iscprim(b) || cp_class(ptr(b)) != sl.runetype)
+		if(cp_class(ptr(a)) == sl_runetype){
+			if(!iscprim(b) || cp_class(ptr(b)) != sl_runetype)
 				return fixnum(-1);
-		}else if(iscprim(b) && cp_class(ptr(b)) == sl.runetype)
+		}else if(iscprim(b) && cp_class(ptr(b)) == sl_runetype)
 			return fixnum(1);
 		c = numeric_compare(a, b, eq, true, false);
 		if(c != 2)
@@ -345,7 +345,7 @@
 	case TAG_CPRIM:
 		cp = ptr(a);
 		data = cp_data(cp);
-		if(cp_class(cp) == sl.runetype)
+		if(cp_class(cp) == sl_runetype)
 			return inthash(*(Rune*)data);
 		nt = cp_numtype(cp);
 		u.d = conv_to_double(data, nt);
@@ -353,7 +353,7 @@
 	case TAG_CVALUE:
 		cv = ptr(a);
 		data = cv_data(cv);
-		if(cv->type == sl.mptype){
+		if(cv->type == sl_mptype){
 			len = mptobe(*(mpint**)data, nil, 0, (u8int**)&data);
 			h = memhash(data, len);
 			MEM_FREE(data);
--- a/src/iostream.c
+++ b/src/iostream.c
@@ -44,7 +44,7 @@
 static int
 isiostream(sl_v v)
 {
-	return iscvalue(v) && cv_class(ptr(v)) == sl.iostreamtype;
+	return iscvalue(v) && cv_class(ptr(v)) == sl_iostreamtype;
 }
 
 sl_purefn
@@ -89,7 +89,7 @@
 	}
 	if(!r && !w && !c && !t && !a)
 		r = true;  // default to reading
-	sl_v f = cvalue(sl.iostreamtype, sizeof(sl_ios));
+	sl_v f = cvalue(sl_iostreamtype, sizeof(sl_ios));
 	char *fname = tostring(args[0]);
 	sl_ios *s = value2c(sl_ios*, f);
 	if(ios_file(s, fname, r, w, c, t) == nil)
@@ -103,7 +103,7 @@
 {
 	argcount(nargs, 0);
 	USED(args);
-	sl_v f = cvalue(sl.iostreamtype, sizeof(sl_ios));
+	sl_v f = cvalue(sl_iostreamtype, sizeof(sl_ios));
 	sl_ios *s = value2c(sl_ios*, f);
 	if(ios_mem(s, 0) == nil)
 		lerrorf(sl_errmem, "could not allocate stream");
@@ -153,7 +153,7 @@
 	argcount(nargs, 2);
 	sl_ios *s = toiostream(args[0]);
 	sl_cprim *cp = ptr(args[1]);
-	if(!iscprim(args[1]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[1]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[1]);
 	Rune r = *(Rune*)cp_data(cp);
 	return fixnum(ios_pututf8(s, r));
@@ -282,7 +282,7 @@
 	sl_ios *s = toiostream(args[0]);
 	sl_v v = args[1];
 	sl_cprim *cp = ptr(v);
-	if(iscprim(args[1]) && cp_class(cp) == sl.runetype){
+	if(iscprim(args[1]) && cp_class(cp) == sl_runetype){
 		if(nargs > 2)
 			lerrorf(sl_errarg, "offset argument not supported for characters");
 		Rune r = *(Rune*)cp_data(ptr(args[1]));
@@ -305,7 +305,7 @@
 	usize uldelim = tosize(arg);
 	if(uldelim > 0x7f){
 		// runes > 0x7f, or anything else > 0xff, are out of range
-		if((iscprim(arg) && cp_class(ptr(arg)) == sl.runetype) || uldelim > 0xff)
+		if((iscprim(arg) && cp_class(ptr(arg)) == sl_runetype) || uldelim > 0xff)
 			lerrorf(sl_errarg, "delimiter out of range");
 	}
 	return (u8int)uldelim;
@@ -413,9 +413,9 @@
 	}else{
 		u8int *b = ios_takebuf(st, &n); n--;
 		if(n == 0)
-			return sl.the_empty_string;
+			return sl_emptystr;
 		b[n] = '\0';
-		str = cvalue_from_ref(sl.stringtype, b, n);
+		str = cvalue_from_ref(sl_stringtype, b, n);
 		cv_autorelease(ptr(str));
 	}
 	return str;
@@ -429,7 +429,7 @@
 		lerrorf(sl_errarg, "requires memory stream");
 	bool eof = ios_eof(src);
 	sl_v v = stream_to_string(&args[0]);
-	if(eof && v == sl.the_empty_string)
+	if(eof && v == sl_emptystr)
 		v = sl_eof;
 	return v;
 }
@@ -445,8 +445,8 @@
 	sl_truncsym = csymbol(":truncate");
 	sl_instrsym = csymbol("*input-stream*");
 	sl_outstrsym = csymbol("*output-stream*");
-	sl.iostreamtype = define_opaque_type(sl_iostreamsym, sizeof(sl_ios), &iostream_vtable, nil);
-	set(csymbol("*stdout*"), cvalue_from_ref(sl.iostreamtype, ios_stdout, sizeof(sl_ios)));
-	set(csymbol("*stderr*"), cvalue_from_ref(sl.iostreamtype, ios_stderr, sizeof(sl_ios)));
-	set(csymbol("*stdin*"), cvalue_from_ref(sl.iostreamtype, ios_stdin, sizeof(sl_ios)));
+	sl_iostreamtype = define_opaque_type(sl_iostreamsym, sizeof(sl_ios), &iostream_vtable, nil);
+	set(csymbol("*stdout*"), cvalue_from_ref(sl_iostreamtype, ios_stdout, sizeof(sl_ios)));
+	set(csymbol("*stderr*"), cvalue_from_ref(sl_iostreamtype, ios_stderr, sizeof(sl_ios)));
+	set(csymbol("*stdin*"), cvalue_from_ref(sl_iostreamtype, ios_stdin, sizeof(sl_ios)));
 }
--- a/src/print.c
+++ b/src/print.c
@@ -222,7 +222,7 @@
 		const char *s = symbol_name(v);
 		return u8_strwidth(s, strlen(s));
 	}
-	if(iscprim(v) && ptr(v) != nil && cp_class(ptr(v)) == sl.runetype)
+	if(iscprim(v) && ptr(v) != nil && cp_class(ptr(v)) == sl_runetype)
 		return 4;
 	return -1;
 }
@@ -816,8 +816,8 @@
 	void *data = cptr(v);
 	sl_v label;
 
-	if(cv_class(cv) == sl.builtintype){
-		label = (sl_v)ptrhash_get(&sl.reverse_dlsym_lookup_table, cv);
+	if(cv_class(cv) == sl_builtintype){
+		label = (sl_v)ptrhash_get(&slg.reverse_dlsym_lookup, cv);
 		assert(label != (sl_v)HT_NOTFOUND);
 		if(sl.print_princ){
 			outs(f, symbol_name(label));
@@ -865,7 +865,7 @@
 	sl_print_child(f, v);
 
 	if(sl.print_level >= 0 || sl.print_length >= 0)
-		memset(sl.consflags, 0, 4*bitvector_nwords(sl.heapsize/sizeof(sl_cons)));
+		memset(sl.consflags, 0, 4*bitvector_nwords(slg.heapsize/sizeof(sl_cons)));
 
 	if((iscons(v) || isvector(v) || isfunction(v) || iscvalue(v)) &&
 		!sl_isstring(v) && v != sl_t && v != sl_nil && v != sl_void)
--- a/src/read.c
+++ b/src/read.c
@@ -413,7 +413,7 @@
 static sl_v
 read_vector(Rctx *ctx, sl_v label, u32int closer)
 {
-	sl_v v = sl.the_empty_vector, elt;
+	sl_v v = sl_emptyvec, elt;
 	u32int i = 0;
 	PUSH(v);
 	if(label != UNBOUND)
--- a/src/sl.c
+++ b/src/sl.c
@@ -11,7 +11,7 @@
 #include "iostream.h"
 #include "compress.h"
 
-sl_v sl_builtins_table_sym, sl_quote, sl_lambda, sl_function, sl_comma, sl_commaat;
+sl_v sl_builtinssym, sl_quote, sl_lambda, sl_function, sl_comma, sl_commaat;
 sl_v sl_commadot, sl_trycatch, sl_backquote;
 sl_v sl_conssym, sl_symbolsym, sl_fixnumsym, sl_vectorsym, sl_builtinsym, sl_vu8sym;
 sl_v sl_defsym, sl_defmacrosym, sl_forsym, sl_setqsym;
@@ -19,7 +19,8 @@
 sl_v sl_nulsym, sl_alarmsym, sl_backspacesym, sl_tabsym, sl_linefeedsym, sl_newlinesym;
 sl_v sl_vtabsym, sl_pagesym, sl_returnsym, sl_escsym, sl_spacesym, sl_deletesym;
 sl_v sl_errio, sl_errparse, sl_errtype, sl_errarg, sl_errmem;
-sl_v sl_errdiv0, sl_errbounds, sl_err, sl_errkey, sl_errunbound;
+sl_v sl_errdiv0, sl_errbounds, sl_err, sl_errkey, sl_errunbound, sl_erroom;
+sl_v sl_emptyvec, sl_emptystr;
 
 sl_v sl_printwidthsym, sl_printreadablysym, sl_printprettysym, sl_printlengthsym;
 sl_v sl_printlevelsym;
@@ -31,7 +32,17 @@
 sl_v sl_bytesym, sl_runesym, sl_floatsym, sl_doublesym;
 sl_v sl_stringtypesym, sl_runestringtypesym;
 
+sl_type *sl_tabletype, *sl_iostreamtype, *sl_mptype, *sl_builtintype;
+sl_type *sl_s8type, *sl_u8type;
+sl_type *sl_s16type, *sl_u16type;
+sl_type *sl_s32type, *sl_u32type;
+sl_type *sl_s64type, *sl_u64type;
+sl_type *sl_floattype, *sl_doubletype;
+sl_type *sl_bytetype, *sl_runetype;
+sl_type *sl_stringtype, *sl_runestringtype;
+
 sl_thread(Sl *slp);
+Slg slg = {0};
 
 typedef struct {
 	const char *name;
@@ -59,7 +70,7 @@
 _Noreturn void
 sl_exit(int status)
 {
-	sl.exiting = true;
+	slg.exiting = true;
 	sl_gc(false);
 	exit(status);
 }
@@ -67,7 +78,7 @@
 #define sl_TRY \
 	sl_exctx _ctx; int l__tr, l__ca; \
 	_ctx.sp = sl.sp; _ctx.frame = sl.curr_frame; _ctx.rdst = sl.readstate; _ctx.prev = sl.exctx; \
-	_ctx.ngchnd = sl.ngchandles; sl.exctx = &_ctx; \
+	_ctx.ngchnd = slg.ngchandles; sl.exctx = &_ctx; \
 	if(!sl_setjmp(_ctx.buf)) \
 		for(l__tr = 1; l__tr; l__tr = 0, (void)(sl.exctx = sl.exctx->prev))
 
@@ -89,7 +100,7 @@
 	_ctx->frame = sl.curr_frame;
 	_ctx->rdst = sl.readstate;
 	_ctx->prev = sl.exctx;
-	_ctx->ngchnd = sl.ngchandles;
+	_ctx->ngchnd = slg.ngchandles;
 }
 
 void
@@ -115,7 +126,7 @@
 	}
 	if(sl.throwing_frame == 0)
 		sl.throwing_frame = sl.curr_frame;
-	sl.ngchandles = sl.exctx->ngchnd;
+	slg.ngchandles = sl.exctx->ngchnd;
 	sl_exctx *thisctx = sl.exctx;
 	if(sl.exctx->prev)   // don't throw past toplevel
 		sl.exctx = sl.exctx->prev;
@@ -212,9 +223,9 @@
 	int len = strlen(str);
 	sl_sym *v;
 	const char *k;
-	if(!Tgetkv(sl.symtab, str, len, &k, (void**)&v)){
+	if(!Tgetkv(slg.symbols, str, len, &k, (void**)&v)){
 		v = mk_symbol(str, len, copy);
-		sl.symtab = Tsetl(sl.symtab, v->name, len, v);
+		slg.symbols = Tsetl(slg.symbols, v->name, len, v);
 	}
 	return tagptr(v, TAG_SYM);
 }
@@ -223,7 +234,7 @@
 csymbol_(const char *str, int len)
 {
 	sl_sym *v = mk_symbol(str, len, false);
-	sl.symtab = Tsetl(sl.symtab, str, len, v);
+	slg.symbols = Tsetl(slg.symbols, str, len, v);
 	return tagptr(v, TAG_SYM);
 }
 
@@ -232,7 +243,7 @@
 	argcount(nargs, 0);
 	USED(args);
 	sl_gensym *gs = alloc_words(sizeof(sl_gensym)/sizeof(sl_v));
-	gs->id = sl.gensym_ctr++;
+	gs->id = slg.gensym_ctr++;
 	gs->binding = UNBOUND;
 	gs->type = nil;
 	return tagptr(gs, TAG_SYM);
@@ -277,8 +288,8 @@
 {
 	if(ismanaged(v)){
 		sl_gensym *gs = ptr(v);
-		sl.gsnameno = 1-sl.gsnameno;
-		char *n = uint2str(sl.gsname[sl.gsnameno]+1, sizeof(sl.gsname[0])-1, gs->id, 10);
+		slg.gsnameno = 1-slg.gsnameno;
+		char *n = uint2str(slg.gsname[slg.gsnameno]+1, sizeof(slg.gsname[0])-1, gs->id, 10);
 		*(--n) = 'g';
 		return n;
 	}
@@ -292,10 +303,10 @@
 {
 	sl_cons *c;
 
-	if(sl_unlikely(sl.curheap > sl.lim))
+	if(sl_unlikely(slg.curheap > slg.lim))
 		sl_gc(false);
-	c = (sl_cons*)sl.curheap;
-	sl.curheap += sizeof(sl_cons);
+	c = (sl_cons*)slg.curheap;
+	slg.curheap += sizeof(sl_cons);
 	return tagptr(c, TAG_CONS);
 }
 
@@ -309,13 +320,13 @@
 	if(n & 1)
 		n++;
 #endif
-	if(sl_unlikely((sl_v*)sl.curheap > (sl_v*)sl.lim+2-n)){
+	if(sl_unlikely((sl_v*)slg.curheap > (sl_v*)slg.lim+2-n)){
 		sl_gc(false);
-		while(sl_unlikely((sl_v*)sl.curheap > ((sl_v*)sl.lim)+2-n))
+		while(sl_unlikely((sl_v*)slg.curheap > ((sl_v*)slg.lim)+2-n))
 			sl_gc(true);
 	}
-	first = (sl_v*)sl.curheap;
-	sl.curheap += n*sizeof(sl_v);
+	first = (sl_v*)slg.curheap;
+	slg.curheap += n*sizeof(sl_v);
 	return first;
 }
 
@@ -323,7 +334,7 @@
 alloc_vector(usize n, bool init)
 {
 	if(n == 0)
-		return sl.the_empty_vector;
+		return sl_emptyvec;
 	sl_v *c = alloc_words(n+1);
 	sl_v v = tagptr(c, TAG_VECTOR);
 	vector_setsize(v, n);
@@ -339,16 +350,16 @@
 void
 sl_gc_handle(sl_v *pv)
 {
-	if(sl_unlikely(sl.ngchandles >= N_GC_HANDLES))
+	if(sl_unlikely(slg.ngchandles >= N_GC_HANDLES))
 		lerrorf(sl_errmem, "out of gc handles");
-	sl.gchandles[sl.ngchandles++] = pv;
+	slg.gchandles[slg.ngchandles++] = pv;
 }
 
 void
 sl_free_gc_handles(int n)
 {
-	assert(sl.ngchandles >= n);
-	sl.ngchandles -= n;
+	assert(slg.ngchandles >= n);
+	slg.ngchandles -= n;
 }
 
 sl_v
@@ -370,8 +381,8 @@
 				return first;
 			}
 			d = cdr_(v);
-			*pcdr = nc = tagptr((sl_cons*)sl.curheap, TAG_CONS);
-			sl.curheap += sizeof(sl_cons);
+			*pcdr = nc = tagptr((sl_cons*)slg.curheap, TAG_CONS);
+			slg.curheap += sizeof(sl_cons);
 			forward(v, nc);
 			car_(nc) = ismanaged(a) ? relocate(a) : a;
 			pcdr = &cdr_(nc);
@@ -452,7 +463,7 @@
 {
 	const char *k = nil;
 	sl_sym *v;
-	while(Tnext(sl.symtab, &k, (void**)&v)){
+	while(Tnext(slg.symbols, &k, (void**)&v)){
 		if(v->binding != UNBOUND)
 			v->binding = relocate(v->binding);
 	}
@@ -461,12 +472,12 @@
 void
 sl_gc(bool mustgrow)
 {
-	sl.gccalls++;
-	sl.curheap = sl.tospace;
-	if(sl.grew)
-		sl.lim = sl.curheap+sl.heapsize*2-sizeof(sl_cons);
+	slg.gccalls++;
+	slg.curheap = slg.tospace;
+	if(slg.grew)
+		slg.lim = slg.curheap+slg.heapsize*2-sizeof(sl_cons);
 	else
-		sl.lim = sl.curheap+sl.heapsize-sizeof(sl_cons);
+		slg.lim = slg.curheap+slg.heapsize-sizeof(sl_cons);
 
 	sl_v *top, *f;
 	if(sl.throwing_frame > sl.curr_frame){
@@ -484,8 +495,8 @@
 		top = f - 3;
 		f = (sl_v*)*top;
 	}
-	for(int i = 0; i < sl.ngchandles; i++)
-		*sl.gchandles[i] = relocate(*sl.gchandles[i]);
+	for(int i = 0; i < slg.ngchandles; i++)
+		*slg.gchandles[i] = relocate(*slg.gchandles[i]);
 	trace_globals();
 	relocate_typetable();
 	sl_readstate *rs = sl.readstate;
@@ -505,45 +516,45 @@
 		rs = rs->prev;
 	}
 	sl.lasterror = relocate(sl.lasterror);
-	sl.memory_exception_value = relocate(sl.memory_exception_value);
-	sl.the_empty_vector = relocate(sl.the_empty_vector);
-	sl.the_empty_string = relocate(sl.the_empty_string);
+	sl_erroom = relocate(sl_erroom);
+	sl_emptyvec = relocate(sl_emptyvec);
+	sl_emptystr = relocate(sl_emptystr);
 
 	sweep_finalizers();
 
-	void *temp = sl.tospace;
-	sl.tospace = sl.fromspace;
-	sl.fromspace = temp;
+	void *temp = slg.tospace;
+	slg.tospace = slg.fromspace;
+	slg.fromspace = temp;
 
 	// FIXME(sigrid): add some extra to the "used"?
-	sl_segused(sl.fromspace, sl.heapsize, sl.curheap-sl.fromspace);
+	sl_segused(slg.fromspace, slg.heapsize, slg.curheap-slg.fromspace);
 
 	// if we're using > 80% of the space, resize tospace so we have
 	// more space to fill next time. if we grew tospace last time,
 	// grow the other half of the heap this time to catch up.
-	if(sl.grew || ((intptr)(sl.lim-sl.curheap) < (intptr)sl.heapsize/5) || mustgrow){
-		sl_segfree(sl.tospace, sl.heapsize);
-		sl.tospace = sl_segalloc(sl.heapsize*2);
-		if(sl_unlikely(sl.tospace == nil)){
-			sl.tospace = sl_segalloc(sl.heapsize);
-			if(sl.tospace == nil){
+	if(slg.grew || ((intptr)(slg.lim-slg.curheap) < (intptr)slg.heapsize/5) || mustgrow){
+		sl_segfree(slg.tospace, slg.heapsize);
+		slg.tospace = sl_segalloc(slg.heapsize*2);
+		if(sl_unlikely(slg.tospace == nil)){
+			slg.tospace = sl_segalloc(slg.heapsize);
+			if(slg.tospace == nil){
 				// FIXME(sigrid): lost it entirely. give up?
 				// alternatively, wait and try indefinitely?
 				ios_printf(ios_stderr, "lost tospace\n");
 				exit(1);
 			}
-			sl_raise(sl.memory_exception_value);
+			sl_raise(sl_erroom);
 		}
-		if(sl.grew){
-			sl.heapsize *= 2;
-			temp = bitvector_resize(sl.consflags, 0, sl.heapsize/sizeof(sl_cons), 1);
+		if(slg.grew){
+			slg.heapsize *= 2;
+			temp = bitvector_resize(sl.consflags, 0, slg.heapsize/sizeof(sl_cons), 1);
 			if(sl_unlikely(temp == nil))
-				sl_raise(sl.memory_exception_value);
+				sl_raise(sl_erroom);
 			sl.consflags = (u32int*)temp;
 		}
-		sl.grew = !sl.grew;
+		slg.grew = !slg.grew;
 	}
-	if(sl_unlikely((sl_v*)sl.curheap > (sl_v*)sl.lim-2)){
+	if(sl_unlikely((sl_v*)slg.curheap > (sl_v*)slg.lim-2)){
 		// all data was live; gc again and grow heap.
 		// but also always leave at least 4 words available, so a closure
 		// can be allocated without an extra check.
@@ -566,7 +577,7 @@
 	else if(isfunction(f))
 		v = apply_cl(n);
 	else if(sl_likely(isbuiltin(f))){
-		sl_v tab = symbol_value(sl_builtins_table_sym);
+		sl_v tab = symbol_value(sl_builtinssym);
 		if(sl_unlikely(ptr(tab) == nil))
 			unbound_error(tab);
 		saveSP[-n-1] = vector_elt(tab, uintval(f));
@@ -671,7 +682,7 @@
 		return true;
 	if(iscprim(v)){
 		sl_cprim *c = ptr(v);
-		return c->type != sl.runetype && valid_numtype(c->type->numtype);
+		return c->type != sl_runetype && valid_numtype(c->type->numtype);
 	}
 	return false;
 }
@@ -940,7 +951,7 @@
 	csl_v *arr = ptr(args[0]);
 	cv_pin(arr);
 	u8int *data = cv_data(arr);
-	if(sl.loading){
+	if(slg.loading){
 		// read syntax, shifted 48 for compact text representation
 		usize i, sz = cv_len(arr);
 		for(i = 0; i < sz; i++)
@@ -1010,7 +1021,7 @@
 	if(isbuiltin(v))
 		return symbol(builtins[uintval(v)].name, false);
 	if(iscbuiltin(v)){
-		v = (sl_v)ptrhash_get(&sl.reverse_dlsym_lookup_table, ptr(v));
+		v = (sl_v)ptrhash_get(&slg.reverse_dlsym_lookup, ptr(v));
 		if(v == (sl_v)HT_NOTFOUND)
 			return sl_nil;
 		return v;
@@ -1040,7 +1051,7 @@
 				first = lst;
 			else
 				cdr_(lastcons) = lst;
-			lastcons = tagptr((((sl_cons*)sl.curheap)-1), TAG_CONS);
+			lastcons = tagptr((((sl_cons*)slg.curheap)-1), TAG_CONS);
 		}else if(lst != sl_nil){
 			type_error("cons", lst);
 		}
@@ -1165,14 +1176,14 @@
 {
 	USED(args);
 	argcount(nargs, 0);
-	ios_printf(ios_stderr, "heap total     %10"PRIuPTR" bytes\n", sl.heapsize);
-	ios_printf(ios_stderr, "heap free      %10"PRIuPTR" bytes\n", (uintptr)(sl.lim-sl.curheap));
-	ios_printf(ios_stderr, "heap used      %10"PRIuPTR" bytes\n", (uintptr)(sl.curheap-sl.fromspace));
+	ios_printf(ios_stderr, "heap total     %10"PRIuPTR" bytes\n", slg.heapsize);
+	ios_printf(ios_stderr, "heap free      %10"PRIuPTR" bytes\n", (uintptr)(slg.lim-slg.curheap));
+	ios_printf(ios_stderr, "heap used      %10"PRIuPTR" bytes\n", (uintptr)(slg.curheap-slg.fromspace));
 	ios_printf(ios_stderr, "stack          %10"PRIu64" bytes\n", (u64int)sl.nstack*sizeof(sl_v));
-	ios_printf(ios_stderr, "finalizers     %10"PRIu32"\n", (u32int)sl.nfinalizers);
-	ios_printf(ios_stderr, "max finalizers %10"PRIu32"\n", (u32int)sl.maxfinalizers);
-	ios_printf(ios_stderr, "gc handles     %10"PRIu32"\n", (u32int)sl.ngchandles);
-	ios_printf(ios_stderr, "gc calls       %10"PRIu64"\n", (u64int)sl.gccalls);
+	ios_printf(ios_stderr, "finalizers     %10"PRIu32"\n", (u32int)slg.nfinalizers);
+	ios_printf(ios_stderr, "max finalizers %10"PRIu32"\n", (u32int)slg.maxfinalizers);
+	ios_printf(ios_stderr, "gc handles     %10"PRIu32"\n", (u32int)slg.ngchandles);
+	ios_printf(ios_stderr, "gc calls       %10"PRIu64"\n", (u64int)slg.gccalls);
 	ios_printf(ios_stderr, "opcodes        %10d\n", N_OPCODES);
 	return sl_void;
 }
@@ -1194,14 +1205,14 @@
 		return -1;
 	sl.scr_width = 100;
 
-	sl.heapsize = heapsize*sizeof(sl_v);
+	slg.heapsize = heapsize*sizeof(sl_v);
 
-	if((sl.fromspace = sl_segalloc(sl.heapsize)) == nil){
+	if((slg.fromspace = sl_segalloc(slg.heapsize)) == nil){
 failed:
 		MEM_FREE(sl.consflags);
-		MEM_FREE(sl.finalizers);
-		sl_segfree(sl.fromspace, sl.heapsize);
-		sl_segfree(sl.tospace, sl.heapsize);
+		MEM_FREE(slg.finalizers);
+		sl_segfree(slg.fromspace, slg.heapsize);
+		sl_segfree(slg.tospace, slg.heapsize);
 		sl_segfree(sl.stack, stacksize*sizeof(sl_v));
 		htable_free(&sl.printconses);
 		MEM_FREE(slp);
@@ -1208,10 +1219,10 @@
 		return -1;
 	}
 
-	if((sl.tospace = sl_segalloc(sl.heapsize)) == nil)
+	if((slg.tospace = sl_segalloc(slg.heapsize)) == nil)
 		goto failed;
-	sl.curheap = sl.fromspace;
-	sl.lim = sl.curheap+sl.heapsize-sizeof(sl_cons);
+	slg.curheap = slg.fromspace;
+	slg.lim = slg.curheap+slg.heapsize-sizeof(sl_cons);
 
 	if((sl.stack = sl_segalloc(stacksize*sizeof(sl_v))) == nil)
 		goto failed;
@@ -1218,11 +1229,11 @@
 	sl.curr_frame = sl.sp = sl.stack;
 	sl.nstack = stacksize;
 
-	sl.maxfinalizers = 512;
-	if((sl.finalizers = MEM_ALLOC(sl.maxfinalizers * sizeof(*sl.finalizers))) == nil)
+	slg.maxfinalizers = 512;
+	if((slg.finalizers = MEM_ALLOC(slg.maxfinalizers * sizeof(*slg.finalizers))) == nil)
 		goto failed;
 
-	if((sl.consflags = bitvector_new(sl.heapsize/sizeof(sl_cons), 1)) == nil)
+	if((sl.consflags = bitvector_new(slg.heapsize/sizeof(sl_cons), 1)) == nil)
 		goto failed;
 	if((htable_new(&sl.printconses, 32)) == nil)
 		goto failed;
@@ -1273,7 +1284,7 @@
 	sl_spacesym = csymbol("space");
 	sl_deletesym = csymbol("delete");
 	sl_newlinesym = csymbol("newline");
-	sl_builtins_table_sym = csymbol("*builtins*");
+	sl_builtinssym = csymbol("*builtins*");
 
 	set(sl_printprettysym = csymbol("*print-pretty*"), sl_t);
 	set(sl_printreadablysym = csymbol("*print-readably*"), sl_t);
@@ -1289,8 +1300,8 @@
 	setc(csymbol("procedure?"), builtin(OP_FUNCTIONP));
 	setc(csymbol("top-level-bound?"), builtin(OP_BOUNDP));
 
-	sl.the_empty_vector = tagptr(alloc_words(1), TAG_VECTOR);
-	vector_setsize(sl.the_empty_vector, 0);
+	sl_emptyvec = tagptr(alloc_words(1), TAG_VECTOR);
+	vector_setsize(sl_emptyvec, 0);
 
 	cvalues_init();
 
@@ -1298,7 +1309,7 @@
 #if defined(__os_version__)
 	set(csymbol("*os-version*"), cvalue_static_cstring(__os_version__));
 #endif
-	sl.memory_exception_value = mk_list2(sl_errmem, cvalue_static_cstring("out of memory"));
+	sl_erroom = mk_list2(sl_errmem, cvalue_static_cstring("out of memory"));
 
 	const sl_builtinspec *b;
 	for(i = 0, b = builtin_fns; i < nelem(builtin_fns); i++, b++)
@@ -1320,7 +1331,7 @@
 int
 sl_load_system_image(sl_v sys_image_iostream)
 {
-	sl.loading = true;
+	slg.loading = true;
 	PUSH(sys_image_iostream);
 	sl_v *saveSP = sl.sp;
 	sl_TRY{
@@ -1354,6 +1365,6 @@
 		return -1;
 	}
 	sl.sp = saveSP-1;
-	sl.loading = false;
+	slg.loading = false;
 	return 0;
 }
--- a/src/sl.h
+++ b/src/sl.h
@@ -118,7 +118,7 @@
 
 // allocate n consecutive conses
 #define cons_reserve(n) tagptr(alloc_words((n)*2), TAG_CONS)
-#define cons_index(c) (((sl_cons*)ptr(c))-((sl_cons*)sl.fromspace))
+#define cons_index(c) (((sl_cons*)ptr(c))-((sl_cons*)slg.fromspace))
 #define ismarked(c) bitvector_get(sl.consflags, cons_index(c))
 #define mark_cons(c) bitvector_set(sl.consflags, cons_index(c))
 #define unmark_cons(c) bitvector_reset(sl.consflags, cons_index(c))
@@ -154,10 +154,10 @@
 #define iskeyword(s) ((s)->flags & FLAG_KEYWORD)
 #define symbol_value(s) (((sl_sym*)ptr(s))->binding)
 #define sym_to_numtype(s) (((sl_sym*)ptr(s))->numtype)
-#define ismanaged(v) ((((u8int*)ptr(v)) >= sl.fromspace) && (((u8int*)ptr(v)) < sl.fromspace+sl.heapsize))
+#define ismanaged(v) ((((u8int*)ptr(v)) >= slg.fromspace) && (((u8int*)ptr(v)) < slg.fromspace+slg.heapsize))
 #define isgensym(x)  (issymbol(x) && ismanaged(x))
 #define isfunction(x) (tag(x) == TAG_FUNCTION && (x) > (N_BUILTINS<<3))
-#define iscbuiltin(x) (iscvalue(x) && cv_class(ptr(x)) == sl.builtintype)
+#define iscbuiltin(x) (iscvalue(x) && cv_class(ptr(x)) == sl_builtintype)
 // utility for iterating over all arguments in a builtin
 // i=index, i0=start index, arg = var for each arg, args = arg array
 // assumes "nargs" is the argument count
@@ -317,7 +317,7 @@
 #define cv_len(cv) (((csl_v*)(cv))->len)
 #define cv_type(cv) (cv_class(cv)->type)
 #define cv_data(cv) (((csl_v*)(cv))->data)
-#define cv_isstr(cv) (cv_class(cv)->eltype == sl.bytetype)
+#define cv_isstr(cv) (cv_class(cv)->eltype == sl_bytetype)
 #define cv_isPOD(cv) (cv_class(cv)->init != nil)
 #define cvalue_data(v) cv_data((csl_v*)ptr(v))
 #define cvalue_len(v) cv_len((csl_v*)ptr(v))
@@ -348,67 +348,26 @@
 	sl_eof = builtin(OP_EOF_OBJECT),
 };
 
-#define N_GC_HANDLES 1024
+enum {
+	N_GC_HANDLES = 1024,
+};
 
 typedef struct Sl Sl;
+typedef struct Slg Slg;
 
 struct Sl {
 	sl_v *sp;
-	u8int *curheap;
 	sl_v *curr_frame;
 
-	u8int *fromspace;
-	u8int *tospace;
-	u8int *lim;
-
-	sl_v *stack;
-
-	uintptr heapsize;//bytes
-	usize malloc_pressure;
-	u32int nstack;
-
-	csl_v **finalizers;
-	usize nfinalizers;
-	usize maxfinalizers;
-
-	sl_readstate *readstate;
-	Tbl *symtab;
-
 	// saved execution state for an unwind target
 	sl_exctx *exctx;
 	sl_v *throwing_frame;  // active frame when exception was thrown
 	sl_v lasterror;
 
-	sl_type *tabletype;
-
-	sl_type *iostreamtype;
-
-	sl_v the_empty_vector;
-	sl_v the_empty_string;
-	sl_v memory_exception_value;
-
-	sl_type *mptype;
-	sl_type *s8type, *u8type;
-	sl_type *s16type, *u16type;
-	sl_type *s32type, *u32type;
-	sl_type *s64type, *u64type;
-	sl_type *floattype, *doubletype;
-	sl_type *bytetype, *runetype;
-	sl_type *stringtype, *runestringtype;
-	sl_type *builtintype;
-
-	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;
-
-	bool loading;
-	bool exiting;
-	bool grew;
-
+	sl_readstate *readstate;
 	u32int *consflags;
-	usize gccalls;
+	sl_v *stack;
+	u32int nstack;
 
 	sl_htable printconses;
 	u32int printlabel;
@@ -419,17 +378,40 @@
 	sl_fx p_level;
 	int scr_width;
 	ssize hpos, vpos;
+};
 
-	sl_htable reverse_dlsym_lookup_table;
-	sl_htable TypeTable;
+struct Slg {
+	u8int *curheap;
+	u8int *lim;
+	usize malloc_pressure;
+	csl_v **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;
+	bool loading;
+	bool exiting;
+	bool grew;
 	int ngchandles;
 	sl_v *gchandles[N_GC_HANDLES];
+	usize gccalls;
+	sl_htable reverse_dlsym_lookup;
+	sl_htable types;
+	u8int *fromspace;
+	u8int *tospace;
+	uintptr heapsize; // bytes
 };
 
 extern sl_thread(Sl *slp);
 #define sl (*slp)
 
-extern sl_v sl_builtins_table_sym, sl_quote, sl_lambda, sl_function, sl_comma, sl_commaat;
+extern Slg slg;
+
+extern sl_v sl_builtinssym, sl_quote, sl_lambda, sl_function, sl_comma, sl_commaat;
 extern sl_v sl_commadot, sl_trycatch, sl_backquote;
 extern sl_v sl_conssym, sl_symbolsym, sl_fixnumsym, sl_vectorsym, sl_builtinsym, sl_vu8sym;
 extern sl_v sl_defsym, sl_defmacrosym, sl_forsym, sl_setqsym;
@@ -437,7 +419,8 @@
 extern sl_v sl_nulsym, sl_alarmsym, sl_backspacesym, sl_tabsym, sl_linefeedsym, sl_newlinesym;
 extern sl_v sl_vtabsym, sl_pagesym, sl_returnsym, sl_escsym, sl_spacesym, sl_deletesym;
 extern sl_v sl_errio, sl_errparse, sl_errtype, sl_errarg, sl_errmem;
-extern sl_v sl_errdiv0, sl_errbounds, sl_err, sl_errkey, sl_errunbound;
+extern sl_v sl_errdiv0, sl_errbounds, sl_err, sl_errkey, sl_errunbound, sl_erroom;
+extern sl_v sl_emptyvec, sl_emptystr;
 
 extern sl_v sl_printwidthsym, sl_printreadablysym, sl_printprettysym, sl_printlengthsym;
 extern sl_v sl_printlevelsym;
@@ -448,5 +431,14 @@
 extern sl_v sl_s64sym, sl_u64sym, sl_bignumsym;
 extern sl_v sl_bytesym, sl_runesym, sl_floatsym, sl_doublesym;
 extern sl_v sl_stringtypesym, sl_runestringtypesym;
+
+extern sl_type *sl_tabletype, *sl_iostreamtype, *sl_mptype, *sl_builtintype;
+extern sl_type *sl_s8type, *sl_u8type;
+extern sl_type *sl_s16type, *sl_u16type;
+extern sl_type *sl_s32type, *sl_u32type;
+extern sl_type *sl_s64type, *sl_u64type;
+extern sl_type *sl_floattype, *sl_doubletype;
+extern sl_type *sl_bytetype, *sl_runetype;
+extern sl_type *sl_stringtype, *sl_runestringtype;
 
 _Noreturn void slmain(const u8int *boot, int bootsz, int argc, char **argv);
--- a/src/slmain.c
+++ b/src/slmain.c
@@ -101,7 +101,7 @@
 		exit(1);
 	}
 
-	sl_v f = cvalue(sl.iostreamtype, (int)sizeof(sl_ios));
+	sl_v f = cvalue(sl_iostreamtype, (int)sizeof(sl_ios));
 	sl_gc_handle(&f);
 	sl_v args = argv_list(argc, argv);
 	sl_gc_handle(&args);
--- a/src/string.c
+++ b/src/string.c
@@ -46,7 +46,7 @@
 	argcount(nargs, 1);
 	if(iscprim(args[0])){
 		sl_cprim *cp = ptr(args[0]);
-		if(cp_class(cp) == sl.runetype){
+		if(cp_class(cp) == sl_runetype){
 			int w = sl_wcwidth(*(Rune*)cp_data(cp));
 			return w < 0 ? sl_nil : fixnum(w);
 		}
@@ -76,7 +76,7 @@
 	if(iscvalue(args[0])){
 		csl_v *cv = ptr(args[0]);
 		sl_type *t = cv_class(cv);
-		if(t->eltype == sl.runetype){
+		if(t->eltype == sl_runetype){
 			usize nr = cv_len(cv) / sizeof(Rune);
 			Rune *r = (Rune*)cv_data(cv);
 			usize nb = runenlen(r, nr);
@@ -106,7 +106,7 @@
 	usize newsz = nc*sizeof(Rune);
 	if(term)
 		newsz += sizeof(Rune);
-	sl_v runestr = cvalue(sl.runestringtype, newsz);
+	sl_v runestr = cvalue(sl_runestringtype, newsz);
 	ptr = cvalue_data(args[0]);  // relocatable pointer
 	Rune *r = cvalue_data(runestr);
 	for(usize i = 0; i < nb; i++)
@@ -226,7 +226,7 @@
 {
 	argcount(nargs, 1);
 	sl_cprim *cp = ptr(args[0]);
-	if(!iscprim(args[0]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[0]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[0]);
 	return mk_rune(toupperrune(*(Rune*)cp_data(cp)));
 }
@@ -235,7 +235,7 @@
 {
 	argcount(nargs, 1);
 	sl_cprim *cp = ptr(args[0]);
-	if(!iscprim(args[0]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[0]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[0]);
 	return mk_rune(tolowerrune(*(Rune*)cp_data(cp)));
 }
@@ -244,7 +244,7 @@
 {
 	argcount(nargs, 1);
 	sl_cprim *cp = ptr(args[0]);
-	if(!iscprim(args[0]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[0]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[0]);
 	return mk_rune(totitlerune(*(Rune*)cp_data(cp)));
 }
@@ -254,7 +254,7 @@
 {
 	argcount(nargs, 1);
 	sl_cprim *cp = ptr(args[0]);
-	if(!iscprim(args[0]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[0]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[0]);
 	return isalpharune(*(Rune*)cp_data(cp)) ? sl_t : sl_nil;
 }
@@ -264,7 +264,7 @@
 {
 	argcount(nargs, 1);
 	sl_cprim *cp = ptr(args[0]);
-	if(!iscprim(args[0]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[0]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[0]);
 	return islowerrune(*(Rune*)cp_data(cp)) ? sl_t : sl_nil;
 }
@@ -274,7 +274,7 @@
 {
 	argcount(nargs, 1);
 	sl_cprim *cp = ptr(args[0]);
-	if(!iscprim(args[0]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[0]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[0]);
 	return isupperrune(*(Rune*)cp_data(cp)) ? sl_t : sl_nil;
 }
@@ -284,7 +284,7 @@
 {
 	argcount(nargs, 1);
 	sl_cprim *cp = ptr(args[0]);
-	if(!iscprim(args[0]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[0]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[0]);
 	return istitlerune(*(Rune*)cp_data(cp)) ? sl_t : sl_nil;
 }
@@ -294,7 +294,7 @@
 {
 	argcount(nargs, 1);
 	sl_cprim *cp = ptr(args[0]);
-	if(!iscprim(args[0]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[0]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[0]);
 	return isdigitrune(*(Rune*)cp_data(cp)) ? sl_t : sl_nil;
 }
@@ -304,7 +304,7 @@
 {
 	argcount(nargs, 1);
 	sl_cprim *cp = ptr(args[0]);
-	if(!iscprim(args[0]) || cp_class(cp) != sl.runetype)
+	if(!iscprim(args[0]) || cp_class(cp) != sl_runetype)
 		type_error("rune", args[0]);
 	return isspacerune(*(Rune*)cp_data(cp)) ? sl_t : sl_nil;
 }
@@ -325,12 +325,12 @@
 
 	sl_v v = args[1];
 	sl_cprim *cp = ptr(v);
-	if(iscprim(v) && cp_class(cp) == sl.runetype){
+	if(iscprim(v) && cp_class(cp) == sl_runetype){
 		Rune r = *(Rune*)cp_data(cp);
 		needlesz = runetochar(cbuf, &r);
 		needle = cbuf;
 		needle[needlesz] = 0;
-	}else if(iscprim(v) && cp_class(cp) == sl.bytetype){
+	}else if(iscprim(v) && cp_class(cp) == sl_bytetype){
 		needlesz = 1;
 		needle = cbuf;
 		needle[0] = *(char*)cp_data(cp);
--- a/src/table.c
+++ b/src/table.c
@@ -69,7 +69,7 @@
 bool
 ishashtable(sl_v v)
 {
-	return iscvalue(v) && cv_class(ptr(v)) == sl.tabletype;
+	return iscvalue(v) && cv_class(ptr(v)) == sl_tabletype;
 }
 
 sl_purefn
@@ -95,9 +95,9 @@
 	sl_v nt;
 	// prevent small tables from being added to finalizer list
 	if(cnt <= HT_N_INLINE)
-		nt = cvalue_nofinalizer(sl.tabletype, sizeof(sl_htable));
+		nt = cvalue_nofinalizer(sl_tabletype, sizeof(sl_htable));
 	else
-		nt = cvalue(sl.tabletype, sizeof(sl_htable)-inline_space);
+		nt = cvalue(sl_tabletype, sizeof(sl_htable)-inline_space);
 	sl_htable *h = cvalue_data(nt);
 	htable_new(h, cnt/2);
 	sl_v k = sl_nil, arg;
@@ -196,5 +196,5 @@
 void
 table_init(void)
 {
-	sl.tabletype = define_opaque_type(symbol("table", false), sizeof(sl_htable), &table_vtable, nil);
+	sl_tabletype = define_opaque_type(symbol("table", false), sizeof(sl_htable), &table_vtable, nil);
 }
--- a/src/types.c
+++ b/src/types.c
@@ -12,7 +12,7 @@
 		if(ft != nil)
 			return ft;
 	}
-	void **bp = equalhash_bp(&sl.TypeTable, (void*)t);
+	void **bp = equalhash_bp(&slg.types, (void*)t);
 	if(*bp != HT_NOTFOUND){
 		assert(*bp != nil);
 		return *bp;
@@ -74,7 +74,7 @@
 void
 relocate_typetable(void)
 {
-	sl_htable *h = &sl.TypeTable;
+	sl_htable *h = &slg.types;
 	for(int i = 0; i < h->size; i += 2){
 		if(h->table[i] != HT_NOTFOUND){
 			void *nv = (void*)relocate((sl_v)h->table[i]);
--- a/src/vm.h
+++ b/src/vm.h
@@ -295,12 +295,12 @@
 }
 
 OP(OP_CONS) {
-	if(sl.curheap > sl.lim){
+	if(slg.curheap > slg.lim){
 		sl.sp = sp;
 		sl_gc(0);
 	}
-	sl_cons *c = (sl_cons*)sl.curheap;
-	sl.curheap += sizeof(sl_cons);
+	sl_cons *c = (sl_cons*)slg.curheap;
+	slg.curheap += sizeof(sl_cons);
 	c->car = sp[-2];
 	c->cdr = sp[-1];
 	sp[-2] = tagptr(c, TAG_CONS);