tagged release 0.7.1
[parrot.git] / src / pmc / sub.pmc
blob452a27f6dc12b28efb2bbb5fd420bcb91843292e
1 /*
2 Copyright (C) 2001-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/sub.pmc - Subroutine
9 =head1 DESCRIPTION
11 These are the vtable functions for the Sub (subroutine) base class
13 =head2 Functions
15 =over 4
17 =cut
21 #include "parrot/parrot.h"
22 #include "parrot/oplib/ops.h"
23 #include "sub.str"
25 static void
26 print_sub_name(PARROT_INTERP, PMC *sub)
28     Interp * const tracer = interp->debugger ? interp->debugger : interp;
30     /* sub was located via globals */
31     PIO_eprintf(tracer, "# Calling sub '%Ss'\n# ",
32         Parrot_full_sub_name(interp, sub));
34     print_pbc_location(interp);
38  * A sub now contains more data like namespace, which makes it
39  * effectively a container. Therefore need_ext has to be set
40  */
41 pmclass Sub need_ext {
45 =item C<void init()>
47 Initializes the subroutine.
49 =cut
53     /*
54      * Sub PMC's flags usage:
55      * - private0 ... Coroutine flip/flop - C exception handler
56      * - private1 ... _IS_OUTER - have to preserve context
57      *                as some other sub has :outer(this)
58      * - private2 ... tailcall invoked this Sub
59      * - private3 ... pythonic coroutine generator flag
60      * - private4 ... :main (originally @MAIN)
61      * - private5 ... :load (originally @LOAD)
62      * - private6 ... :immediate (originally @IMMEDIATE)
63      * - private7 ... :postcomp (originally @POSTCOMP)
64      *
65      * see also the enum in include/parrot/sub.h
66      *
67      * Data used:
68      *   PMC_struct_val ... Parrot_sub structure
69      *   PMC_pmc_val    ... unused / bound object in Bound_Meth PMC
70      */
71     VTABLE void init() {
72         PMC_struct_val(SELF) = new_sub(INTERP);
73         PMC_pmc_val(SELF)    = NULL;
74         PObj_custom_mark_destroy_SETALL(SELF);
75     }
79 =item C<void destroy()>
81 Destroys the subroutine.
83 =cut
87     VTABLE void destroy() {
88         Parrot_sub * const sub = PMC_sub(SELF);
90         if (!sub)
91             return;
92         if (sub->arg_info)
93             mem_sys_free(sub->arg_info);
95         mem_sys_free(sub);
96         PMC_struct_val(SELF) = NULL;
97     }
101 =item C<STRING *get_string()>
103 Returns the name of the subroutine.
105 =item C<void set_string_native(STRING *subname)>
107 Sets the name of the subroutine.
109 =cut
113     VTABLE STRING *get_string() {
114         const Parrot_sub * const sub = PMC_sub(SELF);
115         return string_copy(INTERP, sub->name);
116     }
118     VTABLE void set_string_native(STRING *subname) {
119         Parrot_sub * const sub = PMC_sub(SELF);
120         sub->name              = string_copy(INTERP, subname);
121     }
125 =item C<void set_pointer(void *value)>
127 Sets the pointer to the actual subroutine.
129 *** Don't use that - use .Sub constants instead ***
131 =cut
135     VTABLE void set_pointer(void *value) {
136         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
137             "Don't set the address of a sub\nuse .Sub constants instead");
138     }
142 =item C<void *get_pointer()>
144 Returns the address of the actual subroutine.
146 =cut
150     VTABLE void *get_pointer() {
151         const Parrot_sub * const sub = PMC_sub(SELF);
152         return sub->seg->base.data + sub->start_offs;
153     }
157 =item C<INTVAL get_integer_keyed(PMC *key)>
159 I<This just unconditionally returns the start of bytecode. It's wrong,
160 wrong, wrong, *WRONG*. And there's no other good way, so it's here for
161 now.> -DRS
163 =cut
167     VTABLE INTVAL get_integer_keyed(PMC *key) {
168         return (INTVAL) ((PMC_sub(SELF))->seg->base.data);
169     }
173 =item C<INTVAL defined()>
175 =item C<INTVAL get_bool()>
177 Returns True.
179 =cut
183     VTABLE INTVAL defined() {
184         return 1;
185     }
187     VTABLE INTVAL get_bool() {
188         return 1;
189     }
193 =item C<opcode_t *invoke(void *next)>
195 Invokes the subroutine.
197 =cut
201     VTABLE opcode_t *invoke(void *next) {
202         Parrot_sub     * const sub = PMC_sub(SELF);
203         Parrot_Context        *caller_ctx;
204         Parrot_Context        *context;
205         PMC                   *ccont;
206         opcode_t              *pc;
208         if (Interp_trace_TEST(INTERP, PARROT_TRACE_SUB_CALL_FLAG))
209             print_sub_name(INTERP, SELF);
211         /*
212          * A remark WRT tail calls
213          *
214          * we have:
215          * sub A:
216          *    ...
217          *    B()
218          *    ...
219          * sub B:
220          *    ...
221          *    .return C(...)
222          *
223          * that is the sub B() returns whatever C() returns.
224          *
225          * We are just calling the sub C().
226          * If the private2 flag is set, this code is called by a
227          * tailcall opcode.
228          *
229          * We allocate a new register frame and recycle it
230          * immediately after argument passing.
231          *
232          */
233         pc                   = sub->seg->base.data + sub->start_offs;
234         caller_ctx           = CONTEXT(interp);
235         ccont                = INTERP->current_cont;
236         INTERP->current_cont = NULL;
238         if (ccont == NEED_CONTINUATION)
239             ccont = new_ret_continuation_pmc(interp, (opcode_t *)next);
241         PARROT_ASSERT(!PMC_IS_NULL(ccont));
243         /*
244          * plain subroutine call
245          * create new context, place it in interpreter
246          */
247 #define PREMATURE_OPT
248 #ifdef PREMATURE_OPT
249         if (caller_ctx->current_sub == SELF)
250             context = Parrot_dup_context(INTERP, caller_ctx);
251         else
252 #endif
253         context               = Parrot_alloc_context(INTERP, sub->n_regs_used);
254         context->current_sub  = SELF;
255         context->caller_ctx   = caller_ctx;
256         context->current_pc   = pc;
257         context->current_cont = ccont;
259         /* check recursion/call depth */
260         if (++context->recursion_depth > INTERP->recursion_limit)
261             Parrot_ex_throw_from_c_args(INTERP, next, CONTROL_ERROR,
262                     "maximum recursion depth exceeded");
264         /* and copy set context variables */
265         PMC_cont(ccont)->from_ctx = context;
267         /* set context of the sub */
268         sub->ctx = context;
270         /* don't destroy context */
271         if (PObj_get_FLAGS(SELF) & SUB_FLAG_IS_OUTER)
272             ccont->vtable = interp->vtables[enum_class_Continuation];
274         /* reference counting should work */
275         context->ref_count++;
277         if (!PMC_IS_NULL(INTERP->current_object)) {
278             context->current_object = INTERP->current_object;
279             INTERP->current_object  = NULL;
280         }
282         context->current_HLL       = sub->HLL_id;
283         context->current_namespace = sub->namespace_stash;
285         /* create pad if needed
286          * TODO move this up in front of argument passing
287          *      and factor out common code with coroutine pmc
288          */
289         if (!PMC_IS_NULL(sub->lex_info)) {
290             context->lex_pad = pmc_new_init(INTERP,
291                     Parrot_get_ctx_HLL_type(interp,
292                         enum_class_LexPad),
293                     sub->lex_info);
294             VTABLE_set_pointer(INTERP, context->lex_pad, context);
295         }
297         /* switch code segment if needed */
298         if (INTERP->code != sub->seg)
299             Parrot_switch_to_cs(INTERP, sub->seg, 1);
301         if (PObj_get_FLAGS(ccont) & SUB_FLAG_TAILCALL) {
302             if (!(*pc == PARROT_OP_get_params_pc ||
303                         (*pc == PARROT_OP_push_eh_ic &&
304                          pc[2] == PARROT_OP_get_params_pc))) {
306                 /* TODO keep it or resize it */
307                 --context->recursion_depth;
309                 PObj_get_FLAGS(ccont) &= ~SUB_FLAG_TAILCALL;
310                 context->caller_ctx    = caller_ctx->caller_ctx;
312                 Parrot_free_context(INTERP, caller_ctx, 0);
313             }
314         }
316         return pc;
317     }
321 =item C<PMC *clone()>
323 Creates and returns a clone of the subroutine.
325 =cut
329     VTABLE PMC *clone() {
330         Parrot_sub *sub = mem_allocate_typed(Parrot_sub);
331         PMC * const ret = pmc_new_noinit(INTERP, SELF->vtable->base_type);
333         /* we have to mark it ourselves */
334         PObj_custom_mark_destroy_SETALL(ret);
336         /* first set the sub struct, string_copy may cause GC */
337         PMC_struct_val(ret) = sub;
338         PMC_pmc_val(ret)    = NULL;
339         memcpy(sub, PMC_sub(SELF), sizeof (Parrot_sub));
340         sub->name           = string_copy(INTERP, sub->name);
342         return ret;
343     }
347 =item C<void assign_pmc(PMC *other)>
349 Set SELF to the data in other.
351 =cut
355     VTABLE void set_pmc(PMC *other) {
356         SELF.assign_pmc(other);
357     }
359     VTABLE void assign_pmc(PMC *other) {
360         /* only handle the case where the other PMC is the same type */
361         if (other->vtable->base_type == SELF->vtable->base_type) {
362             /* copy the sub struct */
363             memcpy(PMC_sub(SELF), PMC_sub(other), sizeof (struct Parrot_sub));
365             /* copy the name so it's a different string in memory */
366             PMC_sub(SELF)->name = string_copy(INTERP, PMC_sub(SELF)->name);
367         }
368         else
369             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
370                 "Can't assign a non-Sub type to a Sub");
371     }
375 =item C<void mark()>
377 Marks the sub as live.
379 =cut
383     VTABLE void mark() {
384         const Parrot_sub * const sub = PMC_sub(SELF);
386         if (!sub)
387             return;
389         if (sub->name)
390             pobject_lives(INTERP, (PObj *) sub->name);
391         if (!PMC_IS_NULL(sub->namespace_name))
392             pobject_lives(INTERP, (PObj *) sub->namespace_name);
393         if (!PMC_IS_NULL(sub->multi_signature))
394             pobject_lives(INTERP, (PObj *) sub->multi_signature);
395         if (!PMC_IS_NULL(sub->lex_info))
396             pobject_lives(INTERP, (PObj *) sub->lex_info);
397         if (!PMC_IS_NULL(sub->outer_sub))
398             pobject_lives(INTERP, (PObj *) sub->outer_sub);
399         if (!PMC_IS_NULL(sub->eval_pmc))
400             pobject_lives(INTERP, (PObj *) sub->eval_pmc);
401         if (sub->lexid)
402             pobject_lives(INTERP, (PObj *) sub->lexid);
403         if (sub->ctx)
404             mark_context(interp, sub->ctx);
405     }
409 =item C<INTVAL is_equal(PMC *value)>
411 Returns whether the two subroutines are equal.
413 =cut
417     VTABLE INTVAL is_equal(PMC *value) {
418         return SELF->vtable == value->vtable &&
419             (PMC_sub(SELF))->start_offs == (PMC_sub(value))->start_offs &&
420             (PMC_sub(SELF))->seg == (PMC_sub(value))->seg;
421     }
425 =item C<void visit(visit_info *info)>
427 This is used by freeze/thaw to visit the contents of the sub.
429 =item C<void freeze(visit_info *info)>
431 Archives the subroutine.
433 =cut
437     VTABLE void visit(visit_info *info) {
438         Parrot_sub * const sub = PMC_sub(SELF);
440         info->thaw_ptr = &sub->namespace_name;
441         (info->visit_pmc_now)(INTERP, sub->namespace_name, info);
443         info->thaw_ptr = &sub->multi_signature;
444         (info->visit_pmc_now)(INTERP, sub->multi_signature, info);
446         info->thaw_ptr = &sub->outer_sub;
447         (info->visit_pmc_now)(INTERP, sub->outer_sub, info);
449         /*
450          * XXX visit_pmc_now is wrong, because it breaks
451          *     depth-first visit inside the todo list
452          * TODO change all user visit functions to use
453          *    visit_pmc (the todo renamed visit_pm_later)
454          *
455          * Therefore the hash must be last during visit for now.
456          */
457         info->thaw_ptr = &sub->lex_info;
458         (info->visit_pmc_now)(INTERP, sub->lex_info, info);
459         SUPER(info);
460     }
462     VTABLE void freeze(visit_info *info) {
463         IMAGE_IO   * const io  = info->image_io;
464         Parrot_sub * const sub = PMC_sub(SELF);
465         STRING            *hll_name;
466         int i;
468         SUPER(info);
469         /*
470          * we currently need to write these items:
471          * - start offset in byte-code segment
472          * - end   offset in byte-code segment
473          * - segment TODO ???
474          * - flags  (i.e. :load pragma and such)
475          * - name of the sub's label
476          * - namespace
477          * - HLL_id
478          * - multi_signature
479          * - n_regs_used[i]
480          * - lex_info
481          * - vtable_index
482          * - lexid
483          */
485         VTABLE_push_integer(INTERP, io, (INTVAL) sub->start_offs);
486         VTABLE_push_integer(INTERP, io, (INTVAL) sub->end_offs);
487         VTABLE_push_integer(INTERP, io,
488             PObj_get_FLAGS(pmc) & SUB_FLAG_PF_MASK);
490         VTABLE_push_string(INTERP, io, sub->name);
492         hll_name = Parrot_get_HLL_name(INTERP, sub->HLL_id);
493         if (!hll_name)
494             hll_name = CONST_STRING(INTERP, "");
496         VTABLE_push_string(INTERP, io, hll_name);
498         VTABLE_push_integer(INTERP, io, sub->comp_flags);
499         VTABLE_push_integer(INTERP, io, sub->vtable_index);
501         for (i = 0; i < 4; ++i)
502             VTABLE_push_integer(INTERP, io, sub->n_regs_used[i]);
504         if (!sub->lexid)
505             sub->lexid = CONST_STRING(INTERP, "");
506         VTABLE_push_string(INTERP, io, sub->lexid);
507     }
511 =item C<void thaw(visit_info *info)>
513 Unarchives the subroutine.
515 =cut
519     VTABLE void thaw(visit_info *info) {
520         IMAGE_IO * const io = info->image_io;
521         SUPER(info);
523         if (info->extra_flags == EXTRA_IS_NULL) {
524             Parrot_sub * const sub = PMC_sub(SELF);
525             INTVAL flags;
526             int    i;
528             /* we get relative offsets */
529             sub->start_offs   = (size_t) VTABLE_shift_integer(INTERP, io);
530             sub->end_offs     = (size_t) VTABLE_shift_integer(INTERP, io);
531             flags             = VTABLE_shift_integer(INTERP, io);
533             PObj_get_FLAGS(SELF) |= flags & SUB_FLAG_PF_MASK;
535             sub->name         = VTABLE_shift_string(INTERP, io);
536             sub->HLL_id       = Parrot_get_HLL_id(INTERP,
537                 VTABLE_shift_string(INTERP, io));
538             sub->comp_flags   = VTABLE_shift_integer(INTERP, io);
539             sub->vtable_index = VTABLE_shift_integer(INTERP, io);
541             for (i = 0; i < 4; ++i)
542                 sub->n_regs_used[i] = VTABLE_shift_integer(INTERP, io);
544             sub->lexid        = VTABLE_shift_string(INTERP, io);
545         }
546     }
550 =item C<PMC *inspect()>
552 Returns the full set of meta-data about the sub.
554 =cut
558     PMC *inspect()
559     {
560         /* Create a hash, then use inspect_str to get all of the data to
561          * fill it up with. */
562         PMC    * const metadata    = pmc_new(interp, enum_class_Hash);
563         STRING * const pos_required_str    = CONST_STRING(interp, "pos_required");
564         STRING * const pos_optional_str      = CONST_STRING(interp, "pos_optional");
565         STRING * const named_required_str   = CONST_STRING(interp, "named_required");
566         STRING * const named_optional_str   = CONST_STRING(interp, "named_optional");
567         STRING * const pos_slurpy_str = CONST_STRING(interp, "pos_slurpy");
568         STRING * const named_slurpy_str   = CONST_STRING(interp, "named_slurpy");
570         VTABLE_set_pmc_keyed_str(interp, metadata, pos_required_str,
571             VTABLE_inspect_str(interp, SELF, pos_required_str));
573         VTABLE_set_pmc_keyed_str(interp, metadata, pos_optional_str,
574             VTABLE_inspect_str(interp, SELF, pos_optional_str));
576         VTABLE_set_pmc_keyed_str(interp, metadata, named_required_str,
577             VTABLE_inspect_str(interp, SELF, named_required_str));
579         VTABLE_set_pmc_keyed_str(interp, metadata, named_optional_str,
580             VTABLE_inspect_str(interp, SELF, named_optional_str));
582         VTABLE_set_pmc_keyed_str(interp, metadata, pos_slurpy_str,
583             VTABLE_inspect_str(interp, SELF, pos_slurpy_str));
585         VTABLE_set_pmc_keyed_str(interp, metadata, named_slurpy_str,
586             VTABLE_inspect_str(interp, SELF, named_slurpy_str));
588         return metadata;
589     }
593 =item C<PMC *inspect_str(STRING *what)>
595 Returns the specified item of metadata about the sub. Allowable
596 values are:
598 =over 4
600 =item pos_required
602 The number of required positional arguments
604 =item pos_optional
606 The number of optional positional arguments
608 =item named_required
610 The number of required named arguments
612 =item named_optional
614 The number of optional named arguments
616 =item pos_slurpy
618 1 if it takes slurpy positional arguments, 0 if not
620 =item named_slurpy
622 1 if it takes slurpy named arguments, 0 if not
624 =back
626 =cut
630     PMC *inspect_str(STRING *what)
631     {
632         Parrot_sub * const sub = PMC_sub(SELF);
633         INTVAL count_found = -1;
634         PMC *retval;
636         /* If the argument info hasn't been generated yet, generate it. */
637         if (sub->arg_info == NULL)
638         {
639             /* Get pointer into the bytecode where this sub starts. */
640             opcode_t *pc = sub->seg->base.data + sub->start_offs;
642             /* Allocate structure to store argument information in. */
643             sub->arg_info = mem_allocate_zeroed_typed(Parrot_sub_arginfo);
645             /* If the first instruction is a get_params... */
646             if (*pc == PARROT_OP_get_params_pc) {
647                 int i, sig_length;
648                 PMC *sig;
650                 /* Get the signature (the next thing in the bytecode). */
651                 pc++;
652                 sig = PF_CONST(sub->seg, *pc)->u.key;
653                 ASSERT_SIG_PMC(sig);
655                 /* Iterate over the signature and compute argument counts. */
656                 sig_length = SIG_ELEMS(sig);
657                 for (i = 0; i < sig_length; i++)
658                 {
659                     int sig_item = SIG_ITEM(sig, i);
660                     if (PARROT_ARG_SLURPY_ARRAY_ISSET(sig_item)){
661                         if (PARROT_ARG_NAME_ISSET(sig_item))
662                             sub->arg_info->named_slurpy = 1;
663                         else
664                             sub->arg_info->pos_slurpy = 1;
665                     }
666                     else if (PARROT_ARG_OPTIONAL_ISSET(sig_item)) {
667                         if (PARROT_ARG_NAME_ISSET(sig_item))
668                             sub->arg_info->named_optional++;
669                         else
670                             sub->arg_info->pos_optional++;
671                     }
672                     else if (!PARROT_ARG_OPT_FLAG_ISSET(sig_item)) {
673                         if (PARROT_ARG_NAME_ISSET(sig_item))
674                             sub->arg_info->named_required++;
675                         else
676                             sub->arg_info->pos_required++;
677                     }
678                 }
679             }
680         }
682         /* Return the argument information that was requested. */
683         if (string_equal(interp, what, CONST_STRING(interp, "pos_required")) == 0) {
684             count_found = (INTVAL)sub->arg_info->pos_required;
685         }
686         else if (string_equal(interp, what, CONST_STRING(interp, "pos_optional")) == 0) {
687             count_found = (INTVAL)sub->arg_info->pos_optional;
688         }
689         else if (string_equal(interp, what, CONST_STRING(interp, "pos_slurpy")) == 0) {
690             count_found = (INTVAL)sub->arg_info->pos_slurpy;
691         }
692         else if (string_equal(interp, what, CONST_STRING(interp, "named_required")) == 0) {
693             count_found = (INTVAL)sub->arg_info->named_required;
694         }
695         else if (string_equal(interp, what, CONST_STRING(interp, "named_optional")) == 0) {
696             count_found = (INTVAL)sub->arg_info->named_optional;
697         }
698         else if (string_equal(interp, what, CONST_STRING(interp, "named_slurpy")) == 0) {
699             count_found = (INTVAL)sub->arg_info->named_slurpy;
700         }
701         else {
702             Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
703                 "Unknown introspection value '%S'", what);
704         }
706         retval = pmc_new(INTERP, enum_class_Integer);
707         VTABLE_set_integer_native(INTERP, retval, count_found);
708         return retval;
709     }
713 =back
715 =head2 METHODS
717 =over 4
719 =item C<PMC *get_namespace()>
721 Return the namespace PMC, where the Sub is defined.
723 TODO return C<namespace_stash> instead.
725 =item C<INTVAL __get_regs_used(char *kind)>
727 Return amount of used registers for register kinds "I", "S", "P", "N".
729 =item C<PMC *get_lexinfo()>
731 Return the LexInfo PMC, if any or a Null PMC.
733 =item C<PMC *get_multisig()>
735 Return the MMD signature PMC, if any or a Null PMC.
737 =item C<PMC *get_outer()>
739 Gets the sub that is the outer of this one, if any or a Null PMC.
741 =item C<void set_outer(PMC *outer)>
743 Sets the sub that is the outer of this one.
745 =item C<INTVAL arity()>
747 Return the arity of the Sub (the number of arugments, excluding optional and
748 slurpy arguments).
750 =cut
754     METHOD get_namespace() {
755         Parrot_sub * const sub = PMC_sub(SELF);
756         PMC *_namespace = sub->namespace_stash;
757         RETURN(PMC *_namespace);
758     }
760     METHOD __get_regs_used(STRING *reg) {
761         Parrot_sub * const sub  = PMC_sub(SELF);
762         char              *kind = string_to_cstring(interp, reg);
763         INTVAL             regs_used;
765         /* TODO switch to canonical NiSP order
766          * see also imcc/reg_alloc.c */
767         static const char types[] = "INSP";
768         char *p;
770         PARROT_ASSERT(sub->n_regs_used);
772         if (!*kind || kind[1]) {
773             string_cstring_free(kind);
774             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
775                 "illegal register kind '%Ss'", reg);
776         }
778         p = strchr(types, *kind);
779         string_cstring_free(kind);
781         if (!p)
782             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
783                 "illegal register kind '%Ss'", reg);
785         regs_used = sub->n_regs_used[p - types];
786         RETURN(INTVAL regs_used);
787     }
789     METHOD get_lexinfo() {
790         const Parrot_sub * const sub = PMC_sub(SELF);
791         PMC *lexinfo = sub->lex_info ? sub->lex_info : PMCNULL;
792         RETURN(PMC *lexinfo);
793     }
795     METHOD get_outer() {
796         const Parrot_sub * const sub = PMC_sub(SELF);
797         PMC *outersub = sub->outer_sub ? sub->outer_sub : PMCNULL;
798         RETURN(PMC *outersub);
799     }
801     METHOD set_outer(PMC *outer) {
802         /* Set outer sub. */
803         Parrot_sub * const sub = PMC_sub(SELF);
804         sub->outer_sub = outer;
806         /* Make sure outer flag of that sub is set. */
807         PObj_get_FLAGS(outer) |= SUB_FLAG_IS_OUTER;
809         /* Ensure we have lex info. */
810         if (PMC_IS_NULL(sub->lex_info)) {
811             const INTVAL lex_info_id = Parrot_get_ctx_HLL_type(interp,
812                                            enum_class_LexInfo);
813             sub->lex_info = pmc_new_init(interp, lex_info_id, SELF);
814         }
816         /* Finally, this sub needs to become a closure. Safe since
817          * they both use the same underlying structure. */
818         SELF->vtable = interp->vtables[enum_class_Closure];
819     }
821     METHOD get_multisig() {
822         const Parrot_sub * const sub = PMC_sub(SELF);
823         PMC *multisig = sub->multi_signature ? sub->multi_signature : PMCNULL;
824         RETURN(PMC *multisig);
825     }
827     METHOD arity() {
828         PMC *pos_required =
829             VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "pos_required"));
830         PMC *named_required =
831             VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "named_required"));
832         INTVAL arity = VTABLE_get_integer(INTERP, pos_required) +
833             VTABLE_get_integer(INTERP, named_required);
835         RETURN(INTVAL arity);
836     }
840  * Local variables:
841  *   c-file-style: "parrot"
842  * End:
843  * vim: expandtab shiftwidth=4:
844  */