picrin/lib/object.h

289 lines
7.1 KiB
C
Raw Normal View History

2016-02-10 07:50:39 -05:00
/**
* See Copyright Notice in picrin.h
*/
2016-02-18 10:03:34 -05:00
#ifndef PICRIN_OBJECT_H
#define PICRIN_OBJECT_H
2016-02-10 07:50:39 -05:00
#if defined(__cplusplus)
extern "C" {
#endif
2017-03-28 10:09:40 -04:00
#include "khash.h"
2017-04-11 13:54:03 -04:00
#define OBJECT_HEADER \
2017-03-28 10:09:40 -04:00
unsigned char tt;
2017-04-09 06:14:02 -04:00
2017-04-11 13:54:03 -04:00
#define TYPE_MASK 0x7f
#define GC_MARK 0x80
2016-02-18 11:05:28 -05:00
2016-02-21 06:32:00 -05:00
struct object; /* defined in gc.c */
2016-02-20 02:33:51 -05:00
2016-02-21 06:32:00 -05:00
struct basic {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
};
2017-04-04 01:54:58 -04:00
struct symbol {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2017-04-04 01:54:58 -04:00
struct string *str;
2016-02-19 05:08:45 -05:00
};
2016-02-18 12:29:40 -05:00
2016-02-21 06:32:00 -05:00
struct pair {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2016-02-18 12:29:40 -05:00
pic_value car;
pic_value cdr;
};
2016-02-21 06:32:00 -05:00
struct blob {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2016-02-18 10:20:15 -05:00
unsigned char *data;
int len;
};
2016-02-21 06:32:00 -05:00
struct string {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2016-02-21 06:32:00 -05:00
struct rope *rope;
2016-02-18 10:14:50 -05:00
};
2017-04-04 01:54:58 -04:00
KHASH_DECLARE(dict, struct symbol *, pic_value)
2017-03-28 10:09:40 -04:00
2016-02-21 06:32:00 -05:00
struct dict {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2016-02-18 10:40:35 -05:00
khash_t(dict) hash;
};
2017-03-28 10:09:40 -04:00
KHASH_DECLARE(weak, struct object *, pic_value)
2016-02-21 06:32:00 -05:00
struct weak {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2016-02-10 07:50:39 -05:00
khash_t(weak) hash;
2016-02-21 06:32:00 -05:00
struct weak *prev; /* for GC */
2016-02-10 07:50:39 -05:00
};
2016-02-21 06:32:00 -05:00
struct vector {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2016-02-19 05:08:45 -05:00
pic_value *data;
int len;
};
2016-02-18 10:50:13 -05:00
2016-02-21 06:32:00 -05:00
struct data {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2016-02-18 10:50:13 -05:00
const pic_data_type *type;
void *data;
};
struct record {
OBJECT_HEADER
2017-04-09 04:34:56 -04:00
struct symbol *type;
pic_value datum;
};
2017-04-14 10:40:07 -04:00
enum {
OP_HALT = 0x00, /* 0x00 OP_HALT */
OP_CALL = 0x01, /* 0x01 0x** OP_CALL argc */
OP_PROC = 0x02, /* 0x02 0x** 0x** OP_PROC dest irep */
OP_LOAD = 0x03, /* 0x03 0x** 0x** OP_LOAD dest i */
OP_LREF = 0x04, /* 0x04 0x** 0x** 0x** OP_LREF dest n i */
OP_LSET = 0x05, /* 0x05 0x** 0x** 0x** OP_LSET src n i */
OP_GREF = 0x06, /* 0x06 0x** 0x** OP_GREF dest i */
OP_GSET = 0x07, /* 0x07 0x** 0x** OP_GSET src i */
OP_COND = 0x08, /* 0x08 0x** 0x** 0x** OP_COND c offset */
OP_LOADT = 0x09, /* 0x09 0x** OP_LOADT dest */
OP_LOADF = 0x0A, /* 0x0A 0x** OP_LOADF dest */
OP_LOADN = 0x0B, /* 0x0B 0x** OP_LOADN dest */
OP_LOADU = 0x0C, /* 0x0C 0x** OP_LOADU dest */
2017-04-15 02:45:28 -04:00
OP_LOADI = 0x0D /* 0x0D 0x** 0x** OP_LOADI dest i */
2017-04-14 10:40:07 -04:00
};
typedef unsigned char code_t;
#define IREP_VARG 1
#define IREP_CODE_STATIC 2
2017-03-30 10:29:08 -04:00
struct irep {
OBJECT_HEADER
2017-04-14 10:40:07 -04:00
unsigned char argc;
unsigned char flags;
unsigned char frame_size;
unsigned char irepc, objc;
2017-04-22 20:16:40 -04:00
size_t codec;
2017-03-30 10:29:08 -04:00
struct irep **irep;
2017-04-14 10:40:07 -04:00
pic_value *obj;
const code_t *code;
2017-03-30 10:29:08 -04:00
};
2017-04-09 02:49:04 -04:00
struct frame {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2017-04-14 10:40:07 -04:00
unsigned char regc;
2017-04-09 02:49:04 -04:00
pic_value *regs;
struct frame *up;
2016-02-18 10:56:56 -05:00
};
2016-02-21 06:32:00 -05:00
struct proc {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2016-02-18 10:56:56 -05:00
union {
pic_func_t func;
struct irep *irep;
2016-02-18 10:56:56 -05:00
} u;
2017-04-14 10:40:07 -04:00
struct frame *env;
2016-02-18 10:56:56 -05:00
};
2017-03-28 10:09:40 -04:00
enum {
FILE_READ = 01,
FILE_WRITE = 02,
FILE_UNBUF = 04,
FILE_EOF = 010,
FILE_ERR = 020,
FILE_LNBUF = 040
};
2016-02-21 06:32:00 -05:00
struct port {
2016-02-23 12:36:09 -05:00
OBJECT_HEADER
2017-03-28 10:09:40 -04:00
struct file {
/* buffer */
char buf[1]; /* fallback buffer */
long cnt; /* characters left */
char *ptr; /* next character position */
char *base; /* location of the buffer */
/* operators */
2017-03-28 18:11:27 -04:00
void *cookie;
const pic_port_type *vtable;
2017-03-28 10:09:40 -04:00
int flag; /* mode of the file access */
} file;
2016-02-18 15:58:34 -05:00
};
struct error {
OBJECT_HEADER
2017-04-04 01:54:58 -04:00
struct symbol *type;
struct string *msg;
pic_value irrs;
};
2016-02-23 08:53:20 -05:00
#define TYPENAME_int "integer"
#define TYPENAME_blob "bytevector"
#define TYPENAME_char "character"
#define TYPENAME_sym "symbol"
#define TYPENAME_error "error"
#define TYPENAME_proc "procedure"
#define TYPENAME_str "string"
#define TYPENAME_vec "vector"
#define TYPE_CHECK(pic, v, type) do { \
if (! pic_##type##_p(pic, v)) \
pic_error(pic, TYPENAME_##type " required", 1, v); \
} while (0)
2016-02-19 07:56:45 -05:00
#define VALID_INDEX(pic, len, i) do { \
2016-02-22 14:03:42 -05:00
if (i < 0 || len <= i) pic_error(pic, "index out of range", 1, pic_int_value(pic, i)); \
2016-02-19 07:56:45 -05:00
} while (0)
#define VALID_RANGE(pic, len, s, e) do { \
2016-02-22 14:03:42 -05:00
if (s < 0 || len < s) pic_error(pic, "invalid start index", 1, pic_int_value(pic, s)); \
if (e < s || len < e) pic_error(pic, "invalid end index", 1, pic_int_value(pic, e)); \
2016-02-19 07:56:45 -05:00
} while (0)
2016-02-22 14:03:42 -05:00
#define VALID_ATRANGE(pic, tolen, at, fromlen, s, e) do { \
VALID_INDEX(pic, tolen, at); \
VALID_RANGE(pic, fromlen, s, e); \
if (tolen - at < e - s) pic_error(pic, "invalid range", 0); \
2016-02-19 07:56:45 -05:00
} while (0)
2017-04-09 06:14:02 -04:00
PIC_STATIC_INLINE int
obj_type(pic_state *PIC_UNUSED(pic), void *ptr)
{
2017-04-11 13:54:03 -04:00
return ((struct basic *)ptr)->tt & TYPE_MASK;
2017-04-09 06:14:02 -04:00
}
#if !PIC_NAN_BOXING
PIC_STATIC_INLINE struct object *
obj_ptr(pic_state *PIC_UNUSED(pic), pic_value v)
{
return (struct object *)(v.u.data);
}
PIC_STATIC_INLINE bool
obj_p(pic_state *PIC_UNUSED(pic), pic_value v)
{
return v.type > PIC_IVAL_END;
}
PIC_STATIC_INLINE pic_value
obj_value(pic_state *PIC_UNUSED(pic), void *ptr)
{
2017-04-09 06:14:02 -04:00
pic_value v = pic_make_value(obj_type(pic, ptr));
v.u.data = ptr;
return v;
}
#else /* NAN_BOXING */
PIC_STATIC_INLINE struct object *
obj_ptr(pic_state *PIC_UNUSED(pic), pic_value v)
{
return (struct object *)((0x3ffffffffffful & v.v) << 2);
}
PIC_STATIC_INLINE bool
obj_p(pic_state *PIC_UNUSED(pic), pic_value v)
{
return v.v > ((0x3ffC0ul + (0x3f & PIC_IVAL_END)) << 46);
}
PIC_STATIC_INLINE pic_value
obj_value(pic_state *PIC_UNUSED(pic), void *ptr)
{
2017-04-09 06:14:02 -04:00
pic_value v = pic_make_value(obj_type(pic, ptr));
v.v |= 0x3ffffffffffful & ((uint64_t)ptr >> 2);
return v;
}
#endif /* NAN_BOXING */
#define DEFPTR(name,type) \
PIC_STATIC_INLINE type * \
name##_ptr(pic_state *PIC_UNUSED(pic), pic_value o) { \
assert(pic_##name##_p(pic,o)); \
return (type *) obj_ptr(pic, o); \
2017-03-28 18:11:27 -04:00
}
2017-04-01 11:12:24 -04:00
#define pic_data_p(pic,o) (pic_data_p(pic,o,NULL))
#define pic_port_p(pic,o) (pic_port_p(pic,o,NULL))
2017-04-04 01:54:58 -04:00
DEFPTR(sym, struct symbol)
2017-04-01 11:12:24 -04:00
DEFPTR(str, struct string)
DEFPTR(blob, struct blob)
DEFPTR(pair, struct pair)
DEFPTR(vec, struct vector)
DEFPTR(dict, struct dict)
DEFPTR(weak, struct weak)
DEFPTR(data, struct data)
DEFPTR(proc, struct proc)
DEFPTR(port, struct port)
DEFPTR(error, struct error)
DEFPTR(rec, struct record)
DEFPTR(irep, struct irep)
#undef pic_data_p
#undef pic_port_p
2017-03-28 18:11:27 -04:00
2017-04-12 00:18:06 -04:00
struct object *pic_obj_alloc(pic_state *, int type);
2017-04-14 10:40:07 -04:00
struct object *pic_obj_alloc_unsafe(pic_state *, int type);
2017-03-28 18:11:27 -04:00
2017-04-14 10:40:07 -04:00
struct frame *pic_make_frame_unsafe(pic_state *, int n);
pic_value pic_make_proc_irep_unsafe(pic_state *, struct irep *, struct frame *);
pic_value pic_make_proc_func(pic_state *, pic_func_t);
2017-03-28 10:09:40 -04:00
pic_value pic_make_record(pic_state *, pic_value type, pic_value datum);
2017-04-04 01:54:58 -04:00
pic_value pic_record_type(pic_state *pic, pic_value record);
pic_value pic_record_datum(pic_state *pic, pic_value record);
2017-04-20 16:28:15 -04:00
pic_value pic_make_cont(pic_state *pic, pic_value k);
2017-04-15 05:59:41 -04:00
pic_value pic_make_error(pic_state *, const char *type, const char *msg, pic_value irrs);
2016-02-19 02:58:39 -05:00
2016-02-26 11:38:07 -05:00
struct rope *pic_rope_incref(struct rope *);
2016-02-21 06:32:00 -05:00
void pic_rope_decref(pic_state *, struct rope *);
2016-02-19 02:58:39 -05:00
2016-02-20 05:47:46 -05:00
2017-03-31 01:39:01 -04:00
void pic_warnf(pic_state *pic, const char *fmt, ...); /* deprecated */
2016-02-10 07:50:39 -05:00
#if defined(__cplusplus)
}
#endif
#endif