tagged release 0.6.4
[parrot.git] / src / inter_call.c
blobe04f328528571118d598d8e6c6d13571e046f142
1 /*
2 Copyright (C) 2001-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/inter_call.c - Parrot Interpreter - Argument passing code
9 =head1 DESCRIPTION
11 Functions in this file handle argument/return value passing to and from
12 subroutines.
14 =head2 Functions
16 =over 4
18 =cut
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)
33 FUNC_MODIFIES(*st);
35 static void check_named(PARROT_INTERP, ARGMOD(call_state *st))
36 __attribute__nonnull__(1)
37 __attribute__nonnull__(2)
38 FUNC_MODIFIES(*st);
40 static void clone_key_arg(PARROT_INTERP, ARGMOD(call_state *st))
41 __attribute__nonnull__(1)
42 __attribute__nonnull__(2)
43 FUNC_MODIFIES(*st);
45 static void commit_last_arg(PARROT_INTERP,
46 int index,
47 int cur,
48 ARGMOD(opcode_t *n_regs_used),
49 int seen_arrow,
50 ARGIN(PMC * const *sigs),
51 ARGMOD(opcode_t **indexes),
52 ARGMOD(parrot_context_t *ctx),
53 ARGIN_NULLOK(PMC *pmc),
54 ARGIN(va_list *list))
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)
63 FUNC_MODIFIES(*ctx);
65 static void convert_arg_from_int(PARROT_INTERP, ARGMOD(call_state *st))
66 __attribute__nonnull__(1)
67 __attribute__nonnull__(2)
68 FUNC_MODIFIES(*st);
70 static void convert_arg_from_num(PARROT_INTERP, ARGMOD(call_state *st))
71 __attribute__nonnull__(1)
72 __attribute__nonnull__(2)
73 FUNC_MODIFIES(*st);
75 static void convert_arg_from_pmc(PARROT_INTERP, ARGMOD(call_state *st))
76 __attribute__nonnull__(1)
77 __attribute__nonnull__(2)
78 FUNC_MODIFIES(*st);
80 static void convert_arg_from_str(PARROT_INTERP, ARGMOD(call_state *st))
81 __attribute__nonnull__(1)
82 __attribute__nonnull__(2)
83 FUNC_MODIFIES(*st);
85 static int fetch_arg_op(PARROT_INTERP, ARGMOD(call_state *st))
86 __attribute__nonnull__(1)
87 __attribute__nonnull__(2)
88 FUNC_MODIFIES(*st);
90 static int fetch_arg_sig(PARROT_INTERP, ARGMOD(call_state *st))
91 __attribute__nonnull__(1)
92 __attribute__nonnull__(2)
93 FUNC_MODIFIES(*st);
95 static void init_call_stats(ARGMOD(call_state *st))
96 __attribute__nonnull__(1)
97 FUNC_MODIFIES(*st);
99 static void init_first_dest_named(PARROT_INTERP, ARGMOD(call_state *st))
100 __attribute__nonnull__(1)
101 __attribute__nonnull__(2)
102 FUNC_MODIFIES(*st);
104 static int locate_named_named(PARROT_INTERP, ARGMOD(call_state *st))
105 __attribute__nonnull__(1)
106 __attribute__nonnull__(2)
107 FUNC_MODIFIES(*st);
109 static void next_arg_sig(ARGMOD(call_state_item *sti))
110 __attribute__nonnull__(1)
111 FUNC_MODIFIES(*sti);
113 static void null_val(int sig, ARGMOD(call_state *st))
114 __attribute__nonnull__(2)
115 FUNC_MODIFIES(*st);
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)
125 FUNC_MODIFIES(*st);
127 static void start_flatten(PARROT_INTERP,
128 ARGMOD(call_state *st),
129 ARGIN(PMC *p_arg))
130 __attribute__nonnull__(1)
131 __attribute__nonnull__(2)
132 __attribute__nonnull__(3)
133 FUNC_MODIFIES(*st);
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
175 signature.
177 =cut
181 PARROT_API
182 void
183 Parrot_init_arg_nci(PARROT_INTERP, ARGOUT(call_state *st),
184 ARGIN(const char *sig))
186 init_call_stats(st);
188 if (PMC_IS_NULL(interp->args_signature))
189 Parrot_init_arg_op(interp, CONTEXT(interp), interp->current_args,
190 &st->src);
191 else
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
204 signature.
206 =cut
210 PARROT_API
211 void
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,
233 and a signature PMC.
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.
240 =cut
244 PARROT_API
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) {
251 ++indexes;
252 sig_pmc = ctx->constants[*indexes]->u.key;
253 ASSERT_SIG_PMC(sig_pmc);
254 ++indexes;
257 sti->used = 1;
258 sti->i = 0;
259 sti->n = 0;
260 sti->mode = CALL_STATE_OP;
261 sti->ctx = ctx;
262 sti->sig = 0;
263 sti->slurp = NULL;
265 if (indexes) {
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 */
272 if (sti->n)
273 next_arg_sig(sti);
276 return sti->n > 0;
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.
287 =cut
291 PARROT_API
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;
298 if (pc) {
299 ++pc;
300 sig_pmc = ctx->constants[*pc]->u.key;
301 ASSERT_SIG_PMC(sig_pmc);
302 ++pc;
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.
316 =cut
320 PARROT_API
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))
326 sti->used = 1;
327 sti->i = 0;
328 sti->n = 0;
329 sti->mode = CALL_STATE_SIG;
330 sti->ctx = ctx;
331 sti->sig = 0;
333 if (*sig) {
334 sti->u.sig.sig = sig;
335 sti->u.sig.ap = ap;
336 sti->n = strlen(sig);
338 /* initialize st->sig */
339 if (sti->n)
340 next_arg_sig(sti);
343 return sti->n > 0;
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.
354 =cut
358 static void
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);
373 else {
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;
381 st->src.slurp_i = 0;
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.
396 =cut
400 static void
401 next_arg_sig(ARGMOD(call_state_item *sti))
403 switch (sti->mode & CALL_S_D_MASK) {
404 case CALL_STATE_OP:
405 sti->sig = SIG_ITEM(sti->u.op.signature, sti->i);
406 break;
407 case CALL_STATE_SIG:
408 switch (sti->u.sig.sig[sti->i]) {
409 case 'I':
410 sti->sig = PARROT_ARG_INTVAL; break;
411 case 'N':
412 sti->sig = PARROT_ARG_FLOATVAL; break;
413 case 'S':
414 sti->sig = PARROT_ARG_STRING; break;
415 case 'O':
416 case 'P':
417 sti->sig = PARROT_ARG_PMC; break;
418 case '@':
419 sti->sig = PARROT_ARG_PMC | PARROT_ARG_SLURPY_ARRAY; break;
420 case 'F':
421 sti->sig = PARROT_ARG_PMC | PARROT_ARG_FLATTEN; break;
422 default:
423 break;
425 break;
426 default:
427 break;
434 =item C<static int fetch_arg_sig>
436 Fetches the next argument from the signature in the given call state.
438 =cut
442 /* Fetch an argument from C code */
443 static int
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);
451 break;
452 case PARROT_ARG_STRING:
453 UVal_str(st->val) = va_arg(*ap, STRING *);
454 break;
455 case PARROT_ARG_FLOATVAL:
456 UVal_num(st->val) = va_arg(*ap, FLOATVAL);
457 break;
458 case PARROT_ARG_PMC:
459 if (st->src.u.sig.sig[st->src.i] == 'O')
460 UVal_pmc(st->val) = CONTEXT(interp)->current_object;
461 else {
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) {
467 int retval;
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;
473 st->src.i++;
476 st->src.used = 1;
477 retval = Parrot_fetch_arg(interp, st);
479 if (!PMC_IS_NULL(st->key))
480 dod_unregister_pmc(interp, st->key);
482 return retval;
484 break;
485 default:
486 break;
489 st->src.i++;
490 return 1;
496 =item C<static int fetch_arg_op>
498 Fetches an argument from the appropriate context.
500 =cut
504 static int
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);
513 break;
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);
517 break;
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);
521 break;
522 case PARROT_ARG_PMC:
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) {
527 int retval;
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;
533 st->src.i++;
536 st->src.used = 1;
537 retval = Parrot_fetch_arg(interp, st);
539 if (!PMC_IS_NULL(st->key))
540 dod_unregister_pmc(interp, st->key);
542 return retval;
544 break;
545 default:
546 break;
549 st->src.i++;
550 return 1;
556 =item C<int Parrot_fetch_arg>
558 RT#48260: Not yet documented!!!
560 =cut
564 /* Fetch a new argument.
566 PARROT_API
568 Parrot_fetch_arg(PARROT_INTERP, ARGMOD(call_state *st))
570 if (!st->src.used)
571 return 1;
573 if (st->src.i >= st->src.n)
574 return 0;
576 st->src.used = 0;
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)) {
584 st->src.slurp_i++;
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);
591 else {
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);
605 st->key = PMCNULL;
606 st->src.i++;
609 return 1;
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) {
622 case CALL_STATE_OP:
623 return fetch_arg_op(interp, st);
624 case CALL_STATE_SIG:
625 return fetch_arg_sig(interp, st);
626 default:
627 real_exception(interp, NULL, 1, "invalid call state mode");
634 =item C<int Parrot_fetch_arg_nci>
636 RT#48260: Not yet documented!!!
638 =cut
642 PARROT_API
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)) {
654 st->src.used = 1;
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);
662 else {
663 Parrot_fetch_arg(interp, st);
664 st->src.used = 1;
665 Parrot_convert_arg(interp, st);
668 st->dest.i++;
669 return 1;
675 =item C<static void convert_arg_from_int>
677 Autoboxes an int into the expected container type.
679 =cut
683 static void
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);
689 break;
690 case PARROT_ARG_STRING:
691 UVal_str(st->val) = string_from_int(interp, UVal_int(st->val));
692 break;
693 case PARROT_ARG_PMC:
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);
702 break;
703 default:
704 break;
711 =item C<static void convert_arg_from_num>
713 Autoboxes a num into the expected container type.
715 =cut
719 static void
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);
725 break;
726 case PARROT_ARG_STRING:
727 UVal_str(st->val) = string_from_num(interp, UVal_num(st->val));
728 break;
729 case PARROT_ARG_PMC:
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);
738 break;
739 default:
740 break;
747 =item C<static void convert_arg_from_str>
749 Autoboxes a string primitive to the expected container type.
751 =cut
755 static void
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));
761 break;
762 case PARROT_ARG_FLOATVAL:
763 UVal_num(st->val) = string_to_num(interp, UVal_str(st->val));
764 break;
765 case PARROT_ARG_PMC:
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);
774 break;
775 default:
776 break;
782 =item C<static void convert_arg_from_pmc>
784 Unboxes a PMC to the expected primitive type.
786 =cut
790 static void
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));
796 break;
797 case PARROT_ARG_FLOATVAL:
798 UVal_num(st->val) = VTABLE_get_number(interp, UVal_pmc(st->val));
799 break;
800 case PARROT_ARG_STRING:
801 UVal_str(st->val) = VTABLE_get_string(interp, UVal_pmc(st->val));
802 break;
803 default:
804 break;
811 =item C<static void check_for_opt_flag>
813 Processes the next argument, if it has the optional flag set. Otherwise moves
816 =cut
820 static void
821 check_for_opt_flag(ARGMOD(call_state *st), int has_arg)
823 INTVAL idx;
824 call_state_item * const dest = &st->dest;
826 ++st->optionals;
828 /* look at the next arg */
829 dest->i++;
830 if (dest->i >= dest->n)
831 return;
833 next_arg_sig(dest);
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)) {
838 dest->i--;
839 return;
842 /* we're at an :opt_flag argument, so actually store something */
843 idx = st->dest.u.op.pc[st->dest.i];
845 --st->params;
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.
859 =cut
863 static void
864 clone_key_arg(PARROT_INTERP, ARGMOD(call_state *st))
866 PMC *key = UVal_pmc(st->val);
868 if (!key)
869 return;
871 if (key->vtable->base_type != enum_class_Key)
872 return;
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)
883 return;
891 =item C<static void init_first_dest_named>
893 Initializes dest calling state for the first named arg.
895 =cut
899 static void
900 init_first_dest_named(PARROT_INTERP, ARGMOD(call_state *st))
902 int i, n_named;
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;
909 n_named = 0;
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))
922 continue;
924 /* slurpy named args, create slurpy hash */
925 else if (sig & PARROT_ARG_SLURPY_ARRAY) {
926 int idx;
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 */
939 else
940 n_named++;
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");
948 st->named_done = 0;
954 =item C<static int locate_named_named>
956 Locates a destination argument name, returning 0 if not found.
958 =cut
962 static int
963 locate_named_named(PARROT_INTERP, ARGMOD(call_state *st))
965 int i;
966 int n_named = -1;
968 for (i = st->first_named; i < st->dest.n; ++i) {
969 int idx;
970 STRING *param;
972 st->dest.sig = SIG_ITEM(st->dest.u.op.signature, i);
973 if (!(st->dest.sig & PARROT_ARG_NAME))
974 continue;
976 if (st->dest.sig & PARROT_ARG_SLURPY_ARRAY)
977 return 1;
979 n_named++;
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) {
986 ++i;
987 st->dest.sig = SIG_ITEM(st->dest.u.op.signature, i);
988 st->dest.i = 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;
996 return 1;
1000 return 0;
1006 =item C<static void store_arg>
1008 Stores the next argument in the destination register appropriately.
1010 =cut
1014 static void
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);
1020 break;
1021 case PARROT_ARG_FLOATVAL:
1022 CTX_REG_NUM(st->dest.ctx, idx) = UVal_num(st->val);
1023 break;
1024 case PARROT_ARG_STRING:
1025 CTX_REG_STR(st->dest.ctx, idx) = UVal_str(st->val);
1026 break;
1027 case PARROT_ARG_PMC:
1028 CTX_REG_PMC(st->dest.ctx, idx) = UVal_pmc(st->val);
1029 break;
1030 default:
1031 break;
1038 =item C<int Parrot_store_arg>
1040 RT#48260: Not yet documented!!!
1042 =cut
1047 Parrot_store_arg(SHIM_INTERP, ARGIN(const call_state *st))
1049 INTVAL idx;
1050 if (st->dest.i >= st->dest.n)
1051 return 0;
1053 PARROT_ASSERT(st->dest.mode & CALL_STATE_OP);
1054 idx = st->dest.u.op.pc[st->dest.i];
1055 PARROT_ASSERT(idx >= 0);
1056 store_arg(st, idx);
1058 return 1;
1064 =item C<static void too_few>
1066 Throws an exception if there are too few arguments passed.
1068 =cut
1072 static void
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",
1081 st->n_actual_args,
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.
1094 =cut
1098 static void
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",
1107 st->n_actual_args,
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.
1120 =cut
1124 static void
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;
1132 default:
1133 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
1153 =cut
1157 static void
1158 check_named(PARROT_INTERP, ARGMOD(call_state *st))
1160 int i;
1161 int n_named = -1;
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) {
1167 INTVAL arg_sig;
1168 int last_name_pos;
1170 /* if slurpy then no errors, return */
1171 if (sig & PARROT_ARG_SLURPY_ARRAY)
1172 return;
1174 n_named++;
1175 last_name_pos = i;
1177 /* move on to the actual arg */
1178 i++;
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)
1190 i++;
1192 continue;
1194 else if (arg_sig & PARROT_ARG_OPTIONAL) {
1195 INTVAL idx;
1196 null_val(arg_sig, st);
1197 idx = st->dest.u.op.pc[i];
1198 store_arg(st, idx);
1200 /* Don't walk off the end of the array */
1201 if (i+1 >= st->dest.n)
1202 continue;
1203 arg_sig = st->dest.sig = SIG_ITEM(st->dest.u.op.signature, i+1);
1204 if (arg_sig & PARROT_ARG_OPT_FLAG) {
1205 i++;
1206 idx = st->dest.u.op.pc[i];
1207 CTX_REG_INT(st->dest.ctx, idx) = 0;
1209 continue;
1211 else {
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);
1222 else
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>.
1235 =cut
1239 static void
1240 init_call_stats(ARGMOD(call_state *st))
1242 /* initial guess, adjusted for :flat args */
1243 st->n_actual_args = st->src.n;
1245 st->optionals = 0;
1246 st->params = st->dest.n;
1247 st->name = NULL;
1248 st->key = PMCNULL;
1249 st->first_named = -1;
1255 =item C<void Parrot_process_args>
1257 RT#48260: Not yet documented!!!
1259 =cut
1263 PARROT_API
1264 void
1265 Parrot_process_args(PARROT_INTERP, ARGMOD(call_state *st), arg_pass_t param_or_result)
1267 int n_named;
1268 int err_check = 1;
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))
1278 err_check = 0;
1280 else if (!PARROT_ERRORS_test(interp, PARROT_ERRORS_PARAM_COUNT_FLAG))
1281 err_check = 0;
1283 init_call_stats(st);
1285 src = &st->src;
1286 dest = &st->dest;
1288 /* 1st: Positional non-:slurpy */
1289 for (; dest->i < dest->n; dest->i++) {
1290 INTVAL idx;
1291 int has_arg;
1293 /* check if the next dest arg is :slurpy */
1294 next_arg_sig(dest);
1295 if (dest->sig & PARROT_ARG_SLURPY_ARRAY)
1296 break;
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
1300 * argument. */
1301 has_arg = Parrot_fetch_arg(interp, st);
1303 /* if the src arg is named, we're done here */
1304 if (st->name) {
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);
1312 store_arg(st, idx);
1314 check_for_opt_flag(st, 0);
1316 /* next dest arg */
1317 dest->i++;
1318 next_arg_sig(dest);
1320 break;
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) {
1326 if (!has_arg)
1327 break;
1328 dest->i++;
1329 next_arg_sig(dest);
1332 /* if there *is* an arg, convert it */
1333 if (has_arg) {
1334 src->used = 1;
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) */
1343 else if (err_check)
1344 too_few(interp, st, action);
1346 /* otherwise, we're done */
1347 else
1348 return;
1350 /* actually store the argument */
1351 idx = st->dest.u.op.pc[st->dest.i];
1352 PARROT_ASSERT(idx >= 0);
1353 store_arg(st, idx);
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
1368 * references it. */
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 */
1374 if (st->name)
1375 break;
1377 src->used = 1;
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));
1386 dest->i++;
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)
1397 return;
1399 /* 3rd: :named */
1400 init_first_dest_named(interp, st);
1401 n_named = 0;
1403 while (Parrot_fetch_arg(interp, st)) {
1404 src->used = 1;
1406 if (!st->name)
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);
1416 n_named++;
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));
1425 else {
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 */
1436 st->name = NULL;
1439 check_named(interp, st);
1441 /* we may or may not have registered this pmc */
1442 if (dest->slurp)
1443 dod_unregister_pmc(interp, dest->slurp);
1449 =item C<void Parrot_convert_arg>
1451 Converts a source argument to the expected destination type.
1453 =cut
1457 PARROT_API
1458 void
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))
1467 return;
1469 /* convert */
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;
1475 default:
1476 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
1490 destination.
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.
1496 =cut
1500 PARROT_API
1501 void
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)
1507 call_state st;
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. */
1533 if (st.dest.slurp)
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.
1545 =cut
1549 PARROT_CANNOT_RETURN_NULL
1550 PARROT_WARN_UNUSED_RESULT
1551 opcode_t *
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)
1555 call_state st;
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!!!
1570 =cut
1574 static int
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;
1583 if (todo) {
1584 todo = Parrot_init_arg_sig(interp, CONTEXT(interp), sig, NULL,
1585 &st->dest);
1587 if (todo) {
1588 Parrot_fetch_arg(interp, st);
1589 Parrot_convert_arg(interp, st);
1590 return 1;
1594 return 0;
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.
1605 =cut
1609 PARROT_WARN_UNUSED_RESULT
1610 PARROT_CAN_RETURN_NULL
1611 void *
1612 set_retval(PARROT_INTERP, int sig_ret, ARGIN(parrot_context_t *ctx))
1614 call_state st;
1616 if (!sig_ret || sig_ret == 'v')
1617 return NULL;
1619 switch (sig_ret) {
1620 case 'S':
1621 if (set_retval_util(interp, "S", ctx, &st))
1622 return UVal_str(st.val);
1623 case 'P':
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;
1629 default:
1630 return NULL;
1637 =item C<INTVAL set_retval_i>
1639 Handles an INTVAL return value, returning its value if present and 0 otherwise.
1641 =cut
1645 INTVAL
1646 set_retval_i(PARROT_INTERP, int sig_ret, ARGIN(parrot_context_t *ctx))
1648 call_state st;
1650 if (sig_ret != 'I')
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);
1656 return 0;
1662 =item C<FLOATVAL set_retval_f>
1664 Handles a FLOATVAL return value, returning its value if present and 0.0
1665 otherwise.
1667 =cut
1671 FLOATVAL
1672 set_retval_f(PARROT_INTERP, int sig_ret, ARGIN(parrot_context_t *ctx))
1674 call_state st;
1676 if (sig_ret != 'N')
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);
1682 return 0.0;
1688 =item C<STRING* set_retval_s>
1690 Handles a STRING return value, returning its pointer if present and NULL
1691 otherwise.
1693 =cut
1697 PARROT_CAN_RETURN_NULL
1698 PARROT_WARN_UNUSED_RESULT
1699 STRING*
1700 set_retval_s(PARROT_INTERP, int sig_ret, ARGIN(parrot_context_t *ctx))
1702 call_state st;
1704 if (sig_ret != 'S')
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);
1710 return NULL;
1716 =item C<PMC* set_retval_p>
1718 Handles a PMC return value, returning the PMC pointer if present and NULL
1719 otherwise.
1721 =cut
1725 PARROT_CAN_RETURN_NULL
1726 PARROT_WARN_UNUSED_RESULT
1727 PMC*
1728 set_retval_p(PARROT_INTERP, int sig_ret, ARGIN(parrot_context_t *ctx))
1730 call_state st;
1732 if (sig_ret != 'P')
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);
1738 return NULL;
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.
1749 =cut
1753 static void
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))
1759 int reg_offset = 0;
1761 /* invocant already commited, just return */
1762 if (seen_arrow == 0 && index == 0 && pmc)
1763 return;
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;
1775 default:
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 */
1788 if (!seen_arrow) {
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;
1798 default:
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
1817 course.
1819 Signatures:
1820 uppercase letters repesent each arg and denote its types
1822 I INTVAL
1823 N FLOATVAL
1824 S STRING *
1825 P PMC *
1827 lowercase letters are adverb modifiers to the preceeding uppercase arg
1828 identifier
1830 f flatten
1831 n named
1832 s slurpy
1833 o optional
1834 p opt flag
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.
1840 Example signature:
1842 "SnIPf->INPs"
1844 The args to the method invocation are
1845 a named INTVAL: SnI
1846 a flattened PMC: Pf
1848 The results of the method invocation are
1849 a INTVAL: I
1850 a FLOATVAL: N
1851 a slurpy PMC: Ps
1853 invokes a PMC method
1855 =cut
1859 PARROT_API
1860 void
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 */
1890 PMC *sigs[2];
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 };
1897 int seen_arrow = 0;
1899 const char *x;
1900 const char *ret_x = NULL;
1901 int index = -1;
1902 int cur = 0;
1904 va_list list;
1905 va_start(list, signature);
1907 indexes[0] = arg_indexes;
1908 indexes[1] = result_indexes;
1909 sigs[0] = args_sig;
1910 sigs[1] = results_sig;
1912 /* account for passing invocant in-band */
1913 if (!pmc)
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++) {
1922 switch (*x) {
1923 case '-':
1924 /* detect -> separator */
1925 seen_arrow = 1 ;
1926 ++x;
1927 if (*x != '>')
1928 real_exception(interp, NULL, E_IndexError,
1929 "Parrot_PCCINVOKE: invalid signature separator %c!",
1930 *x);
1931 break;
1932 case 'I':
1933 arg_ret_cnt[seen_arrow]++;
1934 max_regs[seen_arrow * 4 + REGNO_INT]++;
1935 break;
1936 case 'N':
1937 arg_ret_cnt[seen_arrow]++;
1938 max_regs[seen_arrow * 4 + REGNO_NUM]++;
1939 break;
1940 case 'S':
1941 arg_ret_cnt[seen_arrow]++;
1942 max_regs[seen_arrow * 4 + REGNO_STR]++;
1943 break;
1944 case 'P':
1945 arg_ret_cnt[seen_arrow]++;
1946 max_regs[seen_arrow * 4 + REGNO_PMC]++;
1947 break;
1948 case 'f':
1949 case 'n':
1950 case 's':
1951 case 'o':
1952 case 'p':
1953 break;
1954 default:
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 */
1976 n_regs_used[0] = 0;
1977 n_regs_used[1] = 0;
1978 n_regs_used[2] = 0;
1979 n_regs_used[3] = 0;
1981 /* second loop through signature to build all index and arg_flag
1982 * loop also assigns args(up to the ->) to registers */
1983 index = -1;
1984 seen_arrow = 0;
1986 /* account for passing invocant in-band */
1987 indexes[0][0] = 0;
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]++;
1993 index = 0;
1995 for (x = signature; *x != '\0'; x++) {
1996 /* detect -> separator */
1997 if (*x == '-') {
1999 /* skip '>' */
2000 x++;
2002 /* allows us to jump directly to the result signature portion
2003 * during results assignment */
2004 ret_x = x;
2006 /* save off pointer to results */
2007 ret_x++;
2009 if (index >= 0)
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 */
2014 seen_arrow = 1;
2015 index = -1;
2017 /* reset n_regs_used for reuse during result index allocation */
2018 n_regs_used[0] = 0;
2019 n_regs_used[1] = 0;
2020 n_regs_used[2] = 0;
2021 n_regs_used[3] = 0;
2023 /* parse arg type */
2024 else if (isupper((unsigned char)*x)) {
2025 if (index >= 0)
2026 commit_last_arg(interp, index, cur, n_regs_used, seen_arrow,
2027 sigs, indexes, ctx, pmc, &list);
2029 index++;
2031 switch (*x) {
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;
2036 default:
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)) {
2044 switch (*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;
2050 default:
2051 real_exception(interp, NULL, E_IndexError,
2052 "Parrot_PCCINVOKE: invalid adverb type %c!", *x);
2057 if (index >= 0)
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;
2077 ctx->ref_count++;
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",
2082 method_name);
2083 else
2084 VTABLE_invoke(interp, pccinvoke_meth, NULL);
2086 /* result_accessors perform the arg accessor function,
2087 * assigning the corresponding registers to the result variables */
2088 index = 0;
2089 seen_arrow = 1;
2091 for (x = ret_x; x && *x; x++) {
2092 if (isupper((unsigned char)*x)) {
2093 switch (*x) {
2094 case 'I':
2096 INTVAL * const tmpINTVAL = va_arg(list, INTVAL*);
2097 *tmpINTVAL = CTX_REG_INT(ctx, indexes[seen_arrow][index]);
2099 break;
2100 case 'N':
2102 FLOATVAL * const tmpFLOATVAL = va_arg(list, FLOATVAL*);
2103 *tmpFLOATVAL = CTX_REG_NUM(ctx, indexes[seen_arrow][index]);
2105 break;
2106 case 'S':
2108 STRING ** const tmpSTRING = va_arg(list, STRING**);
2109 *tmpSTRING = CTX_REG_STR(ctx, indexes[seen_arrow][index]);
2111 break;
2112 case 'P':
2114 PMC ** const tmpPMC = va_arg(list, PMC**);
2115 *tmpPMC = CTX_REG_PMC(ctx, indexes[seen_arrow][index]);
2117 break;
2118 default:
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;
2138 =back
2140 =head1 SEE ALSO
2142 F<include/parrot/interpreter.h>, F<src/inter_run.c>, F<src/pmc/sub.pmc>.
2144 =cut
2149 * Local variables:
2150 * c-file-style: "parrot"
2151 * End:
2152 * vim: expandtab shiftwidth=4: