304 lines
6.0 KiB
C
304 lines
6.0 KiB
C
/**
|
|
* See Copyright Notice in picrin.h
|
|
*/
|
|
|
|
#include "picrin.h"
|
|
#include "picrin/dict.h"
|
|
#include "picrin/cont.h"
|
|
#include "picrin/pair.h"
|
|
|
|
static int
|
|
xh_value_hash(const void *key, void *data)
|
|
{
|
|
union { double f; int i; } u;
|
|
pic_value val = *(pic_value *)key;
|
|
int hash, vtype;
|
|
|
|
UNUSED(data);
|
|
|
|
vtype = pic_vtype(val);
|
|
|
|
switch (vtype) {
|
|
default:
|
|
hash = 0;
|
|
break;
|
|
case PIC_VTYPE_SYMBOL:
|
|
hash = pic_sym(val);
|
|
break;
|
|
case PIC_VTYPE_FLOAT:
|
|
u.f = pic_float(val);
|
|
hash = u.i;
|
|
break;
|
|
case PIC_VTYPE_INT:
|
|
hash = pic_int(val);
|
|
break;
|
|
case PIC_VTYPE_HEAP:
|
|
hash = (int)(intptr_t)pic_ptr(val);
|
|
break;
|
|
}
|
|
|
|
return hash + vtype;
|
|
}
|
|
|
|
static int
|
|
xh_value_equal(const void *key1, const void *key2, void *pic)
|
|
{
|
|
return pic_equal_p(pic, *(pic_value *)key1, *(pic_value *)key2);
|
|
}
|
|
|
|
static void
|
|
xh_init_value(pic_state *pic, xhash *x)
|
|
{
|
|
xh_init_(x, sizeof(pic_value), sizeof(pic_value), xh_value_hash, xh_value_equal, pic);
|
|
}
|
|
|
|
static inline xh_entry *
|
|
xh_get_value(xhash *x, pic_value key)
|
|
{
|
|
return xh_get_(x, &key);
|
|
}
|
|
|
|
static inline xh_entry *
|
|
xh_put_value(xhash *x, pic_value key, void *val)
|
|
{
|
|
return xh_put_(x, &key, val);
|
|
}
|
|
|
|
static inline void
|
|
xh_del_value(xhash *x, pic_value key)
|
|
{
|
|
xh_del_(x, &key);
|
|
}
|
|
|
|
struct pic_dict *
|
|
pic_make_dict(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
|
|
dict = (struct pic_dict *)pic_obj_alloc(pic, sizeof(struct pic_dict), PIC_TT_DICT);
|
|
xh_init_value(pic, &dict->hash);
|
|
|
|
return dict;
|
|
}
|
|
|
|
pic_value
|
|
pic_dict_ref(pic_state *pic, struct pic_dict *dict, pic_value key)
|
|
{
|
|
xh_entry *e;
|
|
|
|
e = xh_get_value(&dict->hash, key);
|
|
if (! e) {
|
|
pic_errorf(pic, "element not found for a key: ~s", key);
|
|
}
|
|
return xh_val(e, pic_value);
|
|
}
|
|
|
|
void
|
|
pic_dict_set(pic_state *pic, struct pic_dict *dict, pic_value key, pic_value val)
|
|
{
|
|
UNUSED(pic);
|
|
|
|
xh_put_value(&dict->hash, key, &val);
|
|
}
|
|
|
|
size_t
|
|
pic_dict_size(pic_state *pic, struct pic_dict *dict)
|
|
{
|
|
UNUSED(pic);
|
|
|
|
return dict->hash.count;
|
|
}
|
|
|
|
bool
|
|
pic_dict_has(pic_state *pic, struct pic_dict *dict, pic_value key)
|
|
{
|
|
UNUSED(pic);
|
|
|
|
return xh_get_value(&dict->hash, key) != NULL;
|
|
}
|
|
|
|
void
|
|
pic_dict_del(pic_state *pic, struct pic_dict *dict, pic_value key)
|
|
{
|
|
if (xh_get_value(&dict->hash, key) == NULL) {
|
|
pic_errorf(pic, "no slot named ~s found in dictionary", key);
|
|
}
|
|
|
|
xh_del_value(&dict->hash, key);
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_make_dictionary(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
|
|
pic_get_args(pic, "");
|
|
|
|
dict = pic_make_dict(pic);
|
|
|
|
return pic_obj_value(dict);
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_dictionary(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
pic_value *argv;
|
|
int argc, i;
|
|
|
|
pic_get_args(pic, "*", &argc, &argv);
|
|
|
|
dict = pic_make_dict(pic);
|
|
|
|
for (i = 0; i < argc; i += 2) {
|
|
pic_dict_set(pic, dict, argv[i], argv[i+1]);
|
|
}
|
|
|
|
return pic_obj_value(dict);
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_dictionary_p(pic_state *pic)
|
|
{
|
|
pic_value obj;
|
|
|
|
pic_get_args(pic, "o", &obj);
|
|
|
|
return pic_bool_value(pic_dict_p(obj));
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_dictionary_ref(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
pic_value key;
|
|
|
|
pic_get_args(pic, "do", &dict, &key);
|
|
|
|
if (pic_dict_has(pic, dict, key)) {
|
|
return pic_values2(pic, pic_dict_ref(pic, dict, key), pic_true_value());
|
|
} else {
|
|
return pic_values2(pic, pic_none_value(), pic_false_value());
|
|
}
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_dictionary_set(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
pic_value key, val;
|
|
|
|
pic_get_args(pic, "doo", &dict, &key, &val);
|
|
|
|
pic_dict_set(pic, dict, key, val);
|
|
|
|
return pic_none_value();
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_dictionary_del(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
pic_value key;
|
|
|
|
pic_get_args(pic, "do", &dict, &key);
|
|
|
|
pic_dict_del(pic, dict, key);
|
|
|
|
return pic_none_value();
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_dictionary_size(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
|
|
pic_get_args(pic, "d", &dict);
|
|
|
|
return pic_size_value(pic_dict_size(pic, dict));
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_dictionary_to_alist(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
pic_value item, alist = pic_nil_value();
|
|
xh_entry *it;
|
|
|
|
pic_get_args(pic, "d", &dict);
|
|
|
|
for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) {
|
|
item = pic_cons(pic, xh_key(it, pic_value), xh_val(it, pic_value));
|
|
pic_push(pic, item, alist);
|
|
}
|
|
|
|
return pic_reverse(pic, alist);
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_alist_to_dictionary(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
pic_value alist, e;
|
|
|
|
pic_get_args(pic, "o", &alist);
|
|
|
|
dict = pic_make_dict(pic);
|
|
|
|
pic_for_each (e, pic_reverse(pic, alist)) {
|
|
pic_dict_set(pic, dict, pic_car(pic, e), pic_cdr(pic, e));
|
|
}
|
|
|
|
return pic_obj_value(dict);
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_dictionary_to_plist(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
pic_value plist = pic_nil_value();
|
|
xh_entry *it;
|
|
|
|
pic_get_args(pic, "d", &dict);
|
|
|
|
for (it = xh_begin(&dict->hash); it != NULL; it = xh_next(it)) {
|
|
pic_push(pic, xh_key(it, pic_value), plist);
|
|
pic_push(pic, xh_val(it, pic_value), plist);
|
|
}
|
|
|
|
return pic_reverse(pic, plist);
|
|
}
|
|
|
|
static pic_value
|
|
pic_dict_plist_to_dictionary(pic_state *pic)
|
|
{
|
|
struct pic_dict *dict;
|
|
pic_value plist, e;
|
|
|
|
pic_get_args(pic, "o", &plist);
|
|
|
|
dict = pic_make_dict(pic);
|
|
|
|
for (e = pic_reverse(pic, plist); ! pic_nil_p(e); e = pic_cddr(pic, e)) {
|
|
pic_dict_set(pic, dict, pic_cadr(pic, e), pic_car(pic, e));
|
|
}
|
|
|
|
return pic_obj_value(dict);
|
|
}
|
|
|
|
void
|
|
pic_init_dict(pic_state *pic)
|
|
{
|
|
pic_defun(pic, "make-dictionary", pic_dict_make_dictionary);
|
|
pic_defun(pic, "dictionary?", pic_dict_dictionary_p);
|
|
pic_defun(pic, "dictionary", pic_dict_dictionary);
|
|
pic_defun(pic, "dictionary-ref", pic_dict_dictionary_ref);
|
|
pic_defun(pic, "dictionary-set!", pic_dict_dictionary_set);
|
|
pic_defun(pic, "dictionary-delete!", pic_dict_dictionary_del);
|
|
pic_defun(pic, "dictionary-size", pic_dict_dictionary_size);
|
|
pic_defun(pic, "dictionary->alist", pic_dict_dictionary_to_alist);
|
|
pic_defun(pic, "alist->dictionary", pic_dict_alist_to_dictionary);
|
|
pic_defun(pic, "dictionary->plist", pic_dict_dictionary_to_plist);
|
|
pic_defun(pic, "plist->dictionary", pic_dict_plist_to_dictionary);
|
|
}
|