2 Copyright (C) 2008-2010, Parrot Foundation.
7 src/pmc/callcontext.pmc - CallContext PMC
11 The CallContext PMC is used to store the argument list and argument meta
12 information for a multiple dispatch call.
22 typedef struct Pcc_cell
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,
79 __attribute__nonnull__(1)
80 __attribute__nonnull__(2);
82 static void ensure_positionals_storage_ap(PARROT_INTERP,
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
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)
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)>
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;
198 GETATTR_CallContext_positionals(interp, self, array);
201 new_array = (Pcc_cell *)Parrot_gc_allocate_memory_chunk(interp,
202 size * sizeof (Pcc_cell));
204 new_array = (Pcc_cell *)Parrot_gc_allocate_fixed_size_storage(interp,
205 size * sizeof (Pcc_cell));
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);
214 Parrot_gc_free_fixed_size_storage(interp,
215 allocated_positionals * sizeof (Pcc_cell), array);
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)>
230 PARROT_CANNOT_RETURN_NULL
232 get_cell_at(PARROT_INTERP, ARGIN(PMC *self), INTVAL key)
234 ASSERT_ARGS(get_cell_at)
236 ensure_positionals_storage(interp, self, key + 1);
237 GETATTR_CallContext_positionals(interp, self, cells);
243 =item C<static INTVAL autobox_intval(PARROT_INTERP, const Pcc_cell *cell)>
250 autobox_intval(PARROT_INTERP, ARGIN(const Pcc_cell *cell))
252 ASSERT_ARGS(autobox_intval)
253 switch (CELL_TYPE_MASK(cell)) {
255 return CELL_INT(cell);
257 return (INTVAL)CELL_FLOAT(cell);
259 return CELL_STRING(cell) ? Parrot_str_to_int(interp, CELL_STRING(cell)) : 0;
261 return PMC_IS_NULL(CELL_PMC(cell))
263 : VTABLE_get_integer(interp, CELL_PMC(cell));
274 =item C<static FLOATVAL autobox_floatval(PARROT_INTERP, const Pcc_cell *cell)>
281 autobox_floatval(PARROT_INTERP, ARGIN(const Pcc_cell *cell))
283 ASSERT_ARGS(autobox_floatval)
284 switch (CELL_TYPE_MASK(cell)) {
286 return (FLOATVAL)CELL_INT(cell);
288 return CELL_FLOAT(cell);
290 return CELL_STRING(cell) ? Parrot_str_to_num(interp, CELL_STRING(cell)) : 0.0;
292 return PMC_IS_NULL(CELL_PMC(cell))
294 : VTABLE_get_number(interp, CELL_PMC(cell));
305 =item C<static STRING * autobox_string(PARROT_INTERP, const Pcc_cell *cell)>
311 PARROT_CANNOT_RETURN_NULL
313 autobox_string(PARROT_INTERP, ARGIN(const Pcc_cell *cell))
315 ASSERT_ARGS(autobox_string)
316 switch (CELL_TYPE_MASK(cell)) {
318 return Parrot_str_from_int(interp, CELL_INT(cell));
320 return Parrot_str_from_num(interp, CELL_FLOAT(cell));
322 return CELL_STRING(cell);
324 return PMC_IS_NULL(CELL_PMC(cell))
326 : VTABLE_get_string(interp, CELL_PMC(cell));
337 =item C<static PMC * autobox_pmc(PARROT_INTERP, Pcc_cell *cell, INTVAL type)>
343 PARROT_CANNOT_RETURN_NULL
345 autobox_pmc(PARROT_INTERP, ARGIN(Pcc_cell *cell), INTVAL type)
347 ASSERT_ARGS(autobox_pmc)
348 PMC *result = PMCNULL;
352 result = Parrot_pmc_new(interp, HLL_TYPE(enum_class_Integer));
353 VTABLE_set_integer_native(interp, result, CELL_INT(cell));
356 result = Parrot_pmc_new(interp, HLL_TYPE(enum_class_Float));
357 VTABLE_set_number_native(interp, result, CELL_FLOAT(cell));
360 result = Parrot_pmc_new(interp, HLL_TYPE(enum_class_String));
361 VTABLE_set_string_native(interp, result, CELL_STRING(cell));
364 result = CELL_PMC(cell);
375 =item C<static Hash * get_hash(PARROT_INTERP, PMC *SELF)>
381 PARROT_CANNOT_RETURN_NULL
383 get_hash(PARROT_INTERP, ARGIN(PMC *SELF))
385 ASSERT_ARGS(get_hash)
388 GETATTR_CallContext_hash(interp, SELF, hash);
391 hash = parrot_create_hash(interp,
393 Hash_key_type_STRING);
395 SETATTR_CallContext_hash(interp, SELF, hash);
403 =item C<static void mark_cell(PARROT_INTERP, Pcc_cell *c)>
410 mark_cell(PARROT_INTERP, ARGIN(Pcc_cell *c))
412 ASSERT_ARGS(mark_cell)
413 switch (CELL_TYPE_MASK(c)) {
416 Parrot_gc_mark_STRING_alive(interp, CELL_STRING(c));
419 if (!PMC_IS_NULL(CELL_PMC(c)))
420 Parrot_gc_mark_PMC_alive(interp, CELL_PMC(c));
432 =item C<static void mark_positionals(PARROT_INTERP, PMC *self)>
439 mark_positionals(PARROT_INTERP, ARGIN(PMC *self))
441 ASSERT_ARGS(mark_positionals)
444 GETATTR_CallContext_num_positionals(interp, self, size);
449 GETATTR_CallContext_positionals(interp, self, cells);
451 for (i = 0; i < size; ++i)
452 mark_cell(interp, &cells[i]);
458 =item C<static void mark_hash(PARROT_INTERP, Hash *h)>
464 /* don't look now, but here goes encapsulation.... */
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)>
482 PARROT_CAN_RETURN_NULL
484 get_named_names(PARROT_INTERP, ARGIN(PMC *SELF))
486 ASSERT_ARGS(get_named_names)
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) {
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););
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 */
555 Initializes a newly created CallContext object.
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);
574 Mark any referenced strings and PMCs.
583 Pcc_cell *positionals;
584 UINTVAL *n_regs_used;
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);
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);
638 const UINTVAL regs_p = n_regs_used[REGNO_PMC];
639 const UINTVAL regs_s = n_regs_used[REGNO_STR];
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 */
647 Parrot_gc_mark_PMC_alive(INTERP, p);
650 for (i = 0; i < regs_s; ++i) {
651 STRING * const s = bp_ps.regs_s[i];
653 Parrot_gc_mark_STRING_alive(INTERP, s);
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
669 VTABLE void morph(PMC *type) {
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);
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);
693 VTABLE void destroy() {
694 INTVAL allocated_positionals;
700 GET_ATTR_hash(INTERP, SELF, hash);
701 GET_ATTR_allocated_positionals(INTERP, SELF, allocated_positionals);
703 if (allocated_positionals) {
706 GET_ATTR_positionals(INTERP, SELF, c);
707 if (allocated_positionals > 8)
708 Parrot_gc_free_memory_chunk(INTERP, c);
710 Parrot_gc_free_fixed_size_storage(INTERP,
711 allocated_positionals * sizeof (Pcc_cell), c);
715 parrot_hash_iterate(hash,
716 FREE_CELL(INTERP, (Pcc_cell *)_bucket->value););
717 parrot_hash_destroy(INTERP, hash);
720 Parrot_pcc_free_registers(INTERP, SELF);
725 =item C<void set_string_native(STRING *value)>
727 Sets the short signature for the CallContext.
733 VTABLE void set_string_native(STRING *value) {
734 SET_ATTR_short_sig(INTERP, SELF, value);
739 =item C<STRING *get_string()>
741 Returns the short signature for the CallContext.
747 VTABLE STRING *get_string() {
750 INTVAL num_positionals, i;
752 GET_ATTR_short_sig(INTERP, SELF, 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) {
765 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, "I"));
768 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, "N"));
771 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, "S"));
774 res = Parrot_str_concat(INTERP, res, CONST_STRING(INTERP, "P"));
777 PARROT_FAILURE("Impossible flag");
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);
791 =item C<void set_pmc(PMC *value)>
793 Sets a fixed-size array of integer types (a type tuple) for the CallContext.
799 VTABLE void set_pmc(PMC *value) {
800 SET_ATTR_type_tuple(INTERP, SELF, value);
805 =item C<PMC *get_pmc()>
807 Returns a fixed-size array of integer types (a type tuple) for the
814 VTABLE PMC *get_pmc() {
817 GET_ATTR_type_tuple(INTERP, SELF, type_tuple);
819 if (PMC_IS_NULL(type_tuple)) {
821 INTVAL num_positionals;
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) {
834 case INTCELL: type = enum_type_INTVAL; break;
835 case FLOATCELL: type = enum_type_FLOATVAL; break;
836 case STRINGCELL: type = enum_type_STRING; break;
838 type = PMC_IS_NULL(c[i].u.p)
839 ? (INTVAL) enum_type_PMC
840 : VTABLE_type(INTERP, c[i].u.p);
843 Parrot_ex_throw_from_c_args(INTERP, NULL,
844 EXCEPTION_INVALID_OPERATION,
845 "Multiple Dispatch: invalid argument type!");
848 VTABLE_set_integer_keyed_int(INTERP, type_tuple, i, type);
851 SET_ATTR_type_tuple(INTERP, SELF, type_tuple);
860 =item C<void set_attr_str(STRING *key, PMC *value)>
862 Set a PMC value for an attribute by string name.
868 Stores the return signature, an array of PMCs.
872 Stores a set of flags for the call signature arguments, an array of
877 Stores a set of flags for the call signature return arguments, an array
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);
891 else if (Parrot_str_equal(INTERP, key, CONST_STRING(INTERP, "return_flags"))) {
892 SET_ATTR_return_flags(INTERP, SELF, value);
895 Parrot_ex_throw_from_c_args(INTERP, NULL,
896 EXCEPTION_ATTRIB_NOT_FOUND, "No such attribute '%S'", key);
901 =item C<PMC *get_attr_str(STRING *key)>
903 Get a PMC value for an attribute by string name.
909 Retrieves the return signature, an array of PMCs.
913 Retrieves the flags for the call signature arguments, an array of
918 Retrieves the flags for the call signature return arguments, an array of
923 Retrieves the hash of named arguments.
927 return Caller Context
943 return list of ExceptioHandlers
947 return current Continuation
951 return current Object (if in method call)
953 =item current_namespace
955 return current Namespace
963 VTABLE PMC *get_attr_str(STRING *key) {
964 PMC *value = PMCNULL;
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);
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));
1000 Parrot_ex_throw_from_c_args(INTERP, NULL,
1001 EXCEPTION_ATTRIB_NOT_FOUND, "No such attribute '%S'", key);
1006 VTABLE INTVAL elements() {
1007 INTVAL num_positionals;
1009 if (!PMC_data(SELF))
1012 GET_ATTR_num_positionals(INTERP, SELF, num_positionals);
1014 return num_positionals;
1017 VTABLE void push_integer(INTVAL value) {
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);
1033 VTABLE void push_float(FLOATVAL value) {
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);
1046 VTABLE void push_string(STRING *value) {
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);
1059 VTABLE void push_pmc(PMC *value) {
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);
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.
1080 VTABLE void unshift_pmc(PMC *value) {
1082 const INTVAL size = STATICSELF.elements();
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);
1096 VTABLE PMC * shift_pmc() {
1099 const INTVAL size = STATICSELF.elements();
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);
1118 VTABLE STRING * shift_string() {
1121 const INTVAL size = STATICSELF.elements();
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);
1139 VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
1143 GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1144 if (key >= num_pos || key < 0)
1147 GET_ATTR_positionals(INTERP, SELF, cells);
1148 return autobox_intval(INTERP, &cells[key]);
1151 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
1155 GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1156 if (key >= num_pos || key < 0)
1159 GET_ATTR_positionals(INTERP, SELF, cells);
1160 return autobox_floatval(INTERP, &cells[key]);
1163 VTABLE STRING * get_string_keyed_int(INTVAL key) {
1167 GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1168 if (key >= num_pos || key < 0)
1171 GET_ATTR_positionals(INTERP, SELF, cells);
1172 return autobox_string(INTERP, &cells[key]);
1175 VTABLE PMC * get_pmc_keyed_int(INTVAL key) {
1177 INTVAL num_pos, type;
1179 GET_ATTR_num_positionals(INTERP, SELF, num_pos);
1180 if (key >= num_pos || key < 0)
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);
1190 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
1191 Pcc_cell * const cell = get_cell_at(INTERP, SELF, key);
1195 cell->type = INTCELL;
1197 GET_ATTR_num_positionals(INTERP, SELF, pos);
1199 SET_ATTR_num_positionals(INTERP, SELF, key + 1);
1202 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
1203 Pcc_cell * const cell = get_cell_at(INTERP, SELF, key);
1207 cell->type = FLOATCELL;
1209 GET_ATTR_num_positionals(INTERP, SELF, pos);
1211 SET_ATTR_num_positionals(INTERP, SELF, key + 1);
1214 VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
1215 Pcc_cell * const cell = get_cell_at(INTERP, SELF, key);
1219 cell->type = STRINGCELL;
1221 GET_ATTR_num_positionals(INTERP, SELF, pos);
1223 SET_ATTR_num_positionals(INTERP, SELF, key + 1);
1226 VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) {
1228 Pcc_cell * const cell = get_cell_at(INTERP, SELF, key);
1231 cell->type = PMCCELL;
1233 GET_ATTR_num_positionals(INTERP, SELF, pos);
1235 SET_ATTR_num_positionals(INTERP, SELF, key + 1);
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);
1243 cell = ALLOC_CELL(INTERP);
1244 parrot_hash_put(INTERP, hash, (void *)key, (void *)cell);
1248 cell->type = INTCELL;
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);
1256 cell = ALLOC_CELL(INTERP);
1257 parrot_hash_put(INTERP, hash, (void *)key, (void *)cell);
1261 cell->type = FLOATCELL;
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);
1269 cell = ALLOC_CELL(INTERP);
1270 parrot_hash_put(INTERP, hash, (void *)key, (void *)cell);
1274 cell->type = STRINGCELL;
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);
1282 cell = ALLOC_CELL(INTERP);
1283 parrot_hash_put(INTERP, hash, (void *)key, (void *)cell);
1287 cell->type = PMCCELL;
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);
1296 cell = ALLOC_CELL(INTERP);
1297 parrot_hash_put(INTERP, hash, k, (void *)cell);
1301 cell->type = INTCELL;
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);
1310 cell = ALLOC_CELL(INTERP);
1311 parrot_hash_put(INTERP, hash, k, (void *)cell);
1315 cell->type = FLOATCELL;
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);
1324 cell = ALLOC_CELL(INTERP);
1325 parrot_hash_put(INTERP, hash, k, (void *)cell);
1329 cell->type = STRINGCELL;
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);
1338 cell = ALLOC_CELL(INTERP);
1339 parrot_hash_put(INTERP, hash, k, (void *)cell);
1343 cell->type = PMCCELL;
1346 VTABLE INTVAL get_integer_keyed_str(STRING *key) {
1348 GETATTR_CallContext_hash(INTERP, SELF, 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);
1355 return autobox_intval(INTERP, cell);
1361 VTABLE FLOATVAL get_number_keyed_str(STRING *key) {
1363 GETATTR_CallContext_hash(INTERP, SELF, 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);
1370 return autobox_floatval(INTERP, cell);
1377 VTABLE STRING * get_string_keyed_str(STRING *key) {
1379 GETATTR_CallContext_hash(INTERP, SELF, 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);
1386 return autobox_string(INTERP, cell);
1392 VTABLE PMC * get_pmc_keyed_str(STRING *key) {
1394 GETATTR_CallContext_hash(INTERP, SELF, 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);
1401 INTVAL type = CELL_TYPE_MASK(cell);
1402 if (type == PMCCELL)
1403 return CELL_PMC(cell);
1404 return autobox_pmc(INTERP, cell, type);
1411 VTABLE INTVAL get_integer_keyed(PMC *key) {
1413 GETATTR_CallContext_hash(INTERP, SELF, 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);
1420 return autobox_intval(INTERP, cell);
1426 VTABLE FLOATVAL get_number_keyed(PMC *key) {
1428 GETATTR_CallContext_hash(INTERP, SELF, 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);
1435 return autobox_floatval(INTERP, cell);
1441 VTABLE STRING * get_string_keyed(PMC *key) {
1443 GETATTR_CallContext_hash(INTERP, SELF, 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);
1450 return autobox_string(INTERP, cell);
1456 VTABLE PMC * get_pmc_keyed(PMC *key) {
1458 GETATTR_CallContext_hash(INTERP, SELF, 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);
1465 INTVAL type = CELL_TYPE_MASK(cell);
1466 if (type == PMCCELL)
1467 return CELL_PMC(cell);
1468 return autobox_pmc(INTERP, cell, type);
1475 VTABLE INTVAL exists_keyed(PMC *key) {
1477 GETATTR_CallContext_hash(INTERP, SELF, hash);
1480 void * const k = hash_key_from_pmc(INTERP, hash, key);
1481 return parrot_hash_exists(INTERP, hash, k);
1487 VTABLE INTVAL exists_keyed_str(STRING *key) {
1489 GETATTR_CallContext_hash(INTERP, SELF, hash);
1492 void * const k = hash_key_from_string(INTERP, hash, key);
1493 return parrot_hash_exists(INTERP, hash, k);
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;
1512 =item C<PMC *clone()>
1514 Creates and returns a clone of the signature.
1519 VTABLE PMC *clone() {
1521 PMC *type_tuple, *arg_flags, *return_flags;
1522 PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
1524 Pcc_cell *our_cells, *dest_cells;
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));
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));
1555 parrot_hash_clone(INTERP, hash, get_hash(INTERP, dest));
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.
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. */
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);
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
1602 : Parrot_pcc_get_pc(INTERP, cur_ctx);
1604 annotations = PackFile_Annotations_lookup(INTERP,
1605 seg->annotations, pc - seg->base.data,
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);
1620 RETURN(PMC *result);
1634 * c-file-style: "parrot"
1636 * vim: expandtab shiftwidth=4: