fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / pmc / packfileconstanttable.pmc
blob4b51a0b973185a495a2ce53839e85dfbde2bb8de
1 /*
2 Copyright (C) 2001-2010, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/packfileconstanttable.pmc - PackfileConstantTable PMC
9 =head1 DESCRIPTION
11 This class implements a PackfileConstantTable object, a segment of the .pbc
12 data file used for storing constants of various types.  (int, string, PMC)
14 See packfile.pmc for the toplevel Packfile interface, see packfilesegment.pmc
15 for the list of common methods every packfile segment pmc must implement; see
16 PDD13 for the design spec.
19 =head2 Methods
21 =over 4
23 =cut
27 /* HEADERIZER HFILE: none */
28 /* HEADERIZER BEGIN: static */
29 /* HEADERIZER END: static */
31 pmclass PackfileConstantTable auto_attrs extends PackfileSegment {
32     /* ResizablePMCArray for storing constants */
33     ATTR PMC *constants;
35     /* ResizableIntegerArray for storing constant types */
36     ATTR PMC *types;
40 =item C<init>
42 Create empty PackfileConstantTable.
44 =cut
48     VTABLE void init() {
49         Parrot_PackfileConstantTable_attributes * const attrs =
50                 PMC_data_typed(SELF, Parrot_PackfileConstantTable_attributes*);
52         attrs->constants = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
53         attrs->types     = Parrot_pmc_new(INTERP, enum_class_ResizableIntegerArray);
55         PObj_custom_mark_SET(SELF);
56         PMC_data(SELF) = attrs;
57     }
61 =item C<void mark()>
63 Marks the object as live.
65 =cut
69     VTABLE void mark() {
70         Parrot_PackfileConstantTable_attributes * const attrs =
71                 PARROT_PACKFILECONSTANTTABLE(SELF);
73         Parrot_gc_mark_PMC_alive(INTERP, attrs->constants);
74         Parrot_gc_mark_PMC_alive(INTERP, attrs->types);
76         SUPER();
77     }
82 =item C<set_pointer>
84 Set pointer to underlying PackFile_ConstTable
86 =cut
90     VTABLE void set_pointer(void * pointer) {
91         Parrot_PackfileConstantTable_attributes * const attrs =
92                 PARROT_PACKFILECONSTANTTABLE(SELF);
93         const PackFile_ConstTable * const table =
94                 (const PackFile_ConstTable *)(pointer);
95         opcode_t i;
97         /* Preallocate required amount of memory */
98         VTABLE_set_integer_native(INTERP, attrs->constants, table->const_count);
99         VTABLE_set_integer_native(INTERP, attrs->types, table->const_count);
101         for (i = 0; i < table->const_count; ++i) {
102             const PackFile_Constant * val = &table->constants[i];
103             switch (val->type) {
104               case PFC_NONE:
105                 break;
106               case PFC_NUMBER:
107                 SELF.set_number_keyed_int(i, val->u.number);
108                 break;
109               case PFC_STRING:
110                 SELF.set_string_keyed_int(i, val->u.string);
111                 break;
112               case PFC_KEY:
113                 /* fall through */
114               case PFC_PMC:
115                 SELF.set_pmc_keyed_int(i, val->u.key);
116                 break;
117               default:
118                 Parrot_ex_throw_from_c_args(INTERP, NULL,
119                         EXCEPTION_MALFORMED_PACKFILE,
120                         "Unknown PackFile constant type: %d", val->type);
121             }
122         }
123     }
127 =item C<void *get_pointer()>
128 =cut
131     VTABLE void *get_pointer() {
132         Parrot_PackfileConstantTable_attributes * const attrs =
133                 PARROT_PACKFILECONSTANTTABLE(SELF);
134         PackFile_ConstTable * const pftable =
135                 mem_gc_allocate_zeroed_typed(INTERP, PackFile_ConstTable);
136         opcode_t              i;
138         pftable->base.type = PF_CONST_SEG;
140         /* Copy all constanst with respect of type */
141         pftable->const_count = VTABLE_get_integer(INTERP, attrs->constants);
142         pftable->constants   = mem_gc_allocate_n_typed(INTERP,
143                 pftable->const_count, PackFile_Constant);
145         for (i = 0; i < pftable->const_count; ++i) {
146             PackFile_Constant * const value = &pftable->constants[i];
147             value->type = VTABLE_get_integer_keyed_int(INTERP, attrs->types, i);
148             switch (value->type) {
149               case PFC_NONE:
150                 break;
151               case PFC_NUMBER:
152                 value->u.number = VTABLE_get_number_keyed_int(INTERP,
153                             attrs->constants, i);
154                 break;
155               case PFC_STRING:
156                 value->u.string = VTABLE_get_string_keyed_int(INTERP,
157                             attrs->constants, i);
158                 break;
159               case PFC_KEY:
160               case PFC_PMC:
161                 value->u.key = VTABLE_get_pmc_keyed_int(INTERP,
162                             attrs->constants, i);
163                 break;
164               default:
165                 Parrot_ex_throw_from_c_args(INTERP, NULL,
166                         EXCEPTION_MALFORMED_PACKFILE,
167                         "Unknown PackFile constant type: %d", value->type);
168             }
169         }
171         return pftable;
172     }
176 =item C<INTVAL elements()>
178 Get the number of elements in the array.
180 =cut
183     VTABLE INTVAL elements() {
184         return VTABLE_elements(INTERP,
185                 PARROT_PACKFILECONSTANTTABLE(SELF)->constants);
186     }
191 =item C<FLOATVAL get_number_keyed_int(INTVAL index)>
193 Fetch a numeric constant.  An exception is thrown if the given constant isn't
194 numeric.
196 =cut
199     VTABLE FLOATVAL get_number_keyed_int(INTVAL index)  {
200         return VTABLE_get_number_keyed_int(INTERP,
201                 PARROT_PACKFILECONSTANTTABLE(SELF)->constants, index);
202     }
207 =item C<STRING *get_string_keyed_int(INTVAL index)>
209 Fetch a string constant.  An exception is thrown if the given constant isn't
210 a string.
212 =cut
215     VTABLE STRING *get_string_keyed_int(INTVAL index)  {
216         return VTABLE_get_string_keyed_int(INTERP,
217                 PARROT_PACKFILECONSTANTTABLE(SELF)->constants, index);
218     }
223 =item C<PMC *get_pmc_keyed_int(INTVAL index)>
225 Fetch a PMC constant.  An exception is thrown if the given constant isn't a PMC.
227 =cut
230     VTABLE PMC *get_pmc_keyed_int(INTVAL index)  {
231         return VTABLE_get_pmc_keyed_int(INTERP,
232                 PARROT_PACKFILECONSTANTTABLE(SELF)->constants, index);
233     }
238 =item C<void set_number_keyed_int(INTVAL index, FLOATVAL value)>
240 Set the constant to the given number.
242 =cut
245     VTABLE void set_number_keyed_int(INTVAL index, FLOATVAL value)  {
246         Parrot_PackfileConstantTable_attributes * const attrs =
247                 PARROT_PACKFILECONSTANTTABLE(SELF);
249         VTABLE_set_number_keyed_int(INTERP, attrs->constants, index, value);
250         VTABLE_set_integer_keyed_int(INTERP, attrs->types, index, PFC_NUMBER);
251     }
256 =item C<void set_string_keyed_int(INTVAL index, STRING *value)>
258 Set the constant to the given string.
260 =cut
264     VTABLE void set_string_keyed_int(INTVAL index, STRING *value)  {
265         Parrot_PackfileConstantTable_attributes * const attrs =
266                 PARROT_PACKFILECONSTANTTABLE(SELF);
268         VTABLE_set_string_keyed_int(INTERP, attrs->constants, index, value);
269         VTABLE_set_integer_keyed_int(INTERP, attrs->types, index, PFC_STRING);
270     }
275 =item C<void set_pmc_keyed_int(INTVAL index, PMC *value)>
277 Set the constant to the given PMC (or key).
279 =cut
282     VTABLE void set_pmc_keyed_int(INTVAL index, PMC *value)  {
283         Parrot_PackfileConstantTable_attributes * const attrs =
284                 PARROT_PACKFILECONSTANTTABLE(SELF);
285         const opcode_t type =
286             VTABLE_isa(INTERP, value, Parrot_str_new_constant(INTERP, "Key"))
287                 ? PFC_KEY
288                 : PFC_PMC;
290         VTABLE_set_pmc_keyed_int(INTERP, attrs->constants,  index, value);
291         VTABLE_set_integer_keyed_int(INTERP, attrs->types, index, type);
292     }
297 =item C<INTVAL get_type(INTVAL index)>
299 Get the type of the specified constant.  Possible type IDs:
301 =over 4
303 =item 0x00 - No constant
305 =item 0x6E - Number constant
307 =item 0x73 - String constant
309 =item 0x70 - PMC constant
311 =item 0x6B - Key constant
313 =back
315 =cut
318     METHOD get_type(INTVAL index) {
319         INTVAL rv = VTABLE_get_integer_keyed_int(INTERP,
320                 PARROT_PACKFILECONSTANTTABLE(SELF)->types, index);
321         RETURN(INTVAL rv);
322     }
326 =item C<void set_main(INTVAL index)>
328 Set the :main flag in a Sub in the constant table.
330 Experimental. Use with care. There is no way to set the
331 private flags from PIR, so we need something like this.
333 If something goes wrong, blame NotFound.
335 =cut
338     METHOD set_main(INTVAL index) {
339         PMC *mainsub = SELF.get_pmc_keyed_int(index);
340         if (mainsub->vtable->base_type != enum_class_Sub)
341             Parrot_ex_throw_from_c_args(INTERP, NULL,
342                 EXCEPTION_INVALID_OPERATION,
343                 "Attempt to set main flag in a non Sub");
344         SUB_FLAG_flag_SET(PF_MAIN, mainsub);
345     }
349 =item C<INTVAL get_or_create_constant()>
351 Get or create constant for passed value.
353 =cut
356     MULTI INTVAL get_or_create_constant(STRING *value) {
357         Parrot_PackfileConstantTable_attributes * const attrs =
358                 PARROT_PACKFILECONSTANTTABLE(SELF);
359         const INTVAL num = VTABLE_elements(INTERP, attrs->types);
360         INTVAL  i;
362         for (i=0; i < num; ++i) {
363             const INTVAL type = VTABLE_get_integer_keyed_int(INTERP, attrs->types, i);
364             if (type == PFC_STRING) {
365                 STRING * const str = VTABLE_get_string_keyed_int(INTERP, attrs->constants, i);
366                 if (Parrot_str_equal(INTERP, value, str))
367                     return i;
368             }
369         }
370         /* Constant not found. Add new one */
371         VTABLE_set_string_keyed_int(INTERP, SELF, i, value);
372         return i;
373     }
375     MULTI INTVAL get_or_create_constant(FLOATVAL value) {
376         Parrot_PackfileConstantTable_attributes * const attrs =
377                 PARROT_PACKFILECONSTANTTABLE(SELF);
378         const INTVAL num = VTABLE_elements(INTERP, attrs->types);
379         INTVAL   i;
381         for (i=0; i < num; ++i) {
382             const INTVAL type = VTABLE_get_integer_keyed_int(INTERP, attrs->types, i);
383             if (type == PFC_NUMBER) {
384                 const FLOATVAL val = VTABLE_get_number_keyed_int(INTERP, attrs->constants, i);
385                 if (FLOAT_IS_ZERO(fabs(val - value)))
386                     return i;
387             }
388         }
389         /* Constant not found. Add new one */
390         VTABLE_set_number_keyed_int(INTERP, SELF, i, value);
391         return i;
392     }
394     MULTI INTVAL get_or_create_constant(PMC *value) {
395         Parrot_PackfileConstantTable_attributes * const attrs =
396                 PARROT_PACKFILECONSTANTTABLE(SELF);
397         const INTVAL   num = VTABLE_elements(INTERP, attrs->types);
398         INTVAL   i;
399         const INTVAL val_type =
400             value->vtable->base_type == enum_class_Key
401                             ? PFC_KEY
402                             : PFC_PMC;
404         for (i=0; i < num; ++i) {
405             const INTVAL type = VTABLE_get_integer_keyed_int(INTERP, attrs->types, i);
406             if (type == val_type) {
407                 PMC * const val = VTABLE_get_pmc_keyed_int(INTERP, attrs->constants, i);
408                 if (VTABLE_is_equal(INTERP, value, val))
409                     return i;
410             }
411         }
412         /* Constant not found. Add new one */
413         VTABLE_set_pmc_keyed_int(INTERP, SELF, i, value);
414         return i;
415     }
419 =item C<METHOD type()>
421 Set segment type.
423 =cut
427     METHOD type() {
428         RETURN(INTVAL PF_CONST_SEG);
429     }
435 =back
437 =cut
442  * Local variables:
443  *   c-file-style: "parrot"
444  * End:
445  * vim: expandtab shiftwidth=4:
446  */