Sigrid Solveig Haflínudóttirtable-foldl → table-fold69965461 year agoHistory
229 lines · 4.7 KB · C
RawDownload
#include "sl.h"#include "equal.h"#include "equalhash.h"#include "cvalues.h"#include "types.h"#include "print.h"#include "table.h" #define inline_space sizeof(((sl_htable*)nil)->_space) static sl_type *sl_tabletype; static voidprint_htable(sl_v v, ios *f){	sl_htable *h = cvalue_data(v);	bool first = true;	sl_print_str(f, "#table(", true);	for(int i = 0, k = 0; k < h->num && i < h->size; i += 2){		if(h->table[i+1] == HT_NOTFOUND)			continue;		k++;		if(!first)			sl_print_str(f, "  ", true);		sl_print_child(f, (sl_v)h->table[i]);		sl_print_chr(f, ' ');		sl_print_child(f, (sl_v)h->table[i+1]);		first = false;	}	sl_print_chr(f, ')');} static voidprint_traverse_htable(sl_v self){	sl_htable *h = cvalue_data(self);	for(int i = 0; i < h->size; i += 2){		if(h->table[i+1] != HT_NOTFOUND){			sl_print_traverse((sl_v)h->table[i]);			sl_print_traverse((sl_v)h->table[i+1]);		}	}} static voidfree_htable(sl_v self){	sl_htable *h = cvalue_data(self);	htable_free(h);} static voidrelocate_htable(sl_v oldv, sl_v newv){	sl_htable *oldh = cvalue_data(oldv);	sl_htable *h = cvalue_data(newv);	if(oldh->table == &oldh->_space[0])		h->table = &h->_space[0];	h->i = oldh->i;	h->num = oldh->num;	for(int i = 0, k = 0; k < h->num && i < h->size; i += 2){		if(oldh->table[i+1] == HT_NOTFOUND)			continue;		k++;		h->table[i] = (void*)sl_relocate((sl_v)oldh->table[i]);		h->table[i+1] = (void*)sl_relocate((sl_v)oldh->table[i+1]);	}} static sl_vbounded_compare_htable(sl_v a, sl_v b, int bound, bool eq){	sl_htable *ha = totable(a), *hb = totable(b);	int na = ha->size;	void **ta = ha->table; 	bound--;	for(int i = 0, k = 0; k < ha->num && i < na; i += 2){		if(ta[i+1] == HT_NOTFOUND)			continue;		k++;		sl_v v = (sl_v)equalhash_get(hb, ta[i]);		if(v == (sl_v)HT_NOTFOUND)			return fixnum(1);		v = bounded_compare((sl_v)ta[i+1], v, bound, eq);		if(v != fixnum(0))			return v;	}	if(ha->num != hb->num)		return ha->num > hb->num ? fixnum(1) : fixnum(-1);	return fixnum(0);} static sl_cvtable table_vtable = {	print_htable,	relocate_htable,	free_htable,	print_traverse_htable,	bounded_compare_htable}; boolishashtable(sl_v v){	return iscvalue(v) && cv_class(ptr(v)) == sl_tabletype;} sl_purefnBUILTIN("table?", tablep){	argcount(nargs, 1);	return ishashtable(args[0]) ? sl_t : sl_nil;} sl_htable *totable(sl_v v){	if(!ishashtable(v))		cthrow(type_error(nil, "table", v), v);	return cvalue_data(v);} BUILTIN("table", table){	int cnt = nargs;	if(cnt & 1)		bthrow(lerrorf(sl_errarg, "arguments must come in pairs"));	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));	else		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;	int i;	FOR_ARGS(i, 0, arg, args){		if(i & 1)			equalhash_put(h, (void*)k, (void*)arg);		else			k = arg;	}	assert(h->table == &h->_space[0] || cnt > HT_N_INLINE);	return nt;} BUILTIN("put!", put){	argcount(nargs, 3);	sl_htable *h = totable(args[0]);	void **table0 = h->table;	equalhash_put(h, (void*)args[1], (void*)args[2]);	// register finalizer if we outgrew inline space	if(table0 == &h->_space[0] && h->table != &h->_space[0]){		sl_cv *cv = ptr(args[0]);		add_finalizer(cv);		cv->len = sizeof(sl_htable) - inline_space;	}	return args[0];} _Noreturnstatic voidkey_error(sl_v key){	sl_raise(mk_list2(sl_errkey, key));} sl_purefnBUILTIN("get", get){	if(nargs != 3)		argcount(nargs, 2);	sl_htable *h = totable(args[0]);	sl_v v = (sl_v)equalhash_get(h, (void*)args[1]);	if(v == (sl_v)HT_NOTFOUND){		if(nargs == 3)			return args[2];		bthrow(key_error(args[1]));	}	return v;} sl_purefnBUILTIN("has?", has){	argcount(nargs, 2);	sl_htable *h = totable(args[0]);	return equalhash_has(h, (void*)args[1]) ? sl_t : sl_nil;} BUILTIN("del!", del){	argcount(nargs, 2);	sl_htable *h = totable(args[0]);	equalhash_remove(h, (void*)args[1]);	return args[0];} BUILTIN("table-fold", table_fold){	argcount(nargs, 3);	sl_v f = args[0], zero = args[1], t = args[2];	sl_htable *h = totable(t);	int n = h->size;	void **table = h->table;	sl_gc_handle(&f);	sl_gc_handle(&zero);	sl_gc_handle(&t);	for(int i = 0, k = 0; k < h->num && i < n; i += 2){		if(table[i+1] == HT_NOTFOUND)			continue;		k++;		zero = sl_applyn(3, f, (sl_v)table[i], (sl_v)table[i+1], zero);		// reload pointer		h = cvalue_data(t);		n = h->size;		table = h->table;	}	sl_free_gc_handles(3);	return zero;} voidtable_init(void){	sl_tabletype = define_opaque_type(mk_sym("table", false), sizeof(sl_htable), &table_vtable, nil);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t