Skip to content

Commit d36a4cd

Browse files
committed
Stub in NQPLexInfo and NQPLexPad, which will eventually give static lexpad support.
1 parent ecaf0c5 commit d36a4cd

File tree

3 files changed

+281
-1
lines changed

3 files changed

+281
-1
lines changed

build/Makefile.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,8 @@ DYNOPS = $(OPS_DIR)/$(OPS)$(LOAD_EXT)
146146

147147
PMC_SOURCES = $(PMC_DIR)/stable.pmc $(PMC_DIR)/rakudoobject.pmc \
148148
$(PMC_DIR)/repr.pmc $(PMC_DIR)/dispatchersub.pmc \
149-
$(PMC_DIR)/nqpmultisig.pmc
149+
$(PMC_DIR)/nqpmultisig.pmc $(PMC_DIR)/nqplexinfo.pmc \
150+
$(PMC_DIR)/nqplexpad.pmc
150151

151152
OPS_SOURCE = nqp.ops
152153

src/pmc/nqplexinfo.pmc

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
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. */
7+
pmclass NQPLexInfo provides hash auto_attrs dynpmc group nqp {
8+
/* Hash mapping a name to the register that always holds its
9+
* value. */
10+
ATTR PMC *name_to_register_map;
11+
12+
/* Hash mapping names to static values. This is the authoritative
13+
* source of these, but we always build a more quickly usable
14+
* cache in the next two attributes. */
15+
ATTR PMC *static_values;
16+
17+
/* Integer array of slots that we always want to pre-initialize
18+
* with static values; built from the static_values hash. */
19+
ATTR PMC *static_slots_cache;
20+
21+
/* Matching PMC array of the values to pre-init with; built from
22+
* the static_values hash. */
23+
ATTR PMC *static_values_cache;
24+
25+
void class_init() {
26+
INTERP->vtables[entry]->flags |= VTABLE_IS_CONST_PMC_FLAG;
27+
}
28+
29+
VTABLE void init() {
30+
SELF.init_pmc(PMCNULL);
31+
}
32+
33+
VTABLE void init_pmc(PMC *sub) {
34+
/* Set up the lex info storage. */
35+
PMC *name_to_register_map = pmc_new(interp, enum_class_Hash);
36+
VTABLE_init_int(interp, name_to_register_map, (INTVAL)enum_type_INTVAL);
37+
SET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
38+
39+
/* Ensure we're constant. */
40+
PARROT_ASSERT(PObj_constant_TEST(SELF));
41+
42+
/* Need custom mark. */
43+
PObj_custom_mark_SET(SELF);
44+
}
45+
46+
VTABLE INTVAL get_integer_keyed_str(STRING *key) {
47+
PMC *name_to_register_map;
48+
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
49+
return VTABLE_get_integer_keyed_str(interp, name_to_register_map, key);
50+
}
51+
52+
VTABLE INTVAL exists_keyed_str(STRING *key) {
53+
PMC *name_to_register_map;
54+
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
55+
return VTABLE_exists_keyed_str(interp, name_to_register_map, key);
56+
}
57+
58+
VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
59+
PMC *name_to_register_map;
60+
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
61+
VTABLE_set_integer_keyed_str(interp, name_to_register_map, key, value);
62+
}
63+
64+
/*
65+
66+
=item C<void declare_lex_preg(STRING *name, INTVAL preg)>
67+
68+
Declare a lexical variable that is an alias for a PMC register. The PIR
69+
compiler calls this method in response to a ".lex STRING, PREG" directive.
70+
71+
=cut
72+
73+
*/
74+
75+
METHOD declare_lex_preg(STRING *name, INTVAL preg) {
76+
PMC *name_to_register_map;
77+
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
78+
VTABLE_set_integer_keyed_str(INTERP, name_to_register_map, name, preg);
79+
}
80+
81+
/*
82+
83+
=item C<PMC *inspect_str(STRING *what)>
84+
85+
Introspects this LexInfo structure. The only valid introspection key is
86+
C<symbols>, which gets an array of the names of the symbols in this lexpad.
87+
88+
=cut
89+
90+
*/
91+
92+
VTABLE PMC *inspect_str(STRING *what) {
93+
if (STRING_equal(INTERP, what, CONST_STRING(INTERP, "symbols"))) {
94+
PMC * const result = Parrot_pmc_new(INTERP, enum_class_ResizableStringArray);
95+
PMC *name_to_register_map;
96+
Hash *hash;
97+
98+
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
99+
hash = (Hash *)VTABLE_get_pointer(interp, name_to_register_map);
100+
101+
parrot_hash_iterate(hash,
102+
PARROT_ASSERT(_bucket->key);
103+
VTABLE_push_string(INTERP, result, (STRING *)_bucket->key););
104+
105+
return result;
106+
}
107+
else
108+
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
109+
"Unknown introspection value '%S'", what);
110+
}
111+
}

src/pmc/nqplexpad.pmc

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
#include "pmc_nqplexinfo.h"
2+
3+
pmclass NQPLexPad provides hash no_ro auto_attrs dynpmc group nqp {
4+
ATTR PMC *lexinfo;
5+
ATTR PMC *ctx;
6+
7+
VTABLE void init() {
8+
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
9+
"Cannot create a NQPLexPad PMC without an initializer");
10+
}
11+
12+
/*
13+
14+
=item C<init_pmc(PMC *lexinfo)>
15+
16+
Initialize the LexPad PMC and remember the associate
17+
lexinfo.
18+
19+
=item C<void set_pointer(void *)>
20+
21+
Associate the context, and set into it any static entries.
22+
23+
=item C<INTVAL elements()>
24+
25+
Returns the number of elements in the hash.
26+
27+
=item C<INTVAL exists_keyed(PMC *name)>
28+
29+
=item C<INTVAL exists_keyed_str(STRING *name)>
30+
31+
Returns whether a lexical C<name> exists in the hash.
32+
33+
=item C<PMC *get_pmc_keyed_str(STRING *name)>
34+
35+
=item C<PMC *get_pmc_keyed(PMC *name)>
36+
37+
Return the lexical with the given name, or NULL (not PMCNULL), if the
38+
lexical doesn't exist.
39+
40+
=item C<void set_pmc_keyed(PMC *name, PMC *value)>
41+
42+
=item C<void set_pmc_keyed_str(STRING *name, PMC *value)>
43+
44+
Set the lexical with the given name to value. If the lexical name
45+
doesn't exist, it is created.
46+
47+
=item C<PMC *get_lexinfo()>
48+
49+
Return the LexInfo PMC, if any or a Null PMC.
50+
51+
=cut
52+
53+
*/
54+
VTABLE void init_pmc(PMC *lexinfo) {
55+
SET_ATTR_lexinfo(INTERP, SELF, lexinfo);
56+
}
57+
58+
VTABLE void set_pointer(void *ctx) {
59+
SET_ATTR_ctx(INTERP, SELF, (PMC *)ctx);
60+
}
61+
62+
VTABLE INTVAL elements() {
63+
PMC *info, *name_map;
64+
GET_ATTR_lexinfo(INTERP, SELF, info);
65+
GETATTR_NQPLexInfo_name_to_register_map(INTERP, info, name_map);
66+
return Parrot_hash_size(INTERP,
67+
(Hash *)VTABLE_get_pointer(INTERP, name_map));
68+
}
69+
70+
VTABLE INTVAL exists_keyed_str(STRING *name) {
71+
PMC *info, *name_map;
72+
const Hash *hash;
73+
GET_ATTR_lexinfo(INTERP, SELF, info);
74+
GETATTR_NQPLexInfo_name_to_register_map(INTERP, info, name_map);
75+
hash = (const Hash *)VTABLE_get_pointer(INTERP, name_map);
76+
77+
return hash->entries
78+
? (Parrot_hash_get_bucket(INTERP, hash, name) != 0)
79+
: 0;
80+
}
81+
82+
VTABLE INTVAL exists_keyed(PMC *name) {
83+
STRING * const s = VTABLE_get_string(INTERP, name);
84+
return SELF.exists_keyed_str(s);
85+
}
86+
87+
VTABLE PMC *get_pmc_keyed_str(STRING *name) {
88+
PMC *info, *name_map;
89+
const Hash *hash;
90+
PMC *ctx;
91+
HashBucket *b;
92+
93+
GET_ATTR_lexinfo(INTERP, SELF, info);
94+
GETATTR_NQPLexInfo_name_to_register_map(INTERP, info, name_map);
95+
hash = (const Hash *)VTABLE_get_pointer(INTERP, name_map);
96+
97+
if (!hash->entries)
98+
return PMCNULL;
99+
100+
b = Parrot_hash_get_bucket(INTERP, hash, name);
101+
102+
if (!b)
103+
return PMCNULL;
104+
105+
GET_ATTR_ctx(INTERP, SELF, ctx);
106+
return CTX_REG_PMC(ctx, (INTVAL)b->value);
107+
}
108+
109+
VTABLE PMC *get_pmc_keyed(PMC *name) {
110+
STRING * const s = VTABLE_get_string(INTERP, name);
111+
return SELF.get_pmc_keyed_str(s);
112+
}
113+
114+
VTABLE void set_pmc_keyed_str(STRING *name, PMC *value) {
115+
PMC *info, *name_map;
116+
const Hash *hash;
117+
PMC * ctx;
118+
HashBucket * b;
119+
120+
GET_ATTR_lexinfo(INTERP, SELF, info);
121+
GETATTR_NQPLexInfo_name_to_register_map(INTERP, info, name_map);
122+
hash = (const Hash *)VTABLE_get_pointer(INTERP, name_map);
123+
b = Parrot_hash_get_bucket(INTERP, hash, name);
124+
125+
if (!b)
126+
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LEX_NOT_FOUND,
127+
"Lexical '%Ss' not found", name);
128+
129+
GET_ATTR_ctx(INTERP, SELF, ctx);
130+
CTX_REG_PMC(ctx, (INTVAL)b->value) = value;
131+
PARROT_GC_WRITE_BARRIER(INTERP, ctx);
132+
}
133+
134+
VTABLE void set_pmc_keyed(PMC *name, PMC *value) {
135+
STRING * const s = VTABLE_get_string(INTERP, name);
136+
SELF.set_pmc_keyed_str(s, value);
137+
}
138+
139+
METHOD get_lexinfo() {
140+
PMC *lexinfo;
141+
GET_ATTR_lexinfo(INTERP, SELF, lexinfo);
142+
RETURN(PMC *lexinfo);
143+
}
144+
145+
/*
146+
147+
=item C<PMC *get_iter()>
148+
149+
Get iterator for declared lexicals.
150+
151+
=cut
152+
153+
*/
154+
VTABLE PMC *get_iter() {
155+
PMC *lexinfo;
156+
GET_ATTR_lexinfo(INTERP, SELF, lexinfo);
157+
return VTABLE_get_iter(INTERP, lexinfo);
158+
}
159+
160+
}
161+
162+
/*
163+
164+
=back
165+
166+
=cut
167+
168+
*/

0 commit comments

Comments
 (0)