=head1 NAME Subs - Parrot Subroutines =head1 VERSION $Revision: 37201 $ =head1 ABSTRACT This document describes how to define, call, and return from Parrot subroutine objects and other invokables. =head1 DESCRIPTION Parrot comes with different subroutine and related classes which implement CPS (Continuation Passing Style) and PCC (Parrot Calling Conventions) F. =head2 Class Tree These are all of the built-in classes that are directly callable, or "invokable": Sub Closure Coroutine Eval Continuation RetContinuation ExceptionHandler By "invokable" we mean that they can be supplied as the first argument to the C, C, or C instructions. Generally speaking, invokable objects are divided into two subtypes: C and classes that are built on it create a new context when invoked, and C classes return control to an existing context that was captured when the C was created. There are (of course) two classes that straddle this distinction: =over 4 =item 1. Invoking a C object creates a new context for the sub it refers to directly, but it also captures an "outer" context that provides bindings for the immediately-enclosing lexical scope (and, if that context is itself is for a C, the subsequent scopes working outwards). [add a C example? -- rgr, 6-Apr-08.] =item 2. A C acts like a normal sub when called initially, and can also return normally, but acts like a continuation when exited via the C instruction and re-entered by re-invoking. [need a reference to a C example. -- rgr, 6-Apr-08.] =back =head1 SYNOPSIS =head2 Creating subs Subs are created by IMCC (the PIR compiler) via the B<.sub> directive. Unless the C<:anon> pragma is included, they are stored in the constant table associated with the bytecode and can be fetched with the B and B opcodes. Within the PIR source, they can also be put in registers with a C<.const .Sub> declaration: .const .Sub rsub = 'random_sub' This uses C under the hood to look up the sub named "random_sub". Here's an example of fetching a sub from another namespace: .sub main :main get_hll_global $P0, ['Other'; 'Namespace'], "the_sub" $P0() print "back\n" .end .namespace ['Other'; 'Namespace'] .sub the_sub print "in sub\n" .end Note that C could be defined in a different bytecode or PIR source file from C
. =head2 Program entry point One subroutine in the first executed source or bytecode file may be flagged as the "main" subroutine, where execution starts. .sub the_main_event :main In the absence of a B<:main> entry Parrot starts execution at the first statement. Any C<:main> directives in a subsequent PIR or bytecode file that are loaded under program control are ignored. Note that if the first executed source or bytecode file contains more than one sub flagged as C<:main>, Parrot currently picks the I such sub to start execution. This is arguably a bug, so users should not depend upon it. =head2 Load-time initialization If a subroutine is marked as B<:load> this subroutine is run, before the B opcode returns. e.g. .sub main :main print "in main\n" load_bytecode "library_code.pir" print "back to main\n" .end # library_code.pir .sub _my_lib_init :load print "initializing library\n" .end If a subroutine is marked as B<:init> this subroutine is run before the B<:main> or the first subroutine in the source file runs. Unlike B<:main> subs, B<:init> subs are also run when compiling from memory. B<:load> subs are run only in any source or bytecode files loaded subsequently. These markers are called "pragmas", and are defined fully in L. The following table summarizes the behavior of the five pragmas that cause Parrot to run a sub implicitly: ------ Executed when -------- compiling to -- loading -- Sub Pragma disk memory first after ========== ==== ====== ===== ===== :immediate yes yes no no :postcomp yes no no no :load no no no yes :init no yes yes no :main no no yes no The same load-time behavior applies regardless of whether the loaded file is PIR source or bytecode. Note that it is possible to mark a sub with both B<:load> and B<:init>. =head2 Calling the sub PIR sub invocation syntax is similar to HLL syntax: $P0 = do_something($P1, $S3) This is syntactic sugar for the following four bytecode instructions: # Establish arguments. set_args '(0,0)', $P1, $S3 # Find the sub. $P8 = find_sub_not_null "do_something" # Establish return values. get_results '(0)', $P0 # Call the sub in $P8, implicitly creating a return continuation. invokecc $P8 The sub name could be replaced with a PMC register, in which case the C instruction would not be needed. If the return values from the sub were ignored (by dropping the C<$P0 => part), the C instruction would be omitted. However, C is emitted even in the case of a call without arguments. The first operands to the C and C instructions are actually placeholders for an integer array that describes the register types. For example, the '(0,0)' for C is replaced internally with C<[2, 1]>, which means "two arguments, of type PMC and string". Note that return values get the same register type coercion as sub parameters. This is all described in much more detail in L. To receive multiple values, put the register names in parentheses: ($P10, $P11) = do_something($P1, $S3) To test whether a value was returned, declare it C<:optional>, and follow it with an integer register declared C<:opt_val>: ($P10 :optional, $I10 :opt_val) = do_something($P1, $S3) Both of these affect only the signature provided via C. [should also describe :flat, :slurpy, :named, ..., or at least provide a reference. -- rgr, 25-May-08.] # Call the sub in $P8, with continuation (created earlier) in $P9. invoke $P8, $P9 =head2 Returning from a sub PIR supports a convenient syntax for returning any number of values from a sub or closure: .return ($P0, $I1, $S3) Integer, float, and string constants are also accepted. This is translated to: get_results '(0,0,0)', $P0, $I1, $S3 returncc # return by calling the current continuation As for C, the '(0,0,0)' is actually a placeholder for an integer array that describes the register types; it is replaced internally with C<[2, 0, 1]>, which means "three arguments, of type PMC, integer, and string". Another way to return from a sub is to use tail-calling, which calls a new sub with the current continuation, so that the new sub returns directly to the caller of the old sub (i.e. without first returning to the old sub). This passes the three values to C via tail-calling: .return another_sub($P0, $I1, $S3) This is translated into a C instruction for the call, but with C instead of C: set_args '(0,0,0)', $P0, $I1, $S3 $P8 = find_sub_not_null "another_sub" tailcall $P8 As for calling, the sub name could be replaced with a PMC register, in which case the C instruction would not be needed. If needed, the current continuation can be extracted and called explicitly as follows: ## This is what defines .INTERPINFO_CURRENT_CONT. .include 'interpinfo.pasm' ## Store our return continuation as exit_cont. .local pmc exit_cont exit_cont = interpinfo .INTERPINFO_CURRENT_CONT ## Invoke it explicitly: invokecc exit_cont ## ... or equivalently: tailcall exit_cont To return values, use C as before. =head2 All together now The following complete example illustrates the typical call/return pattern: .sub main :main print "in main\n" the_sub() print "back to main\n" .end .sub the_sub print "in sub\n" .end Notice that we are not passing or returning values here. [example of passing values. this could get pretty elaborate; look for other examples first. -- rgr, 6-Apr-08.] If a short subroutine is called several times, for instance inside a loop, the creation of the return continuation can be done outside the loop: .sub main :main ## Initialize the sub and the return cont. .local pmc cont cont = new 'Continuation' set_addr cont, ret_label .const .Sub rsub = 'random_sub' ## Loop initialization. .local int loop_max, i loop_max = 1000000 i = 0 ## Main loop. again: set_args '(0)', i invoke rsub, cont ret_label: ## This is where "cont" returns. inc i if i < loop_max goto again .end .sub random_sub .param int foo ## do_something .end If the sub returns values, the C must be B C in order to receive them. Since this is much more obscure than the PIR calling syntax, it should only be done if there is a measurable performance advantage. Even in this trivial example, calling "rsub(i)" is only about a third slower on x86. =head1 FILES F, F, F, F, F, F =head1 SEE ALSO F F =head1 AUTHOR Leopold Toetsch =cut __END__ Local Variables: fill-column:78 End: