picrin/lib/value.h

271 lines
5.3 KiB
C

/**
* See Copyright Notice in picrin.h
*/
#ifndef PICRIN_VALUE_H
#define PICRIN_VALUE_H
#if defined(__cplusplus)
extern "C" {
#endif
enum {
PIC_TYPE_INVALID = 1,
PIC_TYPE_FLOAT = 2,
PIC_TYPE_INT = 3,
PIC_TYPE_CHAR = 4,
PIC_TYPE_EOF = 5,
PIC_TYPE_UNDEF = 6,
PIC_TYPE_TRUE = 8,
PIC_TYPE_NIL = 7,
PIC_TYPE_FALSE = 9,
PIC_IVAL_END = 10,
/* -------------------- */
PIC_TYPE_SYMBOL = 16,
PIC_TYPE_STRING = 17,
PIC_TYPE_BLOB = 18,
PIC_TYPE_DATA = 19,
PIC_TYPE_PAIR = 20,
PIC_TYPE_VECTOR = 21,
PIC_TYPE_DICT = 22,
PIC_TYPE_RECORD = 23,
PIC_TYPE_ATTR = 24,
PIC_TYPE_IREP = 27,
PIC_TYPE_FRAME = 28,
PIC_TYPE_PROC_FUNC = 29,
PIC_TYPE_PROC_IREP = 30,
PIC_TYPE_MAX = 63
};
#if !PIC_NAN_BOXING
PIC_STATIC_INLINE void
make_value(struct value *v, int type)
{
static const struct value zero = { 0 };
*v = zero;
v->type = type;
}
PIC_STATIC_INLINE void
make_int_value(struct value *v, int i)
{
make_value(v, PIC_TYPE_INT);
v->u.i = i;
}
PIC_STATIC_INLINE void
make_float_value(struct value *v, double f)
{
make_value(v, PIC_TYPE_FLOAT);
v->u.f = f;
}
PIC_STATIC_INLINE struct value
make_char_value(struct value *v, char c)
{
make_value(v, PIC_TYPE_CHAR);
v->u.c = c;
}
PIC_STATIC_INLINE void
make_obj_value(struct value *v, void *p, int type)
{
make_value(v, type);
v->u.p = p;
}
PIC_STATIC_INLINE int
value_type(struct value *v)
{
return (int)(v->type);
}
PIC_STATIC_INLINE int
value_int(struct value *v)
{
return v->u.i;
}
PIC_STATIC_INLINE double
value_float(struct value *v)
{
return v->u.f;
}
PIC_STATIC_INLINE char
value_char(struct value *v)
{
return v->u.c;
}
PIC_STATIC_INLINE void *
value_ptr(struct value *v)
{
return v->u.p;
}
PIC_STATIC_INLINE bool
value_eq_p(struct value *x, struct value *y)
{
return memcmp(x, y, sizeof(struct value)) == 0;
}
PIC_STATIC_INLINE bool
value_eqv_p(struct value *x, struct value *y)
{
return memcmp(x, y, sizeof(struct value)) == 0;
}
#else /* NAN_BOXING */
/**
* value representation by nan-boxing:
* float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
* ptr : 111111111111TTTT TTPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP
* int : 111111111111TTTT TT00000000000000 IIIIIIIIIIIIIIII IIIIIIIIIIIIIIII
* char : 111111111111TTTT TT00000000000000 CCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCC
*/
PIC_STATIC_INLINE void
make_value(struct value *v, int type)
{
v->v = 0xfff0000000000000ul | ((uint64_t)(type) << 46);
}
PIC_STATIC_INLINE void
make_int_value(struct value *v, int i)
{
make_value(v, PIC_TYPE_INT);
v->v |= (unsigned)i;
}
PIC_STATIC_INLINE void
make_float_value(struct value *v, double f)
{
if (f != f) {
v->v = 0x7ff8000000000000ul;
} else {
union { double f; uint64_t i; } u;
u.f = f;
v->v = u.i;
}
}
PIC_STATIC_INLINE void
make_char_value(struct value *v, char c)
{
make_value(v, PIC_TYPE_CHAR);
v->v |= (unsigned char)c;
}
PIC_STATIC_INLINE void
make_obj_value(struct value *v, void *ptr, int type)
{
make_value(v, type);
v->v |= 0x3ffffffffffful & ((uint64_t)ptr >> 2);
}
PIC_STATIC_INLINE int
value_type(struct value *v)
{
return 0xfff0000000000000ul >= v->v ? PIC_TYPE_FLOAT : ((v->v >> 46) & 0x3f);
}
PIC_STATIC_INLINE int
value_int(struct value *v)
{
union { int i; unsigned u; } u;
u.u = v->v & 0xfffffffful;
return u.i;
}
PIC_STATIC_INLINE double
value_float(struct value *v)
{
union { double f; uint64_t i; } u;
u.i = v->v;
return u.f;
}
PIC_STATIC_INLINE char
value_char(struct value *v)
{
return v->v & 0xfffffffful;
}
PIC_STATIC_INLINE void *
value_ptr(struct value *v)
{
return (void *)((0x3ffffffffffful & v->v) << 2);
}
PIC_STATIC_INLINE bool
value_eq_p(struct value *x, struct value *y)
{
return x->v == y->v;
}
PIC_STATIC_INLINE bool
value_eqv_p(struct value *x, struct value *y)
{
return x->v == y->v;
}
#endif /* NAN_BOXING end */
#define DEFPRED(name, type) \
PIC_STATIC_INLINE bool \
value_##name##_p(struct value *v) { \
return value_type(v) == type; \
}
DEFPRED(invalid, PIC_TYPE_INVALID)
DEFPRED(float, PIC_TYPE_FLOAT)
DEFPRED(int, PIC_TYPE_INT)
DEFPRED(char, PIC_TYPE_CHAR)
DEFPRED(eof, PIC_TYPE_EOF)
DEFPRED(undef, PIC_TYPE_UNDEF)
DEFPRED(true, PIC_TYPE_TRUE)
DEFPRED(nil, PIC_TYPE_NIL)
DEFPRED(false, PIC_TYPE_FALSE)
DEFPRED(str, PIC_TYPE_STRING)
DEFPRED(vec, PIC_TYPE_VECTOR)
DEFPRED(blob, PIC_TYPE_BLOB)
DEFPRED(dict, PIC_TYPE_DICT)
DEFPRED(attr, PIC_TYPE_ATTR)
DEFPRED(rec, PIC_TYPE_RECORD)
DEFPRED(sym, PIC_TYPE_SYMBOL)
DEFPRED(pair, PIC_TYPE_PAIR)
DEFPRED(proc_func, PIC_TYPE_PROC_FUNC)
DEFPRED(proc_irep, PIC_TYPE_PROC_IREP)
DEFPRED(irep, PIC_TYPE_IREP)
DEFPRED(data, PIC_TYPE_DATA)
#undef DEFPRED
PIC_STATIC_INLINE bool
value_obj_p(struct value *v)
{
return value_type(v) > PIC_IVAL_END;
}
void *pic_ptr(pic_state *, pic_value);
int pic_type(pic_state *, pic_value);
pic_value pic_invalid_value(pic_state *);
pic_value pic_obj_value(pic_state *, void *, int);
bool pic_invalid_p(pic_state *, pic_value);
bool pic_attr_p(pic_state *, pic_value);
bool pic_rec_p(pic_state *, pic_value);
bool pic_irep_p(pic_state *, pic_value);
bool pic_proc_func_p(pic_state *, pic_value);
bool pic_proc_irep_p(pic_state *, pic_value);
bool pic_obj_p(pic_state *, pic_value);
#if defined(__cplusplus)
}
#endif
#endif