1
/* This implements a container of static lexical information for
2
* NQP (will also be used by Rakudo). It differs from Parrot's
3
* LexInfo in that it provides support for static lexical values
4
* that get set into each created lexpad by default. It will also
5
* enable indexed lookups and, some day, may also allow for native
6
* values to be stored too. */
14
/* The static (not closure cloned) sub that this is lexpad is used for. */
15
ATTR PMC *static_code;
17
/* Hash mapping a name to the register that always holds its
19
ATTR PMC *name_to_register_map;
21
/* Hash mapping names to static values. This is the authoritative
22
* source of these, but we always build a more quickly usable
23
* cache in the next two attributes. */
24
ATTR PMC *static_values;
26
/* Integer array of slots that we always want to pre-initialize
27
* with static values; built from the static_values hash. */
28
ATTR PMC *static_slots_cache;
30
/* Matching PMC array of the values to pre-init with; built from
31
* the static_values hash. */
32
ATTR PMC *static_values_cache;
35
SELF.init_pmc(PMCNULL);
38
VTABLE void init_pmc(PMC *sub) {
39
/* Set up the lex info storage. */
40
PMC *name_to_register_map = Parrot_pmc_new(interp, enum_class_Hash);
41
VTABLE_init_int(interp, name_to_register_map, (INTVAL)enum_type_INTVAL);
42
SET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
45
SET_ATTR_static_code(INTERP, SELF, sub);
47
/* Need custom mark. */
48
PObj_custom_mark_SET(SELF);
52
PMC *name_to_register_map, *static_values;
53
PMC *static_slots_cache, *static_values_cache;
54
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
55
Parrot_gc_mark_PMC_alive(INTERP, name_to_register_map);
56
GET_ATTR_static_values(INTERP, SELF, static_values);
57
Parrot_gc_mark_PMC_alive(INTERP, static_values);
58
GET_ATTR_static_slots_cache(INTERP, SELF, static_slots_cache);
59
Parrot_gc_mark_PMC_alive(INTERP, static_slots_cache);
60
GET_ATTR_static_values_cache(INTERP, SELF, static_values_cache);
61
Parrot_gc_mark_PMC_alive(INTERP, static_values_cache);
64
VTABLE INTVAL elements() {
65
PMC *name_to_register_map;
66
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
67
return VTABLE_elements(interp, name_to_register_map);
70
VTABLE INTVAL get_integer_keyed_str(STRING *key) {
71
PMC *name_to_register_map;
72
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
73
return VTABLE_get_integer_keyed_str(interp, name_to_register_map, key);
76
VTABLE INTVAL exists_keyed_str(STRING *key) {
77
PMC *name_to_register_map;
78
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
79
return VTABLE_exists_keyed_str(interp, name_to_register_map, key);
82
VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
83
PMC *name_to_register_map;
84
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
85
VTABLE_set_integer_keyed_str(interp, name_to_register_map, key, value);
88
VTABLE void visit(PMC *info) {
89
VISIT_PMC_ATTR(INTERP, info, SELF, NQPLexInfo, name_to_register_map);
90
VISIT_PMC_ATTR(INTERP, info, SELF, NQPLexInfo, static_code);
94
VTABLE void thaw(PMC *info) {
97
/* Need custom mark. */
98
PObj_custom_mark_SET(SELF);
101
VTABLE PMC *get_iter() {
102
PMC *name_to_register_map;
103
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
104
return VTABLE_get_iter(interp, name_to_register_map);
109
=item C<void declare_lex_preg(STRING *name, INTVAL preg)>
111
Declare a lexical variable that is an alias for a PMC register. The PIR
112
compiler calls this method in response to a ".lex STRING, PREG" directive.
118
METHOD declare_lex_preg(STRING *name, INTVAL preg) {
119
PMC *name_to_register_map;
120
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
121
VTABLE_set_integer_keyed_str(INTERP, name_to_register_map, name, preg);
124
METHOD set_static_lexpad_value(STRING *key, PMC *value) {
125
/* Stash static value in hash. */
127
GET_ATTR_static_values(INTERP, SELF, svs);
128
if (PMC_IS_NULL(svs)) {
129
svs = Parrot_pmc_new(interp, enum_class_Hash);
130
SET_ATTR_static_values(INTERP, SELF, svs);
132
VTABLE_set_pmc_keyed_str(interp, svs, key, value);
135
METHOD finish_static_lexpad() {
136
/* Build caches from the static lexpad. */
138
GET_ATTR_static_values(INTERP, SELF, svs);
139
if (PMC_IS_NULL(svs) || !VTABLE_elements(interp, svs)) {
140
/* No values; clear caches. */
141
SET_ATTR_static_slots_cache(INTERP, SELF, PMCNULL);
142
SET_ATTR_static_values_cache(INTERP, SELF, PMCNULL);
146
PMC *slots = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
147
PMC *values = Parrot_pmc_new(interp, enum_class_ResizablePMCArray);
148
PMC *iter = VTABLE_get_iter(interp, svs);
149
while (VTABLE_get_bool(interp, iter)) {
150
STRING *name = VTABLE_shift_string(interp, iter);
151
INTVAL slot = VTABLE_get_integer_keyed_str(interp, SELF, name);
152
PMC *value = VTABLE_get_pmc_keyed_str(interp, svs, name);
153
VTABLE_push_integer(interp, slots, slot >> 2);
154
VTABLE_push_pmc(interp, values, value);
156
SET_ATTR_static_slots_cache(INTERP, SELF, slots);
157
SET_ATTR_static_values_cache(INTERP, SELF, values);
161
METHOD get_static_code() {
163
GET_ATTR_static_code(INTERP, SELF, static_code);
164
RETURN (PMC *static_code);
169
=item C<PMC *inspect_str(STRING *what)>
171
Introspects this LexInfo structure. The only valid introspection key is
172
C<symbols>, which gets an array of the names of the symbols in this lexpad.
178
VTABLE PMC *inspect_str(STRING *what) {
179
if (STRING_equal(INTERP, what, CONST_STRING(INTERP, "symbols"))) {
180
PMC * const result = Parrot_pmc_new(INTERP, enum_class_ResizableStringArray);
181
PMC *name_to_register_map;
184
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
185
hash = (Hash *)VTABLE_get_pointer(interp, name_to_register_map);
187
parrot_hash_iterate(hash,
188
PARROT_ASSERT(_bucket->key);
189
VTABLE_push_string(INTERP, result, (STRING *)_bucket->key););
194
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
195
"Unknown introspection value '%S'", what);