Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Stub in NQPLexInfo and NQPLexPad, which will eventually give static l…
…expad support.
  • Loading branch information
jnthn committed Mar 6, 2011
1 parent ecaf0c5 commit d36a4cd
Show file tree
Hide file tree
Showing 3 changed files with 281 additions and 1 deletion.
3 changes: 2 additions & 1 deletion build/Makefile.in
Expand Up @@ -146,7 +146,8 @@ DYNOPS = $(OPS_DIR)/$(OPS)$(LOAD_EXT)

PMC_SOURCES = $(PMC_DIR)/stable.pmc $(PMC_DIR)/rakudoobject.pmc \
$(PMC_DIR)/repr.pmc $(PMC_DIR)/dispatchersub.pmc \
$(PMC_DIR)/nqpmultisig.pmc
$(PMC_DIR)/nqpmultisig.pmc $(PMC_DIR)/nqplexinfo.pmc \
$(PMC_DIR)/nqplexpad.pmc

OPS_SOURCE = nqp.ops

Expand Down
111 changes: 111 additions & 0 deletions src/pmc/nqplexinfo.pmc
@@ -0,0 +1,111 @@
/* This implements a container of static lexical information for
* NQP (will also be used by Rakudo). It differs from Parrot's
* LexInfo in that it provides support for static lexical values
* that get set into each created lexpad by default. It will also
* enable indexed lookups and, some day, may also allow for native
* values to be stored too. */
pmclass NQPLexInfo provides hash auto_attrs dynpmc group nqp {
/* Hash mapping a name to the register that always holds its
* value. */
ATTR PMC *name_to_register_map;

/* Hash mapping names to static values. This is the authoritative
* source of these, but we always build a more quickly usable
* cache in the next two attributes. */
ATTR PMC *static_values;

/* Integer array of slots that we always want to pre-initialize
* with static values; built from the static_values hash. */
ATTR PMC *static_slots_cache;

/* Matching PMC array of the values to pre-init with; built from
* the static_values hash. */
ATTR PMC *static_values_cache;

void class_init() {
INTERP->vtables[entry]->flags |= VTABLE_IS_CONST_PMC_FLAG;
}

VTABLE void init() {
SELF.init_pmc(PMCNULL);
}

VTABLE void init_pmc(PMC *sub) {
/* Set up the lex info storage. */
PMC *name_to_register_map = pmc_new(interp, enum_class_Hash);
VTABLE_init_int(interp, name_to_register_map, (INTVAL)enum_type_INTVAL);
SET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);

/* Ensure we're constant. */
PARROT_ASSERT(PObj_constant_TEST(SELF));

/* Need custom mark. */
PObj_custom_mark_SET(SELF);
}

VTABLE INTVAL get_integer_keyed_str(STRING *key) {
PMC *name_to_register_map;
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
return VTABLE_get_integer_keyed_str(interp, name_to_register_map, key);
}

VTABLE INTVAL exists_keyed_str(STRING *key) {
PMC *name_to_register_map;
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
return VTABLE_exists_keyed_str(interp, name_to_register_map, key);
}

VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
PMC *name_to_register_map;
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
VTABLE_set_integer_keyed_str(interp, name_to_register_map, key, value);
}

/*

=item C<void declare_lex_preg(STRING *name, INTVAL preg)>

Declare a lexical variable that is an alias for a PMC register. The PIR
compiler calls this method in response to a ".lex STRING, PREG" directive.

=cut

*/

METHOD declare_lex_preg(STRING *name, INTVAL preg) {
PMC *name_to_register_map;
GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
VTABLE_set_integer_keyed_str(INTERP, name_to_register_map, name, preg);
}

/*

=item C<PMC *inspect_str(STRING *what)>

Introspects this LexInfo structure. The only valid introspection key is
C<symbols>, which gets an array of the names of the symbols in this lexpad.

=cut

*/

VTABLE PMC *inspect_str(STRING *what) {
if (STRING_equal(INTERP, what, CONST_STRING(INTERP, "symbols"))) {
PMC * const result = Parrot_pmc_new(INTERP, enum_class_ResizableStringArray);
PMC *name_to_register_map;
Hash *hash;

GET_ATTR_name_to_register_map(INTERP, SELF, name_to_register_map);
hash = (Hash *)VTABLE_get_pointer(interp, name_to_register_map);

parrot_hash_iterate(hash,
PARROT_ASSERT(_bucket->key);
VTABLE_push_string(INTERP, result, (STRING *)_bucket->key););

return result;
}
else
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
"Unknown introspection value '%S'", what);
}
}
168 changes: 168 additions & 0 deletions src/pmc/nqplexpad.pmc
@@ -0,0 +1,168 @@
#include "pmc_nqplexinfo.h"

pmclass NQPLexPad provides hash no_ro auto_attrs dynpmc group nqp {
ATTR PMC *lexinfo;
ATTR PMC *ctx;

VTABLE void init() {
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
"Cannot create a NQPLexPad PMC without an initializer");
}

/*

=item C<init_pmc(PMC *lexinfo)>

Initialize the LexPad PMC and remember the associate
lexinfo.

=item C<void set_pointer(void *)>

Associate the context, and set into it any static entries.

=item C<INTVAL elements()>

Returns the number of elements in the hash.

=item C<INTVAL exists_keyed(PMC *name)>

=item C<INTVAL exists_keyed_str(STRING *name)>

Returns whether a lexical C<name> exists in the hash.

=item C<PMC *get_pmc_keyed_str(STRING *name)>

=item C<PMC *get_pmc_keyed(PMC *name)>

Return the lexical with the given name, or NULL (not PMCNULL), if the
lexical doesn't exist.

=item C<void set_pmc_keyed(PMC *name, PMC *value)>

=item C<void set_pmc_keyed_str(STRING *name, PMC *value)>

Set the lexical with the given name to value. If the lexical name
doesn't exist, it is created.

=item C<PMC *get_lexinfo()>

Return the LexInfo PMC, if any or a Null PMC.

=cut

*/
VTABLE void init_pmc(PMC *lexinfo) {
SET_ATTR_lexinfo(INTERP, SELF, lexinfo);
}

VTABLE void set_pointer(void *ctx) {
SET_ATTR_ctx(INTERP, SELF, (PMC *)ctx);
}

VTABLE INTVAL elements() {
PMC *info, *name_map;
GET_ATTR_lexinfo(INTERP, SELF, info);
GETATTR_NQPLexInfo_name_to_register_map(INTERP, info, name_map);
return Parrot_hash_size(INTERP,
(Hash *)VTABLE_get_pointer(INTERP, name_map));
}

VTABLE INTVAL exists_keyed_str(STRING *name) {
PMC *info, *name_map;
const Hash *hash;
GET_ATTR_lexinfo(INTERP, SELF, info);
GETATTR_NQPLexInfo_name_to_register_map(INTERP, info, name_map);
hash = (const Hash *)VTABLE_get_pointer(INTERP, name_map);

return hash->entries
? (Parrot_hash_get_bucket(INTERP, hash, name) != 0)
: 0;
}

VTABLE INTVAL exists_keyed(PMC *name) {
STRING * const s = VTABLE_get_string(INTERP, name);
return SELF.exists_keyed_str(s);
}

VTABLE PMC *get_pmc_keyed_str(STRING *name) {
PMC *info, *name_map;
const Hash *hash;
PMC *ctx;
HashBucket *b;

GET_ATTR_lexinfo(INTERP, SELF, info);
GETATTR_NQPLexInfo_name_to_register_map(INTERP, info, name_map);
hash = (const Hash *)VTABLE_get_pointer(INTERP, name_map);

if (!hash->entries)
return PMCNULL;

b = Parrot_hash_get_bucket(INTERP, hash, name);

if (!b)
return PMCNULL;

GET_ATTR_ctx(INTERP, SELF, ctx);
return CTX_REG_PMC(ctx, (INTVAL)b->value);
}

VTABLE PMC *get_pmc_keyed(PMC *name) {
STRING * const s = VTABLE_get_string(INTERP, name);
return SELF.get_pmc_keyed_str(s);
}

VTABLE void set_pmc_keyed_str(STRING *name, PMC *value) {
PMC *info, *name_map;
const Hash *hash;
PMC * ctx;
HashBucket * b;

GET_ATTR_lexinfo(INTERP, SELF, info);
GETATTR_NQPLexInfo_name_to_register_map(INTERP, info, name_map);
hash = (const Hash *)VTABLE_get_pointer(INTERP, name_map);
b = Parrot_hash_get_bucket(INTERP, hash, name);

if (!b)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LEX_NOT_FOUND,
"Lexical '%Ss' not found", name);

GET_ATTR_ctx(INTERP, SELF, ctx);
CTX_REG_PMC(ctx, (INTVAL)b->value) = value;
PARROT_GC_WRITE_BARRIER(INTERP, ctx);
}

VTABLE void set_pmc_keyed(PMC *name, PMC *value) {
STRING * const s = VTABLE_get_string(INTERP, name);
SELF.set_pmc_keyed_str(s, value);
}

METHOD get_lexinfo() {
PMC *lexinfo;
GET_ATTR_lexinfo(INTERP, SELF, lexinfo);
RETURN(PMC *lexinfo);
}

/*

=item C<PMC *get_iter()>

Get iterator for declared lexicals.

=cut

*/
VTABLE PMC *get_iter() {
PMC *lexinfo;
GET_ATTR_lexinfo(INTERP, SELF, lexinfo);
return VTABLE_get_iter(INTERP, lexinfo);
}

}

/*

=back

=cut

*/

0 comments on commit d36a4cd

Please sign in to comment.