-
Notifications
You must be signed in to change notification settings - Fork 0
/
sexp.h
155 lines (132 loc) · 4.57 KB
/
sexp.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#ifndef CIAPOS_SEXP_H
#define CIAPOS_SEXP_H
#include <stdint.h>
#include <sys/types.h>
#include <assert.h>
#include "symbol.h"
#include "dict.h"
typedef ciapos_symbol tagged;
typedef struct ciapos_gc_header {
ciapos_symbol tag;
unsigned char mark;
struct ciapos_gc_header *next;
} ciapos_gc_header;
typedef int64_t ciapos_integer;
typedef double ciapos_real;
typedef struct ciapos_string {
ciapos_gc_header header;
size_t length;
char buffer[];
} ciapos_string;
typedef struct ciapos_opaque {
ciapos_gc_header header;
ciapos_symbol description;
size_t size;
uint8_t buffer[]; // follows 64-bit int, so should sufficiently aligned for whatever data is put here
} ciapos_opaque;
typedef struct ciapos_sexp {
ciapos_symbol tag;
uint32_t debug_info; // line/col/file info for sexps read from source code
union {
ciapos_symbol symbol;
ciapos_integer integer;
ciapos_real real;
ciapos_string *string;
struct ciapos_function *function;
ciapos_opaque *opaque;
struct ciapos_environment *environment;
struct ciapos_tuple *tuple;
};
} ciapos_sexp;
struct ciapos_vm;
typedef ciapos_sexp (*ciapos_function_evaluator)(
struct ciapos_vm *vm,
ciapos_sexp fbody,
ciapos_sexp env,
ciapos_sexp args);
typedef struct ciapos_function {
ciapos_gc_header header;
ciapos_function_evaluator evaluator;
ciapos_sexp fbody;
ciapos_sexp env;
} ciapos_function;
typedef struct ciapos_tuple {
ciapos_gc_header header;
size_t length;
ciapos_sexp buffer[];
} ciapos_tuple;
// TODO better hash
#define CIAPOS_DICT_HASH(a) (a)
#define CIAPOS_DICT_EQ(a, b) ((a) == (b))
CIAPOS_DICT(
ciapos_sym2sexp,
ciapos_symbol,
ciapos_sexp,
CIAPOS_DICT_HASH,
CIAPOS_DICT_EQ)
typedef struct ciapos_environment {
ciapos_gc_header header;
ciapos_sym2sexp bindings;
} ciapos_environment;
void ciapos_gc_deinit(ciapos_gc_header *obj);
static inline ciapos_sexp ciapos_mknil(void) {
return (ciapos_sexp) { .tag = CIAPOS_TAGNIL, .debug_info = 0 };
}
static inline ciapos_sexp ciapos_mksymbol(ciapos_symbol a) {
return (ciapos_sexp) { .tag = CIAPOS_TAGSYM, .debug_info = 0, .symbol = a };
}
static inline ciapos_sexp ciapos_mkinteger(ciapos_integer a) {
return (ciapos_sexp) { .tag = CIAPOS_TAGINT, .debug_info = 0, .integer = a };
}
static inline ciapos_sexp ciapos_mkreal(ciapos_real a) {
return (ciapos_sexp) { .tag = CIAPOS_TAGREAL, .debug_info = 0, .real = a };
}
ciapos_sexp ciapos_mkstring(ciapos_gc_header **heap, size_t len, char *buf);
ciapos_sexp ciapos_mkfunction(ciapos_gc_header **heap, ciapos_function_evaluator, ciapos_sexp fbody, ciapos_sexp env);
ciapos_sexp ciapos_mkopaque(ciapos_gc_header **heap, ciapos_symbol description, size_t len);
ciapos_sexp ciapos_mkenvironment(ciapos_gc_header **heap, size_t nbuckets);
ciapos_sexp ciapos_mktuple(ciapos_gc_header **heap, size_t len);
static inline ciapos_sexp ciapos_function_eval(ciapos_sexp function, struct ciapos_vm *vm, ciapos_sexp args) {
assert(function.tag == CIAPOS_TAGFN);
return function.function->evaluator(vm, function.function->fbody, function.function->env, args);
}
static inline void *ciapos_opaque_get(ciapos_sexp a) {
assert(a.tag == CIAPOS_TAGOPAQUE);
return a.opaque->buffer;
}
static inline int ciapos_environment_has(ciapos_sexp a, ciapos_symbol key) {
assert(a.tag == CIAPOS_TAGENV);
return ciapos_sym2sexp_has(&a.environment->bindings, key);
}
static inline ciapos_sexp ciapos_environment_get(ciapos_sexp a, ciapos_symbol key) {
assert(a.tag == CIAPOS_TAGENV);
return ciapos_sym2sexp_get(&a.environment->bindings, key);
}
static inline void ciapos_environment_put(ciapos_sexp a, ciapos_symbol key, ciapos_sexp val) {
assert(a.tag == CIAPOS_TAGENV);
ciapos_sym2sexp_put(&a.environment->bindings, key, val);
}
static inline ciapos_sexp ciapos_tuple_get(ciapos_sexp a, off_t idx) {
assert(a.tag >= CIAPOS_TAGTUP);
return a.tuple->buffer[idx];
}
static inline ciapos_sexp *ciapos_tuple_ref(ciapos_sexp a, off_t idx) {
assert(a.tag >= CIAPOS_TAGTUP);
return &a.tuple->buffer[idx];
}
static inline void ciapos_tuple_put(ciapos_sexp a, off_t idx, ciapos_sexp b) {
assert(a.tag >= CIAPOS_TAGTUP);
a.tuple->buffer[idx] = b;
}
static inline void ciapos_sexp_set_type(ciapos_sexp *sexp, ciapos_symbol type) {
assert(sexp->tag >= CIAPOS_TAGTUP);
sexp->tag = type;
sexp->tuple->header.tag = type;
}
#ifndef NDEBUG
void ciapos_sexp_debug(ciapos_symreg *registry, ciapos_sexp sexp);
#else
#define ciapos_sexp_debug(r, s)
#endif
#include "vm.h"
#endif