[svn:parrot] r38810 - trunk/docs/pmc
coke at svn.parrot.org
coke at svn.parrot.org
Sat May 16 01:44:33 UTC 2009
Author: coke
Date: Sat May 16 01:44:32 2009
New Revision: 38810
URL: https://trac.parrot.org/parrot/changeset/38810
Log:
[docs] mark & test more PIR/PASM code
Update a bunch of these examples ot use valid PIR. Mark some as _INVALID.
Modified:
trunk/docs/pmc/array.pod
trunk/docs/pmc/subs.pod
Modified: trunk/docs/pmc/array.pod
==============================================================================
--- trunk/docs/pmc/array.pod Sat May 16 01:33:10 2009 (r38809)
+++ trunk/docs/pmc/array.pod Sat May 16 01:44:32 2009 (r38810)
@@ -13,17 +13,21 @@
=head1 SYNOPSIS
- new P0, 'Array' # initialize P0 as an array
+=begin PIR_FRAGMENT
- set I0, P0 # set I0 to the size of the array in P0
- set P0, 2 # set the size of the array in P0 to 2
+ new $P0, 'Array' # initialize P0 as an array
- set P0[0], "foo" # put "foo" into the array at position 0
- set I1, P0[1] # get an integer value from the entry
- # at array position 1
+ set $I0, $P0 # set I0 to the size of the array in P0
+ set $P0, 2 # set the size of the array in P0 to 2
- defined I2, P0[1] # is the value at position 1 defined?
- exists I3, P0[0] # is there an element at position 0?
+ set $P0[0], "foo " # put "foo" into the array at position 0
+ set $I1, $P0[1] # get an integer value from the entry
+ # at array position 1
+
+ defined $I2, $P0[1] # is the value at position 1 defined?
+ exists $I3, $P0[0] # is there an element at position 0?
+
+=end PIR_FRAGMENT
=head1 DESCRIPTION
@@ -32,20 +36,32 @@
As with any other PMC, the following line creates an array PMC in register
C<P0>:
- new P0, 'Array'
+=begin PIR_FRAGMENT
+
+ new $P0, 'Array'
+
+=end PIR_FRAGMENT
=head2 Array sizes
You can retrieve the size of the array using
- set I0, P0
+=begin PIR_FRAGMENT
+
+ set $I0, $P0
+
+=end PIR_FRAGMENT
This will put the size of the array in register C<P0> into C<I0>. In the same
way, assigning an integer directly to the array sets the size of the array.
For instance:
- new P0, 'Array'
- set P0, 2
+=begin PIR_FRAGMENT
+
+ new $P0, 'Array'
+ set $P0, 2
+
+=end PIR_FRAGMENT
creates a new Array (with default size 0) and then expands the size of the
array to two.
@@ -62,49 +78,73 @@
first position to the integer C<-8> and second position to the floating point
number C<3.1415>.
- new P0, 'Array'
- set P0, 2
+=begin PIR_FRAGMENT
+
+ new $P0, 'Array'
+ set $P0, 2
+
+ set $P0[0], -8
+ set $P0[1], 3.1415
- set P0[0], -8
- set P0[1], 3.1415
+=end PIR_FRAGMENT
You can also assign directly from registers; for instance:
- new P0, 'Array'
- set P0, 2
+=begin PIR_FRAGMENT
- set I0, -8
- set N0, 3.1415
+ new $P0, 'Array'
+ set $P0, 2
- set P0[0], I0
- set P0[1], N0
+ set $I0, -8
+ set $N0, 3.1415
+
+ set $P0[0], $I0
+ set $P0[1], $N0
+
+=end PIR_FRAGMENT
leaves P0 in the same state as in the previous code snippet.
To retrieve elements, we use the same syntax:
- set N1, P0[1]
- set I1, P0[0]
+=begin PIR_FRAGMENT
+
+ set $N1, $P0[1]
+ set $I1, $P0[0]
+
+=end PIR_FRAGMENT
Those two lines retrieve the values from the array back into registers.
The value stored at a given position is not fixed; it can be changed simply by
assigning a new value:
- set P0[1], "A string"
+=begin PIR_FRAGMENT
+
+ set $P0[1], "A string"
+
+=end PIR_FRAGMENT
Accessing an out-of-bounds array element raises an exception; if you want an
Array that will automatically resize, then use a C<ResizablePMCArray>.
You can test if there is a defined element at an array position by using
- defined I0, P0[1]
+=begin PIR_FRAGMENT
+
+ defined $I0, $P0[1]
+
+=end PIR_FRAGMENT
for the position you want to test. On the other hand, if you only want to test
whether a given element exists (rather than whether it is defined), then use
the C<exists> op instead:
- exists I0, P0[0]
+=begin PIR_FRAGMENT
+
+ exists $I0, $P0[0]
+
+=end PIR_FRAGMENT
=head2 TODO
Modified: trunk/docs/pmc/subs.pod
==============================================================================
--- trunk/docs/pmc/subs.pod Sat May 16 01:33:10 2009 (r38809)
+++ trunk/docs/pmc/subs.pod Sat May 16 01:44:32 2009 (r38810)
@@ -70,13 +70,19 @@
B<get_root_global> opcodes. Within the PIR source, they can also be put in
registers with a C<.const 'Sub'> declaration:
+=begin PIR_FRAGMENT
+
.const 'Sub' rsub = 'random_sub'
+=end PIR_FRAGMENT
+
This uses C<find_sub_not_null> under the hood to look up the sub named
"random_sub".
Here's an example of fetching a sub from another namespace:
+=begin PIR
+
.sub main :main
get_hll_global $P0, ['Other'; 'Namespace'], "the_sub"
$P0()
@@ -89,6 +95,8 @@
print "in sub\n"
.end
+=end PIR
+
Note that C<the_sub> could be defined in a different bytecode or PIR source
file from C<main>.
@@ -97,7 +105,13 @@
One subroutine in the first executed source or bytecode file may be flagged as
the "main" subroutine, where execution starts.
+=begin PIR
+
.sub the_main_event :main
+ # ...
+ .end
+
+=end PIR
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
@@ -114,6 +128,8 @@
e.g.
+=begin PIR
+
.sub main :main
print "in main\n"
load_bytecode "library_code.pir"
@@ -126,6 +142,8 @@
print "initializing library\n"
.end
+=end PIR
+
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
@@ -153,10 +171,16 @@
PIR sub invocation syntax is similar to HLL syntax:
+=begin PIR_FRAGMENT
+
$P0 = do_something($P1, $S3)
+=end PIR_FRAGMENT
+
This is syntactic sugar for the following four bytecode instructions:
+=begin PIR_FRAGMENT
+
# Establish arguments.
set_args '(0,0)', $P1, $S3
# Find the sub.
@@ -166,6 +190,8 @@
# Call the sub in $P8, implicitly creating a return continuation.
invokecc $P8
+=end PIR_FRAGMENT
+
The sub name could be replaced with a PMC register, in which case the
C<find_sub_not_null> instruction would not be needed. If the return values
from the sub were ignored (by dropping the C<$P0 => part), the C<get_results>
@@ -181,34 +207,85 @@
To receive multiple values, put the register names in parentheses:
+=begin PIR_FRAGMENT
+
+ ($P10, $P11) = do_something($P1, $S3)
+
($P10, $P11) = do_something($P1, $S3)
+=end PIR_FRAGMENT
+
+To test whether a value was returned, declare it C<:optional>, and follow it
+with an integer register declared C<:opt_val>:
+
+=begin PIR_FRAGMENT_INVALID
+
+ ($P10 :optional, $I10 :opt_val) = do_something($P1, $S3)
+
+=end PIR_FRAGMENT_INVALID
+
+Both of these affect only the signature provided via C<get_results>.
+
+[should also describe :flat, :slurpy, :named, ..., or at least provide a
+reference. -- rgr, 25-May-08.]
+
+=begin PIR_FRAGMENT
+
+ # Call the sub in $P8, with continuation (created earlier) in $P9.
+ invoke $P8, $P9
+
+=end PIR_FRAGMENT
+
+=head2 Returning from a sub
+
+PIR supports a convenient syntax for returning any number of values from a sub
+or closure:
+
+
To test whether a value was returned, declare it C<:optional>, and follow it
with an integer register declared C<:opt_val>:
+=begin PIR_FRAGMENT_INVALID
+
($P10 :optional, $I10 :opt_val) = do_something($P1, $S3)
+=end PIR_FRAGMENT_INVALID
+
Both of these affect only the signature provided via C<get_results>.
[should also describe :flat, :slurpy, :named, ..., or at least provide a
reference. -- rgr, 25-May-08.]
+=begin PIR_FRAGMENT
+
# Call the sub in $P8, with continuation (created earlier) in $P9.
invoke $P8, $P9
+=end PIR_FRAGMENT
+
=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)
+=begin PIR
+
+ .sub main
+ .return ($P0, $I1, $S3)
+ .end
+
+=end PIR
Integer, float, and string constants are also accepted. This is translated
to:
+=begin PIR_FRAGMENT
+
get_results '(0,0,0)', $P0, $I1, $S3
returncc # return by calling the current continuation
+=end PIR_FRAGMENT
+
As for C<set_args>, 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".
@@ -218,21 +295,33 @@
caller of the old sub (i.e. without first returning to the old sub). This
passes the three values to C<another_sub> via tail-calling:
- .return another_sub($P0, $I1, $S3)
+=begin PIR
+
+ .sub main
+ .tailcall another_sub($P0, $I1, $S3)
+ .end
+
+=end PIR
This is translated into a C<set_args> instruction for the call, but with
C<tailcall> instead of C<invokecc>:
+=begin PIR_FRAGMENT
+
set_args '(0,0,0)', $P0, $I1, $S3
$P8 = find_sub_not_null "another_sub"
tailcall $P8
+=end PIR_FRAGMENT
+
As for calling, the sub name could be replaced with a PMC register, in which
case the C<find_sub_not_null> instruction would not be needed.
If needed, the current continuation can be extracted and called explicitly as
follows:
+=begin PIR_FRAGMENT
+
## This is what defines .INTERPINFO_CURRENT_CONT.
.include 'interpinfo.pasm'
## Store our return continuation as exit_cont.
@@ -243,12 +332,16 @@
## ... or equivalently:
tailcall exit_cont
+=end PIR_FRAGMENT
+
To return values, use C<set_args> as before.
=head2 All together now
The following complete example illustrates the typical call/return pattern:
+=begin PIR
+
.sub main :main
print "in main\n"
the_sub()
@@ -259,6 +352,8 @@
print "in sub\n"
.end
+=end PIR
+
Notice that we are not passing or returning values here.
[example of passing values. this could get pretty elaborate; look for other
@@ -267,6 +362,8 @@
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:
+=begin PIR_INVALID
+
.sub main :main
## Initialize the sub and the return cont.
.local pmc cont
@@ -293,6 +390,8 @@
## do_something
.end
+=end PIR_INVALID
+
If the sub returns values, the C<get_results> must be B<after> C<ret_label> in
order to receive them.
More information about the parrot-commits
mailing list