[TT #871] Add rand as a dynop, with tests
[parrot.git] / src / pmc / lexinfo.pmc
blobde164b18cf0a888f8fc24e220514b9ded5ec228e
1 /*
2 Copyright (C) 2008, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/lexinfo.pmc - LexInfo PMC
9 =head1 DESCRIPTION
11 These are the vtable functions for the lexinfo PMC.
13 =head2 Functions
15 =over 4
17 =cut
21 /* included manually to prevent breaking C++ builds -- see RT #56534*/
22 #include "pmc_hash.h"
25  * LexInfo contains a constant Hash with constant string
26  * keys and integer indices - no marking and no pmc_ext
27  * needed (except for freeze/thaw
28  */
30 pmclass LexInfo extends Hash need_ext provides hash no_ro {
34 =item C<void class_init()>
36 Manipulate vtable->flags so that constant PMCs are created.
37 If your inherited LexInfo is not so constant, then don't
38 do that and provide a mark() method and set the custom_mark flag.
40 =item C<init_pmc(PMC *sub)>
42 Initialize the LexInfo PMC and remember the associate
43 subroutine.
45 =cut
49     void class_init() {
51         /* there is no pmclass const_pmc flag yet */
52         if (pass == 1)
53             interp->vtables[entry]->flags |= VTABLE_IS_CONST_PMC_FLAG;
55     }
57     VTABLE void init() {
58         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
59                 "Cannot create a LexInfo PMC without an initializer");
60     }
62     VTABLE void init_pmc(PMC *sub) {
63         Hash                      *hash;
64         Parrot_LexInfo_attributes *attrs =
65             mem_allocate_zeroed_typed(Parrot_LexInfo_attributes);
66         PARROT_ASSERT(PObj_constant_TEST(SELF));
68         hash = parrot_create_hash(INTERP,
69             (PARROT_DATA_TYPE)enum_hash_int,
70             Hash_key_type_STRING,
71             (hash_comp_fn)Parrot_str_not_equal,     /* STRING compare */
72             (hash_hash_key_fn)Parrot_str_to_hashval); /*        hash    */
74         PMC_data(SELF) = attrs;
75         SELF.set_pointer(hash);
76         PObj_active_destroy_SET(SELF);
77     }
81 =item C<void declare_lex_preg(STRING *name, INTVAL preg)>
83 Declare a lexical variable that is an alias for a PMC register.  The PIR
84 compiler calls this method in response to a ".lex STRING, PREG" directive.
86 =item C<INTVAL elements()>
88 Returns the number of elements in the LexInfo hash.
90 =cut
94     METHOD declare_lex_preg(STRING *name, INTVAL preg) {
95         parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), name, (void*)preg);
96     }
98     VTABLE INTVAL elements() {
99         return parrot_hash_size(INTERP, (Hash *)SELF.get_pointer());
100     }
105 =item C<PMC *inspect_str(STRING *what)>
107 Introspects this LexInfo structure. The only valid introspection key is
108 C<symbols>, which gets an array of the names of the symbols in this lexpad.
110 =cut
114     VTABLE PMC *inspect_str(STRING *what) {
115         if (Parrot_str_equal(interp, what, CONST_STRING(interp, "symbols"))) {
116             PMC *result     = pmc_new(interp, enum_class_ResizableStringArray);
117             Hash *hash      = (Hash *)SELF.get_pointer();
118             UINTVAL entries = hash->entries;
119             UINTVAL found   = 0;
120             INTVAL  i;
122             for (i = hash->mask; i >= 0; --i) {
123                 HashBucket *bucket = hash->bi[i];
124                 while (bucket) {
125                     if (++found > entries)
126                         Parrot_ex_throw_from_c_args(interp, NULL, 1,
127                             "Detected corruption at LexInfo hash %p entries %d",
128                             hash, (int)entries);
130                     PARROT_ASSERT(bucket->key);
131                     VTABLE_push_string(interp, result, (STRING *)bucket->key);
133                     bucket = bucket->next;
134                 }
135             }
137             return result;
138         }
139         else
140             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
141                 "Unknown introspection value '%S'", what);
142     }
146 =item C<void visit(visit_info *info)>
148 =item C<void freeze(visit_info *info)>
150 =item C<void thaw(visit_info *info)>
152 Freeze/thaw interface used during freeze/thaw of the Sub PMC.
153 The implementation of the Hash PMC is called.
155 =cut
160     VTABLE void thaw(visit_info *info) {
161         IMAGE_IO * const io = info->image_io;
163         if (info->extra_flags == EXTRA_IS_NULL) {
164             const INTVAL elems  = VTABLE_shift_integer(INTERP, io);
165             const INTVAL k_type = VTABLE_shift_integer(INTERP, io);
166             const INTVAL v_type = VTABLE_shift_integer(INTERP, io);
167             Hash        *hash;
169             UNUSED(k_type);
170             UNUSED(v_type);
172             PARROT_ASSERT(v_type == enum_hash_int);
173             /* TODO make a better interface for hash creation
174              * TODO create hash with needed types in the first place
175              */
177             SELF.init_pmc(NULL);
178             hash          = (Hash *)SELF.get_pointer();
179             hash->entries = elems;
180         }
181         else {
182             SUPER(info);
183         }
184     }
190 =back
192 =head1 SEE ALSO
194 F<docs/pdds/pdd20_lexical_vars.pod>, F<src/classes/lexpad.pmc>.
196 =cut
201  * Local variables:
202  *   c-file-style: "parrot"
203  * End:
204  * vim: expandtab shiftwidth=4:
205  */