2 Copyright (C) 2001-2010, Parrot Foundation.
7 src/pmc/sub.pmc - Subroutine
11 These are the vtable functions for the Sub (subroutine) base class
21 #include "parrot/oplib/ops.h"
22 #include "parrot/oplib/core_ops.h"
25 /* HEADERIZER HFILE: none */
26 /* HEADERIZER BEGIN: static */
27 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
29 static void print_sub_name(PARROT_INTERP, ARGIN_NULLOK(PMC *sub))
30 __attribute__nonnull__(1);
32 #define ASSERT_ARGS_print_sub_name __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
33 PARROT_ASSERT_ARG(interp))
34 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
35 /* HEADERIZER END: static */
39 =item C<static void print_sub_name(PARROT_INTERP, PMC *sub)>
46 print_sub_name(PARROT_INTERP, ARGIN_NULLOK(PMC *sub))
48 ASSERT_ARGS(print_sub_name)
49 Interp * const tracer = (interp->pdb && interp->pdb->debugger)
50 ? interp->pdb->debugger
53 /* sub was located via globals */
54 Parrot_io_eprintf(tracer, "# Calling sub '%Ss'\n# ",
55 Parrot_full_sub_name(interp, sub));
57 print_pbc_location(interp);
60 pmclass Sub auto_attrs provides invokable {
61 ATTR PackFile_ByteCode *seg; /* bytecode segment */
62 ATTR size_t start_offs; /* sub entry in ops from seg->base.data */
65 ATTR INTVAL HLL_id; /* see src/hll.c XXX or per segment? */
66 ATTR PMC *namespace_name; /* where this Sub is in - this is either
67 * a String or a [Key] and describes
68 * the relative path in the NameSpace
70 ATTR PMC *namespace_stash; /* the actual hash, HLL::namespace */
71 ATTR STRING *name; /* name of the sub */
72 ATTR STRING *method_name; /* method name of the sub */
73 ATTR STRING *ns_entry_name; /* ns entry name of the sub */
74 ATTR STRING *subid; /* The ID of the sub. */
75 ATTR INTVAL vtable_index; /* index in Parrot_vtable_slot_names */
76 ATTR PMC *multi_signature; /* list of types for MMD */
77 ATTR UINTVAL n_regs_used[4]; /* INSP in PBC */
79 ATTR PMC *lex_info; /* LexInfo PMC */
80 ATTR PMC *outer_sub; /* :outer for closures */
81 ATTR PMC *eval_pmc; /* eval container / NULL */
82 ATTR PMC *ctx; /* the context this sub is in */
83 ATTR UINTVAL comp_flags; /* compile time and additional flags */
84 ATTR Parrot_sub_arginfo *arg_info; /* Argument counts and flags. */
86 ATTR PMC *outer_ctx; /* outer context, if a closure */
92 Initializes the subroutine.
99 * Sub PMC's flags usage:
100 * - private0 ... Coroutine flip/flop - C exception handler
101 * - private1 ... _IS_OUTER - have to preserve context
102 * as some other sub has :outer(this)
103 * - private2 ... tailcall invoked this Sub
104 * - private3 ... pythonic coroutine generator flag
105 * - private4 ... :main (originally @MAIN)
106 * - private5 ... :load (originally @LOAD)
107 * - private6 ... :immediate (originally @IMMEDIATE)
108 * - private7 ... :postcomp (originally @POSTCOMP)
110 * see also the enum in include/parrot/sub.h
113 Parrot_Sub_attributes * const attrs =
114 PMC_data_typed(SELF, Parrot_Sub_attributes *);
116 attrs->seg = INTERP->code;
117 attrs->outer_sub = PMCNULL;
118 attrs->multi_signature = PMCNULL;
119 attrs->namespace_name = PMCNULL;
120 attrs->vtable_index = -1;
122 PObj_custom_mark_destroy_SETALL(SELF);
128 =item C<void init_pmc()>
130 Initializes the "detached" subroutine from passed Hash. "Detached" means that
131 surboutine is fully constructed but not attached to interpreter.
137 VTABLE void init_pmc(PMC* init) {
138 Parrot_Sub_attributes * const attrs =
139 PMC_data_typed(SELF, Parrot_Sub_attributes *);
140 STRING *field = CONST_STRING(INTERP, "start_offs");
142 if (VTABLE_exists_keyed_str(INTERP, init, field))
143 attrs->start_offs = VTABLE_get_integer_keyed_str(INTERP, init, field);
145 field = CONST_STRING(INTERP, "end_offs");
146 if (VTABLE_exists_keyed_str(INTERP, init, field))
147 attrs->end_offs = VTABLE_get_integer_keyed_str(INTERP, init, field);
149 field = CONST_STRING(INTERP, "HLL_id");
150 if (VTABLE_exists_keyed_str(INTERP, init, field))
151 attrs->HLL_id = VTABLE_get_integer_keyed_str(INTERP, init, field);
153 field = CONST_STRING(INTERP, "namespace_name");
154 if (VTABLE_exists_keyed_str(INTERP, init, field))
155 attrs->namespace_name = VTABLE_get_pmc_keyed_str(INTERP, init, field);
157 field = CONST_STRING(INTERP, "namespace_stash");
158 if (VTABLE_exists_keyed_str(INTERP, init, field))
159 attrs->namespace_stash = VTABLE_get_pmc_keyed_str(INTERP, init, field);
161 field = CONST_STRING(INTERP, "name");
162 if (VTABLE_exists_keyed_str(INTERP, init, field))
163 attrs->name = VTABLE_get_string_keyed_str(INTERP, init, field);
165 field = CONST_STRING(INTERP, "method_name");
166 if (VTABLE_exists_keyed_str(INTERP, init, field))
167 attrs->method_name = VTABLE_get_string_keyed_str(INTERP, init, field);
169 field = CONST_STRING(INTERP, "ns_entry_name");
170 if (VTABLE_exists_keyed_str(INTERP, init, field))
171 attrs->ns_entry_name = VTABLE_get_string_keyed_str(INTERP, init, field);
173 field = CONST_STRING(INTERP, "subid");
174 if (VTABLE_exists_keyed_str(INTERP, init, field))
175 attrs->subid = VTABLE_get_string_keyed_str(INTERP, init, field);
177 field = CONST_STRING(INTERP, "vtable_index");
178 if (VTABLE_exists_keyed_str(INTERP, init, field))
179 attrs->vtable_index = VTABLE_get_integer_keyed_str(INTERP, init, field);
181 attrs->vtable_index = -1;
183 field = CONST_STRING(INTERP, "multi_signature");
184 if (VTABLE_exists_keyed_str(INTERP, init, field))
185 attrs->multi_signature = VTABLE_get_pmc_keyed_str(INTERP, init, field);
187 field = CONST_STRING(INTERP, "lex_info");
188 if (VTABLE_exists_keyed_str(INTERP, init, field))
189 attrs->lex_info = VTABLE_get_pmc_keyed_str(INTERP, init, field);
191 field = CONST_STRING(INTERP, "outer_sub");
192 if (VTABLE_exists_keyed_str(INTERP, init, field))
193 attrs->outer_sub = VTABLE_get_pmc_keyed_str(INTERP, init, field);
195 /* comp_flags is actually UINTVAL */
196 field = CONST_STRING(INTERP, "comp_flags");
197 if (VTABLE_exists_keyed_str(INTERP, init, field)) {
198 UINTVAL flags = (UINTVAL)VTABLE_get_integer_keyed_str(INTERP, init, field);
199 /* Mask comp flags only */
200 attrs->comp_flags = flags & SUB_COMP_FLAG_MASK;
203 /* In order to create Sub dynamicaly we have to set PObj flags */
204 field = CONST_STRING(INTERP, "pf_flags");
205 if (VTABLE_exists_keyed_str(INTERP, init, field)) {
206 UINTVAL flags = (UINTVAL)VTABLE_get_integer_keyed_str(INTERP, init, field);
207 /* Mask Sub specific flags only */
208 PObj_get_FLAGS(SELF) |= flags & SUB_FLAG_PF_MASK;
211 field = CONST_STRING(INTERP, "n_regs_used");
212 if (VTABLE_exists_keyed_str(INTERP, init, field)) {
213 PMC * const tmp = VTABLE_get_pmc_keyed_str(INTERP, init, field);
215 for (i = 0; i < 4; ++i)
216 attrs->n_regs_used[i] = VTABLE_get_integer_keyed_int(INTERP, tmp, i);
219 field = CONST_STRING(INTERP, "arg_info");
220 if (VTABLE_exists_keyed_str(INTERP, init, field)) {
221 PMC * const tmp = VTABLE_get_pmc_keyed_str(INTERP, init, field);
222 /* Allocate structure to store argument information in. */
223 attrs->arg_info = mem_gc_allocate_zeroed_typed(INTERP,
226 Hash.get_integer_keyed_str return 0 if key doesn't exists.
227 So, don't check existence of key, just use it.
228 NB: Don't split line. CONST_STRING b0rked.
230 attrs->arg_info->pos_required = VTABLE_get_integer_keyed_str(INTERP, tmp, CONST_STRING(INTERP, "pos_required"));
231 attrs->arg_info->pos_optional = VTABLE_get_integer_keyed_str(INTERP, tmp, CONST_STRING(INTERP, "pos_optional"));
232 attrs->arg_info->pos_slurpy = VTABLE_get_integer_keyed_str(INTERP, tmp, CONST_STRING(INTERP, "pos_slurpy"));
233 attrs->arg_info->named_required = VTABLE_get_integer_keyed_str(INTERP, tmp, CONST_STRING(INTERP, "named_required"));
234 attrs->arg_info->named_optional = VTABLE_get_integer_keyed_str(INTERP, tmp, CONST_STRING(INTERP, "named_optional"));
235 attrs->arg_info->named_slurpy = VTABLE_get_integer_keyed_str(INTERP, tmp, CONST_STRING(INTERP, "named_slurpy"));
238 /* C<eval_pmc> and C<ctx> are not handled here, and shouldn't be,
239 * because of run-time nature. */
241 PObj_custom_mark_destroy_SETALL(SELF);
247 =item C<void destroy()>
249 Destroys the subroutine.
255 VTABLE void destroy() {
256 Parrot_Sub_attributes * const sub = PARROT_SUB(SELF);
258 if (sub && sub->arg_info)
259 mem_gc_free(INTERP, sub->arg_info);
265 =item C<STRING *get_string()>
267 Returns the name of the subroutine.
269 =item C<void set_string_native(STRING *subname)>
271 Sets the name of the subroutine.
277 VTABLE STRING *get_string() {
279 GET_ATTR_name(INTERP, SELF, name);
284 VTABLE void set_string_native(STRING *subname) {
285 SET_ATTR_name(INTERP, SELF, subname);
291 =item C<void set_pointer(void *value)>
293 Sets the pointer to the actual subroutine.
295 *** Don't use that - use C<.const 'Sub'> in PIR instead ***
301 VTABLE void set_pointer(void *value) {
303 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
304 "Don't set the address of a sub\nuse .const 'Sub' instead");
310 =item C<void *get_pointer()>
312 Returns the address of the actual subroutine.
318 VTABLE void *get_pointer() {
319 Parrot_Sub_attributes *sub;
320 PMC_get_sub(INTERP, SELF, sub);
321 return sub->seg->base.data + sub->start_offs;
327 =item C<INTVAL get_integer_keyed(PMC *key)>
329 I<This just unconditionally returns the start of bytecode. It's wrong,
330 wrong, wrong, *WRONG*. And there's no other good way, so it's here for
337 VTABLE INTVAL get_integer_keyed(PMC *key) {
338 Parrot_Sub_attributes *sub;
340 PMC_get_sub(INTERP, SELF, sub);
342 return (INTVAL) (sub->seg->base.data);
348 =item C<INTVAL defined()>
350 =item C<INTVAL get_bool()>
358 VTABLE INTVAL defined() {
362 VTABLE INTVAL get_bool() {
369 =item C<opcode_t *invoke(void *next)>
371 Invokes the subroutine.
377 VTABLE opcode_t *invoke(void *next) {
378 PMC * const caller_ctx = CURRENT_CONTEXT(INTERP);
379 PMC *ccont = INTERP->current_cont;
382 /* plain subroutine call
383 * create new context, place it in interpreter */
384 PMC *context = Parrot_pcc_get_signature(INTERP, caller_ctx);
386 Parrot_Sub_attributes *sub;
389 PMC_get_sub(INTERP, SELF, sub);
390 if (Interp_trace_TEST(INTERP, PARROT_TRACE_SUB_CALL_FLAG))
391 print_sub_name(INTERP, SELF);
394 * A remark WRT tail calls
405 * that is the sub B() returns whatever C() returns.
407 * We are just calling the sub C().
408 * If the private2 flag is set, this code is called by a
411 * We allocate a new register frame and recycle it
412 * immediately after argument passing.
415 pc = sub->seg->base.data + sub->start_offs;
416 INTERP->current_cont = NULL;
418 if (ccont == NEED_CONTINUATION) {
419 ccont = pmc_new(INTERP, enum_class_Continuation);
420 VTABLE_set_pointer(INTERP, ccont, next);
423 PARROT_ASSERT(!PMC_IS_NULL(ccont));
425 if (PMC_IS_NULL(context))
426 context = Parrot_pmc_new(INTERP, enum_class_CallContext);
428 CURRENT_CONTEXT(INTERP) = context;
429 Parrot_pcc_set_caller_ctx(INTERP, context, caller_ctx);
430 Parrot_pcc_allocate_registers(INTERP, context, sub->n_regs_used);
431 /* Preserve object */
432 object = Parrot_pcc_get_object(INTERP, context);
433 Parrot_pcc_init_context(INTERP, context, caller_ctx);
434 Parrot_pcc_set_object(INTERP, context, object);
436 Parrot_pcc_set_sub(INTERP, context, SELF);
437 Parrot_pcc_set_continuation(INTERP, context, ccont);
438 Parrot_pcc_set_constants(INTERP, context, sub->seg->const_table->constants);
440 /* check recursion/call depth */
441 if (Parrot_pcc_inc_recursion_depth(INTERP, context) > INTERP->recursion_limit)
442 Parrot_ex_throw_from_c_args(INTERP, next, CONTROL_ERROR,
443 "maximum recursion depth exceeded");
445 /* and copy set context variables */
446 PARROT_CONTINUATION(ccont)->from_ctx = context;
448 /* if this is an outer sub, then we need to set sub->ctx
449 * to the new context (refcounted) */
450 if (PObj_get_FLAGS(SELF) & SUB_FLAG_IS_OUTER) {
454 /* create pad if needed
455 * TODO move this up in front of argument passing
456 * and factor out common code with coroutine pmc
458 if (!PMC_IS_NULL(sub->lex_info)) {
459 Parrot_pcc_set_lex_pad(INTERP, context, Parrot_pmc_new_init(INTERP,
460 Parrot_get_ctx_HLL_type(INTERP, enum_class_LexPad),
462 VTABLE_set_pointer(INTERP, Parrot_pcc_get_lex_pad(INTERP, context), context);
465 /* set outer context */
466 if (!PMC_IS_NULL(sub->outer_ctx))
467 Parrot_pcc_set_outer_ctx(INTERP, context, sub->outer_ctx);
471 PMC *outer_c = Parrot_pcc_get_outer_ctx(INTERP, c);
473 for (c = context; PMC_IS_NULL(outer_c); c = outer_c) {
476 Parrot_Sub_attributes *current_sub, *outer_sub;
478 PMC_get_sub(INTERP, Parrot_pcc_get_sub(INTERP, c), current_sub);
479 outer_pmc = current_sub->outer_sub;
481 if (PMC_IS_NULL(outer_pmc))
484 PMC_get_sub(INTERP, outer_pmc, outer_sub);
486 if (PMC_IS_NULL(outer_sub->ctx)) {
487 PMC * const dummy = Parrot_alloc_context(INTERP,
488 outer_sub->n_regs_used, NULL);
489 Parrot_pcc_set_sub(INTERP, dummy, outer_pmc);
491 if (!PMC_IS_NULL(outer_sub->lex_info)) {
492 Parrot_pcc_set_lex_pad(INTERP, dummy,
493 Parrot_pmc_new_init(INTERP,
494 Parrot_get_ctx_HLL_type(INTERP,
495 enum_class_LexPad), outer_sub->lex_info));
497 VTABLE_set_pointer(INTERP,
498 Parrot_pcc_get_lex_pad(INTERP, dummy), dummy);
501 if (!PMC_IS_NULL(outer_sub->outer_ctx))
502 Parrot_pcc_set_outer_ctx(INTERP, dummy,
503 outer_sub->outer_ctx);
505 outer_sub->ctx = dummy;
508 Parrot_pcc_set_outer_ctx(INTERP, c, outer_sub->ctx);
509 outer_c = outer_sub->ctx;
513 /* switch code segment if needed */
514 if (INTERP->code != sub->seg)
515 Parrot_switch_to_cs(INTERP, sub->seg, 1);
523 =item C<PMC *clone()>
525 Creates and returns a clone of the subroutine.
531 VTABLE PMC *clone() {
532 PMC * const ret = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
534 Parrot_Sub_attributes *dest_sub;
535 Parrot_Sub_attributes *sub;
538 /* we have to mark it ourselves */
539 PObj_custom_mark_destroy_SETALL(ret);
541 PMC_get_sub(INTERP, SELF, dest_sub);
542 PMC_get_sub(INTERP, ret, sub);
544 /* first set the sub struct, Parrot_str_copy may cause GC */
547 /* Be sure not to share arg_info. */
548 dest_sub->arg_info = NULL;
556 =item C<void assign_pmc(PMC *other)>
558 Set SELF to the data in other.
564 VTABLE void set_pmc(PMC *other) {
565 SELF.assign_pmc(other);
568 VTABLE void assign_pmc(PMC *other) {
569 /* only handle the case where the other PMC is the same type */
570 if (other->vtable->base_type == SELF->vtable->base_type) {
571 Parrot_Sub_attributes *my_sub;
572 Parrot_Sub_attributes *other_sub;
574 PMC_get_sub(INTERP, SELF, my_sub);
575 PMC_get_sub(INTERP, other, other_sub);
577 /* copy the sub struct */
578 memmove(my_sub, other_sub, sizeof (Parrot_Sub_attributes));
581 Parrot_ex_throw_from_c_args(INTERP, NULL,
582 EXCEPTION_INVALID_OPERATION,
583 "Can't assign a non-Sub type to a Sub");
591 Marks the sub as live.
598 Parrot_Sub_attributes * const sub = PARROT_SUB(SELF);
603 Parrot_gc_mark_STRING_alive(INTERP, sub->name);
604 Parrot_gc_mark_STRING_alive(INTERP, sub->subid);
605 Parrot_gc_mark_STRING_alive(INTERP, sub->method_name);
606 Parrot_gc_mark_STRING_alive(INTERP, sub->ns_entry_name);
608 Parrot_gc_mark_PMC_alive(INTERP, sub->ctx);
609 Parrot_gc_mark_PMC_alive(INTERP, sub->eval_pmc);
610 Parrot_gc_mark_PMC_alive(INTERP, sub->lex_info);
611 Parrot_gc_mark_PMC_alive(INTERP, sub->outer_ctx);
612 Parrot_gc_mark_PMC_alive(INTERP, sub->outer_sub);
613 Parrot_gc_mark_PMC_alive(INTERP, sub->namespace_name);
614 Parrot_gc_mark_PMC_alive(INTERP, sub->multi_signature);
615 Parrot_gc_mark_PMC_alive(INTERP, sub->namespace_stash);
620 =item C<INTVAL is_equal(PMC *value)>
622 Returns whether the two subroutines are equal.
628 MULTI INTVAL is_equal(PMC *value) {
629 Parrot_Sub_attributes *my_sub, *value_sub;
631 PMC_get_sub(INTERP, SELF, my_sub);
632 PMC_get_sub(INTERP, value, value_sub);
634 return SELF->vtable == value->vtable
635 && (my_sub)->start_offs == (value_sub)->start_offs
636 && (my_sub)->seg == (value_sub)->seg;
642 =item C<void visit(PMC *info)>
644 This is used by freeze/thaw to visit the contents of the sub.
646 =item C<void freeze(PMC *info)>
648 Archives the subroutine.
654 VTABLE void visit(PMC *info) {
655 VISIT_PMC_ATTR(INTERP, info, SELF, Sub, namespace_name);
656 VISIT_PMC_ATTR(INTERP, info, SELF, Sub, multi_signature);
657 VISIT_PMC_ATTR(INTERP, info, SELF, Sub, outer_sub);
660 * XXX visit_pmc_now is wrong, because it breaks
661 * depth-first visit inside the todo list
662 * TODO change all user visit functions to use
663 * visit_pmc (the todo renamed visit_pm_later)
665 * Therefore the hash must be last during visit for now.
667 VISIT_PMC_ATTR(INTERP, info, SELF, Sub, lex_info);
673 VTABLE void freeze(PMC *info) {
674 Parrot_Sub_attributes *sub;
679 PMC_get_sub(INTERP, SELF, sub);
681 * we currently need to write these items:
682 * - start offset in byte-code segment
683 * - end offset in byte-code segment
685 * - flags (i.e. :load pragma and such)
686 * - name of the sub's label
698 VTABLE_push_integer(INTERP, info, (INTVAL) sub->start_offs);
699 VTABLE_push_integer(INTERP, info, (INTVAL) sub->end_offs);
700 VTABLE_push_integer(INTERP, info,
701 (INTVAL)(PObj_get_FLAGS(SELF) & SUB_FLAG_PF_MASK));
703 VTABLE_push_string(INTERP, info, sub->name);
705 if (!sub->method_name)
706 sub->method_name = CONST_STRING(INTERP, "");
707 VTABLE_push_string(INTERP, info, sub->method_name);
709 if (!sub->ns_entry_name)
710 sub->ns_entry_name = CONST_STRING(INTERP, "");
711 VTABLE_push_string(INTERP, info, sub->ns_entry_name);
713 hll_name = Parrot_get_HLL_name(INTERP, sub->HLL_id);
715 hll_name = CONST_STRING(INTERP, "");
716 VTABLE_push_string(INTERP, info, hll_name);
718 VTABLE_push_integer(INTERP, info, (INTVAL)sub->comp_flags);
719 VTABLE_push_integer(INTERP, info, sub->vtable_index);
721 for (i = 0; i < 4; ++i)
722 VTABLE_push_integer(INTERP, info, sub->n_regs_used[i]);
725 sub->subid = CONST_STRING(INTERP, "");
727 VTABLE_push_string(INTERP, info, sub->subid);
733 =item C<void thaw(PMC *info)>
735 Unarchives the subroutine.
741 VTABLE void thaw(PMC *info) {
742 Parrot_Sub_attributes *sub;
748 PMC_get_sub(INTERP, SELF, sub);
750 /* we get relative offsets */
751 sub->start_offs = (size_t) VTABLE_shift_integer(INTERP, info);
752 sub->end_offs = (size_t) VTABLE_shift_integer(INTERP, info);
753 flags = VTABLE_shift_integer(INTERP, info);
755 PObj_get_FLAGS(SELF) |= flags & SUB_FLAG_PF_MASK;
757 sub->name = VTABLE_shift_string(INTERP, info);
758 sub->method_name = VTABLE_shift_string(INTERP, info);
759 sub->ns_entry_name = VTABLE_shift_string(INTERP, info);
760 sub->HLL_id = Parrot_get_HLL_id(INTERP,
761 VTABLE_shift_string(INTERP, info));
762 sub->comp_flags = VTABLE_shift_integer(INTERP, info);
763 sub->vtable_index = VTABLE_shift_integer(INTERP, info);
765 for (i = 0; i < 4; ++i)
766 sub->n_regs_used[i] = VTABLE_shift_integer(INTERP, info);
768 sub->subid = VTABLE_shift_string(INTERP, info);
774 =item C<PMC *inspect()>
776 Returns the full set of meta-data about the sub.
782 VTABLE PMC *inspect()
784 /* Create a hash, then use inspect_str to get all of its data */
786 PMC * const metadata = Parrot_pmc_new(INTERP, enum_class_Hash);
787 STRING * const pos_required_str = CONST_STRING(INTERP, "pos_required");
788 STRING * const pos_optional_str = CONST_STRING(INTERP, "pos_optional");
789 STRING * const named_required_str = CONST_STRING(INTERP, "named_required");
790 STRING * const named_optional_str = CONST_STRING(INTERP, "named_optional");
791 STRING * const pos_slurpy_str = CONST_STRING(INTERP, "pos_slurpy");
792 STRING * const named_slurpy_str = CONST_STRING(INTERP, "named_slurpy");
794 VTABLE_set_pmc_keyed_str(INTERP, metadata, pos_required_str,
795 VTABLE_inspect_str(INTERP, SELF, pos_required_str));
797 VTABLE_set_pmc_keyed_str(INTERP, metadata, pos_optional_str,
798 VTABLE_inspect_str(INTERP, SELF, pos_optional_str));
800 VTABLE_set_pmc_keyed_str(INTERP, metadata, named_required_str,
801 VTABLE_inspect_str(INTERP, SELF, named_required_str));
803 VTABLE_set_pmc_keyed_str(INTERP, metadata, named_optional_str,
804 VTABLE_inspect_str(INTERP, SELF, named_optional_str));
806 VTABLE_set_pmc_keyed_str(INTERP, metadata, pos_slurpy_str,
807 VTABLE_inspect_str(INTERP, SELF, pos_slurpy_str));
809 VTABLE_set_pmc_keyed_str(INTERP, metadata, named_slurpy_str,
810 VTABLE_inspect_str(INTERP, SELF, named_slurpy_str));
818 =item C<PMC *inspect_str(STRING *what)>
820 Returns the specified item of metadata about the sub. Allowable
827 The number of required positional arguments
831 The number of optional positional arguments
835 The number of required named arguments
839 The number of optional named arguments
843 1 if it takes slurpy positional arguments, 0 if not
847 1 if it takes slurpy named arguments, 0 if not
855 VTABLE PMC *inspect_str(STRING *what)
857 Parrot_Sub_attributes *sub;
859 INTVAL count_found = -1;
861 PMC_get_sub(INTERP, SELF, sub);
863 /* If the argument info hasn't been generated yet, generate it. */
864 if (!sub->arg_info) {
865 /* Get pointer into the bytecode where this sub starts. */
866 const opcode_t *pc = sub->seg->base.data + sub->start_offs;
867 op_lib_t *core_ops = PARROT_GET_CORE_OPLIB(INTERP);
869 /* Allocate structure to store argument information in. */
870 sub->arg_info = mem_gc_allocate_zeroed_typed(INTERP,
873 /* If the first instruction is a get_params... */
874 if (OPCODE_IS(INTERP, sub->seg, *pc, core_ops, PARROT_OP_get_params_pc)) {
875 /* Get the signature (the next thing in the bytecode). */
876 PMC * const sig = PF_CONST(sub->seg, *(++pc)).u.key;
878 /* Iterate over the signature and compute argument counts. */
879 const INTVAL sig_length = VTABLE_elements(INTERP, sig);
884 for (i = 0; i < sig_length; ++i) {
885 int sig_item = VTABLE_get_integer_keyed_int(INTERP, sig, i);
886 if (PARROT_ARG_SLURPY_ARRAY_ISSET(sig_item)){
887 if (PARROT_ARG_NAME_ISSET(sig_item))
888 sub->arg_info->named_slurpy = 1;
890 sub->arg_info->pos_slurpy = 1;
892 else if (PARROT_ARG_NAME_ISSET(sig_item)) {
894 sig_item = VTABLE_get_integer_keyed_int(INTERP, sig, i);
895 if (PARROT_ARG_OPTIONAL_ISSET(sig_item))
896 ++sub->arg_info->named_optional;
898 ++sub->arg_info->named_required;
900 else if (!PARROT_ARG_OPT_FLAG_ISSET(sig_item)) {
901 if (PARROT_ARG_OPTIONAL_ISSET(sig_item))
902 ++sub->arg_info->pos_optional;
904 ++sub->arg_info->pos_required;
910 /* Return the requested argument information */
911 if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "pos_required"))) {
912 count_found = (INTVAL)sub->arg_info->pos_required;
914 else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "pos_optional"))) {
915 count_found = (INTVAL)sub->arg_info->pos_optional;
917 else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "pos_slurpy"))) {
918 count_found = (INTVAL)sub->arg_info->pos_slurpy;
920 else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "named_required"))) {
921 count_found = (INTVAL)sub->arg_info->named_required;
923 else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "named_optional"))) {
924 count_found = (INTVAL)sub->arg_info->named_optional;
926 else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "named_slurpy"))) {
927 count_found = (INTVAL)sub->arg_info->named_slurpy;
930 Parrot_ex_throw_from_c_args(INTERP, NULL,
931 EXCEPTION_INVALID_OPERATION,
932 "Unknown introspection value '%S'", what);
934 retval = Parrot_pmc_new_init_int(INTERP, enum_class_Integer, count_found);
947 =item C<INTVAL start_offs()>
949 Returns the start offset of the Sub.
951 =item C<INTVAL end_offs()>
953 Returns the end offset of the Sub.
955 =item C<PMC *get_namespace()>
957 Returns the namespace PMC, where the Sub is defined.
959 TODO return C<namespace_stash> instead.
961 =item C<INTVAL __get_regs_used(char *kind)>
963 Returns the number of used registers for register kinds "I", "S", "P", "N".
965 =item C<PMC *get_lexinfo()>
967 Returns the LexInfo PMC, if any or a Null PMC.
969 =item C<PMC *get_multisig()>
971 Returns the MMD signature PMC, if any, or a Null PMC.
973 =item C<PMC *get_outer()>
975 Gets the sub that is the outer of this one, if any, or a Null PMC.
977 =item C<void set_outer(PMC *outer)>
979 Sets the sub that is the outer of this one.
981 =item C<void set_outer_ctx(PMC *outer_ctx)>
983 Set the outer context to be used on the next invocation of this sub.
985 =item C<INTVAL arity()>
987 Returns the arity of the Sub (the number of arguments, excluding optional and
993 METHOD start_offs() {
994 Parrot_Sub_attributes *sub;
997 PMC_get_sub(INTERP, SELF, sub);
998 start_offs = sub->start_offs;
999 RETURN(INTVAL start_offs);
1004 Parrot_Sub_attributes *sub;
1006 PMC_get_sub(INTERP, SELF, sub);
1007 end_offs = sub->end_offs;
1008 RETURN(INTVAL end_offs);
1012 METHOD get_namespace() {
1014 Parrot_Sub_attributes *sub;
1016 PMC_get_sub(INTERP, SELF, sub);
1018 XXX Rakudo's failing with with this code on ASSERT. Why???
1019 GET_ATTR_namespace_stash(INTERP, SELF, _namespace);
1020 PARROT_ASSERT(_namespace == sub->namespace_stash || !"consistency!!!");
1022 _namespace = sub->namespace_stash;
1023 RETURN(PMC *_namespace);
1027 METHOD __get_regs_used(STRING *reg) {
1028 /* TODO switch to canonical NiSP order
1029 * see also imcc/reg_alloc.c */
1030 STRING * const types = CONST_STRING(INTERP, "INSP");
1031 Parrot_Sub_attributes *sub;
1035 PMC_get_sub(INTERP, SELF, sub);
1036 PARROT_ASSERT(sub->n_regs_used);
1038 if (!reg || Parrot_str_length(INTERP, reg) != 1)
1039 Parrot_ex_throw_from_c_args(INTERP, NULL,
1040 EXCEPTION_INVALID_OPERATION,
1041 "illegal register kind '%Ss'", reg);
1043 kind = Parrot_str_find_index(INTERP, types, reg, 0);
1046 Parrot_ex_throw_from_c_args(INTERP, NULL,
1047 EXCEPTION_INVALID_OPERATION, "illegal register kind '%Ss'", reg);
1049 regs_used = sub->n_regs_used[kind];
1050 RETURN(INTVAL regs_used);
1054 METHOD get_lexinfo() {
1056 Parrot_Sub_attributes *sub;
1057 PMC_get_sub(INTERP, SELF, sub);
1059 lexinfo = sub->lex_info ? sub->lex_info : PMCNULL;
1061 RETURN(PMC *lexinfo);
1065 METHOD get_subid() {
1067 Parrot_Sub_attributes *sub;
1068 PMC_get_sub(INTERP, SELF, sub);
1070 subid = sub->subid ? sub->subid : CONST_STRING(INTERP, "");
1072 RETURN(STRING *subid);
1076 METHOD get_outer() {
1078 Parrot_Sub_attributes *sub;
1079 PMC_get_sub(INTERP, SELF, sub);
1081 outersub = sub->outer_sub ? sub->outer_sub : PMCNULL;
1083 RETURN(PMC *outersub);
1087 METHOD set_outer(PMC *outer) {
1088 /* Set outer sub. */
1089 Parrot_Sub_attributes *sub;
1091 PMC_get_sub(INTERP, SELF, sub);
1093 sub->outer_sub = outer;
1095 /* Make sure outer flag of that sub is set. */
1096 PObj_get_FLAGS(outer) |= SUB_FLAG_IS_OUTER;
1098 /* Ensure we have lex info. */
1099 if (PMC_IS_NULL(sub->lex_info)) {
1100 const INTVAL lex_info_id = Parrot_get_ctx_HLL_type(INTERP,
1101 enum_class_LexInfo);
1102 sub->lex_info = Parrot_pmc_new_init(INTERP, lex_info_id, SELF);
1105 /* Clear any existing outer context */
1106 sub->outer_ctx = PMCNULL;
1108 /* If we've got a context around for the outer sub, set it as the
1110 outer_ctx = CURRENT_CONTEXT(INTERP);
1112 while (!PMC_IS_NULL(outer_ctx)) {
1113 if (Parrot_pcc_get_sub(INTERP, outer_ctx) == outer) {
1114 sub->outer_ctx = outer_ctx;
1117 outer_ctx = Parrot_pcc_get_caller_ctx(INTERP, outer_ctx);
1122 METHOD set_outer_ctx(PMC *outer_ctx) {
1123 Parrot_Sub_attributes *sub;
1124 PMC_get_sub(INTERP, SELF, sub);
1125 sub->outer_ctx = outer_ctx;
1129 METHOD get_multisig() {
1131 Parrot_Sub_attributes *sub;
1132 PMC_get_sub(INTERP, SELF, sub);
1134 multisig = sub->multi_signature ? sub->multi_signature : PMCNULL;
1136 RETURN(PMC *multisig);
1141 PMC * const pos_required = VTABLE_inspect_str(INTERP, SELF, CONST_STRING(INTERP, "pos_required"));
1142 PMC * const named_required = VTABLE_inspect_str(INTERP, SELF, CONST_STRING(INTERP, "named_required"));
1144 const INTVAL arity = VTABLE_get_integer(INTERP, pos_required)
1145 + VTABLE_get_integer(INTERP, named_required);
1147 RETURN(INTVAL arity);
1151 =item C<INTVAL comp_flags()>
1153 =item C<INTVAL pf_flags()>
1155 (Experimental) Returns Sub flags.
1162 METHOD comp_flags() {
1163 Parrot_Sub_attributes *sub;
1166 PMC_get_sub(INTERP, SELF, sub);
1167 flags = sub->comp_flags;
1168 RETURN(INTVAL flags);
1172 /* Only PF specific flags */
1173 INTVAL flags = PObj_get_FLAGS(SELF) & SUB_FLAG_PF_MASK;
1174 RETURN(INTVAL flags);
1182 * c-file-style: "parrot"
1184 * vim: expandtab shiftwidth=4: