2 Copyright (C) 2001-2008, 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 pmclass PackfileAnnotations auto_attrs extends PackfileSegment {
33 /* ConstantTable used for names lookup */
34 ATTR PMC *const_table;
36 /* RPA of Annotation */
37 ATTR PMC *annotations;
43 Initialize PackfileAnnotations.
49 Parrot_PackfileAnnotations_attributes * attrs =
50 PMC_data_typed(SELF, Parrot_PackfileAnnotations_attributes*);
52 attrs->annotations = Parrot_pmc_new(interp, enum_class_ResizablePMCArray);
54 Don't initialize C<const_table>. It will be set to NULL bu auto_attrs
55 handling. And should be set to proper PMC in set_directory.
58 PObj_custom_mark_SET(SELF);
65 Marks the object as live.
72 Parrot_PackfileAnnotations_attributes * attrs =
73 PARROT_PACKFILEANNOTATIONS(SELF);
75 Parrot_gc_mark_PMC_alive(interp, attrs->const_table);
76 Parrot_gc_mark_PMC_alive(interp, attrs->annotations);
84 =item C<INTVAL elements()>
86 Get the number of elements in the array.
91 VTABLE INTVAL elements() {
92 return VTABLE_elements(interp,
93 PARROT_PACKFILEANNOTATIONS(SELF)->annotations);
99 =item C<PMC *get_pmc_keyed_int(INTVAL index)>
101 Fetch an annotation PMC from the array.
106 VTABLE PMC *get_pmc_keyed_int(INTVAL index) {
107 return VTABLE_get_pmc_keyed_int(interp,
108 PARROT_PACKFILEANNOTATIONS(SELF)->annotations, index);
114 =item C<void set_pmc_keyed_int(INTVAL index, PMC *annotation)>
116 Add an annotation to the array at the given offset. An exception will be
117 thrown unless all of the following criteria are met:
121 =item - The type of the PMC passed is PackfileAnnotation
123 =item - The entry at the previous index is defined
125 =item - The offset of the previous entry is less than this entry
127 =item - The offset of the next entry, if it exists, is greater than this entry
129 =item - The key ID references a valid annotation key
136 VTABLE void set_pmc_keyed_int(INTVAL index, PMC *annotation) {
137 Parrot_PackfileAnnotations_attributes * attrs =
138 PARROT_PACKFILEANNOTATIONS(SELF);
139 Parrot_PackfileAnnotation_attributes * entity_attrs =
140 PARROT_PACKFILEANNOTATION(annotation);
143 /* TODO: add checks desribed above */
144 VTABLE_set_pmc_keyed_int(interp, attrs->annotations, index, annotation);
146 /* Add required constants */
147 Parrot_mmd_multi_dispatch_from_c_args(interp,
148 "get_or_create_constant", "PS->I", attrs->const_table,
149 entity_attrs->name, &dummy);
151 switch (entity_attrs->value_type) {
152 case PF_ANNOTATION_KEY_TYPE_STR:
153 Parrot_mmd_multi_dispatch_from_c_args(interp,
154 "get_or_create_constant", "PS->I", attrs->const_table,
155 entity_attrs->str_value, &dummy);
158 case PF_ANNOTATION_KEY_TYPE_NUM:
159 Parrot_mmd_multi_dispatch_from_c_args(interp,
160 "get_or_create_constant", "PN->I", attrs->const_table,
161 entity_attrs->num_value, &dummy);
165 /* Do nothing. If value_type if INT it will be stored directly */
172 =item C<void set_directory()>
174 Handle setting of ownership.
176 Find PackfileConstantTable in PackfileDirectory and pass it to
177 PackfileAnnotationKeys.
183 METHOD set_directory(PMC *directory) {
184 Parrot_PackfileAnnotations_attributes *attrs =
185 PARROT_PACKFILEANNOTATIONS(SELF);
189 PMC *iter = VTABLE_get_iter(interp, directory);
190 while (VTABLE_get_bool(interp, iter)) {
191 name = VTABLE_shift_string(interp, iter);
192 segment = VTABLE_get_pmc_keyed_str(interp, directory, name);
193 if (VTABLE_isa(interp, segment,
194 Parrot_str_new_constant(interp, "PackfileConstantTable"))) {
195 attrs->const_table = segment;
203 =item C<void set_pointer(void *ptr)>
205 Initialize PackfileAnnotations from PackFile_Annotations*.
210 VTABLE void set_pointer(void *pointer) {
211 PackFile_Annotations * a = (PackFile_Annotations*)pointer;
212 Parrot_PackfileAnnotations_attributes *attrs =
213 PARROT_PACKFILEANNOTATIONS(SELF);
216 Parrot_PackfileAnnotation_attributes *annotation_attrs;
218 /* Copy annotations to own array */
219 VTABLE_set_integer_native(interp, attrs->annotations, a->num_entries);
220 for (i = 0; i < a->num_entries; ++i) {
221 PackFile_Annotations_Entry *entry = a->entries[i];
222 PackFile_Annotations_Key *key = a->keys[entry->key];
223 annotation = Parrot_pmc_new(interp, enum_class_PackfileAnnotation);
225 /* Poke directly to annotation attributes. */
226 annotation_attrs = PARROT_PACKFILEANNOTATION(annotation);
227 annotation_attrs->offset = entry->bytecode_offset;
228 annotation_attrs->name = VTABLE_get_string_keyed_int(interp,
229 attrs->const_table, key->name);
231 case PF_ANNOTATION_KEY_TYPE_INT:
232 VTABLE_set_integer_native(interp, annotation, entry->value);
234 case PF_ANNOTATION_KEY_TYPE_STR:
235 VTABLE_set_string_native(interp, annotation,
236 VTABLE_get_string_keyed_int(interp, attrs->const_table, entry->value));
238 case PF_ANNOTATION_KEY_TYPE_NUM:
239 VTABLE_set_number_native(interp, annotation,
240 VTABLE_get_number_keyed_int(interp, attrs->const_table, entry->value));
243 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
244 "Unknown value type %d in Packfile Annotation", key->type);
247 VTABLE_set_pmc_keyed_int(interp, attrs->annotations, i, annotation);
253 =item C<void *get_pointer()>
255 Create PackFile_Annotations* from self.
260 VTABLE void *get_pointer() {
261 Parrot_PackfileAnnotations_attributes *attrs =
262 PARROT_PACKFILEANNOTATIONS(SELF);
263 PackFile_Annotations *res = mem_gc_allocate_zeroed_typed(INTERP,
264 PackFile_Annotations);
267 PMC *keys; /* Temporary representation of Keys */
268 PMC *names; /* Constants for Key's names */
269 PMC *types; /* Types of Keys */
274 res->base.type = PF_ANNOTATIONS_SEG;
277 Create keys. Hash will be created in next structure:
286 Each key has name from ConstantTable. We store them in names Array.
293 keys = Parrot_pmc_new(interp, enum_class_Hash);
294 names = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
295 types = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
298 /* Iterate over stored annotations and create Key if required. */
299 num = VTABLE_elements(interp, attrs->annotations);
300 res->num_entries = num;
301 res->entries = mem_gc_allocate_n_typed(INTERP, num, PackFile_Annotations_Entry*);
302 for (i = 0; i < num; ++i) {
303 PMC *entity = VTABLE_get_pmc_keyed_int(interp, attrs->annotations, i);
304 Parrot_PackfileAnnotation_attributes *entity_attrs = PARROT_PACKFILEANNOTATION(entity);
306 /* Handle creating of Key */
307 PMC * key_array = VTABLE_get_pmc_keyed_str(interp, keys, entity_attrs->name);
308 if (PMC_IS_NULL(key_array)) {
309 /* Never see this name before. Create new FIA and add to keys. */
310 key_array = Parrot_pmc_new(interp, enum_class_FixedIntegerArray);
311 VTABLE_set_integer_native(interp, key_array, 3);
312 VTABLE_set_integer_keyed_int(interp, key_array, 0, -1);
313 VTABLE_set_integer_keyed_int(interp, key_array, 1, -1);
314 VTABLE_set_integer_keyed_int(interp, key_array, 2, -1);
316 VTABLE_set_pmc_keyed_str(interp, keys, entity_attrs->name, key_array);
319 /* PackfileAnnotation.value_type exactly the same as key.type */
320 key_id = VTABLE_get_integer_keyed_int(interp, key_array, entity_attrs->value_type);
322 /* If key_id is -1 it means we have to create new key. */
324 key_id = ++last_key_id;
325 VTABLE_set_integer_keyed_int(interp, key_array, entity_attrs->value_type, key_id);
328 VTABLE_set_integer_keyed_int(interp, types, key_id, entity_attrs->value_type);
331 /* Store constant for name. */
332 Parrot_mmd_multi_dispatch_from_c_args(interp, "get_or_create_constant",
333 "PS->I", attrs->const_table, entity_attrs->name, &name_id);
335 VTABLE_set_integer_keyed_int(interp, names, key_id, name_id);
338 /* At this point we have create (if nesassary) key and name constant. */
339 /* Start storing real entity */
340 res->entries[i] = mem_gc_allocate_zeroed_typed(INTERP,
341 PackFile_Annotations_Entry);
343 res->entries[i]->bytecode_offset = entity_attrs->offset;
344 res->entries[i]->key = key_id;
347 switch (entity_attrs->value_type) {
348 case PF_ANNOTATION_KEY_TYPE_INT:
349 res->entries[i]->value = entity_attrs->int_value;
351 case PF_ANNOTATION_KEY_TYPE_STR:
352 Parrot_mmd_multi_dispatch_from_c_args(interp, "get_or_create_constant",
353 "PS->I", attrs->const_table, entity_attrs->str_value,
354 &res->entries[i]->value);
356 case PF_ANNOTATION_KEY_TYPE_NUM:
357 Parrot_mmd_multi_dispatch_from_c_args(interp, "get_or_create_constant",
358 "PN->I", attrs->const_table, entity_attrs->num_value,
359 &res->entries[i]->value);
362 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_MALFORMED_PACKFILE,
363 "Unknown value type in PackfileAnnotation");
367 /* Time to pack keys */
368 num = VTABLE_elements(interp, types);
370 res->keys = mem_gc_allocate_n_zeroed_typed(INTERP, num,
371 PackFile_Annotations_Key*);
372 for (i = 0; i < num; ++i) {
373 res->keys[i] = mem_gc_allocate_typed(INTERP, PackFile_Annotations_Key);
374 res->keys[i]->name = VTABLE_get_integer_keyed_int(interp, names, i);
375 res->keys[i]->type = VTABLE_get_integer_keyed_int(interp, types, i);
383 =item C<METHOD type()>
392 RETURN(INTVAL PF_ANNOTATIONS_SEG);
407 * c-file-style: "parrot"
409 * vim: expandtab shiftwidth=4: