fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / pmc / callcontext.pmc
blob9d98988ed537497b8eecc22808871d977b4cbc4d
1 /*
2 Copyright (C) 2008-2010, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/callcontext.pmc - CallContext PMC
9 =head1 DESCRIPTION
11 The CallContext PMC is used to store the argument list and argument meta
12 information for a multiple dispatch call.
14 =head2 Functions
16 =over 4
18 =cut
22 typedef struct Pcc_cell
24     union u {
25         PMC     *p;
26         STRING  *s;
27         INTVAL   i;
28         FLOATVAL n;
29     } u;
30     INTVAL type;
31 } Pcc_cell;
33 #define NOCELL     0
34 #define INTCELL    1
35 #define FLOATCELL  2
36 #define STRINGCELL 3
37 #define PMCCELL    4
39 #define ALLOC_CELL(i) \
40     (Pcc_cell *)Parrot_gc_allocate_fixed_size_storage((i), sizeof (Pcc_cell))
42 #define FREE_CELL(i, c) \
43     Parrot_gc_free_fixed_size_storage((i), sizeof (Pcc_cell), (c))
45 #define CELL_TYPE_MASK(c) (c)->type
47 #define CELL_INT(c)     (c)->u.i
48 #define CELL_FLOAT(c)   (c)->u.n
49 #define CELL_STRING(c)  (c)->u.s
50 #define CELL_PMC(c)     (c)->u.p
52 #define HLL_TYPE(i) Parrot_get_ctx_HLL_type(interp, (i))
54 /* HEADERIZER HFILE: none */
55 /* HEADERIZER BEGIN: static */
56 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
58 static FLOATVAL autobox_floatval(PARROT_INTERP, ARGIN(const Pcc_cell *cell))
59         __attribute__nonnull__(1)
60         __attribute__nonnull__(2);
62 static INTVAL autobox_intval(PARROT_INTERP, ARGIN(const Pcc_cell *cell))
63         __attribute__nonnull__(1)
64         __attribute__nonnull__(2);
66 PARROT_CANNOT_RETURN_NULL
67 static PMC * autobox_pmc(PARROT_INTERP, ARGIN(Pcc_cell *cell), INTVAL type)
68         __attribute__nonnull__(1)
69         __attribute__nonnull__(2);
71 PARROT_CANNOT_RETURN_NULL
72 static STRING * autobox_string(PARROT_INTERP, ARGIN(const Pcc_cell *cell))
73         __attribute__nonnull__(1)
74         __attribute__nonnull__(2);
76 static void ensure_positionals_storage(PARROT_INTERP,
77     ARGIN(PMC *self),
78     INTVAL size)
79         __attribute__nonnull__(1)
80         __attribute__nonnull__(2);
82 static void ensure_positionals_storage_ap(PARROT_INTERP,
83     ARGIN(PMC *self),
84     INTVAL size,
85     INTVAL allocated_positionals)
86         __attribute__nonnull__(1)
87         __attribute__nonnull__(2);
89 PARROT_CANNOT_RETURN_NULL
90 static Pcc_cell* get_cell_at(PARROT_INTERP, ARGIN(PMC *self), INTVAL key)
91         __attribute__nonnull__(1)
92         __attribute__nonnull__(2);
94 PARROT_CANNOT_RETURN_NULL
95 static Hash * get_hash(PARROT_INTERP, ARGIN(PMC *SELF))
96         __attribute__nonnull__(1)
97         __attribute__nonnull__(2);
99 PARROT_CAN_RETURN_NULL
100 static PMC * get_named_names(PARROT_INTERP, ARGIN(PMC *SELF))
101         __attribute__nonnull__(1)
102         __attribute__nonnull__(2);
104 static void mark_cell(PARROT_INTERP, ARGIN(Pcc_cell *c))
105         __attribute__nonnull__(1)
106         __attribute__nonnull__(2);
108 static void mark_hash(PARROT_INTERP, ARGIN(Hash *h))
109         __attribute__nonnull__(1)
110         __attribute__nonnull__(2);
112 static void mark_positionals(PARROT_INTERP, ARGIN(PMC *self))
113         __attribute__nonnull__(1)
114         __attribute__nonnull__(2);
116 #define ASSERT_ARGS_autobox_floatval __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
117        PARROT_ASSERT_ARG(interp) \
118     , PARROT_ASSERT_ARG(cell))
119 #define ASSERT_ARGS_autobox_intval __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
120        PARROT_ASSERT_ARG(interp) \
121     , PARROT_ASSERT_ARG(cell))
122 #define ASSERT_ARGS_autobox_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
123        PARROT_ASSERT_ARG(interp) \
124     , PARROT_ASSERT_ARG(cell))
125 #define ASSERT_ARGS_autobox_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
126        PARROT_ASSERT_ARG(interp) \
127     , PARROT_ASSERT_ARG(cell))
128 #define ASSERT_ARGS_ensure_positionals_storage __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
129        PARROT_ASSERT_ARG(interp) \
130     , PARROT_ASSERT_ARG(self))
131 #define ASSERT_ARGS_ensure_positionals_storage_ap __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
132        PARROT_ASSERT_ARG(interp) \
133     , PARROT_ASSERT_ARG(self))
134 #define ASSERT_ARGS_get_cell_at __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
135        PARROT_ASSERT_ARG(interp) \
136     , PARROT_ASSERT_ARG(self))
137 #define ASSERT_ARGS_get_hash __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
138        PARROT_ASSERT_ARG(interp) \
139     , PARROT_ASSERT_ARG(SELF))
140 #define ASSERT_ARGS_get_named_names __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
141        PARROT_ASSERT_ARG(interp) \
142     , PARROT_ASSERT_ARG(SELF))
143 #define ASSERT_ARGS_mark_cell __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
144        PARROT_ASSERT_ARG(interp) \
145     , PARROT_ASSERT_ARG(c))
146 #define ASSERT_ARGS_mark_hash __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
147        PARROT_ASSERT_ARG(interp) \
148     , PARROT_ASSERT_ARG(h))
149 #define ASSERT_ARGS_mark_positionals __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
150        PARROT_ASSERT_ARG(interp) \
151     , PARROT_ASSERT_ARG(self))
152 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
153 /* HEADERIZER END: static */
157 =item C<static void ensure_positionals_storage(PARROT_INTERP, PMC *self, INTVAL
158 size)>
160 =cut
164 static void
165 ensure_positionals_storage(PARROT_INTERP, ARGIN(PMC *self), INTVAL size)
167     ASSERT_ARGS(ensure_positionals_storage)
168     INTVAL allocated_positionals;
170     GETATTR_CallContext_allocated_positionals(interp, self, allocated_positionals);
172     if (size <= allocated_positionals)
173         return;
175     ensure_positionals_storage_ap(interp, self, size, allocated_positionals);
180 =item C<static void ensure_positionals_storage_ap(PARROT_INTERP, PMC *self,
181 INTVAL size, INTVAL allocated_positionals)>
183 =cut
187 static void
188 ensure_positionals_storage_ap(PARROT_INTERP,
189                               ARGIN(PMC *self), INTVAL size, INTVAL allocated_positionals)
191     ASSERT_ARGS(ensure_positionals_storage_ap)
192     INTVAL num_positionals;
193     Pcc_cell *array, *new_array;
195     if (size < 8)
196         size = 8;
198     GETATTR_CallContext_positionals(interp, self, array);
200     if (size > 8)
201         new_array = (Pcc_cell *)Parrot_gc_allocate_memory_chunk(interp,
202                 size * sizeof (Pcc_cell));
203     else
204         new_array = (Pcc_cell *)Parrot_gc_allocate_fixed_size_storage(interp,
205                 size * sizeof (Pcc_cell));
207     if (array) {
208         GETATTR_CallContext_num_positionals(interp, self, num_positionals);
209         memcpy(new_array, array, num_positionals * sizeof (Pcc_cell));
211         if (allocated_positionals > 8)
212             Parrot_gc_free_memory_chunk(interp, array);
213         else
214             Parrot_gc_free_fixed_size_storage(interp,
215                 allocated_positionals * sizeof (Pcc_cell), array);
216     }
218     SETATTR_CallContext_allocated_positionals(interp, self, size);
219     SETATTR_CallContext_positionals(interp, self, new_array);
224 =item C<static Pcc_cell* get_cell_at(PARROT_INTERP, PMC *self, INTVAL key)>
226 =cut
230 PARROT_CANNOT_RETURN_NULL
231 static Pcc_cell*
232 get_cell_at(PARROT_INTERP, ARGIN(PMC *self), INTVAL key)
234     ASSERT_ARGS(get_cell_at)
235     Pcc_cell *cells;
236     ensure_positionals_storage(interp, self, key + 1);
237     GETATTR_CallContext_positionals(interp, self, cells);
238     return &cells[key];
243 =item C<static INTVAL autobox_intval(PARROT_INTERP, const Pcc_cell *cell)>
245 =cut
249 static INTVAL
250 autobox_intval(PARROT_INTERP, ARGIN(const Pcc_cell *cell))
252     ASSERT_ARGS(autobox_intval)
253     switch (CELL_TYPE_MASK(cell)) {
254       case INTCELL:
255         return CELL_INT(cell);
256       case FLOATCELL:
257         return (INTVAL)CELL_FLOAT(cell);
258       case STRINGCELL:
259         return CELL_STRING(cell) ? Parrot_str_to_int(interp, CELL_STRING(cell)) : 0;
260       case PMCCELL:
261         return PMC_IS_NULL(CELL_PMC(cell))
262                 ? 0
263                 : VTABLE_get_integer(interp, CELL_PMC(cell));
264       default:
265         break;
266     }
268     /* exception */
269     return 0;
274 =item C<static FLOATVAL autobox_floatval(PARROT_INTERP, const Pcc_cell *cell)>
276 =cut
280 static FLOATVAL
281 autobox_floatval(PARROT_INTERP, ARGIN(const Pcc_cell *cell))
283     ASSERT_ARGS(autobox_floatval)
284     switch (CELL_TYPE_MASK(cell)) {
285       case INTCELL:
286         return (FLOATVAL)CELL_INT(cell);
287       case FLOATCELL:
288         return CELL_FLOAT(cell);
289       case STRINGCELL:
290         return CELL_STRING(cell) ? Parrot_str_to_num(interp, CELL_STRING(cell)) : 0.0;
291       case PMCCELL:
292         return PMC_IS_NULL(CELL_PMC(cell))
293                 ? 0.0
294                 : VTABLE_get_number(interp, CELL_PMC(cell));
295       default:
296         break;
297     }
299     /* exception */
300     return 0.0;
305 =item C<static STRING * autobox_string(PARROT_INTERP, const Pcc_cell *cell)>
307 =cut
311 PARROT_CANNOT_RETURN_NULL
312 static STRING *
313 autobox_string(PARROT_INTERP, ARGIN(const Pcc_cell *cell))
315     ASSERT_ARGS(autobox_string)
316     switch (CELL_TYPE_MASK(cell)) {
317       case INTCELL:
318         return Parrot_str_from_int(interp, CELL_INT(cell));
319       case FLOATCELL:
320         return Parrot_str_from_num(interp, CELL_FLOAT(cell));
321       case STRINGCELL:
322         return CELL_STRING(cell);
323       case PMCCELL:
324         return PMC_IS_NULL(CELL_PMC(cell))
325                 ? NULL
326                 : VTABLE_get_string(interp, CELL_PMC(cell));
327       default:
328         break;
329     }
331     /* exception */
332     return NULL;
337 =item C<static PMC * autobox_pmc(PARROT_INTERP, Pcc_cell *cell, INTVAL type)>
339 =cut
343 PARROT_CANNOT_RETURN_NULL
344 static PMC *
345 autobox_pmc(PARROT_INTERP, ARGIN(Pcc_cell *cell), INTVAL type)
347     ASSERT_ARGS(autobox_pmc)
348     PMC *result = PMCNULL;
350     switch (type) {
351       case INTCELL:
352         result = Parrot_pmc_new(interp, HLL_TYPE(enum_class_Integer));
353         VTABLE_set_integer_native(interp, result, CELL_INT(cell));
354         break;
355       case FLOATCELL:
356         result = Parrot_pmc_new(interp, HLL_TYPE(enum_class_Float));
357         VTABLE_set_number_native(interp, result, CELL_FLOAT(cell));
358         break;
359       case STRINGCELL:
360         result = Parrot_pmc_new(interp, HLL_TYPE(enum_class_String));
361         VTABLE_set_string_native(interp, result, CELL_STRING(cell));
362         break;
363       case PMCCELL:
364         result = CELL_PMC(cell);
365       default:
366         /* exception */
367         break;
368     }
370     return result;
375 =item C<static Hash * get_hash(PARROT_INTERP, PMC *SELF)>
377 =cut
381 PARROT_CANNOT_RETURN_NULL
382 static Hash *
383 get_hash(PARROT_INTERP, ARGIN(PMC *SELF))
385     ASSERT_ARGS(get_hash)
386     Hash   *hash;
388     GETATTR_CallContext_hash(interp, SELF, hash);
390     if (!hash) {
391         hash = parrot_create_hash(interp,
392             enum_type_ptr,
393             Hash_key_type_STRING);
395         SETATTR_CallContext_hash(interp, SELF, hash);
396     }
398     return hash;
403 =item C<static void mark_cell(PARROT_INTERP, Pcc_cell *c)>
405 =cut
409 static void
410 mark_cell(PARROT_INTERP, ARGIN(Pcc_cell *c))
412     ASSERT_ARGS(mark_cell)
413     switch (CELL_TYPE_MASK(c)) {
414         case STRINGCELL:
415             if (CELL_STRING(c))
416                 Parrot_gc_mark_STRING_alive(interp, CELL_STRING(c));
417             break;
418         case PMCCELL:
419             if (!PMC_IS_NULL(CELL_PMC(c)))
420                 Parrot_gc_mark_PMC_alive(interp, CELL_PMC(c));
421             break;
422         case INTCELL:
423         case FLOATCELL:
424         default:
425             break;
426     }
432 =item C<static void mark_positionals(PARROT_INTERP, PMC *self)>
434 =cut
438 static void
439 mark_positionals(PARROT_INTERP, ARGIN(PMC *self))
441     ASSERT_ARGS(mark_positionals)
442     INTVAL size;
444     GETATTR_CallContext_num_positionals(interp, self, size);
446     if (size) {
447         Pcc_cell *cells;
448         INTVAL i;
449         GETATTR_CallContext_positionals(interp, self, cells);
451         for (i = 0; i < size; ++i)
452             mark_cell(interp, &cells[i]);
453     }
458 =item C<static void mark_hash(PARROT_INTERP, Hash *h)>
460 =cut
464 /* don't look now, but here goes encapsulation.... */
465 static void
466 mark_hash(PARROT_INTERP, ARGIN(Hash *h))
468     ASSERT_ARGS(mark_hash)
469     parrot_hash_iterate(h,
470         Parrot_gc_mark_STRING_alive(interp, (STRING *)_bucket->key);
471         mark_cell(interp, (Pcc_cell *)_bucket->value););
476 =item C<static PMC * get_named_names(PARROT_INTERP, PMC *SELF)>
478 =cut
482 PARROT_CAN_RETURN_NULL
483 static PMC *
484 get_named_names(PARROT_INTERP, ARGIN(PMC *SELF))
486     ASSERT_ARGS(get_named_names)
487     Hash *hash;
489     GETATTR_CallContext_hash(interp, SELF, hash);
491     /* yes, this *looks* risky, but it's a Parrot STRING hash internally */
492     if (hash && hash->entries) {
493         UINTVAL j = 0;
494         PMC *result = Parrot_pmc_new_init_int(interp, enum_class_FixedStringArray, hash->entries);
495         parrot_hash_iterate(hash,
496             VTABLE_set_string_keyed_int(interp, result, j++, (STRING *)_bucket->key););
497         return result;
498     }
500     return PMCNULL;
503 #include "parrot/packfile.h"
504 #include "pmc/pmc_sub.h"
506 pmclass CallContext provides array provides hash auto_attrs {
507     /* Context attributes */
508     ATTR PMC     *caller_ctx;      /* caller context */
510     ATTR void    *registers;       /* pointer to allocated registers */
511     ATTR Regs_ni  bp;              /* pointers to FLOATVAL & INTVAL */
512     ATTR Regs_ps  bp_ps;           /* pointers to PMC & STR */
514     ATTR UINTVAL  n_regs_used[4];   /* INSP in PBC points to Sub */
515     ATTR PMC      *lex_pad;         /* LexPad PMC */
516     ATTR PMC      *outer_ctx;       /* outer context, if a closure */
518     /* new call scheme and introspective variables */
519     ATTR PMC      *current_sub;           /* the Sub we are executing */
521     /* for now use a return continuation PMC */
522     ATTR PMC      *handlers;              /* local handlers for the context */
523     ATTR PMC      *current_cont;          /* the return continuation PMC */
524     ATTR PMC      *current_object;        /* current object if a method call */
525     ATTR PMC      *current_namespace;     /* The namespace we're currently in */
526     ATTR opcode_t *current_pc;            /* program counter of Sub invocation */
527     ATTR PMC      *current_sig;           /* temporary CallContext PMC for active call */
529     /* deref the constants - we need it all the time */
530     ATTR struct PackFile_Constant *constants;
532     ATTR INTVAL                 current_HLL;     /* see also src/hll.c */
534     ATTR UINTVAL                warns;           /* Keeps track of what warnings
535                                              * have been activated */
536     ATTR UINTVAL                errors;          /* fatals that can be turned off */
537     ATTR UINTVAL                trace_flags;
538     ATTR UINTVAL                recursion_depth; /* Sub call recursion depth */
540     /* Storage for arguments */
541     ATTR struct Pcc_cell *positionals; /* array of positionals */
542     ATTR INTVAL  num_positionals;      /* count of used positionals */
543     ATTR INTVAL  allocated_positionals;/* count of allocated positionals */
545     ATTR PMC    *type_tuple;           /* Cached argument types for MDD */
546     ATTR STRING *short_sig;            /* Simple string sig args & returns */
547     ATTR PMC    *arg_flags;            /* Integer array of argument flags */
548     ATTR PMC    *return_flags;         /* Integer array of return flags */
549     ATTR Hash   *hash;                 /* Hash of named arguments */
553 =item C<void init()>
555 Initializes a newly created CallContext object.
557 =cut
561     VTABLE void init() {
562         SET_ATTR_type_tuple(INTERP, SELF, PMCNULL);
564         SET_ATTR_positionals(INTERP, SELF, NULL);
565         SET_ATTR_num_positionals(INTERP, SELF, 0);
567         PObj_custom_mark_destroy_SETALL(SELF);
568     }
572 =item C<void mark()>
574 Mark any referenced strings and PMCs.
576 =cut
579     VTABLE void mark() {
580         Hash     *hash;
581         PMC      *tmp;
582         STRING   *short_sig;
583         Pcc_cell *positionals;
584         UINTVAL  *n_regs_used;
586         if (!PMC_data(SELF))
587             return;
589         GET_ATTR_short_sig(INTERP, SELF, short_sig);
590         Parrot_gc_mark_STRING_alive(INTERP, short_sig);
592         mark_positionals(INTERP, SELF);
594         GET_ATTR_hash(INTERP, SELF, hash);
595         if (hash)
596             mark_hash(INTERP, hash);
598         GET_ATTR_arg_flags(INTERP, SELF, tmp);
599         Parrot_gc_mark_PMC_alive(INTERP, tmp);
601         GET_ATTR_return_flags(INTERP, SELF, tmp);
602         Parrot_gc_mark_PMC_alive(INTERP, tmp);
604         GET_ATTR_type_tuple(INTERP, SELF, tmp);
605         Parrot_gc_mark_PMC_alive(INTERP, tmp);
607         GET_ATTR_caller_ctx(INTERP, SELF, tmp);
608         Parrot_gc_mark_PMC_alive(INTERP, tmp);
610         GET_ATTR_lex_pad(INTERP, SELF, tmp);
611         Parrot_gc_mark_PMC_alive(INTERP, tmp);
613         GET_ATTR_outer_ctx(INTERP, SELF, tmp);
614         Parrot_gc_mark_PMC_alive(INTERP, tmp);
616         GET_ATTR_current_sub(INTERP, SELF, tmp);
617         Parrot_gc_mark_PMC_alive(INTERP, tmp);
619         GET_ATTR_handlers(INTERP, SELF, tmp);
620         Parrot_gc_mark_PMC_alive(INTERP, tmp);
622         GET_ATTR_current_cont(INTERP, SELF, tmp);
623         Parrot_gc_mark_PMC_alive(INTERP, tmp);
625         GET_ATTR_current_object(INTERP, SELF, tmp);
626         Parrot_gc_mark_PMC_alive(INTERP, tmp);
628         GET_ATTR_current_namespace(INTERP, SELF, tmp);
629         Parrot_gc_mark_PMC_alive(INTERP, tmp);
631         GET_ATTR_current_sig(INTERP, SELF, tmp);
632         Parrot_gc_mark_PMC_alive(INTERP, tmp);
634         GET_ATTR_n_regs_used(INTERP, SELF, n_regs_used);
636         if (n_regs_used) {
637             Regs_ps         bp_ps;
638             const UINTVAL   regs_p = n_regs_used[REGNO_PMC];
639             const UINTVAL   regs_s = n_regs_used[REGNO_STR];
640             UINTVAL         i;
642             GET_ATTR_bp_ps(INTERP, SELF, bp_ps);
643             for (i = 0; i < regs_p; ++i) {
644                 PMC * const p = bp_ps.regs_p[-1L-(i)];
645                 /* Original code from CTX_REG_PMC */
646                 if (p)
647                     Parrot_gc_mark_PMC_alive(INTERP, p);
648             }
650             for (i = 0; i < regs_s; ++i) {
651                 STRING * const s = bp_ps.regs_s[i];
652                 if (s)
653                     Parrot_gc_mark_STRING_alive(INTERP, s);
654             }
655         }
656     }
660 =item C<void morph(PMC *type)>
662 Morph the call signature into a return signature. (Currenly ignores
663 the type passed in, and resets the named and positional arguments
664 stored.)
666 =cut
669     VTABLE void morph(PMC *type) {
670         Hash     *hash;
672         if (!PMC_data(SELF))
673             return;
675         SET_ATTR_short_sig(INTERP, SELF, NULL);
676         SET_ATTR_arg_flags(INTERP, SELF, PMCNULL);
677         SET_ATTR_return_flags(INTERP, SELF, PMCNULL);
678         SET_ATTR_type_tuple(INTERP, SELF, PMCNULL);
680         /* Don't free positionals. Just reuse them */
681         SET_ATTR_num_positionals(INTERP, SELF, 0);
683         GET_ATTR_hash(INTERP, SELF, hash);
685         if (hash) {
686             parrot_hash_iterate(hash,
687                FREE_CELL(INTERP, (Pcc_cell *)_bucket->value););
688             parrot_hash_destroy(INTERP, hash);
689             SET_ATTR_hash(INTERP, SELF, NULL);
690         }
691     }
693     VTABLE void destroy() {
694         INTVAL    allocated_positionals;
695         Hash     *hash;
697         if (!PMC_data(SELF))
698             return;
700         GET_ATTR_hash(INTERP, SELF, hash);
701         GET_ATTR_allocated_positionals(INTERP, SELF, allocated_positionals);
703         if (allocated_positionals) {
704             Pcc_cell *c;
706             GET_ATTR_positionals(INTERP, SELF, c);
707             if (allocated_positionals > 8)
708                 Parrot_gc_free_memory_chunk(INTERP, c);
709             else
710                 Parrot_gc_free_fixed_size_storage(INTERP,
711                     allocated_positionals * sizeof (Pcc_cell), c);
712         }
714         if (hash) {
715             parrot_hash_iterate(hash,
716                 FREE_CELL(INTERP, (Pcc_cell *)_bucket->value););
717             parrot_hash_destroy(INTERP, hash);
718         }
720         Parrot_pcc_free_registers(INTERP, SELF);
721     }
725 =item C<void set_string_native(STRING *value)>
727 Sets the short signature for the CallContext.
729 =cut
733     VTABLE void set_string_native(STRING *value) {
734         SET_ATTR_short_sig(INTERP, SELF, value);
735     }
739 =item C<STRING *get_string()>
741 Returns the short signature for the CallContext.
743 =cut
747     VTABLE STRING *get_string() {
748         STRING   *res;
749         Pcc_cell *c;
750         INTVAL    num_positionals, i;
752         GET_ATTR_short_sig(INTERP, SELF, res);
754         if (res)
755             return res;
757         GET_ATTR_positionals(INTERP, SELF, c);
758         GET_ATTR_num_positionals(INTERP, SELF, num_positionals);
760         res = Parrot_str_new(INTERP, NULL, num_positionals);
762         for (i = 0; i < num_positionals; ++i) {
763             switch (c[i].type) {
764               case INTCELL:
765                 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, "I"));
766                 break;
767               case FLOATCELL:
768                 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, "N"));
769                 break;
770               case STRINGCELL:
771                 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, "S"));
772                 break;
773               case PMCCELL:
774                 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, "P"));
775                 break;
776               default:
777                 PARROT_FAILURE("Impossible flag");
778                 break;
779             }
780         }
781         /* TODO Add named args to signature */
782         /* After fixind build_MMD_type_tuple to use raw arguments instead of signature */
784         SET_ATTR_short_sig(INTERP, SELF, res);
786         return res;
787     }
791 =item C<void set_pmc(PMC *value)>
793 Sets a fixed-size array of integer types (a type tuple) for the CallContext.
795 =cut
799     VTABLE void set_pmc(PMC *value) {
800         SET_ATTR_type_tuple(INTERP, SELF, value);
801     }
805 =item C<PMC *get_pmc()>
807 Returns a fixed-size array of integer types (a type tuple) for the
808 CallContext.
810 =cut
814     VTABLE PMC *get_pmc() {
815         PMC *type_tuple;
817         GET_ATTR_type_tuple(INTERP, SELF, type_tuple);
819         if (PMC_IS_NULL(type_tuple)) {
820             Pcc_cell *c;
821             INTVAL    num_positionals;
822             INTVAL    i = 0;
824             GET_ATTR_positionals(INTERP, SELF, c);
825             GET_ATTR_num_positionals(INTERP, SELF, num_positionals);
827             type_tuple = Parrot_pmc_new_init_int(INTERP,
828                 enum_class_FixedIntegerArray, num_positionals);
830             for (i = 0; i < num_positionals; ++i) {
831                 INTVAL type;
833                 switch (c[i].type) {
834                     case INTCELL:    type = enum_type_INTVAL;   break;
835                     case FLOATCELL:  type = enum_type_FLOATVAL; break;
836                     case STRINGCELL: type = enum_type_STRING;   break;
837                     case PMCCELL:
838                         type = PMC_IS_NULL(c[i].u.p)
839                              ? (INTVAL) enum_type_PMC
840                              : VTABLE_type(INTERP, c[i].u.p);
841                         break;
842                     default:
843                         Parrot_ex_throw_from_c_args(INTERP, NULL,
844                             EXCEPTION_INVALID_OPERATION,
845                             "Multiple Dispatch: invalid argument type!");
846                 }
848                 VTABLE_set_integer_keyed_int(INTERP, type_tuple, i, type);
849             }
851             SET_ATTR_type_tuple(INTERP, SELF, type_tuple);
852         }
854         return type_tuple;
855     }
860 =item C<void set_attr_str(STRING *key, PMC *value)>
862 Set a PMC value for an attribute by string name.
864 =over
866 =item results
868 Stores the return signature, an array of PMCs.
870 =item arg_flags
872 Stores a set of flags for the call signature arguments, an array of
873 integers.
875 =item return_flags
877 Stores a set of flags for the call signature return arguments, an array
878 of integers.
880 =back
882 =cut
886     VTABLE void set_attr_str(STRING *key, PMC *value) {
888         if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "arg_flags"))) {
889             SET_ATTR_arg_flags(INTERP, SELF, value);
890         }
891         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "return_flags"))) {
892             SET_ATTR_return_flags(INTERP, SELF, value);
893         }
894         else
895             Parrot_ex_throw_from_c_args(INTERP, NULL,
896                 EXCEPTION_ATTRIB_NOT_FOUND, "No such attribute '%S'", key);
897     }
901 =item C<PMC *get_attr_str(STRING *key)>
903 Get a PMC value for an attribute by string name.
905 =over
907 =item results
909 Retrieves the return signature, an array of PMCs.
911 =item arg_flags
913 Retrieves the flags for the call signature arguments, an array of
914 integers.
916 =item return_flags
918 Retrieves the flags for the call signature return arguments, an array of
919 integers.
921 =item named
923 Retrieves the hash of named arguments.
925 =item caller_ctx
927 return Caller Context
929 =item lex_pad
931 return LexPad
933 =item outer_ctx
935 return Outer Context
937 =item current_sub
939 return current Sub
941 =item handlers
943 return list of ExceptioHandlers
945 =item current_cont
947 return current Continuation
949 =item current_object
951 return current Object (if in method call)
953 =item current_namespace
955 return current Namespace
957 =back
959 =cut
963     VTABLE PMC *get_attr_str(STRING *key) {
964         PMC    *value = PMCNULL;
965         INTVAL  hll;
967         if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "named")))
968             value = get_named_names(INTERP, SELF);
969         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "arg_flags")))
970             GET_ATTR_arg_flags(INTERP, SELF, value);
971         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "return_flags")))
972             GET_ATTR_return_flags(INTERP, SELF, value);
973         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "caller_ctx")))
974             GET_ATTR_caller_ctx(INTERP, SELF, value);
975         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "lex_pad")))
976             GET_ATTR_lex_pad(INTERP, SELF, value);
977         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "outer_ctx")))
978             GET_ATTR_outer_ctx(INTERP, SELF, value);
979         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "current_sub")))
980             GET_ATTR_current_sub(INTERP, SELF, value);
981         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "current_cont")))
982             GET_ATTR_current_cont(INTERP, SELF, value);
983         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "current_object")))
984             GET_ATTR_current_object(INTERP, SELF, value);
985         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "current_namespace")))
986             GET_ATTR_current_namespace(INTERP, SELF, value);
987         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "handlers")))
988             GET_ATTR_handlers(INTERP, SELF, value);
989         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "current_HLL"))) {
990             GET_ATTR_current_HLL(INTERP, SELF, hll);
991             value = Parrot_pmc_new(interp, Parrot_get_ctx_HLL_type(interp, enum_class_Integer));
992             VTABLE_set_integer_native(interp, value, hll);
993         }
994         else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "current_hll"))) {
995             GET_ATTR_current_HLL(INTERP, SELF, hll);
996             value = Parrot_pmc_new(interp, Parrot_get_ctx_HLL_type(interp, enum_class_String));
997             VTABLE_set_string_native(interp, value, Parrot_get_HLL_name(INTERP, hll));
998         }
999         else
1000             Parrot_ex_throw_from_c_args(INTERP, NULL,
1001                 EXCEPTION_ATTRIB_NOT_FOUND, "No such attribute '%S'", key);
1003         return value;
1004     }
1006     VTABLE INTVAL elements() {
1007         INTVAL num_positionals;
1009         if (!PMC_data(SELF))
1010             return 0;
1012         GET_ATTR_num_positionals(INTERP, SELF, num_positionals);
1014         return num_positionals;
1015     }
1017     VTABLE void push_integer(INTVAL value) {
1018         Pcc_cell *cells;
1019         INTVAL    num_pos, allocated_positionals;
1021         GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1022         GET_ATTR_allocated_positionals(INTERP, SELF, allocated_positionals);
1024         if (num_pos + 1 > allocated_positionals)
1025             ensure_positionals_storage_ap(INTERP, SELF, num_pos + 1, allocated_positionals);
1027         GET_ATTR_positionals(INTERP, SELF, cells);
1028         cells[num_pos].u.i      = value;
1029         cells[num_pos].type     = INTCELL;
1030         SET_ATTR_num_positionals(INTERP, SELF, num_pos + 1);
1031     }
1033     VTABLE void push_float(FLOATVAL value) {
1034         Pcc_cell *cells;
1035         INTVAL    num_pos;
1037         GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1038         ensure_positionals_storage(INTERP, SELF, num_pos + 1);
1040         GET_ATTR_positionals(INTERP, SELF, cells);
1041         cells[num_pos].u.n      = value;
1042         cells[num_pos].type     = FLOATCELL;
1043         SET_ATTR_num_positionals(INTERP, SELF, num_pos + 1);
1044     }
1046     VTABLE void push_string(STRING *value) {
1047         Pcc_cell *cells;
1048         INTVAL    num_pos;
1050         GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1051         ensure_positionals_storage(INTERP, SELF, num_pos + 1);
1053         GET_ATTR_positionals(INTERP, SELF, cells);
1054         cells[num_pos].u.s      = value;
1055         cells[num_pos].type     = STRINGCELL;
1056         SET_ATTR_num_positionals(INTERP, SELF, num_pos + 1);
1057     }
1059     VTABLE void push_pmc(PMC *value) {
1060         Pcc_cell *cells;
1061         INTVAL    num_pos, allocated_positionals;
1063         GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1064         GET_ATTR_allocated_positionals(INTERP, SELF, allocated_positionals);
1066         if (num_pos + 1 > allocated_positionals)
1067             ensure_positionals_storage_ap(INTERP, SELF, num_pos + 1, allocated_positionals);
1069         GET_ATTR_positionals(INTERP, SELF, cells);
1070         cells[num_pos].u.p      = value;
1071         cells[num_pos].type     = PMCCELL;
1072         SET_ATTR_num_positionals(INTERP, SELF, num_pos + 1);
1073     }
1075     /*
1076         TODO It's very naive implementation. But we do unshift _once_ only.
1077         So, for speed sake, allocate _one_ Cell upfront. Or store it independent.
1078     */
1080     VTABLE void unshift_pmc(PMC *value) {
1081         Pcc_cell *cells;
1082         const INTVAL size = STATICSELF.elements();
1083         INTVAL    i;
1085         ensure_positionals_storage(INTERP, SELF, size + 1);
1086         GET_ATTR_positionals(INTERP, SELF, cells);
1088         for (i = size; i; --i)
1089             cells[i] = cells[i - 1];
1091         cells[0].u.p    = value;
1092         cells[0].type   = PMCCELL;
1093         SET_ATTR_num_positionals(INTERP, SELF, size + 1);
1094     }
1096     VTABLE PMC * shift_pmc() {
1097         Pcc_cell *cells;
1098         PMC      *retval;
1099         const INTVAL size = STATICSELF.elements();
1100         INTVAL    i, type;
1102         if (size < 1)
1103             Parrot_ex_throw_from_c_args(INTERP, NULL,
1104                 EXCEPTION_INVALID_OPERATION,
1105                 "Cannot shift PMC from empty CallContext");
1107         GET_ATTR_positionals(INTERP, SELF, cells);
1108         type   = CELL_TYPE_MASK(&cells[0]);
1109         retval = autobox_pmc(INTERP, &cells[0], type);
1111         for (i = 1; i < size; ++i)
1112             cells[i - 1] = cells[i];
1114         SET_ATTR_num_positionals(INTERP, SELF, size - 1);
1115         return retval;
1116     }
1118     VTABLE STRING * shift_string() {
1119         Pcc_cell *cells;
1120         STRING   *retval;
1121         const INTVAL size = STATICSELF.elements();
1122         INTVAL    i;
1124         if (size < 1)
1125             Parrot_ex_throw_from_c_args(INTERP, NULL,
1126                 EXCEPTION_INVALID_OPERATION,
1127                 "Cannot shift PMC from empty CallContext");
1129         GET_ATTR_positionals(INTERP, SELF, cells);
1130         retval = autobox_string(INTERP, &cells[0]);
1132         for (i = 1; i < size; ++i)
1133             cells[i - 1] = cells[i];
1135         SET_ATTR_num_positionals(INTERP, SELF, size - 1);
1136         return retval;
1137     }
1139     VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
1140         Pcc_cell *cells;
1141         INTVAL    num_pos;
1143         GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1144         if (key >= num_pos || key < 0)
1145             return 0;
1147         GET_ATTR_positionals(INTERP, SELF, cells);
1148         return autobox_intval(INTERP, &cells[key]);
1149     }
1151     VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
1152         Pcc_cell *cells;
1153         INTVAL    num_pos;
1155         GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1156         if (key >= num_pos || key < 0)
1157             return 0.0;
1159         GET_ATTR_positionals(INTERP, SELF, cells);
1160         return autobox_floatval(INTERP, &cells[key]);
1161     }
1163     VTABLE STRING * get_string_keyed_int(INTVAL key) {
1164         Pcc_cell *cells;
1165         INTVAL    num_pos;
1167         GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1168         if (key >= num_pos || key < 0)
1169             return NULL;
1171         GET_ATTR_positionals(INTERP, SELF, cells);
1172         return autobox_string(INTERP, &cells[key]);
1173     }
1175     VTABLE PMC * get_pmc_keyed_int(INTVAL key) {
1176         Pcc_cell *cells;
1177         INTVAL    num_pos, type;
1179         GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1180         if (key >= num_pos || key < 0)
1181             return PMCNULL;
1183         GET_ATTR_positionals(INTERP, SELF, cells);
1184         type = CELL_TYPE_MASK(&cells[key]);
1185         if (type == PMCCELL)
1186             return CELL_PMC(&cells[key]);
1187         return autobox_pmc(INTERP, &cells[key], type);
1188     }
1190     VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
1191         Pcc_cell * const cell = get_cell_at(INTERP, SELF, key);
1192         INTVAL    pos;
1194         cell->u.i   = value;
1195         cell->type  = INTCELL;
1197         GET_ATTR_num_positionals(INTERP, SELF, pos);
1198         if (pos <= key)
1199             SET_ATTR_num_positionals(INTERP, SELF, key + 1);
1200     }
1202     VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
1203         Pcc_cell * const cell = get_cell_at(INTERP, SELF, key);
1204         INTVAL    pos;
1206         cell->u.n   = value;
1207         cell->type  = FLOATCELL;
1209         GET_ATTR_num_positionals(INTERP, SELF, pos);
1210         if (pos <= key)
1211             SET_ATTR_num_positionals(INTERP, SELF, key + 1);
1212     }
1214     VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
1215         Pcc_cell * const cell = get_cell_at(INTERP, SELF, key);
1216         INTVAL    pos;
1218         cell->u.s   = value;
1219         cell->type  = STRINGCELL;
1221         GET_ATTR_num_positionals(INTERP, SELF, pos);
1222         if (pos <= key)
1223             SET_ATTR_num_positionals(INTERP, SELF, key + 1);
1224     }
1226     VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) {
1227         INTVAL    pos;
1228         Pcc_cell * const cell = get_cell_at(INTERP, SELF, key);
1230         cell->u.p   = value;
1231         cell->type  = PMCCELL;
1233         GET_ATTR_num_positionals(INTERP, SELF, pos);
1234         if (pos <= key)
1235             SET_ATTR_num_positionals(INTERP, SELF, key + 1);
1236     }
1238     VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
1239         Hash     * const hash = get_hash(INTERP, SELF);
1240         Pcc_cell *cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, (void *)key);
1242         if (!cell) {
1243             cell = ALLOC_CELL(INTERP);
1244             parrot_hash_put(INTERP, hash, (void *)key, (void *)cell);
1245         }
1247         cell->u.i       = value;
1248         cell->type      = INTCELL;
1249     }
1251     VTABLE void set_number_keyed_str(STRING *key, FLOATVAL value) {
1252         Hash     * const hash = get_hash(INTERP, SELF);
1253         Pcc_cell *cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, (void *)key);
1255         if (!cell) {
1256             cell = ALLOC_CELL(INTERP);
1257             parrot_hash_put(INTERP, hash, (void *)key, (void *)cell);
1258         }
1260         cell->u.n       = value;
1261         cell->type      = FLOATCELL;
1262     }
1264     VTABLE void set_string_keyed_str(STRING *key, STRING *value) {
1265         Hash     * const hash = get_hash(INTERP, SELF);
1266         Pcc_cell *cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, (void *)key);
1268         if (!cell) {
1269             cell = ALLOC_CELL(INTERP);
1270             parrot_hash_put(INTERP, hash, (void *)key, (void *)cell);
1271         }
1273         cell->u.s       = value;
1274         cell->type      = STRINGCELL;
1275     }
1277     VTABLE void set_pmc_keyed_str(STRING *key, PMC *value) {
1278         Hash     * const hash = get_hash(INTERP, SELF);
1279         Pcc_cell *cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, (void *)key);
1281         if (!cell) {
1282             cell = ALLOC_CELL(INTERP);
1283             parrot_hash_put(INTERP, hash, (void *)key, (void *)cell);
1284         }
1286         cell->u.p       = value;
1287         cell->type      = PMCCELL;
1288     }
1290     VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
1291         Hash     * const hash = get_hash(INTERP, SELF);
1292         void     * const k    = hash_key_from_pmc(INTERP, hash, key);
1293         Pcc_cell *cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1295         if (!cell) {
1296             cell = ALLOC_CELL(INTERP);
1297             parrot_hash_put(INTERP, hash, k, (void *)cell);
1298         }
1300         cell->u.i       = value;
1301         cell->type      = INTCELL;
1302     }
1304     VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
1305         Hash     * const hash = get_hash(INTERP, SELF);
1306         void     * const k    = hash_key_from_pmc(INTERP, hash, key);
1307         Pcc_cell *cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1309         if (!cell) {
1310             cell = ALLOC_CELL(INTERP);
1311             parrot_hash_put(INTERP, hash, k, (void *)cell);
1312         }
1314         cell->u.n       = value;
1315         cell->type      = FLOATCELL;
1316     }
1318     VTABLE void set_string_keyed(PMC *key, STRING *value) {
1319         Hash     * const hash = get_hash(INTERP, SELF);
1320         void     * const k    = hash_key_from_pmc(INTERP, hash, key);
1321         Pcc_cell *cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1323         if (!cell) {
1324             cell = ALLOC_CELL(INTERP);
1325             parrot_hash_put(INTERP, hash, k, (void *)cell);
1326         }
1328         cell->u.s       = value;
1329         cell->type      = STRINGCELL;
1330     }
1332     VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
1333         Hash     * const hash = get_hash(INTERP, SELF);
1334         void     * const k    = hash_key_from_pmc(INTERP, hash, key);
1335         Pcc_cell *cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1337         if (!cell) {
1338             cell = ALLOC_CELL(INTERP);
1339             parrot_hash_put(INTERP, hash, k, (void *)cell);
1340         }
1342         cell->u.p       = value;
1343         cell->type      = PMCCELL;
1344     }
1346     VTABLE INTVAL get_integer_keyed_str(STRING *key) {
1347         Hash *hash;
1348         GETATTR_CallContext_hash(INTERP, SELF, hash);
1350         if (hash) {
1351             void     * const k    = hash_key_from_string(INTERP, hash, key);
1352             Pcc_cell * const cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1354             if (cell)
1355                 return autobox_intval(INTERP, cell);
1356         }
1358         return 0;
1359     }
1361     VTABLE FLOATVAL get_number_keyed_str(STRING *key) {
1362         Hash *hash;
1363         GETATTR_CallContext_hash(INTERP, SELF, hash);
1365         if (hash) {
1366             void     * const k    = hash_key_from_string(INTERP, hash, key);
1367             Pcc_cell * const cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1369             if (cell)
1370                 return autobox_floatval(INTERP, cell);
1371         }
1373         return 0.0;
1374     }
1377     VTABLE STRING * get_string_keyed_str(STRING *key) {
1378         Hash *hash;
1379         GETATTR_CallContext_hash(INTERP, SELF, hash);
1381         if (hash) {
1382             void     * const k    = hash_key_from_string(INTERP, hash, key);
1383             Pcc_cell * const cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1385             if (cell)
1386                 return autobox_string(INTERP, cell);
1387         }
1389         return NULL;
1390     }
1392     VTABLE PMC * get_pmc_keyed_str(STRING *key) {
1393         Hash *hash;
1394         GETATTR_CallContext_hash(INTERP, SELF, hash);
1396         if (hash) {
1397             void     * const k    = hash_key_from_string(INTERP, hash, key);
1398             Pcc_cell * const cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1400             if (cell) {
1401                 INTVAL type = CELL_TYPE_MASK(cell);
1402                 if (type == PMCCELL)
1403                     return CELL_PMC(cell);
1404                 return autobox_pmc(INTERP, cell, type);
1405             }
1406         }
1408         return PMCNULL;
1409     }
1411     VTABLE INTVAL get_integer_keyed(PMC *key) {
1412         Hash *hash;
1413         GETATTR_CallContext_hash(INTERP, SELF, hash);
1415         if (hash) {
1416             void     * const k    = hash_key_from_pmc(INTERP, hash, key);
1417             Pcc_cell * const cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1419             if (cell)
1420                 return autobox_intval(INTERP, cell);
1421         }
1423         return 0;
1424     }
1426     VTABLE FLOATVAL get_number_keyed(PMC *key) {
1427         Hash *hash;
1428         GETATTR_CallContext_hash(INTERP, SELF, hash);
1430         if (hash) {
1431             void     * const k    = hash_key_from_pmc(INTERP, hash, key);
1432             Pcc_cell * const cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1434             if (cell)
1435                 return autobox_floatval(INTERP, cell);
1436         }
1438         return 0.0;
1439     }
1441     VTABLE STRING * get_string_keyed(PMC *key) {
1442         Hash *hash;
1443         GETATTR_CallContext_hash(INTERP, SELF, hash);
1445         if (hash) {
1446             void     * const k    = hash_key_from_pmc(INTERP, hash, key);
1447             Pcc_cell * const cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1449             if (cell)
1450                 return autobox_string(INTERP, cell);
1451         }
1453         return NULL;
1454     }
1456     VTABLE PMC * get_pmc_keyed(PMC *key) {
1457         Hash *hash;
1458         GETATTR_CallContext_hash(INTERP, SELF, hash);
1460         if (hash) {
1461             void     * const k    = hash_key_from_pmc(INTERP, hash, key);
1462             Pcc_cell * const cell = (Pcc_cell *)parrot_hash_get(INTERP, hash, k);
1464             if (cell) {
1465                 INTVAL type = CELL_TYPE_MASK(cell);
1466                 if (type == PMCCELL)
1467                     return CELL_PMC(cell);
1468                 return autobox_pmc(INTERP, cell, type);
1469             }
1470         }
1472         return PMCNULL;
1473     }
1475     VTABLE INTVAL exists_keyed(PMC *key) {
1476         Hash *hash;
1477         GETATTR_CallContext_hash(INTERP, SELF, hash);
1479         if (hash) {
1480             void * const k = hash_key_from_pmc(INTERP, hash, key);
1481             return parrot_hash_exists(INTERP, hash, k);
1482         }
1484         return 0;
1485     }
1487     VTABLE INTVAL exists_keyed_str(STRING *key) {
1488         Hash *hash;
1489         GETATTR_CallContext_hash(INTERP, SELF, hash);
1491         if (hash) {
1492             void * const k = hash_key_from_string(INTERP, hash, key);
1493             return parrot_hash_exists(INTERP, hash, k);
1494         }
1496         return 0;
1497     }
1499     VTABLE INTVAL exists_keyed_int(INTVAL key) {
1500         INTVAL num_positionals;
1502         GET_ATTR_num_positionals(INTERP, SELF, num_positionals);
1504         if (num_positionals)
1505             return key < num_positionals;
1507         return 0;
1508     }
1512 =item C<PMC *clone()>
1514 Creates and returns a clone of the signature.
1516 =cut
1519     VTABLE PMC *clone() {
1520         STRING      *short_sig;
1521         PMC         *type_tuple, *arg_flags, *return_flags;
1522         PMC * const  dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
1523         INTVAL       num;
1524         Pcc_cell    *our_cells, *dest_cells;
1525         Hash        *hash;
1527         GET_ATTR_num_positionals(INTERP, SELF, num);
1528         /* Copy positionals */
1529         ensure_positionals_storage(INTERP, dest, num);
1530         GET_ATTR_positionals(INTERP, SELF, our_cells);
1531         GET_ATTR_positionals(INTERP, dest, dest_cells);
1532         memcpy(dest_cells, our_cells, num * sizeof (Pcc_cell));
1533         SET_ATTR_num_positionals(INTERP, dest, num);
1535         GET_ATTR_type_tuple(INTERP, SELF, type_tuple);
1536         GET_ATTR_short_sig(INTERP, SELF, short_sig);
1537         GET_ATTR_arg_flags(INTERP, SELF, arg_flags);
1538         GET_ATTR_return_flags(INTERP, SELF, return_flags);
1540         GET_ATTR_hash(INTERP, SELF, hash);
1542         if (!PMC_IS_NULL(type_tuple))
1543             SET_ATTR_type_tuple(INTERP, dest, VTABLE_clone(INTERP, type_tuple));
1545         if (short_sig)
1546             SET_ATTR_short_sig(INTERP, dest, short_sig);
1548         if (!PMC_IS_NULL(arg_flags))
1549             SET_ATTR_arg_flags(INTERP, dest, VTABLE_clone(INTERP, arg_flags));
1551         if (!PMC_IS_NULL(return_flags))
1552             SET_ATTR_return_flags(INTERP, dest, VTABLE_clone(INTERP, return_flags));
1554         if (hash)
1555             parrot_hash_clone(INTERP, hash, get_hash(INTERP, dest));
1557         return dest;
1558     }
1562 =item C<PMC *backtrace>
1564 Gets a representation of the backtrace starting from this Context.
1565 Returns an array of hashes. Each array element represents a caller in
1566 the backtrace, the most recent caller first. The hash has two keys: C<sub>,
1567 which holds the PMC representing the sub, and C<annotations> which is a hash
1568 of the annotations at the point where the exception was thrown for the current
1569 sub, or for the point of the call a level deeper for the rest.
1571 =cut
1575     METHOD backtrace(PMC *resume :optional, INTVAL has_resume :opt_flag) {
1576         PMC *result  = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
1577         PMC *cur_ctx = SELF;
1578         Parrot_Continuation_attributes * const cont = has_resume ? PMC_cont(resume) : NULL;
1580         /* Get starting context, then loop over them. */
1581         while (cur_ctx) {
1582             PMC        * const frame       = Parrot_pmc_new(INTERP, enum_class_Hash);
1583             PMC        *annotations = NULL;
1584             Parrot_Sub_attributes *sub;
1586             /* Get sub and put it in the hash. */
1587             PMC *sub_pmc = Parrot_pcc_get_sub(INTERP, cur_ctx);
1589             if (!sub_pmc)
1590                 sub_pmc = PMCNULL;
1592             VTABLE_set_pmc_keyed_str(INTERP, frame, CONST_STRING(INTERP, "sub"), sub_pmc);
1594             /* Look up any annotations and put them in the hash. */
1595             if (!PMC_IS_NULL(sub_pmc)) {
1596                 PMC_get_sub(INTERP, sub_pmc, sub);
1598                 if (sub->seg->annotations) {
1599                     PackFile_ByteCode *seg = sub->seg;
1600                     opcode_t          *pc  = cont && cur_ctx == cont->to_ctx
1601                                              ? cont->address
1602                                              : Parrot_pcc_get_pc(INTERP, cur_ctx);
1604                     annotations = PackFile_Annotations_lookup(INTERP,
1605                         seg->annotations, pc - seg->base.data,
1606                         NULL);
1607                 }
1608             }
1610             if (!annotations)
1611                 annotations = Parrot_pmc_new(INTERP, enum_class_Hash);
1613             VTABLE_set_pmc_keyed_str(INTERP, frame, CONST_STRING(INTERP, "annotations"), annotations);
1615             /* Push frame and go to next caller. */
1616             VTABLE_push_pmc(INTERP, result, frame);
1617             cur_ctx = Parrot_pcc_get_caller_ctx(INTERP, cur_ctx);
1618         }
1620         RETURN(PMC *result);
1621     }
1624 =back
1626 =cut
1630 } /* end pmclass */
1633  * Local variables:
1634  *   c-file-style: "parrot"
1635  * End:
1636  * vim: expandtab shiftwidth=4:
1637  */