add user-defined data type API

This commit is contained in:
Yuichi Nishiwaki 2014-03-29 20:42:06 +09:00
parent 1813ba2d6f
commit d8c182bc69
7 changed files with 74 additions and 1 deletions

33
include/picrin/data.h Normal file
View File

@ -0,0 +1,33 @@
/**
* See Copyright Notice in picrin.h
*/
#ifndef PICRIN_DATA_H__
#define PICRIN_DATA_H__
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct {
const char *type_name;
void (*dtor)(pic_state *, void *);
} pic_data_type;
struct pic_data {
PIC_OBJECT_HEADER;
const pic_data_type *type;
xhash storage; /* const char * to pic_value table */
void *data;
};
#define pic_data_p(o) (pic_type(o) == PIC_TT_DATA)
#define pic_data_ptr(o) ((struct pic_data *)pic_ptr(o))
struct pic_data *pic_data_alloc(pic_state *, const pic_data_type *, void *);
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -114,7 +114,8 @@ enum pic_tt {
PIC_TT_SC,
PIC_TT_LIB,
PIC_TT_VAR,
PIC_TT_IREP
PIC_TT_IREP,
PIC_TT_DATA
};
#define PIC_OBJECT_HEADER \
@ -258,6 +259,8 @@ pic_type_repr(enum pic_tt tt)
return "var";
case PIC_TT_IREP:
return "irep";
case PIC_TT_DATA:
return "data";
}
return 0; /* logic flaw */
}

View File

@ -823,6 +823,7 @@ analyze_node(analyze_state *state, pic_value obj, bool tailpos)
case PIC_TT_LIB:
case PIC_TT_VAR:
case PIC_TT_IREP:
case PIC_TT_DATA:
pic_errorf(pic, "invalid expression given: ~s", obj);
}
UNREACHABLE();

15
src/data.c Normal file
View File

@ -0,0 +1,15 @@
#include "picrin.h"
#include "picrin/data.h"
struct pic_data *
pic_data_alloc(pic_state *pic, const pic_data_type *type, void *userdata)
{
struct pic_data *data;
data = (struct pic_data *)pic_obj_alloc(pic, sizeof(struct pic_data), PIC_TT_DATA);
data->type = type;
data->data = userdata;
xh_init_str(&data->storage, sizeof(pic_value));
return data;
}

View File

@ -18,6 +18,7 @@
#include "picrin/macro.h"
#include "picrin/lib.h"
#include "picrin/var.h"
#include "picrin/data.h"
#if GC_DEBUG
# include <string.h>
@ -485,6 +486,16 @@ gc_mark_object(pic_state *pic, struct pic_object *obj)
}
break;
}
case PIC_TT_DATA: {
struct pic_data *data = (struct pic_data *)obj;
xh_iter it;
xh_begin(&it, &data->storage);
while (xh_next(&it)) {
gc_mark(pic, xh_val(it.e, pic_value));
}
break;
}
case PIC_TT_NIL:
case PIC_TT_BOOL:
case PIC_TT_FLOAT:
@ -629,6 +640,12 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj)
pic_free(pic, irep->pool);
break;
}
case PIC_TT_DATA: {
struct pic_data *data = (struct pic_data *)obj;
data->type->dtor(pic, data->data);
xh_destroy(&data->storage);
break;
}
case PIC_TT_NIL:
case PIC_TT_BOOL:
case PIC_TT_FLOAT:

View File

@ -508,6 +508,7 @@ macroexpand_node(pic_state *pic, pic_value expr, struct pic_senv *senv)
case PIC_TT_LIB:
case PIC_TT_VAR:
case PIC_TT_IREP:
case PIC_TT_DATA:
pic_error(pic, "unexpected value type");
return pic_undef_value(); /* unreachable */
}

View File

@ -332,6 +332,9 @@ write_core(struct writer_control *p, pic_value obj)
case PIC_TT_IREP:
xfprintf(file, "#<irep %p>", pic_ptr(obj));
break;
case PIC_TT_DATA:
xfprintf(file, "#<data %p>", pic_ptr(obj));
break;
}
}