2 Copyright (C) 2001-2010, Parrot Foundation.
7 src/pmc/packfileannotations.pmc - PackfileAnnotations PMC
11 This class implements a PackfileAnnotations object, a segment of the .pbc data
12 file used for listing annotations. It is a container for PackfileAnnotation
15 See packfile.pmc for the toplevel Packfile interface, see packfilesegment.pmc
16 for the list of common methods every packfile segment pmc must implement; see
17 PDD13 for the design spec.
19 To works properly PackfileAnnotations has to be added to PackfileDirectory with
20 PackfileConstantTable. Otherwise PackfileAnnotationKey can't be created.
30 #include "pmc/pmc_packfileannotation.h"
32 /* HEADERIZER HFILE: none */
33 /* HEADERIZER BEGIN: static */
34 /* HEADERIZER END: static */
36 pmclass PackfileAnnotations auto_attrs extends PackfileSegment {
37 /* ConstantTable used for names lookup */
38 ATTR PMC *const_table;
40 /* Annotations group: two RIA for a now */
43 /* RPA of Annotation */
44 ATTR PMC *annotations;
50 Initialize PackfileAnnotations.
56 Parrot_PackfileAnnotations_attributes * attrs =
57 PMC_data_typed(SELF, Parrot_PackfileAnnotations_attributes*);
59 attrs->annotations = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
61 Don't initialize C<const_table>. It will be set to NULL bu auto_attrs
62 handling. And should be set to proper PMC in set_directory.
65 PObj_custom_mark_SET(SELF);
72 Marks the object as live.
79 Parrot_PackfileAnnotations_attributes * attrs =
80 PARROT_PACKFILEANNOTATIONS(SELF);
82 Parrot_gc_mark_PMC_alive(INTERP, attrs->const_table);
83 Parrot_gc_mark_PMC_alive(INTERP, attrs->gr_byte);
84 Parrot_gc_mark_PMC_alive(INTERP, attrs->gr_entries);
85 Parrot_gc_mark_PMC_alive(INTERP, attrs->annotations);
93 =item C<INTVAL elements()>
95 Get the number of elements in the array.
100 VTABLE INTVAL elements() {
101 return VTABLE_elements(INTERP,
102 PARROT_PACKFILEANNOTATIONS(SELF)->annotations);
108 =item C<PMC *get_pmc_keyed_int(INTVAL index)>
110 Fetch an annotation PMC from the array.
115 VTABLE PMC *get_pmc_keyed_int(INTVAL index) {
116 return VTABLE_get_pmc_keyed_int(INTERP,
117 PARROT_PACKFILEANNOTATIONS(SELF)->annotations, index);
123 =item C<void set_pmc_keyed_int(INTVAL index, PMC *annotation)>
125 Add an annotation to the array at the given offset. An exception will be
126 thrown unless all of the following criteria are met:
130 =item - The type of the PMC passed is PackfileAnnotation
132 =item - The entry at the previous index is defined
134 =item - The offset of the previous entry is less than this entry
136 =item - The offset of the next entry, if it exists, is greater than this entry
138 =item - The key ID references a valid annotation key
145 VTABLE void set_pmc_keyed_int(INTVAL index, PMC *annotation) {
146 Parrot_PackfileAnnotations_attributes * attrs =
147 PARROT_PACKFILEANNOTATIONS(SELF);
148 Parrot_PackfileAnnotation_attributes * entity_attrs =
149 PARROT_PACKFILEANNOTATION(annotation);
152 /* TODO: add checks desribed above */
153 VTABLE_set_pmc_keyed_int(INTERP, attrs->annotations, index, annotation);
155 /* Add required constants */
156 Parrot_mmd_multi_dispatch_from_c_args(INTERP,
157 "get_or_create_constant", "PS->I", attrs->const_table,
158 entity_attrs->name, &dummy);
160 switch (entity_attrs->value_type) {
161 case PF_ANNOTATION_KEY_TYPE_STR:
162 Parrot_mmd_multi_dispatch_from_c_args(INTERP,
163 "get_or_create_constant", "PS->I", attrs->const_table,
164 entity_attrs->str_value, &dummy);
167 case PF_ANNOTATION_KEY_TYPE_NUM:
168 Parrot_mmd_multi_dispatch_from_c_args(INTERP,
169 "get_or_create_constant", "PN->I", attrs->const_table,
170 entity_attrs->num_value, &dummy);
174 /* Do nothing. If value_type if INT it will be stored directly */
181 =item C<void set_directory()>
183 Handle setting of ownership.
185 Find PackfileConstantTable in PackfileDirectory and pass it to
186 PackfileAnnotationKeys.
192 METHOD set_directory(PMC *directory) {
193 Parrot_PackfileAnnotations_attributes *attrs =
194 PARROT_PACKFILEANNOTATIONS(SELF);
198 PMC *iter = VTABLE_get_iter(INTERP, directory);
199 while (VTABLE_get_bool(INTERP, iter)) {
200 name = VTABLE_shift_string(INTERP, iter);
201 segment = VTABLE_get_pmc_keyed_str(INTERP, directory, name);
202 if (VTABLE_isa(INTERP, segment,
203 Parrot_str_new_constant(INTERP, "PackfileConstantTable"))) {
204 attrs->const_table = segment;
212 =item C<void set_pointer(void *ptr)>
214 Initialize PackfileAnnotations from PackFile_Annotations*.
219 VTABLE void set_pointer(void *pointer) {
220 PackFile_Annotations * a = (PackFile_Annotations*)pointer;
221 Parrot_PackfileAnnotations_attributes *attrs =
222 PARROT_PACKFILEANNOTATIONS(SELF);
225 Parrot_PackfileAnnotation_attributes *annotation_attrs;
227 /* Copy annotations groups */
228 if (a->num_groups > 0) {
229 attrs->gr_byte = Parrot_pmc_new_init_int(INTERP,
230 enum_class_ResizableIntegerArray, a->num_groups);
231 attrs->gr_entries = Parrot_pmc_new_init_int(INTERP,
232 enum_class_ResizableIntegerArray, a->num_groups);
233 for (i = 0; i < a->num_groups; ++i) {
234 VTABLE_set_integer_keyed_int(INTERP, attrs->gr_byte, i,
235 a->groups[i].bytecode_offset);
236 VTABLE_set_integer_keyed_int(INTERP, attrs->gr_entries, i,
237 a->groups[i].entries_offset);
241 /* Copy annotations to own array */
242 VTABLE_set_integer_native(INTERP, attrs->annotations, a->num_entries);
243 for (i = 0; i < a->num_entries; ++i) {
244 PackFile_Annotations_Entry *entry = a->entries + i;
245 PackFile_Annotations_Key *key = a->keys + entry->key;
246 annotation = Parrot_pmc_new(INTERP, enum_class_PackfileAnnotation);
248 /* Poke directly to annotation attributes. */
249 annotation_attrs = PARROT_PACKFILEANNOTATION(annotation);
250 annotation_attrs->offset = entry->bytecode_offset;
251 if (! attrs->const_table)
252 Parrot_ex_throw_from_c_args(INTERP, NULL,
253 EXCEPTION_MALFORMED_PACKFILE, "No constant table");
255 annotation_attrs->name = VTABLE_get_string_keyed_int(INTERP,
256 attrs->const_table, key->name);
258 case PF_ANNOTATION_KEY_TYPE_INT:
259 VTABLE_set_integer_native(INTERP, annotation, entry->value);
261 case PF_ANNOTATION_KEY_TYPE_STR:
262 VTABLE_set_string_native(INTERP, annotation,
263 VTABLE_get_string_keyed_int(INTERP, attrs->const_table, entry->value));
265 case PF_ANNOTATION_KEY_TYPE_NUM:
266 VTABLE_set_number_native(INTERP, annotation,
267 VTABLE_get_number_keyed_int(INTERP, attrs->const_table, entry->value));
270 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_MALFORMED_PACKFILE,
271 "Unknown value type %d in Packfile Annotation", key->type);
274 VTABLE_set_pmc_keyed_int(INTERP, attrs->annotations, i, annotation);
280 =item C<void *get_pointer()>
282 Create PackFile_Annotations* from self.
287 VTABLE void *get_pointer() {
288 Parrot_PackfileAnnotations_attributes *attrs =
289 PARROT_PACKFILEANNOTATIONS(SELF);
290 PackFile_Annotations *res = mem_gc_allocate_zeroed_typed(INTERP,
291 PackFile_Annotations);
293 PMC *keys; /* Temporary representation of Keys */
294 PMC *names; /* Constants for Key's names */
295 PMC *types; /* Types of Keys */
300 res->base.type = PF_ANNOTATIONS_SEG;
302 /* Create annotations groups */
303 num = PMC_IS_NULL(attrs->gr_byte) ?
304 (INTVAL)0 : VTABLE_elements(INTERP, attrs->gr_byte);
305 res->num_groups = num;
307 res->groups = mem_gc_allocate_n_zeroed_typed(interp,
308 num, PackFile_Annotations_Group);
309 for (i = 0; i < num; ++i) {
310 res->groups[i].bytecode_offset =
311 VTABLE_get_integer_keyed_int(INTERP, attrs->gr_byte, i);
312 res->groups[i].entries_offset =
313 VTABLE_get_integer_keyed_int(INTERP, attrs->gr_entries, i);
318 Create keys. Hash will be created in next structure:
327 Each key has name from ConstantTable. We store them in names Array.
334 keys = Parrot_pmc_new(INTERP, enum_class_Hash);
335 names = Parrot_pmc_new(INTERP, enum_class_ResizableIntegerArray);
336 types = Parrot_pmc_new(INTERP, enum_class_ResizableIntegerArray);
339 /* Iterate over stored annotations and create Key if required. */
340 num = VTABLE_elements(INTERP, attrs->annotations);
341 res->num_entries = num;
342 res->entries = mem_gc_allocate_n_typed(INTERP, num, PackFile_Annotations_Entry);
343 for (i = 0; i < num; ++i) {
344 PMC * const entity = VTABLE_get_pmc_keyed_int(INTERP, attrs->annotations, i);
345 const Parrot_PackfileAnnotation_attributes * const entity_attrs =
346 PARROT_PACKFILEANNOTATION(entity);
348 /* Handle creating of Key */
349 PMC * key_array = VTABLE_get_pmc_keyed_str(INTERP, keys, entity_attrs->name);
350 if (PMC_IS_NULL(key_array)) {
351 /* Never see this name before. Create new FIA and add to keys. */
352 key_array = Parrot_pmc_new_init_int(INTERP, enum_class_FixedIntegerArray, 3);
353 VTABLE_set_integer_keyed_int(INTERP, key_array, 0, -1);
354 VTABLE_set_integer_keyed_int(INTERP, key_array, 1, -1);
355 VTABLE_set_integer_keyed_int(INTERP, key_array, 2, -1);
357 VTABLE_set_pmc_keyed_str(INTERP, keys, entity_attrs->name, key_array);
360 /* PackfileAnnotation.value_type exactly the same as key.type */
361 key_id = VTABLE_get_integer_keyed_int(INTERP, key_array, entity_attrs->value_type);
363 /* If key_id is -1 it means we have to create new key. */
365 key_id = ++last_key_id;
366 VTABLE_set_integer_keyed_int(INTERP, key_array, entity_attrs->value_type, key_id);
369 VTABLE_set_integer_keyed_int(INTERP, types, key_id, entity_attrs->value_type);
372 /* Store constant for name. */
373 Parrot_mmd_multi_dispatch_from_c_args(INTERP, "get_or_create_constant",
374 "PS->I", attrs->const_table, entity_attrs->name, &name_id);
376 VTABLE_set_integer_keyed_int(INTERP, names, key_id, name_id);
379 /* At this point we have create (if nesassary) key and name constant. */
380 /* Start storing real entity */
382 res->entries[i].bytecode_offset = entity_attrs->offset;
383 res->entries[i].key = key_id;
386 switch (entity_attrs->value_type) {
387 case PF_ANNOTATION_KEY_TYPE_INT:
388 res->entries[i].value = entity_attrs->int_value;
390 case PF_ANNOTATION_KEY_TYPE_STR:
391 Parrot_mmd_multi_dispatch_from_c_args(INTERP, "get_or_create_constant",
392 "PS->I", attrs->const_table, entity_attrs->str_value,
393 &res->entries[i].value);
395 case PF_ANNOTATION_KEY_TYPE_NUM:
396 Parrot_mmd_multi_dispatch_from_c_args(INTERP, "get_or_create_constant",
397 "PN->I", attrs->const_table, entity_attrs->num_value,
398 &res->entries[i].value);
401 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_MALFORMED_PACKFILE,
402 "Unknown value type in PackfileAnnotation");
406 /* Time to pack keys */
407 num = VTABLE_elements(INTERP, types);
409 res->keys = mem_gc_allocate_n_zeroed_typed(INTERP, num,
410 PackFile_Annotations_Key);
411 for (i = 0; i < num; ++i) {
412 res->keys[i].name = VTABLE_get_integer_keyed_int(INTERP, names, i);
413 res->keys[i].type = VTABLE_get_integer_keyed_int(INTERP, types, i);
421 =item C<METHOD type()>
430 RETURN(INTVAL PF_ANNOTATIONS_SEG);
445 * c-file-style: "parrot"
447 * vim: expandtab shiftwidth=4: