2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/inter_call.c - Parrot Interpreter - Argument passing code
11 Functions in this file handle argument/return value passing to and from
22 #include "parrot/parrot.h"
23 #include "parrot/oplib/ops.h"
24 #include "inter_call.str"
26 /* HEADERIZER HFILE: include/parrot/inter_call.h */
28 /* HEADERIZER BEGIN: static */
29 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
31 static void check_for_opt_flag(ARGMOD(call_state
*st
), int has_arg
)
32 __attribute__nonnull__(1)
35 static void check_named(PARROT_INTERP
, ARGMOD(call_state
*st
))
36 __attribute__nonnull__(1)
37 __attribute__nonnull__(2)
40 static void clone_key_arg(PARROT_INTERP
, ARGMOD(call_state
*st
))
41 __attribute__nonnull__(1)
42 __attribute__nonnull__(2)
45 static void commit_last_arg(PARROT_INTERP
,
48 ARGMOD(opcode_t
*n_regs_used
),
50 ARGIN(PMC
* const *sigs
),
51 ARGMOD(opcode_t
**indexes
),
52 ARGMOD(parrot_context_t
*ctx
),
53 ARGIN_NULLOK(PMC
*pmc
),
55 __attribute__nonnull__(1)
56 __attribute__nonnull__(4)
57 __attribute__nonnull__(6)
58 __attribute__nonnull__(7)
59 __attribute__nonnull__(8)
60 __attribute__nonnull__(10)
61 FUNC_MODIFIES(*n_regs_used
)
62 FUNC_MODIFIES(*indexes
)
65 static void convert_arg_from_int(PARROT_INTERP
, ARGMOD(call_state
*st
))
66 __attribute__nonnull__(1)
67 __attribute__nonnull__(2)
70 static void convert_arg_from_num(PARROT_INTERP
, ARGMOD(call_state
*st
))
71 __attribute__nonnull__(1)
72 __attribute__nonnull__(2)
75 static void convert_arg_from_pmc(PARROT_INTERP
, ARGMOD(call_state
*st
))
76 __attribute__nonnull__(1)
77 __attribute__nonnull__(2)
80 static void convert_arg_from_str(PARROT_INTERP
, ARGMOD(call_state
*st
))
81 __attribute__nonnull__(1)
82 __attribute__nonnull__(2)
85 static int fetch_arg_op(PARROT_INTERP
, ARGMOD(call_state
*st
))
86 __attribute__nonnull__(1)
87 __attribute__nonnull__(2)
90 static int fetch_arg_sig(PARROT_INTERP
, ARGMOD(call_state
*st
))
91 __attribute__nonnull__(1)
92 __attribute__nonnull__(2)
95 static void init_call_stats(ARGMOD(call_state
*st
))
96 __attribute__nonnull__(1)
99 static void init_first_dest_named(PARROT_INTERP
, ARGMOD(call_state
*st
))
100 __attribute__nonnull__(1)
101 __attribute__nonnull__(2)
104 static int locate_named_named(PARROT_INTERP
, ARGMOD(call_state
*st
))
105 __attribute__nonnull__(1)
106 __attribute__nonnull__(2)
109 static void next_arg_sig(ARGMOD(call_state_item
*sti
))
110 __attribute__nonnull__(1)
113 static void null_val(int sig
, ARGMOD(call_state
*st
))
114 __attribute__nonnull__(2)
117 static int set_retval_util(PARROT_INTERP
,
118 ARGIN(const char *sig
),
119 ARGIN(parrot_context_t
*ctx
),
120 ARGMOD(call_state
*st
))
121 __attribute__nonnull__(1)
122 __attribute__nonnull__(2)
123 __attribute__nonnull__(3)
124 __attribute__nonnull__(4)
127 static void start_flatten(PARROT_INTERP
,
128 ARGMOD(call_state
*st
),
130 __attribute__nonnull__(1)
131 __attribute__nonnull__(2)
132 __attribute__nonnull__(3)
135 static void store_arg(ARGIN(const call_state
*st
), INTVAL idx
)
136 __attribute__nonnull__(1);
138 static void too_few(PARROT_INTERP
,
139 ARGIN(const call_state
*st
),
140 ARGIN(const char *action
))
141 __attribute__nonnull__(1)
142 __attribute__nonnull__(2)
143 __attribute__nonnull__(3);
145 static void too_many(PARROT_INTERP
,
146 ARGIN(const call_state
*st
),
147 ARGIN(const char *action
))
148 __attribute__nonnull__(1)
149 __attribute__nonnull__(2)
150 __attribute__nonnull__(3);
152 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
153 /* HEADERIZER END: static */
156 /* Make sure we don't conflict with any other MAX() macros defined elsewhere */
157 #define PARROT_MAX(a, b) (((a)) > (b) ? (a) : (b))
159 #define SAVE_OFF_REGS(orig, next, save) \
160 (save).bp = (orig).bp;\
161 (save).bp_ps = (orig).bp_ps;\
162 (orig).bp = (next).bp;\
163 (orig).bp_ps = (next).bp_ps;
165 #define RESTORE_REGS(orig, save) \
166 (orig).bp = (save).bp;\
167 (orig).bp_ps = (save).bp_ps;
172 =item C<void Parrot_init_arg_nci>
174 Initializes the argument passing state C<call_state> for the given NCI
183 Parrot_init_arg_nci(PARROT_INTERP
, ARGOUT(call_state
*st
),
184 ARGIN(const char *sig
))
188 if (PMC_IS_NULL(interp
->args_signature
))
189 Parrot_init_arg_op(interp
, CONTEXT(interp
), interp
->current_args
,
192 Parrot_init_arg_indexes_and_sig_pmc(interp
, CONTEXT(interp
),
193 interp
->current_args
, interp
->args_signature
, &st
->src
);
195 Parrot_init_arg_sig(interp
, CONTEXT(interp
), sig
, NULL
, &st
->dest
);
201 =item C<void Parrot_init_ret_nci>
203 Initializes the return value, passing state C<call_state> for the given NCI
212 Parrot_init_ret_nci(PARROT_INTERP
, ARGOUT(call_state
*st
), ARGIN(const char *sig
))
214 Parrot_Context
*ctx
= CONTEXT(interp
);
215 PMC
* const current_cont
= ctx
->current_cont
;
217 /* if this NCI call was a taicall, return results to caller's get_results
218 * this also means that we pass the caller's register base pointer */
219 if (SUB_FLAG_TAILCALL_ISSET(current_cont
))
220 ctx
= PMC_cont(current_cont
)->to_ctx
;
222 /* TODO simplify all */
223 Parrot_init_arg_sig(interp
, CONTEXT(interp
), sig
, NULL
, &st
->src
);
224 Parrot_init_arg_op(interp
, ctx
, ctx
->current_results
, &st
->dest
);
230 =item C<int Parrot_init_arg_indexes_and_sig_pmc>
232 Initializes argument transfer with given context registers, register indexes,
235 All C<Parrot_init_arg*> functions can be used for either source or destination,
236 by passing either C<&st.src> or C<&st.dest> of a C<call_state> structure.
238 These functions return 0 if no arguments are present, or 1 on success.
246 Parrot_init_arg_indexes_and_sig_pmc(SHIM_INTERP
, ARGIN(parrot_context_t
*ctx
),
247 ARGIN_NULLOK(opcode_t
*indexes
), ARGIN_NULLOK(PMC
* sig_pmc
),
248 ARGMOD(call_state_item
*sti
))
250 if (!sig_pmc
&& indexes
) {
252 sig_pmc
= ctx
->constants
[*indexes
]->u
.key
;
253 ASSERT_SIG_PMC(sig_pmc
);
260 sti
->mode
= CALL_STATE_OP
;
266 ASSERT_SIG_PMC(sig_pmc
);
267 sti
->u
.op
.signature
= sig_pmc
;
268 sti
->u
.op
.pc
= indexes
;
269 sti
->n
= SIG_ELEMS(sig_pmc
);
271 /* initialize sti->sig */
282 =item C<int Parrot_init_arg_op>
284 Initializes argument transfer with given context registers and opcode location
285 of a C<get_*> or C<set_*> argument opcode.
293 Parrot_init_arg_op(PARROT_INTERP
, ARGIN(parrot_context_t
*ctx
),
294 ARGIN_NULLOK(opcode_t
*pc
), ARGIN(call_state_item
*sti
))
296 PMC
*sig_pmc
= PMCNULL
;
300 sig_pmc
= ctx
->constants
[*pc
]->u
.key
;
301 ASSERT_SIG_PMC(sig_pmc
);
305 return Parrot_init_arg_indexes_and_sig_pmc(interp
, ctx
, pc
, sig_pmc
, sti
);
311 =item C<int Parrot_init_arg_sig>
313 Initializes argument transfer with given code segment (holding the
314 const_table), registers, function signature, and arguments.
322 Parrot_init_arg_sig(SHIM_INTERP
, ARGIN(parrot_context_t
*ctx
),
323 ARGIN(const char *sig
), ARGIN_NULLOK(void *ap
),
324 ARGMOD(call_state_item
*sti
))
329 sti
->mode
= CALL_STATE_SIG
;
334 sti
->u
.sig
.sig
= sig
;
336 sti
->n
= strlen(sig
);
338 /* initialize st->sig */
349 =item C<static void start_flatten>
351 Marks the source state as flattening with the passed PMC being flattened and
352 fetches the first arg from the flattened set.
359 start_flatten(PARROT_INTERP
, ARGMOD(call_state
*st
), ARGIN(PMC
*p_arg
))
361 if (PARROT_ARG_NAME_ISSET(st
->src
.sig
)) {
362 /* src ought to be an hash */
363 if (!VTABLE_does(interp
, p_arg
, CONST_STRING(interp
, "hash")))
364 real_exception(interp
, NULL
, E_ValueError
, "argument doesn't hash");
366 /* create key needed to iterate the hash */
367 st
->key
= pmc_new(interp
, enum_class_Key
);
368 PMC_int_val(st
->key
) = 0;
369 PMC_data(st
->key
) = (void *)INITBucketIndex
;
371 dod_register_pmc(interp
, st
->key
);
374 /* src ought to be an array */
375 if (!VTABLE_does(interp
, p_arg
, CONST_STRING(interp
, "array")))
376 real_exception(interp
, NULL
, E_ValueError
, "argument doesn't array");
379 st
->src
.mode
|= CALL_STATE_FLATTEN
;
380 st
->src
.slurp
= p_arg
;
382 st
->src
.slurp_n
= VTABLE_elements(interp
, p_arg
);
384 /* the -1 is because the :flat PMC itself doesn't count. */
385 st
->n_actual_args
+= st
->src
.slurp_n
- 1;
391 =item C<static void next_arg_sig>
393 Moves the call state to the next argument in the signature, calculating which
394 type of argument/parameter to get next. The index gets increased elsewhere.
401 next_arg_sig(ARGMOD(call_state_item
*sti
))
403 switch (sti
->mode
& CALL_S_D_MASK
) {
405 sti
->sig
= SIG_ITEM(sti
->u
.op
.signature
, sti
->i
);
408 switch (sti
->u
.sig
.sig
[sti
->i
]) {
410 sti
->sig
= PARROT_ARG_INTVAL
; break;
412 sti
->sig
= PARROT_ARG_FLOATVAL
; break;
414 sti
->sig
= PARROT_ARG_STRING
; break;
417 sti
->sig
= PARROT_ARG_PMC
; break;
419 sti
->sig
= PARROT_ARG_PMC
| PARROT_ARG_SLURPY_ARRAY
; break;
421 sti
->sig
= PARROT_ARG_PMC
| PARROT_ARG_FLATTEN
; break;
434 =item C<static int fetch_arg_sig>
436 Fetches the next argument from the signature in the given call state.
442 /* Fetch an argument from C code */
444 fetch_arg_sig(PARROT_INTERP
, ARGMOD(call_state
*st
))
446 va_list * const ap
= (va_list *)(st
->src
.u
.sig
.ap
);
448 switch (st
->src
.sig
& PARROT_ARG_TYPE_MASK
) {
449 case PARROT_ARG_INTVAL
:
450 UVal_int(st
->val
) = va_arg(*ap
, INTVAL
);
452 case PARROT_ARG_STRING
:
453 UVal_str(st
->val
) = va_arg(*ap
, STRING
*);
455 case PARROT_ARG_FLOATVAL
:
456 UVal_num(st
->val
) = va_arg(*ap
, FLOATVAL
);
459 if (st
->src
.u
.sig
.sig
[st
->src
.i
] == 'O')
460 UVal_pmc(st
->val
) = CONTEXT(interp
)->current_object
;
462 UVal_pmc(st
->val
) = va_arg(*ap
, PMC
*);
463 dod_register_pmc(interp
, UVal_pmc(st
->val
));
466 if (st
->src
.sig
& PARROT_ARG_FLATTEN
) {
468 start_flatten(interp
, st
, UVal_pmc(st
->val
));
470 /* if the :flat arg is empty, just go to the next arg */
471 if (!st
->src
.slurp_n
) {
472 st
->src
.mode
&= ~CALL_STATE_FLATTEN
;
477 retval
= Parrot_fetch_arg(interp
, st
);
479 if (!PMC_IS_NULL(st
->key
))
480 dod_unregister_pmc(interp
, st
->key
);
496 =item C<static int fetch_arg_op>
498 Fetches an argument from the appropriate context.
505 fetch_arg_op(PARROT_INTERP
, ARGMOD(call_state
*st
))
507 const int constant
= PARROT_ARG_CONSTANT_ISSET(st
->src
.sig
);
508 const INTVAL idx
= st
->src
.u
.op
.pc
[st
->src
.i
];
510 switch (PARROT_ARG_TYPE_MASK_MASK(st
->src
.sig
)) {
511 case PARROT_ARG_INTVAL
:
512 UVal_int(st
->val
) = constant
? idx
: CTX_REG_INT(st
->src
.ctx
, idx
);
514 case PARROT_ARG_STRING
:
515 UVal_str(st
->val
) = constant
? st
->src
.ctx
->constants
[idx
]->u
.string
516 : CTX_REG_STR(st
->src
.ctx
, idx
);
518 case PARROT_ARG_FLOATVAL
:
519 UVal_num(st
->val
) = constant
? st
->src
.ctx
->constants
[idx
]->u
.number
520 : CTX_REG_NUM(st
->src
.ctx
, idx
);
523 UVal_pmc(st
->val
) = constant
? st
->src
.ctx
->constants
[idx
]->u
.key
524 : CTX_REG_PMC(st
->src
.ctx
, idx
);
526 if (st
->src
.sig
& PARROT_ARG_FLATTEN
) {
528 start_flatten(interp
, st
, UVal_pmc(st
->val
));
530 /* if the :flat arg is empty, just go to the next arg */
531 if (!st
->src
.slurp_n
) {
532 st
->src
.mode
&= ~CALL_STATE_FLATTEN
;
537 retval
= Parrot_fetch_arg(interp
, st
);
539 if (!PMC_IS_NULL(st
->key
))
540 dod_unregister_pmc(interp
, st
->key
);
556 =item C<int Parrot_fetch_arg>
558 RT#48260: Not yet documented!!!
564 /* Fetch a new argument.
568 Parrot_fetch_arg(PARROT_INTERP
, ARGMOD(call_state
*st
))
573 if (st
->src
.i
>= st
->src
.n
)
578 next_arg_sig(&st
->src
);
580 /* check if we're supposed to continue a :flat argument */
581 if (st
->src
.mode
& CALL_STATE_FLATTEN
) {
582 PARROT_ASSERT(st
->src
.slurp_i
< st
->src
.slurp_n
);
583 if (!PMC_IS_NULL(st
->key
)) {
585 st
->name
= (STRING
*)parrot_hash_get_idx(interp
,
586 (Hash
*)PMC_struct_val(st
->src
.slurp
), st
->key
);
587 PARROT_ASSERT(st
->name
);
588 UVal_pmc(st
->val
) = VTABLE_get_pmc_keyed_str(interp
,
589 st
->src
.slurp
, st
->name
);
592 UVal_pmc(st
->val
) = VTABLE_get_pmc_keyed_int(interp
,
593 st
->src
.slurp
, st
->src
.slurp_i
++);
596 st
->src
.sig
= PARROT_ARG_PMC
;
598 /* done with flattening */
599 if (st
->src
.slurp_i
== st
->src
.slurp_n
) {
600 st
->src
.mode
&= ~CALL_STATE_FLATTEN
;
602 if (!PMC_IS_NULL(st
->key
))
603 dod_unregister_pmc(interp
, st
->key
);
612 /* If we're at a named arg, store the name and then get the next arg, which
613 * is the actual value of the named arg. */
614 if ((st
->src
.sig
& PARROT_ARG_NAME
)
615 && !(st
->src
.sig
& PARROT_ARG_FLATTEN
)) {
616 fetch_arg_op(interp
, st
);
617 st
->name
= UVal_str(st
->val
);
618 next_arg_sig(&st
->src
);
621 switch (st
->src
.mode
& CALL_S_D_MASK
) {
623 return fetch_arg_op(interp
, st
);
625 return fetch_arg_sig(interp
, st
);
627 real_exception(interp
, NULL
, 1, "invalid call state mode");
634 =item C<int Parrot_fetch_arg_nci>
636 RT#48260: Not yet documented!!!
644 Parrot_fetch_arg_nci(PARROT_INTERP
, ARGMOD(call_state
*st
))
646 next_arg_sig(&st
->dest
);
648 if (st
->dest
.sig
& PARROT_ARG_SLURPY_ARRAY
) {
649 PMC
*slurped
= pmc_new(interp
, enum_class_ResizablePMCArray
);
651 PARROT_ASSERT((st
->dest
.sig
& PARROT_ARG_TYPE_MASK
) == PARROT_ARG_PMC
);
653 while (Parrot_fetch_arg(interp
, st
)) {
655 Parrot_convert_arg(interp
, st
);
656 VTABLE_push_pmc(interp
, slurped
, UVal_pmc(st
->val
));
659 UVal_pmc(st
->val
) = slurped
;
660 dod_register_pmc(interp
, slurped
);
663 Parrot_fetch_arg(interp
, st
);
665 Parrot_convert_arg(interp
, st
);
675 =item C<static void convert_arg_from_int>
677 Autoboxes an int into the expected container type.
684 convert_arg_from_int(PARROT_INTERP
, ARGMOD(call_state
*st
))
686 switch (st
->dest
.sig
& PARROT_ARG_TYPE_MASK
) {
687 case PARROT_ARG_FLOATVAL
:
688 UVal_num(st
->val
) = (FLOATVAL
)UVal_int(st
->val
);
690 case PARROT_ARG_STRING
:
691 UVal_str(st
->val
) = string_from_int(interp
, UVal_int(st
->val
));
695 PMC
* const d
= pmc_new(interp
,
696 Parrot_get_ctx_HLL_type(interp
, enum_class_Integer
));
698 VTABLE_set_integer_native(interp
, d
, UVal_int(st
->val
));
699 UVal_pmc(st
->val
) = d
;
700 dod_register_pmc(interp
, d
);
711 =item C<static void convert_arg_from_num>
713 Autoboxes a num into the expected container type.
720 convert_arg_from_num(PARROT_INTERP
, ARGMOD(call_state
*st
))
722 switch (st
->dest
.sig
& PARROT_ARG_TYPE_MASK
) {
723 case PARROT_ARG_INTVAL
:
724 UVal_int(st
->val
) = (INTVAL
)UVal_num(st
->val
);
726 case PARROT_ARG_STRING
:
727 UVal_str(st
->val
) = string_from_num(interp
, UVal_num(st
->val
));
731 PMC
* const d
= pmc_new(interp
,
732 Parrot_get_ctx_HLL_type(interp
, enum_class_Float
));
734 VTABLE_set_number_native(interp
, d
, UVal_num(st
->val
));
735 UVal_pmc(st
->val
) = d
;
736 dod_register_pmc(interp
, d
);
747 =item C<static void convert_arg_from_str>
749 Autoboxes a string primitive to the expected container type.
756 convert_arg_from_str(PARROT_INTERP
, ARGMOD(call_state
*st
))
758 switch (st
->dest
.sig
& PARROT_ARG_TYPE_MASK
) {
759 case PARROT_ARG_INTVAL
:
760 UVal_int(st
->val
) = string_to_int(interp
, UVal_str(st
->val
));
762 case PARROT_ARG_FLOATVAL
:
763 UVal_num(st
->val
) = string_to_num(interp
, UVal_str(st
->val
));
767 PMC
* const d
= pmc_new(interp
,
768 Parrot_get_ctx_HLL_type(interp
, enum_class_String
));
770 VTABLE_set_string_native(interp
, d
, UVal_str(st
->val
));
771 UVal_pmc(st
->val
) = d
;
772 dod_register_pmc(interp
, d
);
782 =item C<static void convert_arg_from_pmc>
784 Unboxes a PMC to the expected primitive type.
791 convert_arg_from_pmc(PARROT_INTERP
, ARGMOD(call_state
*st
))
793 switch (st
->dest
.sig
& PARROT_ARG_TYPE_MASK
) {
794 case PARROT_ARG_INTVAL
:
795 UVal_int(st
->val
) = VTABLE_get_integer(interp
, UVal_pmc(st
->val
));
797 case PARROT_ARG_FLOATVAL
:
798 UVal_num(st
->val
) = VTABLE_get_number(interp
, UVal_pmc(st
->val
));
800 case PARROT_ARG_STRING
:
801 UVal_str(st
->val
) = VTABLE_get_string(interp
, UVal_pmc(st
->val
));
811 =item C<static void check_for_opt_flag>
813 Processes the next argument, if it has the optional flag set. Otherwise moves
821 check_for_opt_flag(ARGMOD(call_state
*st
), int has_arg
)
824 call_state_item
* const dest
= &st
->dest
;
828 /* look at the next arg */
830 if (dest
->i
>= dest
->n
)
835 /* if this isn't an :opt_flag argument, we need to reset things
836 * and go to the next argument */
837 if (!(st
->dest
.sig
& PARROT_ARG_OPT_FLAG
)) {
842 /* we're at an :opt_flag argument, so actually store something */
843 idx
= st
->dest
.u
.op
.pc
[st
->dest
.i
];
846 PARROT_ASSERT(idx
>= 0);
847 CTX_REG_INT(st
->dest
.ctx
, idx
) = has_arg
;
853 =item C<static void clone_key_arg>
855 Replaces any src registers by their values (done inside clone). This needs a
856 test for tailcalls too, but I think there is no syntax to pass a key to a
857 tailcalled function or method.
864 clone_key_arg(PARROT_INTERP
, ARGMOD(call_state
*st
))
866 PMC
*key
= UVal_pmc(st
->val
);
871 if (key
->vtable
->base_type
!= enum_class_Key
)
874 for (; key
; key
=key_next(interp
, key
)) {
875 /* register keys have to be cloned */
876 if (PObj_get_FLAGS(key
) & KEY_register_FLAG
) {
877 parrot_context_t temp_ctx
;
879 /* clone sets key values according to refered register items */
880 SAVE_OFF_REGS(interp
->ctx
, (*(st
->src
.ctx
)), temp_ctx
)
881 UVal_pmc(st
->val
) = VTABLE_clone(interp
, key
);
882 RESTORE_REGS(interp
->ctx
, temp_ctx
)
891 =item C<static void init_first_dest_named>
893 Initializes dest calling state for the first named arg.
900 init_first_dest_named(PARROT_INTERP
, ARGMOD(call_state
*st
))
904 if (st
->dest
.mode
& CALL_STATE_SIG
)
905 real_exception(interp
, NULL
, E_ValueError
,
906 "Can't call C function with named arguments");
908 st
->first_named
= st
->dest
.i
;
911 /* 1) if we were slurpying positional args, we are done, turn it off
912 * 2) set destination named args bit */
913 st
->dest
.slurp
= NULL
;
915 /* 1) count named args, make sure there is less than 32/64
916 * 2) create slurpy hash if needed */
917 for (i
= st
->dest
.i
; i
< st
->dest
.n
; ++i
) {
918 const INTVAL sig
= SIG_ITEM(st
->dest
.u
.op
.signature
, i
);
920 /* skip the arg name, only count the actual args of the named args */
921 if (!(sig
& PARROT_ARG_NAME
))
924 /* slurpy named args, create slurpy hash */
925 else if (sig
& PARROT_ARG_SLURPY_ARRAY
) {
928 /* Create PMC for slurpy mode and register it; we must do this
929 * otherwise it may get collected. */
930 st
->dest
.slurp
= pmc_new(interp
,
931 Parrot_get_ctx_HLL_type(interp
, enum_class_Hash
));
932 dod_register_pmc(interp
, st
->dest
.slurp
);
934 /* pass the slurpy hash */
935 idx
= st
->dest
.u
.op
.pc
[i
];
936 CTX_REG_PMC(st
->dest
.ctx
, idx
) = st
->dest
.slurp
;
938 /* must be the actual arg of a named arg, count it */
943 /* only 32/64 named args allowed;
944 * uses UINTVAL as a bitfield to detect duplicates */
945 if (n_named
>= (int)(sizeof (UINTVAL
) * 8))
946 real_exception(interp
, NULL
, E_ValueError
, "Too many named arguments");
954 =item C<static int locate_named_named>
956 Locates a destination argument name, returning 0 if not found.
963 locate_named_named(PARROT_INTERP
, ARGMOD(call_state
*st
))
968 for (i
= st
->first_named
; i
< st
->dest
.n
; ++i
) {
972 st
->dest
.sig
= SIG_ITEM(st
->dest
.u
.op
.signature
, i
);
973 if (!(st
->dest
.sig
& PARROT_ARG_NAME
))
976 if (st
->dest
.sig
& PARROT_ARG_SLURPY_ARRAY
)
980 idx
= st
->dest
.u
.op
.pc
[i
];
981 param
= PARROT_ARG_CONSTANT_ISSET(st
->dest
.sig
)
982 ? st
->dest
.ctx
->constants
[idx
]->u
.string
983 : CTX_REG_STR(st
->dest
.ctx
, idx
);
985 if (st
->name
== param
|| string_equal(interp
, st
->name
, param
) == 0) {
987 st
->dest
.sig
= SIG_ITEM(st
->dest
.u
.op
.signature
, i
);
990 /* if bit is set we have a duplicate */
991 if (st
->named_done
& (1 << n_named
))
992 real_exception(interp
, NULL
, E_ValueError
,
993 "duplicate named argument - '%Ss' not expected", param
);
995 st
->named_done
|= 1 << n_named
;
1006 =item C<static void store_arg>
1008 Stores the next argument in the destination register appropriately.
1015 store_arg(ARGIN(const call_state
*st
), INTVAL idx
)
1017 switch (st
->dest
.sig
& PARROT_ARG_TYPE_MASK
) {
1018 case PARROT_ARG_INTVAL
:
1019 CTX_REG_INT(st
->dest
.ctx
, idx
) = UVal_int(st
->val
);
1021 case PARROT_ARG_FLOATVAL
:
1022 CTX_REG_NUM(st
->dest
.ctx
, idx
) = UVal_num(st
->val
);
1024 case PARROT_ARG_STRING
:
1025 CTX_REG_STR(st
->dest
.ctx
, idx
) = UVal_str(st
->val
);
1027 case PARROT_ARG_PMC
:
1028 CTX_REG_PMC(st
->dest
.ctx
, idx
) = UVal_pmc(st
->val
);
1038 =item C<int Parrot_store_arg>
1040 RT#48260: Not yet documented!!!
1047 Parrot_store_arg(SHIM_INTERP
, ARGIN(const call_state
*st
))
1050 if (st
->dest
.i
>= st
->dest
.n
)
1053 PARROT_ASSERT(st
->dest
.mode
& CALL_STATE_OP
);
1054 idx
= st
->dest
.u
.op
.pc
[st
->dest
.i
];
1055 PARROT_ASSERT(idx
>= 0);
1064 =item C<static void too_few>
1066 Throws an exception if there are too few arguments passed.
1073 too_few(PARROT_INTERP
, ARGIN(const call_state
*st
), ARGIN(const char *action
))
1075 const int max_expected_args
= st
->params
;
1076 const int min_expected_args
= max_expected_args
- st
->optionals
;
1078 if (st
->n_actual_args
< min_expected_args
) {
1079 real_exception(interp
, NULL
, E_ValueError
,
1080 "too few arguments passed (%d) - %s%d %s expected",
1082 (min_expected_args
< max_expected_args
? "at least " : ""),
1083 min_expected_args
, action
);
1090 =item C<static void too_many>
1092 Throws an exception if there are too many arguments passed.
1099 too_many(PARROT_INTERP
, ARGIN(const call_state
*st
), ARGIN(const char *action
))
1101 const int max_expected_args
= st
->params
;
1102 const int min_expected_args
= max_expected_args
- st
->optionals
;
1104 if (st
->n_actual_args
> max_expected_args
) {
1105 real_exception(interp
, NULL
, E_ValueError
,
1106 "too many arguments passed (%d) - %s%d %s expected",
1108 (min_expected_args
< max_expected_args
? "at most " : ""),
1109 max_expected_args
, action
);
1116 =item C<static void null_val>
1118 Adds a null value to the appropriate register.
1125 null_val(int sig
, ARGMOD(call_state
*st
))
1127 switch (sig
& PARROT_ARG_TYPE_MASK
) {
1128 case PARROT_ARG_INTVAL
: UVal_int(st
->val
) = 0; break;
1129 case PARROT_ARG_FLOATVAL
: UVal_num(st
->val
) = 0.0; break;
1130 case PARROT_ARG_STRING
: UVal_str(st
->val
) = NULL
; break;
1131 case PARROT_ARG_PMC
: UVal_pmc(st
->val
) = PMCNULL
; break;
1140 =item C<static void check_named>
1142 Makes sure that all required named args are set and that all optional
1143 args and flags are set to null and false if not present.
1145 A named arg takes the form of
1147 STRING* name, [INPS] actual_arg,
1151 STRING* name, [INPS] actual_arg, int opt_arg_flag
1158 check_named(PARROT_INTERP
, ARGMOD(call_state
*st
))
1163 for (i
= st
->first_named
; i
< st
->dest
.n
; ++i
) {
1164 /* verify that a name exists */
1165 const INTVAL sig
= st
->dest
.sig
= SIG_ITEM(st
->dest
.u
.op
.signature
, i
);
1166 if (sig
& PARROT_ARG_NAME
) {
1170 /* if slurpy then no errors, return */
1171 if (sig
& PARROT_ARG_SLURPY_ARRAY
)
1177 /* move on to the actual arg */
1180 /* verify that an actual arg exists */
1181 arg_sig
= st
->dest
.sig
= SIG_ITEM(st
->dest
.u
.op
.signature
, i
);
1182 PARROT_ASSERT(!(arg_sig
& PARROT_ARG_NAME
));
1184 /* if this named arg is already filled, continue */
1185 if (st
->named_done
& (1 << n_named
)) {
1186 arg_sig
= st
->dest
.sig
= SIG_ITEM(st
->dest
.u
.op
.signature
, i
+1);
1188 /* skip associated opt flag arg as well */
1189 if (arg_sig
& PARROT_ARG_OPT_FLAG
)
1194 else if (arg_sig
& PARROT_ARG_OPTIONAL
) {
1196 null_val(arg_sig
, st
);
1197 idx
= st
->dest
.u
.op
.pc
[i
];
1200 /* Don't walk off the end of the array */
1201 if (i
+1 >= st
->dest
.n
)
1203 arg_sig
= st
->dest
.sig
= SIG_ITEM(st
->dest
.u
.op
.signature
, i
+1);
1204 if (arg_sig
& PARROT_ARG_OPT_FLAG
) {
1206 idx
= st
->dest
.u
.op
.pc
[i
];
1207 CTX_REG_INT(st
->dest
.ctx
, idx
) = 0;
1212 const INTVAL idx
= st
->dest
.u
.op
.pc
[last_name_pos
];
1213 STRING
* const param
= PARROT_ARG_CONSTANT_ISSET(sig
)
1214 ? st
->dest
.ctx
->constants
[idx
]->u
.string
1215 : CTX_REG_STR(st
->dest
.ctx
, idx
);
1217 real_exception(interp
, NULL
, E_ValueError
,
1218 "too few arguments passed"
1219 " - missing required named arg '%Ss'", param
);
1223 real_exception(interp
, NULL
, E_ValueError
,
1224 "invalid arg type in named portion of args");
1231 =item C<static void init_call_stats>
1233 Sets the default values of the passed C<call_state>.
1240 init_call_stats(ARGMOD(call_state
*st
))
1242 /* initial guess, adjusted for :flat args */
1243 st
->n_actual_args
= st
->src
.n
;
1246 st
->params
= st
->dest
.n
;
1249 st
->first_named
= -1;
1255 =item C<void Parrot_process_args>
1257 RT#48260: Not yet documented!!!
1265 Parrot_process_args(PARROT_INTERP
, ARGMOD(call_state
*st
), arg_pass_t param_or_result
)
1269 call_state_item
*src
, *dest
;
1271 const char * const action
= (param_or_result
== PARROT_PASS_RESULTS
)
1272 ? "results" : "params";
1274 /* Check if we should be throwing errors. This can be configured separately
1275 * for parameters and return values. */
1276 if (param_or_result
== PARROT_PASS_RESULTS
) {
1277 if (!PARROT_ERRORS_test(interp
, PARROT_ERRORS_RESULT_COUNT_FLAG
))
1280 else if (!PARROT_ERRORS_test(interp
, PARROT_ERRORS_PARAM_COUNT_FLAG
))
1283 init_call_stats(st
);
1288 /* 1st: Positional non-:slurpy */
1289 for (; dest
->i
< dest
->n
; dest
->i
++) {
1293 /* check if the next dest arg is :slurpy */
1295 if (dest
->sig
& PARROT_ARG_SLURPY_ARRAY
)
1298 /* Check if there is another argument. We need to store the value to
1299 * handle :opt_flag, which needs to know if there was a preceding
1301 has_arg
= Parrot_fetch_arg(interp
, st
);
1303 /* if the src arg is named, we're done here */
1305 /* but first, take care of any :optional arguments */
1306 while (dest
->sig
& PARROT_ARG_OPTIONAL
) {
1307 null_val(st
->dest
.sig
, st
);
1309 /* actually store the argument */
1310 idx
= st
->dest
.u
.op
.pc
[st
->dest
.i
];
1311 PARROT_ASSERT(idx
>= 0);
1314 check_for_opt_flag(st
, 0);
1323 /* if the dest is a named argument, we need to fill it as a positional
1324 * since no named arguments have been given. so skip the name. */
1325 if (dest
->sig
& PARROT_ARG_NAME
) {
1332 /* if there *is* an arg, convert it */
1335 Parrot_convert_arg(interp
, st
);
1338 /* if this is an optional argument, null it */
1339 else if (dest
->sig
& PARROT_ARG_OPTIONAL
)
1340 null_val(st
->dest
.sig
, st
);
1342 /* there's no argument - throw an exception (if we're in to that) */
1344 too_few(interp
, st
, action
);
1346 /* otherwise, we're done */
1350 /* actually store the argument */
1351 idx
= st
->dest
.u
.op
.pc
[st
->dest
.i
];
1352 PARROT_ASSERT(idx
>= 0);
1355 /* if we're at an :optional argument, check for an :opt_flag */
1356 if (dest
->sig
& PARROT_ARG_OPTIONAL
)
1357 check_for_opt_flag(st
, has_arg
);
1360 /* 2nd: Positional :slurpy */
1361 if (dest
->sig
& PARROT_ARG_SLURPY_ARRAY
&& !(dest
->sig
& PARROT_ARG_NAME
)) {
1362 PMC
* const array
= pmc_new(interp
, enum_class_ResizablePMCArray
);
1363 const INTVAL idx
= st
->dest
.u
.op
.pc
[dest
->i
];
1365 PARROT_ASSERT(idx
>= 0);
1367 /* Must register this PMC or it may get collected when only the struct
1369 dod_register_pmc(interp
, array
);
1370 CTX_REG_PMC(st
->dest
.ctx
, idx
) = array
;
1372 while (Parrot_fetch_arg(interp
, st
)) {
1373 /* if the src arg is named, we're done here */
1379 /* we have to convert to a PMC to we can put it in the PMC array */
1380 dest
->sig
|= PARROT_ARG_PMC
;
1381 Parrot_convert_arg(interp
, st
);
1383 VTABLE_push_pmc(interp
, array
, UVal_pmc(st
->val
));
1387 dod_unregister_pmc(interp
, array
);
1390 /* is there another argument? if we're throwing errors, that's an error */
1391 if (err_check
&& Parrot_fetch_arg(interp
, st
)
1392 && !st
->name
&& !(dest
->sig
& PARROT_ARG_NAME
))
1393 too_many(interp
, st
, action
);
1395 /* are we at the end? */
1396 if (dest
->i
== dest
->n
)
1400 init_first_dest_named(interp
, st
);
1403 while (Parrot_fetch_arg(interp
, st
)) {
1407 real_exception(interp
, NULL
, 0,
1408 "positional inside named args at position %i",
1409 st
->src
.i
- n_named
);
1411 if (!locate_named_named(interp
, st
))
1412 real_exception(interp
, NULL
, E_ValueError
,
1413 "too many named arguments"
1414 " - '%Ss' not expected", st
->name
);
1418 /* if the dest arg is :named :slurpy */
1419 if (dest
->sig
& PARROT_ARG_SLURPY_ARRAY
) {
1420 /* Convert to a PMC to store in the hash */
1421 dest
->sig
|= PARROT_ARG_PMC
;
1422 Parrot_convert_arg(interp
, st
);
1423 VTABLE_set_pmc_keyed_str(interp
, dest
->slurp
, st
->name
, UVal_pmc(st
->val
));
1426 Parrot_convert_arg(interp
, st
);
1427 Parrot_store_arg(interp
, st
);
1429 /* if we're at an :optional argument, check for an :opt_flag */
1430 if (dest
->sig
& PARROT_ARG_OPTIONAL
)
1431 check_for_opt_flag(st
, 1);
1434 /* otherwise this doesn't get reset and we can't catch positional args
1435 * inside of named args */
1439 check_named(interp
, st
);
1441 /* we may or may not have registered this pmc */
1443 dod_unregister_pmc(interp
, dest
->slurp
);
1449 =item C<void Parrot_convert_arg>
1451 Converts a source argument to the expected destination type.
1459 Parrot_convert_arg(PARROT_INTERP
, ARGMOD(call_state
*st
))
1461 /* register key args have to be cloned */
1462 if ((st
->src
.sig
& PARROT_ARG_TYPE_MASK
) == PARROT_ARG_PMC
)
1463 clone_key_arg(interp
, st
);
1465 /* if types are already equivalent, no need to convert */
1466 if (PARROT_ARG_TYPE(st
->dest
.sig
) == PARROT_ARG_TYPE(st
->src
.sig
))
1470 switch (st
->src
.sig
& PARROT_ARG_TYPE_MASK
) {
1471 case PARROT_ARG_INTVAL
: convert_arg_from_int(interp
, st
); break;
1472 case PARROT_ARG_FLOATVAL
: convert_arg_from_num(interp
, st
); break;
1473 case PARROT_ARG_STRING
: convert_arg_from_str(interp
, st
); break;
1474 case PARROT_ARG_PMC
: convert_arg_from_pmc(interp
, st
); break;
1483 =item C<void parrot_pass_args>
1485 Main argument passing routine.
1487 Prelims: code segments aren't yet switched, so the current constants are still
1488 that of the caller. The destination context is already created and set,
1489 C<src_ctx> point to the caller's context. C<dst_seg> has the constants of the
1492 C<what> is either C<PARROT_OP_get_params_pc> or C<PARROT_OP_get_results_pc>.
1493 With the former arguments are passed from the caller into a subroutine, the
1494 latter handles return values and yields.
1502 parrot_pass_args(PARROT_INTERP
,
1503 ARGMOD(parrot_context_t
*src_ctx
), ARGMOD(parrot_context_t
*dest_ctx
),
1504 ARGMOD(opcode_t
*src_indexes
), ARGMOD(opcode_t
*dest_indexes
),
1505 arg_pass_t param_or_result
)
1508 PMC
*src_signature
, *dest_signature
;
1510 if (param_or_result
== PARROT_PASS_PARAMS
) {
1511 src_signature
= interp
->args_signature
;
1512 dest_signature
= interp
->params_signature
;
1513 interp
->args_signature
= NULL
;
1514 interp
->params_signature
= NULL
;
1516 else /* (param_or_result == PARROT_PASS_RESULTS) */ {
1517 src_signature
= interp
->returns_signature
;
1518 dest_signature
= dest_ctx
->results_signature
;
1519 interp
->returns_signature
= NULL
;
1520 dest_ctx
->results_signature
= NULL
;
1523 Parrot_init_arg_indexes_and_sig_pmc(interp
, src_ctx
, src_indexes
,
1524 src_signature
, &st
.src
);
1526 Parrot_init_arg_indexes_and_sig_pmc(interp
, dest_ctx
, dest_indexes
,
1527 dest_signature
, &st
.dest
);
1529 Parrot_process_args(interp
, &st
, param_or_result
);
1531 /* If we created a slurpy, we had to DOD register it so it did not get
1532 * collected during arg processing; we'll now unregister it. */
1534 dod_unregister_pmc(interp
, st
.dest
.slurp
);
1540 =item C<opcode_t * parrot_pass_args_fromc>
1542 Passes arguments from C code with given signature to a Parrot Sub.
1543 Prerequisites are like above.
1549 PARROT_CANNOT_RETURN_NULL
1550 PARROT_WARN_UNUSED_RESULT
1552 parrot_pass_args_fromc(PARROT_INTERP
, ARGIN(const char *sig
),
1553 ARGMOD(opcode_t
*dest
), ARGIN(parrot_context_t
*old_ctxp
), va_list ap
)
1557 Parrot_init_arg_op(interp
, CONTEXT(interp
), dest
, &st
.dest
);
1558 Parrot_init_arg_sig(interp
, old_ctxp
, sig
, PARROT_VA_TO_VAPTR(ap
), &st
.src
);
1559 Parrot_process_args(interp
, &st
, PARROT_PASS_PARAMS
);
1560 return dest
+ st
.dest
.n
+ 2;
1566 =item C<static int set_retval_util>
1568 RT#48260: Not yet documented!!!
1575 set_retval_util(PARROT_INTERP
, ARGIN(const char *sig
),
1576 ARGIN(parrot_context_t
*ctx
), ARGMOD(call_state
*st
))
1578 opcode_t
* const src_pc
= interp
->current_returns
;
1579 int todo
= Parrot_init_arg_op(interp
, ctx
, src_pc
, &st
->src
);
1581 interp
->current_returns
= NULL
;
1584 todo
= Parrot_init_arg_sig(interp
, CONTEXT(interp
), sig
, NULL
,
1588 Parrot_fetch_arg(interp
, st
);
1589 Parrot_convert_arg(interp
, st
);
1600 =item C<void * set_retval>
1602 Handles void and pointer (PMC *, STRING *) return values. Returns a PMC,
1603 STRING, or NULL pointer as appropriate.
1609 PARROT_WARN_UNUSED_RESULT
1610 PARROT_CAN_RETURN_NULL
1612 set_retval(PARROT_INTERP
, int sig_ret
, ARGIN(parrot_context_t
*ctx
))
1616 if (!sig_ret
|| sig_ret
== 'v')
1621 if (set_retval_util(interp
, "S", ctx
, &st
))
1622 return UVal_str(st
.val
);
1624 if (set_retval_util(interp
, "P", ctx
, &st
)) {
1625 PMC
*retval
= UVal_pmc(st
.val
);
1626 dod_unregister_pmc(interp
, retval
);
1627 return (void *)retval
;
1637 =item C<INTVAL set_retval_i>
1639 Handles an INTVAL return value, returning its value if present and 0 otherwise.
1646 set_retval_i(PARROT_INTERP
, int sig_ret
, ARGIN(parrot_context_t
*ctx
))
1651 real_exception(interp
, NULL
, E_ValueError
, "return signature not 'I'");
1653 if (set_retval_util(interp
, "I", ctx
, &st
))
1654 return UVal_int(st
.val
);
1662 =item C<FLOATVAL set_retval_f>
1664 Handles a FLOATVAL return value, returning its value if present and 0.0
1672 set_retval_f(PARROT_INTERP
, int sig_ret
, ARGIN(parrot_context_t
*ctx
))
1677 real_exception(interp
, NULL
, E_ValueError
, "return signature not 'N'");
1679 if (set_retval_util(interp
, "N", ctx
, &st
))
1680 return UVal_num(st
.val
);
1688 =item C<STRING* set_retval_s>
1690 Handles a STRING return value, returning its pointer if present and NULL
1697 PARROT_CAN_RETURN_NULL
1698 PARROT_WARN_UNUSED_RESULT
1700 set_retval_s(PARROT_INTERP
, int sig_ret
, ARGIN(parrot_context_t
*ctx
))
1705 real_exception(interp
, NULL
, E_ValueError
, "return signature not 'S'");
1707 if (set_retval_util(interp
, "S", ctx
, &st
))
1708 return UVal_str(st
.val
);
1716 =item C<PMC* set_retval_p>
1718 Handles a PMC return value, returning the PMC pointer if present and NULL
1725 PARROT_CAN_RETURN_NULL
1726 PARROT_WARN_UNUSED_RESULT
1728 set_retval_p(PARROT_INTERP
, int sig_ret
, ARGIN(parrot_context_t
*ctx
))
1733 real_exception(interp
, NULL
, E_ValueError
, "return signature not 'P'");
1735 if (set_retval_util(interp
, "P", ctx
, &st
))
1736 return UVal_pmc(st
.val
);
1744 =item C<static void commit_last_arg>
1746 Called by Parrot_PCCINVOKE when it reaches the end of each arg in the arg
1747 signature. See C<Parrot_PCCINVOKE> for signature syntax.
1754 commit_last_arg(PARROT_INTERP
, int index
, int cur
,
1755 ARGMOD(opcode_t
*n_regs_used
), int seen_arrow
, ARGIN(PMC
* const *sigs
),
1756 ARGMOD(opcode_t
**indexes
), ARGMOD(parrot_context_t
*ctx
),
1757 ARGIN_NULLOK(PMC
*pmc
), ARGIN(va_list *list
))
1761 /* invocant already commited, just return */
1762 if (seen_arrow
== 0 && index
== 0 && pmc
)
1765 /* calculate arg's register offset */
1766 switch (cur
& PARROT_ARG_TYPE_MASK
) { /* calc reg offset */
1767 case PARROT_ARG_INTVAL
:
1768 reg_offset
= n_regs_used
[seen_arrow
* 4 + REGNO_INT
]++; break;
1769 case PARROT_ARG_FLOATVAL
:
1770 reg_offset
= n_regs_used
[seen_arrow
* 4 + REGNO_NUM
]++; break;
1771 case PARROT_ARG_STRING
:
1772 reg_offset
= n_regs_used
[seen_arrow
* 4 + REGNO_STR
]++; break;
1773 case PARROT_ARG_PMC
:
1774 reg_offset
= n_regs_used
[seen_arrow
* 4 + REGNO_PMC
]++; break;
1776 real_exception(interp
, NULL
, E_IndexError
,
1777 "Parrot_PCCINVOKE: invalid reg type");
1780 /* set the register offset into the index int[] */
1781 indexes
[seen_arrow
][index
] = reg_offset
;
1783 /* set the PARROT_ARG_FLAGS into the signature FIA */
1784 VTABLE_set_integer_keyed_int(interp
, sigs
[seen_arrow
], index
, cur
);
1786 /* perform the arg accessor function, assigning the arg to its
1787 * corresponding register */
1789 switch (cur
& PARROT_ARG_TYPE_MASK
) {
1790 case PARROT_ARG_INTVAL
:
1791 CTX_REG_INT(ctx
, reg_offset
) = va_arg(*list
, INTVAL
); break;
1792 case PARROT_ARG_FLOATVAL
:
1793 CTX_REG_NUM(ctx
, reg_offset
) = va_arg(*list
, FLOATVAL
); break;
1794 case PARROT_ARG_STRING
:
1795 CTX_REG_STR(ctx
, reg_offset
) = va_arg(*list
, STRING
*); break;
1796 case PARROT_ARG_PMC
:
1797 CTX_REG_PMC(ctx
, reg_offset
) = va_arg(*list
, PMC
*); break;
1799 real_exception(interp
, NULL
, E_IndexError
,
1800 "Parrot_PCCINVOKE: invalid reg type");
1808 =item C<void Parrot_PCCINVOKE>
1810 pmc is the invocant.
1812 method_name is the method_name used in the find_method VTABLE call
1814 signature is a string describing the Parrot calling conventions for
1815 Parrot_PCCINVOKE. ... variable args contains the IN arguments followed by the
1816 OUT results variables. You must pass the address_of(&) the OUT results of
1820 uppercase letters repesent each arg and denote its types
1827 lowercase letters are adverb modifiers to the preceeding uppercase arg
1836 -> is the separator between args and results, similar to type theory notation.
1838 Named args require two arg slots. The first is the name, the second the arg.
1844 The args to the method invocation are
1848 The results of the method invocation are
1853 invokes a PMC method
1861 Parrot_PCCINVOKE(PARROT_INTERP
, ARGIN(PMC
* pmc
), ARGMOD(STRING
*method_name
),
1862 ARGIN(const char *signature
), ...)
1864 #define PCC_ARG_MAX 1024
1865 /* variables from PCCINVOKE impl in PCCMETHOD.pm */
1866 /* args INSP, returns INSP */
1867 INTVAL n_regs_used
[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1869 /* Each of these is 8K. Do we want 16K on the stack? */
1870 opcode_t arg_indexes
[PCC_ARG_MAX
];
1871 opcode_t result_indexes
[PCC_ARG_MAX
];
1873 PMC
* const args_sig
= pmc_new(interp
, enum_class_FixedIntegerArray
);
1874 PMC
* const results_sig
= pmc_new(interp
, enum_class_FixedIntegerArray
);
1875 PMC
* const ret_cont
= new_ret_continuation_pmc(interp
, NULL
);
1877 parrot_context_t
*ctx
;
1878 PMC
*pccinvoke_meth
;
1880 opcode_t
*save_current_args
;
1881 PMC
*save_args_signature
;
1882 PMC
*save_current_object
;
1884 /* temporary state vars for building PCC index and PCC signature arrays. */
1886 /* arg_indexes, result_indexes */
1887 opcode_t
*indexes
[2];
1889 /* args_sig, results_sig */
1892 /* # of arg args, # of result args */
1893 int arg_ret_cnt
[2] = { 0, 0 };
1895 /* INSP args, INSP results */
1896 int max_regs
[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1900 const char *ret_x
= NULL
;
1905 va_start(list
, signature
);
1907 indexes
[0] = arg_indexes
;
1908 indexes
[1] = result_indexes
;
1910 sigs
[1] = results_sig
;
1912 /* account for passing invocant in-band */
1914 real_exception(interp
, NULL
, 1,
1915 "NULL PMC passed into Parrot_PCCINVOKE");
1917 arg_ret_cnt
[seen_arrow
]++;
1918 max_regs
[REGNO_PMC
]++;
1920 /* first loop through signature to get sizing info */
1921 for (x
= signature
; *x
!= '\0'; x
++) {
1924 /* detect -> separator */
1928 real_exception(interp
, NULL
, E_IndexError
,
1929 "Parrot_PCCINVOKE: invalid signature separator %c!",
1933 arg_ret_cnt
[seen_arrow
]++;
1934 max_regs
[seen_arrow
* 4 + REGNO_INT
]++;
1937 arg_ret_cnt
[seen_arrow
]++;
1938 max_regs
[seen_arrow
* 4 + REGNO_NUM
]++;
1941 arg_ret_cnt
[seen_arrow
]++;
1942 max_regs
[seen_arrow
* 4 + REGNO_STR
]++;
1945 arg_ret_cnt
[seen_arrow
]++;
1946 max_regs
[seen_arrow
* 4 + REGNO_PMC
]++;
1955 real_exception(interp
, NULL
, E_IndexError
,
1956 "Parrot_PCCINVOKE: invalid reg type %c!", *x
);
1960 /* calculate max reg types needed for both args and results */
1961 n_regs_used
[0] = PARROT_MAX(max_regs
[0], max_regs
[4]);
1962 n_regs_used
[1] = PARROT_MAX(max_regs
[1], max_regs
[5]);
1963 n_regs_used
[2] = PARROT_MAX(max_regs
[2], max_regs
[6]);
1964 n_regs_used
[3] = PARROT_MAX(max_regs
[3], max_regs
[7]);
1966 /* initialize arg and return sig FIAs with collected info */
1967 if (arg_ret_cnt
[0] > 0)
1968 VTABLE_set_integer_native(interp
, args_sig
, arg_ret_cnt
[0]);
1970 if (arg_ret_cnt
[1] > 0)
1971 VTABLE_set_integer_native(interp
, results_sig
, arg_ret_cnt
[1]);
1973 ctx
= Parrot_push_context(interp
, n_regs_used
);
1975 /* reset n_regs_used for reuse reused during arg index allocation step */
1981 /* second loop through signature to build all index and arg_flag
1982 * loop also assigns args(up to the ->) to registers */
1986 /* account for passing invocant in-band */
1989 VTABLE_set_integer_keyed_int(interp
, sigs
[0], 0, PARROT_ARG_PMC
);
1990 CTX_REG_PMC(ctx
, 0) = pmc
;
1992 n_regs_used
[seen_arrow
* 4 + REGNO_PMC
]++;
1995 for (x
= signature
; *x
!= '\0'; x
++) {
1996 /* detect -> separator */
2002 /* allows us to jump directly to the result signature portion
2003 * during results assignment */
2006 /* save off pointer to results */
2010 commit_last_arg(interp
, index
, cur
, n_regs_used
, seen_arrow
,
2011 sigs
, indexes
, ctx
, pmc
, &list
);
2013 /* reset parsing state so we can now handle results */
2017 /* reset n_regs_used for reuse during result index allocation */
2023 /* parse arg type */
2024 else if (isupper((unsigned char)*x
)) {
2026 commit_last_arg(interp
, index
, cur
, n_regs_used
, seen_arrow
,
2027 sigs
, indexes
, ctx
, pmc
, &list
);
2032 case 'I': cur
= PARROT_ARG_INTVAL
; break;
2033 case 'N': cur
= PARROT_ARG_FLOATVAL
; break;
2034 case 'S': cur
= PARROT_ARG_STRING
; break;
2035 case 'P': cur
= PARROT_ARG_PMC
; break;
2037 real_exception(interp
, NULL
, E_IndexError
,
2038 "Parrot_PCCINVOKE: invalid reg type %c!", *x
);
2042 /* parse arg adverbs */
2043 else if (islower((unsigned char)*x
)) {
2045 case 'n': cur
|= PARROT_ARG_NAME
; break;
2046 case 'f': cur
|= PARROT_ARG_FLATTEN
; break;
2047 case 's': cur
|= PARROT_ARG_SLURPY_ARRAY
; break;
2048 case 'o': cur
|= PARROT_ARG_OPTIONAL
; break;
2049 case 'p': cur
|= PARROT_ARG_OPT_FLAG
; break;
2051 real_exception(interp
, NULL
, E_IndexError
,
2052 "Parrot_PCCINVOKE: invalid adverb type %c!", *x
);
2058 commit_last_arg(interp
, index
, cur
, n_regs_used
, seen_arrow
, sigs
,
2059 indexes
, ctx
, pmc
, &list
);
2061 /* code from PCCINVOKE impl in PCCMETHOD.pm */
2062 save_current_args
= interp
->current_args
;
2063 save_args_signature
= interp
->args_signature
;
2064 save_current_object
= interp
->current_object
;
2066 interp
->current_args
= arg_indexes
;
2067 interp
->args_signature
= args_sig
;
2068 ctx
->current_results
= result_indexes
;
2069 ctx
->results_signature
= results_sig
;
2071 /* arg_accessors assigned in loop above */
2073 interp
->current_object
= pmc
;
2074 interp
->current_cont
= NEED_CONTINUATION
;
2075 ctx
->current_cont
= ret_cont
;
2076 PMC_cont(ret_cont
)->from_ctx
= ctx
;
2078 pccinvoke_meth
= VTABLE_find_method(interp
, pmc
, method_name
);
2080 if (PMC_IS_NULL(pccinvoke_meth
))
2081 real_exception(interp
, NULL
, METH_NOT_FOUND
, "Method '%Ss' not found",
2084 VTABLE_invoke(interp
, pccinvoke_meth
, NULL
);
2086 /* result_accessors perform the arg accessor function,
2087 * assigning the corresponding registers to the result variables */
2091 for (x
= ret_x
; x
&& *x
; x
++) {
2092 if (isupper((unsigned char)*x
)) {
2096 INTVAL
* const tmpINTVAL
= va_arg(list
, INTVAL
*);
2097 *tmpINTVAL
= CTX_REG_INT(ctx
, indexes
[seen_arrow
][index
]);
2102 FLOATVAL
* const tmpFLOATVAL
= va_arg(list
, FLOATVAL
*);
2103 *tmpFLOATVAL
= CTX_REG_NUM(ctx
, indexes
[seen_arrow
][index
]);
2108 STRING
** const tmpSTRING
= va_arg(list
, STRING
**);
2109 *tmpSTRING
= CTX_REG_STR(ctx
, indexes
[seen_arrow
][index
]);
2114 PMC
** const tmpPMC
= va_arg(list
, PMC
**);
2115 *tmpPMC
= CTX_REG_PMC(ctx
, indexes
[seen_arrow
][index
]);
2119 real_exception(interp
, NULL
, E_IndexError
,
2120 "Parrot_PCCINVOKE: invalid reg type %c!", *x
);
2125 PObj_live_CLEAR(args_sig
);
2126 PObj_live_CLEAR(results_sig
);
2128 Parrot_pop_context(interp
);
2130 interp
->current_args
= save_current_args
;
2131 interp
->args_signature
= save_args_signature
;
2132 interp
->current_object
= save_current_object
;
2142 F<include/parrot/interpreter.h>, F<src/inter_run.c>, F<src/pmc/sub.pmc>.
2150 * c-file-style: "parrot"
2152 * vim: expandtab shiftwidth=4: