/
repr_registry.c
228 lines (211 loc) · 10.1 KB
/
repr_registry.c
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/* This is an implementation of a representation registry. It keeps track of
* all of the available representations, and is responsible for building them
* at startup. */
#define PARROT_IN_EXTENSION
#include "parrot/parrot.h"
#include "parrot/extend.h"
#include "sixmodelobject.h"
#include "reprs/KnowHOWREPR.h"
#include "reprs/P6opaque.h"
#include "reprs/P6int.h"
#include "reprs/P6num.h"
#include "reprs/P6str.h"
#include "reprs/HashAttrStore.h"
#include "reprs/Uninstantiable.h"
#include "repr_registry.h"
/* An array mapping representation IDs to function tables. */
static REPROps **repr_registry = NULL;
/* Number of representations registered so far. */
static INTVAL num_reprs = 0;
/* Hash mapping representation names to IDs. */
static PMC *repr_name_to_id_map = NULL;
/* Default REPR function handlers. */
PARROT_DOES_NOT_RETURN
static void die_no_attrs(PARROT_INTERP, STRING *repr_name) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"%Ss representation does not support attribute storage", repr_name);
}
static PMC * default_get_attribute_boxed(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint) {
die_no_attrs(interp, st->REPR->name);
}
static void default_get_attribute_native(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint, NativeValue *value) {
die_no_attrs(interp, st->REPR->name);
}
static void default_bind_attribute_boxed(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint, PMC *value) {
die_no_attrs(interp, st->REPR->name);
}
static void default_bind_attribute_native(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint, NativeValue *value) {
die_no_attrs(interp, st->REPR->name);
}
static INTVAL default_is_attribute_initialized(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint) {
die_no_attrs(interp, st->REPR->name);
}
static INTVAL default_hint_for(PARROT_INTERP, STable *st, PMC *class_handle, STRING *name) {
return NO_HINT;
}
static void default_set_int(PARROT_INTERP, STable *st, void *data, INTVAL value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"%Ss cannot box a native int", st->REPR->name);
}
static INTVAL default_get_int(PARROT_INTERP, STable *st, void *data) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"%Ss cannot unbox to a native int", st->REPR->name);
}
static void default_set_num(PARROT_INTERP, STable *st, void *data, FLOATVAL value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"%Ss cannot box a native num", st->REPR->name);
}
static FLOATVAL default_get_num(PARROT_INTERP, STable *st, void *data) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"%Ss cannot unbox to a native num", st->REPR->name);
}
static void default_set_str(PARROT_INTERP, STable *st, void *data, STRING *value) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"%Ss cannot box a native string", st->REPR->name);
}
static STRING * default_get_str(PARROT_INTERP, STable *st, void *data) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"%Ss cannot unbox to a native string", st->REPR->name);
}
static void * default_get_boxed_ref(PARROT_INTERP, STable *st, void *data, INTVAL repr_id) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"%Ss cannot box other types", st->REPR->name);
}
PARROT_DOES_NOT_RETURN
static void die_no_idx(PARROT_INTERP, STRING *repr_name) {
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
"%Ss representation does not support indexed storage", repr_name);
}
static void default_at_pos_native(PARROT_INTERP, STable *st, void *data, INTVAL index, NativeValue *value) {
die_no_idx(interp, st->REPR->name);
}
static PMC * default_at_pos_boxed(PARROT_INTERP, STable *st, void *data, INTVAL index) {
die_no_idx(interp, st->REPR->name);
}
static void default_bind_pos_native(PARROT_INTERP, STable *st, void *data, INTVAL index, NativeValue *value) {
die_no_idx(interp, st->REPR->name);
}
static void default_bind_pos_boxed(PARROT_INTERP, STable *st, void *data, INTVAL index, PMC *obj) {
die_no_idx(interp, st->REPR->name);
}
static INTVAL default_elems(PARROT_INTERP, STable *st, void *data) {
die_no_idx(interp, st->REPR->name);
}
static void default_push_boxed(PARROT_INTERP, STable *st, void *data, PMC *obj) {
die_no_idx(interp, st->REPR->name);
}
static PMC * default_pop_boxed(PARROT_INTERP, STable *st, void *data) {
die_no_idx(interp, st->REPR->name);
}
static void default_unshift_boxed(PARROT_INTERP, STable *st, void *data, PMC *obj) {
die_no_idx(interp, st->REPR->name);
}
static PMC * default_shift_boxed(PARROT_INTERP, STable *st, void *data) {
die_no_idx(interp, st->REPR->name);
}
static STable * default_get_elem_stable(PARROT_INTERP, STable *st) {
die_no_idx(interp, st->REPR->name);
}
/* Set default attribute functions on a REPR that lacks them. */
static void add_default_attr_funcs(PARROT_INTERP, REPROps *repr) {
repr->attr_funcs = mem_allocate_typed(REPROps_Attribute);
repr->attr_funcs->get_attribute_boxed = default_get_attribute_boxed;
repr->attr_funcs->get_attribute_native = default_get_attribute_native;
repr->attr_funcs->bind_attribute_boxed = default_bind_attribute_boxed;
repr->attr_funcs->bind_attribute_native = default_bind_attribute_native;
repr->attr_funcs->is_attribute_initialized = default_is_attribute_initialized;
repr->attr_funcs->hint_for = default_hint_for;
}
/* Set default boxing functions on a REPR that lacks them. */
static void add_default_box_funcs(PARROT_INTERP, REPROps *repr) {
repr->box_funcs = mem_allocate_typed(REPROps_Boxing);
repr->box_funcs->set_int = default_set_int;
repr->box_funcs->get_int = default_get_int;
repr->box_funcs->set_num = default_set_num;
repr->box_funcs->get_num = default_get_num;
repr->box_funcs->set_str = default_set_str;
repr->box_funcs->get_str = default_get_str;
repr->box_funcs->get_boxed_ref = default_get_boxed_ref;
}
/* Set default positional functions on a REPR that lacks them. */
static void add_default_pos_funcs(PARROT_INTERP, REPROps *repr) {
repr->pos_funcs = mem_allocate_typed(REPROps_Positional);
repr->pos_funcs->at_pos_native = default_at_pos_native;
repr->pos_funcs->at_pos_boxed = default_at_pos_boxed;
repr->pos_funcs->bind_pos_native = default_bind_pos_native;
repr->pos_funcs->bind_pos_boxed = default_bind_pos_boxed;
repr->pos_funcs->elems = default_elems;
repr->pos_funcs->push_boxed = default_push_boxed;
repr->pos_funcs->pop_boxed = default_pop_boxed;
repr->pos_funcs->unshift_boxed = default_unshift_boxed;
repr->pos_funcs->shift_boxed = default_shift_boxed;
repr->pos_funcs->get_elem_stable = default_get_elem_stable;
}
/* Registers a representation. It this is ever made public, it should first be
* made thread-safe. */
static void register_repr(PARROT_INTERP, STRING *name, REPROps *repr) {
INTVAL ID = num_reprs;
num_reprs++;
if (repr_registry)
repr_registry = (REPROps **)mem_sys_realloc(repr_registry, num_reprs * sizeof(REPROps *));
else
repr_registry = (REPROps **)mem_sys_allocate(num_reprs * sizeof(REPROps *));
repr_registry[ID] = repr;
VTABLE_set_integer_keyed_str(interp, repr_name_to_id_map, name, ID);
repr->ID = ID;
repr->name = name;
if (!repr->attr_funcs)
add_default_attr_funcs(interp, repr);
if (!repr->box_funcs)
add_default_box_funcs(interp, repr);
if (!repr->pos_funcs)
add_default_pos_funcs(interp, repr);
}
/* Dynamically registers a representation (that is, one defined outside of
* the 6model core). */
static INTVAL REPR_register_dynamic(PARROT_INTERP, STRING *name, REPROps * (*reg) (PARROT_INTERP, void *, void *)) {
REPROps *repr = reg(interp, wrap_object, create_stable);
register_repr(interp, name, repr);
return repr->ID;
}
/* Initializes the representations registry, building up all of the various
* representations. */
void REPR_initialize_registry(PARROT_INTERP) {
PMC *dyn_reg_func;
/* Allocate name to ID map, and anchor it with the GC. */
repr_name_to_id_map = Parrot_pmc_new(interp, enum_class_Hash);
Parrot_pmc_gc_register(interp, repr_name_to_id_map);
/* Add all core representations. */
register_repr(interp, Parrot_str_new_constant(interp, "KnowHOWREPR"),
KnowHOWREPR_initialize(interp));
register_repr(interp, Parrot_str_new_constant(interp, "P6opaque"),
P6opaque_initialize(interp));
register_repr(interp, Parrot_str_new_constant(interp, "P6int"),
P6int_initialize(interp));
register_repr(interp, Parrot_str_new_constant(interp, "P6num"),
P6num_initialize(interp));
register_repr(interp, Parrot_str_new_constant(interp, "P6str"),
P6str_initialize(interp));
register_repr(interp, Parrot_str_new_constant(interp, "HashAttrStore"),
HashAttrStore_initialize(interp));
register_repr(interp, Parrot_str_new_constant(interp, "Uninstantiable"),
Uninstantiable_initialize(interp));
/* Set up object for dynamically registering extra representations. */
dyn_reg_func = Parrot_pmc_new(interp, enum_class_Pointer);
VTABLE_set_pointer(interp, dyn_reg_func, REPR_register_dynamic);
VTABLE_set_pmc_keyed_str(interp, interp->root_namespace,
Parrot_str_new_constant(interp, "_REGISTER_REPR"), dyn_reg_func);
}
/* Get a representation's ID from its name. Note that the IDs may change so
* it's best not to store references to them in e.g. the bytecode stream. */
INTVAL REPR_name_to_id(PARROT_INTERP, STRING *name) {
return VTABLE_get_integer_keyed_str(interp, repr_name_to_id_map, name);
}
/* Gets a representation by ID. */
REPROps * REPR_get_by_id(PARROT_INTERP, INTVAL id) {
return repr_registry[id];
}
/* Gets a representation by name. */
REPROps * REPR_get_by_name(PARROT_INTERP, STRING *name) {
return repr_registry[VTABLE_get_integer_keyed_str(interp, repr_name_to_id_map, name)];
}