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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
/*
* Copyright (C) 2020-2021 Jo-Philipp Wich <jo@mein.io>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __LIB_H_
#define __LIB_H_
#include "vm.h"
#include "lexer.h"
#include "object.h"
typedef struct {
const char *name;
uc_cfn_ptr func;
} uc_cfunction_list;
typedef struct {
/* value operations */
struct {
uc_prototype *(*proto)(uc_prototype *);
uc_cfunction *(*cfunc)(const char *, uc_cfn_ptr);
json_object *(*dbl)(double);
uc_regexp *(*regexp)(const char *, bool, bool, bool, char **);
uc_ressource *(*ressource)(json_object *, uc_ressource_type *, void *);
enum json_type (*tonumber)(json_object *, int64_t *, double *);
} value;
/* ressource operations */
struct {
uc_ressource_type *(*define)(const char *, uc_prototype *, void (*)(void *));
uc_ressource *(*create)(json_object *, uc_ressource_type *, void *);
void **(*data)(json_object *, const char *);
uc_prototype *(*proto)(json_object *);
} ressource;
/* VM operations */
struct {
uc_exception_type_t (*call)(uc_vm *, bool, size_t);
json_object *(*peek)(uc_vm *, size_t);
json_object *(*pop)(uc_vm *);
void (*push)(uc_vm *, json_object *);
void (*raise)(uc_vm *, uc_exception_type_t, const char *, ...);
} vm;
} uc_ops;
extern const uc_ops uc;
void uc_lib_init(uc_prototype *scope);
void format_source_context(char **msg, size_t *msglen, uc_source *src, size_t off, bool compact);
void format_error_context(char **msg, size_t *msglen, uc_source *src, json_object *stacktrace, size_t off);
/* vm helper */
static inline void *
_uc_get_self(const uc_ops *ops, uc_vm *vm, const char *expected_type)
{
return ops->ressource.data(vm->callframes.entries[vm->callframes.count - 1].ctx, expected_type);
}
#define uc_get_self(...) _uc_get_self(ops, vm, __VA_ARGS__)
static inline json_object *
_uc_get_arg(const uc_ops *ops, uc_vm *vm, size_t nargs, size_t n)
{
if (n >= nargs)
return NULL;
return ops->vm.peek(vm, nargs - n - 1);
}
#define uc_get_arg(...) _uc_get_arg(ops, vm, nargs, __VA_ARGS__)
#define uc_call(nargs) ops->vm.call(vm, false, nargs)
#define uc_push_val(val) ops->vm.push(vm, val)
#define uc_pop_val() ops->vm.pop(vm)
/* value helper */
static inline json_object *
_uc_alloc_proto(const uc_ops *ops, uc_prototype *parent)
{
return ops->value.proto(parent)->header.jso;
}
static inline json_object *
_uc_alloc_cfunc(const uc_ops *ops, const char *name, uc_cfn_ptr fptr)
{
return ops->value.cfunc(name, fptr)->header.jso;
}
static inline json_object *
_uc_alloc_double(const uc_ops *ops, double dbl)
{
return ops->value.dbl(dbl);
}
static inline json_object *
_uc_alloc_regexp(const uc_ops *ops, const char *pattern, bool global, bool icase, bool newline, char **errp)
{
uc_regexp *re = ops->value.regexp(pattern, global, icase, newline, errp);
return re ? re->header.jso : NULL;
}
static inline json_object *
_uc_alloc_ressource(const uc_ops *ops, uc_ressource_type *type, void *data)
{
uc_ressource *res = ops->value.ressource(xjs_new_object(), type, data);
return res ? res->header.jso : NULL;
}
#define uc_alloc_proto(...) _uc_alloc_proto(ops, __VA_ARGS__)
#define uc_alloc_cfunc(...) _uc_alloc_cfunc(ops, __VA_ARGS__)
#define uc_alloc_double(...) _uc_alloc_double(ops, __VA_ARGS__)
#define uc_alloc_regexp(...) _uc_alloc_regexp(ops, __VA_ARGS__)
#define uc_alloc_ressource(...) _uc_alloc_ressource(ops, __VA_ARGS__)
static inline json_type
_uc_to_number(const uc_ops *ops, json_object *v, int64_t *n, double *d)
{
return ops->value.tonumber(v, n, d);
}
static inline double
_uc_to_double(const uc_ops *ops, json_object *v)
{
int64_t n;
double d;
return (ops->value.tonumber(v, &n, &d) == json_type_double) ? d : (double)n;
}
static inline int64_t
_uc_to_int64(const uc_ops *ops, json_object *v)
{
int64_t n;
double d;
return (ops->value.tonumber(v, &n, &d) == json_type_double) ? (int64_t)d : n;
}
#define uc_to_number(...) _uc_to_number(ops, __VA_ARGS__)
#define uc_to_double(...) _uc_to_double(ops, __VA_ARGS__)
#define uc_to_int64(...) _uc_to_int64(ops, __VA_ARGS__)
/* ressource type helper */
static inline uc_ressource_type *
_uc_declare_type(const uc_ops *ops, const char *name, const uc_cfunction_list *list, size_t len, void (*freefn)(void *))
{
uc_prototype *proto = ops->value.proto(NULL);
while (len-- > 0)
json_object_object_add(proto->header.jso, list[len].name,
_uc_alloc_cfunc(ops, list[len].name, list[len].func));
return ops->ressource.define(name, proto, freefn);
}
#define uc_declare_type(name, functions, freefn) \
_uc_declare_type(ops, name, functions, ARRAY_SIZE(functions), freefn)
/* prototype helper */
static inline bool
uc_add_proto_val(uc_prototype *proto, const char *key, json_object *value)
{
if (!proto)
return false;
return json_object_object_add(proto->header.jso, key, value);
}
static inline void
_uc_add_proto_functions(const uc_ops *ops, uc_prototype *proto, const uc_cfunction_list *list, size_t len)
{
while (len-- > 0)
json_object_object_add(proto->header.jso, list[len].name,
_uc_alloc_cfunc(ops, list[len].name, list[len].func));
}
#define uc_add_proto_functions(proto, functions) \
_uc_add_proto_functions(ops, proto, functions, ARRAY_SIZE(functions))
#endif /* __LIB_H_ */
|