shithub: sl

Download patch

ref: 9e0a991374ed0bb6fc8b2a7ca83e5607f77c17ac
parent: f19b5f51f9a9249f5dbf524346a07e1a65eff5b1
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Thu Mar 6 22:47:21 EST 2025

SL(f) -> sl.f (thanks ori)

--- 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(sl.symtab, &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(sl.nfinalizers == sl.maxfinalizers){
+		sl.maxfinalizers *= 2;
+		sl.finalizers = MEM_REALLOC(sl.finalizers, sl.maxfinalizers*sizeof(sl.finalizers));
+		assert(sl.finalizers != nil);
 	}
-	SL(finalizers)[SL(nfinalizers)++] = cv;
+	sl.finalizers[sl.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 = sl.finalizers;
+	usize n = 0, ndel = 0, l = sl.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 = sl.exiting;
 	do{
 		tmp = lst[n];
 		if(isforwarded((sl_v)tmp)){
@@ -55,9 +55,9 @@
 		}
 	}while((n < l-ndel) && SWAP_sf(lst[n], lst[n+ndel]));
 
-	SL(nfinalizers) -= ndel;
+	sl.nfinalizers -= ndel;
 
-	SL(malloc_pressure) = 0;
+	sl.malloc_pressure = 0;
 }
 
 // compute the size of the metadata object for a cvalue
@@ -97,9 +97,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.the_empty_string;
 		sz++;
 		str = true;
 	}
@@ -112,13 +112,13 @@
 		if(!nofinalize && type->vtable != nil && type->vtable->finalize != nil)
 			add_finalizer(pcv);
 	}else{
-		if(SL(malloc_pressure) > ALLOC_LIMIT_TRIGGER)
+		if(sl.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;
+		sl.malloc_pressure += sz;
 	}
 	if(str)
 		((char*)pcv->data)[--sz] = '\0';
@@ -152,8 +152,8 @@
 cvalue_string(usize sz)
 {
 	if(sz == 0)
-		return SL(the_empty_string);
-	return cvalue(SL(stringtype), sz);
+		return sl.the_empty_string;
+	return cvalue(sl.stringtype, sz);
 }
 
 sl_v
@@ -160,8 +160,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.the_empty_string;
+	return cvalue_from_ref(sl.stringtype, (char*)str, strlen(str));
 }
 
 sl_v
@@ -236,10 +236,10 @@
 	{ \
 		if(nargs == 0){ \
 			PUSH(fixnum(0)); \
-			args = SL(sp)-1; \
+			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 +246,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; \
 	}
@@ -292,10 +292,10 @@
 {
 	if(nargs == 0){
 		PUSH(fixnum(0));
-		args = SL(sp)-1;
+		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 +303,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 +529,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 +603,7 @@
 	if(t->vtable != nil && t->vtable->relocate != nil)
 		t->vtable->relocate(v, ncv);
 	forward(v, ncv);
-	if(SL(exiting))
+	if(sl.exiting)
 		cv_autorelease(ptr(ncv));
 	return ncv;
 }
@@ -791,13 +791,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(&sl.reverse_dlsym_lookup_table, cv, (void*)sym);
 
 	return s->binding;
 }
@@ -821,8 +821,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 +1304,10 @@
 void
 cvalues_init(void)
 {
-	htable_new(&SL(TypeTable), 256);
-	htable_new(&SL(reverse_dlsym_lookup_table), 256);
+	htable_new(&sl.TypeTable, 256);
+	htable_new(&sl.reverse_dlsym_lookup_table, 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 +1344,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.the_empty_string = 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.the_empty_string;
 		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.the_empty_string)
 		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
@@ -12,9 +12,9 @@
 {
 	ios_putc(f, c);
 	if(c == '\n')
-		SL(hpos) = 0;
+		sl.hpos = 0;
 	else
-		SL(hpos)++;
+		sl.hpos++;
 }
 
 static inline void
@@ -23,7 +23,7 @@
 	ios_write(f, s, n);
 	ssize w = u8_strwidth(s, n);
 	if(w > 0)
-		SL(hpos) += w;
+		sl.hpos += w;
 }
 
 static inline void
@@ -36,12 +36,12 @@
 outindent(sl_ios *f, int n)
 {
 	// move back to left margin if we get too indented
-	if(n > SL(scr_width)-12)
+	if(n > sl.scr_width-12)
 		n = 2;
 	int n0 = n;
 	ios_putc(f, '\n');
-	SL(vpos)++;
-	SL(hpos) = n;
+	sl.vpos++;
+	sl.hpos = n;
 	while(n >= 8){
 		ios_putc(f, '\t');
 		n -= 8;
@@ -71,9 +71,9 @@
 	sl_v *bp;
 	while(iscons(v)){
 		if(ismarked(v)){
-			bp = (sl_v*)ptrhash_bp(&SL(printconses), (void*)v);
+			bp = (sl_v*)ptrhash_bp(&sl.printconses, (void*)v);
 			if(*bp == (sl_v)HT_NOTFOUND)
-				*bp = fixnum(SL(printlabel)++);
+				*bp = fixnum(sl.printlabel++);
 			return;
 		}
 		mark_cons(v);
@@ -83,9 +83,9 @@
 	if(!ismanaged(v) || issymbol(v))
 		return;
 	if(ismarked(v)){
-		bp = (sl_v*)ptrhash_bp(&SL(printconses), (void*)v);
+		bp = (sl_v*)ptrhash_bp(&sl.printconses, (void*)v);
 		if(*bp == (sl_v)HT_NOTFOUND)
-			*bp = fixnum(SL(printlabel)++);
+			*bp = fixnum(sl.printlabel++);
 		return;
 	}
 	if(isvector(v)){
@@ -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;
 }
@@ -264,7 +264,7 @@
 	sl_v c = car_(v);
 	if(c == sl_lambda || c == sl_setqsym)
 		return false;
-	//if(c == SL(IF)) // TODO: others
+	//if(c == sl.IF) // TODO: others
 	//	return !allsmallp(cdr_(v));
 	return false;
 }
@@ -285,7 +285,7 @@
 	sl_v cd;
 	const char *op;
 	if(iscons(cdr_(v)) && cdr_(cdr_(v)) == sl_nil &&
-		!ptrhash_has(&SL(printconses), (void*)cdr_(v)) &&
+		!ptrhash_has(&sl.printconses, (void*)cdr_(v)) &&
 		((car_(v) == sl_quote     && (op = "'"))  ||
 		 (car_(v) == sl_backquote && (op = "`"))  ||
 		 (car_(v) == sl_comma     && (op = ","))  ||
@@ -298,9 +298,9 @@
 		sl_print_child(f, car_(cdr_(v)));
 		return;
 	}
-	int startpos = SL(hpos);
+	int startpos = sl.hpos;
 	outc(f, '(');
-	int newindent = SL(hpos);
+	int newindent = sl.hpos;
 	int lastv, n = 0, si, ind, est, nextsmall, thistiny;
 	bool always = false, blk = blockindent(v);
 	if(!blk)
@@ -311,14 +311,14 @@
 	int n_unindented = 1;
 	while(1){
 		cd = cdr_(v);
-		if(SL(print_length) >= 0 && n >= SL(print_length) && cd != sl_nil){
+		if(sl.print_length >= 0 && n >= sl.print_length && cd != sl_nil){
 			outsn(f, "...)", 4);
 			break;
 		}
-		lastv = SL(vpos);
+		lastv = sl.vpos;
 		unmark_cons(v);
 		sl_print_child(f, car_(v));
-		if(!iscons(cd) || ptrhash_has(&SL(printconses), (void*)cd)){
+		if(!iscons(cd) || ptrhash_has(&sl.printconses, (void*)cd)){
 			if(cd != sl_nil){
 				outsn(f, " . ", 3);
 				sl_print_child(f, cd);
@@ -327,7 +327,7 @@
 			break;
 		}
 
-		if(!SL(print_pretty) ||
+		if(!sl.print_pretty ||
 			(head == sl_lambda && n == 0)){
 			// never break line before lambda-list
 			ind = 0;
@@ -335,12 +335,12 @@
 			est = lengthestimate(car_(cd));
 			nextsmall = smallp(car_(cd));
 			thistiny = tinyp(car_(v));
-			ind = ((SL(vpos) > lastv ||
-					(SL(hpos)>SL(scr_width)/2 && !nextsmall && !thistiny && n>0)) ||
+			ind = ((sl.vpos > lastv ||
+					(sl.hpos>sl.scr_width/2 && !nextsmall && !thistiny && n>0)) ||
 
-				   (SL(hpos) > SL(scr_width)-4) ||
+				   (sl.hpos > sl.scr_width-4) ||
 
-				   (est != -1 && SL(hpos)+est > SL(scr_width)-2) ||
+				   (est != -1 && sl.hpos+est > sl.scr_width-2) ||
 
 				   (head == sl_lambda && !nextsmall) ||
 
@@ -366,7 +366,7 @@
 				if(si != -1)
 					newindent = startpos + si;
 				else if(!blk)
-					newindent = SL(hpos);
+					newindent = sl.hpos;
 			}
 		}
 		n++;
@@ -380,12 +380,12 @@
 print_circle_prefix(sl_ios *f, sl_v v)
 {
 	sl_v label;
-	if((label = (sl_v)ptrhash_get(&SL(printconses), (void*)v)) != (sl_v)HT_NOTFOUND){
+	if((label = (sl_v)ptrhash_get(&sl.printconses, (void*)v)) != (sl_v)HT_NOTFOUND){
 		if(!ismarked(v)){
-			SL(hpos) += ios_printf(f, "#%"PRIdPTR"#", (intptr)numval(label));
+			sl.hpos += ios_printf(f, "#%"PRIdPTR"#", (intptr)numval(label));
 			return true;
 		}
-		SL(hpos) += ios_printf(f, "#%"PRIdPTR"=", (intptr)numval(label));
+		sl.hpos += ios_printf(f, "#%"PRIdPTR"=", (intptr)numval(label));
 	}
 	if(ismanaged(v))
 		unmark_cons(v);
@@ -396,19 +396,19 @@
 sl_print_child(sl_ios *f, sl_v v)
 {
 	const char *name;
-	if(SL(print_level) >= 0 && SL(p_level) >= SL(print_level) && (iscons(v) || isvector(v) || isfunction(v))){
+	if(sl.print_level >= 0 && sl.p_level >= sl.print_level && (iscons(v) || isvector(v) || isfunction(v))){
 		outc(f, '#');
 		return;
 	}
-	SL(p_level)++;
+	sl.p_level++;
 
 	switch(tag(v)){
 	case TAG_NUM: case TAG_NUM1:
-		SL(hpos) += ios_printf(f, "%"PRIdFIXNUM, numval(v));
+		sl.hpos += ios_printf(f, "%"PRIdFIXNUM, numval(v));
 		break;
 	case TAG_SYM:
 		name = symbol_name(v);
-		if(SL(print_princ))
+		if(sl.print_princ)
 			outs(f, name);
 		else if(ismanaged(v)){
 			outsn(f, "#:", 2);
@@ -426,12 +426,12 @@
 		else if(v == sl_void){
 			outsn(f, "#<void>", 7);
 		}else if(isbuiltin(v)){
-			if(!SL(print_princ))
+			if(!sl.print_princ)
 				outsn(f, "#.", 2);
 			outs(f, builtins[uintval(v)].name);
 		}else{
 			assert(isfunction(v));
-			if(!SL(print_princ)){
+			if(!sl.print_princ){
 				if(print_circle_prefix(f, v))
 					break;
 				sl_fn *fn = ptr(v);
@@ -468,26 +468,26 @@
 	case TAG_CVALUE:
 	case TAG_VECTOR:
 	case TAG_CONS:
-		if(!SL(print_princ) && print_circle_prefix(f, v))
+		if(!sl.print_princ && print_circle_prefix(f, v))
 			break;
 		if(isvector(v)){
 			outs(f, "#(");
-			int newindent = SL(hpos), est;
+			int newindent = sl.hpos, est;
 			int i, sz = vector_size(v);
 			for(i = 0; i < sz; i++){
-				if(SL(print_length) >= 0 && i >= SL(print_length) && i < sz-1){
+				if(sl.print_length >= 0 && i >= sl.print_length && i < sz-1){
 					outsn(f, "...", 3);
 					break;
 				}
 				sl_print_child(f, vector_elt(v, i));
 				if(i < sz-1){
-					if(!SL(print_pretty))
+					if(!sl.print_pretty)
 						outc(f, ' ');
 					else{
 						est = lengthestimate(vector_elt(v, i+1));
-						if(SL(hpos) > SL(scr_width)-4 ||
-						   (est != -1 && (SL(hpos)+est > SL(scr_width)-2)) ||
-						   (SL(hpos) > SL(scr_width)/2 && !smallp(vector_elt(v, i+1)) && !tinyp(vector_elt(v, i))))
+						if(sl.hpos > sl.scr_width-4 ||
+						   (est != -1 && (sl.hpos+est > sl.scr_width-2)) ||
+						   (sl.hpos > sl.scr_width/2 && !smallp(vector_elt(v, i+1)) && !tinyp(vector_elt(v, i))))
 							newindent = outindent(f, newindent);
 						else
 							outc(f, ' ');
@@ -503,7 +503,7 @@
 			print_cons(f, v);
 		break;
 	}
-	SL(p_level)--;
+	sl.p_level--;
 }
 
 static void
@@ -643,18 +643,18 @@
 {
 	if(type == sl_bytesym){
 		u8int ch = *(u8int*)data;
-		if(SL(print_princ))
+		if(sl.print_princ)
 			outc(f, ch);
 		else if(weak)
-			SL(hpos) += ios_printf(f, "0x%hhx", ch);
+			sl.hpos += ios_printf(f, "0x%hhx", ch);
 		else
-			SL(hpos) += ios_printf(f, "#byte(0x%hhx)", ch);
+			sl.hpos += ios_printf(f, "#byte(0x%hhx)", ch);
 	}else if(type == sl_runesym){
 		Rune r = *(Rune*)data;
 		char seq[UTFmax+1];
 		int nb = runetochar(seq, &r);
 		seq[nb] = '\0';
-		if(SL(print_princ)){
+		if(sl.print_princ){
 			outsn(f, seq, nb);
 		}else{
 			outsn(f, "#\\", 2);
@@ -674,7 +674,7 @@
 				if(sl_iswprint(r))
 					outs(f, seq);
 				else
-					SL(hpos) += ios_printf(f, "x%04"PRIx32, r);
+					sl.hpos += ios_printf(f, "x%04"PRIx32, r);
 				break;
 			}
 		}
@@ -697,8 +697,8 @@
 				rep = signbit(d) ? "-nan.0" : "+nan.0";
 			else
 				rep = signbit(d) ? "-wtf.0" : "+wtf.0";
-			if(type == sl_floatsym && !SL(print_princ) && !weak)
-				SL(hpos) += ios_printf(f, "#%s(%s)", symbol_name(type), rep);
+			if(type == sl_floatsym && !sl.print_princ && !weak)
+				sl.hpos += ios_printf(f, "#%s(%s)", symbol_name(type), rep);
 			else
 				outs(f, rep);
 		}else if(d == 0){
@@ -706,7 +706,7 @@
 				outsn(f, "-0.0", 4);
 			else
 				outsn(f, "0.0", 3);
-			if(type == sl_floatsym && !SL(print_princ) && !weak)
+			if(type == sl_floatsym && !sl.print_princ && !weak)
 				outc(f, 'f');
 		}else{
 			snprint_real(buf, sizeof(buf), d, 0, ndec, 3, 10);
@@ -714,19 +714,19 @@
 			outs(f, buf);
 			if(!hasdec)
 				outsn(f, ".0", 2);
-			if(type == sl_floatsym && !SL(print_princ) && !weak)
+			if(type == sl_floatsym && !sl.print_princ && !weak)
 				outc(f, 'f');
 		}
 	}else if(type == sl_u64sym){
 		u64int ui64 = *(u64int*)data;
-		if(weak || SL(print_princ))
-			SL(hpos) += ios_printf(f, "%"PRIu64, ui64);
+		if(weak || sl.print_princ)
+			sl.hpos += ios_printf(f, "%"PRIu64, ui64);
 		else
-			SL(hpos) += ios_printf(f, "#%s(%"PRIu64")", symbol_name(type), ui64);
+			sl.hpos += ios_printf(f, "#%s(%"PRIu64")", symbol_name(type), ui64);
 	}else if(type == sl_bignumsym){
 		mpint *i = *(mpint**)data;
 		char *s = mptoa(i, 10, nil, 0);
-		SL(hpos) += ios_printf(f, "%s", s);
+		sl.hpos += ios_printf(f, "%s", s);
 		MEM_FREE(s);
 	}else if(issymbol(type)){
 		// handle other integer prims. we know it's smaller than uint64
@@ -734,12 +734,12 @@
 		sl_numtype nt = sym_to_numtype(type);
 		if(valid_numtype(nt)){
 			s64int i64 = conv_to_s64(data, nt);
-			if(weak || SL(print_princ))
-				SL(hpos) += ios_printf(f, "%"PRId64, i64);
+			if(weak || sl.print_princ)
+				sl.hpos += ios_printf(f, "%"PRId64, i64);
 			else
-				SL(hpos) += ios_printf(f, "#%s(%"PRId64")", symbol_name(type), i64);
+				sl.hpos += ios_printf(f, "#%s(%"PRId64")", symbol_name(type), i64);
 		}else{
-			SL(hpos) += ios_printf(f, "#<%s>", symbol_name(type));
+			sl.hpos += ios_printf(f, "#<%s>", symbol_name(type));
 		}
 	}else if(iscons(type)){
 		if(car_(type) == sl_arraysym){
@@ -755,14 +755,14 @@
 				cnt = elsize ? len/elsize : 0;
 			}
 			if(eltype == sl_bytesym){
-				if(SL(print_princ)){
+				if(sl.print_princ){
 					ios_write(f, data, len);
 					/*
 					char *nl = llt_memrchr(data, '\n', len);
 					if(nl)
-						SL(hpos) = u8_strwidth(nl+1);
+						sl.hpos = u8_strwidth(nl+1);
 					else
-						SL(hpos) += u8_strwidth(data);
+						sl.hpos += u8_strwidth(data);
 					*/
 				}else{
 					outc(f, '"');
@@ -772,17 +772,17 @@
 				return;
 			}else if(eltype == sl_runesym){
 				char buf[UTFmax+1];
-				if(!SL(print_princ))
+				if(!sl.print_princ)
 					outc(f, '"');
 				for(i = 0; i < cnt; i++, data = (char*)data + elsize){
 					int n = runetochar(buf, (Rune*)data);
 					buf[n] = 0;
-					if(SL(print_princ))
+					if(sl.print_princ)
 						ios_write(f, buf, n);
 					else
 						print_string(f, buf, n);
 				}
-				if(!SL(print_princ))
+				if(!sl.print_princ)
 					outc(f, '"');
 				return;
 			}
@@ -816,10 +816,10 @@
 	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(&sl.reverse_dlsym_lookup_table, cv);
 		assert(label != (sl_v)HT_NOTFOUND);
-		if(SL(print_princ)){
+		if(sl.print_princ){
 			outs(f, symbol_name(label));
 		}else{
 			outsn(f, "#fn(", 4);
@@ -841,33 +841,33 @@
 	sl_v pw = symbol_value(sl_printwidthsym);
 	if(!isfixnum(pw))
 		return;
-	SL(scr_width) = numval(pw);
+	sl.scr_width = numval(pw);
 }
 
 void
 sl_print(sl_ios *f, sl_v v)
 {
-	SL(print_pretty) = symbol_value(sl_printprettysym) != sl_nil;
-	if(SL(print_pretty))
+	sl.print_pretty = symbol_value(sl_printprettysym) != sl_nil;
+	if(sl.print_pretty)
 		set_print_width();
-	SL(print_princ) = symbol_value(sl_printreadablysym) == sl_nil;
+	sl.print_princ = symbol_value(sl_printreadablysym) == sl_nil;
 	sl_v pl = symbol_value(sl_printlengthsym);
-	SL(print_length) = isfixnum(pl) ? numval(pl) : -1;
+	sl.print_length = isfixnum(pl) ? numval(pl) : -1;
 	pl = symbol_value(sl_printlevelsym);
-	SL(print_level) = isfixnum(pl) ? numval(pl) : -1;
-	SL(p_level) = 0;
+	sl.print_level = isfixnum(pl) ? numval(pl) : -1;
+	sl.p_level = 0;
 
-	SL(printlabel) = 0;
-	if(!SL(print_princ))
+	sl.printlabel = 0;
+	if(!sl.print_princ)
 		print_traverse(v);
-	SL(hpos) = SL(vpos) = 0;
+	sl.hpos = sl.vpos = 0;
 
 	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)));
+	if(sl.print_level >= 0 || sl.print_length >= 0)
+		memset(sl.consflags, 0, 4*bitvector_nwords(sl.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)
-		htable_reset(&SL(printconses), 32);
+		htable_reset(&sl.printconses, 32);
 }
--- a/src/read.c
+++ b/src/read.c
@@ -24,7 +24,7 @@
 
 static sl_v do_read_sexpr(Rctx *ctx, sl_v label);
 
-#define RS value2c(sl_ios*, SL(readstate)->source)
+#define RS value2c(sl_ios*, sl.readstate->source)
 
 bool
 sl_read_numtok(const char *tok, sl_v *pval, int base)
@@ -397,11 +397,11 @@
 	PUSH(v);
 	assert(s+d > s);
 	sl_v newv = alloc_vector(s+d, 1);
-	v = SL(sp)[-1];
+	v = sl.sp[-1];
 	for(i = 0; i < s; i++)
 		vector_elt(newv, i) = vector_elt(v, i);
 	// use gc to rewrite references from the old vector to the new
-	SL(sp)[-1] = newv;
+	sl.sp[-1] = newv;
 	if(s > 0 && rewrite_refs){
 		((usize*)ptr(v))[0] |= 0x1;
 		vector_elt(v, 0) = newv;
@@ -413,22 +413,22 @@
 static sl_v
 read_vector(Rctx *ctx, sl_v label, u32int closer)
 {
-	sl_v v = SL(the_empty_vector), elt;
+	sl_v v = sl.the_empty_vector, elt;
 	u32int i = 0;
 	PUSH(v);
 	if(label != UNBOUND)
-		ptrhash_put(&SL(readstate)->backrefs, (void*)label, (void*)v);
+		ptrhash_put(&sl.readstate->backrefs, (void*)label, (void*)v);
 	while(peek(ctx) != closer){
 		if(ios_eof(RS))
 			parse_error(&ctx->loc, "unexpected end of input");
-		v = SL(sp)[-1]; // reload after possible alloc in peek()
+		v = sl.sp[-1]; // reload after possible alloc in peek()
 		if(i >= vector_size(v)){
-			v = SL(sp)[-1] = vector_grow(v, label != UNBOUND);
+			v = sl.sp[-1] = vector_grow(v, label != UNBOUND);
 			if(label != UNBOUND)
-				ptrhash_put(&SL(readstate)->backrefs, (void*)label, (void*)v);
+				ptrhash_put(&sl.readstate->backrefs, (void*)label, (void*)v);
 		}
 		elt = do_read_sexpr(ctx, UNBOUND);
-		v = SL(sp)[-1];
+		v = sl.sp[-1];
 		assert(i < vector_size(v));
 		vector_elt(v, i) = elt;
 		i++;
@@ -555,9 +555,9 @@
 
 	loc0 = RS->loc;
 	loc0.colno--;
-	ipval = SL(sp)-1;
+	ipval = sl.sp-1;
 	PUSH(sl_nil);
-	ipc = SL(sp)-1; // to keep track of current cons cell
+	ipc = sl.sp-1; // to keep track of current cons cell
 	t = peek(ctx);
 	while(t != closer){
 		if(ios_eof(RS))
@@ -570,7 +570,7 @@
 			pval = ipval;
 			*pval = c;
 			if(label != UNBOUND)
-				ptrhash_put(&SL(readstate)->backrefs, (void*)label, (void*)c);
+				ptrhash_put(&sl.readstate->backrefs, (void*)label, (void*)c);
 		}
 		*pc = c;
 		c = do_read_sexpr(ctx, UNBOUND);
@@ -645,9 +645,9 @@
 		car_(cdr_(v)) = cdr_(cdr_(v)) = sl_nil;
 		PUSH(v);
 		if(label != UNBOUND)
-			ptrhash_put(&SL(readstate)->backrefs, (void*)label, (void*)v);
+			ptrhash_put(&sl.readstate->backrefs, (void*)label, (void*)v);
 		v = do_read_sexpr(ctx, UNBOUND);
-		car_(cdr_(SL(sp)[-1])) = v;
+		car_(cdr_(sl.sp[-1])) = v;
 		return POP();
 	case TOK_SHARPQUOTE:
 		// StreetLISP doesn't need symbol-function, so #' does nothing
@@ -665,7 +665,7 @@
 		read_list(ctx, UNBOUND, TOK_CLOSE);
 		if(sym == sl_vu8sym){
 			sym = sl_arraysym;
-			SL(sp)[-1] = mk_cons(sl_u8sym, SL(sp)[-1]);
+			sl.sp[-1] = mk_cons(sl_u8sym, sl.sp[-1]);
 		}else if(sym == sl_fnsym){
 			sym = sl_function;
 		}
@@ -691,20 +691,20 @@
 		return sl_toplevel_eval(sym);
 	case TOK_LABEL:
 		// create backreference label
-		if(ptrhash_has(&SL(readstate)->backrefs, (void*)ctx->tokval))
+		if(ptrhash_has(&sl.readstate->backrefs, (void*)ctx->tokval))
 			parse_error(&ctx->loc, "label %"PRIdPTR" redefined", (intptr)numval(ctx->tokval));
 		oldtokval = ctx->tokval;
 		v = do_read_sexpr(ctx, ctx->tokval);
-		ptrhash_put(&SL(readstate)->backrefs, (void*)oldtokval, (void*)v);
+		ptrhash_put(&sl.readstate->backrefs, (void*)oldtokval, (void*)v);
 		return v;
 	case TOK_BACKREF:
 		// look up backreference
-		v = (sl_v)ptrhash_get(&SL(readstate)->backrefs, (void*)ctx->tokval);
+		v = (sl_v)ptrhash_get(&sl.readstate->backrefs, (void*)ctx->tokval);
 		if(v == (sl_v)HT_NOTFOUND)
 			parse_error(&ctx->loc, "undefined label %"PRIdPTR, (intptr)numval(ctx->tokval));
 		return v;
 	case TOK_GENSYM:
-		pv = (sl_v*)ptrhash_bp(&SL(readstate)->gensyms, (void*)ctx->tokval);
+		pv = (sl_v*)ptrhash_bp(&sl.readstate->gensyms, (void*)ctx->tokval);
 		if(*pv == (sl_v)HT_NOTFOUND)
 			*pv = gensym();
 		return *pv;
@@ -726,11 +726,11 @@
 sl_read_sexpr(sl_v f)
 {
 	sl_readstate state;
-	state.prev = SL(readstate);
+	state.prev = sl.readstate;
 	htable_new(&state.backrefs, 8);
 	htable_new(&state.gensyms, 8);
 	state.source = f;
-	SL(readstate) = &state;
+	sl.readstate = &state;
 	Rctx ctx;
 	ctx.toktype = TOK_NONE;
 	sl_gc_handle(&ctx.tokval);
@@ -738,7 +738,7 @@
 	sl_v v = do_read_sexpr(&ctx, UNBOUND);
 
 	sl_free_gc_handles(1);
-	SL(readstate) = state.prev;
+	sl.readstate = state.prev;
 	free_readstate(&state);
 	return v;
 }
--- a/src/sl.c
+++ b/src/sl.c
@@ -31,7 +31,7 @@
 sl_v sl_bytesym, sl_runesym, sl_floatsym, sl_doublesym;
 sl_v sl_stringtypesym, sl_runestringtypesym;
 
-sl_thread(Sl *sl);
+sl_thread(Sl *slp);
 
 typedef struct {
 	const char *name;
@@ -59,7 +59,7 @@
 _Noreturn void
 sl_exit(int status)
 {
-	SL(exiting) = true;
+	sl.exiting = true;
 	sl_gc(false);
 	exit(status);
 }
@@ -66,13 +66,13 @@
 
 #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.sp = sl.sp; _ctx.frame = sl.curr_frame; _ctx.rdst = sl.readstate; _ctx.prev = sl.exctx; \
+	_ctx.ngchnd = sl.ngchandles; sl.exctx = &_ctx; \
 	if(!sl_setjmp(_ctx.buf)) \
-		for(l__tr = 1; l__tr; l__tr = 0, (void)(SL(exctx) = SL(exctx)->prev))
+		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) = _ctx.sp, SL(curr_frame) = _ctx.frame
+	l__ca = 0, sl.lasterror = sl_nil, sl.throwing_frame = 0, sl.sp = _ctx.sp, sl.curr_frame = _ctx.frame
 
 #define sl_CATCH \
 	else \
@@ -85,20 +85,20 @@
 void
 sl_savestate(sl_exctx *_ctx)
 {
-	_ctx->sp = SL(sp);
-	_ctx->frame = SL(curr_frame);
-	_ctx->rdst = SL(readstate);
-	_ctx->prev = SL(exctx);
-	_ctx->ngchnd = SL(ngchandles);
+	_ctx->sp = sl.sp;
+	_ctx->frame = sl.curr_frame;
+	_ctx->rdst = sl.readstate;
+	_ctx->prev = sl.exctx;
+	_ctx->ngchnd = sl.ngchandles;
 }
 
 void
 sl_restorestate(sl_exctx *_ctx)
 {
-	SL(lasterror) = sl_nil;
-	SL(throwing_frame) = 0;
-	SL(sp) = _ctx->sp;
-	SL(curr_frame) = _ctx->frame;
+	sl.lasterror = sl_nil;
+	sl.throwing_frame = 0;
+	sl.sp = _ctx->sp;
+	sl.curr_frame = _ctx->frame;
 }
 
 _Noreturn void
@@ -107,18 +107,18 @@
 	ios_flush(ios_stdout);
 	ios_flush(ios_stderr);
 
-	SL(lasterror) = e;
+	sl.lasterror = e;
 	// unwind read state
-	while(SL(readstate) != SL(exctx)->rdst){
-		free_readstate(SL(readstate));
-		SL(readstate) = SL(readstate)->prev;
+	while(sl.readstate != sl.exctx->rdst){
+		free_readstate(sl.readstate);
+		sl.readstate = sl.readstate->prev;
 	}
-	if(SL(throwing_frame) == 0)
-		SL(throwing_frame) = SL(curr_frame);
-	SL(ngchandles) = SL(exctx)->ngchnd;
-	sl_exctx *thisctx = SL(exctx);
-	if(SL(exctx)->prev)   // don't throw past toplevel
-		SL(exctx) = SL(exctx)->prev;
+	if(sl.throwing_frame == 0)
+		sl.throwing_frame = sl.curr_frame;
+	sl.ngchandles = sl.exctx->ngchnd;
+	sl_exctx *thisctx = sl.exctx;
+	if(sl.exctx->prev)   // don't throw past toplevel
+		sl.exctx = sl.exctx->prev;
 	sl_longjmp(thisctx->buf, 1);
 }
 
@@ -212,9 +212,9 @@
 	int len = strlen(str);
 	sl_sym *v;
 	const char *k;
-	if(!Tgetkv(SL(symtab), str, len, &k, (void**)&v)){
+	if(!Tgetkv(sl.symtab, str, len, &k, (void**)&v)){
 		v = mk_symbol(str, len, copy);
-		SL(symtab) = Tsetl(SL(symtab), v->name, len, v);
+		sl.symtab = Tsetl(sl.symtab, v->name, len, v);
 	}
 	return tagptr(v, TAG_SYM);
 }
@@ -223,7 +223,7 @@
 csymbol_(const char *str, int len)
 {
 	sl_sym *v = mk_symbol(str, len, false);
-	SL(symtab) = Tsetl(SL(symtab), str, len, v);
+	sl.symtab = Tsetl(sl.symtab, str, len, v);
 	return tagptr(v, TAG_SYM);
 }
 
@@ -232,7 +232,7 @@
 	argcount(nargs, 0);
 	USED(args);
 	sl_gensym *gs = alloc_words(sizeof(sl_gensym)/sizeof(sl_v));
-	gs->id = SL(gensym_ctr)++;
+	gs->id = sl.gensym_ctr++;
 	gs->binding = UNBOUND;
 	gs->type = nil;
 	return tagptr(gs, TAG_SYM);
@@ -277,8 +277,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);
+		sl.gsnameno = 1-sl.gsnameno;
+		char *n = uint2str(sl.gsname[sl.gsnameno]+1, sizeof(sl.gsname[0])-1, gs->id, 10);
 		*(--n) = 'g';
 		return n;
 	}
@@ -292,10 +292,10 @@
 {
 	sl_cons *c;
 
-	if(sl_unlikely(SL(curheap) > SL(lim)))
+	if(sl_unlikely(sl.curheap > sl.lim))
 		sl_gc(false);
-	c = (sl_cons*)SL(curheap);
-	SL(curheap) += sizeof(sl_cons);
+	c = (sl_cons*)sl.curheap;
+	sl.curheap += sizeof(sl_cons);
 	return tagptr(c, TAG_CONS);
 }
 
@@ -309,13 +309,13 @@
 	if(n & 1)
 		n++;
 #endif
-	if(sl_unlikely((sl_v*)SL(curheap) > (sl_v*)SL(lim)+2-n)){
+	if(sl_unlikely((sl_v*)sl.curheap > (sl_v*)sl.lim+2-n)){
 		sl_gc(false);
-		while(sl_unlikely((sl_v*)SL(curheap) > ((sl_v*)SL(lim))+2-n))
+		while(sl_unlikely((sl_v*)sl.curheap > ((sl_v*)sl.lim)+2-n))
 			sl_gc(true);
 	}
-	first = (sl_v*)SL(curheap);
-	SL(curheap) += n*sizeof(sl_v);
+	first = (sl_v*)sl.curheap;
+	sl.curheap += n*sizeof(sl_v);
 	return first;
 }
 
@@ -323,7 +323,7 @@
 alloc_vector(usize n, bool init)
 {
 	if(n == 0)
-		return SL(the_empty_vector);
+		return sl.the_empty_vector;
 	sl_v *c = alloc_words(n+1);
 	sl_v v = tagptr(c, TAG_VECTOR);
 	vector_setsize(v, n);
@@ -339,16 +339,16 @@
 void
 sl_gc_handle(sl_v *pv)
 {
-	if(sl_unlikely(SL(ngchandles) >= N_GC_HANDLES))
+	if(sl_unlikely(sl.ngchandles >= N_GC_HANDLES))
 		lerrorf(sl_errmem, "out of gc handles");
-	SL(gchandles)[SL(ngchandles)++] = pv;
+	sl.gchandles[sl.ngchandles++] = pv;
 }
 
 void
 sl_free_gc_handles(int n)
 {
-	assert(SL(ngchandles) >= n);
-	SL(ngchandles) -= n;
+	assert(sl.ngchandles >= n);
+	sl.ngchandles -= n;
 }
 
 sl_v
@@ -370,8 +370,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*)sl.curheap, TAG_CONS);
+			sl.curheap += sizeof(sl_cons);
 			forward(v, nc);
 			car_(nc) = ismanaged(a) ? relocate(a) : a;
 			pcdr = &cdr_(nc);
@@ -452,7 +452,7 @@
 {
 	const char *k = nil;
 	sl_sym *v;
-	while(Tnext(SL(symtab), &k, (void**)&v)){
+	while(Tnext(sl.symtab, &k, (void**)&v)){
 		if(v->binding != UNBOUND)
 			v->binding = relocate(v->binding);
 	}
@@ -461,34 +461,34 @@
 void
 sl_gc(bool mustgrow)
 {
-	SL(gccalls)++;
-	SL(curheap) = SL(tospace);
-	if(SL(grew))
-		SL(lim) = SL(curheap)+SL(heapsize)*2-sizeof(sl_cons);
+	sl.gccalls++;
+	sl.curheap = sl.tospace;
+	if(sl.grew)
+		sl.lim = sl.curheap+sl.heapsize*2-sizeof(sl_cons);
 	else
-		SL(lim) = SL(curheap)+SL(heapsize)-sizeof(sl_cons);
+		sl.lim = sl.curheap+sl.heapsize-sizeof(sl_cons);
 
 	sl_v *top, *f;
-	if(SL(throwing_frame) > SL(curr_frame)){
-		top = SL(throwing_frame) - 3;
+	if(sl.throwing_frame > sl.curr_frame){
+		top = sl.throwing_frame - 3;
 		f = (sl_v*)*top;
 	}else{
-		top = SL(sp);
-		f = SL(curr_frame);
+		top = sl.sp;
+		f = sl.curr_frame;
 	}
 	for(;;){
 		for(sl_v *p = f; p < top; p++)
 			*p = relocate(*p);
-		if(f == SL(stack))
+		if(f == sl.stack)
 			break;
 		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 < sl.ngchandles; i++)
+		*sl.gchandles[i] = relocate(*sl.gchandles[i]);
 	trace_globals();
 	relocate_typetable();
-	sl_readstate *rs = SL(readstate);
+	sl_readstate *rs = sl.readstate;
 	while(rs){
 		sl_v ent;
 		for(int i = 0; i < rs->backrefs.size; i++){
@@ -504,46 +504,46 @@
 		rs->source = relocate(rs->source);
 		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.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);
 
 	sweep_finalizers();
 
-	void *temp = SL(tospace);
-	SL(tospace) = SL(fromspace);
-	SL(fromspace) = temp;
+	void *temp = sl.tospace;
+	sl.tospace = sl.fromspace;
+	sl.fromspace = temp;
 
 	// FIXME(sigrid): add some extra to the "used"?
-	sl_segused(SL(fromspace), SL(heapsize), SL(curheap)-SL(fromspace));
+	sl_segused(sl.fromspace, sl.heapsize, sl.curheap-sl.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(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){
 				// 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.memory_exception_value);
 		}
-		if(SL(grew)){
-			SL(heapsize) *= 2;
-			temp = bitvector_resize(SL(consflags), 0, SL(heapsize)/sizeof(sl_cons), 1);
+		if(sl.grew){
+			sl.heapsize *= 2;
+			temp = bitvector_resize(sl.consflags, 0, sl.heapsize/sizeof(sl_cons), 1);
 			if(sl_unlikely(temp == nil))
-				sl_raise(SL(memory_exception_value));
-			SL(consflags) = (u32int*)temp;
+				sl_raise(sl.memory_exception_value);
+			sl.consflags = (u32int*)temp;
 		}
-		SL(grew) = !SL(grew);
+		sl.grew = !sl.grew;
 	}
-	if(sl_unlikely((sl_v*)SL(curheap) > (sl_v*)SL(lim)-2)){
+	if(sl_unlikely((sl_v*)sl.curheap > (sl_v*)sl.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.
@@ -558,7 +558,7 @@
 static sl_v
 _applyn(int n)
 {
-	sl_v *saveSP = SL(sp);
+	sl_v *saveSP = sl.sp;
 	sl_v f = saveSP[-n-1];
 	sl_v v;
 	if(iscbuiltin(f))
@@ -574,7 +574,7 @@
 	}else{
 		type_error("function", f);
 	}
-	SL(sp) = saveSP;
+	sl.sp = saveSP;
 	return v;
 }
 
@@ -581,7 +581,7 @@
 sl_v
 sl_apply(sl_v f, sl_v v)
 {
-	sl_v *saveSP = SL(sp);
+	sl_v *saveSP = sl.sp;
 
 	PUSH(f);
 	int n;
@@ -592,7 +592,7 @@
 	if(v != sl_nil)
 		lerrorf(sl_errarg, "apply: last argument: not a list");
 	v = _applyn(n);
-	SL(sp) = saveSP;
+	sl.sp = saveSP;
 	return v;
 }
 
@@ -618,7 +618,7 @@
 {
 	va_list ap;
 	va_start(ap, n);
-	sl_v *si = SL(sp);
+	sl_v *si = sl.sp;
 
 	for(int i = 0; i < n; i++){
 		sl_v a = va_arg(ap, sl_v);
@@ -671,7 +671,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;
 }
@@ -703,7 +703,7 @@
 {
 	if(!iscons(L))
 		return sl_nil;
-	sl_v *plcons = SL(sp);
+	sl_v *plcons = sl.sp;
 	sl_v *pL = plcons+1;
 	PUSH(sl_nil);
 	PUSH(L);
@@ -729,11 +729,11 @@
 static sl_v
 do_trycatch(void)
 {
-	sl_v *saveSP = SL(sp);
+	sl_v *saveSP = sl.sp;
 	sl_v v = sl_nil;
 	sl_v thunk = saveSP[-2];
-	SL(sp)[-2] = saveSP[-1];
-	SL(sp)[-1] = thunk;
+	sl.sp[-2] = saveSP[-1];
+	sl.sp[-1] = thunk;
 
 	sl_TRY{
 		v = apply_cl(0);
@@ -741,10 +741,10 @@
 	sl_CATCH{
 		v = saveSP[-2];
 		PUSH(v);
-		PUSH(SL(lasterror));
+		PUSH(sl.lasterror);
 		v = apply_cl(1);
 	}
-	SL(sp) = saveSP;
+	sl.sp = saveSP;
 	return v;
 }
 
@@ -759,9 +759,9 @@
 	int ntot = nreq+extr;
 	sl_v args[64], v = sl_nil;
 	int i, a = 0, nrestargs;
-	sl_v s1 = SL(sp)[-1];
-	sl_v s3 = SL(sp)[-3];
-	sl_v s4 = SL(sp)[-4];
+	sl_v s1 = sl.sp[-1];
+	sl_v s3 = sl.sp[-3];
+	sl_v s4 = sl.sp[-4];
 	if(sl_unlikely(nargs < nreq))
 		lerrorf(sl_errarg, "too few arguments");
 	if(sl_unlikely(extr > nelem(args)))
@@ -811,13 +811,13 @@
 	if(nrestargs)
 		memmove(bp+ntot, bp+i, nrestargs*sizeof(sl_v));
 	memmove(bp+nreq, args, extr*sizeof(sl_v));
-	SL(sp) = bp + nargs;
-	assert((intptr)(SL(sp)-SL(stack)) < (intptr)SL(nstack)-4);
+	sl.sp = bp + nargs;
+	assert((intptr)(sl.sp-sl.stack) < (intptr)sl.nstack-4);
 	PUSH(s4);
 	PUSH(s3);
 	PUSH(nargs);
 	PUSH(s1);
-	SL(curr_frame) = SL(sp);
+	sl.curr_frame = sl.sp;
 	return nargs;
 }
 
@@ -845,8 +845,8 @@
 static sl_v
 apply_cl(int nargs)
 {
-	sl_v *top_frame = SL(curr_frame), *bp, *ipd;
-	register sl_v *sp = SL(sp);
+	sl_v *top_frame = sl.curr_frame, *bp, *ipd;
+	register sl_v *sp = sl.sp;
 	const u8int *ip;
 	bool tail;
 	int n;
@@ -891,7 +891,7 @@
 _stacktrace(sl_v *top)
 {
 	sl_v lst = sl_nil;
-	sl_v *stack = SL(stack);
+	sl_v *stack = sl.stack;
 
 	sl_gc_handle(&lst);
 	while(top > stack){
@@ -940,7 +940,7 @@
 	csl_v *arr = ptr(args[0]);
 	cv_pin(arr);
 	u8int *data = cv_data(arr);
-	if(SL(loading)){
+	if(sl.loading){
 		// read syntax, shifted 48 for compact text representation
 		usize i, sz = cv_len(arr);
 		for(i = 0; i < sz; i++)
@@ -1010,7 +1010,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(&sl.reverse_dlsym_lookup_table, ptr(v));
 		if(v == (sl_v)HT_NOTFOUND)
 			return sl_nil;
 		return v;
@@ -1040,7 +1040,7 @@
 				first = lst;
 			else
 				cdr_(lastcons) = lst;
-			lastcons = tagptr((((sl_cons*)SL(curheap))-1), TAG_CONS);
+			lastcons = tagptr((((sl_cons*)sl.curheap)-1), TAG_CONS);
 		}else if(lst != sl_nil){
 			type_error("cons", lst);
 		}
@@ -1062,7 +1062,7 @@
 {
 	USED(args);
 	argcount(nargs, 0);
-	return _stacktrace(SL(throwing_frame) ? SL(throwing_frame) : SL(curr_frame));
+	return _stacktrace(sl.throwing_frame ? sl.throwing_frame : sl.curr_frame);
 }
 
 BUILTIN("map", map)
@@ -1069,7 +1069,7 @@
 {
 	if(sl_unlikely(nargs < 2))
 		lerrorf(sl_errarg, "too few arguments");
-	sl_v *k = SL(sp);
+	sl_v *k = sl.sp;
 	PUSH(sl_nil);
 	PUSH(sl_nil);
 	for(bool first = true;;){
@@ -1165,14 +1165,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, "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, "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, "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, "opcodes        %10d\n", N_OPCODES);
 	return sl_void;
 }
@@ -1190,41 +1190,41 @@
 {
 	int i;
 
-	if((sl = MEM_CALLOC(1, sizeof(*sl))) == nil)
+	if((slp = MEM_CALLOC(1, sizeof(*slp))) == nil)
 		return -1;
-	SL(scr_width) = 100;
+	sl.scr_width = 100;
 
-	SL(heapsize) = heapsize*sizeof(sl_v);
+	sl.heapsize = heapsize*sizeof(sl_v);
 
-	if((SL(fromspace) = sl_segalloc(SL(heapsize))) == nil){
+	if((sl.fromspace = sl_segalloc(sl.heapsize)) == nil){
 failed:
-		MEM_FREE(SL(consflags));
-		MEM_FREE(SL(finalizers));
-		sl_segfree(SL(fromspace), SL(heapsize));
-		sl_segfree(SL(tospace), SL(heapsize));
-		sl_segfree(SL(stack), stacksize*sizeof(sl_v));
-		htable_free(&SL(printconses));
-		MEM_FREE(sl);
+		MEM_FREE(sl.consflags);
+		MEM_FREE(sl.finalizers);
+		sl_segfree(sl.fromspace, sl.heapsize);
+		sl_segfree(sl.tospace, sl.heapsize);
+		sl_segfree(sl.stack, stacksize*sizeof(sl_v));
+		htable_free(&sl.printconses);
+		MEM_FREE(slp);
 		return -1;
 	}
 
-	if((SL(tospace) = sl_segalloc(SL(heapsize))) == nil)
+	if((sl.tospace = sl_segalloc(sl.heapsize)) == nil)
 		goto failed;
-	SL(curheap) = SL(fromspace);
-	SL(lim) = SL(curheap)+SL(heapsize)-sizeof(sl_cons);
+	sl.curheap = sl.fromspace;
+	sl.lim = sl.curheap+sl.heapsize-sizeof(sl_cons);
 
-	if((SL(stack) = sl_segalloc(stacksize*sizeof(sl_v))) == nil)
+	if((sl.stack = sl_segalloc(stacksize*sizeof(sl_v))) == nil)
 		goto failed;
-	SL(curr_frame) = SL(sp) = SL(stack);
-	SL(nstack) = stacksize;
+	sl.curr_frame = sl.sp = sl.stack;
+	sl.nstack = stacksize;
 
-	SL(maxfinalizers) = 512;
-	if((SL(finalizers) = MEM_ALLOC(SL(maxfinalizers) * sizeof(*SL(finalizers)))) == nil)
+	sl.maxfinalizers = 512;
+	if((sl.finalizers = MEM_ALLOC(sl.maxfinalizers * sizeof(*sl.finalizers))) == nil)
 		goto failed;
 
-	if((SL(consflags) = bitvector_new(SL(heapsize)/sizeof(sl_cons), 1)) == nil)
+	if((sl.consflags = bitvector_new(sl.heapsize/sizeof(sl_cons), 1)) == nil)
 		goto failed;
-	if((htable_new(&SL(printconses), 32)) == nil)
+	if((htable_new(&sl.printconses, 32)) == nil)
 		goto failed;
 
 	comparehash_init();
@@ -1277,10 +1277,10 @@
 
 	set(sl_printprettysym = csymbol("*print-pretty*"), sl_t);
 	set(sl_printreadablysym = csymbol("*print-readably*"), sl_t);
-	set(sl_printwidthsym = csymbol("*print-width*"), fixnum(SL(scr_width)));
+	set(sl_printwidthsym = csymbol("*print-width*"), fixnum(sl.scr_width));
 	set(sl_printlengthsym = csymbol("*print-length*"), sl_nil);
 	set(sl_printlevelsym = csymbol("*print-level*"), sl_nil);
-	SL(lasterror) = sl_nil;
+	sl.lasterror = sl_nil;
 
 	for(i = 0; i < nelem(builtins); i++){
 		if(builtins[i].name)
@@ -1289,8 +1289,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.the_empty_vector = tagptr(alloc_words(1), TAG_VECTOR);
+	vector_setsize(sl.the_empty_vector, 0);
 
 	cvalues_init();
 
@@ -1298,7 +1298,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.memory_exception_value = 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,14 +1320,14 @@
 int
 sl_load_system_image(sl_v sys_image_iostream)
 {
-	SL(loading) = true;
+	sl.loading = true;
 	PUSH(sys_image_iostream);
-	sl_v *saveSP = SL(sp);
+	sl_v *saveSP = sl.sp;
 	sl_TRY{
 		while(1){
-			SL(sp) = saveSP;
-			sl_v e = sl_read_sexpr(SL(sp)[-1]);
-			if(ios_eof(value2c(sl_ios*, SL(sp)[-1])))
+			sl.sp = saveSP;
+			sl_v e = sl_read_sexpr(sl.sp[-1]);
+			if(ios_eof(value2c(sl_ios*, sl.sp[-1])))
 				break;
 			if(isfunction(e)){
 				// stage 0 format: series of thunks
@@ -1349,11 +1349,11 @@
 	}
 	sl_CATCH_NO_INC{
 		ios_puts(ios_stderr, "fatal error during bootstrap: ");
-		sl_print(ios_stderr, SL(lasterror));
+		sl_print(ios_stderr, sl.lasterror);
 		ios_putc(ios_stderr, '\n');
 		return -1;
 	}
-	SL(sp) = saveSP-1;
-	SL(loading) = false;
+	sl.sp = saveSP-1;
+	sl.loading = false;
 	return 0;
 }
--- a/src/sl.h
+++ b/src/sl.h
@@ -118,10 +118,10 @@
 
 // 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 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))
+#define cons_index(c) (((sl_cons*)ptr(c))-((sl_cons*)sl.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))
 
 #define isforwarded(v) (*(sl_v*)ptr(v) & FWD_BIT)
 #define forwardloc(v) (*(sl_v*)ptr(v) ^ FWD_BIT)
@@ -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)) >= sl.fromspace) && (((u8int*)ptr(v)) < sl.fromspace+sl.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
@@ -166,13 +166,13 @@
 
 #define PUSH(v) \
 	do{ \
-		*SL(sp)++ = (v); \
+		*sl.sp++ = (v); \
 	}while(0)
 #define POPN(n) \
 	do{ \
-		SL(sp) -= (n); \
+		sl.sp -= (n); \
 	}while(0)
-#define POP() *(--SL(sp))
+#define POP() *(--sl.sp)
 
 bool isbuiltin(sl_v x) sl_constfn sl_hotfn;
 int sl_init(usize heapsize, usize stacksize);
@@ -243,9 +243,9 @@
 
 #define sl_TRY_EXTERN \
 	sl_exctx _ctx; int l__tr, l__ca; \
-	sl_savestate(&_ctx); SL(exctx) = &_ctx; \
+	sl_savestate(&_ctx); sl.exctx = &_ctx; \
 	if(!sl_setjmp(_ctx.buf)) \
-		for(l__tr = 1; l__tr; l__tr = 0, (void)(SL(exctx) = SL(exctx)->prev))
+		for(l__tr = 1; l__tr; l__tr = 0, (void)(sl.exctx = sl.exctx->prev))
 
 #define sl_CATCH_EXTERN_NO_RESTORE \
 	else \
@@ -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))
@@ -426,8 +426,8 @@
 	sl_v *gchandles[N_GC_HANDLES];
 };
 
-extern sl_thread(Sl *sl);
-#define SL(f) sl->f
+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 sl_v sl_commadot, sl_trycatch, sl_backquote;
--- 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);
@@ -137,7 +137,7 @@
 	}
 	sl_CATCH_EXTERN_NO_RESTORE{
 		ios_puts(ios_stderr, "fatal error:\n");
-		sl_print(ios_stderr, SL(lasterror));
+		sl_print(ios_stderr, sl.lasterror);
 		ios_putc(ios_stderr, '\n');
 		break;
 	}
--- 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(&sl.TypeTable, (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 = &sl.TypeTable;
 	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
@@ -33,7 +33,7 @@
 		if(v > (N_BUILTINS<<3)){
 			nargs = n;
 			if(tail){
-				SL(curr_frame) = (sl_v*)SL(curr_frame)[-3];
+				sl.curr_frame = (sl_v*)sl.curr_frame[-3];
 				for(sl_fx s = -1; s < (sl_fx)n; s++)
 					bp[s] = sp[s-n];
 				sp = bp+n;
@@ -45,10 +45,10 @@
 			ip = cvalue_data(fn->bcode);
 			assert(!ismanaged((uintptr)ip));
 			*sp++ = fn->env;
-			*sp++ = (sl_v)SL(curr_frame);
+			*sp++ = (sl_v)sl.curr_frame;
 			*sp++ = nargs;
 			ipd = sp++;
-			SL(curr_frame) = sp;
+			sl.curr_frame = sp;
 			NEXT_OP;
 		}
 		int i = uintval(v);
@@ -55,10 +55,10 @@
 		assert(isbuiltin(v));
 		sl_fx s = builtins[i].nargs;
 		if(s >= 0){
-			SL(sp) = sp;
+			sl.sp = sp;
 			argcount(n, s);
 		}else if(s != ANYARGS && n < -s){
-			SL(sp) = sp;
+			sl.sp = sp;
 			argcount(n, -s);
 		}
 		// remove function arg
@@ -87,13 +87,13 @@
 		}
 	}else if(sl_likely(iscbuiltin(v))){
 		sl_v *p = sp - n;
-		SL(sp) = sp;
+		sl.sp = sp;
 		v = ((csl_v*)ptr(v))->cbuiltin(p, n);
 		sp = p;
 		p[-1] = v;
 		NEXT_OP;
 	}
-	SL(sp) = sp;
+	sl.sp = sp;
 	type_error("function", v);
 }
 
@@ -106,7 +106,7 @@
 	}
 	if(sl_unlikely(nargs != na)){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		arity_error(nargs, na);
 	}
 	NEXT_OP;
@@ -118,17 +118,17 @@
 
 OP(OP_RET) {
 	sl_v v = *(--sp);
-	sp = SL(curr_frame);
-	SL(curr_frame) = (sl_v*)sp[-3];
-	if(SL(curr_frame) == top_frame){
-		SL(sp) = sp;
+	sp = sl.curr_frame;
+	sl.curr_frame = (sl_v*)sp[-3];
+	if(sl.curr_frame == top_frame){
+		sl.sp = sp;
 		return v;
 	}
 	sp -= 4+nargs;
-	ipd = SL(curr_frame)-1;
+	ipd = sl.curr_frame-1;
 	ip = (u8int*)*ipd;
-	nargs = SL(curr_frame)[-2];
-	bp = SL(curr_frame) - 4 - nargs;
+	nargs = sl.curr_frame[-2];
+	bp = sl.curr_frame - 4 - nargs;
 	sp[-1] = v;
 	NEXT_OP;
 }
@@ -160,7 +160,7 @@
 	sl_sym *sym = ptr(v);
 	if(sl_unlikely(sym->binding == UNBOUND)){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		unbound_error(v);
 	}
 	*sp++ = sym->binding;
@@ -256,7 +256,7 @@
 		v = car_(v);
 	else if(sl_unlikely(v != sl_nil)){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		type_error("cons", v);
 	}
 	sp[-1] = v;
@@ -266,7 +266,7 @@
 OP(OP_CLOSURE) {
 	int x = *ip++;
 	assert(x > 0);
-	SL(sp) = sp;
+	sl.sp = sp;
 	sl_v *pv = alloc_words(
 		1+x+
 #if !defined(BITS64)
@@ -295,12 +295,12 @@
 }
 
 OP(OP_CONS) {
-	if(SL(curheap) > SL(lim)){
-		SL(sp) = sp;
+	if(sl.curheap > sl.lim){
+		sl.sp = sp;
 		sl_gc(0);
 	}
-	sl_cons *c = (sl_cons*)SL(curheap);
-	SL(curheap) += sizeof(sl_cons);
+	sl_cons *c = (sl_cons*)sl.curheap;
+	sl.curheap += sizeof(sl_cons);
 	c->car = sp[-2];
 	c->cdr = sp[-1];
 	sp[-2] = tagptr(c, TAG_CONS);
@@ -319,7 +319,7 @@
 		v = cdr_(v);
 	else if(sl_unlikely(v != sl_nil)){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		type_error("cons", v);
 	}
 	sp[-1] = v;
@@ -355,11 +355,11 @@
 			bp[i+3] = i+1;
 			bp[i+4] = 0;
 			sp = bp+i+5;
-			SL(curr_frame) = sp;
+			sl.curr_frame = sp;
 		}
 	}else if(sl_unlikely(s < 0)){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		lerrorf(sl_errarg, "too few arguments");
 	}else{
 		sp++;
@@ -367,7 +367,7 @@
 		sp[-3] = sp[-4];
 		sp[-4] = sp[-5];
 		sp[-5] = sl_nil;
-		SL(curr_frame) = sp;
+		sl.curr_frame = sp;
 	}
 	ipd = sp-1;
 	nargs = i+1;
@@ -385,7 +385,7 @@
 	sl_v v = sp[-2];
 	if(sl_unlikely(!iscons(v))){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		type_error("cons", v);
 	}
 	car_(v) = sp[-1];
@@ -399,7 +399,7 @@
 
 OP(OP_BOX) {
 	int i = *ip++;
-	SL(sp) = sp;
+	sl.sp = sp;
 	sl_v v = alloc_cons();
 	car_(v) = bp[i];
 	cdr_(v) = sl_nil;
@@ -434,7 +434,7 @@
 		usize isz = tosize(e);
 		if(isvector(v)){
 			if(sl_unlikely(isz >= vector_size(v))){
-				SL(sp) = sp;
+				sl.sp = sp;
 				bounds_error(v, e);
 			}
 			v = vector_elt(v, isz);
@@ -441,7 +441,7 @@
 			continue;
 		}
 		if(!iscons(v) && v != sl_nil){
-			SL(sp) = sp;
+			sl.sp = sp;
 			type_error("sequence", v);
 		}
 		for(sl_v v0 = v;; isz--){
@@ -451,7 +451,7 @@
 			}
 			v = cdr_(v);
 			if(sl_unlikely(!iscons(v))){
-				SL(sp) = sp;
+				sl.sp = sp;
 				bounds_error(v0, e);
 			}
 		}
@@ -491,7 +491,7 @@
 	sl_v v = sp[-2];
 	if(sl_unlikely(!iscons(v))){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		type_error("cons", v);
 	}
 	cdr_(v) = sp[-1];
@@ -520,7 +520,7 @@
 			usize isz = tosize(e);
 			if(isvector(v)){
 				if(sl_unlikely(isz >= vector_size(v))){
-					SL(sp) = sp;
+					sl.sp = sp;
 					bounds_error(v, e);
 				}
 				v = vector_elt(v, isz);
@@ -527,7 +527,7 @@
 				continue;
 			}
 			if(!iscons(v) && v != sl_nil){
-				SL(sp) = sp;
+				sl.sp = sp;
 				type_error("sequence", v);
 			}
 			for(sl_v v0 = v;; isz--){
@@ -537,7 +537,7 @@
 				}
 				v = cdr_(v);
 				if(sl_unlikely(!iscons(v))){
-					SL(sp) = sp;
+					sl.sp = sp;
 					bounds_error(v0, e);
 				}
 			}
@@ -548,7 +548,7 @@
 	usize isz = tosize(e);
 	if(isvector(v)){
 		if(sl_unlikely(isz >= vector_size(v))){
-			SL(sp) = sp;
+			sl.sp = sp;
 			bounds_error(v, e);
 		}
 		vector_elt(v, isz) = (e = sp[-1]);
@@ -560,7 +560,7 @@
 			}
 			v = cdr_(v);
 			if(sl_unlikely(!iscons(v))){
-				SL(sp) = sp;
+				sl.sp = sp;
 				bounds_error(v0, e);
 			}
 		}
@@ -567,7 +567,7 @@
 	}else if(isarray(v)){
 		e = cvalue_array_aset(sp-3);
 	}else{
-		SL(sp) = sp;
+		sl.sp = sp;
 		type_error("sequence", v);
 	}
 	sp -= n;
@@ -615,13 +615,13 @@
 	ip += 4;
 	if(sl_unlikely(nargs < i)){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		lerrorf(sl_errarg, "too few arguments");
 	}
 	if(x > 0){
 		if(sl_unlikely(nargs > x)){
 			*ipd = (uintptr)ip;
-			SL(sp) = sp;
+			sl.sp = sp;
 			lerrorf(sl_errarg, "too many arguments");
 		}
 	}else
@@ -633,7 +633,7 @@
 		sp[-2] = nargs+x;
 		sp[-3] = sp[-x-3];
 		sp[-4] = sp[-x-4];
-		SL(curr_frame) = sp;
+		sl.curr_frame = sp;
 		ipd = sp-1;
 		for(i = 0; i < x; i++)
 			bp[nargs+i] = UNBOUND;
@@ -699,7 +699,7 @@
 LABEL(cadr_nil):
 		if(sl_unlikely(v != sl_nil)){
 			*ipd = (uintptr)ip;
-			SL(sp) = sp;
+			sl.sp = sp;
 			type_error("cons", v);
 		}
 	}
@@ -723,7 +723,7 @@
 	}
 	if(v != sl_nil){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		lerrorf(sl_errarg, "apply: last argument: not a list");
 	}
 	n = sp-p;
@@ -768,7 +768,7 @@
 	sl_v b = sp[-1];
 	if(sl_unlikely(b == 0)){
 		*ipd = (uintptr)ip;
-		SL(sp) = sp;
+		sl.sp = sp;
 		divide_by_0_error();
 	}
 	sl_v v;
@@ -807,7 +807,7 @@
 OP(OP_VECTOR) {
 	n = *ip++;
 LABEL(apply_vector):;
-	SL(sp) = sp;
+	sl.sp = sp;
 	sl_v v = alloc_vector(n, 0);
 	memcpy(&vector_elt(v, 0), sp-n, n*sizeof(sl_v));
 	sp -= n;
@@ -827,7 +827,7 @@
 	sl_fx s = tofixnum(p[-3]);
 	sl_fx hi = tofixnum(p[-2]);
 	sp += 2;
-	SL(sp) = sp;
+	sl.sp = sp;
 	for(v = sl_void; s <= hi; s++){
 		p[0] = p[-1];
 		p[1] = fixnum(s);
@@ -862,7 +862,7 @@
 
 OP(OP_TRYCATCH) {
 	*ipd = (uintptr)ip;
-	SL(sp) = sp;
+	sl.sp = sp;
 	sl_v v = do_trycatch();
 	sp--;
 	sp[-1] = v;
@@ -904,9 +904,9 @@
 	sl_fx s = GET_S32(ip);
 	ip += 4;
 	*ipd = (uintptr)ip;
-	SL(sp) = sp;
+	sl.sp = sp;
 	nargs = process_keys(v, i, x, labs(s)-(i+x), bp, nargs, s<0);
-	sp = SL(sp);
+	sp = sl.sp;
 	ipd = sp-1;
 	NEXT_OP;
 }
@@ -946,7 +946,7 @@
 OP(OP_BOXL) {
 	int i = GET_S32(ip);
 	ip += 4;
-	SL(sp) = sp;
+	sl.sp = sp;
 	sl_v v = alloc_cons();
 	car_(v) = bp[i];
 	cdr_(v) = sl_nil;
--