2008-09-06 18:19:51 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include "llt.h"
|
|
|
|
#include "flisp.h"
|
2008-12-21 00:55:00 -05:00
|
|
|
#include "equalhash.h"
|
2008-09-06 18:19:51 -04:00
|
|
|
|
2008-12-20 01:16:00 -05:00
|
|
|
static value_t tablesym;
|
|
|
|
static fltype_t *tabletype;
|
|
|
|
|
2008-09-06 18:19:51 -04:00
|
|
|
typedef struct {
|
|
|
|
void *(*get)(void *t, void *key);
|
|
|
|
void (*remove)(void *t, void *key);
|
|
|
|
void **(*bp)(void *t, void *key);
|
|
|
|
} table_interface_t;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
table_interface_t *ti;
|
|
|
|
ulong_t nkeys;
|
2008-11-23 02:12:37 -05:00
|
|
|
htable_t ht;
|
2008-09-06 18:19:51 -04:00
|
|
|
} fltable_t;
|
|
|
|
|
2008-12-20 01:16:00 -05:00
|
|
|
void print_htable(value_t v, ios_t *f, int princ)
|
2008-09-06 18:19:51 -04:00
|
|
|
{
|
2008-12-20 01:16:00 -05:00
|
|
|
fltable_t *pt = (fltable_t*)cv_data((cvalue_t*)ptr(v));
|
|
|
|
htable_t *h = &pt->ht;
|
|
|
|
size_t i;
|
|
|
|
int first=1;
|
|
|
|
fl_print_str("#table(", f);
|
|
|
|
for(i=0; i < h->size; i+=2) {
|
|
|
|
if (h->table[i+1] != HT_NOTFOUND) {
|
|
|
|
if (!first) fl_print_str(" ", f);
|
|
|
|
fl_print_child(f, (value_t)h->table[i], princ);
|
|
|
|
fl_print_chr(' ', f);
|
|
|
|
fl_print_child(f, (value_t)h->table[i+1], princ);
|
|
|
|
first = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fl_print_chr(')', f);
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
|
|
|
|
2008-12-21 00:55:00 -05:00
|
|
|
void print_traverse_htable(value_t self)
|
|
|
|
{
|
|
|
|
fltable_t *pt = (fltable_t*)cv_data((cvalue_t*)ptr(self));
|
|
|
|
htable_t *h = &pt->ht;
|
|
|
|
size_t i;
|
|
|
|
for(i=0; i < h->size; i+=2) {
|
|
|
|
if (h->table[i+1] != HT_NOTFOUND) {
|
|
|
|
print_traverse((value_t)h->table[i]);
|
|
|
|
print_traverse((value_t)h->table[i+1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-06 18:19:51 -04:00
|
|
|
void free_htable(value_t self)
|
|
|
|
{
|
|
|
|
fltable_t *pt = (fltable_t*)cv_data((cvalue_t*)ptr(self));
|
2008-11-23 02:12:37 -05:00
|
|
|
htable_free(&pt->ht);
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
|
|
|
|
2008-11-28 16:44:59 -05:00
|
|
|
void relocate_htable(value_t oldv, value_t newv)
|
2008-09-06 18:19:51 -04:00
|
|
|
{
|
2008-12-21 00:55:00 -05:00
|
|
|
(void)oldv;
|
2008-11-28 16:44:59 -05:00
|
|
|
fltable_t *pt = (fltable_t*)cv_data((cvalue_t*)ptr(newv));
|
2008-11-23 02:12:37 -05:00
|
|
|
htable_t *h = &pt->ht;
|
2008-09-06 18:19:51 -04:00
|
|
|
size_t i;
|
|
|
|
for(i=0; i < h->size; i++) {
|
2008-11-23 02:12:37 -05:00
|
|
|
if (h->table[i] != HT_NOTFOUND)
|
2008-11-28 16:44:59 -05:00
|
|
|
h->table[i] = (void*)relocate_lispvalue((value_t)h->table[i]);
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-21 00:55:00 -05:00
|
|
|
cvtable_t table_vtable = { print_htable, relocate_htable, free_htable,
|
|
|
|
print_traverse_htable };
|
2008-09-06 18:19:51 -04:00
|
|
|
|
|
|
|
int ishashtable(value_t v)
|
|
|
|
{
|
2008-12-20 01:16:00 -05:00
|
|
|
return iscvalue(v) && cv_class((cvalue_t*)ptr(v)) == tabletype;
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
|
|
|
|
2008-12-21 00:55:00 -05:00
|
|
|
value_t fl_hashtablep(value_t *args, uint32_t nargs)
|
2008-09-06 18:19:51 -04:00
|
|
|
{
|
2008-12-20 01:16:00 -05:00
|
|
|
argcount("hashtablep", nargs, 1);
|
|
|
|
return ishashtable(args[0]) ? T : NIL;
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
|
|
|
|
2008-12-21 00:55:00 -05:00
|
|
|
static fltable_t *totable(value_t v, char *fname)
|
|
|
|
{
|
|
|
|
if (ishashtable(v))
|
|
|
|
return (fltable_t*)cv_data((cvalue_t*)ptr(v));
|
|
|
|
type_error(fname, "table", v);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t fl_table(value_t *args, uint32_t nargs)
|
2008-09-06 18:19:51 -04:00
|
|
|
{
|
2008-12-20 01:16:00 -05:00
|
|
|
if (nargs & 1)
|
|
|
|
lerror(ArgError, "table: arguments must come in pairs");
|
|
|
|
value_t nt = cvalue(tabletype, sizeof(fltable_t));
|
|
|
|
fltable_t *h = (fltable_t*)cv_data((cvalue_t*)ptr(nt));
|
|
|
|
htable_new(&h->ht, 8);
|
2008-12-21 00:55:00 -05:00
|
|
|
uint32_t i;
|
2008-12-20 01:16:00 -05:00
|
|
|
for(i=0; i < nargs; i+=2)
|
2008-12-21 00:55:00 -05:00
|
|
|
equalhash_put(&h->ht, (void*)args[i], (void*)args[i+1]);
|
2008-12-20 01:16:00 -05:00
|
|
|
return nt;
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
|
|
|
|
2008-11-05 23:04:04 -05:00
|
|
|
// (put table key value)
|
2008-12-21 00:55:00 -05:00
|
|
|
value_t fl_table_put(value_t *args, uint32_t nargs)
|
2008-09-06 18:19:51 -04:00
|
|
|
{
|
2008-11-05 23:04:04 -05:00
|
|
|
argcount("put", nargs, 3);
|
2008-12-21 00:55:00 -05:00
|
|
|
fltable_t *pt = totable(args[0], "put");
|
|
|
|
equalhash_put(&pt->ht, (void*)args[1], (void*)args[2]);
|
|
|
|
return args[0];
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
|
|
|
|
2008-12-20 01:16:00 -05:00
|
|
|
// (get table key [default])
|
2008-12-21 00:55:00 -05:00
|
|
|
value_t fl_table_get(value_t *args, uint32_t nargs)
|
2008-09-06 18:19:51 -04:00
|
|
|
{
|
2008-12-21 00:55:00 -05:00
|
|
|
if (nargs != 3)
|
|
|
|
argcount("get", nargs, 2);
|
|
|
|
fltable_t *pt = totable(args[0], "get");
|
|
|
|
value_t v = (value_t)equalhash_get(&pt->ht, (void*)args[1]);
|
|
|
|
if (v == (value_t)HT_NOTFOUND) {
|
|
|
|
if (nargs == 3)
|
|
|
|
return args[2];
|
|
|
|
lerror(KeyError, "get: key not found");
|
|
|
|
}
|
|
|
|
return v;
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
|
|
|
|
2008-11-05 23:04:04 -05:00
|
|
|
// (has table key)
|
2008-12-21 00:55:00 -05:00
|
|
|
value_t fl_table_has(value_t *args, uint32_t nargs)
|
2008-09-06 18:19:51 -04:00
|
|
|
{
|
2008-11-05 23:04:04 -05:00
|
|
|
argcount("has", nargs, 2);
|
2008-12-21 00:55:00 -05:00
|
|
|
fltable_t *pt = totable(args[0], "has");
|
|
|
|
return equalhash_has(&pt->ht, (void*)args[1]) ? T : NIL;
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
|
|
|
|
2008-11-05 23:04:04 -05:00
|
|
|
// (del table key)
|
2008-12-21 00:55:00 -05:00
|
|
|
value_t fl_table_del(value_t *args, uint32_t nargs)
|
2008-09-06 18:19:51 -04:00
|
|
|
{
|
2008-11-05 23:04:04 -05:00
|
|
|
argcount("del", nargs, 2);
|
2008-12-21 00:55:00 -05:00
|
|
|
fltable_t *pt = totable(args[0], "del");
|
|
|
|
if (!equalhash_remove(&pt->ht, (void*)args[1]))
|
|
|
|
lerror(KeyError, "del: key not found");
|
|
|
|
return args[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
value_t fl_table_foldl(value_t *args, uint32_t nargs)
|
|
|
|
{
|
|
|
|
argcount("table.foldl", nargs, 3);
|
|
|
|
PUSH(listn(3, NIL, NIL, NIL));
|
|
|
|
fltable_t *pt = totable(args[2], "table.foldl");
|
|
|
|
size_t i, n = pt->ht.size;
|
|
|
|
void **table = pt->ht.table;
|
|
|
|
value_t c;
|
|
|
|
for(i=0; i < n; i+=2) {
|
|
|
|
if (table[i+1] != HT_NOTFOUND) {
|
|
|
|
c = Stack[SP-1];
|
|
|
|
car_(c) = (value_t)table[i];
|
|
|
|
car_(cdr_(c)) = (value_t)table[i+1];
|
|
|
|
car_(cdr_(cdr_(c))) = args[1];
|
|
|
|
args[1] = apply(args[0], c);
|
|
|
|
// reload pointer
|
|
|
|
table = ((fltable_t*)cv_data((cvalue_t*)ptr(args[2])))->ht.table;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(void)POP();
|
|
|
|
return args[1];
|
2008-09-06 18:19:51 -04:00
|
|
|
}
|
2008-12-20 01:16:00 -05:00
|
|
|
|
|
|
|
static builtinspec_t tablefunc_info[] = {
|
|
|
|
{ "table", fl_table },
|
2008-12-21 00:55:00 -05:00
|
|
|
{ "put", fl_table_put },
|
|
|
|
{ "get", fl_table_get },
|
|
|
|
{ "has", fl_table_has },
|
|
|
|
{ "del", fl_table_del },
|
|
|
|
{ "table.foldl", fl_table_foldl },
|
2008-12-20 01:16:00 -05:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
void table_init()
|
|
|
|
{
|
|
|
|
tablesym = symbol("table");
|
|
|
|
tabletype = define_opaque_type(tablesym, sizeof(fltable_t),
|
2008-12-21 00:55:00 -05:00
|
|
|
&table_vtable, NULL);
|
2008-12-20 01:16:00 -05:00
|
|
|
assign_global_builtins(tablefunc_info);
|
|
|
|
}
|