1 #include <BindingTable.h>
6 * A Binding is an association between a name (char*) and a value
15 * This callback function should return the hashcode of a key. The
16 * hashcode is used for indexing into the backing Vector for
17 * finding the an item via its key. The same key must map
18 * consistently to the same hashcode while the hashtable contains
19 * an item with that key. Different keys map map to the same
20 * hashcode, in which case the Vector placement is made at the
21 * first empty or hole slot following the hashcode index.
23 static unsigned long binding_hashcode(void *this,void *key) {
24 char *name = (char *) key;
25 unsigned long n = strlen( name );
26 return HashVector_hashcode( (unsigned char *) name, n );
30 * This callback function should determine whether an item has a
33 static int binding_haskey(void *this,void *item,void *key) {
34 Binding *b = (Binding*) item;
35 char *name = (char *) key;
36 return strcmp( name, (char*) b->name ) == 0;
40 * This callback function should return a (possibly temporary) key
41 * of an item. It can be anything (i.e., with or without internal
42 * structure) as it is treated as an identifier that other
43 * callbacks recognize. It is merely understood as a value in an
46 static void *binding_itemkey(void *this,void *item) {
47 Binding *b = (Binding*) item;
53 * This callback function should handle a key obtained from the
54 * itemkey callback function, e.g., reclaim temporary allocation.
56 static void binding_releasekey(void *this,void *key) {
60 * This callback function writes a representation of an item into
63 static int binding_tostring(void *this,void *item,char *buffer,int limit) {
64 Binding *b = (Binding*) item;
65 return snprintf( buffer, limit, "{%s,%p}", b->name, b->value );
69 * This is the "item type" for Binding items.
71 ItemKeyFun bindingitem = {
72 .hashcode = binding_hashcode,
73 .haskey = binding_haskey,
74 .itemkey = binding_itemkey,
75 .releasekey = binding_releasekey,
76 .tostring = binding_tostring
79 BindingTable *BindingTable_create(BindingTable *next) {
80 BindingTable *this = (BindingTable*) malloc( sizeof( BindingTable ) );
81 this->table = (HashVector) {
83 .variant = Nibble_index_levels, .size = 16, .entries = 0
84 }, .fill = 0, .holes = 0, .type = &bindingitem
90 BindingTable *BindingTable_release(BindingTable *bt) {
92 BindingTable *next = bt->next;
93 Vector_resize( &bt->table.table, 0, Vector_free_any, 0 );
100 void BindingTable_set(BindingTable *bt,char *name,void *value) {
101 Binding *b = (Binding*) HashVector_find( &bt->table, name );
103 b = (Binding*) malloc( sizeof( Binding ) );
105 HashVector_add( &bt->table, b );
110 void *BindingTable_get(BindingTable *bt,char *name) {
111 for ( ; bt; bt = bt->next ) {
112 Binding *b = (Binding*) HashVector_find( &bt->table, name );
120 void BindingTable_deref(BindingTable *bt,int arity,Tuple *t) {
122 for ( i = 0; i < arity; i++ ) {
123 if ( t->elements[i] ) {
124 t->elements[i] = BindingTable_get( bt, t->elements[i] );
129 int BindingTable_unify(
130 BindingTable *bt,char *n1,char *n2,int (*eq)(void*,void*)) {
131 void *v1 = BindingTable_get( bt, n1 );
132 void *v2 = BindingTable_get( bt, n2 );
133 if ( v2 && v1 == 0 ) {
134 BindingTable_set( bt, n1, v2 );
136 if ( v1 && v2 == 0 ) {
137 BindingTable_set( bt, n2, v1 );
139 return ( v1 && v2 )? ( eq? ( eq( v1, v2 ) == 0 ) : ( v1 == v2 ) ) : 1;
142 #define COPYA(T,P,N) (T*) memcpy( malloc( N * sizeof(T) ), P, N * sizeof( T ) )
144 Tuple *BindingTable_tuple_get(BindingTable *bt,int arity,Tuple *t) {
145 Tuple *vt = Tuple_clone( arity, t );
146 BindingTable_deref( bt, arity, vt );
150 void BindingTable_tuple_set(BindingTable *bt,int arity,Tuple *nm,Tuple *vs) {
152 for ( i = 0; i < arity; i++ ) {
153 BindingTable_set( bt, nm->elements[i], vs->elements[i] );