shithub: femtolisp

Download patch

ref: d9f6cb0d7f88d15f8a110c63e84ab7b5514755c2
parent: b08031edac53f6a4aed024e6662a9bbacc25458c
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Dec 29 00:13:31 EST 2024

predefined symbols do not need to reside in the Fl structure

--- a/builtins.c
+++ b/builtins.c
@@ -206,7 +206,7 @@
 	if(issymbol(args[0]))
 		return isconstant((symbol_t*)ptr(args[0])) ? FL_t : FL_f;
 	if(iscons(args[0])){
-		if(car_(args[0]) == FL(quote))
+		if(car_(args[0]) == FL_quote)
 			return FL_t;
 		return FL_f;
 	}
@@ -371,7 +371,7 @@
 	}
 	char *ptr = tostring(args[0]);
 	if(chdir(ptr))
-		lerrorf(FL(IOError), "could not cd to %s", ptr);
+		lerrorf(FL_IOError, "could not cd to %s", ptr);
 	return FL_void;
 }
 
@@ -404,7 +404,7 @@
 		result = setenv(name, val, 1);
 	}
 	if(result != 0)
-		lerrorf(FL(ArgError), "invalid environment variable");
+		lerrorf(FL_ArgError, "invalid environment variable");
 	return FL_t;
 }
 
--- a/compress.c
+++ b/compress.c
@@ -34,7 +34,7 @@
 		: blz_pack(in, out, insz, work);
 	MEM_FREE(work);
 	if(n == BLZ_ERROR)
-		lerrorf(FL(ArgError), "blz error");
+		lerrorf(FL_ArgError, "blz error");
 	cvalue_len(v) = n;
 	return v;
 }
@@ -51,19 +51,19 @@
 	size_t outsz;
 	uint8_t *out;
 	value_t v;
-	if(args[1] == FL(sizesym)){
+	if(args[1] == FL_sizesym){
 		outsz = tosize(args[2]);
 		v = cvalue(cv_class(ptr(args[0])), outsz);
 		out = cvalue_data(v);
-	}else if(args[1] == FL(tosym)){
+	}else if(args[1] == FL_tosym){
 		v = args[2];
 		to_sized_ptr(v, &out, &outsz);
 	}else{
-		lerrorf(FL(ArgError), "either :size or :to must be specified");
+		lerrorf(FL_ArgError, "either :size or :to must be specified");
 	}
 	unsigned long n = blz_depack_safe(in, insz, out, outsz);
 	if(n == BLZ_ERROR)
-		lerrorf(FL(ArgError), "blz error");
+		lerrorf(FL_ArgError, "blz error");
 	cvalue_len(v) = n;
 	return v;
 }
@@ -71,6 +71,6 @@
 void
 compress_init(void)
 {
-	FL(sizesym) = symbol(":size", false);
-	FL(tosym) = symbol(":to", false);
+	FL_sizesym = symbol(":size", false);
+	FL_tosym = symbol(":to", false);
 }
--- a/cvalues.c
+++ b/cvalues.c
@@ -17,7 +17,7 @@
 		size_t nn = FL(maxfinalizers) == 0 ? 256 : FL(maxfinalizers)*2;
 		cvalue_t **temp = MEM_REALLOC(FL(finalizers), nn*sizeof(cvalue_t*));
 		if(temp == nil)
-			lerrorf(FL(MemoryError), "out of memory");
+			lerrorf(FL_MemoryError, "out of memory");
 		FL(finalizers) = temp;
 		FL(maxfinalizers) = nn;
 	}
@@ -400,7 +400,7 @@
 				return 0;
 			}
 		}
-		lerrorf(FL(ArgError), "invalid enum value");
+		lerrorf(FL_ArgError, "invalid enum value");
 	}
 	if(isfixnum(arg))
 		n = (int)numval(arg);
@@ -410,7 +410,7 @@
 	}else
 		type_error("number", arg);
 	if((unsigned)n >= vector_size(syms))
-		lerrorf(FL(ArgError), "value out of range");
+		lerrorf(FL_ArgError, "value out of range");
 	*(int*)dest = n;
 	return 0;
 }
@@ -448,7 +448,7 @@
 	if(iscons(cdr_(cdr_(type)))){
 		size_t tc = tosize(car_(cdr_(cdr_(type))));
 		if(tc != cnt)
-			lerrorf(FL(ArgError), "size mismatch");
+			lerrorf(FL_ArgError, "size mismatch");
 	}
 
 	sz = elsize * cnt;
@@ -474,7 +474,7 @@
 			arg = cdr_(arg);
 		}
 		if(i != cnt)
-			lerrorf(FL(ArgError), "size mismatch");
+			lerrorf(FL_ArgError, "size mismatch");
 		return 0;
 	}
 	if(iscvalue(arg)){
@@ -485,11 +485,11 @@
 				if(cv_len(cv) == sz)
 					memcpy(dest, cv_data(cv), sz);
 				else
-					lerrorf(FL(ArgError), "size mismatch");
+					lerrorf(FL_ArgError, "size mismatch");
 				return 0;
 			}else{
 				// TODO: initialize array from different type elements
-				lerrorf(FL(ArgError), "element type mismatch");
+				lerrorf(FL_ArgError, "element type mismatch");
 			}
 		}
 	}
@@ -532,7 +532,7 @@
 		argcount(nargs, 3);
 	cnt = tosize(args[1]);
 	if(cnt < 0)
-		lerrorf(FL(ArgError), "invalid size: %d", cnt);
+		lerrorf(FL_ArgError, "invalid size: %d", cnt);
 
 	fltype_t *type = get_array_type(args[0]);
 	elsize = type->elsz;
@@ -571,10 +571,10 @@
 
 	if(iscons(type)){
 		value_t hed = car_(type);
-		if(hed == FL(arraysym)){
+		if(hed == FL_arraysym){
 			value_t t = car(cdr_(type));
 			if(!iscons(cdr_(cdr_(type))))
-				lerrorf(FL(ArgError), "incomplete type");
+				lerrorf(FL_ArgError, "incomplete type");
 			value_t n = car_(cdr_(cdr_(type)));
 			size_t sz = tosize(n);
 			return sz * ctype_sizeof(t);
@@ -581,7 +581,7 @@
 		}
 	}
 
-	lerrorf(FL(ArgError), "invalid c type");
+	lerrorf(FL_ArgError, "invalid c type");
 }
 
 // get pointer and size for any plain-old-data value
@@ -626,22 +626,22 @@
 {
 	argcount(nargs, 1);
 	switch(tag(args[0])){
-	case TAG_CONS: return FL(conssym);
-	case TAG_NUM1: case TAG_NUM: return FL(fixnumsym);
-	case TAG_SYM: return FL(symbolsym);
-	case TAG_VECTOR: return FL(vectorsym);
+	case TAG_CONS: return FL_conssym;
+	case TAG_NUM1: case TAG_NUM: return FL_fixnumsym;
+	case TAG_SYM: return FL_symbolsym;
+	case TAG_VECTOR: return FL_vectorsym;
 	case TAG_FUNCTION:
 		if(args[0] == FL_t || args[0] == FL_f)
-			return FL(booleansym);
+			return FL_booleansym;
 		if(args[0] == FL_nil)
-			return FL(nullsym);
+			return FL_nullsym;
 		if(args[0] == FL_eof)
 			return FL_eof;
 		if(args[0] == FL_void)
 			return FL_void;
 		if(isbuiltin(args[0]))
-			return FL(builtinsym);
-		return FL(function);
+			return FL_builtinsym;
+		return FL_function;
 	}
 	return cv_type(ptr(args[0]));
 }
@@ -702,11 +702,11 @@
 {
 	argcount(nargs, 1);
 	if(iscons(args[0]) || isvector(args[0]))
-		lerrorf(FL(ArgError), "argument must be a leaf atom");
+		lerrorf(FL_ArgError, "argument must be a leaf atom");
 	if(!iscvalue(args[0]))
 		return args[0];
 	if(!cv_isPOD(ptr(args[0])))
-		lerrorf(FL(ArgError), "argument must be a plain-old-data type");
+		lerrorf(FL_ArgError, "argument must be a plain-old-data type");
 	return cvalue_copy(args[0]);
 }
 
@@ -723,7 +723,7 @@
 {
 	cvinitfunc_t f = type->init;
 	if(f == nil)
-		lerrorf(FL(ArgError), "invalid c type");
+		lerrorf(FL_ArgError, "invalid c type");
 	f(type, v, dest);
 }
 
@@ -843,7 +843,7 @@
 	argcount(nargs, 1);
 	symbol_t *s = tosymbol(args[0]);
 	if(!iscbuiltin(s->binding))
-		lerrorf(FL(ArgError), "function %s not found", s->name);
+		lerrorf(FL_ArgError, "function %s not found", s->name);
 	return s->binding;
 }
 
@@ -867,7 +867,7 @@
 
 #define cv_intern(tok) \
 	do{ \
-		FL(tok##sym) = symbol(#tok, false); \
+		FL_##tok##sym = symbol(#tok, false); \
 	}while(0)
 
 #define ctor_cv_intern(tok, nt, ctype) \
@@ -874,9 +874,9 @@
 	do{ \
 		symbol_t *s; \
 		cv_intern(tok); \
-		set(FL(tok##sym), cbuiltin(#tok, fn_builtin_##tok)); \
+		set(FL_##tok##sym, cbuiltin(#tok, fn_builtin_##tok)); \
 		if(valid_numtype(nt)){ \
-			s = ptr(FL(tok##sym)); \
+			s = ptr(FL_##tok##sym); \
 			s->numtype = nt; \
 			s->size = sizeof(ctype); \
 		} \
@@ -884,7 +884,7 @@
 
 #define mk_primtype(name, ctype) \
 	do{ \
-		FL(name##type) = get_type(FL(name##sym)); \
+		FL(name##type) = get_type(FL_##name##sym); \
 		FL(name##type)->init = cvalue_##ctype##_init; \
 	}while(0)
 
@@ -1058,7 +1058,7 @@
 _Noreturn void
 DivideByZeroError(void)
 {
-	lerrorf(FL(DivideError), "/: division by zero");
+	lerrorf(FL_DivideError, "/: division by zero");
 }
 
 value_t
@@ -1376,7 +1376,7 @@
 	htable_new(&FL(TypeTable), 256);
 	htable_new(&FL(reverse_dlsym_lookup_table), 256);
 
-	FL(builtintype) = define_opaque_type(FL(builtinsym), sizeof(builtin_t), nil, nil);
+	FL(builtintype) = define_opaque_type(FL_builtinsym, sizeof(builtin_t), nil, nil);
 
 	ctor_cv_intern(int8, T_INT8, int8_t);
 	ctor_cv_intern(uint8, T_UINT8, uint8_t);
@@ -1393,11 +1393,11 @@
 
 	ctor_cv_intern(array, NONNUMERIC, int);
 
-	FL(stringtypesym) = symbol("*string-type*", false);
-	set(FL(stringtypesym), fl_list2(FL(arraysym), FL(bytesym)));
+	FL_stringtypesym = symbol("*string-type*", false);
+	set(FL_stringtypesym, fl_list2(FL_arraysym, FL_bytesym));
 
-	FL(runestringtypesym) = symbol("*runestring-type*", false);
-	set(FL(runestringtypesym), fl_list2(FL(arraysym), FL(runesym)));
+	FL_runestringtypesym = symbol("*runestring-type*", false);
+	set(FL_runestringtypesym, fl_list2(FL_arraysym, FL_runesym));
 
 	mk_primtype(int8, int8_t);
 	mk_primtype(uint8, uint8_t);
@@ -1413,11 +1413,11 @@
 	mk_primtype(double, double);
 
 	ctor_cv_intern(bignum, T_MPINT, mpint*);
-	FL(mpinttype) = get_type(FL(bignumsym));
+	FL(mpinttype) = get_type(FL_bignumsym);
 	FL(mpinttype)->init = cvalue_mpint_init;
 	FL(mpinttype)->vtable = &mpint_vtable;
 
-	FL(stringtype) = get_type(symbol_value(FL(stringtypesym)));
+	FL(stringtype) = get_type(symbol_value(FL_stringtypesym));
 	FL(the_empty_string) = cvalue_from_ref(FL(stringtype), (char*)"", 0, FL_nil);
-	FL(runestringtype) = get_type(symbol_value(FL(runestringtypesym)));
+	FL(runestringtype) = get_type(symbol_value(FL_runestringtypesym));
 }
--- a/flisp.c
+++ b/flisp.c
@@ -19,6 +19,28 @@
 #include "fsixel.h"
 #include "compress.h"
 
+value_t FL_builtins_table_sym, FL_quote, FL_lambda, FL_function, FL_comma, FL_commaat;
+value_t FL_commadot, FL_trycatch, FL_backquote;
+value_t FL_conssym, FL_symbolsym, FL_fixnumsym, FL_vectorsym, FL_builtinsym, FL_vu8sym;
+value_t FL_definesym, FL_defmacrosym, FL_forsym, FL_setqsym;
+value_t FL_tsym, FL_Tsym, FL_fsym, FL_Fsym, FL_booleansym, FL_nullsym, FL_evalsym, FL_fnsym;
+value_t FL_nulsym, FL_alarmsym, FL_backspacesym, FL_tabsym, FL_linefeedsym, FL_newlinesym;
+value_t FL_vtabsym, FL_pagesym, FL_returnsym, FL_escsym, FL_spacesym, FL_deletesym;
+value_t FL_IOError, FL_ParseError, FL_TypeError, FL_ArgError, FL_MemoryError;
+value_t FL_DivideError, FL_BoundsError, FL_Error, FL_KeyError, FL_EnumerationError;
+value_t FL_UnboundError;
+value_t FL_sizesym, FL_tosym;
+
+value_t FL_printwidthsym, FL_printreadablysym, FL_printprettysym, FL_printlengthsym;
+value_t FL_printlevelsym;
+value_t FL_tablesym, FL_arraysym;
+value_t FL_iostreamsym, FL_rdsym, FL_wrsym, FL_apsym, FL_crsym, FL_truncsym;
+value_t FL_instrsym, FL_outstrsym;
+value_t FL_int8sym, FL_uint8sym, FL_int16sym, FL_uint16sym, FL_int32sym, FL_uint32sym;
+value_t FL_int64sym, FL_uint64sym, FL_bignumsym;
+value_t FL_bytesym, FL_runesym, FL_floatsym, FL_doublesym;
+value_t FL_stringtypesym, FL_runestringtypesym;
+
 typedef struct {
 	char *name;
 	builtin_t fptr;
@@ -132,19 +154,19 @@
 _Noreturn void
 type_error(const char *expected, value_t got)
 {
-	fl_raise(fl_listn(3, FL(TypeError), symbol(expected, false), got));
+	fl_raise(fl_listn(3, FL_TypeError, symbol(expected, false), got));
 }
 
 _Noreturn void
 bounds_error(value_t arr, value_t ind)
 {
-	fl_raise(fl_listn(3, FL(BoundsError), arr, ind));
+	fl_raise(fl_listn(3, FL_BoundsError, arr, ind));
 }
 
 _Noreturn void
 unbound_error(value_t sym)
 {
-	fl_raise(fl_listn(2, FL(UnboundError), sym));
+	fl_raise(fl_listn(2, FL_UnboundError, sym));
 }
 
 // safe cast operators --------------------------------------------------------
@@ -323,7 +345,7 @@
 fl_gc_handle(value_t *pv)
 {
 	if(__unlikely(FL(ngchandles) >= N_GC_HANDLES))
-		lerrorf(FL(MemoryError), "out of gc handles");
+		lerrorf(FL_MemoryError, "out of gc handles");
 	FL(gchandles)[FL(ngchandles)++] = pv;
 }
 
@@ -535,7 +557,7 @@
 	size_t newsz = FL(nstack) * 2;
 	value_t *ns = MEM_REALLOC(FL(stack), newsz*sizeof(value_t));
 	if(__unlikely(ns == nil))
-		lerrorf(FL(MemoryError), "stack overflow");
+		lerrorf(FL_MemoryError, "stack overflow");
 	FL(stack) = ns;
 	FL(nstack) = newsz;
 }
@@ -554,7 +576,7 @@
 	else if(isfunction(f))
 		v = apply_cl(n);
 	else if(__likely(isbuiltin(f))){
-		value_t tab = symbol_value(FL(builtins_table_sym));
+		value_t tab = symbol_value(FL_builtins_table_sym);
 		if(__unlikely(ptr(tab) == nil))
 			unbound_error(tab);
 		FL(stack)[FL(sp)-n-1] = vector_elt(tab, uintval(f));
@@ -580,7 +602,7 @@
 		v = cdr_(v);
 	}
 	if(v != FL_nil)
-		lerrorf(FL(ArgError), "apply: last argument: not a list");
+		lerrorf(FL_ArgError, "apply: last argument: not a list");
 	n = FL(sp) - n - 1;
 	v = _applyn(n);
 	POPN(n+1);
@@ -764,9 +786,9 @@
 	value_t s3 = FL(stack)[FL(sp)-3];
 	value_t s4 = FL(stack)[FL(sp)-4];
 	if(__unlikely(nargs < nreq))
-		lerrorf(FL(ArgError), "too few arguments");
+		lerrorf(FL_ArgError, "too few arguments");
 	if(__unlikely(extr > nelem(args)))
-		lerrorf(FL(ArgError), "too many arguments");
+		lerrorf(FL_ArgError, "too many arguments");
 	for(i = 0; i < extr; i++)
 		args[i] = UNBOUND;
 	for(i = nreq; i < nargs; i++){
@@ -784,7 +806,7 @@
 	do{
 		i++;
 		if(__unlikely(i >= nargs))
-			lerrorf(FL(ArgError), "keyword %s requires an argument", symbol_name(v));
+			lerrorf(FL_ArgError, "keyword %s requires an argument", symbol_name(v));
 		value_t hv = fixnum(((symbol_t*)ptr(v))->hash);
 		fixnum_t lx = numval(hv);
 		uintptr_t x = 2*((lx < 0 ? -lx : lx) % n);
@@ -797,7 +819,7 @@
 				args[idx] = FL(stack)[bp+i];
 			}
 		}else{
-			lerrorf(FL(ArgError), "unsupported keyword %s", symbol_name(v));
+			lerrorf(FL_ArgError, "unsupported keyword %s", symbol_name(v));
 		}
 		i++;
 		if(i >= nargs)
@@ -807,7 +829,7 @@
 no_kw:
 	nrestargs = nargs - i;
 	if(__unlikely(!va && nrestargs > 0))
-		lerrorf(FL(ArgError), "too many arguments");
+		lerrorf(FL_ArgError, "too many arguments");
 	nargs = ntot + nrestargs;
 	if(nrestargs)
 		memmove(&FL(stack)[bp+ntot], &FL(stack)[bp+i], nrestargs*sizeof(value_t));
@@ -1019,7 +1041,7 @@
 	ms = compute_maxstack((uint8_t*)data, cv_len(arr));
 #endif
 	if(ms < 0)
-		lerrorf(FL(ArgError), "invalid bytecode");
+		lerrorf(FL_ArgError, "invalid bytecode");
 	PUT_INT32(data, ms);
 	function_t *fn = alloc_words(4);
 	value_t fv = tagptr(fn, TAG_FUNCTION);
@@ -1026,7 +1048,7 @@
 	fn->bcode = args[0];
 	fn->vals = args[1];
 	fn->env = FL_nil;
-	fn->name = FL(lambda);
+	fn->name = FL_lambda;
 	if(nargs > 2){
 		if(issymbol(args[2])){
 			fn->name = args[2];
@@ -1041,7 +1063,7 @@
 			}
 		}
 		if(__unlikely(isgensym(fn->name)))
-			lerrorf(FL(ArgError), "name should not be a gensym");
+			lerrorf(FL_ArgError, "name should not be a gensym");
 	}
 	return fv;
 }
@@ -1140,7 +1162,7 @@
 BUILTIN("map", map)
 {
 	if(__unlikely(nargs < 2))
-		lerrorf(FL(ArgError), "too few arguments");
+		lerrorf(FL_ArgError, "too few arguments");
 	intptr_t argSP = args-FL(stack);
 	assert(argSP >= 0 && argSP < FL(nstack));
 	while(FL(sp)+2+1+nargs >= FL(nstack))
@@ -1175,7 +1197,7 @@
 BUILTIN("for-each", for_each)
 {
 	if(__unlikely(nargs < 2))
-		lerrorf(FL(ArgError), "too few arguments");
+		lerrorf(FL_ArgError, "too few arguments");
 	intptr_t argSP = args-FL(stack);
 	assert(argSP >= 0 && argSP < FL(nstack));
 	if(FL(sp)+1+2*nargs >= FL(nstack))
@@ -1283,61 +1305,62 @@
 	FL(nstack) = 4096;
 	FL(stack) = MEM_ALLOC(FL(nstack)*sizeof(value_t));
 
-	FL(lambda) = symbol("λ", false);
-	FL(function) = symbol("function", false);
-	FL(quote) = symbol("quote", false);
-	FL(trycatch) = symbol("trycatch", false);
-	FL(backquote) = symbol("quasiquote", false);
-	FL(comma) = symbol("unquote", false);
-	FL(commaat) = symbol("unquote-splicing", false);
-	FL(commadot) = symbol("unquote-nsplicing", false);
-	FL(IOError) = symbol("io-error", false);
-	FL(ParseError) = symbol("parse-error", false);
-	FL(TypeError) = symbol("type-error", false);
-	FL(ArgError) = symbol("arg-error", false);
-	FL(UnboundError) = symbol("unbound-error", false);
-	FL(KeyError) = symbol("key-error", false);
-	FL(MemoryError) = symbol("memory-error", false);
-	FL(BoundsError) = symbol("bounds-error", false);
-	FL(DivideError) = symbol("divide-error", false);
-	FL(EnumerationError) = symbol("enumeration-error", false);
-	FL(Error) = symbol("error", false);
-	FL(conssym) = symbol("cons", false);
-	FL(symbolsym) = symbol("symbol", false);
-	FL(fixnumsym) = symbol("fixnum", false);
-	FL(vectorsym) = symbol("vector", false);
-	FL(builtinsym) = symbol("builtin", false);
-	FL(booleansym) = symbol("boolean", false);
-	FL(nullsym) = symbol("null", false);
-	FL(definesym) = symbol("define", false);
-	FL(defmacrosym) = symbol("define-macro", false);
-	FL(forsym) = symbol("for", false);
-	FL(setqsym) = symbol("set!", false);
-	FL(evalsym) = symbol("eval", false);
-	FL(vu8sym) = symbol("vu8", false);
-	FL(fnsym) = symbol("fn", false);
-	FL(nulsym) = symbol("nul", false);
-	FL(alarmsym) = symbol("alarm", false);
-	FL(backspacesym) = symbol("backspace", false);
-	FL(tabsym) = symbol("tab", false);
-	FL(linefeedsym) = symbol("linefeed", false);
-	FL(vtabsym) = symbol("vtab", false);
-	FL(pagesym) = symbol("page", false);
-	FL(returnsym) = symbol("return", false);
-	FL(escsym) = symbol("esc", false);
-	FL(spacesym) = symbol("space", false);
-	FL(deletesym) = symbol("delete", false);
-	FL(newlinesym) = symbol("newline", false);
-	FL(tsym) = symbol("t", false);
-	FL(Tsym) = symbol("T", false);
-	FL(fsym) = symbol("f", false);
-	FL(Fsym) = symbol("F", false);
-	FL(builtins_table_sym) = symbol("*builtins*", false);
-	set(FL(printprettysym) = symbol("*print-pretty*", false), FL_t);
-	set(FL(printreadablysym) = symbol("*print-readably*", false), FL_t);
-	set(FL(printwidthsym) = symbol("*print-width*", false), fixnum(FL(scr_width)));
-	set(FL(printlengthsym) = symbol("*print-length*", false), FL_f);
-	set(FL(printlevelsym) = symbol("*print-level*", false), FL_f);
+	FL_lambda = symbol("λ", false);
+	FL_function = symbol("function", false);
+	FL_quote = symbol("quote", false);
+	FL_trycatch = symbol("trycatch", false);
+	FL_backquote = symbol("quasiquote", false);
+	FL_comma = symbol("unquote", false);
+	FL_commaat = symbol("unquote-splicing", false);
+	FL_commadot = symbol("unquote-nsplicing", false);
+	FL_IOError = symbol("io-error", false);
+	FL_ParseError = symbol("parse-error", false);
+	FL_TypeError = symbol("type-error", false);
+	FL_ArgError = symbol("arg-error", false);
+	FL_UnboundError = symbol("unbound-error", false);
+	FL_KeyError = symbol("key-error", false);
+	FL_MemoryError = symbol("memory-error", false);
+	FL_BoundsError = symbol("bounds-error", false);
+	FL_DivideError = symbol("divide-error", false);
+	FL_EnumerationError = symbol("enumeration-error", false);
+	FL_Error = symbol("error", false);
+	FL_conssym = symbol("cons", false);
+	FL_symbolsym = symbol("symbol", false);
+	FL_fixnumsym = symbol("fixnum", false);
+	FL_vectorsym = symbol("vector", false);
+	FL_builtinsym = symbol("builtin", false);
+	FL_booleansym = symbol("boolean", false);
+	FL_nullsym = symbol("null", false);
+	FL_definesym = symbol("define", false);
+	FL_defmacrosym = symbol("define-macro", false);
+	FL_forsym = symbol("for", false);
+	FL_setqsym = symbol("set!", false);
+	FL_evalsym = symbol("eval", false);
+	FL_vu8sym = symbol("vu8", false);
+	FL_fnsym = symbol("fn", false);
+	FL_nulsym = symbol("nul", false);
+	FL_alarmsym = symbol("alarm", false);
+	FL_backspacesym = symbol("backspace", false);
+	FL_tabsym = symbol("tab", false);
+	FL_linefeedsym = symbol("linefeed", false);
+	FL_vtabsym = symbol("vtab", false);
+	FL_pagesym = symbol("page", false);
+	FL_returnsym = symbol("return", false);
+	FL_escsym = symbol("esc", false);
+	FL_spacesym = symbol("space", false);
+	FL_deletesym = symbol("delete", false);
+	FL_newlinesym = symbol("newline", false);
+	FL_tsym = symbol("t", false);
+	FL_Tsym = symbol("T", false);
+	FL_fsym = symbol("f", false);
+	FL_Fsym = symbol("F", false);
+	FL_builtins_table_sym = symbol("*builtins*", false);
+
+	set(FL_printprettysym = symbol("*print-pretty*", false), FL_t);
+	set(FL_printreadablysym = symbol("*print-readably*", false), FL_t);
+	set(FL_printwidthsym = symbol("*print-width*", false), fixnum(FL(scr_width)));
+	set(FL_printlengthsym = symbol("*print-length*", false), FL_f);
+	set(FL_printlevelsym = symbol("*print-level*", false), FL_f);
 	FL(lasterror) = FL_nil;
 	for(i = 0; i < nelem(builtins); i++){
 		if(builtins[i].name)
@@ -1352,7 +1375,7 @@
 	cvalues_init();
 
 	set(symbol("*os-name*", false), cvalue_static_cstring(__os_name__));
-	FL(memory_exception_value) = fl_list2(FL(MemoryError), cvalue_static_cstring("out of memory"));
+	FL(memory_exception_value) = fl_list2(FL_MemoryError, cvalue_static_cstring("out of memory"));
 
 	const builtinspec_t *b;
 	for(i = 0, b = builtin_fns; i < nelem(builtin_fns); i++, b++)
@@ -1369,7 +1392,7 @@
 value_t
 fl_toplevel_eval(value_t expr)
 {
-	return fl_applyn(1, symbol_value(FL(evalsym)), expr);
+	return fl_applyn(1, symbol_value(FL_evalsym), expr);
 }
 
 int
--- a/flisp.h
+++ b/flisp.h
@@ -253,7 +253,7 @@
 #define argcount(nargs, c) \
 	do{ \
 		if(__unlikely(nargs != c)) \
-			lerrorf(FL(ArgError), "arity mismatch: wanted %d, got %d", c, nargs); \
+			lerrorf(FL_ArgError, "arity mismatch: wanted %d, got %d", c, nargs); \
 	}while(0)
 
 typedef struct {
@@ -350,10 +350,6 @@
 
 	size_t malloc_pressure;
 
-	value_t quote;
-	value_t lambda, trycatch;
-	value_t backquote, comma, commaat, commadot, function;
-
 	bool grew;
 
 	cvalue_t **finalizers;
@@ -371,38 +367,14 @@
 	uint32_t throwing_frame;  // active frame when exception was thrown
 	value_t lasterror;
 
-	value_t printwidthsym, printreadablysym, printprettysym, printlengthsym;
-	value_t printlevelsym, builtins_table_sym;
-	value_t conssym, symbolsym, fixnumsym, vectorsym, builtinsym, vu8sym;
-	value_t definesym, defmacrosym, forsym, setqsym;
-	value_t tsym, Tsym, fsym, Fsym, booleansym, nullsym, evalsym, fnsym;
-	// for reading characters
-	value_t nulsym, alarmsym, backspacesym, tabsym, linefeedsym, newlinesym;
-	value_t vtabsym, pagesym, returnsym, escsym, spacesym, deletesym;
+	fltype_t *tabletype;
 
-	value_t IOError, ParseError, TypeError, ArgError, MemoryError;
-	value_t DivideError, BoundsError, Error, KeyError, EnumerationError;
-	value_t UnboundError;
+	fltype_t *iostreamtype;
 
 	value_t the_empty_vector;
 	value_t the_empty_string;
 	value_t memory_exception_value;
 
-	value_t tablesym;
-	fltype_t *tabletype;
-
-	value_t sizesym, tosym;
-
-	value_t iostreamsym, rdsym, wrsym, apsym, crsym, truncsym;
-	value_t instrsym, outstrsym;
-	fltype_t *iostreamtype;
-
-	value_t int8sym, uint8sym, int16sym, uint16sym, int32sym, uint32sym;
-	value_t int64sym, uint64sym, bignumsym;
-	value_t bytesym, runesym, floatsym, doublesym;
-	value_t stringtypesym, runestringtypesym;
-	value_t arraysym;
-
 	htable_t TypeTable;
 	htable_t reverse_dlsym_lookup_table;
 	fltype_t *mpinttype;
@@ -424,7 +396,6 @@
 
 	bool exiting;
 
-	value_t fsosym;
 	fltype_t *fsotype;
 
 	uint32_t *consflags;
@@ -448,6 +419,29 @@
 Fl *fl;
 
 #define FL(f) fl->f
+
+extern value_t FL_builtins_table_sym, FL_quote, FL_lambda, FL_function, FL_comma, FL_commaat;
+extern value_t FL_commadot, FL_trycatch, FL_backquote;
+extern value_t FL_conssym, FL_symbolsym, FL_fixnumsym, FL_vectorsym, FL_builtinsym, FL_vu8sym;
+extern value_t FL_definesym, FL_defmacrosym, FL_forsym, FL_setqsym;
+extern value_t FL_tsym, FL_Tsym, FL_fsym, FL_Fsym, FL_booleansym, FL_nullsym, FL_evalsym, FL_fnsym;
+extern value_t FL_nulsym, FL_alarmsym, FL_backspacesym, FL_tabsym, FL_linefeedsym, FL_newlinesym;
+extern value_t FL_vtabsym, FL_pagesym, FL_returnsym, FL_escsym, FL_spacesym, FL_deletesym;
+extern value_t FL_IOError, FL_ParseError, FL_TypeError, FL_ArgError, FL_MemoryError;
+extern value_t FL_DivideError, FL_BoundsError, FL_Error, FL_KeyError, FL_EnumerationError;
+extern value_t FL_UnboundError;
+extern value_t FL_sizesym, FL_tosym;
+extern value_t FL_fsosym;
+
+extern value_t FL_printwidthsym, FL_printreadablysym, FL_printprettysym, FL_printlengthsym;
+extern value_t FL_printlevelsym;
+extern value_t FL_tablesym, FL_arraysym;
+extern value_t FL_iostreamsym, FL_rdsym, FL_wrsym, FL_apsym, FL_crsym, FL_truncsym;
+extern value_t FL_instrsym, FL_outstrsym;
+extern value_t FL_int8sym, FL_uint8sym, FL_int16sym, FL_uint16sym, FL_int32sym, FL_uint32sym;
+extern value_t FL_int64sym, FL_uint64sym, FL_bignumsym;
+extern value_t FL_bytesym, FL_runesym, FL_floatsym, FL_doublesym;
+extern value_t FL_stringtypesym, FL_runestringtypesym;
 
 extern double D_PNAN, D_NNAN, D_PINF, D_NINF;
 extern float F_PNAN, F_NNAN, F_PINF, F_NINF;
--- a/iostream.c
+++ b/iostream.c
@@ -73,15 +73,15 @@
 	size_t i;
 	int r = 0, w = 0, c = 0, t = 0, a = 0;
 	for(i = 1; i < nargs; i++){
-		if(args[i] == FL(rdsym))
+		if(args[i] == FL_rdsym)
 			r = 1;
-		else if(args[i] == FL(wrsym))
+		else if(args[i] == FL_wrsym)
 			w = 1;
-		else if(args[i] == FL(apsym))
+		else if(args[i] == FL_apsym)
 			a = w = 1;
-		else if(args[i] == FL(crsym))
+		else if(args[i] == FL_crsym)
 			c = w = 1;
-		else if(args[i] == FL(truncsym))
+		else if(args[i] == FL_truncsym)
 			t = w = 1;
 	}
 	if((r|w|c|t|a) == 0)
@@ -90,7 +90,7 @@
 	char *fname = tostring(args[0]);
 	ios_t *s = value2c(ios_t*, f);
 	if(ios_file(s, fname, r, w, c, t) == nil)
-		lerrorf(FL(IOError), "could not open \"%s\"", fname);
+		lerrorf(FL_IOError, "could not open \"%s\"", fname);
 	if(a)
 		ios_seek_end(s);
 	return f;
@@ -103,7 +103,7 @@
 	value_t f = cvalue(FL(iostreamtype), sizeof(ios_t));
 	ios_t *s = value2c(ios_t*, f);
 	if(ios_mem(s, 0) == nil)
-		lerrorf(FL(MemoryError), "could not allocate stream");
+		lerrorf(FL_MemoryError, "could not allocate stream");
 	return f;
 }
 
@@ -111,10 +111,10 @@
 {
 	if(nargs > 1)
 		argcount(nargs, 1);
-	value_t a = nargs == 0 ? symbol_value(FL(instrsym)) : args[0];
+	value_t a = nargs == 0 ? symbol_value(FL_instrsym) : args[0];
 	USED(toiostream(a));
 	value_t v = fl_read_sexpr(a);
-	a = nargs == 0 ? symbol_value(FL(instrsym)) : args[0];
+	a = nargs == 0 ? symbol_value(FL_instrsym) : args[0];
 	return ios_eof(toiostream(a)) ? FL_eof : v;
 }
 
@@ -125,10 +125,10 @@
 	Rune r;
 	int res;
 	if((res = ios_getutf8(s, &r)) == IOS_EOF)
-		//lerrorf(FL(IOError), "end of file reached");
+		//lerrorf(FL_IOError, "end of file reached");
 		return FL_eof;
 	if(res == 0)
-		lerrorf(FL(IOError), "invalid UTF-8 sequence");
+		lerrorf(FL_IOError, "invalid UTF-8 sequence");
 	return mk_rune(r);
 }
 
@@ -142,7 +142,7 @@
 		return r ? FL_t : FL_f;
 	if(r == IOS_EOF)
 		return FL_eof;
-	lerrorf(FL(IOError), "i/o error");
+	lerrorf(FL_IOError, "i/o error");
 }
 
 BUILTIN("io-putc", io_putc)
@@ -218,7 +218,7 @@
 	if(nargs < 1 || nargs > 2)
 		argcount(nargs, 1);
 	ios_t *s;
-	s = nargs == 2 ? toiostream(args[1]) : toiostream(symbol_value(FL(outstrsym)));
+	s = nargs == 2 ? toiostream(args[1]) : toiostream(symbol_value(FL_outstrsym));
 	fl_print(s, args[0]);
 	return args[0];
 }
@@ -237,7 +237,7 @@
 	}else{
 		ft = get_type(args[1]);
 		if(ft->eltype != nil && !iscons(cdr_(cdr_(args[1]))))
-			lerrorf(FL(ArgError), "incomplete type");
+			lerrorf(FL_ArgError, "incomplete type");
 		n = ft->size;
 	}
 	value_t cv = cvalue(ft, n);
@@ -244,7 +244,7 @@
 	uint8_t *data = cptr(cv);
 	size_t got = ios_read(s, data, n);
 	if(got < n)
-		//lerrorf(FL(IOError), "end of input reached");
+		//lerrorf(FL_IOError, "end of input reached");
 		return FL_eof;
 	return cv;
 }
@@ -268,7 +268,7 @@
 	ios_t *s = toiostream(args[0]);
 	if(iscprim(args[1]) && ((cprim_t*)ptr(args[1]))->type == FL(runetype)){
 		if(nargs > 2)
-			lerrorf(FL(ArgError), "offset argument not supported for characters");
+			lerrorf(FL_ArgError, "offset argument not supported for characters");
 		Rune r = *(Rune*)cp_data(ptr(args[1]));
 		return fixnum(ios_pututf8(s, r));
 	}
@@ -290,7 +290,7 @@
 	if(uldelim > 0x7f){
 		// runes > 0x7f, or anything else > 0xff, are out of range
 		if((iscprim(arg) && cp_class(ptr(arg)) == FL(runetype)) || uldelim > 0xff)
-			lerrorf(FL(ArgError), "delimiter out of range");
+			lerrorf(FL_ArgError, "delimiter out of range");
 	}
 	return (uint8_t)uldelim;
 }
@@ -410,7 +410,7 @@
 	argcount(nargs, 1);
 	ios_t *src = toiostream(args[0]);
 	if(src->bm != bm_mem)
-		lerrorf(FL(ArgError), "requires memory stream");
+		lerrorf(FL_ArgError, "requires memory stream");
 	bool eof = ios_eof(src);
 	value_t v = stream_to_string(&args[0]);
 	if(eof && v == FL(the_empty_string))
@@ -421,15 +421,15 @@
 void
 iostream_init(void)
 {
-	FL(iostreamsym) = symbol("iostream", false);
-	FL(rdsym) = symbol(":read", false);
-	FL(wrsym) = symbol(":write", false);
-	FL(apsym) = symbol(":append", false);
-	FL(crsym) = symbol(":create", false);
-	FL(truncsym) = symbol(":truncate", false);
-	FL(instrsym) = symbol("*input-stream*", false);
-	FL(outstrsym) = symbol("*output-stream*", false);
-	FL(iostreamtype) = define_opaque_type(FL(iostreamsym), sizeof(ios_t), &iostream_vtable, nil);
+	FL_iostreamsym = symbol("iostream", false);
+	FL_rdsym = symbol(":read", false);
+	FL_wrsym = symbol(":write", false);
+	FL_apsym = symbol(":append", false);
+	FL_crsym = symbol(":create", false);
+	FL_truncsym = symbol(":truncate", false);
+	FL_instrsym = symbol("*input-stream*", false);
+	FL_outstrsym = symbol("*output-stream*", false);
+	FL(iostreamtype) = define_opaque_type(FL_iostreamsym, sizeof(ios_t), &iostream_vtable, nil);
 	set(symbol("*stdout*", false), cvalue_from_ref(FL(iostreamtype), ios_stdout, sizeof(ios_t), FL_nil));
 	set(symbol("*stderr*", false), cvalue_from_ref(FL(iostreamtype), ios_stderr, sizeof(ios_t), FL_nil));
 	set(symbol("*stdin*", false), cvalue_from_ref(FL(iostreamtype), ios_stdin, sizeof(ios_t), FL_nil));
--- a/print.c
+++ b/print.c
@@ -205,8 +205,8 @@
 specialindent(value_t head)
 {
 	// indent these forms 2 spaces, not lined up with the first argument
-	if(head == FL(lambda) || head == FL(trycatch) || head == FL(definesym) ||
-		head == FL(defmacrosym) || head == FL(forsym))
+	if(head == FL_lambda || head == FL_trycatch || head == FL_definesym ||
+		head == FL_defmacrosym || head == FL_forsym)
 		return 2;
 	return -1;
 }
@@ -241,7 +241,7 @@
 indentafter3(value_t head, value_t v)
 {
 	// for certain X always indent (X a b c) after b
-	return ((head == FL(forsym)) && !allsmallp(cdr_(v)));
+	return ((head == FL_forsym) && !allsmallp(cdr_(v)));
 }
 
 static int
@@ -248,7 +248,7 @@
 indentafter2(value_t head, value_t v)
 {
 	// for certain X always indent (X a b) after a
-	return ((head == FL(definesym) || head == FL(defmacrosym)) &&
+	return ((head == FL_definesym || head == FL_defmacrosym) &&
 			!allsmallp(cdr_(v)));
 }
 
@@ -258,7 +258,7 @@
 	// indent before every subform of a special form, unless every
 	// subform is "small"
 	value_t c = car_(v);
-	if(c == FL(lambda) || c == FL(setqsym))
+	if(c == FL_lambda || c == FL_setqsym)
 		return 0;
 	//if(c == FL(IF)) // TODO: others
 	//	return !allsmallp(cdr_(v));
@@ -282,11 +282,11 @@
 	char *op;
 	if(iscons(cdr_(v)) && cdr_(cdr_(v)) == FL_nil &&
 		!ptrhash_has(&FL(printconses), (void*)cdr_(v)) &&
-		(((car_(v) == FL(quote))	 && (op = "'"))  ||
-		 ((car_(v) == FL(backquote)) && (op = "`"))  ||
-		 ((car_(v) == FL(comma))	 && (op = ","))  ||
-		 ((car_(v) == FL(commaat))   && (op = ",@")) ||
-		 ((car_(v) == FL(commadot))  && (op = ",.")))){
+		(((car_(v) == FL_quote)	    && (op = "'"))  ||
+		 ((car_(v) == FL_backquote) && (op = "`"))  ||
+		 ((car_(v) == FL_comma)     && (op = ","))  ||
+		 ((car_(v) == FL_commaat)   && (op = ",@")) ||
+		 ((car_(v) == FL_commadot)  && (op = ",.")))){
 		// special prefix syntax
 		unmark_cons(v);
 		unmark_cons(cdr_(v));
@@ -323,7 +323,7 @@
 		}
 
 		if(!FL(print_pretty) ||
-			((head == FL(lambda)) && n == 0)){
+			((head == FL_lambda) && n == 0)){
 			// never break line before lambda-list
 			ind = 0;
 		}else{
@@ -337,7 +337,7 @@
 
 				   (est != -1 && (FL(hpos)+est > FL(scr_width)-2)) ||
 
-				   ((head == FL(lambda)) && !nextsmall) ||
+				   ((head == FL_lambda) && !nextsmall) ||
 
 				   (n > 0 && always) ||
 
@@ -446,7 +446,7 @@
 					outc(f, ' ');
 					fl_print_child(f, fn->env);
 				}
-				if(fn->name != FL(lambda)){
+				if(fn->name != FL_lambda){
 					outc(f, ' ');
 					fl_print_child(f, fn->name);
 				}
@@ -631,7 +631,7 @@
 static void
 cvalue_printdata(ios_t *f, void *data, size_t len, value_t type, int weak)
 {
-	if(type == FL(bytesym)){
+	if(type == FL_bytesym){
 		uint8_t ch = *(uint8_t*)data;
 		if(FL(print_princ))
 			outc(f, ch);
@@ -639,7 +639,7 @@
 			FL(hpos) += ios_printf(f, "0x%hhx", ch);
 		else
 			FL(hpos) += ios_printf(f, "#byte(0x%hhx)", ch);
-	}else if(type == FL(runesym)){
+	}else if(type == FL_runesym){
 		Rune r = *(Rune*)data;
 		char seq[UTFmax+1];
 		int nb = runetochar(seq, &r);
@@ -668,11 +668,11 @@
 				break;
 			}
 		}
-	}else if(type == FL(floatsym) || type == FL(doublesym)){
+	}else if(type == FL_floatsym || type == FL_doublesym){
 		char buf[64];
 		double d;
 		int ndec;
-		if(type == FL(floatsym)){
+		if(type == FL_floatsym){
 			d = (double)*(float*)data;
 			ndec = 8;
 		}else{
@@ -685,7 +685,7 @@
 				rep = signbit(d) ? "-nan.0" : "+nan.0";
 			else
 				rep = signbit(d) ? "-inf.0" : "+inf.0";
-			if(type == FL(floatsym) && !FL(print_princ) && !weak)
+			if(type == FL_floatsym && !FL(print_princ) && !weak)
 				FL(hpos) += ios_printf(f, "#%s(%s)", symbol_name(type), rep);
 			else
 				outs(f, rep);
@@ -694,7 +694,7 @@
 				outsn(f, "-0.0", 4);
 			else
 				outsn(f, "0.0", 3);
-			if(type == FL(floatsym) && !FL(print_princ) && !weak)
+			if(type == FL_floatsym && !FL(print_princ) && !weak)
 				outc(f, 'f');
 		}else{
 			snprint_real(buf, sizeof(buf), d, 0, ndec, 3, 10);
@@ -702,16 +702,16 @@
 			outs(f, buf);
 			if(!hasdec)
 				outsn(f, ".0", 2);
-			if(type == FL(floatsym) && !FL(print_princ) && !weak)
+			if(type == FL_floatsym && !FL(print_princ) && !weak)
 				outc(f, 'f');
 		}
-	}else if(type == FL(uint64sym)){
+	}else if(type == FL_uint64sym){
 		uint64_t ui64 = *(uint64_t*)data;
 		if(weak || FL(print_princ))
 			FL(hpos) += ios_printf(f, "%"PRIu64, ui64);
 		else
 			FL(hpos) += ios_printf(f, "#%s(%"PRIu64")", symbol_name(type), ui64);
-	}else if(type == FL(bignumsym)){
+	}else if(type == FL_bignumsym){
 		mpint *i = *(mpint**)data;
 		char *s = mptoa(i, 10, nil, 0);
 		FL(hpos) += ios_printf(f, "%s", s);
@@ -730,7 +730,7 @@
 			FL(hpos) += ios_printf(f, "#<%s>", symbol_name(type));
 		}
 	}else if(iscons(type)){
-		if(car_(type) == FL(arraysym)){
+		if(car_(type) == FL_arraysym){
 			size_t i;
 			value_t eltype = car(cdr_(type));
 			size_t cnt, elsize;
@@ -742,7 +742,7 @@
 				elsize = ctype_sizeof(eltype);
 				cnt = elsize ? len/elsize : 0;
 			}
-			if(eltype == FL(bytesym)){
+			if(eltype == FL_bytesym){
 				if(FL(print_princ)){
 					ios_write(f, data, len);
 					/*
@@ -758,7 +758,7 @@
 					outc(f, '"');
 				}
 				return;
-			}else if(eltype == FL(runesym)){
+			}else if(eltype == FL_runesym){
 				char buf[UTFmax];
 				if(!FL(print_princ))
 					outc(f, '"');
@@ -774,7 +774,7 @@
 				return;
 			}
 			if(!weak){
-				if(eltype == FL(uint8sym)){
+				if(eltype == FL_uint8sym){
 					outsn(f, "#vu8(", 5);
 				}else{
 					outsn(f, "#array(", 7);
@@ -829,7 +829,7 @@
 static void
 set_print_width(void)
 {
-	value_t pw = symbol_value(FL(printwidthsym));
+	value_t pw = symbol_value(FL_printwidthsym);
 	if(!isfixnum(pw))
 		return;
 	FL(scr_width) = numval(pw);
@@ -838,13 +838,13 @@
 void
 fl_print(ios_t *f, value_t v)
 {
-	FL(print_pretty) = symbol_value(FL(printprettysym)) != FL_f;
+	FL(print_pretty) = symbol_value(FL_printprettysym) != FL_f;
 	if(FL(print_pretty))
 		set_print_width();
-	FL(print_princ) = symbol_value(FL(printreadablysym)) == FL_f;
-	value_t pl = symbol_value(FL(printlengthsym));
+	FL(print_princ) = symbol_value(FL_printreadablysym) == FL_f;
+	value_t pl = symbol_value(FL_printlengthsym);
 	FL(print_length) = isfixnum(pl) ? numval(pl) : -1;
-	pl = symbol_value(FL(printlevelsym));
+	pl = symbol_value(FL_printlevelsym);
 	FL(print_level) = isfixnum(pl) ? numval(pl) : -1;
 	FL(p_level) = 0;
 
--- a/read.c
+++ b/read.c
@@ -128,7 +128,7 @@
 	value_t msg = string_from_cstr(msgbuf);
 	va_end(args);
 
-	fl_raise(fl_list2(FL(ParseError), msg));
+	fl_raise(fl_list2(FL_ParseError, msg));
 }
 
 static void
@@ -241,18 +241,18 @@
 				read_token(ctx, (char)cval, 0);
 				ctx->tokval = symbol(ctx->buf, true);
 				if(ctx->buf[1] == '\0') USED(cval); /* one character */
-				else if(ctx->tokval == FL(nulsym))       cval = 0x00;
-				else if(ctx->tokval == FL(alarmsym))     cval = 0x07;
-				else if(ctx->tokval == FL(backspacesym)) cval = 0x08;
-				else if(ctx->tokval == FL(tabsym))       cval = 0x09;
-				else if(ctx->tokval == FL(linefeedsym))  cval = 0x0A;
-				else if(ctx->tokval == FL(newlinesym))   cval = 0x0A;
-				else if(ctx->tokval == FL(vtabsym))      cval = 0x0B;
-				else if(ctx->tokval == FL(pagesym))      cval = 0x0C;
-				else if(ctx->tokval == FL(returnsym))    cval = 0x0D;
-				else if(ctx->tokval == FL(escsym))       cval = 0x1B;
-				else if(ctx->tokval == FL(spacesym))     cval = 0x20;
-				else if(ctx->tokval == FL(deletesym))    cval = 0x7F;
+				else if(ctx->tokval == FL_nulsym)       cval = 0x00;
+				else if(ctx->tokval == FL_alarmsym)     cval = 0x07;
+				else if(ctx->tokval == FL_backspacesym) cval = 0x08;
+				else if(ctx->tokval == FL_tabsym)       cval = 0x09;
+				else if(ctx->tokval == FL_linefeedsym)  cval = 0x0A;
+				else if(ctx->tokval == FL_newlinesym)   cval = 0x0A;
+				else if(ctx->tokval == FL_vtabsym)      cval = 0x0B;
+				else if(ctx->tokval == FL_pagesym)      cval = 0x0C;
+				else if(ctx->tokval == FL_returnsym)    cval = 0x0D;
+				else if(ctx->tokval == FL_escsym)       cval = 0x1B;
+				else if(ctx->tokval == FL_spacesym)     cval = 0x20;
+				else if(ctx->tokval == FL_deletesym)    cval = 0x7F;
 				else
 					parse_error(&ctx->loc, "unknown character #\\%s", ctx->buf);
 			}
@@ -604,15 +604,15 @@
 		read_list(ctx, &FL(stack)[FL(sp)-1], label, TOK_CLOSEC);
 		return POP();
 	case TOK_COMMA:
-		head = &FL(comma); goto listwith;
+		head = &FL_comma; goto listwith;
 	case TOK_COMMAAT:
-		head = &FL(commaat); goto listwith;
+		head = &FL_commaat; goto listwith;
 	case TOK_COMMADOT:
-		head = &FL(commadot); goto listwith;
+		head = &FL_commadot; goto listwith;
 	case TOK_BQ:
-		head = &FL(backquote); goto listwith;
+		head = &FL_backquote; goto listwith;
 	case TOK_QUOTE:
-		head = &FL(quote);
+		head = &FL_quote;
 	listwith:
 		v = cons_reserve(2);
 		car_(v) = *head;
@@ -629,9 +629,9 @@
 		return do_read_sexpr(ctx, label);
 	case TOK_SHARPSYM:
 		sym = ctx->tokval;
-		if(sym == FL(tsym) || sym == FL(Tsym))
+		if(sym == FL_tsym || sym == FL_Tsym)
 			return FL_t;
-		if(sym == FL(fsym) || sym == FL(Fsym))
+		if(sym == FL_fsym || sym == FL_Fsym)
 			return FL_f;
 		// constructor notation
 		c = nextchar();
@@ -642,11 +642,11 @@
 		}
 		PUSH(FL_nil);
 		read_list(ctx, &FL(stack)[FL(sp)-1], UNBOUND, TOK_CLOSE);
-		if(sym == FL(vu8sym)){
-			sym = FL(arraysym);
-			FL(stack)[FL(sp)-1] = fl_cons(FL(uint8sym), FL(stack)[FL(sp)-1]);
-		}else if(sym == FL(fnsym)){
-			sym = FL(function);
+		if(sym == FL_vu8sym){
+			sym = FL_arraysym;
+			FL(stack)[FL(sp)-1] = fl_cons(FL_uint8sym, FL(stack)[FL(sp)-1]);
+		}else if(sym == FL_fnsym){
+			sym = FL_function;
 		}
 		v = symbol_value(sym);
 		if(v == UNBOUND)
--- a/sixel.c
+++ b/sixel.c
@@ -20,6 +20,7 @@
 	int bufsz;
 };
 
+value_t FL_fsosym;
 static sixel_allocator_t *salloc;
 
 static int
@@ -50,7 +51,7 @@
 		numcolors = tosize(args[0]);
 	}
 	if(numcolors < 1 || numcolors > 256)
-		lerrorf(FL(ArgError), "invalid number of colors: %d", numcolors);
+		lerrorf(FL_ArgError, "invalid number of colors: %d", numcolors);
 	value_t v = cvalue(FL(fsotype), sizeof(fso_t));
 	fso_t *f = value2c(fso_t*, v);
 	if(salloc == nil)
@@ -57,10 +58,10 @@
 		sixel_allocator_new(&salloc, malloc, calloc, realloc, free);
 	SIXELSTATUS r = sixel_output_new(&f->out, fso_write, f, salloc);
 	if(SIXEL_FAILED(r))
-		lerrorf(FL(IOError), "could not create sixel output");
+		lerrorf(FL_IOError, "could not create sixel output");
 	r = sixel_dither_new(&f->dither, numcolors, salloc);
 	if(SIXEL_FAILED(r))
-		lerrorf(FL(IOError), "could not create sixel dither");
+		lerrorf(FL_IOError, "could not create sixel dither");
 	sixel_output_set_palette_type(f->out, SIXEL_PALETTETYPE_RGB);
 	sixel_dither_set_pixelformat(f->dither, SIXEL_PIXELFORMAT_PAL8);
 	sixel_dither_set_transparent(f->dither, 0xff);
@@ -83,7 +84,7 @@
 	if(nargs > 2)
 		scaley = tosize(args[2]);
 	if(scalex < 1 || scalex > 32 || scaley < 1 || scaley > 32)
-		lerrorf(FL(ArgError), "invalid scale factor: %dx%d", scalex, scaley);
+		lerrorf(FL_ArgError, "invalid scale factor: %dx%d", scalex, scaley);
 	f->scalex = scalex;
 	f->scaley = scaley;
 	return FL_void;
@@ -109,7 +110,7 @@
 		else if(len == 3 && strncmp(s, "hls", 3) == 0)
 			isrgb = false;
 		else
-			lerrorf(FL(ArgError), "invalid palette type (must be either \"rgb\" or \"hls\")");
+			lerrorf(FL_ArgError, "invalid palette type (must be either \"rgb\" or \"hls\")");
 	}
 
 	if(!isarray(args[1]))
@@ -116,7 +117,7 @@
 		type_error("array", args[1]);
 	len = cvalue_arraylen(args[1]);
 	if(f->numcolors*3 != (int)len)
-		lerrorf(FL(ArgError), "invalid palette: expected %d colors, got %d", f->numcolors, (int)len);
+		lerrorf(FL_ArgError, "invalid palette: expected %d colors, got %d", f->numcolors, (int)len);
 
 	fltype_t *type = cv_class(ptr(args[1]));
 	size_t elsize = type->elsz;
@@ -125,10 +126,10 @@
 
 	uint8_t out[256*3] = {0};
 	if(isrgb){
-		if(eltype->type == FL(uint8sym) || eltype->type == FL(bytesym))
+		if(eltype->type == FL_uint8sym || eltype->type == FL_bytesym)
 			memcpy(out, cptr(args[1]), f->numcolors*3);
 		else
-			lerrorf(FL(ArgError), "invalid palette type: expected bytes");
+			lerrorf(FL_ArgError, "invalid palette type: expected bytes");
 	}else{
 		uint8_t *pal = cptr(args[1]);
 		for(int i = 0; i < f->numcolors; i++){
@@ -184,7 +185,7 @@
 	if(f->scalex > 1 || f->scaley > 1){
 		int ow = w * f->scalex, oh = h * f->scaley, osz = ow*oh;
 		if(ow < 1 || oh < 1 || osz < ow || osz < oh)
-			lerrorf(FL(ArgError), "scaling out of range");
+			lerrorf(FL_ArgError, "scaling out of range");
 		if(f->bufsz < osz){
 			f->buf = MEM_REALLOC(f->buf, osz);
 			f->bufsz = osz;
@@ -199,7 +200,7 @@
 			salloc
 		);
 		if(SIXEL_FAILED(r))
-			lerrorf(FL(IOError), "could not scale image");
+			lerrorf(FL_IOError, "could not scale image");
 		w = ow;
 		h = oh;
 		pix = f->buf;
@@ -210,7 +211,7 @@
 	}
 	r = sixel_encode(pix, w, h, 0, f->dither, f->out);
 	if(SIXEL_FAILED(r))
-		lerrorf(FL(IOError), "could not encode image");
+		lerrorf(FL_IOError, "could not encode image");
 	return FL_void;
 }
 
@@ -229,7 +230,7 @@
 	sixel_output_destroy(oldf->out);
 	SIXELSTATUS r = sixel_output_new(&f->out, fso_write, f, salloc);
 	if(SIXEL_FAILED(r))
-		lerrorf(FL(IOError), "could not recreate sixel output");
+		lerrorf(FL_IOError, "could not recreate sixel output");
 	sixel_output_set_palette_type(f->out, SIXEL_PALETTETYPE_RGB);
 }
 
@@ -252,6 +253,6 @@
 void
 fsixel_init(void)
 {
-	FL(fsosym) = symbol("sixel-output", false);
-	FL(fsotype) = define_opaque_type(FL(fsosym), sizeof(fso_t), &fso_vtable, nil);
+	FL_fsosym = symbol("sixel-output", false);
+	FL(fsotype) = define_opaque_type(FL_fsosym, sizeof(fso_t), &fso_vtable, nil);
 }
--- a/string.c
+++ b/string.c
@@ -119,17 +119,17 @@
 	value_t arg, buf = fn_builtin_buffer(nil, 0);
 	fl_gc_handle(&buf);
 	ios_t *s = value2c(ios_t*, buf);
-	value_t oldpr = symbol_value(FL(printreadablysym));
-	value_t oldpp = symbol_value(FL(printprettysym));
-	set(FL(printreadablysym), FL_f);
-	set(FL(printprettysym), FL_f);
+	value_t oldpr = symbol_value(FL_printreadablysym);
+	value_t oldpp = symbol_value(FL_printprettysym);
+	set(FL_printreadablysym, FL_f);
+	set(FL_printprettysym, FL_f);
 	uint32_t i;
 	FOR_ARGS(i, 0, arg, args){
 		USED(arg);
 		fl_print(s, args[i]);
 	}
-	set(FL(printreadablysym), oldpr);
-	set(FL(printprettysym), oldpp);
+	set(FL_printreadablysym, oldpr);
+	set(FL_printprettysym, oldpp);
 	value_t outp = stream_to_string(&buf);
 	fl_free_gc_handles(1);
 	return outp;
@@ -349,7 +349,7 @@
 {
 	unsigned long radix = tosize(arg);
 	if(radix < 2 || radix > 36)
-		lerrorf(FL(ArgError), "invalid radix");
+		lerrorf(FL_ArgError, "invalid radix");
 	return radix;
 }
 
--- a/table.c
+++ b/table.c
@@ -91,7 +91,7 @@
 {
 	size_t cnt = (size_t)nargs;
 	if(cnt & 1)
-		lerrorf(FL(ArgError), "arguments must come in pairs");
+		lerrorf(FL_ArgError, "arguments must come in pairs");
 	value_t nt;
 	// prevent small tables from being added to finalizer list
 	if(cnt <= HT_N_INLINE)
@@ -135,7 +135,7 @@
 static void
 key_error(value_t key)
 {
-	lerrorf(fl_list2(FL(KeyError), key), "key not found");
+	lerrorf(fl_list2(FL_KeyError, key), "key not found");
 }
 
 // (get table key [default])
@@ -187,7 +187,7 @@
 			// reload pointer
 			h = cvalue_data(t);
 			if(h->size != n)
-				lerrorf(FL(EnumerationError), "table modified");
+				lerrorf(FL_EnumerationError, "table modified");
 			table = h->table;
 		}
 	}
@@ -198,6 +198,6 @@
 void
 table_init(void)
 {
-	FL(tablesym) = symbol("table", false);
-	FL(tabletype) = define_opaque_type(FL(tablesym), sizeof(htable_t), &table_vtable, nil);
+	FL_tablesym = symbol("table", false);
+	FL(tabletype) = define_opaque_type(FL_tablesym, sizeof(htable_t), &table_vtable, nil);
 }
--- a/types.c
+++ b/types.c
@@ -16,7 +16,7 @@
 	if(*bp != HT_NOTFOUND)
 		return *bp;
 
-	bool isarray = iscons(t) && car_(t) == FL(arraysym) && iscons(cdr_(t));
+	bool isarray = iscons(t) && car_(t) == FL_arraysym && iscons(cdr_(t));
 	size_t sz;
 	if(isarray && !iscons(cdr_(cdr_(t)))){
 		// special case: incomplete array type
@@ -39,7 +39,7 @@
 			fltype_t *eltype = get_type(car_(cdr_(t)));
 			if(eltype->size == 0){
 				MEM_FREE(ft);
-				lerrorf(FL(ArgError), "invalid array element type");
+				lerrorf(FL_ArgError, "invalid array element type");
 			}
 			ft->elsz = eltype->size;
 			ft->eltype = eltype;
@@ -56,7 +56,7 @@
 {
 	fltype_t *et = get_type(eltype);
 	if(et->artype == nil)
-		et->artype = get_type(fl_list2(FL(arraysym), eltype));
+		et->artype = get_type(fl_list2(FL_arraysym, eltype));
 	return et->artype;
 }
 
--- a/vm.inc
+++ b/vm.inc
@@ -539,7 +539,7 @@
 	}
 	if(v != FL_nil){
 		FL(stack)[ipd] = (uintptr_t)ip;
-		lerrorf(FL(ArgError), "apply: last argument: not a list");
+		lerrorf(FL_ArgError, "apply: last argument: not a list");
 	}
 	n = FL(sp)-n;
 	goto LABEL(do_call);
@@ -812,7 +812,7 @@
 		}
 	}else if(__unlikely(s < 0)){
 		FL(stack)[ipd] = (uintptr_t)ip;
-		lerrorf(FL(ArgError), "too few arguments");
+		lerrorf(FL_ArgError, "too few arguments");
 	}else{
 		FL(sp)++;
 		FL(stack)[FL(sp)-2] = i+1;
@@ -839,12 +839,12 @@
 	ip += 4;
 	if(__unlikely(nargs < i)){
 		FL(stack)[ipd] = (uintptr_t)ip;
-		lerrorf(FL(ArgError), "too few arguments");
+		lerrorf(FL_ArgError, "too few arguments");
 	}
 	if((int32_t)n > 0){
 		if(__unlikely(nargs > n)){
 			FL(stack)[ipd] = (uintptr_t)ip;
-			lerrorf(FL(ArgError), "too many arguments");
+			lerrorf(FL_ArgError, "too many arguments");
 		}
 	}else
 		n = -n;