[svn:parrot] r39797 - in branches/pmc_pct: . compilers/imcc compilers/nqp/src/Grammar compilers/pct/src/PAST compilers/pct/src/PCT compilers/pge/PGE config/auto/sizes config/gen config/gen/makefiles docs docs/book docs/book/draft docs/book/pir docs/dev docs/pdds docs/project docs/user/pir examples/languages/abc examples/languages/squaak examples/opengl examples/tutorial include/parrot lib/Parrot lib/Parrot/Docs/Section lib/Parrot/Pmc2c lib/Parrot/Pmc2c/PMC ports/cpan ports/cygwin ports/debian ports/fedora ports/mandriva ports/suse runtime/parrot/languages runtime/parrot/languages/parrot runtime/parrot/library runtime/parrot/library/CGI runtime/parrot/library/Getopt runtime/parrot/library/MIME runtime/parrot/library/Math runtime/parrot/library/NCI runtime/parrot/library/OpenGL runtime/parrot/library/PGE runtime/parrot/library/Test runtime/parrot/library/Test/Builder src src/call src/gc src/interp src/io src/jit/i386 src/ops src/pmc src/runcore src/string src/string/ch arset t/codingstd t/compilers/imcc/syn t/compilers/pge/perl6regex t/compilers/tge t/distro t/dynpmc t/examples t/library t/oo t/op t/pmc t/src tools/dev tools/util
cotto at svn.parrot.org
cotto at svn.parrot.org
Fri Jun 26 08:35:36 UTC 2009
Author: cotto
Date: Fri Jun 26 08:35:24 2009
New Revision: 39797
URL: https://trac.parrot.org/parrot/changeset/39797
Log:
bring branch up-to-date with trunk
Added:
branches/pmc_pct/docs/book/draft/README
- copied unchanged from r39796, trunk/docs/book/draft/README
branches/pmc_pct/docs/book/draft/appa_glossary.pod
- copied unchanged from r39796, trunk/docs/book/draft/appa_glossary.pod
branches/pmc_pct/docs/book/draft/appb_patch_submission.pod
- copied unchanged from r39796, trunk/docs/book/draft/appb_patch_submission.pod
branches/pmc_pct/docs/book/draft/appc_command_line_options.pod
- copied unchanged from r39796, trunk/docs/book/draft/appc_command_line_options.pod
branches/pmc_pct/docs/book/draft/appd_build_options.pod
- copied unchanged from r39796, trunk/docs/book/draft/appd_build_options.pod
branches/pmc_pct/docs/book/draft/appe_source_code.pod
- copied unchanged from r39796, trunk/docs/book/draft/appe_source_code.pod
branches/pmc_pct/docs/book/draft/ch01_introduction.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch01_introduction.pod
branches/pmc_pct/docs/book/draft/ch02_getting_started.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch02_getting_started.pod
branches/pmc_pct/docs/book/draft/ch03_pir.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch03_pir.pod
branches/pmc_pct/docs/book/draft/ch04_compiler_tools.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch04_compiler_tools.pod
branches/pmc_pct/docs/book/draft/ch05_pge.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch05_pge.pod
branches/pmc_pct/docs/book/draft/ch06_nqp.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch06_nqp.pod
branches/pmc_pct/docs/book/draft/ch07_dynpmcs.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch07_dynpmcs.pod
branches/pmc_pct/docs/book/draft/ch08_dynops.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch08_dynops.pod
branches/pmc_pct/docs/book/draft/ch10_opcode_reference.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch10_opcode_reference.pod
branches/pmc_pct/docs/book/draft/ch11_directive_reference.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch11_directive_reference.pod
branches/pmc_pct/docs/book/draft/ch12_operator_reference.pod
- copied unchanged from r39796, trunk/docs/book/draft/ch12_operator_reference.pod
branches/pmc_pct/docs/book/pir/
- copied from r39796, trunk/docs/book/pir/
branches/pmc_pct/examples/opengl/math.pir
- copied unchanged from r39796, trunk/examples/opengl/math.pir
branches/pmc_pct/runtime/parrot/library/Curses.pir
- copied unchanged from r39796, trunk/runtime/parrot/library/Curses.pir
branches/pmc_pct/runtime/parrot/library/NCI/Utils.pir
- copied unchanged from r39796, trunk/runtime/parrot/library/NCI/Utils.pir
branches/pmc_pct/runtime/parrot/library/OpenGL/ (props changed)
- copied from r39796, trunk/runtime/parrot/library/OpenGL/
branches/pmc_pct/t/codingstd/test_file_coverage.t
- copied unchanged from r39796, trunk/t/codingstd/test_file_coverage.t
branches/pmc_pct/t/pmc/handle.t
- copied unchanged from r39796, trunk/t/pmc/handle.t
Replaced:
branches/pmc_pct/docs/book/pir/ch01_introduction.pod
- copied unchanged from r39796, trunk/docs/book/pir/ch01_introduction.pod
branches/pmc_pct/docs/book/pir/ch02_getting_started.pod
- copied unchanged from r39796, trunk/docs/book/pir/ch02_getting_started.pod
branches/pmc_pct/docs/book/pir/ch03_basic_syntax.pod
- copied unchanged from r39796, trunk/docs/book/pir/ch03_basic_syntax.pod
branches/pmc_pct/docs/book/pir/ch04_variables.pod
- copied unchanged from r39796, trunk/docs/book/pir/ch04_variables.pod
branches/pmc_pct/docs/book/pir/ch05_control_structures.pod
- copied unchanged from r39796, trunk/docs/book/pir/ch05_control_structures.pod
branches/pmc_pct/docs/book/pir/ch06_subroutines.pod
- copied unchanged from r39796, trunk/docs/book/pir/ch06_subroutines.pod
branches/pmc_pct/docs/book/pir/ch07_objects.pod
- copied unchanged from r39796, trunk/docs/book/pir/ch07_objects.pod
branches/pmc_pct/docs/book/pir/ch08_io.pod
- copied unchanged from r39796, trunk/docs/book/pir/ch08_io.pod
branches/pmc_pct/docs/book/pir/ch09_exceptions.pod
- copied unchanged from r39796, trunk/docs/book/pir/ch09_exceptions.pod
branches/pmc_pct/runtime/parrot/library/OpenGL/Math.pir
- copied unchanged from r39796, trunk/runtime/parrot/library/OpenGL/Math.pir
Deleted:
branches/pmc_pct/docs/book/README
branches/pmc_pct/docs/book/appa_glossary.pod
branches/pmc_pct/docs/book/appb_patch_submission.pod
branches/pmc_pct/docs/book/appc_command_line_options.pod
branches/pmc_pct/docs/book/appd_build_options.pod
branches/pmc_pct/docs/book/appe_source_code.pod
branches/pmc_pct/docs/book/ch01_introduction.pod
branches/pmc_pct/docs/book/ch02_getting_started.pod
branches/pmc_pct/docs/book/ch03_pir.pod
branches/pmc_pct/docs/book/ch04_compiler_tools.pod
branches/pmc_pct/docs/book/ch05_pge.pod
branches/pmc_pct/docs/book/ch06_nqp.pod
branches/pmc_pct/docs/book/ch07_dynpmcs.pod
branches/pmc_pct/docs/book/ch08_dynops.pod
branches/pmc_pct/docs/book/ch10_opcode_reference.pod
branches/pmc_pct/docs/book/ch11_directive_reference.pod
branches/pmc_pct/docs/book/ch12_operator_reference.pod
branches/pmc_pct/t/distro/test_file_coverage.t
Modified:
branches/pmc_pct/ (props changed)
branches/pmc_pct/CREDITS
branches/pmc_pct/ChangeLog
branches/pmc_pct/DEPRECATED.pod
branches/pmc_pct/MANIFEST
branches/pmc_pct/MANIFEST.SKIP
branches/pmc_pct/MANIFEST.generated
branches/pmc_pct/META.yml
branches/pmc_pct/NEWS
branches/pmc_pct/PLATFORMS
branches/pmc_pct/README
branches/pmc_pct/VERSION
branches/pmc_pct/compilers/imcc/imc.c
branches/pmc_pct/compilers/imcc/imc.h
branches/pmc_pct/compilers/imcc/imcc.l
branches/pmc_pct/compilers/imcc/imcc.y
branches/pmc_pct/compilers/imcc/imclexer.c
branches/pmc_pct/compilers/imcc/imcparser.c
branches/pmc_pct/compilers/imcc/instructions.c
branches/pmc_pct/compilers/imcc/main.c
branches/pmc_pct/compilers/imcc/optimizer.c
branches/pmc_pct/compilers/imcc/parser_util.c
branches/pmc_pct/compilers/imcc/pbc.c
branches/pmc_pct/compilers/imcc/pcc.c
branches/pmc_pct/compilers/imcc/reg_alloc.c
branches/pmc_pct/compilers/imcc/symreg.c
branches/pmc_pct/compilers/nqp/src/Grammar/Actions.pir
branches/pmc_pct/compilers/pct/src/PAST/Compiler.pir
branches/pmc_pct/compilers/pct/src/PCT/Dumper.pir
branches/pmc_pct/compilers/pge/PGE/Match.pir
branches/pmc_pct/compilers/pge/PGE/Perl6Regex.pir
branches/pmc_pct/config/auto/sizes/intval_maxmin_c.in (props changed)
branches/pmc_pct/config/gen/makefiles/root.in
branches/pmc_pct/config/gen/opengl.pm
branches/pmc_pct/docs/book/draft/chXX_hlls.pod (props changed)
branches/pmc_pct/docs/book/draft/chXX_library.pod (props changed)
branches/pmc_pct/docs/book/draft/chXX_testing_and_debugging.pod (props changed)
branches/pmc_pct/docs/dev/c_functions.pod (props changed)
branches/pmc_pct/docs/parrothist.pod
branches/pmc_pct/docs/pdds/pdd19_pir.pod
branches/pmc_pct/docs/pdds/pdd27_multiple_dispatch.pod
branches/pmc_pct/docs/pdds/pdd30_install.pod (props changed)
branches/pmc_pct/docs/project/release_manager_guide.pod
branches/pmc_pct/docs/user/pir/objects.pod
branches/pmc_pct/docs/user/pir/pmcs.pod
branches/pmc_pct/examples/languages/abc/ (props changed)
branches/pmc_pct/examples/languages/squaak/ (props changed)
branches/pmc_pct/examples/opengl/shapes.p6
branches/pmc_pct/examples/opengl/shapes.pir
branches/pmc_pct/examples/opengl/static-triangle.p6
branches/pmc_pct/examples/opengl/static-triangle.pir
branches/pmc_pct/examples/opengl/triangle.p6
branches/pmc_pct/examples/opengl/triangle.pir
branches/pmc_pct/examples/tutorial/01_temp_var.pir
branches/pmc_pct/examples/tutorial/02_local_var.pir
branches/pmc_pct/examples/tutorial/03_temp_var_basic_pmcs.pir
branches/pmc_pct/examples/tutorial/24_string_ops_clone.pir
branches/pmc_pct/examples/tutorial/30_arrays_basic.pir
branches/pmc_pct/examples/tutorial/32_array_ops_sprintf.pir
branches/pmc_pct/examples/tutorial/33_hashes.pir
branches/pmc_pct/examples/tutorial/34_multikey.pir
branches/pmc_pct/examples/tutorial/40_file_ops.pir
branches/pmc_pct/examples/tutorial/55_iterator.pir
branches/pmc_pct/examples/tutorial/56_defined.pir
branches/pmc_pct/examples/tutorial/57_exists.pir
branches/pmc_pct/examples/tutorial/61_namespaces.pir
branches/pmc_pct/examples/tutorial/70_class_object.pir
branches/pmc_pct/examples/tutorial/81_continuation.pir
branches/pmc_pct/include/parrot/call.h (props changed)
branches/pmc_pct/include/parrot/gc_api.h (props changed)
branches/pmc_pct/include/parrot/key.h
branches/pmc_pct/include/parrot/memory.h
branches/pmc_pct/include/parrot/runcore_api.h (props changed)
branches/pmc_pct/include/parrot/runcore_trace.h (props changed)
branches/pmc_pct/include/parrot/stacks.h
branches/pmc_pct/include/parrot/sub.h
branches/pmc_pct/lib/Parrot/Docs/Section/Parrot.pm
branches/pmc_pct/lib/Parrot/Install.pm
branches/pmc_pct/lib/Parrot/Pmc2c/Attribute.pm
branches/pmc_pct/lib/Parrot/Pmc2c/PMC.pm
branches/pmc_pct/lib/Parrot/Pmc2c/PMC/RO.pm
branches/pmc_pct/lib/Parrot/Pmc2c/PMCEmitter.pm
branches/pmc_pct/ports/cpan/pause_guide.pod (props changed)
branches/pmc_pct/ports/cygwin/parrot-1.0.0-1.cygport (props changed)
branches/pmc_pct/ports/debian/libparrot-dev.install.in (props changed)
branches/pmc_pct/ports/debian/libparrot.install.in (props changed)
branches/pmc_pct/ports/debian/parrot-doc.install.in (props changed)
branches/pmc_pct/ports/debian/parrot.install.in (props changed)
branches/pmc_pct/ports/fedora/parrot.spec.fedora (props changed)
branches/pmc_pct/ports/mandriva/parrot.spec.mandriva (props changed)
branches/pmc_pct/ports/suse/parrot.spec.suse (props changed)
branches/pmc_pct/runtime/parrot/languages/ (props changed)
branches/pmc_pct/runtime/parrot/languages/parrot/parrot.pir
branches/pmc_pct/runtime/parrot/library/CGI/QueryHash.pir
branches/pmc_pct/runtime/parrot/library/Getopt/Obj.pir
branches/pmc_pct/runtime/parrot/library/MIME/Base64.pir
branches/pmc_pct/runtime/parrot/library/Math/Rand.pir (props changed)
branches/pmc_pct/runtime/parrot/library/OpenGL.pir
branches/pmc_pct/runtime/parrot/library/P6object.pir
branches/pmc_pct/runtime/parrot/library/PGE/Util.pir
branches/pmc_pct/runtime/parrot/library/Range.pir
branches/pmc_pct/runtime/parrot/library/Test/Builder/Output.pir
branches/pmc_pct/runtime/parrot/library/Test/More.pir
branches/pmc_pct/src/call/ops.c (props changed)
branches/pmc_pct/src/call/pcc.c (props changed)
branches/pmc_pct/src/debug.c
branches/pmc_pct/src/gc/alloc_memory.c (contents, props changed)
branches/pmc_pct/src/gc/alloc_register.c (props changed)
branches/pmc_pct/src/gc/alloc_resources.c (props changed)
branches/pmc_pct/src/gc/api.c (contents, props changed)
branches/pmc_pct/src/gc/gc_ms.c
branches/pmc_pct/src/gc/generational_ms.c (props changed)
branches/pmc_pct/src/gc/incremental_ms.c (props changed)
branches/pmc_pct/src/gc/malloc.c (props changed)
branches/pmc_pct/src/gc/malloc_trace.c (props changed)
branches/pmc_pct/src/gc/mark_sweep.c (props changed)
branches/pmc_pct/src/gc/system.c (props changed)
branches/pmc_pct/src/hash.c
branches/pmc_pct/src/interp/inter_cb.c (props changed)
branches/pmc_pct/src/interp/inter_create.c (contents, props changed)
branches/pmc_pct/src/interp/inter_misc.c (props changed)
branches/pmc_pct/src/io/unix.c
branches/pmc_pct/src/jit/i386/jit_defs.c
branches/pmc_pct/src/key.c
branches/pmc_pct/src/library.c
branches/pmc_pct/src/main.c
branches/pmc_pct/src/ops/cmp.ops
branches/pmc_pct/src/ops/ops.num
branches/pmc_pct/src/packfile.c
branches/pmc_pct/src/parrot_debugger.c
branches/pmc_pct/src/pbc_merge.c
branches/pmc_pct/src/pmc.c
branches/pmc_pct/src/pmc/bignum.pmc
branches/pmc_pct/src/pmc/default.pmc
branches/pmc_pct/src/pmc/filehandle.pmc
branches/pmc_pct/src/pmc/handle.pmc (contents, props changed)
branches/pmc_pct/src/pmc/multisub.pmc
branches/pmc_pct/src/pmc/parrotinterpreter.pmc
branches/pmc_pct/src/pmc/parrotrunningthread.pmc
branches/pmc_pct/src/pmc/parrotthread.pmc
branches/pmc_pct/src/pmc/stringhandle.pmc
branches/pmc_pct/src/pmc/sub.pmc
branches/pmc_pct/src/pmc_freeze.c
branches/pmc_pct/src/runcore/cores.c (props changed)
branches/pmc_pct/src/runcore/main.c (props changed)
branches/pmc_pct/src/runcore/trace.c (contents, props changed)
branches/pmc_pct/src/stacks.c
branches/pmc_pct/src/string/ (props changed)
branches/pmc_pct/src/string/api.c
branches/pmc_pct/src/string/charset/unicode.c
branches/pmc_pct/t/codingstd/c_indent.t
branches/pmc_pct/t/compilers/imcc/syn/errors.t
branches/pmc_pct/t/compilers/imcc/syn/regressions.t
branches/pmc_pct/t/compilers/pge/perl6regex/context.t
branches/pmc_pct/t/compilers/tge/NoneGrammar.tg (props changed)
branches/pmc_pct/t/dynpmc/pair.t (props changed)
branches/pmc_pct/t/examples/pod.t
branches/pmc_pct/t/library/p6object.t
branches/pmc_pct/t/library/test_more.t
branches/pmc_pct/t/oo/root_new.t (props changed)
branches/pmc_pct/t/op/cmp-nonbranch.t
branches/pmc_pct/t/op/debuginfo.t
branches/pmc_pct/t/op/lexicals.t
branches/pmc_pct/t/op/number.t
branches/pmc_pct/t/op/sprintf.t
branches/pmc_pct/t/op/string.t
branches/pmc_pct/t/op/stringu.t
branches/pmc_pct/t/pmc/bignum.t
branches/pmc_pct/t/pmc/exceptionhandler.t
branches/pmc_pct/t/pmc/namespace.t
branches/pmc_pct/t/src/embed.t (props changed)
branches/pmc_pct/tools/dev/branch_status.pl
branches/pmc_pct/tools/dev/fetch_languages.pl (props changed)
branches/pmc_pct/tools/dev/mk_gitignore.pl (props changed)
branches/pmc_pct/tools/dev/pbc_to_exe.pir
branches/pmc_pct/tools/util/perlcritic-cage.conf (props changed)
branches/pmc_pct/tools/util/release.json
Modified: branches/pmc_pct/CREDITS
==============================================================================
--- branches/pmc_pct/CREDITS Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/CREDITS Fri Jun 26 08:35:24 2009 (r39797)
@@ -92,7 +92,7 @@
N: Andrew Whitworth
D: Internals development
D: Documentation
-D: Release manager for 0.8.2
+D: Release manager for 0.8.2 and 1.3.0
E: wknight8111 at gmail.com
U: Whiteknight
Modified: branches/pmc_pct/ChangeLog
==============================================================================
--- branches/pmc_pct/ChangeLog Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/ChangeLog Fri Jun 26 08:35:24 2009 (r39797)
@@ -1,5 +1,9 @@
#1 $Id$
+2009.06.16 Whiteknight
+ * Released 1.3.0
+ Ses NEWS for more.
+
2009.05.19 Infinoid
* Released 1.2.0
See NEWS for more.
Modified: branches/pmc_pct/DEPRECATED.pod
==============================================================================
--- branches/pmc_pct/DEPRECATED.pod Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/DEPRECATED.pod Fri Jun 26 08:35:24 2009 (r39797)
@@ -1,14 +1,26 @@
# $Id$
-=head1 Deprecation in Parrot
+=head1 Purpose
+
+Provide a list of deprecated and experimental items in parrot.
+All items in this list should have a corresponding Trac ticket[1].
+
+=head1 Experimental Status
+
+These features are not considered stable, even though they may
+have shipped in a stable release of parrot[2]. Use them at your own
+risk, as they can be removed or changed in any release. These
+items are marked below with C<[experimental]>.
+
+=head1 Deprecated Status
Please see F<docs/project/support_policy.pod> for the parrot
project's policy regarding deprecated features.
-This is a list of currently deprecated features of Parrot. Every deprecation
-has an associated Trac ticket [1]. Each item indicates the first release
-in which it is eligible for removal. If the release listed is one that
-has already occurred, this feature may be removed in any upcoming release.
+Each item shows the first release in which it is eligible for removal, e.g.
+C<[eligible in 1.5]>. If the release listed is one that has already
+shipped, this feature may be removed in B<any> upcoming release, and
+you should no longer rely on it.
Whenever deprecated items are removed, information
regarding how to cope with the removal will be added to
@@ -63,6 +75,10 @@
L<https://trac.parrot.org/parrot/ticket/679>
+=item Method stdhandle in ParrotInterpreter [experimental]
+
+L<https://trac.parrot.org/parrot/ticket/264>
+
=back
=head1 Opcodes
@@ -362,6 +378,14 @@
L<https://trac.parrot.org/parrot/ticket/508>
+=item NCI::call_toolkit_init [eligible in 1.5]
+
+L<https://trac.parrot.org/parrot/ticket/753>
+
+=item Cross-HLL library loading [experimental]
+
+L<https://trac.parrot.org/parrot/ticket/754>
+
=back
=head1 Footnotes
@@ -374,6 +398,12 @@
Older tickets may be listed at L<RT|https://rt.perl.org/rt3>.
+=item 2
+
+For an item to be considered experimental, it can B<never> have shipped in
+a stable release without the C<[experimental]> tag; otherwise, it must be
+deprecated normally before removal or incompatible change.
+
=back
=cut
Modified: branches/pmc_pct/MANIFEST
==============================================================================
--- branches/pmc_pct/MANIFEST Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/MANIFEST Fri Jun 26 08:35:24 2009 (r39797)
@@ -1,7 +1,7 @@
# ex: set ro:
# $Id$
#
-# generated by tools/dev/mk_manifest_and_skip.pl Thu Jun 11 03:11:36 2009 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Fri Jun 26 08:26:35 2009 UT
#
# See below for documentation on the format of this file.
#
@@ -203,6 +203,7 @@
compilers/pmcc/src/emitter/pmc/default.pir [pmcc]
compilers/pmcc/src/emitter/pmc/default.pm [pmcc]
compilers/pmcc/src/nodes.pir [pmcc]
+compilers/pmcc/src/nodes.pm [pmcc]
compilers/pmcc/src/parser/actions.pm [pmcc]
compilers/pmcc/src/parser/grammar.pg [pmcc]
compilers/pmcc/t/01-parse.t [test]
@@ -479,26 +480,35 @@
config/inter/shlibs.pm []
config/inter/types.pm []
config/inter/yacc.pm []
-docs/book/README []doc
-docs/book/appa_glossary.pod []
-docs/book/appb_patch_submission.pod []
-docs/book/appc_command_line_options.pod []
-docs/book/appd_build_options.pod []
-docs/book/appe_source_code.pod []
-docs/book/ch01_introduction.pod []
-docs/book/ch02_getting_started.pod []
-docs/book/ch03_pir.pod []
-docs/book/ch04_compiler_tools.pod []
-docs/book/ch05_pge.pod []
-docs/book/ch06_nqp.pod []
-docs/book/ch07_dynpmcs.pod []
-docs/book/ch08_dynops.pod []
-docs/book/ch10_opcode_reference.pod []
-docs/book/ch11_directive_reference.pod []
-docs/book/ch12_operator_reference.pod []
+docs/book/draft/README []doc
+docs/book/draft/appa_glossary.pod []
+docs/book/draft/appb_patch_submission.pod []
+docs/book/draft/appc_command_line_options.pod []
+docs/book/draft/appd_build_options.pod []
+docs/book/draft/appe_source_code.pod []
+docs/book/draft/ch01_introduction.pod []
+docs/book/draft/ch02_getting_started.pod []
+docs/book/draft/ch03_pir.pod []
+docs/book/draft/ch04_compiler_tools.pod []
+docs/book/draft/ch05_pge.pod []
+docs/book/draft/ch06_nqp.pod []
+docs/book/draft/ch07_dynpmcs.pod []
+docs/book/draft/ch08_dynops.pod []
+docs/book/draft/ch10_opcode_reference.pod []
+docs/book/draft/ch11_directive_reference.pod []
+docs/book/draft/ch12_operator_reference.pod []
docs/book/draft/chXX_hlls.pod []
docs/book/draft/chXX_library.pod []
docs/book/draft/chXX_testing_and_debugging.pod []
+docs/book/pir/ch01_introduction.pod []
+docs/book/pir/ch02_getting_started.pod []
+docs/book/pir/ch03_basic_syntax.pod []
+docs/book/pir/ch04_variables.pod []
+docs/book/pir/ch05_control_structures.pod []
+docs/book/pir/ch06_subroutines.pod []
+docs/book/pir/ch07_objects.pod []
+docs/book/pir/ch08_io.pod []
+docs/book/pir/ch09_exceptions.pod []
docs/compiler_faq.pod [devel]doc
docs/configuration.pod []
docs/debug.pod [devel]doc
@@ -784,6 +794,7 @@
examples/nci/xlibtest.p6 [examples]
examples/nci/xlibtest.pir [examples]
examples/nci/xlibtest.rb [examples]
+examples/opengl/math.pir [examples]
examples/opengl/shapes.p6 [examples]
examples/opengl/shapes.pir [examples]
examples/opengl/static-triangle.p6 [examples]
@@ -1215,6 +1226,7 @@
runtime/parrot/library/CGI/QueryHash.pir [library]
runtime/parrot/library/Config/JSON.pir [library]
runtime/parrot/library/Crow.pir [library]
+runtime/parrot/library/Curses.pir [library]
runtime/parrot/library/Data/Dumper.pir [library]
runtime/parrot/library/Data/Dumper/Base.pir [library]
runtime/parrot/library/Data/Dumper/Default.pir [library]
@@ -1227,8 +1239,10 @@
runtime/parrot/library/MIME/Base64.pir [library]
runtime/parrot/library/Math/Rand.pir [library]
runtime/parrot/library/Math/Random/mt19937ar.pir [library]
+runtime/parrot/library/NCI/Utils.pir [library]
runtime/parrot/library/NCI/call_toolkit_init.pir [library]
runtime/parrot/library/OpenGL.pir [library]
+runtime/parrot/library/OpenGL/Math.pir [library]
runtime/parrot/library/P6object.pir [library]
runtime/parrot/library/PCT/README []doc
runtime/parrot/library/PGE/Dumper.pir [library]
@@ -1588,6 +1602,7 @@
t/codingstd/pod_todo.t [test]
t/codingstd/svn_id.t [test]
t/codingstd/tabs.t [test]
+t/codingstd/test_file_coverage.t [test]
t/codingstd/trailing_space.t [test]
t/compilers/imcc/imcpasm/cfg.t [test]
t/compilers/imcc/imcpasm/opt0.t [test]
@@ -1726,7 +1741,6 @@
t/distro/file_metadata.t [test]
t/distro/manifest.t [test]
t/distro/meta_yml.t [test]
-t/distro/test_file_coverage.t [test]
t/dynoplibs/myops.t [test]
t/dynpmc/dynlexpad.t [test]
t/dynpmc/foo.t [test]
@@ -1912,6 +1926,7 @@
t/pmc/float.t [test]
t/pmc/freeze.t [test]
t/pmc/globals.t [test]
+t/pmc/handle.t [test]
t/pmc/hash.t [test]
t/pmc/integer.t [test]
t/pmc/io.t [test]
Modified: branches/pmc_pct/MANIFEST.SKIP
==============================================================================
--- branches/pmc_pct/MANIFEST.SKIP Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/MANIFEST.SKIP Fri Jun 26 08:35:24 2009 (r39797)
@@ -1,6 +1,6 @@
# ex: set ro:
# $Id$
-# generated by tools/dev/mk_manifest_and_skip.pl Fri May 15 17:05:40 2009 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Thu Jun 25 20:34:12 2009 UT
#
# This file should contain a transcript of the svn:ignore properties
# of the directories in the Parrot subversion repository. (Needed for
@@ -578,6 +578,9 @@
# generated from svn:ignore of 'runtime/parrot/library/NCI/'
^runtime/parrot/library/NCI/.*\.pbc$
^runtime/parrot/library/NCI/.*\.pbc/
+# generated from svn:ignore of 'runtime/parrot/library/OpenGL/'
+^runtime/parrot/library/OpenGL/.*\.pbc$
+^runtime/parrot/library/OpenGL/.*\.pbc/
# generated from svn:ignore of 'runtime/parrot/library/PCT/'
^runtime/parrot/library/PCT/.*\.pbc$
^runtime/parrot/library/PCT/.*\.pbc/
@@ -825,6 +828,8 @@
^src/string/.*\.o/
^src/string/.*\.obj$
^src/string/.*\.obj/
+^src/string/.*\.str$
+^src/string/.*\.str/
^src/string/private_cstring\.h$
^src/string/private_cstring\.h/
# generated from svn:ignore of 'src/string/charset/'
Modified: branches/pmc_pct/MANIFEST.generated
==============================================================================
--- branches/pmc_pct/MANIFEST.generated Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/MANIFEST.generated Fri Jun 26 08:35:24 2009 (r39797)
@@ -2,10 +2,10 @@
# See tools/dev/install_files.pl for documentation on the
# format of this file.
# Please re-sort this file after *EVERY* modification
-blib/lib/libparrot.1.2.0.dylib [main]lib
+blib/lib/libparrot.1.3.0.dylib [main]lib
blib/lib/libparrot.a [main]lib
blib/lib/libparrot.dylib [main]lib
-blib/lib/libparrot.so.1.2.0 [main]lib
+blib/lib/libparrot.so.1.3.0 [main]lib
blib/lib/libparrot.so [main]lib
compilers/json/JSON/grammar.pbc [json]
compilers/json/JSON.pbc [json]
@@ -122,6 +122,7 @@
runtime/parrot/include/parrotlib.pbc [main]
runtime/parrot/include/pmctypes.pasm [main]
runtime/parrot/include/signal.pasm [main]
+runtime/parrot/include/socket.pasm [main]
runtime/parrot/include/stat.pasm [main]
runtime/parrot/include/stdio.pasm [main]
runtime/parrot/include/stringinfo.pasm [main]
@@ -213,7 +214,9 @@
src/pmc/hash.dump [devel]src
src/pmc/integer.dump [devel]src
src/pmc/multisub.dump [devel]src
+src/pmc/object.dump [devel]src
src/pmc/pmc_boolean.h [devel]include
+src/pmc/pmc_class.h [devel]include
src/pmc/pmc_continuation.h [devel]include
src/pmc/pmc_default.h [devel]include
src/pmc/pmc_fixedintegerarray.h [devel]include
@@ -225,11 +228,13 @@
src/pmc/pmc_object.h [devel]include
src/pmc/pmc_parrotlibrary.h [devel]include
src/pmc/pmc_resizablepmcarray.h [devel]include
+src/pmc/pmc_role.h [devel]include
src/pmc/pmc_scalar.h [devel]include
src/pmc/pmc_string.h [devel]include
src/pmc/pmc_sub.h [devel]include
src/pmc/pmc_undef.h [devel]include
src/pmc/resizablepmcarray.dump [devel]src
+src/pmc/role.dump [devel]src
src/pmc/scalar.dump [devel]src
src/pmc/string.dump [devel]src
src/pmc/sub.dump [devel]src
Modified: branches/pmc_pct/META.yml
==============================================================================
--- branches/pmc_pct/META.yml Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/META.yml Fri Jun 26 08:35:24 2009 (r39797)
@@ -4,7 +4,7 @@
# See http://module-build.sourceforge.net/META-spec-current.html for details.
---
name: parrot
-version: 1.2.0
+version: 1.3.0
author: parrot-dev at lists.parrot.org
abstract: a virtual machine designed for dynamic languages
license: artistic2
Modified: branches/pmc_pct/NEWS
==============================================================================
--- branches/pmc_pct/NEWS Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/NEWS Fri Jun 26 08:35:24 2009 (r39797)
@@ -2,8 +2,32 @@
New in 1.3.0
- Core
- + Optimization for parts of the IO system
- + Fix inheritance heirarchy of FileHandle and Socket PMC types
+ + Optimized parts of the IO system
+ + Fixed inheritance hierarchy of FileHandle and Socket PMC types
+ + Fixed leaks involving subroutines and Parrot_Context
+ + Cleaned up and refactored GC internals, including fixes and optimizations
+ + Optimized PMC class manipulations to use type numbers instead of string names
+ + Fixed problems involving hashval calculations in strings
+ + Removed unnecessary MULTI dispatches in built-in PMCs
+ + Fixed memory leaks involving PMCs that were not properly destroyed
+ + Fixed creation of PMCProxy PMCs in correct namespaces
+ + Added preliminary Pipe support
+ + Fixed cloning of Object PMCs
+ + Added root_new opcode
+ + Added initial versions of Packfile PMCs with read/write capabilities
+- Compilers
+ + Fixed several memory leaks in IMCC
+ + Updated PCT to use root_new opcode
+ + Added support for keyword "self" in NQP
+- Documentation
+ + Improved and expanded /docs/book
+ + Updated project documentation
+ + Defined 'experimental' status and procedures in DEPRECATED.pod
+- Miscellaneous
+ + Cleaned code and improved code-level documentation
+ + Various bugfixes, code cleanups, and coding standard fixes
+ + Added an experimental compiler library to help use PIR libraries from HLLs
+ + Updated OpenGL library and examples to support experimental HLL import
New in 1.2.0
- Core
Modified: branches/pmc_pct/PLATFORMS
==============================================================================
--- branches/pmc_pct/PLATFORMS Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/PLATFORMS Fri Jun 26 08:35:24 2009 (r39797)
@@ -39,6 +39,7 @@
dragonfly2.2.0-i386-gcc-4.1.2 4 Y Y - Y Y Y Y ? 20090427
freebsd-x86-gcc-4.2.1 4 Y Y Y ? ? Y Y Y 20090415
freebsd-amd64-gcc-4.2.1 8 Y - - ? ? Y Y Y 20090419
+linux-amd64-clang-r73854 8 ? ? = Y Y Y/4 Y/1 ? 20090622
linux-ppc-gcc3.4.5 Y Y Y ? ? Y Y ? 20080519
linux-s390x-gcc4.1.2 B4 ? - - Y Y Y Y/2 ? 20080908
linux-x86_64-gcc4.1.2 8 Y - - Y Y Y Y ? 20080220
@@ -93,6 +94,8 @@
--ccflags='-m64' --ldflags='-m64' --linkflags='-m64'
*2 http://rt.perl.org/rt3/Ticket/Display.html?id=60926
*3 failures in 'make examples_tests' (part of 'make fulltest')
+*4 compiles with --ccflags=-U__APPLE_CC__ --without-gmp
+ See http://lists.parrot.org/pipermail/parrot-dev/2009-June/002407.html
The following configurations are also working on x86/linux (and possibly
other platforms):
Modified: branches/pmc_pct/README
==============================================================================
--- branches/pmc_pct/README Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/README Fri Jun 26 08:35:24 2009 (r39797)
@@ -1,4 +1,4 @@
-This is Parrot, version 1.2.0
+This is Parrot, version 1.3.0
------------------------------
Parrot is Copyright (C) 2001-2009, Parrot Foundation.
Modified: branches/pmc_pct/VERSION
==============================================================================
--- branches/pmc_pct/VERSION Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/VERSION Fri Jun 26 08:35:24 2009 (r39797)
@@ -1 +1 @@
-1.2.0
+1.3.0
Modified: branches/pmc_pct/compilers/imcc/imc.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/imc.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/imc.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -143,6 +143,11 @@
clear_globals(interp);
mem_sys_free(IMCC_INFO(interp)->ghash.data);
IMCC_INFO(interp)->ghash.data = NULL;
+
+ if (IMCC_INFO(interp)->state) {
+ free(IMCC_INFO(interp)->state->file);
+ IMCC_INFO(interp)->state->file = NULL;
+ }
}
Modified: branches/pmc_pct/compilers/imcc/imc.h
==============================================================================
--- branches/pmc_pct/compilers/imcc/imc.h Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/imc.h Fri Jun 26 08:35:24 2009 (r39797)
@@ -527,7 +527,6 @@
Interp *interp;
char *file;
FILE *handle;
- int file_needs_free; /* is *file malloced? */
int line;
int pasm_file; /* pasm_file mode of this frame */
};
Modified: branches/pmc_pct/compilers/imcc/imcc.l
==============================================================================
--- branches/pmc_pct/compilers/imcc/imcc.l Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/imcc.l Fri Jun 26 08:35:24 2009 (r39797)
@@ -96,7 +96,7 @@
#define DUP_AND_RET(valp, token) \
do { \
- if (valp) (valp)->s = str_dup(yytext); \
+ if (valp) (valp)->s = mem_sys_strdup(yytext); \
return (token); \
} while (0)
@@ -104,7 +104,7 @@
do { \
if (valp) { \
mem_sys_free((valp)->s); \
- (valp)->s = str_dup(yytext); \
+ (valp)->s = mem_sys_strdup(yytext); \
return (token); \
} \
} while (0)
@@ -171,7 +171,7 @@
}
<heredoc1>.*{EOL} {
- IMCC_INFO(interp)->frames->heredoc_rest = str_dup(yytext);
+ IMCC_INFO(interp)->frames->heredoc_rest = mem_sys_strdup(yytext);
BEGIN(heredoc2);
}
@@ -231,9 +231,8 @@
yy_pop_state(yyscanner);
yy_push_state(cmt3, yyscanner);
- IMCC_INFO(interp)->frames->s.file = str_dup(yytext);
- IMCC_INFO(interp)->frames->s.file_needs_free = 1;
- IMCC_INFO(interp)->cur_unit->file = str_dup(yytext);
+ IMCC_INFO(interp)->frames->s.file = mem_sys_strdup(yytext);
+ IMCC_INFO(interp)->cur_unit->file = mem_sys_strdup(yytext);
return FILECOMMENT;
}
@@ -460,7 +459,7 @@
if (c != STRINGC)
return c;
- /* STRINGCs have a str_dup()ed valp->s */
+ /* STRINGCs have a mem_sys_strdup()ed valp->s */
mem_sys_free(valp->s);
YYCHOP();
include_file(interp, yytext + 1, yyscanner);
@@ -517,7 +516,7 @@
YYCHOP();
if (valp)
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
return LABEL;
}
@@ -540,7 +539,7 @@
<*>{OCT} DUP_AND_RET(valp, INTC);
<*>{BIGINT} {
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
/* trailing 'L' */
valp->s[strlen(valp->s) - 1] = '\0';
@@ -550,7 +549,7 @@
}
<*>{STRINGCONSTANT} {
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
/* RT #42382 delete quotes, -> emit, pbc */
return STRINGC;
@@ -563,7 +562,7 @@
off newline and quote. */
if (IMCC_INFO(interp)->frames->heredoc_rest)
IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR, "nested heredoc not supported");
- IMCC_INFO(interp)->heredoc_end = str_dup(yytext + 3);
+ IMCC_INFO(interp)->heredoc_end = mem_sys_strdup(yytext + 3);
IMCC_INFO(interp)->heredoc_end[strlen(IMCC_INFO(interp)->heredoc_end) - 1] = 0;
if (!strlen(IMCC_INFO(interp)->heredoc_end))
@@ -586,7 +585,7 @@
<*>{UNICODE} {
/* charset:"..." */
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
/* this is actually not unicode but a string with a charset */
return USTRINGC;
@@ -635,7 +634,7 @@
"'%s' is only a valid register name in PASM mode", yytext);
if (valp)
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
return REG;
}
@@ -664,7 +663,7 @@
}
}
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
return (!pesky_global__is_def && is_op(interp, valp->s) ? PARROT_OP : IDENTIFIER);
}
@@ -788,13 +787,8 @@
if (IMCC_INFO(interp)->frames) {
tmp->s.pasm_file = IMCC_INFO(interp)->frames->s.pasm_file;
-
- if (IMCC_INFO(interp)->frames->s.file_needs_free)
- tmp->s.file = str_dup(IMCC_INFO(interp)->frames->s.file);
- else
- tmp->s.file = IMCC_INFO(interp)->frames->s.file;
-
- tmp->s.file_needs_free = IMCC_INFO(interp)->frames->s.file_needs_free;
+ if (IMCC_INFO(interp)->frames->s.file)
+ tmp->s.file = mem_sys_strdup(IMCC_INFO(interp)->frames->s.file);
}
tmp->s.interp = interp;
@@ -833,13 +827,7 @@
} else
ret = frame->s.line;
- /* RT #42383 if frame->s.file was allocated free it */
- /* Update: This should do it! */
- if (frame->s.file_needs_free) {
- DECL_CONST_CAST;
- mem_sys_free(PARROT_const_cast(char *,frame->s.file));
- frame->s.file_needs_free = 0;
- }
+ mem_sys_free(frame->s.file);
mem_sys_free(frame);
if (buffer != NULL)
@@ -866,7 +854,7 @@
if (*p == '\0')
break;
- /* free any str_dup()ed strings */
+ /* free any mem_sys_strdup()ed strings */
if (yytext)
mem_sys_free(valp->s);
} while (*p != '\0');
@@ -924,7 +912,7 @@
{
YYSTYPE val;
size_t len = 0;
- char *current = str_dup("");
+ char *current = mem_sys_strdup("");
yyguts_t *yyg = (yyguts_t *)yyscanner;
int c = yylex_skip(&val, interp, " \n", yyscanner);
@@ -946,7 +934,7 @@
MAX_PARAM, macro_name);
params->name[params->num_param++] = current;
- current = str_dup("");
+ current = mem_sys_strdup("");
len = 0;
if (val.s)
@@ -1121,7 +1109,7 @@
else
memset(&m->params, 0, sizeof (params_t));
- m->expansion = str_dup(expansion);
+ m->expansion = mem_sys_strdup(expansion);
m->line = start_line;
}
@@ -1162,12 +1150,10 @@
/* remember macro name for error reporting
* first free any filename allocated in new_frame() */
- if (frame->s.file && frame->s.file_needs_free)
+ if (frame->s.file)
mem_sys_free(frame->s.file);
- /* RT #42384 check that all the .file text is malloced / freed */
- frame->s.file = str_dup(name);
- frame->s.file_needs_free = 1;
+ frame->s.file = mem_sys_strdup(name);
/* whitespace can be safely ignored */
do {
@@ -1196,7 +1182,7 @@
BEGIN(start_cond);
if (frame->expansion.num_param == 0 && m->params.num_param == 1) {
- frame->expansion.name[0] = str_dup("");
+ frame->expansion.name[0] = mem_sys_strdup("");
frame->expansion.num_param = 1;
}
@@ -1215,7 +1201,7 @@
const char * const s = find_macro_param(interp, current + 1);
if (s) {
- frame->expansion.name[i] = str_dup(s);
+ frame->expansion.name[i] = mem_sys_strdup(s);
mem_sys_free(current);
}
@@ -1258,8 +1244,7 @@
IMCC_fataly(interp, EXCEPTION_EXTERNAL_ERROR, strerror(errno));
mem_sys_free(s);
- frame->s.file = file_name;
- frame->s.file_needs_free = 0;
+ frame->s.file = mem_sys_strdup(file_name);
frame->s.handle = file;
ext = strrchr(file_name, '.');
@@ -1432,17 +1417,16 @@
set_filename(PARROT_INTERP, char * const filename)
{
IMCC_INFO(interp)->frames->s.file = filename;
- IMCC_INFO(interp)->frames->s.file_needs_free = 1;
/* in case .line is used outside a .sub, then this
* can't be done; hence the check.
- * The str_dup() is done, as the original #line implementation
+ * The mem_sys_strdup() is done, as the original #line implementation
* duplicated the string twice as well; one for the
* frames->s.file and one for cur_unit->file.
- * During the parse, the STRINGC is already str_dup()ed once.
+ * During the parse, the STRINGC is already mem_sys_strdup()ed once.
*/
if (IMCC_INFO(interp)->cur_unit)
- IMCC_INFO(interp)->cur_unit->file = str_dup(filename);
+ IMCC_INFO(interp)->cur_unit->file = mem_sys_strdup(filename);
}
/* Functions to set and get yyin, as we can't decorate it for export
Modified: branches/pmc_pct/compilers/imcc/imcc.y
==============================================================================
--- branches/pmc_pct/compilers/imcc/imcc.y Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/imcc.y Fri Jun 26 08:35:24 2009 (r39797)
@@ -42,45 +42,49 @@
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
-static void add_pcc_named_arg(PARROT_INTERP,
+static void add_pcc_named_arg(
ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
- __attribute__nonnull__(4)
- FUNC_MODIFIES(*cur_call);
+ FUNC_MODIFIES(*cur_call)
+ FUNC_MODIFIES(*name)
+ FUNC_MODIFIES(*value);
-static void add_pcc_named_arg_var(PARROT_INTERP,
+static void add_pcc_named_arg_var(
ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
- __attribute__nonnull__(4)
- FUNC_MODIFIES(*cur_call);
+ FUNC_MODIFIES(*cur_call)
+ FUNC_MODIFIES(*name)
+ FUNC_MODIFIES(*value);
-static void add_pcc_named_param(PARROT_INTERP,
+static void add_pcc_named_param(
ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
- __attribute__nonnull__(4)
- FUNC_MODIFIES(*cur_call);
+ FUNC_MODIFIES(*cur_call)
+ FUNC_MODIFIES(*name)
+ FUNC_MODIFIES(*value);
-static void add_pcc_named_result(PARROT_INTERP,
+static void add_pcc_named_result(
ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
- __attribute__nonnull__(4)
- FUNC_MODIFIES(*cur_call);
+ FUNC_MODIFIES(*cur_call)
+ FUNC_MODIFIES(*name)
+ FUNC_MODIFIES(*value);
static void add_pcc_named_return(PARROT_INTERP,
ARGMOD(SymReg *cur_call),
@@ -239,23 +243,19 @@
FUNC_MODIFIES(*name);
#define ASSERT_ARGS_add_pcc_named_arg __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp) \
- || PARROT_ASSERT_ARG(cur_call) \
+ PARROT_ASSERT_ARG(cur_call) \
|| PARROT_ASSERT_ARG(name) \
|| PARROT_ASSERT_ARG(value)
#define ASSERT_ARGS_add_pcc_named_arg_var __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp) \
- || PARROT_ASSERT_ARG(cur_call) \
+ PARROT_ASSERT_ARG(cur_call) \
|| PARROT_ASSERT_ARG(name) \
|| PARROT_ASSERT_ARG(value)
#define ASSERT_ARGS_add_pcc_named_param __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp) \
- || PARROT_ASSERT_ARG(cur_call) \
+ PARROT_ASSERT_ARG(cur_call) \
|| PARROT_ASSERT_ARG(name) \
|| PARROT_ASSERT_ARG(value)
#define ASSERT_ARGS_add_pcc_named_result __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp) \
- || PARROT_ASSERT_ARG(cur_call) \
+ PARROT_ASSERT_ARG(cur_call) \
|| PARROT_ASSERT_ARG(name) \
|| PARROT_ASSERT_ARG(value)
#define ASSERT_ARGS_add_pcc_named_return __attribute__unused__ int _ASSERT_ARGS_CHECK = \
@@ -437,11 +437,11 @@
r[0] = left;
if (ascii) {
/* strip delimiters */
- name = str_dup(constant + 1);
+ name = mem_sys_strdup(constant + 1);
name[strlen(name) - 1] = 0;
}
else {
- name = str_dup(constant);
+ name = mem_sys_strdup(constant);
}
switch (type_enum) {
@@ -487,7 +487,7 @@
SymReg *r[3];
char *const_name;
const int ascii = (*constant == '\'' || *constant == '"');
- char *unquoted_name = str_dup(name + 1);
+ char *unquoted_name = mem_sys_strdup(name + 1);
size_t name_length = strlen(unquoted_name) - 1;
unquoted_name[name_length] = 0;
@@ -504,11 +504,11 @@
r[0] = left;
if (ascii) {
/* strip delimiters */
- const_name = str_dup(constant + 1);
+ const_name = mem_sys_strdup(constant + 1);
const_name[strlen(const_name) - 1] = 0;
}
else {
- const_name = str_dup(constant);
+ const_name = mem_sys_strdup(constant);
}
if ((strncmp(unquoted_name, "Sub", name_length) == 0)
@@ -759,7 +759,7 @@
ASSERT_ARGS(mk_sub_address_fromc)
/* name is a quoted sub name */
SymReg *r;
- char *name_copy = str_dup(name + 1);
+ char *name_copy = mem_sys_strdup(name + 1);
name_copy[strlen(name_copy) - 1] = 0;
r = mk_sub_address(interp, name_copy);
@@ -875,17 +875,17 @@
/*
-=item C<static void add_pcc_named_arg(PARROT_INTERP, SymReg *cur_call, SymReg
-*name, SymReg *value)>
+=item C<static void add_pcc_named_arg(SymReg *cur_call, SymReg *name, SymReg
+*value)>
=cut
*/
static void
-add_pcc_named_arg(PARROT_INTERP, ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+add_pcc_named_arg(ARGMOD(SymReg *cur_call),
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
{
ASSERT_ARGS(add_pcc_named_arg)
name->type |= VT_NAMED;
@@ -896,16 +896,16 @@
/*
-=item C<static void add_pcc_named_arg_var(PARROT_INTERP, SymReg *cur_call,
-SymReg *name, SymReg *value)>
+=item C<static void add_pcc_named_arg_var(SymReg *cur_call, SymReg *name, SymReg
+*value)>
=cut
*/
static void
-add_pcc_named_arg_var(PARROT_INTERP, ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name), ARGIN(SymReg *value))
+add_pcc_named_arg_var(ARGMOD(SymReg *cur_call),
+ ARGMOD(SymReg *name), ARGMOD(SymReg *value))
{
ASSERT_ARGS(add_pcc_named_arg_var)
name->type |= VT_NAMED;
@@ -915,17 +915,17 @@
/*
-=item C<static void add_pcc_named_result(PARROT_INTERP, SymReg *cur_call, SymReg
-*name, SymReg *value)>
+=item C<static void add_pcc_named_result(SymReg *cur_call, SymReg *name, SymReg
+*value)>
=cut
*/
static void
-add_pcc_named_result(PARROT_INTERP, ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+add_pcc_named_result(ARGMOD(SymReg *cur_call),
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
{
ASSERT_ARGS(add_pcc_named_result)
name->type |= VT_NAMED;
@@ -936,17 +936,17 @@
/*
-=item C<static void add_pcc_named_param(PARROT_INTERP, SymReg *cur_call, SymReg
-*name, SymReg *value)>
+=item C<static void add_pcc_named_param(SymReg *cur_call, SymReg *name, SymReg
+*value)>
=cut
*/
static void
-add_pcc_named_param(PARROT_INTERP, ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+add_pcc_named_param(ARGMOD(SymReg *cur_call),
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
{
ASSERT_ARGS(add_pcc_named_param)
name->type |= VT_NAMED;
@@ -1348,7 +1348,7 @@
{
IMCC_INFO(interp)->cur_call->pcc_sub->pragma = $5;
if (!IMCC_INFO(interp)->cur_unit->instructions->symregs[0]->subid) {
- IMCC_INFO(interp)->cur_unit->instructions->symregs[0]->subid = str_dup(
+ IMCC_INFO(interp)->cur_unit->instructions->symregs[0]->subid = mem_sys_strdup(
IMCC_INFO(interp)->cur_unit->instructions->symregs[0]->name);
}
}
@@ -1362,7 +1362,7 @@
| sub_params sub_param '\n'
{
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_param(interp, IMCC_INFO(interp)->cur_call,
+ add_pcc_named_param(IMCC_INFO(interp)->cur_call,
IMCC_INFO(interp)->adv_named_id, $2);
IMCC_INFO(interp)->adv_named_id = NULL;
}
@@ -1657,7 +1657,7 @@
RESULT target paramtype_list { $$ = $2; $$->type |= $3; }
| LOCAL { pesky_global__is_def=1; } type id_list_id
{
- IdList *l = $4;
+ IdList * const l = $4;
SymReg *ignored;
if (l->unique_reg)
ignored = mk_ident_ur(interp, l->id, $3);
@@ -1968,7 +1968,7 @@
classname:
IDENTIFIER
{
- /* there'd normally be a str_dup() here, but the lexer already
+ /* there'd normally be a mem_sys_strdup() here, but the lexer already
* copied the string, so it's safe to use directly */
if ((IMCC_INFO(interp)->cur_pmc_type = pmc_type(interp,
Parrot_str_new(interp, $1, 0))) <= 0) {
@@ -2113,7 +2113,7 @@
| target DOT sub_label_op
{
/* disallow bareword method names; SREG name constants are fine */
- char *name = $3->name;
+ const char * const name = $3->name;
if (!($3->type & VTREG)) {
if (*name != '\'' || *name != '\"')
IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
@@ -2155,7 +2155,7 @@
{
$$ = 0;
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_arg(interp, IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, $3);
+ add_pcc_named_arg(IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, $3);
IMCC_INFO(interp)->adv_named_id = NULL;
}
else
@@ -2165,7 +2165,7 @@
{
$$ = 0;
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_arg(interp, IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, $1);
+ add_pcc_named_arg(IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, $1);
IMCC_INFO(interp)->adv_named_id = NULL;
}
else
@@ -2174,19 +2174,19 @@
| arglist COMMA STRINGC ADV_ARROW var
{
$$ = 0;
- add_pcc_named_arg(interp, IMCC_INFO(interp)->cur_call,
+ add_pcc_named_arg(IMCC_INFO(interp)->cur_call,
mk_const(interp, $3, 'S'), $5);
mem_sys_free($3);
}
| var ADV_ARROW var
{
$$ = 0;
- add_pcc_named_arg_var(interp, IMCC_INFO(interp)->cur_call, $1, $3);
+ add_pcc_named_arg_var(IMCC_INFO(interp)->cur_call, $1, $3);
}
| STRINGC ADV_ARROW var
{
$$ = 0;
- add_pcc_named_arg(interp, IMCC_INFO(interp)->cur_call,
+ add_pcc_named_arg(IMCC_INFO(interp)->cur_call,
mk_const(interp, $1, 'S'), $3);
mem_sys_free($1);
}
@@ -2219,7 +2219,7 @@
{
$$ = 0;
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_result(interp, IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, $3);
+ add_pcc_named_result(IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, $3);
IMCC_INFO(interp)->adv_named_id = NULL;
}
else
@@ -2227,7 +2227,7 @@
}
| targetlist COMMA STRINGC ADV_ARROW target
{
- add_pcc_named_result(interp, IMCC_INFO(interp)->cur_call,
+ add_pcc_named_result(IMCC_INFO(interp)->cur_call,
mk_const(interp, $3, 'S'), $5);
mem_sys_free($3);
}
@@ -2235,7 +2235,7 @@
{
$$ = 0;
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_result(interp, IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, $1);
+ add_pcc_named_result(IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, $1);
IMCC_INFO(interp)->adv_named_id = NULL;
}
else
@@ -2243,7 +2243,7 @@
}
| STRINGC ADV_ARROW target
{
- add_pcc_named_result(interp, IMCC_INFO(interp)->cur_call, mk_const(interp, $1, 'S'), $3);
+ add_pcc_named_result(IMCC_INFO(interp)->cur_call, mk_const(interp, $1, 'S'), $3);
mem_sys_free($1);
}
| /* empty */ { $$ = 0; }
Modified: branches/pmc_pct/compilers/imcc/imclexer.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/imclexer.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/imclexer.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -2464,7 +2464,7 @@
#define DUP_AND_RET(valp, token) \
do { \
- if (valp) (valp)->s = str_dup(yytext); \
+ if (valp) (valp)->s = mem_sys_strdup(yytext); \
return (token); \
} while (0)
@@ -2472,7 +2472,7 @@
do { \
if (valp) { \
mem_sys_free((valp)->s); \
- (valp)->s = str_dup(yytext); \
+ (valp)->s = mem_sys_strdup(yytext); \
return (token); \
} \
} while (0)
@@ -2836,7 +2836,7 @@
YY_RULE_SETUP
#line 173 "compilers/imcc/imcc.l"
{
- IMCC_INFO(interp)->frames->heredoc_rest = str_dup(yytext);
+ IMCC_INFO(interp)->frames->heredoc_rest = mem_sys_strdup(yytext);
BEGIN(heredoc2);
}
YY_BREAK
@@ -2907,16 +2907,15 @@
yy_pop_state(yyscanner);
yy_push_state(cmt3, yyscanner);
- IMCC_INFO(interp)->frames->s.file = str_dup(yytext);
- IMCC_INFO(interp)->frames->s.file_needs_free = 1;
- IMCC_INFO(interp)->cur_unit->file = str_dup(yytext);
+ IMCC_INFO(interp)->frames->s.file = mem_sys_strdup(yytext);
+ IMCC_INFO(interp)->cur_unit->file = mem_sys_strdup(yytext);
return FILECOMMENT;
}
YY_BREAK
case 5:
YY_RULE_SETUP
-#line 241 "compilers/imcc/imcc.l"
+#line 240 "compilers/imcc/imcc.l"
{
yy_pop_state(yyscanner);
yy_push_state(cmt4, yyscanner);
@@ -2924,17 +2923,17 @@
YY_BREAK
case 6:
YY_RULE_SETUP
-#line 246 "compilers/imcc/imcc.l"
+#line 245 "compilers/imcc/imcc.l"
{ yy_push_state(cmt2, yyscanner); }
YY_BREAK
case 7:
YY_RULE_SETUP
-#line 248 "compilers/imcc/imcc.l"
+#line 247 "compilers/imcc/imcc.l"
{ yy_push_state(cmt1, yyscanner); }
YY_BREAK
case 8:
YY_RULE_SETUP
-#line 250 "compilers/imcc/imcc.l"
+#line 249 "compilers/imcc/imcc.l"
{
IMCC_INFO(interp)->line = atoi(yytext);
yy_pop_state(yyscanner);
@@ -2945,7 +2944,7 @@
case 9:
/* rule 9 can match eol */
YY_RULE_SETUP
-#line 257 "compilers/imcc/imcc.l"
+#line 256 "compilers/imcc/imcc.l"
{
yy_pop_state(yyscanner);
IMCC_INFO(interp)->line++;
@@ -2954,7 +2953,7 @@
case 10:
/* rule 10 can match eol */
YY_RULE_SETUP
-#line 262 "compilers/imcc/imcc.l"
+#line 261 "compilers/imcc/imcc.l"
{
if (IMCC_INFO(interp)->expect_pasm == 2)
BEGIN(INITIAL);
@@ -2967,7 +2966,7 @@
YY_BREAK
case 11:
YY_RULE_SETUP
-#line 272 "compilers/imcc/imcc.l"
+#line 271 "compilers/imcc/imcc.l"
{
yy_push_state(cmt5, yyscanner);
}
@@ -2975,7 +2974,7 @@
case 12:
/* rule 12 can match eol */
YY_RULE_SETUP
-#line 276 "compilers/imcc/imcc.l"
+#line 275 "compilers/imcc/imcc.l"
{
if (IMCC_INFO(interp)->expect_pasm == 2)
BEGIN(INITIAL);
@@ -2991,7 +2990,7 @@
case 13:
/* rule 13 can match eol */
YY_RULE_SETUP
-#line 289 "compilers/imcc/imcc.l"
+#line 288 "compilers/imcc/imcc.l"
{
/* this is a stand-alone =cut, but we're
* not in POD mode, so just ignore.
@@ -3000,7 +2999,7 @@
YY_BREAK
case 14:
YY_RULE_SETUP
-#line 295 "compilers/imcc/imcc.l"
+#line 294 "compilers/imcc/imcc.l"
{
IMCC_INFO(interp)->in_pod = 1;
yy_push_state(pod, yyscanner);
@@ -3009,7 +3008,7 @@
case 15:
/* rule 15 can match eol */
YY_RULE_SETUP
-#line 300 "compilers/imcc/imcc.l"
+#line 299 "compilers/imcc/imcc.l"
{
IMCC_INFO(interp)->in_pod = 0;
yy_pop_state(yyscanner);
@@ -3018,473 +3017,473 @@
YY_BREAK
case 16:
YY_RULE_SETUP
-#line 306 "compilers/imcc/imcc.l"
+#line 305 "compilers/imcc/imcc.l"
{ /*ignore*/ }
YY_BREAK
case 17:
/* rule 17 can match eol */
YY_RULE_SETUP
-#line 308 "compilers/imcc/imcc.l"
+#line 307 "compilers/imcc/imcc.l"
{ IMCC_INFO(interp)->line++; }
YY_BREAK
case 18:
YY_RULE_SETUP
-#line 310 "compilers/imcc/imcc.l"
+#line 309 "compilers/imcc/imcc.l"
return TK_LINE;
YY_BREAK
case 19:
YY_RULE_SETUP
-#line 311 "compilers/imcc/imcc.l"
+#line 310 "compilers/imcc/imcc.l"
return TK_FILE;
YY_BREAK
case 20:
YY_RULE_SETUP
-#line 312 "compilers/imcc/imcc.l"
+#line 311 "compilers/imcc/imcc.l"
return ANNOTATE;
YY_BREAK
case 21:
YY_RULE_SETUP
-#line 313 "compilers/imcc/imcc.l"
+#line 312 "compilers/imcc/imcc.l"
return LEXICAL;
YY_BREAK
case 22:
YY_RULE_SETUP
-#line 314 "compilers/imcc/imcc.l"
+#line 313 "compilers/imcc/imcc.l"
return ARG;
YY_BREAK
case 23:
YY_RULE_SETUP
-#line 315 "compilers/imcc/imcc.l"
+#line 314 "compilers/imcc/imcc.l"
return SUB;
YY_BREAK
case 24:
YY_RULE_SETUP
-#line 316 "compilers/imcc/imcc.l"
+#line 315 "compilers/imcc/imcc.l"
return ESUB;
YY_BREAK
case 25:
YY_RULE_SETUP
-#line 317 "compilers/imcc/imcc.l"
+#line 316 "compilers/imcc/imcc.l"
return PCC_BEGIN;
YY_BREAK
case 26:
YY_RULE_SETUP
-#line 318 "compilers/imcc/imcc.l"
+#line 317 "compilers/imcc/imcc.l"
return PCC_END;
YY_BREAK
case 27:
YY_RULE_SETUP
-#line 319 "compilers/imcc/imcc.l"
+#line 318 "compilers/imcc/imcc.l"
return PCC_CALL;
YY_BREAK
case 28:
YY_RULE_SETUP
-#line 320 "compilers/imcc/imcc.l"
+#line 319 "compilers/imcc/imcc.l"
return NCI_CALL;
YY_BREAK
case 29:
YY_RULE_SETUP
-#line 321 "compilers/imcc/imcc.l"
+#line 320 "compilers/imcc/imcc.l"
return METH_CALL;
YY_BREAK
case 30:
YY_RULE_SETUP
-#line 322 "compilers/imcc/imcc.l"
+#line 321 "compilers/imcc/imcc.l"
return INVOCANT;
YY_BREAK
case 31:
YY_RULE_SETUP
-#line 323 "compilers/imcc/imcc.l"
+#line 322 "compilers/imcc/imcc.l"
return PCC_SUB;
YY_BREAK
case 32:
YY_RULE_SETUP
-#line 324 "compilers/imcc/imcc.l"
+#line 323 "compilers/imcc/imcc.l"
return PCC_BEGIN_RETURN;
YY_BREAK
case 33:
YY_RULE_SETUP
-#line 325 "compilers/imcc/imcc.l"
+#line 324 "compilers/imcc/imcc.l"
return PCC_END_RETURN;
YY_BREAK
case 34:
YY_RULE_SETUP
-#line 326 "compilers/imcc/imcc.l"
+#line 325 "compilers/imcc/imcc.l"
return PCC_BEGIN_YIELD;
YY_BREAK
case 35:
YY_RULE_SETUP
-#line 327 "compilers/imcc/imcc.l"
+#line 326 "compilers/imcc/imcc.l"
return PCC_END_YIELD;
YY_BREAK
case 36:
YY_RULE_SETUP
-#line 329 "compilers/imcc/imcc.l"
+#line 328 "compilers/imcc/imcc.l"
return METHOD;
YY_BREAK
case 37:
YY_RULE_SETUP
-#line 330 "compilers/imcc/imcc.l"
+#line 329 "compilers/imcc/imcc.l"
return MULTI;
YY_BREAK
case 38:
YY_RULE_SETUP
-#line 331 "compilers/imcc/imcc.l"
+#line 330 "compilers/imcc/imcc.l"
return MAIN;
YY_BREAK
case 39:
YY_RULE_SETUP
-#line 332 "compilers/imcc/imcc.l"
+#line 331 "compilers/imcc/imcc.l"
return LOAD;
YY_BREAK
case 40:
YY_RULE_SETUP
-#line 333 "compilers/imcc/imcc.l"
+#line 332 "compilers/imcc/imcc.l"
return INIT;
YY_BREAK
case 41:
YY_RULE_SETUP
-#line 334 "compilers/imcc/imcc.l"
+#line 333 "compilers/imcc/imcc.l"
return IMMEDIATE;
YY_BREAK
case 42:
YY_RULE_SETUP
-#line 335 "compilers/imcc/imcc.l"
+#line 334 "compilers/imcc/imcc.l"
return POSTCOMP;
YY_BREAK
case 43:
YY_RULE_SETUP
-#line 336 "compilers/imcc/imcc.l"
+#line 335 "compilers/imcc/imcc.l"
return ANON;
YY_BREAK
case 44:
YY_RULE_SETUP
-#line 337 "compilers/imcc/imcc.l"
+#line 336 "compilers/imcc/imcc.l"
return OUTER;
YY_BREAK
case 45:
YY_RULE_SETUP
-#line 338 "compilers/imcc/imcc.l"
+#line 337 "compilers/imcc/imcc.l"
return NEED_LEX;
YY_BREAK
case 46:
YY_RULE_SETUP
-#line 339 "compilers/imcc/imcc.l"
+#line 338 "compilers/imcc/imcc.l"
return VTABLE_METHOD;
YY_BREAK
case 47:
YY_RULE_SETUP
-#line 340 "compilers/imcc/imcc.l"
+#line 339 "compilers/imcc/imcc.l"
return NS_ENTRY;
YY_BREAK
case 48:
YY_RULE_SETUP
-#line 341 "compilers/imcc/imcc.l"
+#line 340 "compilers/imcc/imcc.l"
return UNIQUE_REG;
YY_BREAK
case 49:
YY_RULE_SETUP
-#line 342 "compilers/imcc/imcc.l"
+#line 341 "compilers/imcc/imcc.l"
return SUB_INSTANCE_OF;
YY_BREAK
case 50:
YY_RULE_SETUP
-#line 343 "compilers/imcc/imcc.l"
+#line 342 "compilers/imcc/imcc.l"
return SUBID;
YY_BREAK
case 51:
YY_RULE_SETUP
-#line 345 "compilers/imcc/imcc.l"
+#line 344 "compilers/imcc/imcc.l"
return RESULT;
YY_BREAK
case 52:
YY_RULE_SETUP
-#line 346 "compilers/imcc/imcc.l"
+#line 345 "compilers/imcc/imcc.l"
return GET_RESULTS;
YY_BREAK
case 53:
YY_RULE_SETUP
-#line 347 "compilers/imcc/imcc.l"
+#line 346 "compilers/imcc/imcc.l"
return YIELDT;
YY_BREAK
case 54:
YY_RULE_SETUP
-#line 348 "compilers/imcc/imcc.l"
+#line 347 "compilers/imcc/imcc.l"
return SET_YIELD;
YY_BREAK
case 55:
YY_RULE_SETUP
-#line 349 "compilers/imcc/imcc.l"
+#line 348 "compilers/imcc/imcc.l"
return RETURN;
YY_BREAK
case 56:
YY_RULE_SETUP
-#line 350 "compilers/imcc/imcc.l"
+#line 349 "compilers/imcc/imcc.l"
return SET_RETURN;
YY_BREAK
case 57:
YY_RULE_SETUP
-#line 351 "compilers/imcc/imcc.l"
+#line 350 "compilers/imcc/imcc.l"
return TAILCALL;
YY_BREAK
case 58:
YY_RULE_SETUP
-#line 352 "compilers/imcc/imcc.l"
+#line 351 "compilers/imcc/imcc.l"
return LOADLIB;
YY_BREAK
case 59:
YY_RULE_SETUP
-#line 354 "compilers/imcc/imcc.l"
+#line 353 "compilers/imcc/imcc.l"
return ADV_FLAT;
YY_BREAK
case 60:
YY_RULE_SETUP
-#line 355 "compilers/imcc/imcc.l"
+#line 354 "compilers/imcc/imcc.l"
return ADV_SLURPY;
YY_BREAK
case 61:
YY_RULE_SETUP
-#line 356 "compilers/imcc/imcc.l"
+#line 355 "compilers/imcc/imcc.l"
return ADV_OPTIONAL;
YY_BREAK
case 62:
YY_RULE_SETUP
-#line 357 "compilers/imcc/imcc.l"
+#line 356 "compilers/imcc/imcc.l"
return ADV_OPT_FLAG;
YY_BREAK
case 63:
YY_RULE_SETUP
-#line 358 "compilers/imcc/imcc.l"
+#line 357 "compilers/imcc/imcc.l"
return ADV_NAMED;
YY_BREAK
case 64:
YY_RULE_SETUP
-#line 359 "compilers/imcc/imcc.l"
+#line 358 "compilers/imcc/imcc.l"
return ADV_ARROW;
YY_BREAK
case 65:
YY_RULE_SETUP
-#line 360 "compilers/imcc/imcc.l"
+#line 359 "compilers/imcc/imcc.l"
return ADV_INVOCANT;
YY_BREAK
case 66:
YY_RULE_SETUP
-#line 362 "compilers/imcc/imcc.l"
+#line 361 "compilers/imcc/imcc.l"
return NAMESPACE;
YY_BREAK
case 67:
YY_RULE_SETUP
-#line 363 "compilers/imcc/imcc.l"
+#line 362 "compilers/imcc/imcc.l"
return HLL;
YY_BREAK
case 68:
YY_RULE_SETUP
-#line 365 "compilers/imcc/imcc.l"
+#line 364 "compilers/imcc/imcc.l"
return LOCAL;
YY_BREAK
case 69:
YY_RULE_SETUP
-#line 366 "compilers/imcc/imcc.l"
+#line 365 "compilers/imcc/imcc.l"
return CONST;
YY_BREAK
case 70:
YY_RULE_SETUP
-#line 367 "compilers/imcc/imcc.l"
+#line 366 "compilers/imcc/imcc.l"
return GLOBAL_CONST;
YY_BREAK
case 71:
YY_RULE_SETUP
-#line 368 "compilers/imcc/imcc.l"
+#line 367 "compilers/imcc/imcc.l"
return PARAM;
YY_BREAK
case 72:
YY_RULE_SETUP
-#line 369 "compilers/imcc/imcc.l"
+#line 368 "compilers/imcc/imcc.l"
return GOTO;
YY_BREAK
case 73:
YY_RULE_SETUP
-#line 370 "compilers/imcc/imcc.l"
+#line 369 "compilers/imcc/imcc.l"
return IF;
YY_BREAK
case 74:
YY_RULE_SETUP
-#line 371 "compilers/imcc/imcc.l"
+#line 370 "compilers/imcc/imcc.l"
return UNLESS;
YY_BREAK
case 75:
YY_RULE_SETUP
-#line 372 "compilers/imcc/imcc.l"
+#line 371 "compilers/imcc/imcc.l"
return PNULL;
YY_BREAK
case 76:
YY_RULE_SETUP
-#line 373 "compilers/imcc/imcc.l"
+#line 372 "compilers/imcc/imcc.l"
return INTV;
YY_BREAK
case 77:
YY_RULE_SETUP
-#line 374 "compilers/imcc/imcc.l"
+#line 373 "compilers/imcc/imcc.l"
return FLOATV;
YY_BREAK
case 78:
YY_RULE_SETUP
-#line 376 "compilers/imcc/imcc.l"
+#line 375 "compilers/imcc/imcc.l"
return PMCV;
YY_BREAK
case 79:
YY_RULE_SETUP
-#line 377 "compilers/imcc/imcc.l"
+#line 376 "compilers/imcc/imcc.l"
return STRINGV;
YY_BREAK
case 80:
YY_RULE_SETUP
-#line 378 "compilers/imcc/imcc.l"
+#line 377 "compilers/imcc/imcc.l"
return SHIFT_LEFT;
YY_BREAK
case 81:
YY_RULE_SETUP
-#line 379 "compilers/imcc/imcc.l"
+#line 378 "compilers/imcc/imcc.l"
return SHIFT_RIGHT;
YY_BREAK
case 82:
YY_RULE_SETUP
-#line 380 "compilers/imcc/imcc.l"
+#line 379 "compilers/imcc/imcc.l"
return SHIFT_RIGHT_U;
YY_BREAK
case 83:
YY_RULE_SETUP
-#line 381 "compilers/imcc/imcc.l"
+#line 380 "compilers/imcc/imcc.l"
return LOG_AND;
YY_BREAK
case 84:
YY_RULE_SETUP
-#line 382 "compilers/imcc/imcc.l"
+#line 381 "compilers/imcc/imcc.l"
return LOG_OR;
YY_BREAK
case 85:
YY_RULE_SETUP
-#line 383 "compilers/imcc/imcc.l"
+#line 382 "compilers/imcc/imcc.l"
return LOG_XOR;
YY_BREAK
case 86:
YY_RULE_SETUP
-#line 384 "compilers/imcc/imcc.l"
+#line 383 "compilers/imcc/imcc.l"
return RELOP_LT;
YY_BREAK
case 87:
YY_RULE_SETUP
-#line 385 "compilers/imcc/imcc.l"
+#line 384 "compilers/imcc/imcc.l"
return RELOP_LTE;
YY_BREAK
case 88:
YY_RULE_SETUP
-#line 386 "compilers/imcc/imcc.l"
+#line 385 "compilers/imcc/imcc.l"
return RELOP_GT;
YY_BREAK
case 89:
YY_RULE_SETUP
-#line 387 "compilers/imcc/imcc.l"
+#line 386 "compilers/imcc/imcc.l"
return RELOP_GTE;
YY_BREAK
case 90:
YY_RULE_SETUP
-#line 388 "compilers/imcc/imcc.l"
+#line 387 "compilers/imcc/imcc.l"
return RELOP_EQ;
YY_BREAK
case 91:
YY_RULE_SETUP
-#line 389 "compilers/imcc/imcc.l"
+#line 388 "compilers/imcc/imcc.l"
return RELOP_NE;
YY_BREAK
case 92:
YY_RULE_SETUP
-#line 390 "compilers/imcc/imcc.l"
+#line 389 "compilers/imcc/imcc.l"
return POW;
YY_BREAK
case 93:
YY_RULE_SETUP
-#line 392 "compilers/imcc/imcc.l"
+#line 391 "compilers/imcc/imcc.l"
return CONCAT;
YY_BREAK
case 94:
YY_RULE_SETUP
-#line 393 "compilers/imcc/imcc.l"
+#line 392 "compilers/imcc/imcc.l"
return DOT;
YY_BREAK
case 95:
YY_RULE_SETUP
-#line 395 "compilers/imcc/imcc.l"
+#line 394 "compilers/imcc/imcc.l"
return PLUS_ASSIGN;
YY_BREAK
case 96:
YY_RULE_SETUP
-#line 396 "compilers/imcc/imcc.l"
+#line 395 "compilers/imcc/imcc.l"
return MINUS_ASSIGN;
YY_BREAK
case 97:
YY_RULE_SETUP
-#line 397 "compilers/imcc/imcc.l"
+#line 396 "compilers/imcc/imcc.l"
return MUL_ASSIGN;
YY_BREAK
case 98:
YY_RULE_SETUP
-#line 398 "compilers/imcc/imcc.l"
+#line 397 "compilers/imcc/imcc.l"
return DIV_ASSIGN;
YY_BREAK
case 99:
YY_RULE_SETUP
-#line 399 "compilers/imcc/imcc.l"
+#line 398 "compilers/imcc/imcc.l"
return MOD_ASSIGN;
YY_BREAK
case 100:
YY_RULE_SETUP
-#line 400 "compilers/imcc/imcc.l"
+#line 399 "compilers/imcc/imcc.l"
return FDIV;
YY_BREAK
case 101:
YY_RULE_SETUP
-#line 401 "compilers/imcc/imcc.l"
+#line 400 "compilers/imcc/imcc.l"
return FDIV_ASSIGN;
YY_BREAK
case 102:
YY_RULE_SETUP
-#line 402 "compilers/imcc/imcc.l"
+#line 401 "compilers/imcc/imcc.l"
return BAND_ASSIGN;
YY_BREAK
case 103:
YY_RULE_SETUP
-#line 403 "compilers/imcc/imcc.l"
+#line 402 "compilers/imcc/imcc.l"
return BOR_ASSIGN;
YY_BREAK
case 104:
YY_RULE_SETUP
-#line 404 "compilers/imcc/imcc.l"
+#line 403 "compilers/imcc/imcc.l"
return BXOR_ASSIGN;
YY_BREAK
case 105:
YY_RULE_SETUP
-#line 405 "compilers/imcc/imcc.l"
+#line 404 "compilers/imcc/imcc.l"
return SHR_ASSIGN;
YY_BREAK
case 106:
YY_RULE_SETUP
-#line 406 "compilers/imcc/imcc.l"
+#line 405 "compilers/imcc/imcc.l"
return SHL_ASSIGN;
YY_BREAK
case 107:
YY_RULE_SETUP
-#line 407 "compilers/imcc/imcc.l"
+#line 406 "compilers/imcc/imcc.l"
return SHR_U_ASSIGN;
YY_BREAK
case 108:
YY_RULE_SETUP
-#line 408 "compilers/imcc/imcc.l"
+#line 407 "compilers/imcc/imcc.l"
return CONCAT_ASSIGN;
YY_BREAK
case 109:
YY_RULE_SETUP
-#line 410 "compilers/imcc/imcc.l"
+#line 409 "compilers/imcc/imcc.l"
{
char *macro_name = NULL;
int start_cond = YY_START;
@@ -3530,21 +3529,21 @@
YY_BREAK
case 110:
YY_RULE_SETUP
-#line 453 "compilers/imcc/imcc.l"
+#line 452 "compilers/imcc/imcc.l"
{
return read_macro(valp, interp, yyscanner);
}
YY_BREAK
case 111:
YY_RULE_SETUP
-#line 457 "compilers/imcc/imcc.l"
+#line 456 "compilers/imcc/imcc.l"
{
const int c = yylex(valp,yyscanner,interp);
if (c != STRINGC)
return c;
- /* STRINGCs have a str_dup()ed valp->s */
+ /* STRINGCs have a mem_sys_strdup()ed valp->s */
mem_sys_free(valp->s);
YYCHOP();
include_file(interp, yytext + 1, yyscanner);
@@ -3552,7 +3551,7 @@
YY_BREAK
case 112:
YY_RULE_SETUP
-#line 469 "compilers/imcc/imcc.l"
+#line 468 "compilers/imcc/imcc.l"
{
if (valp) {
char *label;
@@ -3577,7 +3576,7 @@
YY_BREAK
case 113:
YY_RULE_SETUP
-#line 491 "compilers/imcc/imcc.l"
+#line 490 "compilers/imcc/imcc.l"
{
if (valp) {
@@ -3602,25 +3601,25 @@
YY_BREAK
case 114:
YY_RULE_SETUP
-#line 513 "compilers/imcc/imcc.l"
+#line 512 "compilers/imcc/imcc.l"
return COMMA;
YY_BREAK
case 115:
YY_RULE_SETUP
-#line 515 "compilers/imcc/imcc.l"
+#line 514 "compilers/imcc/imcc.l"
{
/* trim last ':' */
YYCHOP();
if (valp)
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
return LABEL;
}
YY_BREAK
case 116:
YY_RULE_SETUP
-#line 525 "compilers/imcc/imcc.l"
+#line 524 "compilers/imcc/imcc.l"
{
char * const macro_name = yytext + 1;
@@ -3632,34 +3631,34 @@
YY_BREAK
case 117:
YY_RULE_SETUP
-#line 536 "compilers/imcc/imcc.l"
+#line 535 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, FLOATC);
YY_BREAK
case 118:
YY_RULE_SETUP
-#line 537 "compilers/imcc/imcc.l"
+#line 536 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, INTC);
YY_BREAK
case 119:
YY_RULE_SETUP
-#line 538 "compilers/imcc/imcc.l"
+#line 537 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, INTC);
YY_BREAK
case 120:
YY_RULE_SETUP
-#line 539 "compilers/imcc/imcc.l"
+#line 538 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, INTC);
YY_BREAK
case 121:
YY_RULE_SETUP
-#line 540 "compilers/imcc/imcc.l"
+#line 539 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, INTC);
YY_BREAK
case 122:
YY_RULE_SETUP
-#line 542 "compilers/imcc/imcc.l"
+#line 541 "compilers/imcc/imcc.l"
{
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
/* trailing 'L' */
valp->s[strlen(valp->s) - 1] = '\0';
@@ -3670,9 +3669,9 @@
YY_BREAK
case 123:
YY_RULE_SETUP
-#line 552 "compilers/imcc/imcc.l"
+#line 551 "compilers/imcc/imcc.l"
{
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
/* RT #42382 delete quotes, -> emit, pbc */
return STRINGC;
@@ -3680,7 +3679,7 @@
YY_BREAK
case 124:
YY_RULE_SETUP
-#line 559 "compilers/imcc/imcc.l"
+#line 558 "compilers/imcc/imcc.l"
{
macro_frame_t *frame;
@@ -3688,7 +3687,7 @@
off newline and quote. */
if (IMCC_INFO(interp)->frames->heredoc_rest)
IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR, "nested heredoc not supported");
- IMCC_INFO(interp)->heredoc_end = str_dup(yytext + 3);
+ IMCC_INFO(interp)->heredoc_end = mem_sys_strdup(yytext + 3);
IMCC_INFO(interp)->heredoc_end[strlen(IMCC_INFO(interp)->heredoc_end) - 1] = 0;
if (!strlen(IMCC_INFO(interp)->heredoc_end))
@@ -3711,10 +3710,10 @@
YY_BREAK
case 125:
YY_RULE_SETUP
-#line 587 "compilers/imcc/imcc.l"
+#line 586 "compilers/imcc/imcc.l"
{
/* charset:"..." */
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
/* this is actually not unicode but a string with a charset */
return USTRINGC;
@@ -3722,7 +3721,7 @@
YY_BREAK
case 126:
YY_RULE_SETUP
-#line 595 "compilers/imcc/imcc.l"
+#line 594 "compilers/imcc/imcc.l"
{
if (valp) (valp)->s = yytext;
if (IMCC_INFO(interp)->state->pasm_file)
@@ -3733,7 +3732,7 @@
YY_BREAK
case 127:
YY_RULE_SETUP
-#line 603 "compilers/imcc/imcc.l"
+#line 602 "compilers/imcc/imcc.l"
{
if (valp) (valp)->s = yytext;
if (IMCC_INFO(interp)->state->pasm_file)
@@ -3744,7 +3743,7 @@
YY_BREAK
case 128:
YY_RULE_SETUP
-#line 611 "compilers/imcc/imcc.l"
+#line 610 "compilers/imcc/imcc.l"
{
if (valp) (valp)->s = yytext;
if (IMCC_INFO(interp)->state->pasm_file)
@@ -3755,7 +3754,7 @@
YY_BREAK
case 129:
YY_RULE_SETUP
-#line 619 "compilers/imcc/imcc.l"
+#line 618 "compilers/imcc/imcc.l"
{
if (valp) (valp)->s = yytext;
if (IMCC_INFO(interp)->state->pasm_file)
@@ -3766,7 +3765,7 @@
YY_BREAK
case 130:
YY_RULE_SETUP
-#line 627 "compilers/imcc/imcc.l"
+#line 626 "compilers/imcc/imcc.l"
{
IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
"'%s' is not a valid register name", yytext);
@@ -3774,21 +3773,21 @@
YY_BREAK
case 131:
YY_RULE_SETUP
-#line 632 "compilers/imcc/imcc.l"
+#line 631 "compilers/imcc/imcc.l"
{
if (IMCC_INFO(interp)->state->pasm_file == 0)
IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
"'%s' is only a valid register name in PASM mode", yytext);
if (valp)
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
return REG;
}
YY_BREAK
case 132:
YY_RULE_SETUP
-#line 643 "compilers/imcc/imcc.l"
+#line 642 "compilers/imcc/imcc.l"
{
if (!pesky_global__is_def) {
SymReg *r = find_sym(interp, yytext);
@@ -3813,25 +3812,25 @@
}
}
- valp->s = str_dup(yytext);
+ valp->s = mem_sys_strdup(yytext);
return (!pesky_global__is_def && is_op(interp, valp->s) ? PARROT_OP : IDENTIFIER);
}
YY_BREAK
case 133:
YY_RULE_SETUP
-#line 672 "compilers/imcc/imcc.l"
+#line 671 "compilers/imcc/imcc.l"
/* skip */;
YY_BREAK
case 134:
YY_RULE_SETUP
-#line 674 "compilers/imcc/imcc.l"
+#line 673 "compilers/imcc/imcc.l"
{
/* catch all except for state macro */
return yytext[0];
}
YY_BREAK
case YY_STATE_EOF(emit):
-#line 679 "compilers/imcc/imcc.l"
+#line 678 "compilers/imcc/imcc.l"
{
BEGIN(INITIAL);
@@ -3844,18 +3843,18 @@
}
YY_BREAK
case YY_STATE_EOF(INITIAL):
-#line 690 "compilers/imcc/imcc.l"
+#line 689 "compilers/imcc/imcc.l"
yyterminate();
YY_BREAK
case 135:
YY_RULE_SETUP
-#line 692 "compilers/imcc/imcc.l"
+#line 691 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, ENDM);
YY_BREAK
case 136:
/* rule 136 can match eol */
YY_RULE_SETUP
-#line 694 "compilers/imcc/imcc.l"
+#line 693 "compilers/imcc/imcc.l"
{
IMCC_INFO(interp)->line++;
DUP_AND_RET(valp, '\n');
@@ -3863,12 +3862,12 @@
YY_BREAK
case 137:
YY_RULE_SETUP
-#line 699 "compilers/imcc/imcc.l"
+#line 698 "compilers/imcc/imcc.l"
return LABEL;
YY_BREAK
case 138:
YY_RULE_SETUP
-#line 701 "compilers/imcc/imcc.l"
+#line 700 "compilers/imcc/imcc.l"
{
if (yylex(valp,yyscanner,interp) != LABEL)
@@ -3895,7 +3894,7 @@
YY_BREAK
case 139:
YY_RULE_SETUP
-#line 725 "compilers/imcc/imcc.l"
+#line 724 "compilers/imcc/imcc.l"
{
if (valp) {
const size_t len = strlen(IMCC_INFO(interp)->cur_macro_name) + yyleng + 12;
@@ -3914,49 +3913,49 @@
YY_BREAK
case 140:
YY_RULE_SETUP
-#line 741 "compilers/imcc/imcc.l"
+#line 740 "compilers/imcc/imcc.l"
/* skip leading ws */;
YY_BREAK
case 141:
YY_RULE_SETUP
-#line 742 "compilers/imcc/imcc.l"
+#line 741 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, ' ');
YY_BREAK
case 142:
YY_RULE_SETUP
-#line 743 "compilers/imcc/imcc.l"
+#line 742 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, REG);
YY_BREAK
case 143:
YY_RULE_SETUP
-#line 744 "compilers/imcc/imcc.l"
+#line 743 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, REG);
YY_BREAK
case 144:
YY_RULE_SETUP
-#line 745 "compilers/imcc/imcc.l"
+#line 744 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, IDENTIFIER);
YY_BREAK
case 145:
YY_RULE_SETUP
-#line 746 "compilers/imcc/imcc.l"
+#line 745 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, MACRO);
YY_BREAK
case 146:
YY_RULE_SETUP
-#line 747 "compilers/imcc/imcc.l"
+#line 746 "compilers/imcc/imcc.l"
DUP_AND_RET(valp, yytext[0]);
YY_BREAK
case YY_STATE_EOF(macro):
-#line 748 "compilers/imcc/imcc.l"
+#line 747 "compilers/imcc/imcc.l"
yyterminate();
YY_BREAK
case 147:
YY_RULE_SETUP
-#line 750 "compilers/imcc/imcc.l"
+#line 749 "compilers/imcc/imcc.l"
ECHO;
YY_BREAK
-#line 3960 "compilers/imcc/imclexer.c"
+#line 3959 "compilers/imcc/imclexer.c"
case YY_STATE_EOF(pod):
case YY_STATE_EOF(cmt1):
case YY_STATE_EOF(cmt2):
@@ -5158,7 +5157,7 @@
#define YYTABLES_NAME "yytables"
-#line 750 "compilers/imcc/imcc.l"
+#line 749 "compilers/imcc/imcc.l"
@@ -5201,13 +5200,8 @@
if (IMCC_INFO(interp)->frames) {
tmp->s.pasm_file = IMCC_INFO(interp)->frames->s.pasm_file;
-
- if (IMCC_INFO(interp)->frames->s.file_needs_free)
- tmp->s.file = str_dup(IMCC_INFO(interp)->frames->s.file);
- else
- tmp->s.file = IMCC_INFO(interp)->frames->s.file;
-
- tmp->s.file_needs_free = IMCC_INFO(interp)->frames->s.file_needs_free;
+ if (IMCC_INFO(interp)->frames->s.file)
+ tmp->s.file = mem_sys_strdup(IMCC_INFO(interp)->frames->s.file);
}
tmp->s.interp = interp;
@@ -5246,13 +5240,7 @@
} else
ret = frame->s.line;
- /* RT #42383 if frame->s.file was allocated free it */
- /* Update: This should do it! */
- if (frame->s.file_needs_free) {
- DECL_CONST_CAST;
- mem_sys_free(PARROT_const_cast(char *,frame->s.file));
- frame->s.file_needs_free = 0;
- }
+ mem_sys_free(frame->s.file);
mem_sys_free(frame);
if (buffer != NULL)
@@ -5279,7 +5267,7 @@
if (*p == '\0')
break;
- /* free any str_dup()ed strings */
+ /* free any mem_sys_strdup()ed strings */
if (yytext)
mem_sys_free(valp->s);
} while (*p != '\0');
@@ -5337,7 +5325,7 @@
{
YYSTYPE val;
size_t len = 0;
- char *current = str_dup("");
+ char *current = mem_sys_strdup("");
yyguts_t *yyg = (yyguts_t *)yyscanner;
int c = yylex_skip(&val, interp, " \n", yyscanner);
@@ -5359,7 +5347,7 @@
MAX_PARAM, macro_name);
params->name[params->num_param++] = current;
- current = str_dup("");
+ current = mem_sys_strdup("");
len = 0;
if (val.s)
@@ -5534,7 +5522,7 @@
else
memset(&m->params, 0, sizeof (params_t));
- m->expansion = str_dup(expansion);
+ m->expansion = mem_sys_strdup(expansion);
m->line = start_line;
}
@@ -5575,12 +5563,10 @@
/* remember macro name for error reporting
* first free any filename allocated in new_frame() */
- if (frame->s.file && frame->s.file_needs_free)
+ if (frame->s.file)
mem_sys_free(frame->s.file);
- /* RT #42384 check that all the .file text is malloced / freed */
- frame->s.file = str_dup(name);
- frame->s.file_needs_free = 1;
+ frame->s.file = mem_sys_strdup(name);
/* whitespace can be safely ignored */
do {
@@ -5609,7 +5595,7 @@
BEGIN(start_cond);
if (frame->expansion.num_param == 0 && m->params.num_param == 1) {
- frame->expansion.name[0] = str_dup("");
+ frame->expansion.name[0] = mem_sys_strdup("");
frame->expansion.num_param = 1;
}
@@ -5628,7 +5614,7 @@
const char * const s = find_macro_param(interp, current + 1);
if (s) {
- frame->expansion.name[i] = str_dup(s);
+ frame->expansion.name[i] = mem_sys_strdup(s);
mem_sys_free(current);
}
@@ -5671,8 +5657,7 @@
IMCC_fataly(interp, EXCEPTION_EXTERNAL_ERROR, strerror(errno));
mem_sys_free(s);
- frame->s.file = file_name;
- frame->s.file_needs_free = 0;
+ frame->s.file = mem_sys_strdup(file_name);
frame->s.handle = file;
ext = strrchr(file_name, '.');
@@ -5843,17 +5828,16 @@
set_filename(PARROT_INTERP, char * const filename)
{
IMCC_INFO(interp)->frames->s.file = filename;
- IMCC_INFO(interp)->frames->s.file_needs_free = 1;
/* in case .line is used outside a .sub, then this
* can't be done; hence the check.
- * The str_dup() is done, as the original #line implementation
+ * The mem_sys_strdup() is done, as the original #line implementation
* duplicated the string twice as well; one for the
* frames->s.file and one for cur_unit->file.
- * During the parse, the STRINGC is already str_dup()ed once.
+ * During the parse, the STRINGC is already mem_sys_strdup()ed once.
*/
if (IMCC_INFO(interp)->cur_unit)
- IMCC_INFO(interp)->cur_unit->file = str_dup(filename);
+ IMCC_INFO(interp)->cur_unit->file = mem_sys_strdup(filename);
}
/* Functions to set and get yyin, as we can't decorate it for export
Modified: branches/pmc_pct/compilers/imcc/imcparser.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/imcparser.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/imcparser.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -366,45 +366,49 @@
/* HEADERIZER BEGIN: static */
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
-static void add_pcc_named_arg(PARROT_INTERP,
+static void add_pcc_named_arg(
ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
- __attribute__nonnull__(4)
- FUNC_MODIFIES(*cur_call);
+ FUNC_MODIFIES(*cur_call)
+ FUNC_MODIFIES(*name)
+ FUNC_MODIFIES(*value);
-static void add_pcc_named_arg_var(PARROT_INTERP,
+static void add_pcc_named_arg_var(
ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
- __attribute__nonnull__(4)
- FUNC_MODIFIES(*cur_call);
+ FUNC_MODIFIES(*cur_call)
+ FUNC_MODIFIES(*name)
+ FUNC_MODIFIES(*value);
-static void add_pcc_named_param(PARROT_INTERP,
+static void add_pcc_named_param(
ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
- __attribute__nonnull__(4)
- FUNC_MODIFIES(*cur_call);
+ FUNC_MODIFIES(*cur_call)
+ FUNC_MODIFIES(*name)
+ FUNC_MODIFIES(*value);
-static void add_pcc_named_result(PARROT_INTERP,
+static void add_pcc_named_result(
ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3)
- __attribute__nonnull__(4)
- FUNC_MODIFIES(*cur_call);
+ FUNC_MODIFIES(*cur_call)
+ FUNC_MODIFIES(*name)
+ FUNC_MODIFIES(*value);
static void add_pcc_named_return(PARROT_INTERP,
ARGMOD(SymReg *cur_call),
@@ -563,23 +567,19 @@
FUNC_MODIFIES(*name);
#define ASSERT_ARGS_add_pcc_named_arg __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp) \
- || PARROT_ASSERT_ARG(cur_call) \
+ PARROT_ASSERT_ARG(cur_call) \
|| PARROT_ASSERT_ARG(name) \
|| PARROT_ASSERT_ARG(value)
#define ASSERT_ARGS_add_pcc_named_arg_var __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp) \
- || PARROT_ASSERT_ARG(cur_call) \
+ PARROT_ASSERT_ARG(cur_call) \
|| PARROT_ASSERT_ARG(name) \
|| PARROT_ASSERT_ARG(value)
#define ASSERT_ARGS_add_pcc_named_param __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp) \
- || PARROT_ASSERT_ARG(cur_call) \
+ PARROT_ASSERT_ARG(cur_call) \
|| PARROT_ASSERT_ARG(name) \
|| PARROT_ASSERT_ARG(value)
#define ASSERT_ARGS_add_pcc_named_result __attribute__unused__ int _ASSERT_ARGS_CHECK = \
- PARROT_ASSERT_ARG(interp) \
- || PARROT_ASSERT_ARG(cur_call) \
+ PARROT_ASSERT_ARG(cur_call) \
|| PARROT_ASSERT_ARG(name) \
|| PARROT_ASSERT_ARG(value)
#define ASSERT_ARGS_add_pcc_named_return __attribute__unused__ int _ASSERT_ARGS_CHECK = \
@@ -761,11 +761,11 @@
r[0] = left;
if (ascii) {
/* strip delimiters */
- name = str_dup(constant + 1);
+ name = mem_sys_strdup(constant + 1);
name[strlen(name) - 1] = 0;
}
else {
- name = str_dup(constant);
+ name = mem_sys_strdup(constant);
}
switch (type_enum) {
@@ -811,7 +811,7 @@
SymReg *r[3];
char *const_name;
const int ascii = (*constant == '\'' || *constant == '"');
- char *unquoted_name = str_dup(name + 1);
+ char *unquoted_name = mem_sys_strdup(name + 1);
size_t name_length = strlen(unquoted_name) - 1;
unquoted_name[name_length] = 0;
@@ -828,11 +828,11 @@
r[0] = left;
if (ascii) {
/* strip delimiters */
- const_name = str_dup(constant + 1);
+ const_name = mem_sys_strdup(constant + 1);
const_name[strlen(const_name) - 1] = 0;
}
else {
- const_name = str_dup(constant);
+ const_name = mem_sys_strdup(constant);
}
if ((strncmp(unquoted_name, "Sub", name_length) == 0)
@@ -1083,7 +1083,7 @@
ASSERT_ARGS(mk_sub_address_fromc)
/* name is a quoted sub name */
SymReg *r;
- char *name_copy = str_dup(name + 1);
+ char *name_copy = mem_sys_strdup(name + 1);
name_copy[strlen(name_copy) - 1] = 0;
r = mk_sub_address(interp, name_copy);
@@ -1199,17 +1199,17 @@
/*
-=item C<static void add_pcc_named_arg(PARROT_INTERP, SymReg *cur_call, SymReg
-*name, SymReg *value)>
+=item C<static void add_pcc_named_arg(SymReg *cur_call, SymReg *name, SymReg
+*value)>
=cut
*/
static void
-add_pcc_named_arg(PARROT_INTERP, ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+add_pcc_named_arg(ARGMOD(SymReg *cur_call),
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
{
ASSERT_ARGS(add_pcc_named_arg)
name->type |= VT_NAMED;
@@ -1220,16 +1220,16 @@
/*
-=item C<static void add_pcc_named_arg_var(PARROT_INTERP, SymReg *cur_call,
-SymReg *name, SymReg *value)>
+=item C<static void add_pcc_named_arg_var(SymReg *cur_call, SymReg *name, SymReg
+*value)>
=cut
*/
static void
-add_pcc_named_arg_var(PARROT_INTERP, ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name), ARGIN(SymReg *value))
+add_pcc_named_arg_var(ARGMOD(SymReg *cur_call),
+ ARGMOD(SymReg *name), ARGMOD(SymReg *value))
{
ASSERT_ARGS(add_pcc_named_arg_var)
name->type |= VT_NAMED;
@@ -1239,17 +1239,17 @@
/*
-=item C<static void add_pcc_named_result(PARROT_INTERP, SymReg *cur_call, SymReg
-*name, SymReg *value)>
+=item C<static void add_pcc_named_result(SymReg *cur_call, SymReg *name, SymReg
+*value)>
=cut
*/
static void
-add_pcc_named_result(PARROT_INTERP, ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+add_pcc_named_result(ARGMOD(SymReg *cur_call),
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
{
ASSERT_ARGS(add_pcc_named_result)
name->type |= VT_NAMED;
@@ -1260,17 +1260,17 @@
/*
-=item C<static void add_pcc_named_param(PARROT_INTERP, SymReg *cur_call, SymReg
-*name, SymReg *value)>
+=item C<static void add_pcc_named_param(SymReg *cur_call, SymReg *name, SymReg
+*value)>
=cut
*/
static void
-add_pcc_named_param(PARROT_INTERP, ARGMOD(SymReg *cur_call),
- ARGIN(SymReg *name),
- ARGIN(SymReg *value))
+add_pcc_named_param(ARGMOD(SymReg *cur_call),
+ ARGMOD(SymReg *name),
+ ARGMOD(SymReg *value))
{
ASSERT_ARGS(add_pcc_named_param)
name->type |= VT_NAMED;
@@ -3504,7 +3504,7 @@
{
IMCC_INFO(interp)->cur_call->pcc_sub->pragma = (yyvsp[(5) - (6)].t);
if (!IMCC_INFO(interp)->cur_unit->instructions->symregs[0]->subid) {
- IMCC_INFO(interp)->cur_unit->instructions->symregs[0]->subid = str_dup(
+ IMCC_INFO(interp)->cur_unit->instructions->symregs[0]->subid = mem_sys_strdup(
IMCC_INFO(interp)->cur_unit->instructions->symregs[0]->name);
}
}
@@ -3529,7 +3529,7 @@
#line 1363 "compilers/imcc/imcc.y"
{
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_param(interp, IMCC_INFO(interp)->cur_call,
+ add_pcc_named_param(IMCC_INFO(interp)->cur_call,
IMCC_INFO(interp)->adv_named_id, (yyvsp[(2) - (3)].sr));
IMCC_INFO(interp)->adv_named_id = NULL;
}
@@ -3935,7 +3935,7 @@
case 123:
#line 1659 "compilers/imcc/imcc.y"
{
- IdList *l = (yyvsp[(4) - (4)].idlist);
+ IdList * const l = (yyvsp[(4) - (4)].idlist);
SymReg *ignored;
if (l->unique_reg)
ignored = mk_ident_ur(interp, l->id, (yyvsp[(3) - (4)].t));
@@ -4392,7 +4392,7 @@
case 200:
#line 1970 "compilers/imcc/imcc.y"
{
- /* there'd normally be a str_dup() here, but the lexer already
+ /* there'd normally be a mem_sys_strdup() here, but the lexer already
* copied the string, so it's safe to use directly */
if ((IMCC_INFO(interp)->cur_pmc_type = pmc_type(interp,
Parrot_str_new(interp, (yyvsp[(1) - (1)].s), 0))) <= 0) {
@@ -4718,7 +4718,7 @@
#line 2114 "compilers/imcc/imcc.y"
{
/* disallow bareword method names; SREG name constants are fine */
- char *name = (yyvsp[(3) - (3)].sr)->name;
+ const char * const name = (yyvsp[(3) - (3)].sr)->name;
if (!((yyvsp[(3) - (3)].sr)->type & VTREG)) {
if (*name != '\'' || *name != '\"')
IMCC_fataly(interp, EXCEPTION_SYNTAX_ERROR,
@@ -4777,7 +4777,7 @@
{
(yyval.sr) = 0;
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_arg(interp, IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, (yyvsp[(3) - (3)].sr));
+ add_pcc_named_arg(IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, (yyvsp[(3) - (3)].sr));
IMCC_INFO(interp)->adv_named_id = NULL;
}
else
@@ -4790,7 +4790,7 @@
{
(yyval.sr) = 0;
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_arg(interp, IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, (yyvsp[(1) - (1)].sr));
+ add_pcc_named_arg(IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, (yyvsp[(1) - (1)].sr));
IMCC_INFO(interp)->adv_named_id = NULL;
}
else
@@ -4802,7 +4802,7 @@
#line 2175 "compilers/imcc/imcc.y"
{
(yyval.sr) = 0;
- add_pcc_named_arg(interp, IMCC_INFO(interp)->cur_call,
+ add_pcc_named_arg(IMCC_INFO(interp)->cur_call,
mk_const(interp, (yyvsp[(3) - (5)].s), 'S'), (yyvsp[(5) - (5)].sr));
mem_sys_free((yyvsp[(3) - (5)].s));
}
@@ -4812,7 +4812,7 @@
#line 2182 "compilers/imcc/imcc.y"
{
(yyval.sr) = 0;
- add_pcc_named_arg_var(interp, IMCC_INFO(interp)->cur_call, (yyvsp[(1) - (3)].sr), (yyvsp[(3) - (3)].sr));
+ add_pcc_named_arg_var(IMCC_INFO(interp)->cur_call, (yyvsp[(1) - (3)].sr), (yyvsp[(3) - (3)].sr));
}
break;
@@ -4820,7 +4820,7 @@
#line 2187 "compilers/imcc/imcc.y"
{
(yyval.sr) = 0;
- add_pcc_named_arg(interp, IMCC_INFO(interp)->cur_call,
+ add_pcc_named_arg(IMCC_INFO(interp)->cur_call,
mk_const(interp, (yyvsp[(1) - (3)].s), 'S'), (yyvsp[(3) - (3)].sr));
mem_sys_free((yyvsp[(1) - (3)].s));
}
@@ -4871,7 +4871,7 @@
{
(yyval.sr) = 0;
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_result(interp, IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, (yyvsp[(3) - (3)].sr));
+ add_pcc_named_result(IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, (yyvsp[(3) - (3)].sr));
IMCC_INFO(interp)->adv_named_id = NULL;
}
else
@@ -4882,7 +4882,7 @@
case 282:
#line 2229 "compilers/imcc/imcc.y"
{
- add_pcc_named_result(interp, IMCC_INFO(interp)->cur_call,
+ add_pcc_named_result(IMCC_INFO(interp)->cur_call,
mk_const(interp, (yyvsp[(3) - (5)].s), 'S'), (yyvsp[(5) - (5)].sr));
mem_sys_free((yyvsp[(3) - (5)].s));
}
@@ -4893,7 +4893,7 @@
{
(yyval.sr) = 0;
if (IMCC_INFO(interp)->adv_named_id) {
- add_pcc_named_result(interp, IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, (yyvsp[(1) - (1)].sr));
+ add_pcc_named_result(IMCC_INFO(interp)->cur_call, IMCC_INFO(interp)->adv_named_id, (yyvsp[(1) - (1)].sr));
IMCC_INFO(interp)->adv_named_id = NULL;
}
else
@@ -4904,7 +4904,7 @@
case 284:
#line 2245 "compilers/imcc/imcc.y"
{
- add_pcc_named_result(interp, IMCC_INFO(interp)->cur_call, mk_const(interp, (yyvsp[(1) - (3)].s), 'S'), (yyvsp[(3) - (3)].sr));
+ add_pcc_named_result(IMCC_INFO(interp)->cur_call, mk_const(interp, (yyvsp[(1) - (3)].s), 'S'), (yyvsp[(3) - (3)].sr));
mem_sys_free((yyvsp[(1) - (3)].s));
}
break;
Modified: branches/pmc_pct/compilers/imcc/instructions.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/instructions.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/instructions.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -103,8 +103,8 @@
(Instruction*)mem_sys_allocate_zeroed(sizeof (Instruction) + reg_space);
int i;
- ins->opname = str_dup(op);
- ins->format = str_dup(fmt);
+ ins->opname = mem_sys_strdup(op);
+ ins->format = mem_sys_strdup(fmt);
ins->symreg_count = n;
for (i = 0; i < n; i++)
Modified: branches/pmc_pct/compilers/imcc/main.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/main.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/main.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -955,7 +955,7 @@
Parrot_pbc_load(interp, pf);
IMCC_push_parser_state(interp);
- IMCC_INFO(interp)->state->file = strdup(sourcefile);
+ IMCC_INFO(interp)->state->file = mem_sys_strdup(sourcefile);
emit_open(interp, per_pbc, per_pbc ? NULL : (void*)output_file);
Modified: branches/pmc_pct/compilers/imcc/optimizer.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/optimizer.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/optimizer.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -368,7 +368,7 @@
last->opnum = tmp->opnum;
last->opsize = tmp->opsize;
free(last->opname);
- last->opname = str_dup(tmp->opname);
+ last->opname = mem_sys_strdup(tmp->opname);
free_ins(tmp);
/* delete branch */
Modified: branches/pmc_pct/compilers/imcc/parser_util.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/parser_util.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/parser_util.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -677,7 +677,7 @@
IMCC_INFO(interp)->state->next = NULL;
IMCC_INFO(interp)->state->pasm_file = pasm_file;
- IMCC_INFO(interp)->state->file = name;
+ IMCC_INFO(interp)->state->file = mem_sys_strdup(name);
IMCC_INFO(interp)->expect_pasm = 0;
compile_string(interp, s, yyscanner);
@@ -941,7 +941,7 @@
IMCC_push_parser_state(interp);
{
/* Store a copy, in order to know how to free it later */
- char *copyname = strdup(fullname);
+ char *copyname = mem_sys_strdup(fullname);
IMCC_INFO(interp)->state->file = copyname;
ext = strrchr(copyname, '.');
}
Modified: branches/pmc_pct/compilers/imcc/pbc.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/pbc.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/pbc.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -1348,7 +1348,7 @@
ns_const = ns->color;
if (real_name) {
- char * const p = str_dup(real_name + 1);
+ char * const p = mem_sys_strdup(real_name + 1);
free(r->name);
r->name = p;
}
@@ -1394,7 +1394,7 @@
unit->subid = r;
else {
/* trim the quotes */
- unit->subid->name = str_dup(unit->subid->name + 1);
+ unit->subid->name = mem_sys_strdup(unit->subid->name + 1);
unit->subid->name[strlen(unit->subid->name) - 1] = 0;
/* create string constant for it. */
@@ -1809,6 +1809,9 @@
STRING *s;
PMC *p;
+ if (PMC_IS_NULL(_class))
+ IMCC_fatal(interp, 1, "make_pmc_const: no such pmc");
+
if (*r->name == '"')
s = Parrot_str_unescape(interp, r->name + 1, '"', NULL);
Modified: branches/pmc_pct/compilers/imcc/pcc.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/pcc.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/pcc.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -743,6 +743,9 @@
SymReg * const sub = ins->symregs[0];
+ PARROT_ASSERT(sub);
+ PARROT_ASSERT(sub->pcc_sub);
+
if (ins->type & ITRESULT) {
const int n = sub->pcc_sub->nret;
ins = pcc_get_args(interp, unit, ins, "get_results", n,
@@ -767,6 +770,11 @@
if (ins->type & ITCALL) {
SymReg * const the_sub = sub->pcc_sub->sub;
+ /* If this condition is true the generator must haven't be called,
+ * but check it as a last resort.
+ * See also TT #737 */
+ if (the_sub == NULL)
+ IMCC_fatal(interp, 1, "expand_pcc_sub_call: no such sub");
if (!meth_call && (the_sub->type & VTADDRESS)) {
/* sub->pcc_sub->sub is an actual subroutine name, not a variable */
Modified: branches/pmc_pct/compilers/imcc/reg_alloc.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/reg_alloc.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/reg_alloc.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -72,7 +72,7 @@
__attribute__nonnull__(2)
FUNC_MODIFIES(*r);
-static int first_avail(
+static unsigned int first_avail(
ARGIN(const IMC_Unit *unit),
int reg_set,
ARGOUT_NULLOK(Set **avail))
@@ -1110,7 +1110,7 @@
/*
-=item C<static int first_avail(const IMC_Unit *unit, int reg_set, Set **avail)>
+=item C<static unsigned int first_avail(const IMC_Unit *unit, int reg_set, Set **avail)>
find first available register of the given reg_set
@@ -1118,7 +1118,7 @@
*/
-static int
+static unsigned int
first_avail(ARGIN(const IMC_Unit *unit), int reg_set, ARGOUT_NULLOK(Set **avail))
{
ASSERT_ARGS(first_avail)
@@ -1188,10 +1188,10 @@
&& r->color == -1
&& (r->usage & usage)
&& r->use_count) {
- Set *avail = sets[j];
- int first_reg = avail
- ? set_first_zero(avail)
- : first_avail(unit, (int)r->set, &avail);
+ Set *avail = sets[j];
+ unsigned int first_reg = avail
+ ? set_first_zero(avail)
+ : first_avail(unit, (int)r->set, &avail);
set_add(avail, first_reg);
r->color = first_reg++;
Modified: branches/pmc_pct/compilers/imcc/symreg.c
==============================================================================
--- branches/pmc_pct/compilers/imcc/symreg.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/imcc/symreg.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -74,6 +74,14 @@
__attribute__nonnull__(1)
__attribute__nonnull__(2);
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static SymReg * get_sym_by_name(
+ ARGIN(const SymHash *hsh),
+ ARGIN(const char *name))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2);
+
static int int_overflows(ARGIN(const SymReg *r))
__attribute__nonnull__(1);
@@ -105,6 +113,9 @@
#define ASSERT_ARGS_add_ns __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(interp) \
|| PARROT_ASSERT_ARG(name)
+#define ASSERT_ARGS_get_sym_by_name __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+ PARROT_ASSERT_ARG(hsh) \
+ || PARROT_ASSERT_ARG(name)
#define ASSERT_ARGS_int_overflows __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(r)
#define ASSERT_ARGS_mk_pmc_const_2 __attribute__unused__ int _ASSERT_ARGS_CHECK = \
@@ -134,7 +145,7 @@
Namespace * const ns = mem_allocate_zeroed_typed(Namespace);
ns->parent = pesky_global__namespace;
- ns->name = str_dup(name);
+ ns->name = mem_sys_strdup(name);
pesky_global__namespace = ns;
}
@@ -203,6 +214,35 @@
}
+/*
+
+=item C<static SymReg * get_sym_by_name(const SymHash *hsh, const char *name)>
+
+Gets a symbol from the hash, with the given C<name>.
+
+=cut
+
+*/
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CAN_RETURN_NULL
+static SymReg *
+get_sym_by_name(ARGIN(const SymHash *hsh), ARGIN(const char *name))
+{
+ ASSERT_ARGS(get_sym_by_name)
+
+ SymReg *p;
+ const unsigned int i = hash_str(name) % hsh->size;
+
+ for (p = hsh->data[i]; p; p = p->next) {
+ if (STREQ(name, p->name))
+ return p;
+ }
+
+ return NULL;
+}
+
+
/* symbolic registers */
/*
@@ -227,7 +267,7 @@
r = mem_allocate_zeroed_typed(SymReg);
r->set = t;
r->type = VTREG;
- r->name = str_dup(name);
+ r->name = mem_sys_strdup(name);
r->color = -1;
r->want_regno = -1;
@@ -579,7 +619,7 @@
return result;
}
- return str_dup(name);
+ return mem_sys_strdup(name);
}
@@ -600,10 +640,16 @@
{
ASSERT_ARGS(mk_ident)
char * const fullname = _mk_fullname(pesky_global__namespace, name);
- SymReg *r = mk_symreg(interp, fullname, t);
+ SymReg *r = get_sym_by_name(&(IMCC_INFO(interp)->last_unit->hash), name);
+ if (r && r->set != t) {
+ IMCC_print_inc(interp);
+ IMCC_warning(interp, "Duplicated IDENTIFIER '%s'\n", fullname);
+ }
+ r = mk_symreg(interp, fullname, t);
r->type = VTIDENTIFIER;
+
if (pesky_global__namespace) {
Identifier * const ident = mem_allocate_zeroed_typed(Identifier);
@@ -676,7 +722,7 @@
r[0] = left;
/* strip delimiters */
- name = str_dup(rhs->name + 1);
+ name = mem_sys_strdup(rhs->name + 1);
len = strlen(name);
name[len - 1] = '\0';
@@ -874,7 +920,7 @@
if (!IMCC_INFO(interp)->cur_namespace
|| (l = strlen(IMCC_INFO(interp)->cur_namespace->name)) <= 2)
- return str_dup(name);
+ return mem_sys_strdup(name);
/* TODO keyed syntax */
len = strlen(name) + l + 4;
@@ -921,7 +967,7 @@
if (uniq == U_add_all) {
r = mem_allocate_zeroed_typed(SymReg);
r->type = VTADDRESS;
- r->name = str_dup(name);
+ r->name = mem_sys_strdup(name);
_store_symreg(hsh, r);
}
else {
@@ -1104,7 +1150,7 @@
ASSERT_ARGS(dup_sym)
SymReg * const new_sym = mem_allocate_zeroed_typed(SymReg);
STRUCT_COPY(new_sym, r);
- new_sym->name = str_dup(r->name);
+ new_sym->name = mem_sys_strdup(r->name);
if (r->nextkey)
new_sym->nextkey = dup_sym(r->nextkey);
Modified: branches/pmc_pct/compilers/nqp/src/Grammar/Actions.pir
==============================================================================
--- branches/pmc_pct/compilers/nqp/src/Grammar/Actions.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/nqp/src/Grammar/Actions.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -715,7 +715,6 @@
$S0 = expr.'name'()
if $S0 != 'infix:,' goto one_arg
comma_arg:
- .local pmc iter
iter = expr.'iterator'()
iter_loop:
unless iter goto end
Modified: branches/pmc_pct/compilers/pct/src/PAST/Compiler.pir
==============================================================================
--- branches/pmc_pct/compilers/pct/src/PAST/Compiler.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/pct/src/PAST/Compiler.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -406,7 +406,6 @@
.local pmc iter
.local string rtype
- .local int sigidx
iter = node.'iterator'()
sigidx = 1
rtype = substr signature, sigidx, 1
@@ -1423,7 +1422,7 @@
collpast = node[0]
bodypast = node[1]
- .local pmc collpost, testpost
+ .local pmc collpost
collpost = self.'as_post'(collpast, 'rtype'=>'P')
ops.'push'(collpost)
Modified: branches/pmc_pct/compilers/pct/src/PCT/Dumper.pir
==============================================================================
--- branches/pmc_pct/compilers/pct/src/PCT/Dumper.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/pct/src/PCT/Dumper.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -8,7 +8,8 @@
=head1 DESCRIPTION
This file implements a dumper that attempts to output PAST,
-Match, and Capture objects in a YAML-compatible format.
+Match, and Capture objects in a format that can be easily
+consumed by syntax highlighters (such as Padre).
Yes, the code is probably much uglier and convoluted than
it should be. No, I'm not proud of it, but it works for now.
Modified: branches/pmc_pct/compilers/pge/PGE/Match.pir
==============================================================================
--- branches/pmc_pct/compilers/pge/PGE/Match.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/pge/PGE/Match.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -64,7 +64,6 @@
.local pmc target, grammar_class
issrcmatch = isa src, ['PGE';'Match']
if issrcmatch goto target_from_src
- .local pmc target
target = new 'CodeString'
assign target, src
pos = 0
Modified: branches/pmc_pct/compilers/pge/PGE/Perl6Regex.pir
==============================================================================
--- branches/pmc_pct/compilers/pge/PGE/Perl6Regex.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/compilers/pge/PGE/Perl6Regex.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -107,7 +107,7 @@
.return ($P0)
analyze:
- .local pmc exp, pad
+ .local pmc pad
exp = match['expr']
pad = clone adverbs
$P0 = new 'Hash'
Modified: branches/pmc_pct/config/gen/makefiles/root.in
==============================================================================
--- branches/pmc_pct/config/gen/makefiles/root.in Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/config/gen/makefiles/root.in Fri Jun 26 08:35:24 2009 (r39797)
@@ -259,10 +259,12 @@
$(LIBRARY_DIR)/Math/Random/mt19937ar.pbc \
$(LIBRARY_DIR)/Math/Rand.pbc \
$(LIBRARY_DIR)/MIME/Base64.pbc \
+ $(LIBRARY_DIR)/NCI/Utils.pbc \
$(LIBRARY_DIR)/NCI/call_toolkit_init.pbc \
$(LIBRARY_DIR)/ncurses.pbc \
#IF(has_opengl): $(LIBRARY_DIR)/OpenGL.pbc \
#IF(has_opengl): $(LIBRARY_DIR)/OpenGL_funcs.pbc \
+#IF(has_opengl): $(LIBRARY_DIR)/OpenGL/Math.pbc \
$(LIBRARY_DIR)/P6object.pbc \
$(LIBRARY_DIR)/parrotlib.pbc \
$(LIBRARY_DIR)/pcore.pbc \
@@ -619,6 +621,7 @@
$(SRC_DIR)/scheduler.str \
$(SRC_DIR)/spf_render.str \
$(SRC_DIR)/spf_vtable.str \
+ $(SRC_DIR)/string/api.str \
$(SRC_DIR)/sub.str \
$(SRC_DIR)/stacks.str \
\
Modified: branches/pmc_pct/config/gen/opengl.pm
==============================================================================
--- branches/pmc_pct/config/gen/opengl.pm Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/config/gen/opengl.pm Fri Jun 26 08:35:24 2009 (r39797)
@@ -107,6 +107,7 @@
# alter the typemaps to fit this bug.
my %C_TYPE = (
+ VOID => 'void',
GLvoid => 'void',
GLUnurbs => 'void',
GLUquadric => 'void',
@@ -147,11 +148,20 @@
WindowRef => 'void*',
HIViewRef => 'void*',
Style => 'void*',
+ HANDLE => 'void*',
+ HPBUFFERARB => 'void*',
+ HPBUFFEREXT => 'void*',
+ HVIDEOOUTPUTDEVICENV => 'void*',
+ HPVIDEODEV => 'void*',
+ HPGPUNV => 'void*',
+ HGPUNV => 'void*',
HDC => 'void*',
HGLRC => 'void*',
LPGLYPHMETRICSFLOAT => 'void*',
LPLAYERPLANEDESCRIPTOR => 'void*',
LPPIXELFORMATDESCRIPTOR => 'void*',
+ LPVOID => 'void*',
+ PGPU_DEVICE => 'void*',
GLchar => 'char',
GLcharARB => 'char',
@@ -160,10 +170,12 @@
GLboolean => 'unsigned char',
GLshort => 'short',
+ USHORT => 'unsigned short',
GLushort => 'unsigned short',
GLhalfARB => 'unsigned short',
GLhalfNV => 'unsigned short',
+ BOOL => 'int',
Bool => 'int',
Status => 'int',
GLint => 'int',
@@ -171,6 +183,8 @@
GLfixed => 'int',
GLclampx => 'int',
int32_t => 'int',
+ INT32 => 'int',
+ INT => 'int',
GLenum => 'unsigned int',
GLCenum => 'unsigned int',
@@ -182,11 +196,13 @@
CGLError => 'unsigned int',
SphereMapFlags => 'unsigned int',
+ UINT => 'unsigned int',
GLuint => 'unsigned int',
GLbitfield => 'unsigned int',
GLhandleARB => 'unsigned int',
GLXVideoDeviceNV => 'unsigned int',
+ DWORD => 'unsigned long',
GLulong => 'unsigned long',
XID => 'unsigned long',
Window => 'unsigned long',
@@ -208,9 +224,11 @@
GLXVideoSourceSGIX => 'unsigned long',
int64_t => 'long long',
+ INT64 => 'long long',
GLint64EXT => 'signed long long',
GLuint64EXT => 'unsigned long long',
+ FLOAT => 'float',
GLfloat => 'float',
GLclampf => 'float',
GLdouble => 'double',
@@ -307,11 +325,19 @@
'SetPixelFormat',
# Can't handle longlong until RT 53406 is done
+ 'glBufferAddressRangeNV',
+ 'glUniformui64NV',
+ 'glProgramUniformui64NV',
'glPresentFrameKeyedNV',
'glPresentFrameDualFillNV',
'glXSwapBuffersMscOML',
'glXWaitForMscOML',
'glXWaitForSbcOML',
+ 'wglGetSyncValuesOML',
+ 'wglSwapBuffersMscOML',
+ 'wglSwapLayerBuffersMscOML',
+ 'wglWaitForMscOML',
+ 'wglWaitForSbcOML',
# Can't handle weird data types specified only in proprietary headers
'glXCreateGLXVideoSourceSGIX',
@@ -431,6 +457,7 @@
(map "$_/gl/*.h" => @include_paths_win32),
# # Portability testing headers
+# "$ENV{HOME}/src/gentoo3/*.h",
# "$ENV{HOME}/src/osx/headers/GLUT/*.h",
# "$ENV{HOME}/src/osx/headers/OpenGL/*.h",
# "$ENV{HOME}/src/osx-10.4/GLUT/*.h",
Deleted: branches/pmc_pct/docs/book/README
==============================================================================
--- branches/pmc_pct/docs/book/README Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,24 +0,0 @@
-The book will have the following chapters.
-
-1) Overview
-2) Getting Started
-3) Parrot Intermediate Representation (PIR)
-4) Compiler Tools (PCT)
-5) Grammar Engine (PGE)
-6) Grammar Actions (NQP)
-7) Dynamic C-level Objects (PMCs)
-8) Dynamic Opcodes
-9) Parrot Assembly Language (PASM)
-10) Instruction Reference
-11) Directive Reference
-12) Operator Reference
-Appendix A) Glossary
-Appendix B) Patch Submission
-Appendix C) Command-Line Options
-Appendix D) Build Options
-Appendix E) Source Code
-
-
-Top-level headings in each chapter (the chapter title) are level 1 headings.
-All sub-headings in the chapter are level 2 and below. All chapter files should
-contain the VIM suffix (which is a codingstd for all of the Parrot repo).
Deleted: branches/pmc_pct/docs/book/appa_glossary.pod
==============================================================================
--- branches/pmc_pct/docs/book/appa_glossary.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,321 +0,0 @@
-=pod
-
-=head1 Glossary
-
-Short descriptions of words and acronyms found in Parrot development.
-
-=over 4
-
-=item AST
-
-Abstract Syntax Tree: a data structure typically generated by a language
-parser.
-
-=item Continuations
-
-Think of continuations as an execution "context". This context includes
-everything local to that execution path, not just the stack. It is a snapshot
-in time (minus global variables). While it is similar to C's C<setjmp> (taking
-the continuation)/C<longjmp> (invoking the continuation), C<longjmp>'ing only
-works "down" the stack; jumping "up" the stack (ie, back to a frame that has
-returned) is bad. Continuations can work either way.
-
-We can do two important things with continuations:
-
-=over 4
-
-=item 1
-
-Create and pass a continuation object to a subroutine, which may recursively
-pass that object up the call chain until, at some point, the continuation can
-be called/executed to handle the final computation or return value. This is
-pretty much tail recursion.
-
-=item 2
-
-Continuations can be taken at an arbitrary call depth, freezing the call chain
-(context) at that point in time. If we save that continuation object into a
-variable, we can later reinstate the complete context by its "handle". This
-allows neat things like backtracking that aren't easily done in conventional
-stacked languages, such as C. Since continuations represent "branches" in
-context, it requires an environment that uses some combination of heap-based
-stacks, stack trees and/or stack copying.
-
-=back
-
-It is common in a system that supports continuations to implement
-L<co-routines|"Co-Routines"> on top of them.
-
-A continuation is a sort of super-closure. When you take a continuation, it
-makes a note of the current call stack and lexical scratchpads, along with the
-current location in the code. When you invoke a continuation, the system drops
-what it's doing, puts the call stack and scratchpads back, and jumps to the
-execution point you were at when the continuation was taken. It is, in effect,
-like you never left that point in your code.
-
-Note that, like with closures, it only puts the B<scratchpads> back in scope -
-it doesn't do anything with the values in the variables that are in those
-scratchpads.
-
-=item Co-Routines
-
-Co-routines are virtually identical to normal subroutines, except while
-subroutines always execute from their starting instruction to where they
-return, co-routines may suspend themselves (or be suspended asynchronously if
-the language permits) and resume at that point later. We can implement things
-like "factories" with co-routines. If the co-routine never returns, every time
-we call it, we "resume" the routine.
-
-A co-routine is a subroutine that can stop in the middle, and start back up
-later at the point you stopped. For example:
-
- sub sample : coroutine {
- print "A\n";
- yield;
- print "B\n";
- return;
- }
-
- sample();
- print "Foo!\n";
- sample();
-
-will print
-
- A
- Foo!
- B
-
-Basically, the C<yield> keyword says, "Stop here, but the next time we're
-called, pick up at the next statement." If you return from a co-routine, the
-next invocation starts back at the beginning. Co-routines remember all their
-state, local variables, and suchlike things.
-
-=item COW
-
-Copy On Write: a technique that copies strings lazily.
-
-If you have a string A, and make a copy of it to get string B, the two strings
-should be identical, at least to start. With COW, they are, because string A
-and string B aren't actually two separate strings - they're the same string,
-marked COW. If either string A or string B are changed, the system notes it and
-only at that point does it make a copy of the string data and change it.
-
-If the program never actually changes the string - something that's fairly
-common - the program need never make a copy, saving both memory and time.
-
-=item destruction
-
-Destruction is low level memory clean up, such as calling C<free> on
-C<malloc>ed memory. This happens after L<"finalization">, and if resources are
-adequate, may only happen as a side effect of program exit.
-
-=item DOD
-
-Dead Object Detection: the process of sweeping through all the objects,
-variables, and whatnot inside of Parrot, and deciding which ones are in use and
-which ones aren't. The ones that aren't in use are then freed up for later
-reuse. (After they're destroyed, if active destruction is warranted.)
-
-See also: L<"GC">
-
-=item finalization
-
-Finalization is high-level, user visible cleanup of objects, such as closing an
-associated DB handle. Finalization reduces active objects down to passive
-blocks of memory, but does not actually reclaim that memory. Memory is
-reclaimed by the related L<"destruction"> operation, as and when necessary.
-
-=item GC
-
-Garbage Collection: the process of sweeping through all the active objects,
-variables, and structures, marking the memory they're using as in use, and all
-other memory is freed up for later reuse.
-
-Garbage Collection and Dead Object Detection are separate in Parrot, since we
-generally chew through memory segments faster than we chew through objects.
-(This is a characteristic peculiar to Perl and other languages that do string
-processing. Other languages chew through objects faster than memory)
-
-See also: L<"DOD">
-
-=item HLL
-
-High-Level Language; Any of the languages that target the parrot virtual
-machine.
-
-=item ICU
-
-International Components for Unicode
-
-ICU is a C and C++ library that provides support for Unicode on a variety of
-platforms. It was distributed with parrot at one time, but current releases
-require you to get your own copy.
-
-L<http://oss.software.ibm.com/icu/index.html>
-
-=item IMCC
-
-Intermediate Code Compiler: the component of parrot that compiles PASM
-and PIR into bytecode.
-
-See also L<"PIR">.
-
-=item MRO
-
-Method resolution order
-
-=item NCI
-
-Native Call Interface: parrot's interface to native "C" libraries,
-without a C-compiler.
-
-=item NQP
-
-Not Quite Perl (6): designed to be a very small compiler for
-quickly generating PIR routines to create transformers for Parrot (especially
-HLL compilers).
-
-See also L<"PCT">.
-
-=item Packfile
-
-Another name for a PBC file, due to the names used for data structures in one
-of the early implementations in Perl 5.
-
-=item PAST
-
-Acronym for Parrot Abstract Syntax Tree, a set of classes that represent an
-abstract syntax tree.
-
-See also L<"PCT">.
-
-=item PBC
-
-Parrot Bytecode. The name for the "executable" files that can be passed to the
-Parrot interpreter for immediate execution (although PASM and IMC files can be
-executed directly, too).
-
-See also L<"Packfile">.
-
-=item PCT
-
-Parrot Compiler Toolkit: a complete set of tools and libraries
-that are designed to create compilers targeting Parrot. The principal
-components of PCT are PGE, PCT::HLLCompiler (a compiler driver), PAST classes,
-POST classes, PCT::Grammar (a base class for PGE grammars).
-
-In the ideal case, a language can be implemented by providing its parser
-(using Perl 6 rules) which is generated by PGE, and providing a module written
-in NQP that contains the I<actions> that are to be invoked during the parse.
-These actions can then create the appropriate PAST nodes. A PAST to PIR
-transformation already exists. Depending on the language, other phases can
-be added, or overridden (for instance, the PAST to PIR transformation).
-
-=item PIRC
-
-Acronym for PIR Compiler, a PIR compiler currently under development.
-The purpose is to reimplement the PIR language, which is currently
-implemented by IMCC. PIRC is written using a Bison and Flex grammar
-specification.
-
-=item PDD
-
-Parrot Design Document: documents that describe the features parrot must
-implement.
-
-=item PGE
-
-Parrot Grammar Engine.
-
-See also L<"PCT">.
-
-=item PIR
-
-Parrot Intermediate Representation: A medium-level assembly language for Parrot
-that hides messy details like register allocation so language compiler writers
-who target Parrot don't have to roll their own. Files have the
-extension C<.pir>.
-
-=item PMC
-
-Polymorphic Container: these classes are the primitives that
-HLLs use to represent their fundamental types, such as Perl's
-scalar values.
-
-=item Pod
-
-The preferred format for all kinds of documentation in Parrot.
-
-=item POST
-
-Parrot Opcode Syntax Tree: A set of classes that represent opcodes.
-
-See also L<"PCT">.
-
-=item Predereferencing
-
-=for comment
-XXX This section needs to be edited down.
-
-A bytecode transformation technique which reduces the amount of pointer
-dereferencing done in the inner loop of the interpreter by pre-converting
-opcode numbers into pointers to their opfuncs, and also converting the register
-numbers and constant numbers in the arguments to the ops into pointers.
-
-The original implementation by Gregor Purdy was posted on 2001-12-11. On one
-test system, it resulted in a 22% speed increase on a test program with a tight
-inner loop.
-
-L<http://archive.develooper.com/perl6-internals@perl.org/msg06941.html>
-
-On 2001-12-18, predereferencing got a speed boost (to about 47% faster than the
-regular DO_OP inner loop -- without compiler optimizations turned on). This was
-due to an off-list (actually over lunch) suggestion by John Kennedy that
-instead of pre-initializing the new copy of the bytecode with NULL pointers, we
-pre-initialize it with pointers to a pseudo-opfunc that does the
-predereferencing whenever it is encountered.
-
-On 2002-04-11, Jason Gloudon suggested combining aspects of the Computed Goto
-Core and the Prederef[erencing] Core.
-
-L<http://archive.develooper.com/perl6-internals@perl.org/msg07064.html>
-
-The week of 2003-02-09, Leopold Toetsch combined Computed Goto and
-Predereferencing to produce the CGP core.
-
-L<http://dev.perl.org/perl6/list-summaries/2003/p6summary.2003-02-09.html#Week_of_the_alternative_runloops>
-
-Later, on 2003-02-14, Leopold Totsch and Nicholas Clark combined the JIT and
-the Computed Goto Prederef cores to great effect.
-
-L<http://www.perl.com/pub/a/2003/02/p6pdigest/20030216.html>
-
-=item Run Core
-
-aka run loop, aka runcore. The way Parrot executes PBCs.
-See L<running.pod> for a list of available runcores, and how to tell
-parrot which one to use.
-
-=item TGE
-
-Tree Grammar Engine: a tool that can be used to generate tree transformers.
-
-=item vtable
-
-A table of operations attached to some data types, such as PMCs and strings.
-Vtables are used to avoid using switches or long C<if> chains to handle
-different data types. They're similar to method calls, except that their names
-are pre-selected, and there is no direct way to invoke them from PIR.
-
-=item Warnock's Dilemma
-
-The dilemma you face when posting a message to a public forum about something
-and not even getting an acknowledgment of its existence. This leaves you
-wondering if your problem is unimportant or previously addressed, if everyone's
-waiting on someone else to answer you, or if maybe your mail never actually
-made it to anyone else in the forum.
-
-=back
-
-=cut
Deleted: branches/pmc_pct/docs/book/appb_patch_submission.pod
==============================================================================
--- branches/pmc_pct/docs/book/appb_patch_submission.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,138 +0,0 @@
-=pod
-
-=head1 Patch submission
-
-X<Parrot;patch submission>
-Parrot development proceeds through a continuous stream of patches.
-Patches are the currency of exchange in the project--the unit of
-work. Patches can fix bugs, add features, modify capabilities,
-remove cruft, and improve the suite of tests and the project
-documentation. If something needs to change, it will typically require
-the submission of a new patch.
-
-While anyone is free to submit a patch, only a small number of people have
-the ability to apply patches to the central Parrot repository.
-These people are called I<committers>. By allowing all people to get
-involved through patch submission and testing, the project can harness
-the efforts of a large group but still keep the same high quality
-as a small group of experienced developers.
-
-Every submitted patch is automatically forwarded to the p2 list where
-it's subject to peer review. Small patches typically spark little debate,
-and can be well-tested on many platforms before being committed to the
-repository. Patches tend to be small modular changes, which makes for
-easy testing and evaluation. Occasionally a large feature such as an entire
-language implementation is submitted in a single patch, but these are the
-exceptions.
-
-Submitting a patch is fairly straightforward. You create a file that
-lists all your changes, a diff or a patch, and email it to the ticket
-tracking system at U<parrotbug at parrotcode.org>. It's important to make
-sure your patch and your email have descriptive titles so that the
-committers and testers have a better idea about what it does. The body of
-your email should also include a good description about what you changed
-and why.
-
-It's important that you create your patches from a checked-out subversion
-repository, not from a tarball or a snapshot. This way, you can ensure
-that your diff is made against the latest version of the files. If you patch
-an old version, the problem may have already been resolved! Make sure
-the paths listed in the patch match those in the repository. There are two
-methods of creating patches that will do this for you. You can make changes
-directly in your checked-out copy of the subversion repository and
-then create diffs using the command C<svn diff>. Alternatively, you can
-make a copy of the repository and then create diffs between the two
-copies with the C<diff -u> command:
-
- diff -u parrot/README parrot_changed/README
-
-Either method is fine, and both are equally common on p2. Your
-working style and the types of changes you make--small and modular
-versus large and sweeping--will influence which method you choose.
-
-Next, when you're making changes, take some extra time to consider how
-your patch affects the rest of the system. If your patch adds a new
-file, patch the main F<MANIFEST> file to include it. If you add a new
-feature, make sure to write tests for it. If you fix a bug, add a test
-to prove that it's fixed. See "Writing Tests" in Chapter
-9 for more on writing tests for Parrot. Tests are very important for
-Parrot development, and writing good tests is a valuable skill for
-developers to have. Before you submit a patch always recompile the
-system yourself with the patch included and run all tests to prove that
-it works. You can build and test Parrot completely by running the
-following commands:
-
- make clean
- perl Configure.pl
- make
- make test
-
-Consider the people who will review and apply your patch, and try
-to make their jobs easier. Patch filenames should be as descriptive as
-possible: F<fix_readme_aardvark_typo.patch> is far better than
-F<README.patch>. An attached file is better than a diff pasted into an
-email, because it can be applied without manual editing. The
-conventional extension for patch files is F<.patch>.
-
-In the email message, always start the subject with "[PATCH]", and
-make the subject as clear as possible: "[PATCH] misspelled aardvark in
-main README file" is better than "[PATCH] typo". The body of the
-message should clearly explain what the patch is supposed to do and
-why you're submitting it. Make a note if you're adding or deleting
-files so they won't be missed.
-
-Here is a good example of a patch submission using the subversion diff
-method (an actual patch from p2). It's short, sticks to the point, and
-clearly expresses the problem and the solution. The patch filename and
-the subject of the message are both descriptive:
-
-=for author
-
-Possible alternates: ticket #23501, #24053 (not from top level)
-
-=end for
-
- Subject: [PATCH] Pointers in List_chunk not initialized
- From: Bruce Gray
-
- On Win32, these tests are segfaulting due to invalid
- pointers in List_chunk structs:
- t/op/string.t 97-98
- t/pmc/intlist.t 3-4
- t/pmc/pmc.t 80
-
- The problem is caused by list.c/allocate_chunk not
- initializing the pointers. This patch corrects the problem.
-
- --
- Hope this helps,
- Bruce Gray
-
-With the attached file F<list_chunk_initialize.patch>:
-
-
- Index: list.c
- =========================================
- RCS file: /cvs/public/parrot/list.c,v
- retrieving revision 1.23
- diff -u -r1.23 list.c
- --- list.c 27 Dec 2002 09:33:11 -0000 1.23
- +++ list.c 28 Dec 2002 03:37:35 -0000
- @@ -187,6 +187,10 @@
- Parrot_block_GC_sweep(interpreter);
- chunk = (List_chunk *)new_bufferlike_header(interpreter, sizeof(*chunk));
- chunk->items = items;
- + chunk->n_chunks = 0;
- + chunk->n_items = 0;
- + chunk->next = NULL;
- + chunk->prev = NULL;
- Parrot_allocate_zeroed(interpreter, (Buffer *)chunk, size);
- Parrot_unblock_GC_mark(interpreter);
- Parrot_unblock_GC_sweep(interpreter);
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/appc_command_line_options.pod
==============================================================================
--- branches/pmc_pct/docs/book/appc_command_line_options.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,340 +0,0 @@
-=pod
-
-=head1 Command-Line Options
-
-Z<CHP-13-SECT-4>
-
-X<command-line options (Parrot)>
-X<Parrot;command-line options>
-X<running.pod file>
-Since Parrot is both an assembler and a bytecode interpreter, it
-has options to control both behaviors. Some options may have changed
-by the time you read this, especially options related to debugging and
-optimization. The document F<imcc/docs/running.pod> should
-have the latest details. Or just run F<parrot --help>.
-
-=head2 General Usage
-
-Z<CHP-13-SECT-4.1>
-
- parrot [options] file [arguments]
-
-The R<file> is either an F<.pir> or F<.pasm> source file or a
-Parrot bytecode file. Parrot creates an C<Array> object to hold the
-command-line R<arguments> and stores it in C<P5> on program start.
-
-=head2 Assembler Options
-
-Z<CHP-13-SECT-4.2>
-
-=over 4
-
-=item -a, --pasm
-
-X<Parrot;assembler options>
-Assume PASM input on C<stdin>. When Parrot runs a source file with a
-F<.pasm> extension, it parses the file as pure PASM code. This switch
-turns on PASM parsing (instead of the default PIR parsing) when a
-source file is read from C<stdin>.
-
-=item -c,--pbc
-
-Assume PBC file on C<stdin>. When Parrot runs a bytecode file with a
-F<.pbc> extension, it immediately executes the file. This option tells
-Parrot to immediately execute a bytecode file piped in on C<stdin>.
-
-=item -d,--debug [R<hexbits>]
-
-Turn on debugging output. The C<-d> switch takes an optional argument,
-which is a hex value of debug bits. The individual bits are shown in
-Table 11-3. When R<hexbits> isn't specified,
-the default debugging level is 0001. If R<hexbits> is separated
-from the C<-d> switch by whitespace, it has to start with a number.
-
-=begin table picture Debug bits
-
-Z<CHP-13-TABLE-3>
-
-=headrow
-
-=row
-
-=cell Description
-
-=cell Debug bit
-
-=bodyrows
-
-=row
-
-=cell DEBUG_PARROT
-
-=cell 0001
-
-=row
-
-=cell DEBUG_LEXER
-
-=cell 0002
-
-=row
-
-=cell DEBUG_PARSER
-
-=cell 0004
-
-=row
-
-=cell DEBUG_IMC
-
-=cell 0008
-
-=row
-
-=cell DEBUG_CFG
-
-=cell 0010
-
-=row
-
-=cell DEBUG_OPT1
-
-=cell 0020
-
-=row
-
-=cell DEBUG_OPT2
-
-=cell 0040
-
-=row
-
-=cell DEBUG_PBC
-
-=cell 1000
-
-=row
-
-=cell DEBUG_PBC_CONST
-
-=cell 2000
-
-=row
-
-=cell DEBUG_PBC_FIXUP
-
-=cell 4000
-
-=end table
-
-X<Parrot;debugging bits>
-X<debugging bits (Parrot)>
-To produce a huge output on C<stderr>, turn on all the debugging bits:
-
- $ parrot -d 0ffff ...
-
-
-=item --help-debug
-
-Show debug option bits.
-
-=item -h,--help
-
-Print a short summary of options to C<stdout> and exit.
-
-=item -o R<outputfile>
-
-Act like an assembler. With this switch Parrot won't run code unless
-it's combined with the C<-r> switch. If the name of R<outputfile> ends
-with a F<.pbc> extension, Parrot writes a Parrot bytecode file. If
-R<outputfile> ends with a F<.pasm> extension, Parrot writes a PASM
-source file, even if the input file was also PASM. This can be handy
-to check various optimizations when you run Parrot with the C<-Op>
-switch.
-
-If the extension is F<.o> or equivalent, Parrot generates an object
-file from the JITed program code, which can be used to create a
-standalone executable program. This isn't available on all platforms
-yet; see F<PLATFORMS> for which platforms support this.
-
-=item -r,--run-pbc
-
-Immediately execute bytecode. This is the default unless C<-o> is
-present. The combination of C<-r> C<-o> C<output.pbc> writes a
-bytecode file and executes the generated PBC.
-
-=item -v,--verbose
-
-One C<-v> switch (C<imcc> C<-v>) shows which files are worked on and
-prints a summary of register usage and optimization statistics. Two
-C<-v> switches (C<imcc> C<-v> C<-v>) also prints a line for each
-individual processing step.
-
-=item -y,--yydebug
-
-Turn on C<yydebug> for F<yacc>/F<bison>.
-
-=item -E,--pre-process-only
-
-Show output of macro expansions and quit.
-
-=item -V,--version
-
-Print the program version to C<stdout> and exit.
-
-=item -Ox
-
-Turn on optimizations. The flags currently implemented are shown in
-Table 11-4.
-
-X<Parrot;optimizations>
-X<optimizations (Parrot)>
-
-=begin table picture Optimizations
-
-Z<CHP-13-TABLE-4>
-
-=headrow
-
-=row
-
-=cell Flag
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<-O0>
-
-=cell No optimization (default).
-
-=row
-
-=cell C<-O1>
-
-=cell Optimizations without life info (e.g. branches and constants).
-
-=row
-
-=cell C<-O2>
-
-=cell Optimizations with life info.
-
-=row
-
-=cell C<-Oc>
-
-=cell Optimize function call sequence.
-
-=row
-
-=cell C<-Op>
-
-=cell Rearrange PASM registers with the most-used first.
-
-=end table
-
-=back
-
-=head2 Runcore Options
-
-Z<CHP-13-SECT-4.3>
-
-X<Parrot;bytecode interpreter options>
-X<bytecode interpreter options (Parrot)>
-X<computed goto core>
-X<fast core>
-The interpreter options are mainly for selecting which run-time core to
-use for interpreting bytecode. The current default is the I<computed
-goto core> if it's available. Otherwise the I<fast core> is used.
-
-=over 4
-
-=item -R slow
-
-Run with the I<slow core>
-
-=item -R bounds
-
-Activate bounds checking. This also runs with the I<slow core> as a
-side effect.
-
-=item -R fast
-
-Run with the I<fast core>.
-
-=item -R cgoto
-
-Run the I<computed goto core> (CGoto).
-
-=item -R jit
-
-Run with the I<JIT core> if available.
-
-=item -R cgp
-
-Run with the I<CGoto-Prederefed> core.
-
-=item -R cgp-jit
-
-Run with the I<CGoto-Prederefed with jit> core.
-
-=item -R switch
-
-Run with the I<Switched core>.
-
-=item -R switch-jit
-
-Run with the I<Switched core with jit>.
-
-=item -R exec
-
-Run with the I<exec core>
-(uses JIT at compile time to generate native code)
-
-=item -R gcdebug
-
-Performs a full GC run before every op dispatch
-(good for debugging GC problems)
-
-=item -p,--profile
-
-Activate profiling. This prints a summary of opcode usage and
-execution times after the program stops. It also runs within the
-I<slow core>.
-
-=item -t,--trace
-
-Trace execution. This also turns on the I<slow core>.
-
-=item -w,--warnings
-
-Turn on warnings.
-
-=item -G,--no-gc
-
-Turn off GC. This is for debugging only.
-
-=item -.,--wait
-
-Wait for a keypress before running.
-
-=item --leak-test,--destroy-at-end
-
-Cleanup up allocated memory when the final interpreter is destroyed.
-C<Parrot> destroys created interpreters (e.g. threads) on exit but
-doesn't normally free all memory for the last terminating interpreter,
-since the operating system will do this anyway. This can create false
-positives when C<Parrot> is run with a memory leak detector. To prevent
-this, use this option.
-
-=back
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/appd_build_options.pod
==============================================================================
--- branches/pmc_pct/docs/book/appd_build_options.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,93 +0,0 @@
-=pod
-
-=head1 Build Requirements
-
-There are a number of requirements for building Parrot from source, and a
-number of optional libraries and components that can be used to extend its
-capabilities. None of these requirements or optional components are necessary
-unless you are building Parrot from the source code.
-
-=over 4
-
-=item * C Compiler
-
-Parrot can be built with a number of C compilers. Parrot is written using the
-C89 standard, and the Parrot project officially supports the most recent
-C89 compiler on major systems, including the most recent versions of Microsoft
-C Compiler and the GNU Compiler Collection (GCC).
-
-=item * make
-
-Make is a program to manage and automate the build process. Unix-based systems
-will typically have access to the C<make> command as part of the normal
-development tools. Windows systems can get the C<nmake> utility to perform the
-same task.
-
-=item * Subversion
-
-Subversion is the source control system that is used by the Parrot project.
-You need subversion to checkout the latest version of the source code. You can
-get subversion at L<http://subversion.tigris.org>, or through one of the
-common packaging systems.
-
-=item * bison and flex
-
-Bison and Flex are used to create the lexical analyzer and parser components
-for the PIR compilers IMCC and PIRC. These are not necessary most of the time
-unless you are planning to hack on IMCC and PIRC directly.
-
-=item * ICU
-
-ICU is a library for handling and manipulating Unicode text strings. Without
-ICU libraries installed, you wont be able to use Unicode with your built
-Parrot.
-
-=item * GMP
-
-GMP is a mathematics library for manipulating arbitrary precision and
-arbitrary size numbers. GMP is an optional library used by the BigInt
-and BigNum PMCs.
-
-=item * Readline
-
-The readline library allows some advanced behaviors on the command line such
-as command history.
-
-=item * PCRE
-
-PCRE is a library that provides access to the Perl 5 regular expression syntax.
-In order to use these regular expressions, you will want to install PCRE. To
-do that on Linux you use the command:
-
- sudo apt-get install libpcre3-dev
-
-=item * GDBM
-
-=item * PQ
-
-=item * GLUT
-
-GLUT is an interface to the OpenGL API. It enables programs running on Parrot
-to have access to 3D graphics. To get GLUT on Linux systems you can use the
-command:
-
- sudo apt-get install libglut3-dev
-
-=back
-
-In addition to these build requirements listed above, there are a number
-of Perl libraries needed to enable the full set of tests and testing
-facilities, and to generate all the necessary documentation.
-
-To get the Perl packages for Parrot, you can use the commands:
-
- sudo cpan Test::Base Test::Pod Test::Pod::Coverage Pod::Spell
- sudo cpan File::HomeDir File::Which Readonly Regexp::Parser
- sudo cpan Perl::Critic Perl::Critic::Bangs Test::Perl::Critic
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/appe_source_code.pod
==============================================================================
--- branches/pmc_pct/docs/book/appe_source_code.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,72 +0,0 @@
-=pod
-
-=head3 Use the source
-
-X<Parrot;source code>
-The second step to participating in Parrot development is to get a
-copy of the source code. If you just want to try it out--experiment
-with a few features and see how it feels--the best option is to
-download the most recent point release for your system. Point releases
-are usually packaged up for easy download and install for various
-platforms, including Windows, Debian, and Redhat. Point releases are
-available from U<http://www.parrot.org/download>.
-
-If you plan to get involved in development, you'll want to check out
-the source from the subversion repository directly. Anyone can get
-anonymous access to read the files and download a working copy to
-explore and test. For commit access, volunteers need a
-U<https://trac.parrot.org> username, and need to be approved by a
-Metacommitter. To download the most recent version from SVN, type this
-command into your terminal N<This is for Linux users, on Mac or
-Windows systems, follow the instructions from your SVN client>:
-
- svn co https://svn.parrot.org/parrot/trunk parrot
-
-There's also a web interface for viewing files in the repository at
-U<http://svn.parrot.org/parrot/>.
-
-The repository is large and complex, so it's worth taking a little bit
-of time to explore. The code changes constantly, but most files and
-functions have informative descriptions to help keep track of things.
-
-The most important top-level directory is F<docs/>. The content isn't
-always up to date, but it is a good place to start. F<parrot.pod>
-provides a quick overview of what's in each documentation file. If you're
-a capable writer and know a thing or two about how Parrot works, the
-documentation is a great place to start contributing. This book that
-you're reading right now was created in F<docs/book/> by ordinary
-contributors. Most other documentation files found here are parsed and
-converted to HTML for display at U<http://www.parrot.org>.
-
-There are a number of existing language implementations for Parrot:
-Perl 6, Python ("Pynie"), Ruby ("Cardinal"), PHP ("Pipp"), Lisp, Lua,
-Tcl ("partcl"), WMLScript, Forth, Scheme, Befunge, BASIC, and many
-others. These language compilers are in various stages of partial
-completion. The page L<https://trac.parrot.org/parrot/wiki/Languages>
-provides meta information on these languages and where to find them.
-If you have a language you're particularly interested to see implemented
-on Parrot, you can see how far along the effort is, or you can start the
-work to implement it yourself. We'll talk more about creating new
-compilers in Chapter 10: High-Level Languages, if you're interested.
-
-The F<lib/> directory contains Perl 5 classes currently used in
-developing, building, and testing Parrot. The F<src/pmc/> directory
-contains the C source code for Parrot classes (PMCs, which you'll read
-more about in Chapter 11).
-
-Most Parrot development happens in F<src/> for the C source code, and
-F<include/parrot/> for the C development header files.
-
-Libraries for use by programs running on Parrot are found in F<runtime/>.
-
-The F<examples/> directory contains some example Parrot PIR and Assembly
-code, as well as benchmarks. More discussions about these topics will be
-found in Chapter 3, Chapter 5, and Chapter 7
-respectively.
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch01_introduction.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch01_introduction.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,215 +0,0 @@
-=pod
-
-=head1 Introduction
-
-Parrot is a language-neutral virtual machine for dynamic languages such as
-Ruby, Python, PHP, and Perl. It hosts a powerful suite of compiler tools
-tailored to dynamic languages and a next generation regular expression engine.
-Its architecture is fundamentally different than existing virtual machines such
-as the JVM or CLR, with optimizations for dynamic languages included, a
-register-based system rather than stack-based, and the use of continuations as
-the core means of flow control.
-
-The name "Parrot" was inspired by Monty Python's Parrot sketch. As an April
-Fools' Day joke in 2001, Simon Cozens published "Programming Parrot", a
-fictional interview between Guido van Rossum and Larry Wall detailing their
-plans to merge Python and Perl into a new language called Parrot
-(U<http://www.perl.com/pub/a/2001/04/01/parrot.htm>).
-
-=head2 Parrot Resources
-
-The starting point for all things related to Parrot is the main website
-U<http://www.parrot.org/>. The site lists additional resources, well as recent
-news and information about the project and the Parrot Foundation, which holds
-the copyright over Parrot and helps guide development and the community.
-
-=head3 Documentation
-
-Parrot includes extensive documentation in the distribution. The full
-documentation for the latest release is available online at
-U<http://docs.parrot.org/>.
-
-=head3 Mailing Lists
-
-X<parrot-dev (Parrot mailing list)>
-X<mailing lists>
-
-The primary mailing list for Parrot is I<parrot-dev at lists.parrot.org>. If
-you're interested in getting involved in development, you may also want to
-follow the I<parrot-commits> and I<parrot-tickets> lists. Information on all
-the Parrot mailing lists and subscription forms for each is available at
-U<http://lists.parrot.org/mailman/listinfo>.
-
-The archives for I<parrot-dev> are also available on Google Groups at
-U<http://groups.google.com/group/parrot-dev> and via NNTP at
-U<nntp://news.gmane.org/gmane.comp.compilers.parrot.devel>.
-
-=head3 IRC
-
-X<#parrot (Parrot IRC channel)>
-X<IRC channel (#parrot)>
-
-Parrot developers and users congregate on IRC at C<#parrot> on the
-U<irc://irc.parrot.org> server. It's a good place to get real-time answers to
-questions or see how things are progressing.
-
-=head3 Issue Tracking & Wiki
-
-X<trac.parrot.org website>
-X<issue tracking (trac.parrot.org)>
-
-Parrot developers track issues with a Trac site at U<https://trac.parrot.org/>.
-Users can submit new tickets and track the status of existing tickets. The
-site also includes a wiki used in project development, a source code browser,
-and the project roadmap.
-
-=head2 Parrot Development
-
-X<development cycles>
-
-Parrot's first release occurred in September 2001. It reached 1.0 in March
-2009. The Parrot project makes releases on the third Tuesday of each month. Two
-releases a year E<mdash> occuring every January and July E<mdash> are
-"supported" releases intended for production use. The other ten releases are
-development releases for language implementers and testers.
-
-Development proceeds in cycles around releases. Activity just before a release
-focuses on closing tickets, fixing bugs, reviewing documentation, and preparing
-for the release. Immediately after the release, larger changes occur, such as
-merging branches, adding large features, or removing deprecated features. This
-allows developers to ensure that changes have sufficient testing time before
-the next release. Releases also encourage feedback as casual users and testers
-explore the newest versions.
-
-=head2 The Parrot Team
-
-Parrot developers fulfill several rules according to their skills and interests.
-
-=over 4
-
-=item Architect
-
-X<architect role>
-
-The architect has primary responsibility for setting the overall direction of
-the project, facilitating team communication, and explaining and evaluating
-architectural issues. The architect makes design decisions and documents them
-in Parrot Design Documents, and oversees design and documentation work
-delegated to other members of the team to provide a coherent vision across the
-project. The architect also works with the release managers to develop and
-maintain the release schedule. Allison Randal currently leads the Parrot
-project as architect.
-
-=item Release Managers
-
-X<release manager role>
-
-Release managers manage and produce monthly releases according to the release
-schedule. Parrot has multiple release managers who rotate the responsibility
-for each monthly release. The release managers develop and maintain the release
-schedule jointly with the project architect.
-
-=item Metacommitter
-
-X<metacommitter role>
-
-Metacommitters manage commit access to the Parrot repository. Once a
-contributor is selected for commit access, a metacommitter gives the new
-committer access to the SVN repository and the bugtracker. The architect is a
-metacommitter, but other team members also hold this role.
-
-=item Committer
-
-X<committer role>
-
-Contributors who submit numerous, high-quality patches may be considered to
-become a committer. Committers have commit access to the full Parrot
-repository, though they often specialize on particular parts of the project.
-Contributors may be considered for commit access either by being nominated by
-another committer, or by requesting it.
-
-=item Core Developer
-
-X<core developer role>
-
-Core developers develop and maintain core subsystems such as the I/O
-subsystem, the exceptions system, or the concurrency scheduler.
-
-=item Compiler Developer
-
-X<compiler developer role>
-
-Compiler developers develop and maintain one or more Parrot front-end
-compilers such as IMCC, PIRC, PGE and TGE.
-
-=item High-Level Language Developer
-
-X<HLL developer role>
-
-Developers who work on any of the high-level languages that target
-ParrotE<mdash>such as Lua, Perl, PHP, Python, Ruby, or TclE<mdash>are
-high-level language developers. The Parrot repository includes a few example
-languages. A full list of languages is available at
-U<https://trac.parrot.org/parrot/wiki/Languages>.
-
-=item Build Manager
-
-X<build manager role>
-
-Build managers maintain and extend configuration and build subsystems.
-They review smoke reports and attempt to extend platform support.
-
-=item Tester
-
-X<tester role>
-
-Testers develop, maintain, and extend the core test suite coverage and testing
-tools. Testers are also responsible for testing goals, including complete
-coverage of core components on targeted platforms.
-
-=item Patch Monsters
-
-X<patch monster role>
-
-Hackers and developers submit patches to Parrot every day, and it takes a keen
-eye and a steady hand to review and apply them all. Patch monsters check
-patches for conformance with coding standards and desirability of features,
-rework them as necessary, verify that the patches work as desired, and apply
-them.
-
-=item Cage Cleaners
-
-X<cage cleaner role>
-
-The cage cleaners ensure that development follows the project's coding
-standards, documentation is complete and accurate, all tests function properly,
-and new users have accurate and comprehensive coding examples. A special class
-of Trac tickets is available for these tasks. Cage cleaning tasks run the
-gamut from entry-level to advanced; this is a good entry point for new users
-to work on Parrot.
-
-=item General Contributor
-
-X<contributor role>
-
-Contributors write code or documentation, report bugs, take part in email or
-online conversations, or contribute to the project in other ways. All volunteer
-contributions are appreciated.
-
-=back
-
-=head2 Licensing
-
-X<license>
-
-The Parrot foundation supports the Parrot development community and holds
-trademarks and copyrights to Parrot. The project is available under the
-Artistic License 2.0, allowing free use in commercial and open source/free
-software contexts.
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch02_getting_started.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch02_getting_started.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,182 +0,0 @@
-=pod
-
-=head1 Getting Started
-
-Before you can use Parrot, you have to get it running on your machine.
-
-=head2 Installing Parrot
-
-The simplest way to install Parrot is to use a pre-compiled binary for your
-operating system or distribution. Packages are available for many packaging
-systems, including Debian, Ubuntu, Fedora, Mandriva, FreeBSD, Cygwin, and
-MacPorts. The Parrot website lists all known packages at
-U<http://www.parrot.org/download>. A binary installer for Windows is also
-available at U<http://parrotwin32.sourceforge.net/>.
-
-If packages aren't available on your system, download the latest supported
-release from U<http://www.parrot.org/release/supported>.
-
-You need a C compiler and a make utility to build Parrot from source code --
-usually C<gcc> and C<make>, but Parrot can build with standard compiler
-toolchains on different operating systems. Perl 5.8 is also a prerequiste for
-configuring and building Parrot.
-
-If you have these dependencies installed, build the core virtual machine and
-compiler toolkit and run the standard test suite with the commands:
-
- $ B<perl Configure.pl>
- $ B<make>
- $ B<make test>
-
-By default, Parrot installs to directories F<bin/>, C<lib/>, et cetera under
-the prefix F</usr/local>. If you have privileges to write to these
-directories, install Parrot with:
-
- $ B<make install>
-
-To install Parrot beneath a different prefix, use the C<--prefix> option to
-C<Configure.pl>:
-
- $ B<perl Configure.pl --prefix=/home/me/parrot>
-
-If you intend to I<develop> -- not just I<use> -- a language on Parrot, install
-the Parrot developer tools as well:
-
- $ B<make install-dev>
-
-=head2 Running Parrot
-
-Once you've installed Parrot, run it. Create a test file called F<news.pasm>.
-C<.pasm> files contain Parrot Assembly Language (PASM) instructions; this is a
-low-level language native to the Parrot virtual machine.
-
-=begin PASM
-
- say "Here is the news for Parrots."
- end
-
-=end PASM
-
-Now run this file with:
-
- $ B<parrot news.pasm>
-
-which will print:
-
- Here is the news for Parrots.
-
-=head2 Running a Language on Parrot
-
-Next, try out one of Parrot's high-level languages. Create a test file
-called F<more_news.nqp>:
-
- say "No parrots were involved in an accident on the M1 today..."
-
-Then run it as:
-
- $ nqp more_news.nqp
-
-which will print:
-
- No parrots were involved in an accident on the M1 today...
-
-=head2 What Next?
-
-This book describes Parrot in terms of tasks it supports. You may pick and
-choose chapters based on your area of interest:
-
-=over 4
-
-=item Chapter 3, I<Parrot Intermediate Representation>
-
-Parrot Intermediate Representation (PIR) is a mid-level language native to the
-Parrot virtual machine s commonly used for writing extensions and tools for
-Parrot.
-
-=item Chapter 4, I<Compiler Tools>
-
-The Parrot Compiler Toolkit (PCT) provides a common infrastructure and
-utilities for implementing languages on Parrot.
-
-=item Chapter 5, I<Grammar Engine>
-
-The Parrot Grammar Engine (PGE) is a powerful regular expression engine and
-recursive descent parser. PGE is part of the compiler tools; understanding PGE
-is essential to implementing a language on Parrot.
-
-=item Chapter 6, I<Grammar Actions>
-
-NQP (Not Quite Perl) is a lightweight language loosely inspired by Perl 6. NQP
-is part of the compiler tools used for transforming a Parrot-hosted language
-into instructions for Parrot to execute.
-
-=item Chapter 7, I<Dynamic PMCs>
-
-=for author
-
-This chapter suggests the need for a chapter on core PMCs. Alternately, this
-chapter could cover PMCs in general and dynpmcs as a special case of PMCs.
-
-=end for
-
-Parrot allows language developers to extend Parrot's core data types to suit
-the needs of advanced languages.
-
-=item Chapter 8, I<Dynamic Opcodes>
-
-=for author
-
-The same point applies for ops and dynops.
-
-=end for
-
-Parrot allows language developers to extend Parrot's core instruction set --
-again to suit the needs of advanced languages.
-
-=item Chapter 10, I<Instruction Reference>
-
-Parrot's standard instruction set provides powerful behavior for primitive
-operations, control flow, object orientation, exception handling, and more.
-
-=item Chapter 11, I<Directive Reference>
-
-Parrot supports directives used within PIR and PASM code to change the behavior
-of code and to control what happens in bytecode.
-
-=item Chapter 13, I<Operator Reference>
-
-PIR provides several higher-level operators as a convenience to programmers and
-code generators.
-
-=item Appendix A, I<Glossary>
-
-Parrot and its environment have common jargon.
-
-=item Appendix B, I<Command-Line Options>
-
-Parrot supports several flags to control execution modes, debugging, library
-loading, and more.
-
-=item Appendix C, I<Build Options>
-
-Parrot's configuration process gives administrators and developers tremendous
-control over the build system.
-
-=item Appendix D, I<Source Code>
-
-Parrot's source code is organized along logical lines -- logical, once you know
-the layout.
-
-=item Appendix E, I<Patch Submission>
-
-Parrot depends on the combined efforts of numerous volunteers. Your
-contributions are very welcome.
-
-=back
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch03_pir.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch03_pir.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,2412 +0,0 @@
-=pod
-
-=head1 Parrot Intermediate Representation
-
-Z<CHP-3>
-
-X<Parrot Intermediate Representation;;(see PIR)>
-X<PIR (Parrot intermediate representation)>
-
-Parrot Intermediate Representation (PIR) is Parrot's native low-level
-language.N<Parrot has a pure native assembly language called PASM, described in
-Chapter 9.> PIR is fundamentally an assembly language, but it has some
-higher-level features such as operator syntax, syntactic sugar for subroutine
-and method calls, automatic register allocation, and more friendly conditional
-syntax. PIR is commonly used to write Parrot libraries -- including some of
-PCT's compilers -- and is the target form when compiling high-level languages
-to Parrot.
-
-Even so, PIR is more rigid and "close to the machine" then some higher-level
-languages like C. X<.pir files> Files containing PIR code use the F<.pir>
-extension.
-
-=head2 Basics
-
-PIR has a relatively simple syntax. Every line is a comment, a label, a
-statement, or a directive. Each statement or directive stands on its own line.
-There is no end-of-line symbol (such as a semicolon in other languages).
-
-=head3 Comments
-
-X<PIR comments>
-A comment begins with the C<#> symbol, and continues until the end of the line.
-Comments can stand alone on a line or follow a statement or directive.
-
- # This is a regular comment. The PIR
- # interpreter ignores this.
-
-X<PIR POD>
-PIR also treats inline documentation in Pod format as a comment. An
-equals sign as the first character of a line marks the start of a Pod
-block. A C<=cut> marker signals the end of a Pod block.
-
- =head2
-
- This is Pod documentation, and is treated like a
- comment. The PIR interpreter ignores this.
-
- =cut
-
-=head2 Labels
-
-Z<CHP-3-SECT-4>
-
-X<PIR (Parrot intermediate representation);labels> X<labels (PIR)> A label
-attaches to a line of code so other statements can refer to it. Labels can
-contain letters, numbers, and underscores. By convention, labels use all
-capital letters to stand out from the rest of the source code. A label can be
-precede a line of code, though outdenting labels on separate lines improves
-readability:
-
- GREET:
- say "'Allo, 'allo, 'allo."
-
-Labels are vital to control flow.
-
-=head3 Statements
-
-Z<CHP-3-SECT-1>
-
-X<statements (PIR)>
-X<PIR (Parrot intermediate representation);statements>
-A statement is either an opcode or syntactic sugar for one or more opcodes. An
-opcode is a native instruction for the virtual machine; it consists of the name
-of the instruction followed by zero or more arguments.
-
- say "Norwegian Blue"
-
-PIR also provides higher-level constructs, including symbol operators:
-
- $I1 = 2 + 5
-
-Under the hood, these special statement forms are just syntactic sugar for
-regular opcodes. The C<+> symbol corresponds to the C<add> opcode, the C<->
-symbol to the C<sub> opcode, and so on. The previous example is equivalent to:
-
- add $I1, 2, 5
-
-=head3 Directives
-
-Directives begin with a period (C<.>); Parrot's parser handles them specially.
-Some directives specify actions that occur at compile time. Other directives
-represent complex operations that require the generation of multiple
-instructions. The C<.local> directive declares a typed register.
-
- .local string hello
-
-PIR also has a macro facility to create user-defined directives.
-
-=head3 Literals
-
-Integers and floating point numbers are numeric literals. They can be positive
-or negative.
-
- $I0 = 42 # positive
- $I1 = -1 # negative
-
-Integer literals can also be binary, octal, or hexadecimal:
-
- $I3 = 0b01010 # binary
- $I3 = 0o78 # octal
- $I2 = 0xA5 # hexadecimal
-
-Floating point number literals have a decimal point, and can use scientific
-notation:
-
- $N0 = 3.14
- $N2 = -1.2e+4
-
-X<strings;in PIR>
-String literals are enclosed in single or double-quotes.N<L<Strings>
-explains the differences between the quoting types.>
-
- $S0 = "This is a valid literal string"
- $S1 = 'This is also a valid literal string'
-
-=head3 Variables
-
-PIR variables can store four different kinds of valuesE<mdash>integers, numbers
-(floating point), strings, and objects. The simplest way to work with these
-values is through register variables. Register variables always start with a
-dollar sign (C<$>) and a single character which specifies the type of the
-register: integer (C<I>), number (C<N>), string (C<S>), or PMC (C<P>).
-Registers have numbers as well; the "first" string register is
-C<$S0>.N<Register numbers may or may not correspond to the register used
-internally; Parrot's compiler remaps registers as appropriate.>
-
- $S0 = "Who's a pretty boy, then?"
- say $S0
-
-PIR also has named variables, which are declared with the C<.local> directive.
-As with registers, there are four valid types for named variables: C<int>,
-C<num>, C<string>, and C<pmc>.N<Again, for "I<P>olyI<M>orphic I<C>ontainer".>
-After declaring a named variable, you can use the name anywhere you would use a
-register:
-
- .local string hello
- set hello, "'Allo, 'allo, 'allo."
- say hello
-
-Integer (C<I>) and Number (C<N>) registers use platform-dependent sizes and
-limitations.N<There are a few exceptions to this; Parrot smooths out some of the
-bumps and inconsistencies so that PIR code behaves the same way on all
-supported platforms.> Internally, Parrot treats both I and N registers as
-signed quantities internally for the purposes of arithmetic. Parrot's floating
-point values and operations all comply with the IEEE 754 standard.
-
-Strings (S) are buffers of variable-sized data. The most common use of S
-registers and variables is to store textual data. S registers I<may> also be
-buffers for binary or other non-textual data, though this is rare.N<In general,
-a custom PMC is mroe useful.> Parrot strings are flexible and powerful, to
-account for all the complexity of human-readable (and computer-representable)
-textual data.
-
-The final data type is the PMC. PMC resemble classes and objects are in
-object-oriented languages. They are the basis for complex data structures and
-object-oriented behavior in Parrot.
-
-=head2 Strings
-
-Strings in double-quotes accept all sorts of escape sequences using
-backslashes. Strings in single-quotes only allow escapes for nested quotes:
-
- $S0 = "This string is \n on two lines"
- $S0 = 'This is a \n one-line string with a slash in it'
-
-Parrot supports several escape sequences in double-quoted strings:
-
- \xhh 1..2 hex digits
- \ooo 1..3 oct digits
- \cX Control char X
- \x{h..h} 1..8 hex digits
- \uhhhh 4 hex digits
- \Uhhhhhhhh 8 hex digits
- \a An ASCII alarm character
- \b An ASCII backspace character
- \t A tab
- \n A newline
- \v A vertical tab
- \f
- \r
- \e
- \\ A backslash
- \" A quote
-
-If you need more flexibility in defining a string, use a X<heredoc string
-literal>. The C<E<lt>E<lt>> operator starts a heredoc. The string terminator
-immediately follows. All text until the terminator is part of the heredoc.
-The terminator must appear on its own line, must appear at the beginning of the
-line, and may not have any trailing whitespace.
-
- $S2 = << "End_Token"
-
- This is a multi-line string literal. Notice that
- it doesn't use quotation marks.
-
- End_Token
-
-=head3 Strings: Encodings and Charsets
-
-X<charset>
-Strings are complicated; string declarations aren't the whole story. In olden
-times, strings only needed to support the ASCII character set (or charset), a
-mapping of 128 bit patterns to symbols and English-language characters. This
-worked as long as everyone using a computer read and wrote English and used a
-small handful of punctuation symbols.
-
-In other words, it was woefully insufficient for international uses, polyglots, and more.
-
-A modern string system must manage several character encodings and charsets in
-order to make sense out of all the string data in the world. Parrot does this.
-Every string has an associated encoding and an associated character set. The
-default charset is 8-bit ASCII, which is simple to use and is almost
-universally supported.
-
-Double-quoted string constants can have an optional prefix specifying the the
-string's encoding and charset.N<As you might suspect, single-quoted strings do
-not support this.> Parrot will maintain these values internally, and will
-automatically convert strings when necessary to preserve the information.
-String prefixes are specified as C<encoding:charset:> at the front of the
-string. Here are some examples:
-
- $S0 = utf8:unicode:"Hello UTF8 Unicode World!"
- $S1 = utf16:unicode:"Hello UTF16 Unicode World!"
- $S2 = ascii:"This is 8-bit ASCII"
- $S3 = binary:"This is raw, unformatted binary data"
-
-The C<binary:> charset treats the string as a buffer of raw unformatted binary
-data. It isn't really a string per se, because binary data contains no readable
-characters. As mentioned earlier, this exists to support libraries which
-manipulate binary data that doesn't easily fit into any other primitive data
-type.
-
-When Parrot combines two strings (such as through concatenation), they must
-both use the same character set and encoding. Parrot will automatically
-upgrade one or both of the strings to use the next highest compatible format as
-necessary. ASCII strings will automatically upgrade to UTF-8 strings if needed,
-and UTF-8 will upgrade to UTF-16. All of these conversions happen inside
-Parrot; you the programmer don't need to worry about the details.
-
-=head2 Named Variables
-
-Z<CHP-3-SECT-2.3>
-
-X<named variables (PIR)>
-X<PIR (Parrot intermediate representation);named variables>
-
-=for author
-
-The declaration section earlier alludes to this.
-
-=end for
-
-Calling a value "$S0" isn't very descriptive, and usually it's a lot
-nicer to be able to refer to values using a helpful name. For this
-reason Parrot allows registers to be given temporary variable names to
-use instead. These named variables can be used anywhere a register
-would be used normally.N<...because they actually are registers, but
-with fancier names.> They're declared with the C<.local> statement
-which requires a variable type and a name:
-
- .local string hello
- set hello, "Hello, Polly."
- say hello
-
-This snippet defines a string variable named C<hello>, assigns it the value
-"Hello, Polly.", and then prints the value. Under the hood these named
-variables are just normal registers of course, so any operation that a register
-can be used for a named variable can be used for as well.
-
-X<types;variable (PIR)>
-X<variables;types (PIR)>
-The valid types are C<int>, C<num>, C<string>, and C<pmc>
-It should come as no surprise that these are the same as Parrot's four
-built-in register types. Named variables are valid from the point of
-their definition to the end of the current subroutine.
-
-The name of a variable must be a valid PIR identifier. It can contain letters,
-digits and underscores but the first character has to be a letter or an
-underscore. There is no limit to the length of an identifier, other than good
-taste.
-
-As mentioned earlier, Parrot's internal compiler may remap named registers and
-symbolic registers to actual registers as necessary. This happens
-transparently, and for the most part you never need to know about it. There's
-one exception: when you know something outside of Parrot must refer to a
-specific register exactly.N<For example, when an NCI call takes a pointer to a
-register and returns a value through the pointer.> Use the C<:unique_reg>
-modifier on a variable declaration to prevent potential register allocation
-changes:
-
- .local pmc MyUniquePMC :unique_reg
-
-This attribute C<:unique_reg> will not affect the behavior of Parrot otherwise.
-
-=head2 PMC variables
-
-Z<CHP-3-SECT-2.4>
-
-PMC registers and variables act much like any integer, floating-point
-number, or string register or variable, but you have to instantiate a
-new PMC object into a type before you use it. The C<new> instruction creates
-a new PMC of the specified type:
-
- $P0 = new 'String'
- $P0 = "Hello, Polly."
- say $P0
-
-This example creates a C<String> object, stores it in the PMC register C<$P0>,
-assigns it the value "Hello, Polly.", and prints it. The type provided to the
-C<.local> directive is either the generic C<pmc> or a type compatible with the
-type passed to C<new>:
-
- .local String hello # or .local pmc hello
- hello = new 'String'
- hello = "Hello, Polly."
- say hello
-
-PIR is a dynamic language; that dynamicism is evident in how Parrot handles PMC
-values. Primitive registers like strings, numbers, and integers perform a
-special action called X<autoboxing> when assigned to a PMC. Autoboxing is the
-process of converting a primitive type to a PMC object. PMC classes exist for
-String, Number, and Integer; notice that the primitive types are in lower-case,
-while the PMC classes are capitalized. If you want to box a value explicitly,
-use the C<box> opcode:
-
- $P0 = new 'Integer' # The boxed form of int
- $P0 = box 42
- $P1 = new 'Number' # The boxed form of num
- $P1 = box 3.14
- $P2 = new 'String' # The boxed form of string
- $P2 = "This is a string!"
-
-The PMC classes C<Integer>, C<Number>, and C<String> are thin overlays on the
-primitive types they represent. These PMC types have the benefit of the
-X<PMC;VTABLE Interface> VTABLE interface. VTABLEs are a standard API that all
-PMCs conform to for performing standard operations. These PMC types support
-custom methods to perform various operations, may be passed to subroutines that
-expect PMC arguments, and can be subclassed by a user-defined type.
-
-=head2 Named Constants
-
-Z<CHP-3-SECT-2.5>
-
-X<PIR (Parrot intermediate representation);named constants>
-X<named constants (PIR)>
-
-The C<.const> directive declares a named constant. It resembles C<.local>; it
-requires a type and a name. It also requires the assignment of a constant
-value. As with named variables, named constants are visibl only within the
-compilation unit where they're declared. This example declares a named string
-constant C<hello> and prints the value:
-
- .const string hello = "Hello, Polly."
- say hello
-
-Named constants may be used in all the same places as literal constants,
-but have to be declared beforehand:
-
- .const int the_answer = 42 # integer constant
- .const string mouse = "Mouse" # string constant
- .const num pi = 3.14159 # floating point constant
-
-In addition to normal local constants, you can also specify a global constant
-which is accessible from everywhere in the current code file:
-
- .globalconst int days = 365
-
-Currently there is no way to specify a PMC constant in PIR source code.
-
-=for author
-
-Why declare constants?
-
-=end for
-
-=head2 Symbol Operators
-
-Z<CHP-3-SECT-3>
-
-X<symbol operators in PIR>
-
-=for author
-
-An earlier section described this already too.
-
-=end for
-
-PIR has many other symbolic operators: arithmetic, concatenation, comparison,
-bitwise, and logical. All PIR operators are translated into one or more Parrot
-opcodes internally, but the details of this translation stay safely hidden from
-the programmer. Consider this example snippet:
-
- .local int sum
- sum = $I42 + 5
- say sum
-
-The statement C<sum = $I42 + 5> translates to the equivalent statement C<add
-sum, $I42, 5>. PIR symbolic operations are:
-
- $I0 = $I1 + 5 # Addition
- $N0 = $N1 - 7 # Subtraction
- $I3 = 4 * 6 # Multiplication
- $N7 = 3.14 / $N2 # Division
- $S0 = $S1 . $S2 # String concatenation
-
-PIR also provides automatic assignment operators such as C<+=>, C<-=>,
-and C<<< >>= >>>. These operators help programmers to perform common
-manipulations on a data value in place, and save a few keystrokes while
-doing them.
-
-A complete list of PIR operators is available in Chapter 13.
-
-=head2 C<=> and Type Conversion
-
-The C<=> operator is very powerful. Its simplest form stores a value into one
-of the Parrot registers. It can assign a string value to a C<string> register,
-an integer value to an C<int> register, a floating point value into a C<number>
-register, etc. However, the C<=> operator can assign I<any> type of value into
-I<any> type of register; Parrot will handle the conversion for you
-automatically:
-
- $I0 = 5 # Integer. 5
- $S0 = $I0 # Stringify. "5"
- $N0 = $S0 # Numify. 5.0
- $I0 = $N0 # Intify. 5
-
-Notice that conversions between the numeric formats and strings only makes
-sense when the value to convert is a number.
-
- $S0 = "parrot"
- $I0 = $S0 # 0
-
-An earlier example showed a string literal assigned to a PMC register of type
-C<String>. This works for all the primitive types and their autoboxed PMC
-equivalents:
-
- $P0 = new 'Integer'
- $P0 = 5
- $S0 = $P0 # Stringify. "5"
- $N0 = $P0 # Numify. 5.0
- $I0 = $P0 # Unbox. $I0 = 5
-
- $P1 = new 'String'
- $P1 = "5 birds"
- $S1 = $P1 # Unbox. $S1 = "5 birds"
- $I1 = $P1 # Intify. 5
- $N1 = $P1 # Numify. 5.0
-
- $P2 = new 'Number'
- $P2 = 3.14
- $S2 = $P2 # Stringify. "3.14"
- $I2 = $P2 # Intify. 3
- $N2 = $P2 # Unbox. $N2 = 3.14
-
-=head2 Compilation Units
-
-Z<CHP-3-SECT-4.1>
-
-X<PIR (Parrot intermediate representation);subroutine> X<subroutine (PIR)>
-Subroutines in PIR are roughly equivalent to the subroutines or methods of a
-high-level language. All code in a PIR source file must appear within a
-subroutine. The simplest syntax for a PIR subroutine starts with the C<.sub>
-directive and ends with the C<.end> directive:
-
-=begin PIR
-
- .sub 'main'
- say "Hello, Polly."
- .end
-
-=end PIR
-
-This example defines a subroutine named C<main> that prints a string C<"Hello,
-Polly.">. Parrot will normally execute the first subroutine it encounters in
-the first file it runs, but you can flag any subroutine as the first one to
-execute with the C<:main> marker:
-
-=begin PIR
-
- .sub 'first'
- say "Polly want a cracker?"
- .end
-
- .sub 'second' :main
- say "Hello, Polly."
- .end
-
-=end PIR
-
-This code prints out "Hello, Polly." but not "Polly want a cracker?". Though
-the C<first> function appears first in the source code, C<second> has the
-C<:main> flag and gets called. C<first> is never called. Revising that
-program produces different results:
-
-=begin PIR
-
- .sub 'first' :main
- say "Polly want a cracker?"
- .end
-
- .sub 'second'
- say "Hello, Polly."
- .end
-
-=end PIR
-
-The output now is "Polly want a cracker?". Execution in PIR starts at the
-C<:main> function and continues until that function ends. To perform other
-operations, you must call other functions explicitly. Chapter 4 describes
-subroutines and their uses.
-
-=head2 Flow Control
-
-Z<CHP-3-SECT-5>
-
-X<PIR (Parrot intermediate representation);flow control>
-X<flow control;in PIR>
-
-Flow control in PIR occurs entirely with conditional and unconditional branches
-to labels. This may seem simplistic and primitive, but here PIR shows its roots
-as a thin overlay on the assembly language of a virtual processor. PIR does
-not support high-level looping structures such as C<while> or C<for> loops. PIR
-has some support for basic C<if> branching constructs, but does not support
-more complicated C<if>/C<then>/C<else> branch structures.
-
-The control structures of high-level languages hew tightly to the semantics of
-those languages; Parrot provides the minimal feature set necessary to implement
-any semantic of an HLL without dictating how that HLL may implement its
-features. Language agnosticism is an important design goal in Parrot, and
-creates a very flexible and powerful development environment for language
-developers.
-
-X<goto instruction (PIR)>
-The most basic branching instruction is the unconditional branch, C<goto>:
-
-=begin PIR
-
- .sub 'main'
- goto L1
- say "never printed"
-
- L1:
- say "after branch"
- end
- .end
-
-=end PIR
-
-The first C<say> statement never runs because the C<goto> always skips over it
-to the label C<L1>.
-
-The conditional branches combine C<if> or C<unless> with C<goto>.
-
-=begin PIR
-
- .sub 'main'
- $I0 = 42
- if $I0 goto L1
- say "never printed"
- L1:
- say "after branch"
- end
- .end
-
-=end PIR
-
-X<if (conditional);instruction (PIR)> X<unless (conditional);instruction (PIR)>
-In this example, the C<goto> branches to the label C<L1> only if the value
-stored in C<$I0> is true. The C<unless> statement is similar, but it branches
-when the tested value is false. You can use PMC and STRING registers with
-C<if> and C<unless>. The op will call the C<get_bool> vtable entry on any PMC
-so used and will convert the STRING to a boolean value. An undefined value, 0,
-or an empty string are all false values. All other values are true.
-
-The comparison operators (C<E<lt>>, C<E<lt>=>, C<==>, C<!=>, C<E<gt>>,
-C<E<gt>=>) can combine with C<if ... goto>. These branch when the
-comparison is true:
-
-=begin PIR
-
- .sub 'main'
- $I0 = 42
- $I1 = 43
- if $I0 < $I1 goto L1
- say "never printed"
- L1:
- say "after branch"
- end
- .end
-
-=end PIR
-
-This example compares C<$I0> to C<$I1> and branches to the label C<L1> if
-C<$I0> is less than C<$I1>. The C<if $I0 E<lt> $I1 goto L1> statement
-translates directly to the C<lt> branch operation.
-
-Chapter 11's "PIR Instructions" section summarizes the other comparison
-operators.
-
-X<loops;PIR>
-X<PIR (Parrot intermediate representation);loop constructs>
-PIR has no special loop constructs. A combination of conditional and
-unconditional branches handle iteration:
-
-=begin PIR
-
- .sub 'main'
- $I0 = 1 # product
- $I1 = 5 # counter
-
- REDO: # start of loop
- $I0 = $I0 * $I1
- dec $I1
- if $I1 > 0 goto REDO # end of loop
-
- say $I0
- end
- .end
-
-=end PIR
-
-X<do-while style loop;(PIR)>
-This example calculates the factorial C<5!>. Each time through the loop it
-multiplies C<$I0> by the current value of the counter C<$I1>, decrements the
-counter, and branches to the start of the loop. The loop ends when C<$I1>
-counts down to 0. This is a I<do while>-style loop with the condition test at
-the end so that the code always runs at least once through the loop.
-
-X<while-style loop (PIR)>
-For a I<while>-style loop with the condition test at the start, use a
-conditional branch with an unconditional branch:
-
-=begin PIR
-
- .sub 'main'
- $I0 = 1 # product
- $I1 = 5 # counter
-
- REDO: # start of loop
- if $I1 <= 0 goto LAST
- $I0 = $I0 * $I1
- dec $I1
- goto REDO
- LAST: # end of loop
-
- say $I0
- end
- .end
-
-=end PIR
-
-This example tests the counter C<$I1> at the start of the loop. At the end of
-the loop, it unconditionally branches back to the start of the loop and tests
-the condition again. The loop ends when the counter C<$I1> reaches 0 and the
-C<if> branches to the C<LAST> label. If the counter isn't a positive number
-before the loop, the loop will never execute.
-
-You can build any high-level flow control construct from conditional and
-unconditional branches; the lowest level of computer hardware works this way.
-All modern programming languages use branching constructs to implement their
-most complex flow control devices.
-
-That doesn't make complex code easier to write in PIR. Fortunately, a series
-of macros exist to simplify flow control.
-
-=head2 Macros
-
-=for author
-
-Needs supplementing; needs moving.
-
-=end for
-
-=head2 Subroutines
-
-Z<CHP-4>
-
-X<PIR (Parrot intermediate representation);subroutines>
-X<subroutines;in PIR>
-The most basic building block of code reuse in PIR is the subroutine. A large
-program may perform a calculation like "the factorial of a number" several
-times. Subroutines abstract this behavior into a single, named, stand-alone
-unit. PIR is a subroutine-based language in that all code in PIR must exist in
-a subroutine. Execution starts in the C<:main> subroutine, which itself can
-call other subroutines. Subroutines can fit together into more elaborate
-chunks of code reusability such as methods and objects.
-
-Parrot supports multiple high-level languages. Each language uses a different
-syntax for defining and calling subroutines. The goal of PIR is not to be a
-high-level language in itself, but to provide the basic tools that other
-languages can use to implement them. PIR's subroutine syntax may seem very
-primitive for this reason.
-
-=head2 Parrot Calling Conventions
-
-Z<CHP-4-SECT-1>
-
-X<PIR (Parrot intermediate representation);subroutines;Parrot calling conventions>
-X<subroutines;Parrot calling conventions;in PIR>
-
-The way that Parrot calls a subroutine -- passing arguments, altering control
-flow, and returning results -- is the "Parrot Calling Conventions" (PCC).
-Parrot generally hides the details of PCC from the programmer. PIR has several
-constructs to gloss over these details, and the average programmer will not
-need to worry about them. PCC uses the Continuation Passing Style
-X<Continuation Passing Style (CPS)>X<CPS (Continuation Passing Style)> (CPS) to
-pass control to subroutines and back again. Again, the details are irrelevant
-for most uses, but the power is available to anyone who wants to take advantage
-of it.
-
-=head3 Subroutine Calls
-
-X<PIR (Parrot intermediate representation);subroutine calls>
-PIR's simplest subroutine call syntax looks much like a subroutine
-call from a high-level language. This example calls the subroutine
-C<fact> with two arguments and assigns the result to C<$I0>:
-
- $I0 = 'fact'(count, product)
-
-This simple statement hides much complexity. It generates a subroutine PMC
-object, creates a continuation PMC object to represent the control flow up to
-this point, passes the arguments, looks up the subroutine by name (and by
-signature, if necessary)), calls the subroutine, and assigns the results of the
-call to the appropriate integer register. This is all in addition to the
-computation the subroutine itself performs.
-
-=head3 Expanded Subroutine Syntax
-
-The single line subroutine call is incredibly convenient, but it isn't always
-flexible enough. PIR also has a more verbose call syntax that is still more
-convenient than manual calls. This example looks up the subroutine C<fact> out
-in the global symbol table and calls it:
-
- find_global $P1, "fact"
-
- .begin_call
- .arg count
- .arg product
- .call $P1
- .result $I0
- .end_call
-
-X<.arg directive>
-X<.result directive>
-The whole chunk of code from C<.begin_call> to C<.end_call> acts as a single
-unit. The C<.arg> directive sets up and passes arguments to the call. The
-C<.call> directive calls the subroutine and identifies the point at which to
-return control flow after the subroutine has completed. The C<.result>
-directive retrieves returned values from the call.
-
-=head3 Subroutine Declarations
-
-X<.param directive> In addition to syntax for subroutine calls, PIR provides
-syntax for subroutine definitions: the C<.sub> and C<.end> directives shown in
-earlier examples. The C<.param> directive defines input parameters and creates
-local named variables for them (similar to C<.local>):
-
- .param int c
-
-X<.return directive>
-The C<.return> directive allows the subroutine to return control flow
-to the calling subroutine, and optionally returns result output values.
-
-Here's a complete code example that implements the factorial algorithm. The
-subroutine C<fact> is a separate subroutine, assembled and processed after the
-C<main> function. Parrot resolves global symbols like the C<fact> label
-between different units.
-
-=begin PIR
-
- # factorial.pir
- .sub 'main' :main
- .local int count
- .local int product
- count = 5
- product = 1
-
- $I0 = 'fact'(count, product)
-
- say $I0
- end
- .end
-
- .sub 'fact'
- .param int c
- .param int p
-
- loop:
- if c <= 1 goto fin
- p = c * p
- dec c
- branch loop
- fin:
- .return (p)
- .end
-
-=end PIR
-
-This example defines two local named variables, C<count> and C<product>, and
-assigns them the values 1 and 5. It calls the C<fact> subroutine with both
-variables as arguments. The C<fact> subroutine uses C<.param> to retrieve
-these parameters and C<.return> to return the result. The final printed result
-is 120.
-
-As usual, execution of the program starts at the C<:main> subroutine.
-
-=head3 Named Arguments
-
-=for author
-
-We have to get our terms straight here. Which are "arguments" (passed in) and
-which are "parameters" (processed from within)?
-
-=end for
-
-X<positional arguments>
-X<named arguments>
-Parameters passed only by their order are I<positional arguments>. The only
-differentiator between positional arguments is their positions in the function
-call. Putting positional arguments in a different order will produce different
-effects, or may cause errors. Parrot also supports I<named parameters>. Instead
-of passing parameters by their position in the string, parameters are passed by
-name and can be in any order. Here's an example:
-
-=begin PIR
-
- .sub 'MySub'
- .param string yrs :named("age")
- .param string call :named("name")
- $S0 = "Hello " . call
- $S1 = "You are " . yrs
- $S1 .= " years old"
- say $S0
- say $S1
- .end
-
- .sub 'main' :main
- 'MySub'("age" => 42, "name" => "Bob")
- .end
-
-=end PIR
-
-Named arguments are convenient because the order of the pairs does not matter.
-You can also pass these pairs in the opposite order:
-
-=begin PIR
-
- .sub 'main' :main
- 'MySub'("name" => "Bob", "age" => 42) # Same!
- .end
-
-=end PIR
-
-=head3 Optional Arguments
-
-X<optional arguments>
-Some functions have arguments with appropriate default values so that callers
-don't always have to pass them. Parrot provides a mechanism to identify
-optional arguments as well as flag values to determine if the
-caller has passed optional arguments.
-
-Optional parameters appear in PIR as if they're actually I<two> parameters:
-the value and a flag:
-
- .param string name :optional
- .param int has_name :opt_flag
-
-The C<:optional> flag specifies that the given parameter is optional. The
-C<:opt_flag> specifies an integer which parameter contains a boolean flag; this
-flag is true if the value was passed, and false otherwise. To provide a default
-value for an optional parameter, you can write:
-
- .param string name :optional
- .param int has_name :opt_flag
-
- if has_name goto we_have_a_name
- name = "Default value"
- we_have_a_name:
-
-Optional parameters can be positional or named parameters. Optional positional
-parameters must appear at the end of the list of positional parameters. Also,
-the C<:opt_flag> parameter must always appear directly after the C<:optional>
-parameter.
-
- .sub 'Foo'
- .param int optvalue :optional
- .param int hasvalue :opt_flag
- .param pmc notoptional # WRONG!
- ...
-
- .sub 'Bar'
- .param int hasvalue :opt_flag
- .param int optvalue :optional # WRONG!
- ...
-
- .sub 'Baz'
- .param int optvalue :optional
- .param pmc notoptional
- .param int hasvalue :opt_flag # WRONG!
- ...
-
-You may mix optional parameters with named parameters:
-
- .sub 'MySub'
- .param int value :named("answer") :optional
- .param int has_value :opt_flag
- ...
-
-You can call this function in two ways:
-
- 'MySub'("answer" => 42) # with a value
- 'MySub'() # without
-
-=head3 Sub PMCs
-
-Subroutines are a PMC type in Parrot. You can store them in PMC registers and
-manipulate them just as you do the other PMC types. Look up a subroutine in
-the current namespace with the C<get_global> opcode:
-
- $P0 = get_global "MySubName"
-
-To find a subroutine in a different namespace, first look up the appropriate
-the namespace PMC, then use that with C<get_global>:
-
- $P0 = get_namespace "MyNameSpace"
- $P1 = get_global $P0, "MySubName"
-
-You can obviously invoke a Sub PMC:
-
- $P0(1, 2, 3)
-
-You can get or even I<change> its name:
-
- $S0 = $P0 # Get the current name
- $P0 = "MyNewSubName" # Set a new name
-
-You can get a hash of the complete metadata for the subroutine:
-
- $P1 = inspect $P0
-
-The metadata fields in this hash are
-
-=over 4
-
-=item * pos_required
-
-The number of required positional parameters to the Sub
-
-=item * pos_optional
-
-The number of optional positional parameters to the Sub
-
-=item * named_required
-
-The number of required named parameters to the Sub
-
-=item * named_optional
-
-The number of optional named parameters to the Sub
-
-=item * pos_slurpy
-
-Returns true if the sub has a slurpy parameter to eat up extra positional args
-
-=item * named_slurpy
-
-Returns true if the sub has a slurpy parameter to eat up extra named args
-
-=back
-
-Instead of getting the whole inspection hash, you ask about individual pieces
-of metadata:
-
- $I0 = inspect $P0, "pos_required"
-
-To discover to get the total number of defined parameters to the Sub, call the
-C<arity> method:
-
- $I0 = $P0.'arity'()
-
-To fetch the namespace PMC that the Sub was defined into, call the
-C<get_namespace> method:
-
- $P1 = $P0.'get_namespace'()
-
-=head2 The Commandline
-
-Programs written in Parrot have access to arguments passed on the command
-line like any other program would:
-
- .sub 'MyMain' :main
- .param pmc all_args :slurpy
- ...
- .end
-
-=for author
-
-Please verify and expand.
-
-=end for
-
-The C<all_args> PMC is a ResizableStringArray PMC, which means you can loop
-over the results, access them individually, or even modify them.
-
-=head2 Continuation Passing Style
-
-X<continuations>
-X<continuation passing style>
-X<CPS>
-Continuations are snapshots of control flow: frozen images of the current
-execution state of the VM. Once you have a continuation, you can invoke it to
-return to the point where the continuation was first created. It's like a
-magical timewarp that allows the developer to arbitrarily move control flow
-back to any previous point in the program.
-
-Continuations are not a new concept; they've boggled the minds of new Lisp and
-Scheme programmers for many years. Despite their power and heritage, they're
-not visible to most other modern programming languages or their runtimes.
-Parrot aims to change that: it performs almost all control flow through the use
-of continuations. PIR and PCT hide most of this complexity from developers,
-but the full power of continuations is available.
-
-When Parrot invokes a function, it creates a continuation representing the
-current point in the program. It passes this continuation as an invisible
-parameter to the function call. When that function returns, it invokes the
-continuation -- in effect, it performs a goto to the point of creation of that
-continuation. If you have a continuation, you can invoke it to return to its
-point of creation any time you want.
-
-This type of flow control -- invoking continuations instead of performing bare
-jumps -- is X<Continuation Passing Style;CPS> Continuation Passing Style (CPS).
-CPS allows parrot to offer all sorts of neat features, such as tail-call
-optimizations and lexical subroutines.
-
-=head3 Tailcalls
-
-A subroutine may set up and call another subroutine, then return the result of
-the second call directly. This is a X<tailcall> tailcall, and is an important
-opportunity for optimization. Here's a contrived example in pseudocode:
-
- call add_two(5)
-
- subroutine add_two(value)
- value = add_one(value)
- return add_one(value)
-
-In this example, the subroutine C<add_two> makes two calls to c<add_one>. The
-second call to C<add_one> is the return value. C<add_one> gets called; its
-result gets returned to the caller of C<add_two>. Nothing in C<add_two> uses
-that return value directly.
-
-A simple optimization is available for this type of code. The second call to
-C<add_one> will return to the same place that C<add_two> returns; it's
-perfectly safe and correct to use the same return continuation that C<add_two>
-uses. The two subroutine calls can share a return continuation, instead of
-having to create a new continuation for each call.
-
-X<.tailcall directive>
-
-PIR provides the C<.tailcall> directive to identify similar situations. Use it
-in place of the C<.return> directive. C<.tailcall> performs this optimization
-by reusing the return continuation of the parent function to make the tailcall:
-
-=begin PIR
-
- .sub 'main' :main
- .local int value
- value = add_two(5)
- say value
- .end
-
- .sub 'add_two'
- .param int value
- .local int val2
- val2 = add_one(value)
- .tailcall add_one(val2)
- .end
-
- .sub 'add_one'
- .param int a
- .local int b
- b = a + 1
- .return (b)
- .end
-
-=end PIR
-
-This example above print the correct value "7".
-
-=head3 Creating and Using Continuations
-
-While Parrot's use of continuations and CPS is invisible to most code, you can
-create and use them explicitly if you like. Continuations are like any other
-PMC. Create one with the C<new> opcode:
-
- $P0 = new 'Continuation'
-
-The new continuation starts off in an undefined state. If you attempt to invoke
-a new continuation without initializing it, Parrot will raise an exception. To
-prepare the continuation for use, assign it a destination label with the
-C<set_addr> opcode:
-
- $P0 = new 'Continuation'
- set_addr $P0, my_label
-
- my_label:
- ...
-
-To jump to the continuation's stored label and return the context to the state
-it was in I<at the point of its creation>, invoke the continuation:
-
- invoke $P0 # Explicit using "invoke" opcode
- $P0() # Same, but nicer syntax
-
-Even though you can use the subroutine notation C<$P0()> to invoke the
-continuation, it doesn't make any sense to pass arguments or obtain return
-values:
-
- $P0 = new 'Continuation'
- set_addr $P0, my_label
-
- $P0(1, 2) # WRONG!
-
- $P1 = $P0() # WRONG!
-
-=head2 Lexical Subroutines
-
-X<Lexical Subroutines>
-
-Parrot offers support for lexical subroutines. You can define a subroutine by
-name inside a larger subroutine, where the inner subroutine is only visible and
-callable from the outer. The inner subroutine inherits all the lexical
-variables from the outer subroutine, but can itself define its own lexical
-variables that the outer subroutine cannot access. PIR lacks the concept of
-blocks or nested lexical scopes; this is how it performs the same function.
-
-If a subroutine is lexical, find its C<:outer> Sub with the C<get_outer>
-method:
-
- $P1 = $P0.'get_outer'()
-
-If there is no C<:outer> PMC, this returns a NULL PMC. Conversely, you can
-set the outer sub:
-
- $P0.'set_outer'($P1)
-
-=head3 Scope and HLLs
-
-As mentioned previously, X<High Level Languages;HLL> High Level Languages such
-as Perl, Python, and Ruby allow nested scopes, or blocks within blocks that can
-have their own lexical variables. Even this construct is common in the C
-programming language:
-
- {
- int x = 0;
- int y = 1;
- {
- int z = 2;
- /* x, y, and z are all visible here */
- }
-
- /* only x and y are visible here */
- }
-
-In the inner block, all three varaibles are visible. The variable C<z> is only
-visible inside that block. The outer block has no knowledge of C<z>. A very
-direct, naI<iuml>ve translation of this code to PIR might be:
-
- .param int x
- .param int y
- .param int z
- x = 0
- y = 1
- z = 2
- ...
-
-This PIR code is similar, but the handling of the variable C<z> is different:
-C<z> is visible throughout the entire current subroutine, where it is not
-visible throughout the entire C function. To help approximate this effect, PIR
-supplies lexical subroutines to create nested lexical scopes.
-
-=head3 PIR Scoping
-
-Only one PIR structure supports scoping like this: the subroutine.N<... and
-objects that inherit from subroutines, such as methods, coroutines, and
-multisubs> There are no blocks in PIR that have their own scope besides
-subroutines. Fortunately, we can use these lexical subroutines to simulate this
-behavior that HLLs require:
-
-=begin PIR
-
- .sub 'MyOuter'
- .local int x,y
- .lex 'x', x
- .lex 'y', y
- 'MyInner'()
- # only x and y are visible here
- .end
-
- .sub 'MyInner' :outer('MyOuter')
- .local int z
- .lex 'z', z
- # x, y, and z are all "visible" here
- .end
-
-=end PIR
-
-=for author
-
-This paragraph is unclear.
-
-=end for
-
-This example calls the variables in C<MyInner> "visible". This is because
-lexically-defined variables need to be accessed with the C<get_lex> and
-C<set_lex> opcodes. These two opcodes don't just access the value of a
-register, where the value is stored while it's being used, but they also make
-sure to interact with the C<LexPad> PMC that's storing the data. If the value
-isn't properly stored in the LexPad, then they won't be available in nested
-inner subroutines, or available from C<:outer> subroutines either.
-
-=head3 Lexical Variables
-
-=for author
-
-What's the point of this paragraph?
-
-=end for
-
-As we have seen above, we can declare a new subroutine to be a nested inner
-subroutine of an existing outer subroutine using the C<:outer> flag. The outer
-flag is used to specify the name of the outer subroutine. Where there may be
-multiple subroutines with the same name, we can use the C<:subid> flag on the
-outer subroutine to give it a different--and unique--name that the lexical
-subroutines can reference in their C<:outer> declarations. Within lexical
-subroutines, the C<.lex> command defines a local variable that follows these
-scoping rules.
-
-=head3 LexPad and LexInfo PMCs
-
-X<LexPad PMC>
-X<LexInfo PMC>
-Subs store information about lexical variables in two different PMCs: the
-LexPad PMC and the LexInfo PMC. They're not visible to PIR code; Parrot uses
-them internally to store information about lexical variables.
-
-I<LexInfo> PMCs store read-only information about the lexical variables used in
-a Sub. Parrot creates them when it compiles a Sub. Not all subroutines get a
-LexInfo PMC by default; only those that need it. One way to identify such a
-Sub is its use of the C<.lex> directive, but this only works for languages
-which know the names of lexical variables at compile time. If that's not true
-of your language, declare the Sub with the C<:lex> attribute.
-
-I<LexPad> PMCs store run-time information about lexical variables. This
-includes their current values and their type information. Parrot creates LexPad
-PMCs for Subs that already have a LexInfo PMC. As you can imagine, Parrot must
-create a new LexPad for each I<invocation> of a Sub, lest a recursive call
-overwrite previous lexical values.
-
-Call the C<get_lexinfo> method on a Subroutine PMC to access its associated
-LexInfo PMC:
-
- $P0 = find_global "MySubroutine"
- $P1 = $P0.'get_lexinfo'()
-
-Once you have the LexInfo PMC, you can inspect the lexicals it represents:
-
- $I0 = elements $P1 # the number of lexical variables it holds
- $P0 = $P1["name"] # the entry for lexical variable "name"
-
-There's not much else you can do (though the PMC behaves like a Hash PMC, so
-you can iterate over its keys and values).
-
-There is no easy way to get a reference to the current LexPad PMC in a given
-subroutine, but they're not useful from PIR anyway. Remember that subroutines
-themselves can be lexical; the lexical environment of a given variable can
-extend to multiple subroutines with their own LexPads. The opcodes C<find_lex>
-and C<store_lex> search through nested LexPads recursively to find the proper
-environment for the given variables.
-
-=head2 Compilation Units Revisited
-
-Z<CHP-4-SECT-1.1>
-
-X<Subroutine>
-A subroutine is a section of code that forms a single unit. The factorial
-calculation example had two separate subroutines: the C<main> subroutine and
-the C<fact> subroutine. Here is that algorithm in a single subroutine:
-
-=begin PIR
-
- .sub 'main'
- $I1 = 5 # counter
- bsr fact
- say $I0
- $I1 = 6 # counter
- bsr fact
- say $I0
- end
-
- fact:
- $I0 = 1 # product
- L1:
- $I0 = $I0 * $I1
- dec $I1
- if $I1 > 0 goto L1
- ret
- .end
-
-=end PIR
-
-The unit of code from the C<fact> label definition to C<ret> is a reusable
-routine, but is only usable from within the C<main> subroutine. There are
-several problems with this simple approach. In terms of the interface, the
-caller has to know to pass the argument to C<fact> in C<$I1> and to get the
-result from C<$I0>. This differs from Parrot's well-understood calling
-conventions.
-
-Another disadvantage of this approach is that C<main> and C<fact> share the
-same subroutine. Parrot processes them as one piece of code. They share
-registers, and they'd share any LexInfo and LexPad PMCs, if any were needed by
-C<main>. The C<fact> routine is also not easily usable from outside the C<main>
-subroutine, so other parts of your code won't have access to it.
-
-=head2 NameSpaces, Methods, and VTABLES
-
-Z<CHP-4-SECT-2>
-
-X<PIR (Parrot intermediate representation);methods>
-X<methods;in PIR>
-X<classes;methods>
-X<. (dot);. (method call);instruction (PIR)>
-PIR provides syntax to simplify writing methods and method calls for
-object-oriented programming. PIR allows you to define your own classes, and
-with those classes you can define method interfaces to them. Method calls
-follow the Parrot's calling conventions, including the various parameter
-configurations, lexical scoping, and other aspects already shown.
-
-Parrot supports several built-in classes, such as C<ResizablePMCArray> and
-C<Integer>, written in C and compiled with the rest of Parrot. You may also
-declare your own classes in PIR. Like other object oriented systems, Parrot
-classes provide their own I<namespaces> and support I<methods> and
-I<attributes>.
-
-=head3 NameSpaces
-
-Z<CHP-4-SECT-2.1>
-
-X<NameSpaces>
-X<.namespace>
-NameSpaces provide a categorization mechanism to avoid name collisions. This is
-most useful when producing encapsulated libraries or when building large
-systems. Each namespace provides a separate location for function names and
-global variables.
-
-X<namespace collisions>
-X<namespace pollution>
-
-Without a namespace (or in a program that eschews namespaces), all subroutines
-and global variables would live in one big bag, running the risk of
-I<namespace collisions> thanks to I<namespace pollution>. You couldn't tell
-which subroutine performed which operation when two task contexts use the same
-word to mean two different things.
-
-NameSpaces are very effective at hiding private information as well as
-gathering similar things together.
-
-For example, the C<Math> namespace could store subroutines that manipulate
-numbers. The C<Images> namespace could store subroutines create and manipulate
-images. If your program must add two numbers together I<and> perform additive
-image composition, you can use the appropriate namespaced C<add> functions
-without conflict or confusion. Within the C<Image> namespace you could have
-also have sub namespaces for C<jpeg> and C<MRI> and C<schematics>; each of
-these could have its own C<add> subroutine without getting into each other's
-way.
-
-Declare a namespace in PIR with the C<.namespace []> directive. The brackets
-are not optional, but the keys inside them are. For example:
-
- .namespace [ ] # The root namespace
- .namespace [ "Foo" ] # The namespace "Foo"
- .namespace [ "Foo" ; "Bar" ] # NameSpace Foo::Bar
- .namespace # WRONG! The [] are needed
-
-You may nest namespaces to arbitrary depth by separating name components with
-semicolons. NameSpaces are PMC, so you can access them and manipulate them
-just like other data objects. Get the PMC for the root namespace using the
-C<get_root_namespace> opcode:
-
- $P0 = get_root_namespace
-
-The current namespace may be different from the root namespace; retrieved it
-with the C<get_namespace> opcode:
-
- $P0 = get_namespace # get current namespace PMC
- $P0 = get_namespace ["Foo"] # get PMC for namespace "Foo"
-
-X<HLL namespaces>
-X<namespaces; HLL>
-Parrot arranges its namespaces in a hiarachy. The root namespace is the root
-of the tree. Beneath the root are HLL namespaces; hLL compiler gets its own
-HLL namespace where it can store its data during compilation and runtime. Each
-HLL namespace may itself be the root of a tree of namespaces.
-
-=head3 NameSpace PMC
-
-There are multiple ways to address a namespace in PIR, depending on the
-starting point of the lookup. They may start at the root namespace:
-
- # Get namespace "a/b/c" starting at the root namespace
- $P0 = get_root_namespace ["a" ; "b" ; "c"]
-
-... or from the current HLL's namespace as a root:
-
- # Get namespace "a/b/c" starting in the current HLL namespace.
- $P0 = get_hll_namespace ["a" ; "b" ; "c"]
-
-... but this is identical to a root namespace lookup with the HLL as the first
-branch:
-
- $P0 = get_root_namespace ["hll" ; "a" ; "b" ; "c"]
-
-... and, of course, relative to the current namespace without a root:
-
- # Get namespace "a/b/c" starting in the current namespace
- $P0 = get_namespace ["a" ; "b" ; "c"]
-
-Given a namespace PMC, retrieve global variables and subroutine PMCs with the
-C<get_global> opcode:
-
- $P1 = get_global $S0 # Get global in current namespace
- $P1 = get_global ["Foo"], $S0 # Get global in namespace "Foo"
- $P1 = get_global $P0, $S0 # Get global in $P0 namespace PMC
-
-=head3 Operations on the NameSpace PMC
-
-You can perform other operations on the NameSpace PMC. You can find methods
-and variables that are stored in the namespace or add new ones.
-
-For example, to add one namespace to another current namespace, use the
-C<add_namespace> method:
-
- $P0 = get_namespace
- $P0.'add_namespace'($P1)
-
-You can also find a namespace nested in a namespace with the C<find_namespace>
-method. Note that this finds I<only> a namespace, where the C<find_global>
-opcode will find I<any> PMC stored in that namespace under the given name:
-
- $P0 = get_namespace
- $P1 = $P0.'find_namespace'("MyOtherNameSpace")
-
-You may also wish to create a namespace if it doesn't exist and find it
-otherwise. That's the purpose of the C<make_namespace> method:
-
- $P1 = $P0.'make_namespace'("MyNameSpace")
-
-To manipulate Sub PMCs in a namespace, use the C<add_sub> and C<find_sub>
-methods. As with C<find_namespace>, C<find_sub> returns I<only> a Sub PMC and
-never any other kind of global symbol:
-
- $P0.'add_sub'("MySub", $P2)
- $P1 = $P0.'find_sub'("MySub")
-
-Similarly, the C<add_var> and C<find_var> methods work on PMCs of I<any> type:
-
- $P0.'add_var'("MyVar", $P3) # Add variable "MyVar" in $P3
- $P1 = $P0.'find_var'("MyVar") # Find it
-
-You can get the name of a namespace with the C<get_name> method; this returns a
-ResizableStringArray of STRINGs:
-
- $P3 = $P0.'get_name'()
-
-Request a namespace's parent namespace with the C<get_parent> method:
-
- $P5 = $P0.'get_parent'()
-
-Find a class associated with a namespace with the C<get_class> method:
-
- $P6 = $P0.'get_class'()
-
-=head3 Calling Methods
-
-Z<CHP-4-SECT-2.2>
-
-X<methods>
-Namespaces enable plenty of interesting behaviors, such as object oriented
-programming and method calls. Methods resemble subroutines with one big
-change: they require an invocant (an object PMC passed as the C<self>
-parameter).
-
-The basic syntax for a method call resembles a subroutine call. Previous
-examples have demonstrated it already. A PIR method call takes a variable for
-the invocant PMC and a string with the name of the method:
-
- object."methodname"(arguments)
-
-If you forget the quotes around the method's name, PIR will treat the method
-name as a named variable which contains the method's name:
-
- .local string methname = "Foo"
- object.methname() # Same as object."Foo"()
- object."Foo"() # Same
-
-The invocant can be a variable or register, and the method name can be a
-literal string, string variable, or method object PMC.
-
-=head3 Defining Methods
-
-Define a method like any other subroutine, respecting two changes. First, a
-method must be a member of a namespace (the namespace representing the class to
-which the method belongs). Second, they require the C<:method> flag.
-
- .namespace [ "MyClass" ]
-
- .sub 'MyMethod' :method
- ...
- .end
-
-Inside the method, access the invocant object through the C<self> parameter.
-C<self> isn't the only name you can call this value, however. You can also use
-the C<:invocant> flag to define a new name for the invocant object:
-
-(See TT #483)
-
-=begin PIR
-
- .sub 'MyMethod' :method
- $S0 = self # Already defined as "self"
- say $S0
- .end
-
- .sub 'MyMethod2' :method
- .param pmc item :invocant # "self" is now "item"
- $S0 = item
- say $S0
- .end
-
-=end PIR
-
-This example defines two methods in the C<Foo> class. It calls one from the
-main body of the subroutine and the other from within the first method:
-
-=begin PIR
-
- .sub 'main'
- .local pmc class
- .local pmc obj
- newclass class, "Foo" # create a new Foo class
- new obj, "Foo" # instantiate a Foo object
- obj."meth"() # call obj."meth" which is actually
- say "done" # in the "Foo" namespace
- end
- .end
-
- .namespace [ "Foo" ] # start namespace "Foo"
-
- .sub 'meth' :method # define Foo::meth global
- say "in meth"
- $S0 = "other_meth" # method names can be in a register too
- self.$S0() # self is the invocant
- .end
-
- .sub 'other_meth' :method # define another method
- say "in other_meth" # as earlier, Parrot provides a return
- .end # statement
-
-=end PIR
-
-Each method call looks up the method name in the object's class namespace. The
-C<.sub> directive automatically makes a symbol table entry for the subroutine
-in the current namespace.
-
-You can pass multiple arguments to a method and retrieve multiple return values
-just like a single line subroutine call:
-
- (res1, res2) = obj."method"(arg1, arg2)
-
-=head3 VTABLEs
-
-PMCs all implement a common interface of functions called X<VTABLE> VTABLEs.
-Every PMC implements the same set of these interfaces, which perform very
-specific low-level tasks on the PMC. The term VTABLE was originally a shortened
-form of the name "virtual function table", although that name isn't used any
-more by the developers, or in any of the documentation.N<In fact, if you say
-"virtual function table" to one of the developers, they probably won't know
-what you are talking about.> The virtual functions in the VTABLE, called
-X<VTABLE interfaces> VTABLE interfaces, are similar to ordinary functions and
-methods in many respects. VTABLE interfaces are occasionally called "VTABLE
-functions", or "VTABLE methods" or even "VTABLE entries" in casual
-conversation. A quick comparison shows that VTABLE interfaces are not really
-subroutines or methods in the way that those terms have been used throughout
-the rest of Parrot. Like methods on an object, VTABLE interfaces are defined
-for a specific class of PMC, and can be invoked on any member of that class.
-Likewise, in a VTABLE interface declaration, the C<self> keyword is used to
-describe the object that it is invoked upon. That's where the similarities end,
-however. Unlike ordinary subroutines or methods, VTABLE methods cannot be
-invoked directly, they are also not inherited through class hierarchies like
-how methods are. With all this terminology discussion out of the way, we can
-start talking about what VTABLES are and how they are used in Parrot.
-
-VTABLE interfaces are the primary way that data in the PMC is accessed
-and modified. VTABLES also provide a way to invoke the PMC if it's a
-subroutine or subroutine-like PMC. VTABLE interfaces are not called
-directly from PIR code, but are instead called internally by Parrot to
-implement specific opcodes and behaviors. For instance, the C<invoke>
-opcode calls the C<invoke> VTABLE interface of the subroutine PMC,
-while the C<inc> opcode on a PMC calls the C<increment> VTABLE
-interface on that PMC. What VTABLE interface overrides do, in essence,
-is to allow the programmer to change the very way that Parrot accesses
-PMC data in the most fundamental way, and changes the very way that the
-opcodes act on that data.
-
-PMCs, as we will look at more closely in later chapters, are typically
-implemented using X<PMC Script> PMC Script, a layer of syntax and macros
-over ordinary C code. A X<PMC Compiler> PMC compiler program converts the
-PMC files into C code for compilation as part of the ordinary build
-process. However, VTABLE interfaces can be written I<and overwritten> in
-PIR using the C<:vtable> flag on a subroutine declaration. This technique
-is used most commonly when subclassing an existing PMC class in PIR code
-to create a new data type with custom access methods.
-
-VTABLE interfaces are declared with the C<:vtable> flag:
-
- .sub 'set_integer' :vtable
- #set the integer value of the PMC here
- .end
-
-in which case the subroutine must have the same name as the VTABLE
-interface it is intended to implement. VTABLE interfaces all have very
-specific names, and you can't override one with just any arbitrary name.
-However, if you would like to name the function something different but
-still use it as a VTABLE interface, you could add an additional name
-parameter to the flag:
-
- .sub 'MySetInteger' :vtable('set_integer')
- #set the integer value of the PMC here
- .end
-
-VTABLE interfaces are often given the C<:method> flag also, so that they can
-be used directly in PIR code as methods, in addition to being used by Parrot
-as VTABLE interfaces. This means we can have the following:
-
- .namespace [ "MyClass" ]
-
- .sub 'ToString' :vtable('get_string') :method
- $S0 = "hello!"
- .return($S0)
- .end
-
- .namespace [ "OtherClass" ]
-
- .local pmc myclass = new "MyClass"
- say myclass # say converts to string internally
- $S0 = myclass # Convert to a string, store in $S0
- $S0 = myclass.'ToString'() # The same
-
-Inside a VTABLE interface definition, the C<self> local variable contains
-the PMC on which the VTABLE interface is invoked, just like in a method
-declaration.
-
-=head2 Roles
-
-As we've seen above and in the previous chapter, Class PMCs and NameSpace
-PMCs work to keep classes and methods together in a logical way. There is
-another factor to add to this mix: The Role PMC.
-
-Roles are like classes, but don't stand on their own. They represent
-collections of methods and VTABLES that can be added into an existing class.
-Adding a role to a class is called I<composing> that role, and any class
-that has been composed with a role C<does> that role.
-
-Roles are created as PMCs and can be manipulated through opcodes and methods
-like other PMCs:
-
- $P0 = new 'Role'
- $P1 = get_global "MyRoleSub"
- $P0.'add_method'("MyRoleSub", $P1)
-
-Once we've created a role and added methods to it, we can add that role to
-a class, or even to another role:
-
- $P1 = new 'Role'
- $P2 = new 'Class'
- $P1.'add_role'($P0)
- $P2.'add_role'($P0)
- add_role $P2, $P0 # Same!
-
-Now that we have added the role, we can check whether we implement it:
-
- $I0 = does $P2, $P0 # Yes
-
-We can get a list of roles from our Class PMC:
-
- $P3 = $P2.'roles'()
-
-Roles are very useful for ensuring that related classes all implement a common
-interface.
-
-=head2 Coroutines
-
-X<PIR;Coroutines>
-X<Coroutines>
-We've mentioned coroutines several times before, and we're finally going
-to explain what they are. Coroutines are similar to subroutines except
-that they have an internal notion of I<state>.N<And the cool new name!>.
-Coroutines, in addition to performing a normal C<.return> to return
-control flow back to the caller and destroy the lexical environment of
-the subroutine, may also perform a C<.yield> operation. C<.yield> returns
-a value to the caller like C<.return> can, but it does not destroy the
-lexical state of the coroutine. The next time the coroutine is called, it
-continues execution from the point of the last C<.yield>, not at the
-beginning of the coroutine.
-
-In a Coroutine, when we continue from a C<.yield>, the entire lexical
-environment is the same as it was when C<.yield> was called. This
-means that the parameter values don't change, even if we call the
-coroutine with different arguments later.
-
-=head3 Defining Coroutines
-
-Coroutines are defined like any ordinary subroutine. They do not require
-any special flag or any special syntax to mark them as being a
-coroutine. However, what sets them apart is the use of the C<.yield>
-directive. C<.yield> plays several roles:
-
-=over 4
-
-=item * Identifies coroutines
-
-When Parrot sees a yield, it knows to create a Coroutine PMC object
-instead of a Sub PMC.
-
-=item * Creates a continuation
-
-Continuations, as we have already seen, allow us to continue
-execution at the point of the continuation later. It's like a snapshot of
-the current execution environment. C<.yield> creates a continuation in
-the coroutine and stores the continuation object in the coroutine object
-or later resuming from the point of the C<.yield>.
-
-=item * Returns a value
-
-C<.yield> can return a valueN<or many values, or no values> to the caller.
-It is basically the same as a C<.return> in this regard.
-
-=back
-
-Here is a quick example of a simple coroutine:
-
- .sub 'MyCoro'
- .yield(1)
- .yield(2)
- .yield(3)
- .return(4)
- .end
-
- .sub 'main' :main
- $I0 = MyCoro() # 1
- $I0 = MyCoro() # 2
- $I0 = MyCoro() # 3
- $I0 = MyCoro() # 4
- $I0 = MyCoro() # 1
- $I0 = MyCoro() # 2
- $I0 = MyCoro() # 3
- $I0 = MyCoro() # 4
- $I0 = MyCoro() # 1
- $I0 = MyCoro() # 2
- $I0 = MyCoro() # 3
- $I0 = MyCoro() # 4
- .end
-
-This is obviously a contrived example, but it demonstrates how the coroutine
-stores it's state. The coroutine stores it's state when we reach a C<.yield>
-directive, and when the coroutine is called again it picks up where it last
-left off. Coroutines also handle parameters in a way that might not be
-intuitive. Here's an example of this:
-
- .sub 'StoredConstant'
- .param int x
- .yield(x)
- .yield(x)
- .yield(x)
- .end
-
- .sub 'main' :main
- $I0 = StoredConstant(5) # $I0 = 5
- $I0 = StoredConstant(6) # $I0 = 5
- $I0 = StoredConstant(7) # $I0 = 5
- $I0 = StoredConstant(8) # $I0 = 8
- .end
-
-Notice how even though we are calling the C<StoredConstant> coroutine with
-different arguments each time, the value of parameter C<x> doesn't change
-until the coroutine's state resets after the last C<.yield>. Remember that
-a continuation takes a snapshot of the current state, and the C<.yield>
-directive takes a continuation. The next time we call the coroutine, it
-invokes the continuation internally, and returns us to the exact same place in
-the exact same condition as we were when we called the C<.yield>. In order
-to reset the coroutine and enable it to take a new parameter, we must either
-execute a C<.return> directive or reach the end of the coroutine.
-
-=head2 Multiple Dispatch
-
-Multiple dispatch is when there are multiple subroutines in a single
-namespace with the same name. These functions must differ, however, in
-their parameter list, or "signature". All subs with the same name get
-put into a single PMC called a MultiSub. The MultiSub is like a list
-of subroutines. When the multisub is invoked, the MultiSub PMC object
-searches through the list of subroutines and searches for the one with
-the closest matching signature. The best match is the sub that gets
-invoked.
-
-=head3 Defining MultiSubs
-
-MultiSubs are subroutines with the C<:multi> flag applied to them.
-MultiSubs (also called "Multis") must all differ from one another in
-the number and/or type of arguments passed to the function. Having
-two multisubs with the same function signature could result in a
-parsing error, or the later function could overwrite the former one
-in the multi.
-
-Multisubs are defined like this:
-
- .sub 'MyMulti' :multi
- # does whatever a MyMulti does
- .end
-
-Multis belong to a specific namespace. Functions in different namespaces with
-the same name do not conflict with each other. It's only when multiple
-functions in a single namespace need to have the same name that a multi is
-used.
-
-Multisubs take a special designator called a I<multi signature>. The multi
-signature tells Parrot what particular combination of input parameters the
-multi accepts. Each multi will have a different signature, and Parrot will
-be able to dispatch to each one depending on the arguments passed. The
-multi signature is specified in the C<:multi> directive:
-
- .sub 'Add' :multi(I, I)
- .param int x
- .param int y
- .return(x + y)
- .end
-
- .sub 'Add' :multi(N, N)
- .param num x
- .param num y
- .return(x + y)
- .end
-
- .sub 'Start' :main
- $I0 = Add(1, 2) # 3
- $N0 = Add(3.14, 2.0) # 5.14
- $S0 = Add("a", "b") # ERROR! No (S, S) variant!
- .end
-
-Multis can take I, N, S, and P types, but they can also use C<_> (underscore)
-to denote a wildcard, and a string that can be the name of a particular PMC
-type:
-
- .sub 'Add' :multi(I, I) # Two integers
- ...
-
- .sub 'Add' :multi(I, 'Float') # An integer and Float PMC
- ...
-
- # Two Integer PMCs
- .sub 'Add' :multi('Integer', _)
- ...
-
-When we call a multi PMC, Parrot will try to take the most specific
-best-match variant, and will fall back to more general variants if a perfect
-best-match cannot be found. So if we call C<'Add'(1, 2)>, Parrot will dispatch
-to the C<(I, I)> variant. If we call C<'Add'(1, "hi")>, Parrot will match the
-C<(I, _)> variant, since the string in the second argument doesn't match C<I>
-or C<'Float'>. Parrot can also choose to automatically promote one of the I,
-N, or S values to an Integer, Float, or String PMC.
-
-To make the decision about which multi variant to call, Parrot takes a
-I<Manhattan Distance> between the two. Parrot calculates the I<distance>
-between the multi signatures and the argument signature. Every difference
-counts as one step. A difference can be an autobox from a primitive type
-to a PMC, or the conversion from one primitive type to another, or the
-matching of an argument to a C<_> wildcard. After Parrot calculates the
-distance to each variant, it calls the function with the lowest distance.
-Notice that it's possible to define a variant that is impossible to call:
-for every potential combination of arguments there is a better match. This
-isn't necessarily a common occurrence, but it's something to watch out for
-in systems with a lot of multis and a limited number of data types in use.
-
-
-=head2 Classes and Objects
-
-It may seem more appropriate for a discussion of PIR's support for classes
-and objects to reside in its own chapter, instead of appearing in a generic
-chapter about PIR programming "basics". However, part of PIR's core
-functionality is its support for object-oriented programming. PIR doesn't
-use all the fancy syntax as other OO languages, and it doesn't even support
-all the features that most modern OO languages have. What PIR does have is
-support for some of the basic structures and abilities, the necessary subset
-to construct richer and higher-level object systems.
-
-=head2 PMCs as Classes
-
-PMCs aren't exactly "classes" in the way that this term is normally used in
-object-oriented programming languages. They are polymorphic data items that can
-be one of a large variety of predefined types. As we have seen briefly, and as
-we will see in more depth later, PMCs have a standard interface called the
-VTABLE interface. VTABLEs are a standard list of functions that all PMCs
-implement.N<Alternately, PMCs can choose not to implement each interface
-explicitly and instead let Parrot call the default implementations.>
-
-VTABLEs are very strict: There are a fixed number with fixed names and
-fixed argument lists. You can't just create any random VTABLE interface that
-you want to create, you can only make use of the ones that Parrot supplies
-and expects. To circumvent this limitation, PMCs may have METHODS in
-addition to VTABLEs. METHODs are arbitrary code functions that can be
-written in C, may have any name, and may implement any behavior.
-
-=head2 VTABLE Interfaces
-
-Internally, all operations on PMCs are performed by calling various VTABLE
-interfaces.
-
-=head2 Class and Object PMCs
-
-The details about various PMC classes are managed by the Class PMC. Class PMCs
-contain information about the class, available methods, the inheritance
-hierarchy of the class, and various other details. Classes can be created
-with the C<newclass> opcode:
-
- $P0 = newclass "MyClass"
-
-Once we have created the class PMC, we can instantiate objects of that class
-using the C<new> opcode. The C<new> opcode takes either the class name or the
-Class PMC as an argument:
-
- $P1 = new $P0 # $P0 is the Class PMC
- $P2 = new "MyClass" # Same
-
-The C<new> opcode can create two different types of PMC. The first type are
-the built-in core PMC classes. The built-in PMCs are written in C and cannot
-be extended from PIR without subclassing. However, you can also create
-user-defined PMC types in PIR. User-defined PMCs use the Object PMC type for
-instantiation. Object PMCs are used for all user-defined type and keep track
-of the methods and VTABLE override definitions. We're going to talk about
-methods and VTABLE overrides in the next chapter.
-
-=head2 Subclassing PMCs
-
-Existing built-in PMC types can be subclassed to associate additional data
-and methods with that PMC type. Subclassed PMC types act like their PMC
-base types, by sharing the same VTABLE methods and underlying data types.
-However, the subclass can define additional methods and attribute data
-storage. If necessary new VTABLE interfaces can be defined in PIR and old
-VTABLE methods can be overridden using PIR. We'll talk about defining
-methods and VTABLE interface overrides in the next chapter.
-
-Creating a new subclass of an existing PMC class is done using the
-C<subclass> keyword:
-
- # create an anonymous subclass
- $P0 = subclass 'ResizablePMCArray'
-
- # create a subclass named "MyArray"
- $P0 = subclass 'ResizablePMCArray', 'MyArray'
-
-This returns a C<Class> PMC which can be used to create and modify the
-class by adding attributes or creating objects of that class. You can also
-use the new class PMC to create additional subclasses:
-
- $P0 = subclass 'ResizablePMCArray', 'MyArray'
- $P1 = subclass $P0, 'MyOtherArray'
-
-Once you have created these classes, you can create them like normal with
-the C<new> keyword:
-
- $P0 = new 'MyArray'
- $P1 = new 'MyOtherArray'
-
-=head2 Attributes
-
-Classes and subclasses can be given attributes which are named data fields.
-Attributes are created with the C<addattribute> opcode, and can be set and
-retrieved with the C<setattribute> and C<getattribute> opcodes respectively:
-
- # Create the new class with two attributes
- $P0 = newclass 'MyClass'
- addattribute $P0, 'First'
- addattribute $P0, 'Second'
-
- # Create a new item of type MyClass
- $P1 = new 'MyClass'
-
- # Set values to the attributes
- setattribute $P1, 'First', 'First Value'
- setattribute $P1, 'Second', 'Second Value'
-
- # Get the attribute values
- $S0 = getattribute $P1, 'First'
- $S1 = getattribute $P1, 'Second'
-
-Those values added as attributes don't need to be strings, even though
-both of the ones in the example are. They can be integers, numbers
-or PMCs too.
-
-=head2 Input and Output
-
-Like almost everything else in Parrot, input and output are handled by PMCs.
-Using the C<print> opcode or the C<say> opcode like we've already seen in
-some examples does this internally without your knowledge. However, we can
-do it explicitly too. First we'll talk about basic I/O, and then we will talk
-about using PMC-based filehandles for more advanced operations.
-
-=head2 Basic I/O Opcodes
-
-We've seen C<print> and C<say>. These are carry-over artifacts from Perl, when
-Parrot was simply the VM backend to the Perl 6 language. C<print> prints
-the given string argument, or the stringified form of the argument, if it's
-not a string, to standard output. C<say> does the same thing but also appends
-a trailing newline to it. Another opcode worth mentioning is the C<printerr>
-opcode, which prints an argument to the standard error output instead.
-
-We can read values from the standard input using the C<read> and C<readline>
-ops. C<read> takes an integer value and returns a string with that many
-characters. C<readline> reads an entire line of input from the standard
-input, and returns the string without the trailing newline. Here is a simple
-echo program that reads in characters from the user and echos them to
-standard output:
-
-=begin PIR
-
- .sub 'main'
- loop_top:
- $S0 = read 10
- print $S0
- goto loop_top
- .end
-
-=end PIR
-
-=head2 Filehandles
-
-The ops we have seen so far are useful if all your I/O operations are limited
-to the standard streams. However, there are plenty of other places where
-you might want to get data from and send data to. Things like files, sockets,
-and databases all might need to have data sent to them. These things can be
-done by using a file handle.
-
-Filehandles are PMCs that describe a file and keep track of an I/O operations
-internal state. We can get Filehandles for the standard streams using dedicated
-opcodes:
-
- $P0 = getstdin # Standard input handle
- $P1 = getstdout # Standard output handle
- $P2 = getstderr # Standard error handle
-
-If we have a file, we can create a handle to it using the C<open> op:
-
- $P0 = open "my/file/name.txt"
-
-We can also specify the exact mode that the file handle will be in:
-
- $P0 = open "my/file/name.txt", "wa"
-
-The mode string at the end should be familiar to C programmers, because they
-are mostly the same values:
-
- r : read
- w : write
- wa : append
- p : pipe
-
-So if we want a handle that we can read and write to, we write the mode string
-C<"rw">. If we want to be able to read and write to it, but we don't want
-write operations to overwrite the existing contents, we use C<"rwa"> instead.
-
-When we are done with a filehandle that we've created, we can shut it down
-with the C<close> op. Notice that we don't want to be closing any of the
-standard streams.
-
- close $P0
-
-With a filehandle, we can perform all the same operations as we could earlier,
-but we pass the filehandle as an additional argument to tell the op where to
-write or read the data from.
-
- print "hello" # Write "hello!" to STDOUT
-
- $P0 = getstdout
- print $P0, "hello" # Same, but more explicit
-
- say $P0, " world!" # say to STDOUT
-
- $P1 = open "myfile.txt", "wa"
- print $P1, "foo" # Write "foo" to myfile.txt
-
-=head2 Filehandle PMCs
-
-Let's see a little example of a program that reads in data from a file, and
-prints it to STDOUT.
-
-=begin PIR
-
- .sub 'main'
- $P0 = getstdout
- $P1 = open "myfile.txt", "r"
- loop_top:
- $S0 = readline $P1
- print $P0, $S0
- if $P1 goto loop_top
- close $P1
- .end
-
-=end PIR
-
-This example shows that treating a filehandle PMC like a boolean value
-returns whether or not we have reached the end of the file. A true return
-value means there is more file to read. A false return value means we are at
-the end. In addition to this behavior, Filehandle PMCs have a number of methods
-that can be used to perform various operations.
-
-=over 4
-
-=item C<$P0.'open'(STRING filename, STRING mode)>
-
-Opens the filehandle. Takes two optional strings: the name of the file to open
-and the open mode. If no filename is given, the previous filename associated
-with the filehandle is opened. If no mode is given, the previously-used mode
-is used.
-
- $P0 = new 'Filehandle'
- $P0.'open'("myfile.txt", "r")
-
- $P0 = open "myfile.txt", "r" # Same!
-
-The C<open> opcode internally creates a new filehandle PMC and calls the
-C<'open'()> method on it. So even though the above two code snippets act in
-an identical way, the later one is a little more concise to write. The caveat
-is that the C<open> opcode creates a new PMC for every call, while the
-C<'open'()> method call can reuse an existing filehandle PMC for a new file.
-
-=item C<$P0.'isatty'()>
-
-Returns a boolean value whether the filehandle is a TTY terminal
-
-=item C<$P0.'close'()>
-
-Closes the filehandle. Can be reopened with C<.'open'> later.
-
- $P0.'close'()
-
- close $P0 # Same
-
-The C<close> opcode calls the C<'close'()> method on the Filehandle PMC
-internally, so these two calls are equivalent.
-
-=item C<$P0.'is_closed'()>
-
-Returns true if the filehandle is closed, false if it is opened.
-
-=item C<$P0.'read'(INTVAL length)>
-
-Reads C<length> bytes from the filehandle.
-
- $S0 = read $P0, 10
-
- $P0.'read'(10)
-
-The two calls are equivalent, and the C<read> opcode calls the C<'read'()>
-method internally.
-
-=item C<$P0.'readline'()>
-
-Reads an entire line (up to a newline character or EOF) from the filehandle.
-
-=item C<$P0.'readline_interactive'(STRING prompt)>
-
-Displays the string C<prompt> and then reads a line of input.
-
-=item C<$P0.'readall'(STRING name)>
-
-Reads the entire file C<name> into a string. If the filehandle is closed,
-it will open the file given by C<name>, read the entire file, and then close
-the handle. If the filehandle is already open, C<name> should not be passed
-(it is an optional parameter).
-
-=item C<$P0.'flush'()>
-
-Flushes the buffer
-
-=item C<$P0.'print'(PMC to_print)>
-
-Prints the given value to the filehandle. The C<print> opcode uses the
-C<'print'()> method internally.
-
- print "Hello"
-
- $P0 = getstdout
- print $P0, "Hello!" # Same
-
- $P0.'print'("Hello!") # Same
-
-=item C<$P0.'puts'(STRING to_print)>
-
-Prints the given string value to the filehandle
-
-=item C<$P0.'buffer_type'(STRING new_type)>
-
-If C<new_type> is given, changes the buffer to the new type. If it is not,
-returns the current type. Acceptable types are:
-
- unbuffered
- line-buffered
- full-buffered
-
-=item C<$P0.'buffer_size'(INTVAL size)>
-
-If C<size> is given, set the size of the buffer. If not, returns the size of
-the current buffer.
-
-=item C<$P0.'mode'()>
-
-Returns the current file access mode.
-
-=item C<$P0.'encoding'(STRING encoding)>
-
-Sets the filehandle's string encoding to C<encoding> if given, returns the
-current encoding otherwise.
-
-=item C<$P0.'eof'()>
-
-Returns true if the filehandle is at the end of the current file, false
-otherwise.
-
-=item C<$P0.'get_fd'()>
-
-Returns the integer file descriptor of the current file, but only on operating
-systems that use file descriptors. Returns C<-1> on systems that do not
-support this.
-
-=back
-
-=head2 Exceptions
-
-Parrot includes a robust exception mechanism that is not only used internally
-to implement a variety of control flow constructs, but is also available for
-use directly from PIR code. Exceptions, in as few words as possible, are
-error conditions in the program. Exceptions are I<thrown> when an error
-occurs, and they can be I<caught> by special routines called I<handlers>. This
-enables Parrot to recover from errors in a controlled way, instead of crashing
-and terminating the process entirely.
-
-Exceptions, like most other data objects in Parrot, are PMCs. They contain
-and provide access to a number of different bits of data about the error,
-such as the location where the error was thrown (including complete
-backtraces), any annotation information from the file, and other data.
-
-=head2 Throwing Exceptions
-
-Many exceptions are used internally in Parrot to indicate error conditions.
-Opcodes such as C<die> and C<warn> throw exceptions internally to do what they
-are supposed to do. Other opcodes such as C<div> throw exceptions only when
-an error occurs, such as an attempted division by zero.
-
-Exceptions can also be thrown manually using the C<throw> opcode. Here's an
-example:
-
- $P0 = new 'Exception'
- throw $P0
-
-This throws the exception object as an error. If there are any available
-handlers in scope, the interpreter will pass the exception object to the
-handler and continue execution there. If there are no handlers available,
-Parrot will exit.
-
-=head2 Exception Attributes
-
-Since Exceptions are PMC objects, they can contain a number of useful data
-items. One such data item is the message:
-
- $P0 = new 'Exception'
- $P1 = new 'String'
- $P1 = "this is an error message for the exception"
- $P0["message"] = $P1
-
-Another is the severity and the type:
-
- $P0["severity"] = 1 # An integer value
- $P0["type"] = 2 # Also an Integer
-
-Finally, there is a spot for additional data to be included:
-
- $P0["payload"] = $P2 # Any arbitrary PMC
-
-=head2 Exception Handlers
-
-Exception handlers are labels in PIR code that can be jumped to when an
-exception is thrown. To list a label as an exception handler, the C<push_eh>
-opcode is used. All handlers exist on a stack. Pushing a new handler adds it
-to the top of the stack, and using the C<pop_eh> opcode pops the handler off
-the top of the stack.
-
- push_eh my_handler
- # something that might cause an error
-
- my_handler:
- # handle the error here
-
-=head3 Catching Exceptions
-
-The exception PMC that was thrown can be caught using the C<.get_results()>
-directive. This returns the Exception PMC object that was thrown from inside
-the handler:
-
- my_handler:
- .local pmc err
- .get_results(err)
-
-With the exception PMC available, the various attributes of that PMC can be
-accessed and analyzed for additional information about the error.
-
-=head3 Exception Handler PMCs
-
-Like all other interesting data types in Parrot, exception handlers are a PMC
-type. When using the syntax above with C<push_eh LABEL>, the handler PMC
-is created internally by Parrot. However, you can create it explicitly too
-if you want:
-
- $P0 = new 'ExceptionHandler'
- set_addr $P0, my_handler
- push_eh $P0
- ...
-
- my_handler:
- ...
-
-=head2 Rethrowing and Exception Propagation
-
-Exception handlers are nested and are stored in a stack. This is because not
-all handlers are intended to handle all exceptions. If a handler cannot deal
-with a particular exception, it can C<rethrow> the exception to the next
-handler in the stack. Exceptions propagate through the handler stack until it
-reaches the default handler which causes Parrot to exit.
-
-=head2 Annotations
-
-Annotations are pieces of metadata that can be stored in a bytecode file to
-give some information about what the original source code looked like. This
-is especially important when dealing with high-level languages. We'll go into
-detail about annotations and their use in Chapter 10.
-
-Annotations are created using the C<.annotation> keyword. Annotations consist
-of a key/value pair, where the key is a string and the value is an integer,
-a number, or a string. Since annotations are stored compactly as constants in
-the compiled bytecode, PMCs cannot be used.
-
- .annotation 'file', 'mysource.lang'
- .annotation 'line', 42
- .annotation 'compiletime', 0.3456
-
-Annotations exist, or are "in force" throughout the entire subroutine,
-or until they are redefined. Creating a new annotation with the same name as
-an old one overwrites it with the new value. The current hash of annotations
-can be retrieved with the C<annotations> opcode:
-
- .annotation 'line', 1
- $P0 = annotations # {'line' => 1}
- .annotation 'line', 2
- $P0 = annotations # {'line' => 2}
-
-Or, to retrieve a single annotation by name, you can write:
-
- $I0 = annotations 'line'
-
-=head3 Annotations in Exceptions
-
-Exception objects contain information about the annotations that were in force
-when the exception was thrown. These can be retrieved with the
-C<'annotation'()> method of the exception PMC object:
-
- $I0 = $P0.'annotations'('line') # only the 'line' annotation
- $P1 = $P0.'annotations'() # hash of all annotations
-
-Exceptions can also give out a backtrace to try and follow where the program
-was exactly when the exception was thrown:
-
- $P1 = $P0.'backtrace'()
-
-The backtrace PMC is an array of hashes. Each element in the array corresponds
-to a function in the current call stack. Each hash has two elements:
-C<'annotation'> which is the hash of annotations that were in effect at that
-point, and C<'sub'> which is the Sub PMC of that function.
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch04_compiler_tools.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch04_compiler_tools.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,273 +0,0 @@
-=pod
-
-=head1 Parrot Compiler Tools
-
-Z<CHP-4>
-
-The previous chapters demonstrated low-level Parrot programming in PIR. That's
-fun, but Parrot's true power is to host programs written in high level
-languages such as Perl 6, Python, Ruby, Tcl, and PHP.
-
-Parrot's language neutrality was a conscious design decision. Parrot and Perl
-6 hewed closely in the early days; it would have been easy for the two to
-overlap and intermingle.
-
-By keeping the two projects separate and encapsulated, the possibility arose to
-support many other dynamic languages equally well. This modular design also
-benefits designers of future languages. Instead of having to reimplement
-low-level features such as garbage collection and dynamic data types, language
-designers and compiler implementers can leave these details of infrastructure
-to Parrot and focus on the syntax, capabilities, and libraries of their
-high-level languages instead.
-
-Parrot exposes a rich interface for these languages to use, offering several
-important features: a robust exceptions system, compilation into
-platform-independent bytecode, a clean extension and embedding interface,
-just-in-time compilation to machine code, native library interface mechanisms,
-garbage collection, support for objects and classes, and a robust concurrency
-model. Designing a new language or implementing a new compiler for an old
-language is easier with all of these features designed, implemented, tested,
-and supported in a VM already.
-
-Language interoperability is a core goal for Parrot. Different languages are
-suited to different tasks; heated debates explode across the Internet about
-which language is right for which project. There's rarely a perfect fit.
-Developers often settle for one particular language if only because it offers
-the fewest I<disadvantages>. Parrot changes this game by allowing developers
-to combine multiple languages seamlessly within a single project. Well-tested
-libraries written in one languages can interoperate with clean problem-domain
-expression in a second language, glued together by a third language which
-elegantly describes the entire system's architecture. You can use the
-strengths of multiple language and mitigate their weaknesses.
-
-For language hosting and interoperability to work, languages developers need to
-write compilers that convert source code written in high level languages to
-bytecode. This process is analogous to how a compiler such as GCC converts C
-or C++ into machine code -- though instead of targeting machine code for a
-specific hardware platform, compilers written in Parrot produce Parrot code
-which can run on any hardware platform that can run Parrot.
-
-Parrot includes a suite of compiler tools for every step of this conversion:
-lexical analysis, parsing, optimization, resource allocation, and code
-generation. Instead of using traditional low-level languages -- such as the C
-produced by C<lex> and C<yacc> -- to write compilers, Parrot can use any
-language hosted on Parrot in its compiler process. As a practical matter, the
-prevalent tool uses a subset of the Perl 6 programming language called I<Not
-Quite Perl>X<Not Quite Perl> (NQP) and an implementation of the Perl 6 Grammar
-Engine X<Perl 6 Grammar Engine> (PGE) to build compilers for Parrot.
-
-=begin notetip
-
-Yes, the Perl 6 compiler on Parrot is itself written in Perl 6. This
-X<bootstrapping> I<bootstrapping> process is mind-boggling at first.
-
-=end notetip
-
-PGE and NQP are part of the Parrot Compiler Tools. A<CHP-5> Chapter 5
-discusses PGE and A<CHP-6> Chapter 6 explains NQP.
-
-=head2 PCT Overview
-
-The X<Parrot Compiler Tools;PCT> Parrot Compiler Tools (PCT) enable the
-creation of high-level language compilers and runtimes. Though the Perl 6
-development team originally created these tools to produce Rakudo (Perl 6 on
-Parrot), several other Parrot-hosted compilers use them to great effect.
-Writing a compiler using Perl 6 syntax and dynamic language tools is much
-easier than writing a compiler in C, C<lex>, and C<yacc>.
-
-PCT contains several classes that implement various parts of a compiler. HLL
-developers write language-specific subclasses to fill in the details their
-languages require. The X<HLLCompiler> C<PCT::HLLCompiler> class specifies the
-compiler's interface and represents the object used to parse and execute code.
-The X<Parrot Compiler Tools;PCT::Grammar> C<PCT::Grammar> and X<Parrot Compiler
-Tools;PCT::Grammar::Actions> C<PCT::Grammar::Actions> classes represent the
-parser and syntax tree generators, respectively. Creating a new HLL compiler is
-as easy as subclassing these three entities with methods specific to your
-language.
-
-=head3 Grammars and Action Files
-
-A PCT-based compiler requires three basic files: the main entry point file, the
-grammar specification file, and the grammar actions file. In addition,
-compilers and the languages they implement often use large libaries of built-in
-routines to provide language-specific behaviors.
-
-=over 4
-
-=item * The main file
-
-The main file is (often) a PIR program which contains the C<:main> function
-that creates and executes the compiler object. This program instantiates a
-C<PCT::HLLCompiler> subclass, loads any necessary support libraries, and
-initializes any compiler- or languages-specific data.
-
-The main file tends to be short. The guts of the compiler logic is in the
-grammar and actions files. Runtime support and auxiliary functions often
-appear in other files, by convention. This separation of concerns tends to
-make compilers easier to maintain.
-
-=item * A grammar file
-
-The high-level language's grammar appears in a F<.pg> file. This file
-subclasses C<PCT::Grammar> class and implements all of the necessary rules --
-written using PGE -- to parse the languages.
-
-=item * An actions file
-
-Actions contains methods -- written in NQP -- on the C<PCT::Grammar:Actions>
-object which receive parse data from the grammar rules and construct an
-X<Abstract Syntax Tree;Parrot Abstract Syntax Tree;AST;PAST> Abstract Syntax
-Tree (AST).N<The Parrot version of an AST is, of course, the Parrot Abstract
-Syntax Tree, or PAST.>
-
-=back
-
-PCT's workflow is customizable, but simple. The compiler passes the source
-code of the HLL into the grammar engine. The grammer engine parses this code
-and returns a X<PGE;Match Object> special Match object which represents a
-parsed version of the code. The compiler then passes this match object to the
-action methods, which convert it in stages into PAST. The compiler finally
-converts this PAST into PIR code, which it can save to a file, convert to
-bytecode, or execute directly.
-
-=head3 C<mk_language_shell.pl>
-
-The only way creating a new language compiler could be easier is if these files
-created themselves. PCT includes a tool to do just that:
-C<mk_language_shell.pl>. This program automatically creates a new directory in
-F<languages/> for your new language, the necessary three files, starter files
-for libraries, a F<Makefile> to automate the build process, and a basic test
-harness to demonstrate that your language works as expects.
-
-These generated files are all stubs which will require extensive editing to
-implement a full language, but they are a well-understood and working starting
-point. With this single command you can create a working compiler. It's up to
-you to fill the details.
-
-C<mk_language_shell.pl> prefers to run from within a working Parrot repository.
-It requires a single argument, the name of the new project to create. There
-are no hard-and-fast rules about names, but the Parrot developers reccomend
-that Parrot-based implementations of existing languages use unique names.
-
-Consider the names of Perl 5 distributions: Active Perl and Strawberry Perl.
-Python implementations are IronPython (running on the CLR) and Jython (running
-on the JVM). The Ruby-on-Parrot compiler isn't just "Ruby": it's Cardinal.
-The Tcl compiler on Parrot is Partcl.
-
-An entirely new language has no such constraints.
-
-From the Parrot directory, invoke C<mk_language_shell.pl> like:
-
- $ B<cd languages/>
- $ B<perl ../tools/build/mk_language_shell.pl <project name>>
-
-=head3 Parsing Fundamentals
-
-An important part of a compiler is the parser and lexical analyzer. The
-lexical analyzer converts the HLL input file into individual tokens. A token
-may consist of an individual punctuation ("+"), an identifier ("myVar"), a
-keyword ("while"), or any other artifact that stands on its own as a single
-unit. The parser attempts to match a stream of these input tokens against a
-given pattern, or grammar. The matching process orders the input tokens into an
-abstract syntax tree which the other portions of the compiler can process.
-
-X<top-down parser>
-X<bottom-up parser>
-X<parsers; top-down>
-X<parsers; bottom-up>
-Parsers come in top-down and bottom-up varieties. Top-down parsers start with a
-top-level rule which represents the entire input. It attempts to match various
-combination of subrules until it has consumed the entire input. Bottom-down
-parsers start with individual tokens from the lexical analyzer and attempt to
-combine them together into larger and larger patterns until they produce a
-top-level token.
-
-PGE is a top-down parser, although it also contains a bottom-up I<operator
-precedence> parser to make processing token clusters such as mathematical
-expressions more efficient.
-
-=head2 Driver Programs
-
-The driver program for the new compiler must create instances of the various
-necessary classes that run the parser. It must also include the standard
-function libraries, create global variables, and handle commandline options.
-PCT provides several useful command-line options, but driver programs may need
-to override several behaviors.
-
-PCT programs can run in two ways. An interactive mode runs one statement at a
-time in the console. A file mode loads and runs an entire file at once. A
-driver program may specificy information about the interactive prompt and
-environment, as well as help and error messages.
-
-=head3 C<HLLCompiler> class
-
-The C<HLLCompiler> class implements a compiler object. This object contains
-references to language-specific parser grammar and actions files, as well as
-the steps involved in the compilation process. The stub compiler created by
-C<mk_language_shell.pl> might resemble:
-
- .sub 'onload' :anon :load :init
- load_bytecode 'PCT.pbc'
- $P0 = get_hll_global ['PCT'], 'HLLCompiler'
- $P1 = $P0.'new'()
- $P1.'language'('MyCompiler')
- $P1.'parsegrammar'('MyCompiler::Grammar')
- $P1.'parseactions'('MyCompiler::Grammar::Actions')
- .end
-
- .sub 'main' :main
- .param pmc args
- $P0 = compreg 'MyCompiler'
- $P1 = $P0.'command_line'(args)
- .end
-
-The C<:onload> function creates the driver object as an instance of
-C<HLLCompiler>, sets the necessary options, and registers the compiler with
-Parrot. The C<:main> function drives parsing and execution begin. It calls the
-C<compreg> opcode to retrieve the registered compiler object for the language
-"MyCompiler" and invokes that compiler object using the options received from
-the commandline.
-
-The C<compreg> opcode hides some of Parrot's magic; you can use it multiple
-times in a program to compile and run different languages. You can create
-multiple instances of a compiler object for a single language (such as for
-runtime C<eval>) or you can create compiler objects for multiple languages for
-easy interoperability. The Rakudo Perl 6 C<eval> function uses this mechanism
-to allow runtime eval of code snippets in other languages:
-
- eval("puts 'Konnichiwa'", :lang<Ruby>);
-
-=head3 C<HLLCompiler> methods
-
-The previous example showed the use of several HLLCompiler methods:
-C<language>, C<parsegrammar>, and C<parseactions>. These three methods are the
-bare minimum interface any PCT-based compiler should provide. The C<language>
-method takes a string argument that is the name of the compiler. The
-HLLCompiler object uses this name to register the compiler object with Parrot.
-The C<parsegrammar> method creates a reference to the grammar file that you
-write with PGE. The C<parseactions> method takes the class name of the NQP file
-used to create the AST-generator for the compiler.
-
-If your compiler needs additional features, there are several other available
-methods:
-
-=over 4
-
-=item * C<commandline_prompt>
-
-The C<commandline_prompt> method allows you to specify a custom prompt to
-display to users in interactive mode.
-
-=item * C<commandline_banner>
-
-The C<commandline_banner> method allows you to specify a banner message that
-displays at the beginning of interactive mode.
-
-=back
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch05_pge.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch05_pge.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,1558 +0,0 @@
-=pod
-
-=head1 Grammar Engine
-
-X<Parrot Grammar Engine>
-X<PGE (Parrot Grammar Engine)>
-The Parrot Grammar Engine (PGE) is a parser generator, one of the key
-components of the Parrot Compiler Toolkit. It reads grammar files written in
-the PGE rules format and generates parser modules written in PIR code. PGE
-rules provide the full power of I<recursive descent parsing> and I<operator
-precedence parsing>. Fortunately, you don't need to know what those terms
-mean in order to make good use of PGE. We'll introduce the necessary
-concepts as we talk about various features in this chapter.
-
-=head2 Grammars
-
-The ultimate goal of a parser is to match patterns in a source language and
-convert them to an internal data structure for later manipulations. As a
-programmer, you're probably already familiar with some of these types of
-patterns: function declarations, function calls, statements, and assignments.
-Each of these different concepts have a particular form called a I<syntax>.
-In C for example, the syntax to define a function looks something like this:
-
- <return_type> <function_name> ( <arguments> ) { <function_body> }
-
-Things that fit this pattern, so long as all the sub-patterns use the proper
-syntax also, are valid subroutines in C. Similarly, we can use a slightly
-different pattern to create a subroutine:
-
- sub <function_name> { <function_body> }
-
-A grammar is a collection of rules like the ones above that specify all the
-acceptable patterns in a language. Grammars group together these rules in
-much the same way that a groups together related data fields and methods
-N<In languages like Perl 6 for instance, a grammar is just a special kind
-of class and a rule is just a special kind of method.>. Each rule defines
-a pattern for matching one unit of text, and can be made up of various other
-rules which are called recursively to make a complete match.
-
-A rule can contain regular expressions to match patterns of characters:
-
- rule id { \d+ }
-
-A rule can also contain patterns of references to other rules:
-
- rule record { <id> <name> <phone> }
-
-A grammar contains a group of rules that work together to match the entire
-language:
-
- grammar Contacts;
-
- rule name { 'John' | 'Bob ' | 'Fred' }
-
- rule id { \d+ }
-
- rule record { <id> <name> }
-
- ...
-
-=head3 Rules and Tokens
-
-X<rule>
-X<token>
-There are two different kinds of rules: C<rule>, which we saw above, and
-C<token>. A C<rule> performs smart whitespace matching between the various
-pieces of the pattern. The C<record> rule given previously would match
-"6355 John" or "6355 John" but not "6355John".
-
-A C<token> matches whitespace only if you specifically request it. To get the
-same effect with a token, add the C<\s> (match a space character) and C<+>
-(match the preceding atom -- the space character, in this case -- one or more
-times) pattern to the rule:
-
- token record { <id> \s+ <name> }
-
-=head3 The Start Rule
-
-X<top>
-X<top-down parser>
-A recursive descent parser is what's called a I<top-down parser>. It starts
-at the highest-level rule, called C<TOP>, and works its way down through
-individual rules to match an entire string or file. Real Perl 6 allows any
-name for the top-level rule, but PCT expects a rule called C<TOP>. If PCT
-was as fully-featured as Perl 6, people would use it instead! Here's an
-example of a TOP rule:
-
- rule TOP { <record> }
-
-This rule matches a single C<record> pattern in a string or file. Once the
-parser has succeeded in matching the entire string or file passed to the
-start rule, it returns a parse tree. If it cannot match the entire input
-with the rules provided, it can either return a partial match, or it can
-throw a parse error.
-
-=head3 Testing a Grammar
-
-Let's do a small example grammar. Save this example to a file called
-F<Contacts.pg>:
-
- grammar Contacts is PGE::Grammar;
-
- rule TOP { <record> }
- rule record { <id> <name> }
- token name { 'John' | 'Bob ' | 'Fred' }
- token id { \d+ }
-
-Then compile the grammar:
-
- $ B<parrot Perl6Grammar.pbc --output=Contacts.pir Contacts.pg>
-
-=for author
-
-Assume an installed Parrot for all examples? Anyone working from the source
-tree should be able to mangle paths appropriately.
-
-=end for
-
-The path to F<parrot> and to the F<Perl6Grammar.pbc> file will vary on
-different systems. If you compiled Parrot from source, it will be:
-
- $ B<./parrot runtime/parrot/library/PGE/Perl6Grammar.pbc \>
- B<--output=Contacts.pir Contacts.pg>
-
-Next, create a small PIR script to run your grammar. Save it as
-F<grammar_test.pir>:
-
-=begin PIR
-
- .sub main :main
- load_bytecode 'PGE.pbc' # load some required modules
- load_bytecode 'dumper.pbc'
- load_bytecode 'PGE/Dumper.pbc'
-
- load_bytecode 'Contacts.pir' # load your grammar
-
- .local string source
- source = "3 John"
-
- .local pmc top, grammar, match
- top = get_hll_global ['Contacts'], 'TOP'
- grammar = get_class 'Contacts'
- match = top(source, 'grammar' => grammar)
-
- _dumper(match, "match")
- .end
-
-=end PIR
-
-Run the test script:
-
- $ B<parrot grammar_test.pir>
-
-It will print out a text representation of the raw parse tree stored in the
-C<match> variable:
-
- "match" => PMC 'Contacts' => "3 John" @ 0 {
- <record> => PMC 'Contacts' => "3 John" @ 0 {
- <id> => PMC 'Contacts' => "3" @ 0
- <name> => PMC 'Contacts' => "John" @ 2
- }
- }
-
-Each node in the tree corresponds to a rule in the grammar. The top-level
-match variable contains one child named C<record>, which contains two children
-named C<id> and C<name>. C<id> contains the number 3, and C<name> contains the
-string "John". This is exactly what the simple grammar should have matched.
-
-=head2 Rule Syntax
-
-Every language has a set of basic components (words or parts of words) and
-syntax conventions for combining them. The "words" in rules are literal
-characters or symbols, some X<metacharacters> metacharacters (or metasymbols),
-and X<rules;escape sequences>X<escape sequences, rules> escape sequences, while
-the combining syntax includes other metacharacters, X<quantifiers, rules>
-X<rules;quantifiers> quantifiers, bracketing characters, and assertions.
-
-=head3 Metacharacters
-
-The C<.> metacharacter matches any single character, even a newline character.
-The C<^> and C<$> metacharacters are zero-width matches which represent the
-beginning and end of a string. They each have doubled alternates C<^^> and
-C<$$> that match at the beginning and end of every (newline-delimited) line
-within a string.
-
-The C<|>, C<&>, C<\>, C<#>, and C<:=> metacharacters are all syntax structure
-elements. C<|> alternates between two options. C<&> matches two patterns
-simultaneously (the patterns must be the same length). C<\> turns literal
-characters into metacharacters (producing escape sequences). C<#> starts a
-comment which proceeds until the end of the line. You can start a comment at
-any point on any line in a rule. C<:=> binds a hypothetical variable to the
-result of a subrule or grouped pattern (see L<Hypothetical Variables>).
-
-The metacharacters C<()>, C<[]>, C<{}> and C<E<lt>E<gt>> are bracketing pairs.
-Bracketing pairs must always be balanced within the rule; to use a literal
-character, escape it with a C<\>. The C<()> and C<[]> pairs group patterns as
-a single atom. They often capture a result, mark the boundaries of an
-alternation, or mark a group of patterns with a quantifier. Parentheses C<()>
-capture, but square brackets C<[]> do not. The C<{}> brackets define a section
-of code (a closure) within a rule. These closures are always a successful
-zero-width match. The C<E<lt>...E<gt>> brackets mark assertions, which handle a
-variety of constructs including character classes and user-defined quantifiers
-(see L<Assertions>).
-
-Table 7-2 summarizes the basic metacharacters.
-
-=begin table picture Metacharacters
-
-Z<CHP-7-TABLE-2>
-
-=headrow
-
-=row
-
-=cell Symbol
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<.>
-
-=cell Match any single character, including a newline.
-X<. (dot);. match single character (rules)>
-
-=row
-
-=cell C<^>
-
-=cell Match the beginning of a string.
-X<^ (caret);^ beginning of string (rules)>
-
-=row
-
-=cell C<$>
-
-=cell Match the end of a string.
-X<$ (dollar sign);$ end of string (rules)>
-
-=row
-
-=cell C<^^>
-
-=cell Match the beginning of a line within the string.
-X<^ (caret);^^ beginning of line (rules)>
-
-=row
-
-=cell C<$$>
-
-=cell Match the end of a line within the string.
-X<$ (dollar sign);$$ end of line (rules)>
-
-=row
-
-=cell C<|>
-
-=cell Match alternate patterns (OR).
-
-=row
-
-=cell C<&>
-
-=cell Match multiple patterns (AND).
-
-=row
-
-=cell C<\>
-
-=cell Escape a metacharacter to get a literal character, or escape a
-literal character to get a metacharacter.
-X<\ (backslash);\ escape sequences (rules)>
-X<\ (backslash);\ to escape metacharacters (rules)>
-
-=row
-
-=cell C<#>
-
-=cell Mark a comment (to the end of the line).
-
-=row
-
-=cell C<:=>
-
-=cell Bind the result of a match to a hypothetical variable.
-X<: (colon);:= (binding);in rules>
-
-=row
-
-=cell C<(...)>
-
-=cell Group patterns and capture the result.
-
-=row
-
-=cell C<[...]>
-
-=cell Group patterns without capturing.
-
-=row
-
-=cell C<{...}>
-
-=cell Execute a closure (Perl 6 code) within a rule.
-
-=row
-
-=cell C<E<lt>...E<gt>>
-
-=cell Match an assertion.
-
-=end table
-
-=head3 Escape Sequences
-
-Z<CHP-7-SECT-2.2>
-
-X<escape sequences, rules>
-X<rules;escape sequences>
-X<\ (backslash);\ escape sequences (rules)>
-
-Escape sequences are literal characters acting as metacharacters. A preceding
-backslash (C<\>) identifies them as escapes. Some escape sequences represent
-single characters that are difficult to represent literally, such as C<\t> for
-tab, or C<\x[...]> to specify a character by its hexadecimal number. Some
-represent limited character classes, such as C<\d> for digits or C<\w> for word
-characters. Some represent zero-width positions in a match, such as C<\b> for a
-word boundary.
-
-X<variable interpolation in rules>
-X<rules;variable interpolation>
-If you've used Perl 5 regexps, you may remember the C<\Q> escape sequence which
-treats everything until the following C<\E> sequence as literal text,
-containing no escape sequences. Because ordinary variables now interpolate as
-literal strings by default, the C<\Q> escape sequence is rarely needed.
-
-A<CHP-7-TABLE-3>Table 7-3 shows the escape sequences for rules.
-
-=begin table picture Escape sequences
-
-Z<CHP-7-TABLE-3>
-
-=headrow
-
-=row
-
-=cell Escape
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<\0[...]>
-
-=cell Match a character given in octal (brackets optional).
-
-=row
-
-=cell C<\b>
-
-=cell Match a word boundary.
-
-=row
-
-=cell C<\B>
-
-=cell Match when not on a word boundary.
-
-=row
-
-=cell C<\c[...]>
-
-=cell Match a named character or control character.
-
-=row
-
-=cell C<\C[...]>
-
-=cell Match any character except the bracketed named or control character.
-
-=row
-
-=cell C<\d>
-
-=cell Match a digit.
-
-=row
-
-=cell C<\D>
-
-=cell Match a non-digit.
-
-=row
-
-=cell C<\e>
-
-=cell Match an escape character.
-
-=row
-
-=cell C<\E>
-
-=cell Match anything but an escape character.
-
-=row
-
-=cell C<\f>
-
-=cell Match the form feed character.
-
-=row
-
-=cell C<\F>
-
-=cell Match anything but a form feed.
-
-=row
-
-=cell C<\n>
-
-=cell Match a (logical) newline.
-
-=row
-
-=cell C<\N>
-
-=cell Match anything but a (logical) newline.
-
-=row
-
-=cell C<\h>
-
-=cell Match horizontal whitespace.
-
-=row
-
-=cell C<\H>
-
-=cell Match anything but horizontal whitespace.
-
-=row
-
-=cell C<\L[...]>
-
-=cell Everything within the brackets is lowercase.
-
-=row
-
-=cell C<\Q[...]>
-
-=cell All metacharacters within the brackets match as literal characters.
-
-=row
-
-=cell C<\r>
-
-=cell Match a return.
-
-=row
-
-=cell C<\R>
-
-=cell Match anything but a return.
-
-=row
-
-=cell C<\s>
-
-=cell Match any whitespace character.
-
-=row
-
-=cell C<\S>
-
-=cell Match anything but whitespace.
-
-=row
-
-=cell C<\t>
-
-=cell Match a tab.
-
-=row
-
-=cell C<\T>
-
-=cell Match anything but a tab.
-
-=row
-
-=cell C<\U[...]>
-
-=cell Everything within the brackets is uppercase.
-
-=row
-
-=cell C<\v>
-
-=cell Match vertical whitespace.
-
-=row
-
-=cell C<\V>
-
-=cell Match anything but vertical whitespace.
-
-=row
-
-=cell C<\w>
-
-=cell Match a word character (Unicode alphanumeric characters plus the
-underscore C<_>).
-
-=row
-
-=cell C<\W>
-
-=cell Match anything but a word character.
-
-=row
-
-=cell C<\x[...]>
-
-=cell Match a character given in hexadecimal (brackets optional).
-
-=row
-
-=cell C<\X[...]>
-
-=cell Match anything but the character given in hexadecimal (brackets
-optional).
-
-=end table
-
-=head3 Quantifiers
-
-Z<CHP-7-SECT-2.3>
-
-Quantifiers specify the number of times an atom (a single character,
-metacharacter, escape sequence, grouped pattern, assertion, etc) will match.
-
-X<. (dot);.. (range);quantifier (rules)>
-X<. (dot);... (infinite range);quantifier (rules)>
-The numeric quantifiers use assertion syntax. A single number (C<E<lt>3E<gt>>)
-requires exactly that many matches. A numeric range quantifier
-(C<E<lt>3C<..>5E<gt>>) succeeds if the number of matches is between the minimum
-and maximum numbers, inclusive. A range with three trailing dots
-(C<E<lt>2...E<gt>>) is shorthand for C<E<lt>R<n>..InfE<gt>>; it matches as many
-times as possible.
-
-Each quantifier has a minimal alternate form -- marked with a trailing C<?> --
-which matches the shortest possible sequence first. That is, given the string
-C<aaaaaa>, C<aE<lt>3C<..>5E<gt>> will match C<aaaaa> and C<aE<lt>3C<..>5E<gt>?>
-will match C<aaa>.
-
-A<CHP-7-TABLE-4>Table 7-4 shows the built-in
-X<quantifiers, rules> X<rules;quantifiers> quantifiers.
-
-=begin table picture Quantifiers
-
-Z<CHP-7-TABLE-4>
-
-=headrow
-
-=row
-
-=cell Maximal
-
-=cell Minimal
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<*>
-
-=cell C<*?>
-
-=cell Match 0 or more times.
-
-=row
-
-=cell C<+>
-
-=cell C<+?>
-
-=cell Match 1 or more times.
-
-=row
-
-=cell C<?>
-
-=cell C<??>
-
-=cell Match 0 or 1 times.
-
-=row
-
-=cell C<E<lt>>R<n>C<E<gt>>
-
-=cell C<E<lt>>R<n>C<E<gt>?>
-
-=cell Match exactly R<n> times.
-
-=row
-
-=cell C<E<lt>>R<n>C<..>R<m>C<E<gt>>
-
-=cell C<E<lt>>R<n>C<..>R<m>C<E<gt>?>
-
-=cell Match at least R<n> and no more than R<m> times.
-
-=row
-
-=cell C<E<lt>>R<n>C<...E<gt>>
-
-=cell C<E<lt>>R<n>C<...E<gt>?>
-
-=cell Match at least R<n> times.
-
-=end table
-
-=head3 Assertions
-
-Z<CHP-7-SECT-2.4>
-
-X<assertions, rules>
-X<rules;assertions>
-An assertion states that some condition or state is true. The match fails when
-that assertion is false.
-
-X<variable interpolation in rules>
-X<rules;variable interpolation>
-
-Assertions match named and anonymous rules, arrays or hashes containing
-anonymous rules, and subroutines or closures that return anonymous rules.
-
-To interpolate a variable in assertion rules, enclose it in assertion
-delimiters.
-A bare scalar in a pattern
-interpolates as a literal string, while a scalar variable in assertion
-brackets interpolates as an anonymous rule. A bare array in a pattern
-matches as a series of alternate literal strings, while an array in
-assertion brackets interpolates as a series of alternate anonymous
-rules.
-
-A bare hash in a pattern matches a word (C<\w+>) if and only if that word is
-one of its keysN<The effect is similar to matching the keys as a series of
-alternates, but it prefers to match the longest possible key, instead of the
-first potential match.>, while a hash in assertion brackets also matches the
-associated value as an anonymous rule.
-
-X<fail keyword>
-A bare closure in a pattern always matches (unless it calls C<fail>), but a
-closure in assertion brackets C<E<lt>{...}E<gt>> must return an anonymous rule
-to match.
-
-An assertion with parentheses C<E<lt>(...)E<gt>> resembles a bare closure in a
-pattern in that it allows you to include Perl code within a rule.
-C<E<lt>(...)E<gt>> evaluates the return value of the closure in boolean
-context. The match succeeds or fails based on that return value.
-
-Assertions match character classes, both named and enumerated. A named rule
-character class is often more accurate than an enumerated character class. The
-common C<E<lt>[a-zA-Z]E<gt>> idiom matches ASCII alphabetic characters, but the
-more comprehensive built-in rule C<E<lt>alphaE<gt>> matches the full set of
-Unicode alphabetic characters.
-
-A<CHP-7-TABLE-5>Table 7-5 shows the syntax of assertions.
-
-=begin table picture Assertions
-
-Z<CHP-7-TABLE-5>
-
-=headrow
-
-=row
-
-=cell Syntax
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<E<lt>...E<gt>>
-
-=cell Generic assertion delimiter.
-
-=row
-
-=cell C<E<lt>!...E<gt>>
-
-=cell Negate any assertion.
-
-=row
-
-=cell C<E<lt>>R<name>C<E<gt>>
-
-=cell Match a named rule or character class.
-
-=row
-
-=cell C<E<lt>[...]E<gt>>
-
-=cell Match an enumerated character class.
-
-=row
-
-=cell C<E<lt>-...E<gt>>
-
-=cell Complement a character class (named or enumerated).
-
-=row
-
-=cell C<E<lt>"..."E<gt>>
-
-=cell Match a literal string (interpolated at match time).
-
-=row
-
-=cell C<E<lt>'...'E<gt>>
-
-=cell Match a literal string (not interpolated).
-
-=row
-
-=cell C<E<lt>(...)E<gt>>
-
-=cell Boolean assertion. Execute a closure and match if it returns a true
-result.
-
-=row
-
-=cell C<E<lt>$scalarE<gt>>
-
-=cell Match an anonymous rule.
-
-=row
-
-=cell C<E<lt>@arrayE<gt>>
-
-=cell Match a series of anonymous rules as alternates.
-
-=row
-
-=cell C<E<lt>%hashE<gt>>
-
-=cell Match a key from the hash, then its value (as an anonymous rule).
-
-=row
-
-=cell C<E<lt>E<amp>sub()E<gt>>
-
-=cell Match an anonymous rule returned by a sub.
-
-=row
-
-=cell C<E<lt>{>R<code>C<}E<gt>>
-
-=cell Match an anonymous rule returned by a closure.
-
-=row
-
-=cell C<E<lt>.E<gt>>
-
-=cell Match any logical grapheme, including combining character sequences.
-
-=end table
-
-=head3 Modifiers
-
-Z<CHP-7-SECT-2.5>
-
-X<modifiers>
-X<: (colon);: modifier delimiter in rules>
-Modifiers alter the meaning of a pattern. The standard position for modifiers
-is at the beginning of the rule, right after the C<m>, C<s>, or C<rx>, or after
-the name in a named rule. Modifiers cannot attach to the outside of a bare
-C</.../>. For example:
-
- m:i/marvin/ # case insensitive
- rule names :i { marvin | ford | arthur }
-
-You may group single-character modifiers, but you must separate longer
-modifiers by colons:
-
- m:wig/ zaphod / # OK
- m:words:ignorecase:globally / zaphod / # OK
- m:wordsignorecaseglobally / zaphod / # Not OK
-
-Most modifiers can also appear inside the rule when attached to rule or
-grouping delimiters. Internal modifiers are lexically scoped to their enclosing
-delimiters, so can alter subpatterns:
-
- m/:w I saw [:i zaphod] / # only 'zaphod' is case insensitive
-
-The repetition modifiers (C<:R<N>x>, C<:R<N>th>, C<:once>, C<:globally>, and
-C<:exhaustive>) and the continue modifier (C<:cont>) alter the return value of
-the rule as a whole, so you cannot use them lexically inside a rule.
-
-The C<:R<N>x> modifier matches the rule a specific number of times. If the
-modifier expects more matches than the string has, the match fails. Its
-alternate form (C<:x(R<N>)>) can take a variable in place of the number.
-
-The C<:once> modifier on a rule only allows it to match once. The rule will not
-match again until the you call the C<.reset> method on the rule object.
-
-The C<:globally> modifier matches as many times as possible. The C<:exhaustive>
-modifier also matches as many times as possible, in as many different ways as
-possible.
-
-The C<:R<N>th> modifier preserves one result from a particular counted match.
-If the rule matches fewer times than the modifier expects, the match fails. It
-has several alternate forms. One form, C<:th(R<N>)>, takes a variable in place
-of the number. The other forms -- C<:R<N>st>, C<:R<N>nd>, and C<:R<N>rd> --
-allow you to write more naturally C<:1st>, C<:2nd>, C<:3rd>. The other way is
-valid as well; choose whichever is most comfortable.
-
-By default, rules ignore literal whitespace within the pattern. The C<:w>
-modifier makes rules sensitive to literal whitespace, but in an intelligent
-way. Any cluster of literal whitespace acts like an explicit C<\s+> when it
-separates two identifiers and C<\s*> everywhere else.
-
-I<No> modifiers exist to treat the matched string as a single line or multiple
-lines. Instead, use the "beginning of string" and "end of string" or
-"beginning of line" and "end of line" metacharacters.
-
-A<CHP-7-TABLE-6>Table 7-6 lists the available modifiers.
-
-=begin table picture Modifiers
-
-Z<CHP-7-TABLE-6>
-
-=headrow
-
-=row
-
-=cell Short
-
-=cell Long
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<:i>
-
-=cell C<:ignorecase>
-
-=cell Case-insensitive match.
-
-=row
-
-=cell C<:I>
-
-=cell
-
-=cell Case-sensitive match (on by default).
-
-=row
-
-=cell C<:c>
-
-=cell C<:cont>
-
-=cell Continue where the previous match on the string left off.
-
-=row
-
-=cell C<:w>
-
-=cell C<:words>
-
-=cell Literal whitespace in the pattern matches as C<\s+>
-or C<\s*>.
-
-=row
-
-=cell C<:W>
-
-=cell
-
-=cell Turn off intelligent whitespace matching (return to default).
-
-=row
-
-=cell
-
-=cell :R<N>C<x>/C<:x(>R<N>C<)>
-
-=cell Match the pattern R<N> times.
-
-=row
-
-=cell
-
-=cell C<:>R<N>C<th>/C<:nth(>R<N>C<)>
-
-=cell Match the R<N>th occurrence of a pattern.
-
-=row
-
-=cell
-
-=cell C<:once>
-
-=cell Match the pattern once and only once.
-
-=row
-
-=cell C<:g>
-
-=cell C<:globally>
-
-=cell Match the pattern as many times as possible without overlapping
-possibilities.
-
-=row
-
-=cell C<:e>
-
-=cell C<:exhaustive>
-
-=cell Match every possible occurrence of a pattern, including overlapping
-possibilities.
-
-=row
-
-=cell
-
-=cell C<:u0>
-
-=cell . is a byte.
-
-=row
-
-=cell
-
-=cell C<:u1>
-
-=cell . is a Unicode codepoint.
-
-=row
-
-=cell
-
-=cell C<:u2>
-
-=cell . is a Unicode grapheme.
-
-=row
-
-=cell
-
-=cell C<:u3>
-
-=cell . is language dependent.
-
-=row
-
-=cell
-
-=cell C<:p5>
-
-=cell The pattern uses Perl 5 regex syntax.
-
-=end table
-
-=head3 Built-in Rules
-
-Z<CHP-7-SECT-3>
-
-X<rules;built-in>
-PGE provides several named rules, including a complete set of X<POSIX-style
-classes> POSIX-style classes, and X<Unicode property classes> Unicode property
-classes. The list isn't fully defined yet, but A<CHP-7-TABLE-7>Table 7-7 shows
-a few you're likely to see.
-
-The C<E<lt>nullE<gt>> rule matches a zero-width string (it always matches) and
-C<E<lt>priorE<gt>> matches whatever the most recent successful rule matched.
-These replace the two behaviors of X</ (slash);// invalid null pattern>
-X<invalid null pattern //> the Perl 5 null pattern C<//>, which is no longer
-valid syntax for rules.
-
-=begin table picture Built-in rules
-
-Z<CHP-7-TABLE-7>
-
-=headrow
-
-=row
-
-=cell Rule
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<E<lt>alphaE<gt>>
-
-=cell Match a Unicode alphabetic character.
-
-=row
-
-=cell C<E<lt>digitE<gt>>
-
-=cell Match a Unicode digit.
-
-=row
-
-=cell C<E<lt>spE<gt>>
-
-=cell Match a single space character (the same as C<\s>).
-
-=row
-
-=cell C<E<lt>wsE<gt>>
-
-=cell Match any whitespace (the same as C<\s+>).
-
-=row
-
-=cell C<E<lt>nullE<gt>>
-
-=cell Match the null string.
-
-=row
-
-=cell C<E<lt>priorE<gt>>
-
-=cell Match the same thing as the previous match.
-
-=row
-
-=cell C<E<lt>before ...E<gt>>
-
-=cell Zero-width lookahead. Assert that the current position I<precedes> a
-pattern.
-
-=row
-
-=cell C<E<lt>after ...E<gt>>
-
-=cell Zero-width lookbehind. Assert that the current position I<follows> a
-pattern.
-
-=row
-
-=cell C<E<lt>prop ...E<gt>>
-
-=cell Match any character with the named property.
-
-=row
-
-=cell C<E<lt>replace(...)E<gt>>
-
-=cell Replace everything matched so far in the rule or subrule with the
-given string (under consideration).
-
-=end table
-
-=head3 Backtracking Control
-
-Z<CHP-7-SECT-4>
-
-X<backtracking controls>
-X<fail keyword>
-Whenever part of the pattern fails to match, PGE performs backtracking --
-backing up to the previous point at which the match could succeed and trying
-again. You can explicitly trigger backtracking by calling the C<fail> function
-within a closure. A<CHP-7-TABLE-8>Table 7-8 displays metacharacters and
-built-in rules relevant to backtracking.
-
-=for author
-
-This could use an example.
-
-=end for
-
-=begin table picture Backtracking controls
-
-Z<CHP-7-TABLE-8>
-
-=headrow
-
-=row
-
-=cell Operator
-
-=cell Meaning
-
-=bodyrows
-
-=row
-
-=cell C<:>
-
-=cell Don't retry the previous atom. Instead, fail to the next earlier atom.
-X<: (colon);: fail to atom before last (rules)>
-X<backtracking controls;: fail to atom before last>
-
-=row
-
-=cell C<::>
-
-=cell Don't backtrack over this point. Instead fail out of the closest
-enclosing group (C<(...)>, C<[...]>, or the rule delimiters).
-X<: (colon);:: fail out of group (rules)>
-X<backtracking controls;: fail out of group>
-
-=row
-
-=cell C<:::>
-
-=cell Don't backtrack over this point. Instead, fail out of the current rule
-or subrule.
-X<: (colon);::: fail out of rule (rules)>
-X<backtracking controls;: fail out of rule>
-
-=row
-
-=cell C<E<lt>commitE<gt>>
-
-=cell Don't backtrack over this point. Instead, fail out of the entire match
-(even from within a subrule).
-
-=row
-
-=cell C<E<lt>cutE<gt>>
-
-=cell Like C<E<lt>commitE<gt>>, but also cuts the string matched. The current
-matching position at this point becomes the new beginning of the string.
-
-=end table
-
-=head3 Calling Actions
-
-Once the parser has matched the entire input N<a source code file, or a line of
-input at the terminal in interactive mode> the parse has succeeded. The
-generated AST is now available to the code generator for conversion into PIR.
-
-=for author
-
-Please review. The forward declaration is awkward here, but a little bit of
-explanation might ameliorate this.
-
-=end for
-
-This AST gets built up by actions -- code snippets attached to rules and
-tokens. To call an action, insert the C<{*}> token into the rule. When PGE
-encounters C<{*}>, it will call the associated action method with the current
-match object as an argument.
-
-The best way to demonstrate this is by example. Sprinkle the C<persons_name>
-rule liberally with action calls:
-
- rule persons_name {
- {*} <first_name> {*} <last_name> {*}
- }
-
-The first call to the action method contains an empty match object because the
-parser hasn't matched anything yet. The second call contains only the first
-name of the match. The third and final call contains both the matched first and
-last name.
-
-If the match fails halfway through, PGE will still call the actions that have
-succeeded; it will not call the actions after the failure. If you try to match
-the string "Leia", PGE will call the first two action methods. When the rule
-tries to match the last name, it fails, and PGE will not call the third action
-method.
-
-=head3 Alternations and Keys
-
-In addition to sub-rules, groups, and quantifiers, you can also express
-either-or alternations between options. The vertical bar token (C<|>)
-distinguishes between options where only one may match:
-
- rule hero {
- ['Luke' | 'Leia'] 'Skywalker'
- }
-
-This rule will match either "Luke Skywalker" or "Leia Skywalker" but won't
-match "Luke Leia Skywalker"N<nor anything else.>. Given alternations and
-action methods, it's often important to distinguish which alternation matched:
-
- rule hero {
- [
- 'Luke' {*} #= Luke
- | 'Leia' {*} #= Leia
- ]
- 'Skywalker'
- }
-
-This is the same rule, except now it passes two arguments to its action method:
-the match object and the name of the person who matched.
-
-=head3 Warning: Left Recursion
-
-If you've worked with parsers before, you may have seen this coming. If not,
-don't fear. Like functions in ordinary procedural or functional languages, the
-methods in the PGE parser grammar can call themselves recursively. Consider
-some rules derived in part from the grammar for the C programming language:
-
- rule if_statement {
- 'if' <condition> '{' <statement>* '}' <else_block>?
- }
-
- rule statement {
- <if_statement> | <expression>
- }
-
- rule else_block {
- 'else' '{' <statements>* '}'
- }
-
-An C<if_statement> can contain a list of C<statement>s, and that each statement
-may itself be an C<if_statement>. This is I<recursion> X<Recursion>; it's one
-of the reasons PGE is a "Recursive descent" parser.
-
-Consider the more direct example of a comma-separated list of integer digits
-which form a list. A recursive definition might be:
-
- rule list {
- <list> ',' <digit> | <digit>
- }
-
-If there is only one digit, the second option in the alternation matches. If
-there are multiple digits, recursion will match them through the first
-alternation.
-
-That's the intention. The results are insidious.
-
-The recursive descent parser enters the C<list> rule. Its first option is to
-enter the list rule again, so it does. Recursive descent is a X<depth-first
-algorithm> depth-first algorithm; PGE will continue to descend down a
-particular path until it finds a successful match or a match failure. In this
-case, it matches C<list>, then it matches C<list> again, then it matches
-C<list> again, and so on. This rule forms an infinite loop -- a pattern called
-X<left recursion> I<left recursion>. The problem is that the left-most item of
-the left-most alternation is itself a recursion.
-
-The rule above does not recurse infinitely when rewritten as:
-
- rule list {
- <digit> | <list> ',' <digit>
- }
-
-... or even:
-
- rule list {
- <digit> ',' <list> | <digit>
- }
-
-Both options ensure that the left-most item in the rule is recursive.
-
-Left recursion may be trickier. It's not immediately obvious in this grammar:
-
- rule term {
- <expression> '*' <term> | <digit>
- }
-
- rule expression {
- <term> '+' <expression> | <term>
- }
-
-Even this common, limited subset of mathematical equations has the same
-problem. To match a C<term>, the parser first tries to match an C<expression>,
-which in turn matches a C<term> and then an C<expression> ....
-
-Again, the solution is simple. Rewrite at least one of the rules so that the
-first condition it tries to match is not itself a recursive situation.
-
-=head3 Operator Precedence Parser
-
-Recursive descent parsing can be inefficient where statements have lots of
-little tokens and many possible options to match. For example, mathematical
-expressions are very open-ended, with many valid forms which are difficult to
-anticipate. Consider the expression:
-
- a + b * c + d
-
-A recursive descent parser will undergo significant trial and error to parse
-this statement. Recursive descent parsing is not ideal for these situations.
-Instead, a type of bottom-up parser called an I<operator precedence> X<Parser,
-Operator precedence> parser is much better.
-
-=for author
-
-Is this a categorization of all opps or just PGE's opp?
-
-=end for
-
-Operator precedence parsers work similarly to more versatile bottom-up parsers
-such as Lex or Yacc, but are optimized for use with expressions and equations.
-Equations have two subtypes, I<terms> and I<operators>. Operators themselves
-have several subtypes, including prefix (C<-a>), postfix (C<i++>), infix (C<x +
-y>), circumfix (C<[z]>), postcircumfix (C<a[b]>), and list (C<1, 2, 3>). Each
-operator gets its own precedence number that specifies how closely it binds to
-the terms. The previous example should parse as:
-
- a + (b * c) + d
-
-... because the C<*> operator has a higher precedence -- binding more tightly
-to its terms -- than the C<+> operator.
-
-Within a grammar, switch from the top-down recursive descent parser to the
-bottom-up operator precedence parser with an C<optable> X<Parser, optable>
-rule:
-
- rule expression is optable { ... }
-
-The C<...> ellipsis isn't an editorial shortcut, it's the Perl 6 operator to to
-define a function signature. The C<...> indicates that this is just a
-signature; the actual implementation is elsewhere. In this case, that location
-in the definition of the optable.
-
-=head3 Protofunction Definitions
-
-X<Protofunctions>
-
-Protofunctions define operators in the optable in the same way that rules and
-tokens make up the grammar. A proto declares a rule, defined elsewhere, which
-other code may override dynamically. In this case, PCT takes information from
-the proto declaration and fills in the details. The "dynamic overriding"
-implies that a high-level language itself itself can modify its own grammar at
-run time, by overriding the proto definitions for its operator table. Some
-languages call this process X<operator overloading> I<operator overloading>.
-
-A proto definition resembles:
-
- 'proto' <proto_name> [ 'is' <property> ] '{' '...' '}'
-
-The name of the operator, noted as C<< <proto_name> >>, contains both a
-location part and an identifier part. The location is the type of the operator,
-such as infix, postfix, prefix, circumfix, and postcircumfix. The name of the
-operator is the symbol used for the operator in any of the quotes that Perl 6
-understands:
-
- proto infix:<+> # a + b
- proto postfix:'--' # i--
- proto circumfix:«<>» # <x>
-
-The C<is> X<Parser, is> keyword defines a property of the rule. Examples
-include:
-
- is precedence(1) # Specifies an exact precedence
- is equiv('+') # Has the same precedence as the "+" operator
- is assoc('right') # Right associative. May also be "left" or "list"
- is pirop('add') # Operands are passed to the PIR operator "and"
- is subname('mySub') # Operands are passed to the function "mySub"
- is pasttype('if') # Operands are passed as children to an "if" PAST node in
- # the parse tree
- is parsed(&myRule) # The token is parsed and identified using the rule
- # "myRule" from the top-down parser
-
-=for author
-
-Please review.
-
-=end for
-
-Protofunction definitions are function signatures; you can override them with
-multimethod dispatch. This means that you can write functions I<with the same
-name> as the rule to implement the behavior of the operator. Here's a proto:
-
- rule infix:"+" { ... }
-
-... and its corresponding PIR rule:
-
-=begin PIR
-
- .sub 'infix:+'
- .param pmc a
- .param pmc b
- .local pmc c
- c = a + b
- .return(c)
- .end
-
-=end PIR
-
-You may ask "Why have an C<is subname()> property, if you can define all
-operators as subroutines?" Using the C<is subname()> property allows PCT to
-call a subroutine of a different name then the operator. This is a good idea
-if there is already a built-in function in the language that duplicates the
-functionality of the operator. There is no sense in duplicating behavior.
-
-The great thing about protos being overloadable is that you can specify
-different functions to call with different signatures:
-
-=begin PIR
-
- .sub 'infix:+' :multi('Integer', 'Integer')
- #...
- .end
-
- .sub 'infix:+' :multi('CLispRatio', 'Number')
- #...
- .end
-
- .sub 'infix:+' :multi('Perl6Double', 'PythonInteger')
- #...
- .end
-
-=end PIR
-
-This list can be a bit intimidating, and it's hard to imagine that it would be
-necessary to write up a new function to handle addition between every
-conceivable pair of operands. Fortunately, this is rarely the case in Parrot,
-because all these data types support common the VTABLE interface. For most data
-types Parrot already has basic arithmetic operations built in, and it's only
-necessary to override for those data types with special needs.
-
-=head3 Hypothetical Variables
-
-Z<CHP-7-SECT-5>
-
-X<variables;hypothetical>
-X<hypothetical variables>
-X<rules;captures>
-Hypothetical variables are a powerful way of building up data structures from
-within a match. Ordinary captures with C<()> store the result of the captures
-in C<$1>, C<$2>, etc. PGE stores values in these variables if the match is
-successful, but throws them away if the match fails. The numbered capture
-variables are accessible outside the match, but only within the immediate
-surrounding lexical scope:
-
- "Zaphod Beeblebrox" ~~ m:w/ (\w+) (\w+) /;
-
- print $1; # prints Zaphod
-
-You can also capture into any user-defined variable with the binding operator
-C<:=> -- I<if> you have declared these variables in a lexical scope enclosing
-the rule:
-
- my $person;
- "Zaphod's just this guy." ~~ / ^ $person := (\w+) /;
- print $person; # prints Zaphod
-
-You may capture repeated matches into an array:
-
- my @words;
- "feefifofum" ~~ / @words := (f<-[f]>+)* /;
- # @words contains ("fee", "fi", "fo", "fum")
-
-You may capture pairs of repeated matches into a hash:
-
- my %customers;
- $records ~~ m:w/ %customers := [ E<lt>idE<gt> = E<lt>nameE<gt> \n]* /;
-
-If you don't need the captured value outside the rule, use a C<$?> variable
-instead. These are only directly accessible within the rule:
-
- "Zaphod saw Zaphod" ~~ m:w/ $?name := (\w+) \w+ $?name/;
-
-A match of a named rule stores the result in a C<$?> variable with the same
-name as the rule. These variables are also accessible only within the rule:
-
- "Zaphod saw Zaphod" ~~ m:w/ E<lt>nameE<gt> \w+ $?name /;
-
-=for author
-
-This next paragraph feels out of place; is there more?
-
-=end for
-
-When a rule matches a sequence of input tokens, PCT calls an associated method
-within NQP to convert that match into an AST node, which it inserts into the
-I<parse tree>.
-
-=head3 Basic Rules
-
-Consider the simple example rule:
-
- rule persons_name {
- <first_name> <last_name>
- }
-
-... and two example tokens:
-
- token first_name { <alpha>+ }
- token last_name { <alpha>+ }
-
-The special token C<< <alpha> >> is a built-in construct that only accepts
-upper case and lower case letters. The C<+> after the C<< <alpha> >> tag is a
-short way of saying "one or more". The rule will match names like C<Darth
-Vader>N<It also matches many strings that I<aren't> real names>, but won't
-match something like C<C 3P0>.
-
-This rule I<will> match C<Jar Jar Binks>, but not as you might expect: way you
-would expect: It would match the first "Jar" as C<< <first_name> >>, the second
-"Jar" as C<< <last_name> >>, and ignore "Binks"N<You should ignore the whole
-thing.>.
-
-=for author
-
-The rest seems vestigial. An example like this should precede the rest of the
-chapter. There are forward references, but it's a decent overview for people
-who haven't used similar systems before -- if you avoid going out in the weeds.
-
-=end for
-
-this example shows another new construct, the square brackets. Square
-brackets are ways to group things together. The star at the end means
-that we take all the things inside the brackets zero or more times.
-This is similar to the plus, except the plus matches one or more times.
-Notice, however, that the above rule always matches a comma at the end,
-so we would need to have something like:
-
- Darth Vader, Luke Skywalker,
-
-Instead of something more natural like:
-
- Darth Vader, Luke Skywalker
-
-We can modify the rule a little bit so that it always ends with a name
-instead of a comma:
-
- rule TOP {
- [ <persons_name> ',' ]* <persons_name>
- }
-
-Now we don't need a trailing comma, but at the same time we can't match
-an empty file because it always expects to have at least one name at the
-end. If we still want to match empty files successfully, we need to make
-the whole rule optional:
-
- rule TOP {
- [ [ <persons_name> ',' ]* <persons_name> ]?
- }
-
-We've grouped the whole rule together in another set of brackets, and
-put a "?" question mark at the end. The question mark means zero or
-one of the prior item.
-
-The symbols "*" (zero or more), "+" (one or more) and "?" are called
-I<quantifiers>, and allow an item in the rule to match a variable
-number of times. These aren't the only quantifiers, but they are the
-most common. We will talk about other quantifiers later on.
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch06_nqp.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch06_nqp.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,219 +0,0 @@
-=pod
-
-=head1 Grammar Actions
-
-The job of the grammar is to match input patterns from the source language.
-These patterns then need to get converted to nodes in the abstract syntax
-tree for manipulation in other stages of the compiler. We've already seen
-one example of a subroutine structure that takes a match and produces a
-tree node: Protofunctions. Protofunction signatures aren't the only way to
-apply functions to rules matched by a parser. They are limited and are
-slightly primitive, but effective for handling operators. There is an
-easier and more powerful way to write subroutines to convert match objects
-into parse tree nodes, using a language that's almost, but Not Quite Perl.
-
-X<NQP>
-X<Not Quite Perl>
-NQP (Not Quite Perl) is a small language which offers a limited subset of
-Perl 6's syntax and semantics. Though it originated as a bootstrapping tool
-for the Rakudo Perl 6 compiler, several other Parrot-based compilers use it
-as well. It has become a permanent member of PCT, and therefore a permanent
-part of the Parrot code base.
-
-NQP represets almost the smallest subset of the Perl 6 language necessary to
-implement parser transformations, plus a few syntactic convenience features
-that developers have requested. NQP's Perl 6 subset shows its Perl 5 roots,
-so existing Perl 5 programmers should find much of it familiar and should be
-able to leverage their existing skills for writing compilers.
-
-In PGE, at the time of a match the grammar we can invoke an action using the
-special <code>{*}</code> symbol. In general, these action methods are
-written in NQP, although it is possible for them to be written in PIR N<In
-fact, this is how the NQP compiler itself is written>. We won't discuss the
-PIR case here because it's uncommon and needlessly difficult. NQP is the
-standard and preferred choice for this.
-
-=head2 NQP Basics
-
-X<sigils>
-X<scalar>
-Like all flavors and versions of Perl, NQP uses special prefix symbols called
-I<sigils> to distinguish variable types. The C<$> sigil represents scalars,
-C<@> arrays, and C<%> for hashes. A scalar is any single value which can
-interchangeably contain given a string value, an integer value, or an object
-reference. Simple NQP assignments are:
-
- $scalar := "This is a string"
- $x := 123
- $pi := 3.1415 # rounding
-
-X<bind operator>
-X<operators; binding>
-X<:=>
-The C<:=> I<bind> operator performs reference assignment in NQP. Reference
-assignment makes one variable into an alias for another. This means that
-the two variables are just different names for the same storage location,
-and changes to one will change both. It's important to remember that a bind
-is not a copy!
-
-NQP has hashes and arrays just like other flavors of Perl and various
-dynamic languages. NQP does not have a notion of hash and array context,
-but otherwise it works the way you would expect. Arrays have the C<@> sigil,
-and hashes have the C<%> sigil. Here are some examples:
-
- @ary[0] := 1;
- @ary[1] := "foo";
- ...
-
- %hsh{'bar'} := 2;
- %hsh{'baz'} := "parrot";
- ...
-
-There is also a nice shorthand way to index hashes, using angle brackets:
-
- %hsh<bar> := "parrot";
-
-It's also possible to assign a list in I<scalar context>:
-
- $array_but_a_scalar := (1, 2, 3, 4)
-
-Or you could write a new function in PIR to create a new array from a variadic
-argument list:
-
- @my_array := create_new_array(1, 2, 3, 4)
-
-... which calls the PIR function:
-
-=begin PIR
-
- .namespace []
-
- .sub 'create_new_array'
- .param pmc elems :slurpy
- .return(elems)
- .end
-
-=end PIR
-
-=head3 Calling Actions From Rules
-
-=for editor
-
-Needs a link to that section.
-
-=end for
-
-As mentioned in the chapter on grammar rules, the funny little C<{*}> symbol
-calls an action. The action in question is an NQP method with the same name as
-the rule that calls it. NQP rules can have two different signatures:
-
- method name ($/) { ... }
- method name($/, $key) { ... }
-
-Where does the key come from? Consider this grammar:
-
- rule cavepeople {
- 'Fred' {*} #= Caveman
- | 'Wilma' {*} #= Cavewoman
- | 'Dino' {*} #= Dinosaur
- }
-
-The C<cavepeople> rule demonstrates the result:
-
- method cavepeople($/, $key) {
- if $key eq 'Caveman' {
- say "We've found a caveman!";
- } elsif $key eq 'Cavewoman' {
- say "We've found a cavewoman!";
- } elsif $key eq 'Dinosaur' {
- say "A dinosaur isn't a caveperson at all!";
- }
- }
-
-The key is a string that contains whatever any text following the C<#=> symbol.
-Without a C<#=> following the rule invocation, there's no C<$key> to use in the
-method. If you attempt to use one without the other, the NQP compiler will die
-with error messages about mismatched argument/parameter numbers.
-
-=head3 The Match Object C<$/>
-
-X<match object>
-X<$/>
-The match object C<$/> it's a data structure that's all business: it's both a
-hash and an array. Because it's a special variable used pervasively in PCT, it
-has a special shortcut syntax:
-
- $/{'Match_item'} is the same as $<Match_item>
- $/[0] is the same as $[0]
-
-Each key in the match object's hash is the name of a matched rule. Given a
-file containing "C<X + 5>" and a rule:
-
- rule introductions {
- <variable> <operator> <number>
- }
-
-The resulting match object will contain the key/value pairs:
-
- "variable" => "x"
- "operator" => "+"
- "number" => "5"
-
-When the match contains multiple values with the same name, or when rules have
-quantifiers such as C<*> or C<+>, the values in the hash may be arrays. Given
-the input "A A A B B" and the rule:
-
- rule letters {
- <vowel>* <consonant>*
- }
-
-The match object will contain the pairs:
-
- "vowel" => ["A", "A", "A"]
- "consonant" => ["B", "B"]
-
-X<$( ) operator>
-
-Use the C<$( )> operator to count the number of matches in each group (by
-casting it to a scalar):
-
- $($<vowel>) == 3
-
-=head3 Inline PIR
-
-=for author
-
-Needs expansion.
-
-=end for
-
-X<{{ }}>
-X<double curly brackets>
-Sometimes NQP isn't quite flexible enough to handle transforms appropriately.
-In a PGE rule, the C<{{ }}> double curly brackets demarcate inline-PIR mode.
-PGE will execute any PIR code in those brackets. You can access C<$/> directly
-in the grammar without having to jump into NQP.
-
-=head3 PAST Nodes
-
-X<PAST>
-X<PAST nodes>
-NQP's job is to make abstract syntax trees. These trees are all objects -- and
-as such, instances of PAST nodes. Each PAST class represents a unique program
-construct. These constructs are common and simple, but combine to represent
-complicated programming structures.
-
-=head3 Making Trees
-
-Every action has the ability to create a PAST node that represents that action,
-as well as any children of that node. Calling C<make> on that node adds it into
-the growing PAST tree that PCT maintains. Once the C<TOP> rule matches
-successfully and returns, PCT optimizes and converts that tree into PIR and PBC
-for execution.
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch07_dynpmcs.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch07_dynpmcs.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,237 +0,0 @@
-=pod
-
-=head1 Dynamic C-level Objects
-
-Z<CHP-11>
-
-PMCs are one of the four fundamental data types in Parrot, and definitely one
-of the most useful. A PMC can contain a single scalar value (integer, floating
-point number, string), an array of values, a subroutine, a namespace, or an
-entire list of other data types as well. PMCs are the basis for all higher
-order data types in Parrot, and are flexible enough to be used for any
-purpose that an HLL needs.
-
-All the common PMC types are included in the Parrot repository and built directly
-into libparrot and the parrot executable. However, the system is not rigid; new
-PMC types can be defined externally and loaded into Parrot at a later time. In
-this way, HLLs and libraries and applications can add new data types to Parrot
-at the C code level, which helps to ensure speed and efficiency. PMCs loaded
-this way are called X<dynamic PMCs;dynpmcs> Dynamic PMCs or I<dynpmcs>.
-
-=head2 PIR Classes
-
-It's worth a quick diversion here to talk about the difference between a pure
-PIR class object, and a PMC. Even though classes written in PIR can inherit from
-an existing PMC type, they aren't all their own type of PMC. In fact, classes
-written in PIR are all of the Object PMC type. In order to add a new fundamental
-PMC type to Parrot, it needs to be written in C N<well, a superset of C anyway>
-and it needs to be compiled using the X<PMC compiler> PMC compiler.
-
-=head2 Writing PMCs
-
-In the strictest sense, PMCs are written in C and are compiled by your local
-C compiler into machine code for linking with libparrot or the parrot
-executable. However, Parrot's build process makes use of a special PMC compiler
-program that converts PMCs defined in a special C-like script to ordinary
-C code. The PMC compiler adds all the necessary boiler plate code and installs
-the PMC type into Parrot for use. The PMC script is like a macro superset
-N<although the functionality is a little bit more involved then is available
-in the normal C preprocessor> over the C language. All valid C is valid in
-PMC scripts, but there are also a few additions that help to make common tasks
-a little easier.
-
-The PMC script was born of conflicting necessities. The internals of Parrot
-are all written according to the ISO C89 standard for maximum portability.
-However, PIR and languages that are built on top of Parrot are typically
-object-oriented (or have some OO capabilities). PMCs are like classes,
-they have data and methods, and they can inherit from parent PMCs.
-
-C is low-level and portable, which is desirable. But Parrot needed some
-support for OO features that C doesn't have, and the C preprocessor
-can't support directly. To support the necessary features, and to make
-the task of writing PMCs just a little bit easier, the Parrot developers
-created a PMC compiler program that takes a special PMC script and converts
-it into standard ISO C89.
-
-=head3 PMC Files
-
-PMC files have a C<.pmc> file extension. They're written in a C-like
-language with a few additions to help with creating PMCs. PMC files do
-not natively allow POD documentation, so all such documentation must be
-enclosed in C</* */> comments. All PMC files that ship with Parrot
-include significant file-level and function-level documentation to help
-explain how the PMCs operate.
-
-=head3 C<pmclass> Definitions
-
-A PMC file can contain a single PMC class definition and any other helper
-functions or data structure definitions that are needed to support the
-PMC. To define a PMC class in the PMC file, you use the C<pmclass>
-statement. Everything outside the C<pmclass> definition will be ignored by
-the PMC compiler and passed through verbatim into the generated C<.c> file.
-Inside the C<pmclass> definition are going to be all the VTABLE and METHOD
-declarations for the PMC.
-
-A standard definition can contain a number of parts. Here's a pseudo-grammar
-for them:
-
- pmclass CLASSNAME [extends PARENT]? [provides INTERFACE] [FLAGS]* {
- /* Attributes defined here */
-
- /* VTABLE and METHODs defined here. */
-
- }
-
-The C<extends> keyword is optional, but allows us to specify that this
-PMC class is a subtype of the given type. If we have an C<extends>
-in the definition, we can use the C<SUPER> keyword throughout the PMC
-file to refer to the parent type.
-
-The C<FLAGS> are a series of flags that can be specified to determine
-how the PMC behaves and how it's constructed internally. The C<need_ext>
-flag assigns a special C<PMC_EXT> data structure to the PMC structure
-internally. C<PMC_EXT> is necessary to handle data sharing between threads
-or interpreters, storing attributes in the PMC, and a few other uses as
-well. The C<singleton> flag means that there can only be one instantiated
-object of this class. The C<is_ro> and C<has_ro> flags indicate that the
-PMC class is read-only or that it contains read-only data, respectively.
-The C<is_shared> flag indicates that the PMC is intended to be shared
-between multiple interpreters, and therefore special synchronization
-logic should be applied. The C<abstract> flag indicates that the PMC
-class cannot be instantiated directly, but can be inherited from by a
-non-abstract PMC class.
-
-The C<provides> keyword is used to show that the PMC provides certain
-standard interfaces. For instance, you can specify C<provides array>
-and then Parrot will enable us to write things like C<$P0[2]> in PIR
-code to access the PMC using integer indices. C<provides hash> means
-that we can use string and PMC keys to access values in the PMC. These
-C<provides> each correspond to a series of VTABLE interfaces that the
-PMC must provide, or must inherit. Without the necessary VTABLE
-interfaces available, Parrot may try to perform illegal operations and
-things will go badly. We'll talk about all the available C<provides>
-interfaces and the VTABLE interfaces that they must define.
-
-=head3 Attributes
-
-PMCs can be given a custom set of data field attributes using the C<ATTR>
-keyword. ATTR allows the PMC to be extended to contain custom data
-structures that are automatically managed by Parrot's memory subsystem.
-Here's an example:
-
- pmclass Foo {
- ATTR INTVAL bar;
- ATTR PMC baz;
-
- ...
- }
-
-The attributes are stored in a custom data structure that can be accessed
-using a macro with the same name as the PMC, but all upper-case:
-
- Parrot_Foo_Attributes * attrs = PARROT_FOO(SELF);
- attrs->bar = 7; /* it's an INTVAL */
- attrs->baz = pmc_new( ... ) /* it's a PMC */
-
-Notice how the type name of the attributes structure is C<Parrot_>,
-followed by the name of the PMC with the same capitalization as is used
-in the C<pmclass> definition, followed by C<_Attributes>. The macro to
-return this structure is C<PARROT_> followed by the name of the PMC in
-all caps.
-
-=head3 C<INTERP>, C<SUPER> and C<SELF>
-
-The PMC compiler enables us to use a few pre-defined variable names
-throughout the file to make things easier. The C<INTERP> keyword always
-contains a reference to the current interpreter structure. This keyword is
-included by default in all VTABLE interfaces and all PMC methods. It is not
-automatically included in any extra helper functions that you define in
-the PMC file.
-
-Here's an example of a VTABLE interface function:
-
- VTABLE Foo(INVAR PMC, INVAR INTVAL)
- {
- ...
- }
-
-The PMC compiler will convert this to the following C function definition:
-
- void Foo(PARROT_INTERP, PMC *self, PMC *arg_1, INTVAL arg_2)
- {
- ...
- }
-
-The C<interp> and C<self> variables are provided in all VTABLE interfaces,
-even though you don't have to define them explicitly in the PMC file.
-
-If the C<pmclass> definition uses the C<extends> keyword, a reference to
-a member of the parent class is also contained in the C<SUPER> variable.
-The C<SUPER()> function calls the VTABLE interface from the parent class.
-
- VTABLE destroy()
- {
- SUPER(); /* Call the parent PMC's VTABLE */
- }
-
-The PMC compiler also allows the use of "method syntax" for the C<SELF> and
-C<SUPER> variables:
-
- SUPER.clone() /* Call the clone VTABLE interface on SUPER */
- SELF.destroy() /* Call the destroy VTABLE interface on SELF */
-
-Or, you can call the VTABLE interfaces more directly:
-
- VTABLE_clone(INTERP, SUPER)
- VTABLE_destroy(INTERP, SELF)
-
-=head3 PMC Compiler
-
-The PMC compiler is a small program written in Perl 5 that's part of the
-normal Parrot build process. It converts all C<.pmc> files to C<.c> files
-for final compilation. The long-term goal for Parrot is to not be dependent
-on Perl 5 for configuration and building, but for now Perl 5 is required
-when building Parrot.
-
-=head2 VTABLE Function Definitions
-
-=head3 VTABLE Functions Parameters
-
-VTABLE functions are defined just like ordinary C functions, almost. Here's
-a normal definition for a VTABLE method:
-
- VTABLE VTABLENAME (PARAMETERS) {
- /* ordinary C here, almost */
- }
-
-You can't just name your VTABLE functions anything you want. There is a
-predefined list of VTABLE function names, and you must name it exactly
-the same as the one you are trying to implement. The PARAMETERS list
-is pretty particular as well: Each VTABLE function type has a specific
-parameter list that must be implemented exactly or else the compiler
-will throw a warning.
-
-=head2 Methods
-
-VTABLES are standard, but they're rigid. They need to have the exact name
-that Parrot expects, and they need to have the exact function signature
-that Parrot expects too. VTABLES are responsible for the low-level basic
-access operations that all data types need to implement. However, to get
-more out of your PMCs, we need a more flexible want to interact with them.
-
-Enter methods, which are ways to extend the functionality of your PMC
-in ways that the PMC needs. Methods allow the developer to add all sorts
-of arbitrary functionality to a PMC that the VTABLE functions themselves
-cannot define.
-
-=head2 Dynpmcs
-
-=head3 Loading dynpmcs
-
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch08_dynops.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch08_dynops.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,266 +0,0 @@
-=pod
-
-=head1 Dynamic Opcodes
-
-Z<CHP-12>
-
-The smallest executable component is not the compilation unit or even the
-subroutine, but is actually the I<opcode>. Opcodes in Parrot, like opcodes in
-other machines (both virtual and physical), are individual instructions that
-implement low-level operations in the machine. In the world of
-microprocessors, the word "opcode" typically refers to the numeric identifier
-for each instructions. The human-readable word used in the associated assembly
-language is called the "mnemonic". An assembler, among other tasks, is
-responsible for converting mnemonics into opcodes for execution. In Parrot,
-instead of referring to an instruction by different names depending on what
-form it's in, we just call them all "opcodes".
-
-=head2 Opcodes
-
-Opcodes are the smallest logical execution element in Parrot. An
-individual opcode corresponds, in an abstract kind of way, with a single
-machine code instruction for a particular hardware processor
-architecture. Parrot is a pretty high-level virtual machine, and even though
-its opcodes represent the smallest bits of executable code in Parrot, they
-are hardly small or low-level by themselves. In fact, some Parrot opcodes
-implement some complex operations and algorithms. Other opcodes are more
-traditional, performing basic arithmetic and data manipulating operations.
-
-Parrot comes with about 1,200 opcodes total in a basic install. It also has a
-facility for dynamically loading additional opcode libraries, called
-C<dynops>, as needed.
-
-=head3 Opcode naming
-
-To the PIR and PASM programmers, opcodes appear to be polymorphic. That
-is, some opcodes appear to have multiple allowable argument formats. This is
-just an illusion, however. Parrot opcodes are not polymorphic, although
-certain features enable them to appear that way to the PIR programmer.
-Different argument list formats are detected during parsing and mapped to
-separate, unique opcode names.
-
-During the Parrot build process, opcode definitions called "ops files" are
-translated into C code prior to compilation. This translation process renames
-all ops to use unique names depending on their argument lists. An op "foo"
-that takes two PMCs and returns an integer would be renamed to C<foo_i_p_p>.
-Another op named "foo" that takes one floating point number and returns a
-string would be renamed to C<foo_s_n>. So, when we call the opcode "foo" from
-our PIR program, the PIR compiler will look at the list of arguments and
-call the appropriate opcode to handle it.
-
-=head2 Writing Opcodes
-
-Writing Opcodes, like writing PMCs, is done in a C-like language which is
-later compiled into C code by the X<opcode compiler> opcode compiler. The
-opcode script represents a thin overlay on top of ordinary C code: All
-valid C code is valid opcode script. There are a few neat additions that
-make writing opcodes easier. The C<INTERP> keyword, for instance, contains
-a reference to the current interpreter structure. C<INTERP> is always
-available when writing opcodes, even though it isn't defined anywhere.
-Opcodes are all defined with the C<op> keyword.
-
-Opcodes are written in files with the C<.ops> extension. The core
-operation files are stored in the C<src/ops/> directory.
-
-=head3 Opcode Parameters
-
-Each opcode can take any fixed number of input and output arguments. These
-arguments can be any of the four primary data types--INTVALs, PMCs, NUMBERS
-and STRINGs--but can also be one of several other types of values including
-LABELs, KEYs and INTKEYs.
-
-Each parameter can be an input, an output or both, using the C<in>, C<out>,
-and C<inout> keywords respectively. Here is an example:
-
- op Foo (out INT, in NUM)
-
-This opcode could be called like this:
-
- $I0 = Foo $N0 # in PIR syntax
- Foo I0, N0 # in PASM syntax
-
-When Parrot parses through the file and sees the C<Foo> operation, it
-converts it to the real name C<Foo_i_n>. The real name of an opcode
-is its name followed by an underscore-separated ordered list of
-the parameters to that opcode. This is how Parrot appears to use
-polymorphism: It translates the overloaded opcode common names into
-longer unique names depending on the parameter list of that opcode. Here
-is a list of some of the variants of the C<add> opcode:
-
- add_i_i # $I0 += $I1
- add_n_n # $N0 += $N1
- add_p_p # $P0 += $P1
- add_i_i_i # $I0 = $I1 + $I2
- add_p_p_i # $P0 = $P1 + $I0
- add_p_p_n # $P0 = $P1 + $N0
-
-This isn't a complete list, but you should get the picture. Each different
-combination of parameters translates to a different unique operation, and
-each operation is remarkably simple to implement. In some cases, Parrot
-can even use its multi-method dispatch system to call opcodes which are
-heavily overloaded, or for which there is no exact fit but the parameters
-could be coerced into different types to complete the operation. For
-instance, attempting to add a STRING to a PMC might coerce the string into
-a numerical PMC type first, and then dispatch to the C<add_p_p_n> opcode.
-This is just an example, and the exact mechanisms may change as more opcodes
-are added or old ones are deleted.
-
-Parameters can be one of the following types:
-
-=over 4
-
-=item * INT
-
-A normal integer type, such as one of the I registers
-
-=item * NUM
-
-A floating point number, like is used in the N registers
-
-=item * STR
-
-A string, such as in a S register
-
-=item * PMC
-
-A PMC value, like a P register
-
-=item * KEY
-
-A key value. Something like C<[5 ; "Foo" ; 6 ; "Bar"]>. These are the same
-as indexes that we use in PMC aggregates.
-
-=item * INTKEY
-
-A basic key value that uses only integer values C<[1 ; 2 ; 3 ]>.
-
-=item * LABEL
-
-A label value, which represents a named statement in PIR or PASM code.
-
-=back
-
-In addition to these types, you need to specify the direction that data is
-moving through that parameter:
-
-=over 4
-
-=item * in
-
-The parameter is an input, and should be initialized before calling the op.
-
-=item * out
-
-The parameter is an output
-
-=item * inout
-
-The parameter is an input and an output. It should be initialized before
-calling the op, and it's value will change after the op executes.
-
-=item * invar
-
-The parameter is a reference type like a String or PMC, and it's internals
-might change in the call.
-
-=back
-
-=head3 Opcode Control Flow
-
-Some opcodes have the ability to alter control flow of the program they
-are in. There are a number of control behaviors that can be implemented,
-such as an unconditional jump in the C<goto> opcode, or a subroutine
-call in the C<call> code, or the conditional behavior implemented by C<if>.
-
-At the end of each opcode you can call a C<goto> operation to jump to the
-next opcode to execute. If no C<goto> is performed, control flow will
-continue like normal to the next operation in the program. In this way,
-opcodes can easily manipulate control flow. Opcode script provides a
-number of keywords to alter control flow:
-
-=over 4
-
-=item * NEXT()
-
-The keyword C<NEXT> contains the address of the next opcode in memory. At the
-end of a normal op you don't need to call C<goto NEXT()> because moving to the
-next opcode in the program is the default behavior of Parrot N<You can do
-this if you really want to, but it really wouldn't help you any>. The C<NEXT>
-keyword is frequently used in places like the C<invoke> opcode to create a
-continuation to the next opcode to return to after the subroutine returns.
-
-=item * ADDRESS()
-
-Jumps execution to the given address.
-
- ADDRESS(x);
-
-Here, C<x> should be an C<opcode_t *> value of the opcode to jump to.
-
-=item * OFFSET()
-
-Jumps to the address given as an offset from the current address.
-
- OFFSET(x)
-
-Here, C<x> is an offset in C<size_t> units that represents how far forward
-(positive) or how far backwards (negative) to jump to.
-
-=item * POP()
-
-C<POP> pops the next opcode address off the control stack. To put an address
-onto the control stack, use the C<PUSH> keyword instead. C<PUSH> takes a single
-C<opcode_t *> argument to store, and C<POP> returns a single C<opcode_ *>
-value.
-
-=back
-
-=head2 The Opcode Compiler
-
-As we've seen in our discussions above, ops have a number of transformations
-to go through before they can be become C code and compiled into Parrot.
-The various special variables like C<$1>, C<INTERP> and C<ADDRESS> need to be
-converted to normal variable values. Also, each runcore requires the ops be
-compiled into various formats: The slow and fast cores need the ops to be
-compiled into individual subroutines. The switch core needs all the ops to be
-compiled into a single function using a large C<switch> statement. The
-computed goto cores require the ops be compiled into a large function with a
-large array of label addresses.
-
-Parrot's opcode compiler is a tool that's tasked with taking raw opcode files
-with a C<.ops> extension and converting them into several different formats,
-all of which need to be syntactically correct C code for compilation.
-
-=head2 Dynops
-
-Parrot has about 1200 built-in opcodes. These represent operations which are
-sufficiently simple and fundamental, but at the same time are very common.
-However, these do not represent all the possible operations that some
-programmers are going to want to use. Of course, not all of those 1200 ops
-are unique, many of them are overloaded variants of one another. As an example
-there are about 36 variants of the C<set> opcode, to account for all the
-different types of values you may want to set to all the various kinds of
-registers. The number of unique operations therefore is much smaller then 1200.
-
-This is where I<dynops> come in. Dynops are dynamically-loadable libraries of
-ops that can be written and compiled separately from Parrot and loaded in at
-runtime. dynops, along with dynpmcs and runtime libraries are some of the
-primary ways that Parrot can be extended.
-
-Parrot ships with a small number of example dynops libraries in the file
-L<src/dynoplibs/>. These are small libraries of mostly nonsensical but
-demonstrative opcodes that can be used as an example to follow.
-
-Dynops can be written in a C<.ops> file like the normal built-in ops are.
-The ops file should use C<#include "parrot/extend.h"> in addition to any
-other libraries the ops need. They can be compiled into C using the opcode
-compiler, then compiled into a shared library using a normal C compiler. Once
-compiled, the dynops can be loaded into Parrot using the .loadlib directive.
-
-=cut
-
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch10_opcode_reference.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch10_opcode_reference.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,2953 +0,0 @@
-=pod
-
-=head1 Instruction Reference
-
-Z<CHP-10>
-
-This chapter contains a condensed reference to the Parrot virtual
-machine's native instruction set, generally called opcodes. All opcodes
-are valid in both PIR and PASM, and correspond to the bytecode
-instructions.
-
-For complete details on each opcode and the latest changes, read the
-documentation in F<docs/ops/>, or look at all the C<.ops> files in the
-F<ops/> directory.
-
-We've followed a few conventions. C<DEST> is always the register where
-the result of the operation is stored. Sometimes the original value of
-C<DEST> is one of the source values. C<VAL> indicates that the actual
-value might be a literal integer, float, or string, or a register
-containing an integer, float, string, or PMC. See the F<.ops> files
-for the combinations allowed with a particular operation.
-
-=head3 abs
-
-X<abs opcode (PASM)>
-
- abs R<DEST>
- abs R<DEST>, R<VAL>
-
-Return the absolute value of a number. If R<VAL> is left out, R<DEST>
-gets the absolute value of itself.
-
-I<Arguments: IR or NR or IR, I or IR, N or NR, I or NR, N>
-
-=head3 acos
-
-X<acos opcode (PASM)>
-
- acos R<DEST>, R<VAL>
-
-The arc cosine of R<VAL> in radians.
-
-I<Arguments: NR, N or NR, I>
-
-=head3 add
-
-X<add opcode (PASM)>
-
- add R<DEST>, R<VAL>
- add R<DEST>, R<VAL>, R<VAL>
-
-Add two values and return the sum. If only one R<VAL>, add R<VAL> to
-R<DEST>.
-
-I<Arguments: IR, I or NR, I or NR, N or P, I or P, N or P, P or IR, I, I
-or NR, N, I or NR, N, N or P, P, I or P, P, N or P, P, P>
-
-=head3 addattribute
-
-X<addattribute opcode (PASM)>
-
- addattribute R<CLASS>, R<ATTR>
-
-Add the attribute name R<ATTR> to class R<CLASS>.
-
-I<Arguments: P, S>
-
-=head3 addparent
-
-X<addparent opcode (PASM)>
-
- addparent R<CLASS1>, R<CLASS2>
-
-Add class R<CLASS2> to the list of parent classes for R<CLASS1>.
-
-I<Arguments: P, P>
-
-=head3 and
-
-X<and opcode (PASM)>
-
- and R<DEST>, R<VAL1>, R<VAL2>
-
-Logical AND. Return R<VAL1> if it's false; otherwise, return R<VAL2>.
-
-I<Arguments: IR, I, I or P, P, P>
-
-=head3 asec
-
-X<asec opcode (PASM)>
-
- asec R<DEST>, R<VAL>
-
-The arc secant of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 asin
-
-X<asin opcode (PASM)>
-
- asin R<DEST>, R<VAL>
-
-The arc sine of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 assign
-
-X<assign opcode (PASM)>
-
- assign R<DEST>, R<VAL>
-
-Assign a value to a PMC.
-
-I<Arguments: SR, S or P, I or P, N or P, S or P, P>
-
-=head3 atan
-
-X<atan opcode (PASM)>
-
- atan R<DEST>, R<VAL>
- atan R<DEST>, R<VAL1>, R<VAL2>
-
-The arc tangent of R<VAL1> / R<VAL2> in radians (sign significant). If
-R<VAL2> is omitted, then just the arc tangent of R<VAL>.
-
-I<Arguments: NR, I or NR, N or NR, I, I or NR, I, N or NR, N, I or NR,
-N, N>
-
-=head3 band
-
-X<band opcode (PASM)>
-
- band R<DEST>, R<VAL>
- band R<DEST>, R<VAL>, R<VAL>
-
-Bitwise AND on two values. If only one R<VAL>, bitwise AND on R<DEST>
-and R<VAL>.
-
-I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
-
-=head3 bands
-
-X<bands opcode (PASM)>
-
- bands R<DEST>, R<VAL>
- bands R<DEST>, R<VAL>, R<VAL>
-
-Bitwise AND on two strings. If only one R<VAL>, bitwise AND on R<DEST>
-and R<VAL>.
-
-I<Arguments: SR, S or P, S or P, P or SR, S, S or P, P, S or P, P, P>
-
-=head3 bnot
-
-X<bnot opcode (PASM)>
-
- bnot R<DEST>, R<VAL>
-
-Bitwise NOT on R<VAL>.
-
-I<Arguments: IR, I or P, P>
-
-=head3 bnots
-
-X<bnots opcode (PASM)>
-
- bnots R<DEST>, R<VAL>
-
-Bitwise NOT on string R<VAL>.
-
-I<Arguments: SR, S or P, P>
-
-=head3 bor
-
-X<bor opcode (PASM)>
-
- bor R<DEST>, R<VAL>, R<VAL>
-
-Bitwise OR on two values. If only one R<VAL>, bitwise OR on R<DEST>
-and R<VAL>.
-
-I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
-
-=head3 bors
-
-X<bors opcode (PASM)>
-
- bors R<DEST>, R<VAL>, R<VAL>
-
-Bitwise OR on two strings. If only one R<VAL>, bitwise OR on R<DEST>
-and R<VAL>.
-
-I<Arguments: SR, S or P, S or P, P or SR, S, S or P, P, S or P, P, P>
-
-=head3 bounds
-
-X<bounds opcode (PASM)>
-
- bounds R<INT>
-
-Toggle bytecode bounds checking in the interpreter (0 for off, any other
-value for on).
-
-I<Arguments: I>
-
-=head3 branch
-
-X<branch opcode (PASM)>
-
- branch R<LABEL>
-
-Branch to a label. The label is calculated as a relative offset.
-
-I<Arguments: I>
-
-=head3 branch_cs
-
-X<branch_cs opcode (PASM)>
-
- branch_cs R<FIXUP_ENTRY>
-
-Intersegment branch to the location of the given fixup table entry.
-
-I<Arguments: S>
-
-=head3 bsr
-
-X<bsr opcode (PASM)>
-
- bsr R<LABEL>
-
-Branch to a label, like C<branch>, but also push the current location
-onto the call stack so C<ret> can return to it.
-
-I<Arguments: I>
-
-=head3 bxor
-
-X<bxor opcode (PASM)>
-
- bxor R<DEST>, R<VAL>
- bxor R<DEST>, R<VAL>, R<VAL>
-
-Bitwise XOR on two values. If only one R<VAL>, bitwise XOR on R<DEST>
-and R<VAL>.
-
-I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
-
-=head3 bxors
-
-X<bxors opcode (PASM)>
-
- bxors R<DEST>, R<VAL>
- bxors R<DEST>, R<VAL>, R<VAL>
-
-Bitwise XOR on two strings. If only one R<VAL>, bitwise XOR on R<DEST>
-and R<VAL>.
-
-I<Arguments: SR, S or P, S or P, P or SR, S, S or P, P, S or P, P, P>
-
-=head3 callmethod
-
-X<callmethod opcode (PASM)>
-
- callmethod
- callmethod R<METHODNAME>
-
-Call the method named R<METHODNAME> on the object stored in C<P2>
-according to the Parrot Calling Conventions. If no method name, pull the
-name from C<S0>.
-
-I<Arguments: S>
-
-=head3 callmethodcc
-
-X<callmethodcc opcode (PASM)>
-
- callmethodcc
- callmethodcc R<METHODNAME>
-
-Call the method named R<METHODNAME> on the object stored in C<P2>
-according to the Parrot Calling Conventions. If no method name, pull the
-name from C<S0>. Also create a return continuation and store it in
-C<P1>.
-
-I<Arguments: S>
-
-=head3 can
-
-X<can opcode (PASM)>
-
- can R<DEST>, R<OBJECT>, R<METHODNAME>
-
-Return a true value if R<OBJECT> I<can> do the R<METHODNAME> method,
-otherwise return a false value.
-
-I<Arguments: IR, P, S>
-
-=head3 ceil
-
-X<ceil opcode (PASM)>
-
- ceil R<DEST>
- ceil R<DEST>, R<VAL>
-
-Set R<DEST> to the smallest integral value less than or equal to R<VAL>
-(if present) or itself (if not).
-
-I<Arguments: NR or IR, N or NR, N>
-
-=head3 checkevents
-
-X<checkevents opcode (PASM)>
-
- checkevents
-
-Check the interpreter's task queue for unhandled events and run the associated
-event handlers.
-
-=head3 chopn
-
-X<chopn opcode (PASM)>
-
- chopn R<DEST>, R<VAL1>
- chopn R<DEST>, R<VAL1>, R<VAL2>
-
-Remove R<VAL2> number of characters from string R<VAL1>. If no
-R<VAL2>, remove R<VAL> number of characters from string R<DEST>.
-
-I<Arguments: SR, I or SR, S, I>
-
-=head3 chr
-
-X<chr opcode (PASM)>
-
- chr R<DEST>, R<INT>
-
-Return the character represented by the given number.
-
-I<Arguments: SR, I>
-
-=head3 class
-
-X<class opcode (PASM)>
-
- class R<CLASS>, R<OBJECT>
-
-Return the R<CLASS> of the given R<OBJECT>.
-
-I<Arguments: P, P>
-
-=head3 clear_eh
-
-X<clear_eh>
-
- clear_eh
-
-Clear the most recent exception handler.
-
-See also: C<set_eh>, C<throw>.
-
-=head3 clearX
-
-X<cleari opcode (PASM)>
-X<clearn opcode (PASM)>
-X<clearp opcode (PASM)>
-X<clears opcode (PASM)>
-
- cleari
- clearn
- clearp
- clears
-
-Clear all registers of the given type ("i" = integer, "n" = float, "p"
-= PMC, "s" = string). Integer and float registers clear to zero; string
-and PMC registers clear to NULL.
-
-=head3 clone
-
-X<clone opcode (PASM)>
-
- clone R<DEST>, R<VAL>
-
-Clone (deep copy) a string or PMC and return the result.
-
-I<Arguments: SR, S or P, P>
-
-=head3 close
-
-X<close opcode (PASM)>
-
- close R<DEST>
-
-Close the filehandle in the given register.
-
-I<Arguments: P>
-
-=head3 cmod
-
-X<cmod opcode (PASM)>
-
- cmod R<DEST>, R<VAL1>, R<VAL2>
-
-C's built-in mod operator.
-
-See also C<mod>.
-
-I<Arguments: IR, I, I or NR, N, N or P, P, I or P, P, N or P, P, P>
-
-=head3 cmp
-
-X<cmp (comparison);opcode (PASM)>
-
- cmp R<DEST>, R<VAL1>, R<VAL2>
-
-Set R<DEST> to 1 if R<VAL1> is greater then R<VAL2>, to -1 if it's less then
-R<VAL2> or to zero if both are equal. If R<VAL1> and R<VAL2> are both PMCs,
-then the type of comparison depends on R<VAL1>.
-
-I<Arguments: IR, I, I or IR, N, N or IR, S, S or IR, P, I or IR, P, N
-IR, P, S or IR, P, P>
-
-=head3 cmp_num
-
-X<cmp_num opcode (PASM)>
-
- cmp_num R<DEST>, R<VAL1>, R<VAL2>
-
-Like C<cmp>, but forces numeric comparison.
-
-I<Arguments: IR, P, P>
-
-=head3 cmp_str
-
-X<cmp_str opcode (PASM)>
-
- cmp_str R<DEST>, R<VAL1>, R<VAL2>
-
-Like C<cmp>, but forces string comparison.
-
-I<Arguments: IR, P, P>
-
-=head3 cmp_pmc
-
-X<cmp_pmc opcode (PASM)>
-
- cmp_pmc R<DEST>, R<VAL1>, R<VAL2>
-
-Like C<cmp>, but places a PMC in R<DEST>. This opcode is useful for avoiding
-semipredicate problems in HLLs where two PMCs are not always comparable.
-
-I<Arguments: P, P, P>
-
-=head3 collect
-
-X<collect opcode (PASM)>
-
- collect
-
-Trigger a garbage collection (GC) run.
-
-=head3 collectoff
-
-X<collectoff opcode (PASM)>
-
- collectoff
-
-Disable garbage collection runs (nestable).
-
-=head3 collecton
-
-X<collecton opcode (PASM)>
-
- collecton
-
-Re-enable garbage collection runs.
-
-=head3 compile
-
-X<compile opcode (PASM)>
-
- compile R<DEST>, R<COMPILER>, R<SOURCE>
-
-Compile a string of source code with a given compiler PMC and store
-the result.
-
-I<Arguments: P, P, S>
-
-=head3 compreg
-
-X<compreg opcode (PASM)>
-
- compreg R<DEST>, R<TYPE>
-
-Return a compiler PMC for a particular type of source code.
-
-I<Arguments: P, S>
-
- compreg R<TYPE>, R<SUB>
-
-Register R<SUB> as a compiler for language R<TYPE>.
-
-I<Arguments: S, P>
-
-=head3 concat
-
-X<concat opcode (PASM)>
-
- concat R<DEST>, R<VAL>
- concat R<DEST>, R<VAL>, R<VAL>
-
-Concatenate two strings. If only one R<VAL>, concatenate R<VAL> onto
-R<DEST>.
-
-I<Arguments: SR, S or SR, S, S or P, P, S or P, P, P>
-
-=head3 cos
-
-X<cos opcode (PASM)>
-
- cos R<DEST>, R<VAL>
-
-The cosine of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 cosh
-
-X<cosh opcode (PASM)>
-
- cosh R<DEST>, R<VAL>
-
-The hyperbolic cosine of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 debug
-
-X<debug opcode (PASM)>
-
- debug R<FLAG>
-
-Toggle debugging in the interpreter (0 for off, any other value for on).
-
-I<Arguments: I>
-
-=head3 dec
-
-X<dec opcode (PASM)>
-
- dec R<DEST>
-
-Decrement a value by 1.
-
-I<Arguments: I or N or P>
-
-=head3 decodelocaltime
-
-X<decodelocaltime opcode (PASM)>
-
- decodelocaltime R<DEST>, R<VAL>
-
-Set R<DEST> to a new array which represents the decoded time of the
-given epoch-seconds value shifted to local time.
-
-I<Arguments: P, I>
-
-=head3 decodetime
-
-X<decodetime opcode (PASM)>
-
- decodetime R<DEST>, R<VAL>
-
-Set R<DEST> to a new array which represents the decoded time of the
-given epoch-seconds value.
-
-I<Arguments: P, I>
-
-=head3 defined
-
-X<defined opcode (PASM)>
-
- defined R<DEST>, R<PMC>
- defined R<DEST>, R<PMC>[R<KEY>]
-
-Test a keyed PMC value for definedness. If no R<KEY>, test a PMC for
-definedness.
-
-I<Arguments: IR, P>
-
-=head3 delete
-
-X<delete opcode (PASM)>
-
- delete R<DEST>[R<KEY>]
-
-Delete a keyed value from an aggregate PMC.
-
-I<Arguments: P>
-
-=head3 delprop
-
-X<delprop opcode (PASM)>
-
- delprop R<PMC>, R<NAME>
-
-Delete a named property from a PMC.
-
-I<Arguments: P, S>
-
-See also: C<setprop> and C<getprop>.
-
-=head3 deref
-
-X<deref opcode (PASM)>
-
- deref R<DEST>, R<REF>
-
-Set R<DEST> to the PMC that R<REF> refers to.
-
-I<Arguments: P, P>
-
-=head3 die_hard
-
-X<die_hard opcode (PASM)>
-
- die_hard R<LEVEL>, R<ERROR>
-
-Die at a given level of severity, and with the given error code.
-
-I<Arguments: I, I>
-
-See also: C<exit>.
-
-=head3 div
-
-X<div opcode (PASM)>
-
- div R<DEST>, R<VAL>
- div R<DEST>, R<VAL1>, R<VAL2>
-
-Divide R<VAL1> by R<VAL2>. If R<VAL2> is left out, divide R<DEST> by
-R<VAL>.
-
-I<Arguments: IR, I or NR, I or NR, N or P, I or P, N or P, P or IR, I, I
-or NR, N, I or NR, N, N or P, P, I or P, P, N or P, P, P>
-
-=head3 dlfunc
-
-X<dlfunc opcode (PASM)>
-
- dlfunc R<DEST>, R<LIBRARY>, R<SYMBOL>, R<SIGNATURE>
-
-Look up a symbol in a dynamic link library PMC and create a subroutine
-PMC for that symbol with the given signature.
-
-I<Arguments: P, P, S, S>
-
-=head3 dlvar
-
-X<dlvar opcode (PASM)>
-
- dlvar R<DEST>, R<LIBRARY>, R<SYMBOL>
-
-Look up a symbol in a dynamic link library PMC and create a
-PMC for that symbol.
-
-I<Arguments: P, P, S>
-
-=head3 does
-
-X<does opcode (PASM)>
-
- does R<DEST>, R<OBJECT>, R<VAL>
-
-Return a true value if R<OBJECT> I<does> provide the interface R<VAL>,
-otherwise return a false value.
-
-I<Arguments: I, P, S>
-
-=head3 downcase
-
-X<downcase opcode (PASM)>
-
- downcase R<DEST>
- downcase R<DEST>, R<VAL>
-
-Create a copy of the string in R<VAL> with all characters converted to
-lower case, and store it in R<DEST>. If R<VAL> is omitted, convert and
-replace the string in R<DEST>.
-
-I<Arguments: S or S, S>
-
-See also: C<upcase>, C<titlecase>.
-
-=head3 end
-
-X<end opcode (PASM)>
-
- end
-
-End execution within the current code segment or halt the interpreter
-if in the main code segment.
-
-=head3 enternative
-
-X<enternative opcode (PASM)>
-
- enternative
-
-Run the C<run_native> C function.
-
-=head3 eq
-
-X<eq opcode (PASM)>
-
- eq R<VAL>, R<VAL>, R<LABEL>
-
-Jump to a label if the two values are equal.
-
-I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC
-or P, S, IC or P, P, IC>
-
-=head3 eq_addr
-
-X<eq_addr opcode (PASM)>
-
- eq_addr R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> and R<VAL2> point to the same string or PMC.
-Note that this op compares the addresses of the two strings or PMCs,
-not simply their values.
-
-I<Arguments: S, S, IC or P, P, IC>
-
-=head3 eq_num
-
-X<eq_num opcode (PASM)>
-
- eq_num R<VAL>, R<VAL>, R<LABEL>
-
-Jump to a label if the two values are numerically equal.
-
-I<Arguments: P, P, IC>
-
-=head3 eq_str
-
-X<eq_str opcode (PASM)>
-
- eq_str R<VAL>, R<VAL>, R<LABEL>
-
-Jump to a label if the two strings are equal.
-
-I<Arguments: P, P, IC>
-
-=head3 err
-
-X<err opcode (PASM)>
-
- err R<DEST>
- err R<DEST>, R<CODE>
-
-Return the system error code to an integer destination or the system
-error message to a string destination. The two-argument version returns
-the system error message for a given code.
-
-I<Arguments: IR or SR or SR, I>
-
-=head3 errorsoff
-
-X<errorsoff opcode (PASM)>
-
- errorsoff R<VAL>
-
-Turn off errors of type R<VAL>.
-
-I<Arguments: I>
-
-=head3 errorson
-
-X<errorson opcode (PASM)>
-
- errorson R<VAL>
-
-Turn on errors of type R<VAL>.
-
-I<Arguments: I>
-
-=head3 exchange
-
-X<exchange opcode (PASM)>
-
- exchange R<REG>, R<REG>
-
-Exchange the contents of two registers.
-
-I<Arguments: IR, IR or NR, NR or SR, SR or P, P>
-
-=head3 exists
-
-X<exists opcode (PASM)>
-
- exists R<DEST>, R<PMC>[R<KEY>]
-
-Test a PMC key for existence.
-
-I<Arguments: IR, P>
-
-=head3 exit
-
-X<exit opcode (PASM)>
-
- exit R<STATUS>
-
-Exit the interpreter with a given R<STATUS>. (For extended exit status,
-throw an exception with severity C<EXCEPT_exit>.)
-
-I<Arguments: I>
-
-See also: C<throw>, C<die_hard>.
-
-=head3 exp
-
-X<exp opcode (PASM)>
-
- exp R<DEST>, R<VAL>
-
-Base of the natural logarithm, I<e>, to the power of R<VAL>.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 exsec
-
-X<exsec opcode (PASM)>
-
- exsec R<DEST>, R<VAL>
-
-The exsecant of R<VAL> in radians.
-
-I<Arguments: NR, N>
-
-=head3 fact
-
-X<fact opcode (PASM)>
-
- fact R<DEST>, R<INT>
-
-Return the factorial of R<INT>.
-
-I<Arguments: IR, I or NR, I>
-
-=head3 fdopen
-
-X<fdopen opcode (PASM)>
-
- fdopen R<DEST>, R<INT>, R<MODE>
-
-Get a FileHandle object for handle R<INT> with open mode R<MODE>.
-
-I<Arguments: P, I, S>
-
-=head3 find_chartype
-
-X<find_chartype opcode (PASM)>
-
- find_chartype R<DEST>, R<NAME>
-
-Find the chartype named R<NAME> and return its number in R<DEST>.
-
-I<Arguments: IR, S>
-
-=head3 find_encoding
-
-X<strings;encoding>
-X<find_encoding opcode (PASM)>
-
- find_encoding R<DEST>, R<NAME>
-
-Find the encoding named R<NAME> and return its number in R<DEST>.
-
-I<Arguments: IR, S>
-
-=head3 find_global
-
-X<find_global opcode (PASM)>
-
- find_global R<DEST>, R<NAME>
-
-Return a global variable with the given name.
-
-I<Arguments: P, S>
-
- find_global R<DEST>, R<NAMESPACE>, R<NAME>
-
-Return a global variable with the given name from the given namespace.
-
-I<Arguments: P, S, S or P, P, S>
-
-See also: C<store_global>.
-
-=head3 find_lex
-
-X<find_lex opcode (PASM)>
-
- find_lex R<DEST>, R<NAME>
- find_lex R<DEST>, R<DEPTH>, R<NAME>
- find_lex R<DEST>, R<DEPTH>, R<POSITION>
-
-Return the lexical variable of the given name from a lexical
-scratchpad. If R<DEPTH> is provided, only return a variable from the
-scratchpad at that depth. A find by position returns the variable at a
-particular position in the scratchpad.
-
-I<Arguments: P, S or P, I, S or P, I, I>
-
-See also: C<store_lex>.
-
-=head3 find_method
-
-X<find_method opcode (PASM)>
-
- find_method R<DEST>, R<PMC>, R<NAME>
-
-Look up a method by name in a PMC's vtable. Return a method PMC.
-
-I<Arguments: P, P, S>
-
-=head3 find_type
-
-X<find_type opcode (PASM)>
-
- find_type R<DEST>, R<NAME>
-
-Find the integer identifier for a PMC type or native Parrot datatype by name.
-
-I<Arguments: IR, S>
-
-See also: C<typeof>.
-
-=head3 findclass
-
-X<findclass opcode (PASM)>
-
- findclass R<DEST>, R<NAME>
-
-Return 1 if the class R<NAME> exists, and 0 otherwise.
-
-I<Arguments: IR, S>
-
-See also: C<typeof>.
-
-=head3 floor
-
-X<floor opcode (PASM)>
-
- floor R<DEST>
- floor R<DEST>, R<VAL>
-
-Return the largest integral value less than or equal to R<VAL> (if
-present) or itself (if not).
-
-I<Arguments: NR or IR, N or NR, N>
-
-=head3 foldup
-
-X<foldup opcode (PASM)>
-
- foldup R<DEST>
- foldup R<DEST>, R<SKIP>
-
-Return a new array holding all passed subroutine parameters. R<SKIP>
-defines an optional offset.
-
-I<Arguments: P or P, I>
-
-=head3 freeze
-
-X<freeze opcode (PASM)>
-
- freeze R<DEST>, R<VAL>
-
-Create a frozen image R<DEST> from PMC R<VAL>.
-
-I<Arguments: SR, P>
-
-See also: C<thaw>.
-
-=head3 gc_debug
-
-X<gc_debug opcode (PASM)>
-
- gc_debug R<INT>
-
-Toggle garbage collection debugging in the interpreter (0 for off, any
-other value for on).
-
-I<Arguments: I>
-
-=head3 gcd
-
-X<gcd opcode (PASM)>
-
- gcd R<DEST>, R<VAL>, R<VAL>
-
-Return the greatest common divisor of two values.
-
-I<Arguments: IR, I, I or IR, N, N>
-
-=head3 ge
-
-X<ge (greater than or equal);opcode (PASM)>
-
- ge R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is greater than or equal to R<VAL2>.
-
-I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC
-or P, S, IC or P, P, IC>
-
-=head3 ge_num
-
-X<ge_num opcode (PASM)>
-
- ge_num R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is numerically greater than or equal to R<VAL2>.
-
-I<Arguments: P, P, IC>
-
-=head3 ge_str
-
-X<ge_str opcode (PASM)>
-
- ge_str R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is stringwise greater than or equal to R<VAL2>.
-
-I<Arguments: P, P, IC>
-
-=head3 get_addr
-
-X<get_addr opcode (PASM)>
-
- get_addr R<DEST>, R<SUB>
-
-Get the absolute address of a subroutine PMC.
-
-I<Arguments: IR, P>
-
-See also: C<set_addr>.
-
-=head3 getattribute
-
-X<getattribute opcode (PASM)>
-
- getattribute R<DEST>, R<OBJECT>, R<OFFS>
-
-Get a reference to attribute number R<OFFS> from object R<OBJECT>.
-
-I<Arguments: P, P, I>
-
-See also: C<setattribute>, C<classoffset>.
-
-=head3 get_class
-
-X<get_class opcode (PASM)>
-
- get_class R<DEST>, R<NAME>
-
-Return the class PMC of the given name.
-
-I<Arguments: P, S>
-
-=head3 getfile
-
-X<getfile opcode (PASM)>
-
- getfile R<DEST>
-
-Return the name of the current file.
-
-I<Arguments: SR>
-
-=head3 getinterp
-
-X<getinterp opcode (PASM)>
-
- getinterp R<DEST>
-
-Get a PMC representing the current interpreter.
-
-I<Arguments: P>
-
-=head3 getline
-
-X<getline opcode (PASM)>
-
- getline R<DEST>
-
-Return the current line number.
-
-I<Arguments: IR>
-
-=head3 getpackage
-
-X<getpackage opcode (PASM)>
-
- getpackage R<DEST>
-
-Return the current package name.
-
-I<Arguments: SR>
-
-=head3 getprop
-
-X<getprop opcode (PASM)>
-
- getprop R<DEST>, R<NAME>, R<PMC>
-
-Return the value of a named property on a PMC.
-
-I<Arguments: P, S, P>
-
-See also: C<setprop> and C<prophash>.
-
-=head3 getstd*
-
-X<getstderr opcode (PASM)>
-X<getstdin opcode (PASM)>
-X<getstdout opcode (PASM)>
-
- getstderr R<DEST>
- getstdin R<DEST>
- getstdout R<DEST>
-
-Get a FileHandle object for the given standard handle.
-
-I<Arguments: P>
-
-=head3 gmtime
-
-X<gmtime opcode (PASM)>
-
- gmtime R<DEST>, R<VAL>
-
-Take the integer, which represents GMT epoch-seconds, and turn it into a
-formatted string.
-
-I<Arguments: SR, I>
-
-See also: C<localtime>.
-
-=head3 gt
-
-X<gt opcode (PASM)>
-
- gt R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is greater than R<VAL2>.
-
-I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC or
-P, S, IC or P, P, IC>
-
-=head3 gt_num
-
-X<gt_num opcode (PASM)>
-
- gt_num R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is numerically greater than R<VAL2>.
-
-I<Arguments: P, P, IC>
-
-=head3 gt_str
-
-X<gt_str opcode (PASM)>
-
- gt_str R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is stringwise greater than R<VAL2>.
-
-I<Arguments: P, P, IC>
-
-=head3 hav
-
-X<hav opcode (PASM)>
-
- hav R<DEST>, R<VAL>
-
-The haversine of R<VAL> in radians.
-
-I<Arguments: NR, N>
-
-=head3 if
-
-X<if (conditional);opcode (PASM)>
-
- if R<CONDITION>, R<LABEL>
-
-Jump to a label if the condition is a true value.
-
-I<Arguments: I, IC or N, IC or S, IC or P, IC>
-
-=head3 inc
-
-X<inc opcode (PASM)>
-
- inc R<DEST>
-
-Increment a value by one.
-
-I<Arguments: IR or NR or P>
-
-=head3 index
-
-X<index opcode (PASM)>
-
- index R<DEST>, R<STRING>, R<SEARCH>
- index R<DEST>, R<STRING>, R<SEARCH>, R<POS>
-
-Return the position of the first occurrence of the string R<SEARCH> in
-the string R<STRING>, starting at the position R<POS>. If the starting
-position is unspecified, start at the beginning of the string.
-
-I<Arguments: IR, S, S or IR, S, S, I>
-
-=head3 interpinfo
-
-X<interpinfo opcode (PASM)>
-
- interpinfo R<DEST>, R<FLAG>
-
-Return information about the interpreter. An integer flag selects
-which information to return, as listed in
-Table 10-1.
-
-=begin table picture Interpinfo flags
-
-Z<CHP-10-TABLE-1>
-
-=headrow
-
-=row
-
-=cell Flag
-
-=cell Returns
-
-=bodyrows
-
-=row
-
-=cell C<1>
-
-=cell Allocated memory, in bytes.
-
-=row
-
-=cell C<2>
-
-=cell Number of GC mark runs performed.
-
-=row
-
-=cell C<3>
-
-=cell Number of GC runs performed.
-
-=row
-
-=cell C<4>
-
-=cell Number of active PMCs.
-
-=row
-
-=cell C<5>
-
-=cell Number of active buffers.
-
-=row
-
-=cell C<6>
-
-=cell Number of allocated PMCs.
-
-=row
-
-=cell C<7>
-
-=cell Number of allocated buffers.
-
-=row
-
-=cell C<8>
-
-=cell Number of new PMC or buffer headers allocated since last mark run.
-
-=row
-
-=cell C<9>
-
-=cell Number of memory blocks allocated since last GC run.
-
-=row
-
-=cell C<10>
-
-=cell Amount of memory copied during GC runs, in bytes.
-
-=end table
-
-I<Arguments: IR, I>
-
-=head3 invoke
-
-X<invoke opcode (PASM)>
-
- invoke
- invoke R<SUB>
-
-Call a subroutine, coroutine, or continuation stored in a PMC. If no
-PMC register is specified, it calls the subroutine in C<P0> and uses
-the standard calling conventions. Otherwise, no calling convention is
-defined. Also C<yield> from a coroutine.
-
-I<Arguments: P>
-
-=head3 invokecc
-
-X<invokecc opcode (PASM)>
-
- invokecc
- invokecc R<SUB>
-
-Call a subroutine like C<invoke>, but also generate a return
-continuation in C<P1>.
-
-I<Arguments: P>
-
-See also: C<updatecc>.
-
-=head3 isa
-
-X<isa opcode (PASM)>
-
- isa R<DEST>, R<OBJECT>, R<CLASS>
-
-Return a true value if R<OBJECT> I<isa> member of class R<CLASS>, or of
-one of its subclasses, otherwise return a false value.
-
-I<Arguments: IR, P, S>
-
-=head3 isnull
-
-X<isnull opcode (PASM)>
-
- isnull R<VAL>, R<LABEL>
-
-Jump to R<LABEL> if the given PMC is a NULL PMC.
-
-I<Arguments: P, IC>
-
-=head3 join
-
-X<join opcode (PASM)>
-
- join R<DEST>, R<DELIM>, R<ARRAY>
-
-Create a new string by joining all elements from array with the given
-delimiter.
-
-I<Arguments: SR, S, P>
-
-=head3 jsr
-
-X<jsr opcode (PASM)>
-
- jsr R<ADDRESS>
-
-Jump to an address, like C<jump>, but also push the current location
-onto the call stack so C<ret> can return to it.
-
-I<Arguments: I>
-
-=head3 jump
-
-X<jump opcode (PASM)>
-
- jump R<ADDRESS>
-
-Jump to a specified absolute address.
-
-I<Arguments: I>
-
-See also: C<set_addr>.
-
-=head3 lcm
-
-X<lcm opcode (PASM)>
-
- lcm R<DEST>, R<VAL>, R<VAL>
-
-Return the least common multiple of two values.
-
-I<Arguments: IR, I, I or NR, I, I>
-
-=head3 le
-
-X<le (less than or equal);opcode (PASM)>
-
- le R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is less than or equal to R<VAL2>.
-
-I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC or
-P, S, IC or P, P, IC>
-
-=head3 le_num
-
-X<le_num opcode (PASM)>
-
- le_num R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is numerically less than or equal to R<VAL2>.
-
-I<Arguments: P, P, IC>
-
-=head3 le_str
-
-X<le_str opcode (PASM)>
-
- le_str R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is stringwise less than or equal to R<VAL2>.
-
-I<Arguments: P, P, IC>
-
-=head3 length
-
-X<length opcode (PASM)>
-
- length R<DEST>, R<STRING>
-
-Return the character length of a string.
-
-I<Arguments: IR, S>
-
-=head3 ln
-
-X<ln opcode (PASM)>
-
- ln R<DEST>, R<VAL>
-
-The natural logarithm of R<VAL>.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 load_bytecode
-
-X<load_bytecode>
-
- load_bytecode R<FILE>
-
-Load Parrot bytecode from a file.
-
-I<Arguments: S>
-
-=head3 loadlib
-
-X<loadlib opcode (PASM)>
-
- loadlib R<DEST>, R<LIBRARY>
-
-Load a dynamic link library by name and store it in a PMC.
-
-I<Arguments: P, S>
-
-See also: C<dlfunc>.
-
-=head3 localtime
-
-X<localtime opcode (PASM)>
-
- localtime R<DEST>, R<VAL>
-
-Take the integer, which represents GMT epoch-seconds, and turn it into a
-formatted string after adjusting to localtime.
-
-I<Arguments: SR, I>
-
-See also: C<gmtime>.
-
-=head3 log10
-
-X<log10 opcode (PASM)>
-
- log10 R<DEST>, R<VAL>
-
-The base 10 logarithm of R<VAL>.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 log2
-
-X<log2 opcode (PASM)>
-
- log2 R<DEST>, R<VAL>
-
-The base 2 logarithm of R<VAL>.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 lsr
-
-X<lsr opcode (PASM)>
-
- lsr R<DEST>, R<BITS>
- lsr R<DEST>, R<VAL>, R<BITS>
-
-Logically shift a value right by a given number of bits.
-
-I<Arguments: IR, I or IR, I, I>
-
-=head3 lt
-
-X<lt (less than);opcode (PASM)>
-
- lt R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is less than R<VAL2>.
-
-I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC or
-P, S, IC or P, P, IC>
-
-=head3 lt_num
-
-X<lt_num opcode (PASM)>
-
- lt_num R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is numerically less than R<VAL2>.
-
-I<Arguments: P, P, IC>
-
-=head3 lt_str
-
-X<lt_str opcode (PASM)>
-
- lt_str R<VAL1>, R<VAL2>, R<LABEL>
-
-Jump to a label if R<VAL1> is stringwise less than R<VAL2>.
-
-I<Arguments: P, P, IC>
-
-=head3 mod
-
-X<mod opcode (PASM)>
-
- mod R<DEST>, R<VAL>
- mod R<DEST>, R<VAL1>, R<VAL2>
-
-Divide R<VAL1> by R<VAL2> and return the remainder. If R<VAL2> is omitted,
-divide R<DEST> by R<VAL>. The operation is defined as:
-
- x mod y = x - y * floor(x / y)
-
-I<Arguments: P, I or IR, I, I or NR, N, N or P, P, I or P, P, N>
-
-See also: C<cmod>.
-
-=head3 mul
-
-X<mul opcode (PASM)>
-
- mul R<DEST>, R<VAL>
- mul R<DEST>, R<VAL>, R<VAL>
-
-Multiply two values and return the result. If only one R<VAL>,
-multiply R<DEST> by R<VAL>.
-
-I<Arguments: IR, I or NR, I or NR, N or P, I or P, N or P, P or IR, I,
-I or NR, N, I or NR, N, N or P, P, I or P, P, N or P, P, P>
-
-=head3 ne
-
-X<ne (not equal);opcode (PASM)>
-
- ne R<VAL>, R<VAL>, R<LABEL>
-
-Jump to a label if the two values are not equal.
-
-I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC or
-P, S, IC or P, P, IC>
-
-=head3 ne_addr
-
-X<ne_addr opcode (PASM)>
-
- ne_addr R<VAL>, R<VAL>, R<LABEL>
-
-Jump to a label if R<VAL1> and R<VAL2> do not point to the same string
-or PMC.
-
-I<Arguments: S, S, IC or P, P, IC>
-
-=head3 ne_num
-
-X<ne_num opcode (PASM)>
-
- ne_num R<VAL>, R<VAL>, R<LABEL>
-
-Jump to a label if the two values are numerically different.
-
-I<Arguments: P, P, IC>
-
-=head3 ne_str
-
-X<ne_str opcode (PASM)>
-
- ne_str R<VAL>, R<VAL>, R<LABEL>
-
-Jump to a label if the two strings are not equal.
-
-I<Arguments: P, P, IC>
-
-=head3 needs_destroy
-
-X<needs_destroy opcode (PASM)>
-
- needs_destroy R<PMC>
-
-Mark the PMC as requiring timely destruction.
-
-I<Arguments: P>
-
-See also: C<sweep>.
-
-=head3 neg
-
-X<neg opcode (PASM)>
-
- neg R<DEST>
- neg R<DEST>, R<VAL>
-
-Return the negative of a number. If there is no R<VAL>, R<DEST> is the
-negative of itself.
-
-I<Arguments: IR or NR or P or IR, I or NR, N or P, P>
-
-=head3 new
-
-X<new opcode (PASM)>
-
- new R<DEST>, R<TYPE>
- new R<DEST>, R<TYPE>, R<INITIALIZE>
- new R<DEST>, R<TYPE>, R<INITIALIZE>, R<PROPS>
-
-Create a new PMC of type R<TYPE>. R<INITIALIZE> is an array PMC
-containing initialization data for the new PMC. R<PROPS> is a property hash.
-
-I<Arguments: P, I or P, I, P or P, I, P, P>
-
- new R<DEST>
- new R<DEST>, R<LENGTH>
- new R<DEST>, R<LENGTH>, R<ENCODING>
- new R<DEST>, R<LENGTH>, R<ENCODING>, R<TYPE>
-
-Allocate a new empty string with a given R<LENGTH>, R<ENCODING>, and
-R<TYPE>.
-
-I<Arguments: SR or SR, I or SR, I, I or SR, I, I, I>
-
-=head3 new_callback
-
-X<new_callback opcode (PASM)>
-
- new_callback R<DEST>, R<SUB>, R<DATA>, R<SIG>
-
-Create a callback stub R<DEST> for a PASM subroutine R<SUB> with user
-data R<DATA> and function signature R<SIG>.
-
-I<Arguments: P, P, P, S>
-
-=head3 new_pad
-
-X<new_pad opcode (PASM)>
-
- new_pad R<DEPTH>
- new_pad R<DEST>, R<DEPTH>
-
-Create a new lexical scratchpad. If a destination PMC is provided,
-store the pad in the PMC, otherwise push it onto the pad stack.
-R<DEPTH> specifies the static nesting depth for the pad (lower static
-depths are copied from the current static nesting).
-
-I<Arguments: I or P, I>
-
-=head3 newclass
-
-X<newclass opcode (PASM)>
-
- newclass R<DEST>, R<NAME>
-
-Create a new class with the given name.
-
-I<Arguments: P, S>
-
-=head3 newsub
-
-X<newsub opcode (PASM)>
-
- newsub R<DEST>, R<CLASS>, R<LABEL>
-
-Generate a new subroutine object of the given R<CLASS>, located at the
-given R<LABEL>, and store the object in the destination PMC.
-
-I<Arguments: P, I, IC>
-
- newsub R<CLASS>, R<RETCLASS>, R<LABEL>, R<RETADDR>
-
-Generate a new subroutine object of the given R<CLASS>, located at the
-given R<LABEL>, and store the object in C<P0>. Also generate a return
-continuation of class R<RETCLASS> with the return address R<RETADDR> and
-store it in C<P1>.
-
-I<Arguments: I, I, IC, IC>
-
-=head3 noop
-
-X<noop opcode (PASM)>
-
- noop
-
-Do nothing.
-
-=head3 not
-
-X<not opcode (PASM)>
-
- not R<DEST>, R<VAL>
-
-Logical NOT. True if R<VAL> is false.
-
-I<Arguments: IR, I or P, P>
-
-=head3 null
-
-X<null opcode (PASM)>
-
- null R<DEST>
-
-Set R<DEST> (which must be a register) to 0, 0.0 or a NULL pointer,
-depending on its type.
-
-I<Arguments: IR or NR or SR or P>
-
-=head3 open
-
-X<open opcode (PASM)>
-
- open R<DEST>, R<FILENAME>
- open R<DEST>, R<FILENAME>, R<MODE>
-
-Open a file in the specified mode ("r", "w", etc.) and return
-a filehandle. Without the mode it defaults to read/write.
-
-I<Arguments: P, S, S or P, S>
-
-=head3 or
-
-X<or opcode (PASM)>
-
- or R<DEST>, R<VAL1>, R<VAL2>
-
-Logical OR. Return R<VAL1> if it's true; otherwise, return R<VAL2>.
-
-I<Arguments: IR, I, I or P, P, P>
-
-=head3 ord
-
-X<ord opcode (PASM)>
-
- ord R<DEST>, R<STRING>
- ord R<DEST>, R<STRING>, R<POS>
-
-Return the character at position R<POS> in R<STRING>. If R<POS> isn't
-specified, return the 0th character.
-
-I<Arguments: IR, S or IR, S, I>
-
-=head3 peek
-
-X<peek opcode (PASM)>
-
- peek R<DEST>
- peek R<DEST>, R<PIO>
-
-Read the next byte from the given FileHandle object or from C<stdin> but
-don't remove it.
-
-I<Arguments: SR or SR, P>
-
-=head3 peek_pad
-
-X<peek_pad opcode (PASM)>
-
- peek_pad R<DEST>
-
-Store the current lexical scope pad in a PMC.
-
-I<Arguments: P>
-
-=head3 pin
-
-X<pin opcode (PASM)>
-
- pin R<DEST>
-
-Make the string in R<DEST> immobile. This prevents the garbage collector
-from moving it to a different location in memory (which it otherwise may
-choose to do).
-
-I<Arguments: SR>
-
-See also: C<unpin>.
-
-=head3 pop
-
-X<pop opcode (PASM)>
-
- pop R<DEST>, R<PMC>
-
-Pop the last entry off an aggregate PMC and return it.
-
-I<Arguments: IR, P or NR, P or SR, P or P, P>
-
-=head3 pop_pad
-
-X<pop_pad opcode (PASM)>
-
- pop_pad
-
-Pop the current lexical scope pad off the lexical scope stack.
-
-See also: C<peek_pad>.
-
-=head3 popX
-
-X<popi opcode (PASM)>
-X<popn opcode (PASM)>
-X<popp opcode (PASM)>
-X<pops opcode (PASM)>
-
- popi
- popn
- popp
- pops
-
-Restore all the registers of one type from the stack ("i" = integer,
-"n" = float, "p" = PMC, "s" = string).
-
- popbottomi
- popbottomn
- popbottomp
- popbottoms
-
-Restore registers in the range 0..15.
-
- poptopi
- poptopn
- poptopp
- poptops
-
-Restore registers in the range 16..31.
-
-See also: C<push>R<X>.
-
-=head3 pow
-
-X<pow opcode (PASM)>
-
- pow R<DEST>, R<VAL1>, R<VAL2>
-
-Return R<VAL1> raised to the power of R<VAL2>.
-
-I<Arguments: NR, I, I or NR, I, N or NR, N, I or NR, N, N>
-
-=head3 print
-
-X<print opcode (PASM)>
-
- print R<VAL>
- print R<IO>, R<VAL>
-
-Print a value to an I/O object or file descriptor. If no R<IO> is
-given, print the value to standard output.
-
-I<Arguments: I or N or S or P or P, I or P, N or P, S or P, P>
-
-=head3 printerr
-
-X<printerr opcode (PASM)>
-
- printerr R<VAL>
-
-Print a value to C<stderr>.
-
-I<Arguments: I or N or S or P>
-
-=head3 profile
-
-X<profile opcode (PASM)>
-
- profile R<INT>
-
-Toggle profiling in the interpreter (0 for off, any other value for on).
-
-I<Arguments: I>
-
-=head3 prophash
-
-X<prophash opcode (PASM)>
-
- prophash R<DEST>, R<PMC>
-
-Return a hash containing all the properties from a PMC.
-
-I<Arguments: P, P>
-
-See also: C<getprop>.
-
-=head3 push
-
-X<push opcode (PASM)>
-
- push R<PMC>, R<VAL>
-
-Push a value onto the end of an aggregate PMC.
-
-I<Arguments: P, I or P, N or P, S or P, P>
-
-=head3 push_pad
-
-X<push_pad opcode (PASM)>
-
- push_pad R<PAD>
-
-Push a scratchpad stored in a PMC onto the lexical scope stack.
-
-I<Arguments: P>
-
-=head3 pushX
-
-X<pushi opcode (PASM)>
-X<pushn opcode (PASM)>
-X<pushp opcode (PASM)>
-X<pushs opcode (PASM)>
-
- pushi
- pushn
- pushp
- pushs
-
-Save all the registers of one type to the stack ("i" = integer, "n" =
-float, "p" = PMC, "s" = string). Restore with C<pop>R<X>.
-
- pushbottomi
- pushbottomn
- pushbottomp
- pushbottoms
-
-Push registers 0..15.
-
- pushtopi
- pushtopn
- pushtopp
- pushtops
-
-Push registers 16..31.
-
-=head3 read
-
-X<read opcode (PASM)>
-
- read R<DEST>, R<BYTES>
- read R<DEST>, R<IO>, R<BYTES>
-
-Read the specified number of bytes from a Parrot I/O object. Read from
-C<stdin> if no R<IO> is provided.
-
-I<Arguments: SR, I or SR, P, I>
-
-=head3 readline
-
-X<readline opcode (PASM)>
-
- readline R<DEST>, R<IO>
-
-Read a line from a Parrot I/O object.
-
-I<Arguments: SR, P>
-
-=head3 register
-
-X<register opcode (PASM)>
-
- register R<PMC>
-
-Register the given PMC in the interpreter's root set, so that it's
-visible during the mark phase.
-
-I<Arguments: P>
-
-See also: C<unregister>.
-
-=head3 removeparent
-
-X<removeparent opcode (PASM)>
-
- removeparent R<CLASS1>, R<CLASS2>
-
-Remove R<CLASS2> from class C<CLASS1>'s list of parents.
-
-I<Arguments: P, P>
-
-=head3 repeat
-
-X<repeat opcode (PASM)>
-
- repeat R<DEST>, R<VAL>, R<REPEAT>
-
-Repeat a string R<REPEAT> number of times.
-
-I<Arguments: SR, S, I or P, P, I or P, P, P>
-
-=head3 restoretop
-
-X<restoretop opcode (PASM)>
-
- restoretop
-
-Restore registers 16..31. Does a C<pop>R<X> for every type.
-
-See also: C<savetop>.
-
-=head3 ret
-
-X<ret opcode (PASM)>
-
- ret
-
-Pop a location off the top of the call stack, and go there.
-Often used with C<bsr> and C<jsr>.
-
-=head3 rethrow
-
-X<rethrow opcode (PASM)>
-
- rethrow R<EXCEPTION>
-
-Rethrow an exception. Only valid inside an exception handler.
-
-I<Arguments: P>
-
-See also: C<throw>
-
-=head3 runinterp
-
-X<runinterp opcode (PASM)>
-
- runinterp R<INTERPRETER>, R<OFFSET>
-
-Use an interpreter stored in PMC to run code starting at a given
-offset.
-
-I<Arguments: P, I>
-
-See also: C<newinterp>.
-
-=head3 say
-
-X<say opcode (PASM)>
-
- say R<VAL>
-
-Print a value to C<stdout> with a trailing newline.
-
-I<Arguments: I or N or S or P>
-
-=head3 sec
-
-X<sec opcode (PASM)>
-
- sec R<DEST>, R<VAL>
-
-The secant of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 sech
-
-X<sech opcode (PASM)>
-
- sech R<DEST>, R<VAL>
-
-The hyperbolic secant of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 seek
-
-X<seek opcode (PASM)>
-
- seek R<DEST>, R<IO>, R<OFFSET>, R<STARTFLAG>
- seek R<DEST>, R<IO>, R<UPPER32>, R<LOWER32>, R<STARTFLAG>
-
-Set the file position of a Parrot I/O object to a given offset from a
-starting position (STARTFLAG: 0 is the beginning of the file, 1 is
-current the position, 2 is the end of the file). R<DEST> is the
-success or failure of the seek.
-
-64-bit C<seek> combines R<UPPER32> and R<LOWER32> to get one 64-bit
-R<OFFSET>.
-
-I<Arguments: P, I, I or P, I, I, I>
-
-=head3 set
-
-X<set opcode (PASM)>
-
- set R<DEST>, R<VAL>
-
-Set a register to a value.
-
-I<Arguments: IR, I or IR, N or IR, S or IR, P or NR, I or NR, N or NR,
-S or NR, P or SR, I or SR, N or SR, S or SR, P or P, I or P, N or P, S
-or P, P>
-
- set R<DEST[KEY]>, R<VAL>
-
-A keyed set operation on a PMC.
-
-I<Arguments: P, I or P, N or P, S or P, P>
-
- set R<DEST>, R<PMC[KEY]>
-
-A keyed get operation on a PMC.
-
-I<Arguments: I, P or N, P or S, P or P, P>
-
-=head3 setX_ind
-
-X<seti_ind opcode (PASM)>
-X<setn_ind opcode (PASM)>
-X<sets_ind opcode (PASM)>
-X<setp_ind opcode (PASM)>
-
- seti_ind R<REG>, R<VAL>
- setn_ind R<REG>, R<VAL>
- sets_ind R<REG>, R<VAL>
- setp_ind R<REG>, R<VAL>
-
-Set register number R<REG> of the specified type to R<VAL>. Bypasses
-the register allocator, so use with care.
-
-I<Arguments: I, I or I, S or I, N or I, P>
-
-=head3 set_addr
-
-X<set_addr opcode (PASM)>
-
- set_addr R<DEST>, R<LABEL>
-
-Return the current address plus the offset to R<LABEL>. Often used to
-calculate absolute addresses for C<jump> or C<jsr>.
-
-I<Arguments: IR, IC>
-
- set_addr R<SUB>, R<LABEL>
-
-Set the subroutine address pointing to the given label.
-
-I<Arguments: P, I>
-
-=head3 set_chartype
-
-X<set_chartype opcode (PASM)>
-
- set_chartype R<STRING>, R<CHARTYPE>
-
-Set the chartype of a string.
-
-I<Arguments: S, I>
-
-=head3 set_eh
-
-X<set_eh opcode (PASM)>
-
- set_eh R<HANDLER>
-
-Push an exception handler on the control stack.
-
-I<Arguments: P>
-
-See also: C<clear_eh>, C<throw>.
-
-=head3 set_encoding
-
-X<set_encoding opcode (PASM)>
-X<strings;encoding>
-
- set_encoding R<STRING>, R<ENCODING>
-
-Set the encoding of a string.
-
-I<Arguments: S, I>
-
-=head3 setattribute
-
-X<setattribute opcode (PASM)>
-
- setattribute R<OBJECT>, R<OFFSET>, R<ATTRIBUTE>
-
-Set the given attribute at R<OFFSET> for object R<OBJECT>.
-
-I<Arguments: P, I, P>
-
-See also: C<getattribute>, C<classoffset>.
-
-=head3 setprop
-
-X<setprop opcode (PASM)>
-
- setprop R<PMC>, R<NAME>, R<VALUE>
-
-Set the value of a named property on a PMC.
-
-I<Arguments: P, S, P>
-
-See also: C<getprop> and C<delprop>.
-
-=head3 setstd*
-
-X<setstderr opcode (PASM)>
-X<setstdin opcode (PASM)>
-X<setstdout opcode (PASM)>
-
- setstderr R<DEST>
- setstdin R<DEST>
- setstdout R<DEST>
-
-Set a FileHandle object for the given standard handle.
-
-I<Arguments: P>
-
-=head3 shift
-
-X<shift opcode (PASM)>
-
- shift R<DEST>, R<PMC>
-
-Shift a value off the front of an aggregate PMC.
-
-I<Arguments: IR, P or NR, P or SR, P or P, P>
-
-=head3 shl
-
-X<shl opcode (PASM)>
-
- shl R<DEST>, R<VAL>, R<BITS>
-
-Bitwise shift a value left by a given number of bits.
-
-I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
-
-=head3 shr
-
-X<shr opcode (PASM)>
-
- shr R<DEST>, R<VAL>, R<BITS>
-
-Bitwise shift a value right by a given number of bits.
-
-I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
-
-=head3 sin
-
-X<sin opcode (PASM)>
-
- sin R<DEST>, R<VAL>
-
-The sine of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 singleton
-
-X<singleton opcode (PASM)>
-
- singleton R<DEST>
-
-Take the given object and put it into its own singleton class.
-
-I<Arguments: P>
-
-=head3 sinh
-
-X<sinh opcode (PASM)>
-
- sinh R<DEST>, R<VAL>
-
-The hyperbolic sine of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 sizeof
-
-X<sizeof opcode (PASM)>
-
- sizeof R<DEST>, R<TYPE>
-
-Set R<DEST> to the size in bytes of the given natural type.
-
-I<Arguments: IR, I>
-
-=head3 sleep
-
-X<sleep opcode (PASM)>
-
- sleep R<SECONDS>
-
-Sleep for the given number of seconds.
-
-I<Arguments: I or N>
-
-=head3 spawnw
-
-X<spawnw opcode (PASM)>
-
- spawnw R<DEST>, R<COMMAND>
-
-Spawn a subprocess to run the given R<COMMAND>, wait for it to finish,
-and return the result.
-
-I<Arguments: IR, S>
-
-=head3 splice
-
-X<splice opcode (PASM)>
-
- splice R<DEST>, R<REPLACE>, R<OFFSET>, R<COUNT>
-
-Starting at R<OFFSET>, replace R<COUNT> number of values in the
-destination PMC with values provided in the R<REPLACE> PMC.
-
-I<Arguments: P, P, I, I>
-
-=head3 sprintf
-
-X<sprintf opcode (PASM)>
-
- sprintf R<DEST>, R<FORMAT>, R<ARGS>
-
-Format arguments in an aggregate PMC, using format string R<FORMAT>.
-
-I<Arguments: SR, S, P or P, P, P>
-
-=head3 stat
-
-X<stat opcode (PASM)>
-
- stat R<DEST>, R<VAL>, R<VAL>
-
-Stat the VAL1 file and return stat element VAL2, as listed in
-Table 10-2.
-
-I<Arguments: IR, S, I or IR, I, I>
-
-=begin table picture Stat arguments
-
-Z<CHP-10-TABLE-2>
-
-=headrow
-
-=row
-
-=cell Flag
-
-=cell Flagname
-
-=cell Returns
-
-=bodyrows
-
-=row
-
-=cell C<0>
-
-=cell EXISTS
-
-=cell Does the file exist?
-
-=row
-
-=cell C<1>
-
-=cell FILESIZE
-
-=cell Size of file, in bytes
-
-=row
-
-=cell C<2>
-
-=cell ISDIR
-
-=cell Is the file a directory?
-
-=row
-
-=cell C<3>
-
-=cell ISDEV
-
-=cell Is the file a device?
-
-=row
-
-=cell C<4>
-
-=cell CREATETIME
-
-=cell Time file was created
-
-=row
-
-=cell C<5>
-
-=cell ACCESSTIME
-
-=cell Time file was last accessed
-
-=row
-
-=cell C<6>
-
-=cell MODIFYTIME
-
-=cell Time file data was changed
-
-=row
-
-=cell C<7>
-
-=cell CHANGETIME
-
-=cell Time file metadata was changed
-
-=row
-
-=cell C<8>
-
-=cell BACKUPTIME
-
-=cell Time of last backup
-
-=row
-
-=cell C<9>
-
-=cell UID
-
-=cell ID of file owner
-
-=row
-
-=cell C<10>
-
-=cell GID
-
-=cell ID of file group
-
-=end table
-
-=head3 store_global
-
-X<store_global opcode (PASM)>
-
- store_global R<NAME>, R<OBJECT>
- store_global R<NAME>, R<NAMESPACE>, R<OBJECT>
-
-Store a global variable as a named symbol.
-
-I<Arguments: S, P or S, S, P or P, S, P>
-
-See also: C<find_global>.
-
-=head3 store_lex
-
-X<store_lex opcode (PASM)>
-
- store_lex R<NAME>, R<OBJECT>
- store_lex R<DEPTH>, R<NAME>, R<OBJECT>
- store_lex R<DEPTH>, R<POSITION>, R<OBJECT>
-
-Store an object as a lexical variable with a given name. If the symbol
-doesn't exist, it will be created in the lexical scratchpad at the
-specified depth (a negative depth counts back from the current scope).
-If R<DEPTH> isn't provided, the symbol must already exist. If a
-position is provided instead of a name, the symbol will be stored at
-the given position in the scratchpad.
-
-I<Arguments: S, P or I, I, P or I, S, P>
-
-See also: C<find_lex>.
-
-=head3 string_chartype
-
-X<string_chartype opcode (PASM)>
-
- string_chartype R<DEST>, R<STRING>
-
-Return the chartype of the string.
-
-I<Arguments: IR, S>
-
-=head3 string_encoding
-
-X<string_encoding opcode (PASM)>
-X<strings;encoding>
-
- string_encoding R<DEST>, R<STRING>
-
-Return the encoding of the string.
-
-I<Arguments: IR, S>
-
-=head3 stringinfo
-
-X<stringinfo opcode (PASM)>
-
- stringinfo R<DEST>, R<STRING>, R<FLAG>
-
-Return information about a string. An integer flag selects which
-information to return, as listed in Table 10-3.
-
-=begin table picture Stringinfo arguments
-
-Z<CHP-10-TABLE-3>
-
-=headrow
-
-=row
-
-=cell Flag
-
-=cell Returns
-
-=bodyrows
-
-=row
-
-=cell C<1>
-
-=cell Location of string buffer header.
-
-=row
-
-=cell C<2>
-
-=cell Location of start of string memory.
-
-=row
-
-=cell C<3>
-
-=cell Allocated length, in bytes.
-
-=row
-
-=cell C<4>
-
-=cell String flags.
-
-=row
-
-=cell C<5>
-
-=cell Length of string buffer currently used, in bytes.
-
-=row
-
-=cell C<6>
-
-=cell String length, in characters.
-
-=end table
-
-I<Arguments: IR, S, I>
-
-=head3 sub
-
-X<sub opcode (PASM)>
-
- sub R<DEST>, R<VAL>
- sub R<DEST>, R<VAL1>, R<VAL2>
-
-Subtract R<VAL2> from R<VAL1>. If no R<VAL2>, subtract R<VAL> from
-R<DEST>.
-
-I<Arguments: IR, I or NR, I or NR, N or P, I or P, N or P, P or IR, I,
-I or NR, N, I or NR, N, N or P, P, I or P, P, N or P, P, P>
-
-=head3 subclass
-
-X<subclass opcode (PASM)>
-
- subclass R<DEST>, R<CLASS>
- subclass R<DEST>, R<CLASS>, R<NAME>
-
-Create a subclass of R<CLASS>. Without R<NAME> an anonymous subclass is
-created.
-
-I<Arguments: P, S or P, P or P, S, S or P, P, S>
-
-=head3 substr
-
-X<substr opcode (PASM)>
-
- substr R<DEST>, R<STRING>, R<OFFSET>
- substr R<DEST>, R<STRING>, R<OFFSET>, R<LENGTH>
-
-Return a substring of R<STRING>, beginning at R<OFFSET> and with length
-R<LENGTH>.
-
-I<Arguments: SR, S, I or SR, S, I, I or SR, P, I, I>
-
- substr R<DEST>, R<STRING>, R<OFFSET>, R<LENGTH>, R<REPLACE>
-
-If R<REPLACE> is given, use it to replace the returned substring in
-R<STRING>.
-
-I<Arguments: SR, S, I, I, S>
-
- substr R<DEST>, R<OFFSET>, R<LENGTH>, R<REPLACE>
-
-If R<STRING> is omitted, operate on the string in R<DEST>.
-
-I<Arguments: SR, I, I, S>
-
-
-=head3 substr_r
-
-X<substr_r opcode (PASM)>
-
- substr_r R<DEST>, R<STRING>, R<OFFSET>, R<LENGTH>
-
-Acts like C<substr>, but reuses the destination string instead of
-creating a new string. Deprecated.
-
-I<Arguments: SR, S, I, I>
-
-=head3 sweep
-
-X<sweep opcode (PASM)>
-
- sweep R<LAZY>
-
-Trigger a GC mark run. If R<LAZY> is set to 1, only objects that need timely
-destruction may be destroyed.
-
-I<Arguments: IC>
-
-=head3 sweepoff
-
-X<sweepoff opcode (PASM)>
-
- sweepoff
-
-Disable GC mark runs (nestable).
-
-=head3 sweepon
-
-X<sweepon opcode (PASM)>
-
- sweepon
-
-Re-enable GC mark runs.
-
-=head3 sysinfo
-
-X<sysinfo opcode (PASM)>
-
- sysinfo R<DEST>, R<ITEM>
-
-Return OS-specific details given by C<ITEM>.
-
-I<Arguments: IR, I or SR, I>
-
-=head3 tan
-
-X<tan opcode (PASM)>
-
- tan R<DEST>, R<VAL>
-
-The tangent of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 tanh
-
-X<tanh opcode (PASM)>
-
- tanh R<DEST>, R<VAL>
-
-The hyperbolic tangent of R<VAL> in radians.
-
-I<Arguments: NR, I or NR, N>
-
-=head3 tell
-
-X<tell opcode (PASM)>
-
- tell R<DEST>, R<PIO>
- tell R<UPPER32>, R<LOWER32>, R<PIO>
-
-Return the file position of the given FileHandle object.
-
-I<Arguments: IR, P or IR, I, P>
-
-See also: C<seek>.
-
-=head3 thaw
-
-X<thaw opcode (PASM)>
-
- thaw R<DEST>, R<STR>
-
-Create a new PMC representing the frozen image.
-
-I<Arguments: P, S>
-
-See also: C<freeze>.
-
-=head3 throw
-
-X<throw opcode (PASM)>
-
- throw R<EXCEPTION>
-
-Throw an exception.
-
-I<Arguments: P>
-
-See also: C<rethrow>, C<set_eh>, C<clear_eh>
-
-=head3 time
-
-X<time opcode (PASM)>
-
- time R<DEST>
-
-Return the current system time.
-
-I<Arguments: IR or NR>
-
-=head3 titlecase
-
-X<titlecase opcode (PASM)>
-
- titlecase R<DEST>
- titlecase R<DEST>, R<VAL>
-
-Create a copy of the string in R<VAL> with all characters converted to
-title case, and store it in R<DEST>. If R<VAL> is omitted, convert and
-replace the string in R<DEST>.
-
-I<Arguments: SR or SR, S>
-
-See also: C<upcase>, C<downcase>.
-
-=head3 trace
-
-X<trace opcode (PASM)>
-
- trace R<INT>
-
-Toggle tracing in the interpreter (0 for off, any other value for on).
-
-I<Arguments: I>
-
-=head3 transcode
-
-X<transcode opcode (PASM)>
-
- transcode R<DEST>, R<ENCODING>
- transcode R<DEST>, R<SOURCE>, R<ENCODING>
- transcode R<DEST>, R<SOURCE>, R<ENCODING>, R<CHARTYPE>
-
-Transcode a string to the given R<CHARTYPE> and R<ENCODING>. If
-R<CHARTYPE> is omitted, it is assumed to be the same as the original.
-
-I<Arguments: SR, I or SR, S, I or SR, S, I, I>
-
-=head3 typeof
-
-X<typeof opcode (PASM)>
-
- typeof R<DEST>, R<VAL>
- typeof R<DEST>, R<PMC[KEY]>
-
-Return the type of a PMC or Parrot data type, either its class name (to a
-string destination) or integer identifier (to an integer destination).
-
-I<Arguments: IR, P or SR, I or SR, P>
-
-=head3 unless
-
-X<unless (conditional);opcode (PASM)>
-
- unless R<CONDITION>, R<LABEL>
-
-Jump to a label unless the condition is a true value.
-
-I<Arguments: I, IC or N, IC or S, IC or P, IC>
-
-=head3 unpin
-
-X<unpin opcode (PASM)>
-
- unpin R<DEST>
-
-Make the string in R<DEST> movable again. This is the default, so
-C<unpin> is a no-op unless the string has been pinned with C<pin>.
-
-See also: C<pin>.
-
-I<Arguments: SR>
-
-=head3 unregister
-
-X<unregister opcode (PASM)>
-
- unregister R<PMC>
-
-Remove one reference to PMC from the root set registry.
-
-I<Arguments: P>
-
-See also: C<register>.
-
-=head3 unshift
-
-X<unshift opcode (PASM)>
-
- unshift R<DEST>, R<VAL>
-
-Unshift a value onto the front of an aggregate PMC.
-
-I<Arguments: P, I or P, N or P, S or P, P>
-
-=head3 upcase
-
-X<upcase opcode (PASM)>
-
- upcase R<DEST>
- upcase R<DEST>, R<VAL>
-
-Create a copy of the string in R<VAL> with all characters converted to
-upper case, and store it in R<DEST>. If R<VAL> is omitted, convert and
-replace the string in R<DEST>.
-
-I<Arguments: SR or SR, S>
-
-See also: C<downcase>, C<titlecase>.
-
-=head3 updatecc
-
-X<updatecc>
-
- updatecc
-
-Update the state of a return continuation stored in C<P1>. Used when
-context information changes after the return continuation is created
-but before it's invoked.
-
-See also: C<invokecc>.
-
-I<Arguments: IR, I>
-
-=head3 vers
-
-X<vers opcode (PASM)>
-
- vers R<DEST>, R<VAL>
-
-The versine of R<VAL> in radians.
-
-I<Arguments: NR, N>
-
-=head3 warningsoff
-
-X<warningsoff opcode (PASM)>
-
- warningsoff R<CATEGORY>
-
-Turn off a particular category of warnings by category number. Turning
-off one category will not affect the status of other warnings
-categories. See C<warningson> for the list of categories.
-
-I<Arguments: I>
-
-=head3 warningson
-
-X<warningson opcode (PASM)>
-
- warningson R<CATEGORY>
-
-Turn on a particular category of warnings by category number. The
-default is all warnings off. Turning on one category will not turn off
-other categories. Combine category numbers with a bitwise OR to turn on
-more than one at a time. If you include F<warnings.pasm>, the category
-numbers are available by name as:
-
- .PARROT_WARNINGS_ALL_FLAG
- .PARROT_WARNINGS_UNDEF_FLAG
- .PARROT_WARNINGS_IO_FLAG
- .PARROT_WARNINGS_PLATFORM_FLAG
-
-I<Arguments: I>
-
-=head3 xor
-
-X<xor opcode (PASM)>
-
- xor R<DEST>, R<VAL1>, R<VAL2>
-
-Logical XOR. If R<VAL1> is true and R<VAL2> is false, return R<VAL1>.
-If R<VAL1> is false and R<VAL2> is true, return R<VAL2>. Otherwise,
-return a false value.
-
-I<Arguments: IR, I, I or P, P, P>
-
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch11_directive_reference.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch11_directive_reference.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,227 +0,0 @@
-=pod
-
-=head1 Directive Reference
-
-Z<CHP-13-SECT-2>
-
-X<PIR (Parrot intermediate representation);quick reference;directives>
-This is a summary of PIR directives. Directives are preprocessed by the
-Parrot interpreter. Since PIR and PASM run on the same interpreter, many
-of the directives listed here are also valid in PASM code.
-
-
-=head3 .arg
-
-X<.arg directive>
-
- .arg R<VAL>
-
-pass a value to a subroutine according to PCC.
-
-=head3 .const
-
-X<.const directive>
-
- .const R<TYPE>R<NAME> = R<VALUE>
-
-Define a named constant.
-
-=head3 .macro_const
-
-X<.macro_const directive>
-
- .macro_const R<NAME>R<VALUE>
-
-Define a named macro that expands to a given value. Macros are called
-as directives, i.e. .R<NAME> (PASM code only).
-
-=head3 .emit
-
-X<.emit directive>
-
- .emit
-
-Define a compilation unit of PASM code. Always paired with C<.eom>.
-
-=head3 .end
-
-X<.end directive>
-
- .end
-
-End a compilation unit. Always paired with C<.sub>.
-
-=head3 .endm
-
-X<.endm directive>
-
- .endm
-
-End a macro definition. Always paired with C<.macro>.
-
-=head3 .eom
-
-X<.eom directive>
-
- .eom
-
-End a compilation unit of PASM code. Always paired with C<.emit>.
-
-=head3 .flatten_arg
-
-X<.flatten_arg directive>
-
- .flatten_arg R<PArray>
-
-Flatten the passed array PMC and provide args for PCC calls.
-
-=head3 .globalconst
-
-X<.globalconst directive>
-
- .globalconst R<TYPE>R<NAME> = R<VALUE>
-
-Define a named, file visible constant.
-
-=head3 .include
-
-X<.include directive>
-
- .include " R<FILENAME> "
-
-Include the contents of an external file by inserting it in place.
-
-=head3 .invocant
-
-X<.invocant directive>
-
- .invocant R<OBJ>
-
-Set the invocant for a method call.
-
-=head3 .local
-
-X<.local directive>
-
- .local R<TYPE>R<NAME>
-
-Define a local named variable.
-
-=head3 .macro
-
-X<.macro directive>
-
- .macro R<NAME> (R<PARAMS>)
-
-Define a named macro with a list of parameters. The macro is called as
-.R<NAME>(R<arg1>,R<arg2>,...). Always paired with C<.endm>.
-
-=head3 .meth_call
-
-X<.meth_call directive>
-
- .meth_call R<SUB>
- .meth_call R<SUB>, R<RETCONT>
-
-Create a method call.
-
-=head3 .namespace
-
-X<.namespace directive>
-
- .namespace R< [ "namespace" ] >
-
-Define a namespace.
-
-=head3 .nci_call
-
-X<.nci_call directive>
-
- .nci_call R<SUB>
-
-Create an NCI call.
-
-=head3 .param
-
-X<.param directive>
-
- .param R<DEST>
- .param R<TYPE>R<NAME>
-
-Define a subroutine parameter.
-
-=head3 .begin_call
-
-X<.begin_call directive>
-
-Start a call sequence. Always paired with C<.end_call>
-
-=head3 .begin_return
-
-X<.begin_return directive>
-
-Start a return sequence. Always paired with C<.end_return>
-
-=head3 .begin_yield
-
-X<.begin_yield directive>
-
-Start a return of a coroutine sequence. Always paired with C<.end_yield>
-
-=head3 .call
-
-X<.call directive>
-
- .call R<SUB>
- .call R<SUB>, R<RETCONT>
-
-Create a subroutine call.
-
-=head3 .pcc_sub
-
-X<.pcc_sub directive>
-
- .pcc_sub R<_LABEL>
-
-Create a symbol entry for subroutine at the _LABEL. This directive is
-for PASM code only.
-
-=head3 .result
-
-X<.result directive>
-
- .result R<DEST>
-
-Get a return value according to PCC.
-
-=head3 .return
-
-X<.return directive>
-
- .return R<VAL>
-
-Return a value to the calling subroutine according to PCC.
-
-=head3 .sub
-
-X<.sub directive>
-
- .sub R<NAME>
-
-Define a compilation unit. Always paired with C<.end>. Names begin
-with "C<_>" by convention.
-
-=head3 .sym
-
-X<.sym directive>
-
- .sym R<TYPE> R<NAME>
-
-Same as C<.local>.
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Deleted: branches/pmc_pct/docs/book/ch12_operator_reference.pod
==============================================================================
--- branches/pmc_pct/docs/book/ch12_operator_reference.pod Fri Jun 26 08:35:24 2009 (r39796)
+++ /dev/null 00:00:00 1970 (deleted)
@@ -1,299 +0,0 @@
-=pod
-
-=head1 PIR Operator Reference
-
-Z<CHP-13-SECT-3>
-
-X<PIR (Parrot intermediate representation);quick reference;instructions>
-This section is a quick reference to PIR instructions. For more details
-and the latest changes, see F<imcc/docs/syntax.pod> or dive into the
-source code in F<imcc/imcc.l> and F<imcc/imcc.y>.
-
-=head3 =
-
-X<= (equal sign);= (assignment);instruction (PIR)>
-
- R<DEST> = R<VAL>
-
-Assign a value to a particular register, temporary register, or named
-variable.
-
-=head3 +, +=
-
-X<+ (plus sign);+ (addition);instruction (PIR)>
-X<+ (plus sign);+= (addition assignment);instruction (PIR)>
-
- R<DEST> = R<VAL> + R<VAL>
- R<DEST> += R<VAL>
-
-Add two numbers or PMCs.
-
-=head3 -, -=
-
-X<- (hyphen);- (subtraction);instruction (PIR)>
-X<- (hyphen);-= (subtraction assignment);instruction (PIR)>
-X<- (hyphen);- (negation);instruction (PIR)>
-
- R<DEST> = R<VAL1> - R<VAL2>
- R<DEST> -= R<VAL1>
- R<DEST> = - R<VAL>
-
-Subtract R<VAL1> from R<VAL2>. The unary "C<->" negates a number.
-
-=head3 *, *=
-
-X<* (asterisk);* (multiplication);instruction (PIR)>
-X<* (asterisk);*= (multiplication assignment);instruction (PIR)>
-
- R<DEST> = R<VAL> * R<VAL>
- R<DEST> *= R<VAL>
-
-Multiply two numbers or PMCs.
-
-=head3 /, /=
-
-X</ (slash);/ (division);instruction (PIR)>
-X</ (slash);/= (division assignment);instruction (PIR)>
-
- R<DEST> = R<VAL1> / R<VAL2>
- R<DEST> /= R<VAL1>
-
-Divide R<VAL1> by R<VAL2>.
-
-=head3 **
-
-X<* (asterisk);** (exponentiation);instruction (PIR)>
-
- R<DEST> = R<VAL1> ** R<VAL2>
-
-Raise R<VAL1> to the power of R<VAL2>.
-
-=head3 %, %=
-
-X<% (percent sign);% (modulus);instruction (PIR)>
-X<% (percent sign);%= (modulus assignment);instruction (PIR)>
-
- R<DEST> = R<VAL1> % R<VAL2>
- R<DEST> %= R<VAL1>
-
-Divide R<VAL1> by R<VAL2> and return the (C<mod>) remainder.
-
-=head3 ., .=
-
-X<. (dot);. (concatenation) instruction (PIR)>
-X<. (dot);.= (concatenation assignment) instruction (PIR)>
-
- R<DEST> = R<VAL> . R<VAL>
- R<DEST> .= R<VAL>
-
-Concatenate two strings. The concat operator must be surrounded by
-whitespace.
-
-=head3 E<lt>
-
-X<E<lt> (left angle bracket);E<lt> (less than);instruction (PIR)>
-
- if R<VAL1> E<lt> R<VAL2> goto R<LABEL>
-
-Conditionally branch to a label if R<VAL1> is less than R<VAL2>.
-
-=head3 E<lt>=
-
-X<E<lt> (left angle bracket);E<lt>= (less than or equal);instruction (PIR)>
-
- if R<VAL1> E<lt>= R<VAL2> goto R<LABEL>
-
-Conditionally branch to a label if R<VAL1> is less than or equal to
-R<VAL2>.
-
-=head3 E<gt>
-
-X<E<gt> (right angle bracket);E<gt> (greater than);instruction (PIR)>
-
- if R<VAL1> E<gt> R<VAL2> goto R<LABEL>
-
-Conditionally branch to a label if R<VAL1> is greater than R<VAL2>.
-
-=head3 E<gt>=
-
-X<E<gt> (right angle bracket);E<gt>= (greater than or equal);instruction (PIR)>
-
- if R<VAL1> E<gt>= R<VAL2> goto R<LABEL>
-
-Conditionally branch to a label if R<VAL1> is greater than or equal to
-R<VAL2>.
-
-=head3 ==
-
-X<= (equal sign);== (equality);instruction (PIR)>
-
- if R<VAL1> == R<VAL2> goto R<LABEL>
-
-Conditionally branch to a label if R<VAL1> is equal to R<VAL2>.
-
-=head3 !=
-
-X<! (bang);!= (not equal);instruction (PIR)>
-
- if R<VAL1> != R<VAL2> goto R<LABEL>
-
-Conditionally branch to a label if R<VAL1> is not equal to R<VAL2>.
-
-=head3 &&
-
-X<& (ampersand);&& (logical AND);instruction (PIR)>
-
- R<DEST> = R<VAL1> && R<VAL2>
-
-Logical AND. Return R<VAL1> if it's false, otherwise return R<VAL2>.
-
-=head3 ||
-
-X<| (pipe);|| (logical OR);instruction (PIR)>
-
- R<DEST> = R<VAL1> || R<VAL2>
-
-Logical OR. Return R<VAL1> if it's true, otherwise return R<VAL2>.
-
-=head3 ~~
-
-X<~ (tilde);~~ (logical XOR) instruction (PIR)>
-
- R<DEST> = R<VAL1> ~~ R<VAL2>
-
-Logical XOR. If R<VAL1> is true and R<VAL2> is false, return R<VAL1>.
-If R<VAL1> is false and R<VAL2> is true, return R<VAL2>. Otherwise,
-return a false value.
-
-=head3 !
-
-X<! (bang);! (not);instruction (PIR)>
-
- R<DEST> = ! R<VAL>
-
-Logical NOT. Return a true value if R<VAL> is false.
-
-=head3 &, &=
-
-X<& (ampersand);& (bitwise AND) instruction (PIR)>
-X<& (ampersand);&= (bitwise AND assignment) instruction (PIR)>
-
- R<DEST> = R<VAL> & R<VAL>
- R<DEST> &= R<VAL>
-
-Bitwise AND on two values.
-
-=head3 |, |=
-
-X<| (pipe);| (bitwise AND) instruction (PIR)>
-X<| (pipe);|= (bitwise AND assignment) instruction (PIR)>
-
- R<DEST> = R<VAL> | R<VAL>
- R<DEST> |= R<VAL>
-
-Bitwise OR on two values.
-
-=head3 ~, ~=
-
-X<~ (tilde);~ (bitwise XOR) instruction (PIR)>
-X<~ (tilde);~= (bitwise XOR assignment) instruction (PIR)>
-
- R<DEST> = R<VAL> ~ R<VAL>
- R<DEST> ~= R<VAL>
- R<DEST> = ~ R<VAL>
-
-Bitwise XOR on two values. The unary form is a bitwise NOT on a value.
-
-=head3 E<lt>E<lt>, E<lt>E<lt>=
-
-X<E<lt> (left angle bracket);E<lt>E<lt> (bitwise left shift);instruction (PIR)>
-X<E<lt> (left angle bracket);E<lt>E<lt>= (bitwise left shift assignment);instruction (PIR)>
-
- R<DEST> = R<VAL1> E<lt>E<lt> R<VAL2>
- R<DEST> E<lt>E<lt>= R<VAL2>
-
-Bitwise shift R<VAL1> left by R<VAL2> number of bits.
-
-=head3 E<gt>E<gt>, E<gt>E<gt>=
-
-X<E<gt> (right angle bracket);E<gt>E<gt> (bitwise right shift);instruction (PIR)>
-X<E<gt> (right angle bracket);E<gt>E<gt>= (bitwise right shift assignment);instruction (PIR)>
-
- R<DEST> = R<VAL1> E<gt>E<gt> R<VAL2>
- R<DEST> E<gt>E<gt>= R<VAL2>
-
-Bitwise shift R<VAL1> right by R<VAL2> number of bits.
-
-=head3 E<gt>E<gt>E<gt>, E<gt>E<gt>E<gt>=
-
-X<E<gt> (right angle bracket);E<gt>E<gt>E<gt> (logical right shift) instruction (PIR)>
-X<E<gt> (right angle bracket);E<gt>E<gt>E<gt>= (logical right shift assignment) instruction (PIR)>
-
- R<DEST> = R<VAL1> E<gt>E<gt>E<gt> R<VAL2>
- R<DEST> E<gt>E<gt>E<gt>= R<VAL2>
-
-Logically shift R<VAL1> right by R<VAL2> number of bits.
-
-=head3 [ ]
-
-X<[] (brackets);indexed access to PMC (PIR)>
-
- R<DEST> = R<PMC> [ R<KEY> ]
- R<PMC> [ R<KEY> ] = R<VAL>
-
-Indexed access to a PMC and indexed assignment to a PMC.
-
- DEST = STRING [ OFFSET ]
- STRING [ OFFSET ] = VAL
-
-Access a one-character substring on a string, starting at a particular
-offset, or assign to that substring.
-
-=head3 call
-
-X<call instruction (PIR)>
-
- call R<NAME>
-
-Call the named subroutine (a C<.sub> label).
-
-=head3 global
-
-X<global instruction (PIR)>
-
- R<DEST> = global R<NAME>
- global R<NAME> = R<VAL>
-
-Access a global variable for read or write.
-
-=head3 goto
-
-X<goto command (PIR)>
-
- goto R<NAME>
-
-Jump to the named identifier (label or subroutine name).
-
-=head3 if
-
-X<if (conditional);instruction (PIR)>
-
- if R<EXPR> goto R<NAME>
-
-If the value or expression evaluates as true, jump to the named
-identifier.
-
-=head3 unless
-
-X<unless (conditional);instruction (PIR)>
-
- unless R<VAL> goto R<NAME>
-
-Unless the value evaluates as true, jump to the named identifier.
-
-=cut
-
-# Local variables:
-# c-file-style: "parrot"
-# End:
-# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/README (from r39796, trunk/docs/book/draft/README)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/README Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/README)
@@ -0,0 +1,24 @@
+The book will have the following chapters.
+
+1) Overview
+2) Getting Started
+3) Parrot Intermediate Representation (PIR)
+4) Compiler Tools (PCT)
+5) Grammar Engine (PGE)
+6) Grammar Actions (NQP)
+7) Dynamic C-level Objects (PMCs)
+8) Dynamic Opcodes
+9) Parrot Assembly Language (PASM)
+10) Instruction Reference
+11) Directive Reference
+12) Operator Reference
+Appendix A) Glossary
+Appendix B) Patch Submission
+Appendix C) Command-Line Options
+Appendix D) Build Options
+Appendix E) Source Code
+
+
+Top-level headings in each chapter (the chapter title) are level 1 headings.
+All sub-headings in the chapter are level 2 and below. All chapter files should
+contain the VIM suffix (which is a codingstd for all of the Parrot repo).
Copied: branches/pmc_pct/docs/book/draft/appa_glossary.pod (from r39796, trunk/docs/book/draft/appa_glossary.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/appa_glossary.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/appa_glossary.pod)
@@ -0,0 +1,321 @@
+=pod
+
+=head1 Glossary
+
+Short descriptions of words and acronyms found in Parrot development.
+
+=over 4
+
+=item AST
+
+Abstract Syntax Tree: a data structure typically generated by a language
+parser.
+
+=item Continuations
+
+Think of continuations as an execution "context". This context includes
+everything local to that execution path, not just the stack. It is a snapshot
+in time (minus global variables). While it is similar to C's C<setjmp> (taking
+the continuation)/C<longjmp> (invoking the continuation), C<longjmp>'ing only
+works "down" the stack; jumping "up" the stack (ie, back to a frame that has
+returned) is bad. Continuations can work either way.
+
+We can do two important things with continuations:
+
+=over 4
+
+=item 1
+
+Create and pass a continuation object to a subroutine, which may recursively
+pass that object up the call chain until, at some point, the continuation can
+be called/executed to handle the final computation or return value. This is
+pretty much tail recursion.
+
+=item 2
+
+Continuations can be taken at an arbitrary call depth, freezing the call chain
+(context) at that point in time. If we save that continuation object into a
+variable, we can later reinstate the complete context by its "handle". This
+allows neat things like backtracking that aren't easily done in conventional
+stacked languages, such as C. Since continuations represent "branches" in
+context, it requires an environment that uses some combination of heap-based
+stacks, stack trees and/or stack copying.
+
+=back
+
+It is common in a system that supports continuations to implement
+L<co-routines|"Co-Routines"> on top of them.
+
+A continuation is a sort of super-closure. When you take a continuation, it
+makes a note of the current call stack and lexical scratchpads, along with the
+current location in the code. When you invoke a continuation, the system drops
+what it's doing, puts the call stack and scratchpads back, and jumps to the
+execution point you were at when the continuation was taken. It is, in effect,
+like you never left that point in your code.
+
+Note that, like with closures, it only puts the B<scratchpads> back in scope -
+it doesn't do anything with the values in the variables that are in those
+scratchpads.
+
+=item Co-Routines
+
+Co-routines are virtually identical to normal subroutines, except while
+subroutines always execute from their starting instruction to where they
+return, co-routines may suspend themselves (or be suspended asynchronously if
+the language permits) and resume at that point later. We can implement things
+like "factories" with co-routines. If the co-routine never returns, every time
+we call it, we "resume" the routine.
+
+A co-routine is a subroutine that can stop in the middle, and start back up
+later at the point you stopped. For example:
+
+ sub sample : coroutine {
+ print "A\n";
+ yield;
+ print "B\n";
+ return;
+ }
+
+ sample();
+ print "Foo!\n";
+ sample();
+
+will print
+
+ A
+ Foo!
+ B
+
+Basically, the C<yield> keyword says, "Stop here, but the next time we're
+called, pick up at the next statement." If you return from a co-routine, the
+next invocation starts back at the beginning. Co-routines remember all their
+state, local variables, and suchlike things.
+
+=item COW
+
+Copy On Write: a technique that copies strings lazily.
+
+If you have a string A, and make a copy of it to get string B, the two strings
+should be identical, at least to start. With COW, they are, because string A
+and string B aren't actually two separate strings - they're the same string,
+marked COW. If either string A or string B are changed, the system notes it and
+only at that point does it make a copy of the string data and change it.
+
+If the program never actually changes the string - something that's fairly
+common - the program need never make a copy, saving both memory and time.
+
+=item destruction
+
+Destruction is low level memory clean up, such as calling C<free> on
+C<malloc>ed memory. This happens after L<"finalization">, and if resources are
+adequate, may only happen as a side effect of program exit.
+
+=item DOD
+
+Dead Object Detection: the process of sweeping through all the objects,
+variables, and whatnot inside of Parrot, and deciding which ones are in use and
+which ones aren't. The ones that aren't in use are then freed up for later
+reuse. (After they're destroyed, if active destruction is warranted.)
+
+See also: L<"GC">
+
+=item finalization
+
+Finalization is high-level, user visible cleanup of objects, such as closing an
+associated DB handle. Finalization reduces active objects down to passive
+blocks of memory, but does not actually reclaim that memory. Memory is
+reclaimed by the related L<"destruction"> operation, as and when necessary.
+
+=item GC
+
+Garbage Collection: the process of sweeping through all the active objects,
+variables, and structures, marking the memory they're using as in use, and all
+other memory is freed up for later reuse.
+
+Garbage Collection and Dead Object Detection are separate in Parrot, since we
+generally chew through memory segments faster than we chew through objects.
+(This is a characteristic peculiar to Perl and other languages that do string
+processing. Other languages chew through objects faster than memory)
+
+See also: L<"DOD">
+
+=item HLL
+
+High-Level Language; Any of the languages that target the parrot virtual
+machine.
+
+=item ICU
+
+International Components for Unicode
+
+ICU is a C and C++ library that provides support for Unicode on a variety of
+platforms. It was distributed with parrot at one time, but current releases
+require you to get your own copy.
+
+L<http://oss.software.ibm.com/icu/index.html>
+
+=item IMCC
+
+Intermediate Code Compiler: the component of parrot that compiles PASM
+and PIR into bytecode.
+
+See also L<"PIR">.
+
+=item MRO
+
+Method resolution order
+
+=item NCI
+
+Native Call Interface: parrot's interface to native "C" libraries,
+without a C-compiler.
+
+=item NQP
+
+Not Quite Perl (6): designed to be a very small compiler for
+quickly generating PIR routines to create transformers for Parrot (especially
+HLL compilers).
+
+See also L<"PCT">.
+
+=item Packfile
+
+Another name for a PBC file, due to the names used for data structures in one
+of the early implementations in Perl 5.
+
+=item PAST
+
+Acronym for Parrot Abstract Syntax Tree, a set of classes that represent an
+abstract syntax tree.
+
+See also L<"PCT">.
+
+=item PBC
+
+Parrot Bytecode. The name for the "executable" files that can be passed to the
+Parrot interpreter for immediate execution (although PASM and IMC files can be
+executed directly, too).
+
+See also L<"Packfile">.
+
+=item PCT
+
+Parrot Compiler Toolkit: a complete set of tools and libraries
+that are designed to create compilers targeting Parrot. The principal
+components of PCT are PGE, PCT::HLLCompiler (a compiler driver), PAST classes,
+POST classes, PCT::Grammar (a base class for PGE grammars).
+
+In the ideal case, a language can be implemented by providing its parser
+(using Perl 6 rules) which is generated by PGE, and providing a module written
+in NQP that contains the I<actions> that are to be invoked during the parse.
+These actions can then create the appropriate PAST nodes. A PAST to PIR
+transformation already exists. Depending on the language, other phases can
+be added, or overridden (for instance, the PAST to PIR transformation).
+
+=item PIRC
+
+Acronym for PIR Compiler, a PIR compiler currently under development.
+The purpose is to reimplement the PIR language, which is currently
+implemented by IMCC. PIRC is written using a Bison and Flex grammar
+specification.
+
+=item PDD
+
+Parrot Design Document: documents that describe the features parrot must
+implement.
+
+=item PGE
+
+Parrot Grammar Engine.
+
+See also L<"PCT">.
+
+=item PIR
+
+Parrot Intermediate Representation: A medium-level assembly language for Parrot
+that hides messy details like register allocation so language compiler writers
+who target Parrot don't have to roll their own. Files have the
+extension C<.pir>.
+
+=item PMC
+
+Polymorphic Container: these classes are the primitives that
+HLLs use to represent their fundamental types, such as Perl's
+scalar values.
+
+=item Pod
+
+The preferred format for all kinds of documentation in Parrot.
+
+=item POST
+
+Parrot Opcode Syntax Tree: A set of classes that represent opcodes.
+
+See also L<"PCT">.
+
+=item Predereferencing
+
+=for comment
+XXX This section needs to be edited down.
+
+A bytecode transformation technique which reduces the amount of pointer
+dereferencing done in the inner loop of the interpreter by pre-converting
+opcode numbers into pointers to their opfuncs, and also converting the register
+numbers and constant numbers in the arguments to the ops into pointers.
+
+The original implementation by Gregor Purdy was posted on 2001-12-11. On one
+test system, it resulted in a 22% speed increase on a test program with a tight
+inner loop.
+
+L<http://archive.develooper.com/perl6-internals@perl.org/msg06941.html>
+
+On 2001-12-18, predereferencing got a speed boost (to about 47% faster than the
+regular DO_OP inner loop -- without compiler optimizations turned on). This was
+due to an off-list (actually over lunch) suggestion by John Kennedy that
+instead of pre-initializing the new copy of the bytecode with NULL pointers, we
+pre-initialize it with pointers to a pseudo-opfunc that does the
+predereferencing whenever it is encountered.
+
+On 2002-04-11, Jason Gloudon suggested combining aspects of the Computed Goto
+Core and the Prederef[erencing] Core.
+
+L<http://archive.develooper.com/perl6-internals@perl.org/msg07064.html>
+
+The week of 2003-02-09, Leopold Toetsch combined Computed Goto and
+Predereferencing to produce the CGP core.
+
+L<http://dev.perl.org/perl6/list-summaries/2003/p6summary.2003-02-09.html#Week_of_the_alternative_runloops>
+
+Later, on 2003-02-14, Leopold Totsch and Nicholas Clark combined the JIT and
+the Computed Goto Prederef cores to great effect.
+
+L<http://www.perl.com/pub/a/2003/02/p6pdigest/20030216.html>
+
+=item Run Core
+
+aka run loop, aka runcore. The way Parrot executes PBCs.
+See L<running.pod> for a list of available runcores, and how to tell
+parrot which one to use.
+
+=item TGE
+
+Tree Grammar Engine: a tool that can be used to generate tree transformers.
+
+=item vtable
+
+A table of operations attached to some data types, such as PMCs and strings.
+Vtables are used to avoid using switches or long C<if> chains to handle
+different data types. They're similar to method calls, except that their names
+are pre-selected, and there is no direct way to invoke them from PIR.
+
+=item Warnock's Dilemma
+
+The dilemma you face when posting a message to a public forum about something
+and not even getting an acknowledgment of its existence. This leaves you
+wondering if your problem is unimportant or previously addressed, if everyone's
+waiting on someone else to answer you, or if maybe your mail never actually
+made it to anyone else in the forum.
+
+=back
+
+=cut
Copied: branches/pmc_pct/docs/book/draft/appb_patch_submission.pod (from r39796, trunk/docs/book/draft/appb_patch_submission.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/appb_patch_submission.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/appb_patch_submission.pod)
@@ -0,0 +1,138 @@
+=pod
+
+=head1 Patch submission
+
+X<Parrot;patch submission>
+Parrot development proceeds through a continuous stream of patches.
+Patches are the currency of exchange in the project--the unit of
+work. Patches can fix bugs, add features, modify capabilities,
+remove cruft, and improve the suite of tests and the project
+documentation. If something needs to change, it will typically require
+the submission of a new patch.
+
+While anyone is free to submit a patch, only a small number of people have
+the ability to apply patches to the central Parrot repository.
+These people are called I<committers>. By allowing all people to get
+involved through patch submission and testing, the project can harness
+the efforts of a large group but still keep the same high quality
+as a small group of experienced developers.
+
+Every submitted patch is automatically forwarded to the p2 list where
+it's subject to peer review. Small patches typically spark little debate,
+and can be well-tested on many platforms before being committed to the
+repository. Patches tend to be small modular changes, which makes for
+easy testing and evaluation. Occasionally a large feature such as an entire
+language implementation is submitted in a single patch, but these are the
+exceptions.
+
+Submitting a patch is fairly straightforward. You create a file that
+lists all your changes, a diff or a patch, and email it to the ticket
+tracking system at U<parrotbug at parrotcode.org>. It's important to make
+sure your patch and your email have descriptive titles so that the
+committers and testers have a better idea about what it does. The body of
+your email should also include a good description about what you changed
+and why.
+
+It's important that you create your patches from a checked-out subversion
+repository, not from a tarball or a snapshot. This way, you can ensure
+that your diff is made against the latest version of the files. If you patch
+an old version, the problem may have already been resolved! Make sure
+the paths listed in the patch match those in the repository. There are two
+methods of creating patches that will do this for you. You can make changes
+directly in your checked-out copy of the subversion repository and
+then create diffs using the command C<svn diff>. Alternatively, you can
+make a copy of the repository and then create diffs between the two
+copies with the C<diff -u> command:
+
+ diff -u parrot/README parrot_changed/README
+
+Either method is fine, and both are equally common on p2. Your
+working style and the types of changes you make--small and modular
+versus large and sweeping--will influence which method you choose.
+
+Next, when you're making changes, take some extra time to consider how
+your patch affects the rest of the system. If your patch adds a new
+file, patch the main F<MANIFEST> file to include it. If you add a new
+feature, make sure to write tests for it. If you fix a bug, add a test
+to prove that it's fixed. See "Writing Tests" in Chapter
+9 for more on writing tests for Parrot. Tests are very important for
+Parrot development, and writing good tests is a valuable skill for
+developers to have. Before you submit a patch always recompile the
+system yourself with the patch included and run all tests to prove that
+it works. You can build and test Parrot completely by running the
+following commands:
+
+ make clean
+ perl Configure.pl
+ make
+ make test
+
+Consider the people who will review and apply your patch, and try
+to make their jobs easier. Patch filenames should be as descriptive as
+possible: F<fix_readme_aardvark_typo.patch> is far better than
+F<README.patch>. An attached file is better than a diff pasted into an
+email, because it can be applied without manual editing. The
+conventional extension for patch files is F<.patch>.
+
+In the email message, always start the subject with "[PATCH]", and
+make the subject as clear as possible: "[PATCH] misspelled aardvark in
+main README file" is better than "[PATCH] typo". The body of the
+message should clearly explain what the patch is supposed to do and
+why you're submitting it. Make a note if you're adding or deleting
+files so they won't be missed.
+
+Here is a good example of a patch submission using the subversion diff
+method (an actual patch from p2). It's short, sticks to the point, and
+clearly expresses the problem and the solution. The patch filename and
+the subject of the message are both descriptive:
+
+=for author
+
+Possible alternates: ticket #23501, #24053 (not from top level)
+
+=end for
+
+ Subject: [PATCH] Pointers in List_chunk not initialized
+ From: Bruce Gray
+
+ On Win32, these tests are segfaulting due to invalid
+ pointers in List_chunk structs:
+ t/op/string.t 97-98
+ t/pmc/intlist.t 3-4
+ t/pmc/pmc.t 80
+
+ The problem is caused by list.c/allocate_chunk not
+ initializing the pointers. This patch corrects the problem.
+
+ --
+ Hope this helps,
+ Bruce Gray
+
+With the attached file F<list_chunk_initialize.patch>:
+
+
+ Index: list.c
+ =========================================
+ RCS file: /cvs/public/parrot/list.c,v
+ retrieving revision 1.23
+ diff -u -r1.23 list.c
+ --- list.c 27 Dec 2002 09:33:11 -0000 1.23
+ +++ list.c 28 Dec 2002 03:37:35 -0000
+ @@ -187,6 +187,10 @@
+ Parrot_block_GC_sweep(interpreter);
+ chunk = (List_chunk *)new_bufferlike_header(interpreter, sizeof(*chunk));
+ chunk->items = items;
+ + chunk->n_chunks = 0;
+ + chunk->n_items = 0;
+ + chunk->next = NULL;
+ + chunk->prev = NULL;
+ Parrot_allocate_zeroed(interpreter, (Buffer *)chunk, size);
+ Parrot_unblock_GC_mark(interpreter);
+ Parrot_unblock_GC_sweep(interpreter);
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/appc_command_line_options.pod (from r39796, trunk/docs/book/draft/appc_command_line_options.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/appc_command_line_options.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/appc_command_line_options.pod)
@@ -0,0 +1,340 @@
+=pod
+
+=head1 Command-Line Options
+
+Z<CHP-13-SECT-4>
+
+X<command-line options (Parrot)>
+X<Parrot;command-line options>
+X<running.pod file>
+Since Parrot is both an assembler and a bytecode interpreter, it
+has options to control both behaviors. Some options may have changed
+by the time you read this, especially options related to debugging and
+optimization. The document F<imcc/docs/running.pod> should
+have the latest details. Or just run F<parrot --help>.
+
+=head2 General Usage
+
+Z<CHP-13-SECT-4.1>
+
+ parrot [options] file [arguments]
+
+The R<file> is either an F<.pir> or F<.pasm> source file or a
+Parrot bytecode file. Parrot creates an C<Array> object to hold the
+command-line R<arguments> and stores it in C<P5> on program start.
+
+=head2 Assembler Options
+
+Z<CHP-13-SECT-4.2>
+
+=over 4
+
+=item -a, --pasm
+
+X<Parrot;assembler options>
+Assume PASM input on C<stdin>. When Parrot runs a source file with a
+F<.pasm> extension, it parses the file as pure PASM code. This switch
+turns on PASM parsing (instead of the default PIR parsing) when a
+source file is read from C<stdin>.
+
+=item -c,--pbc
+
+Assume PBC file on C<stdin>. When Parrot runs a bytecode file with a
+F<.pbc> extension, it immediately executes the file. This option tells
+Parrot to immediately execute a bytecode file piped in on C<stdin>.
+
+=item -d,--debug [R<hexbits>]
+
+Turn on debugging output. The C<-d> switch takes an optional argument,
+which is a hex value of debug bits. The individual bits are shown in
+Table 11-3. When R<hexbits> isn't specified,
+the default debugging level is 0001. If R<hexbits> is separated
+from the C<-d> switch by whitespace, it has to start with a number.
+
+=begin table picture Debug bits
+
+Z<CHP-13-TABLE-3>
+
+=headrow
+
+=row
+
+=cell Description
+
+=cell Debug bit
+
+=bodyrows
+
+=row
+
+=cell DEBUG_PARROT
+
+=cell 0001
+
+=row
+
+=cell DEBUG_LEXER
+
+=cell 0002
+
+=row
+
+=cell DEBUG_PARSER
+
+=cell 0004
+
+=row
+
+=cell DEBUG_IMC
+
+=cell 0008
+
+=row
+
+=cell DEBUG_CFG
+
+=cell 0010
+
+=row
+
+=cell DEBUG_OPT1
+
+=cell 0020
+
+=row
+
+=cell DEBUG_OPT2
+
+=cell 0040
+
+=row
+
+=cell DEBUG_PBC
+
+=cell 1000
+
+=row
+
+=cell DEBUG_PBC_CONST
+
+=cell 2000
+
+=row
+
+=cell DEBUG_PBC_FIXUP
+
+=cell 4000
+
+=end table
+
+X<Parrot;debugging bits>
+X<debugging bits (Parrot)>
+To produce a huge output on C<stderr>, turn on all the debugging bits:
+
+ $ parrot -d 0ffff ...
+
+
+=item --help-debug
+
+Show debug option bits.
+
+=item -h,--help
+
+Print a short summary of options to C<stdout> and exit.
+
+=item -o R<outputfile>
+
+Act like an assembler. With this switch Parrot won't run code unless
+it's combined with the C<-r> switch. If the name of R<outputfile> ends
+with a F<.pbc> extension, Parrot writes a Parrot bytecode file. If
+R<outputfile> ends with a F<.pasm> extension, Parrot writes a PASM
+source file, even if the input file was also PASM. This can be handy
+to check various optimizations when you run Parrot with the C<-Op>
+switch.
+
+If the extension is F<.o> or equivalent, Parrot generates an object
+file from the JITed program code, which can be used to create a
+standalone executable program. This isn't available on all platforms
+yet; see F<PLATFORMS> for which platforms support this.
+
+=item -r,--run-pbc
+
+Immediately execute bytecode. This is the default unless C<-o> is
+present. The combination of C<-r> C<-o> C<output.pbc> writes a
+bytecode file and executes the generated PBC.
+
+=item -v,--verbose
+
+One C<-v> switch (C<imcc> C<-v>) shows which files are worked on and
+prints a summary of register usage and optimization statistics. Two
+C<-v> switches (C<imcc> C<-v> C<-v>) also prints a line for each
+individual processing step.
+
+=item -y,--yydebug
+
+Turn on C<yydebug> for F<yacc>/F<bison>.
+
+=item -E,--pre-process-only
+
+Show output of macro expansions and quit.
+
+=item -V,--version
+
+Print the program version to C<stdout> and exit.
+
+=item -Ox
+
+Turn on optimizations. The flags currently implemented are shown in
+Table 11-4.
+
+X<Parrot;optimizations>
+X<optimizations (Parrot)>
+
+=begin table picture Optimizations
+
+Z<CHP-13-TABLE-4>
+
+=headrow
+
+=row
+
+=cell Flag
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<-O0>
+
+=cell No optimization (default).
+
+=row
+
+=cell C<-O1>
+
+=cell Optimizations without life info (e.g. branches and constants).
+
+=row
+
+=cell C<-O2>
+
+=cell Optimizations with life info.
+
+=row
+
+=cell C<-Oc>
+
+=cell Optimize function call sequence.
+
+=row
+
+=cell C<-Op>
+
+=cell Rearrange PASM registers with the most-used first.
+
+=end table
+
+=back
+
+=head2 Runcore Options
+
+Z<CHP-13-SECT-4.3>
+
+X<Parrot;bytecode interpreter options>
+X<bytecode interpreter options (Parrot)>
+X<computed goto core>
+X<fast core>
+The interpreter options are mainly for selecting which run-time core to
+use for interpreting bytecode. The current default is the I<computed
+goto core> if it's available. Otherwise the I<fast core> is used.
+
+=over 4
+
+=item -R slow
+
+Run with the I<slow core>
+
+=item -R bounds
+
+Activate bounds checking. This also runs with the I<slow core> as a
+side effect.
+
+=item -R fast
+
+Run with the I<fast core>.
+
+=item -R cgoto
+
+Run the I<computed goto core> (CGoto).
+
+=item -R jit
+
+Run with the I<JIT core> if available.
+
+=item -R cgp
+
+Run with the I<CGoto-Prederefed> core.
+
+=item -R cgp-jit
+
+Run with the I<CGoto-Prederefed with jit> core.
+
+=item -R switch
+
+Run with the I<Switched core>.
+
+=item -R switch-jit
+
+Run with the I<Switched core with jit>.
+
+=item -R exec
+
+Run with the I<exec core>
+(uses JIT at compile time to generate native code)
+
+=item -R gcdebug
+
+Performs a full GC run before every op dispatch
+(good for debugging GC problems)
+
+=item -p,--profile
+
+Activate profiling. This prints a summary of opcode usage and
+execution times after the program stops. It also runs within the
+I<slow core>.
+
+=item -t,--trace
+
+Trace execution. This also turns on the I<slow core>.
+
+=item -w,--warnings
+
+Turn on warnings.
+
+=item -G,--no-gc
+
+Turn off GC. This is for debugging only.
+
+=item -.,--wait
+
+Wait for a keypress before running.
+
+=item --leak-test,--destroy-at-end
+
+Cleanup up allocated memory when the final interpreter is destroyed.
+C<Parrot> destroys created interpreters (e.g. threads) on exit but
+doesn't normally free all memory for the last terminating interpreter,
+since the operating system will do this anyway. This can create false
+positives when C<Parrot> is run with a memory leak detector. To prevent
+this, use this option.
+
+=back
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/appd_build_options.pod (from r39796, trunk/docs/book/draft/appd_build_options.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/appd_build_options.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/appd_build_options.pod)
@@ -0,0 +1,93 @@
+=pod
+
+=head1 Build Requirements
+
+There are a number of requirements for building Parrot from source, and a
+number of optional libraries and components that can be used to extend its
+capabilities. None of these requirements or optional components are necessary
+unless you are building Parrot from the source code.
+
+=over 4
+
+=item * C Compiler
+
+Parrot can be built with a number of C compilers. Parrot is written using the
+C89 standard, and the Parrot project officially supports the most recent
+C89 compiler on major systems, including the most recent versions of Microsoft
+C Compiler and the GNU Compiler Collection (GCC).
+
+=item * make
+
+Make is a program to manage and automate the build process. Unix-based systems
+will typically have access to the C<make> command as part of the normal
+development tools. Windows systems can get the C<nmake> utility to perform the
+same task.
+
+=item * Subversion
+
+Subversion is the source control system that is used by the Parrot project.
+You need subversion to checkout the latest version of the source code. You can
+get subversion at L<http://subversion.tigris.org>, or through one of the
+common packaging systems.
+
+=item * bison and flex
+
+Bison and Flex are used to create the lexical analyzer and parser components
+for the PIR compilers IMCC and PIRC. These are not necessary most of the time
+unless you are planning to hack on IMCC and PIRC directly.
+
+=item * ICU
+
+ICU is a library for handling and manipulating Unicode text strings. Without
+ICU libraries installed, you wont be able to use Unicode with your built
+Parrot.
+
+=item * GMP
+
+GMP is a mathematics library for manipulating arbitrary precision and
+arbitrary size numbers. GMP is an optional library used by the BigInt
+and BigNum PMCs.
+
+=item * Readline
+
+The readline library allows some advanced behaviors on the command line such
+as command history.
+
+=item * PCRE
+
+PCRE is a library that provides access to the Perl 5 regular expression syntax.
+In order to use these regular expressions, you will want to install PCRE. To
+do that on Linux you use the command:
+
+ sudo apt-get install libpcre3-dev
+
+=item * GDBM
+
+=item * PQ
+
+=item * GLUT
+
+GLUT is an interface to the OpenGL API. It enables programs running on Parrot
+to have access to 3D graphics. To get GLUT on Linux systems you can use the
+command:
+
+ sudo apt-get install libglut3-dev
+
+=back
+
+In addition to these build requirements listed above, there are a number
+of Perl libraries needed to enable the full set of tests and testing
+facilities, and to generate all the necessary documentation.
+
+To get the Perl packages for Parrot, you can use the commands:
+
+ sudo cpan Test::Base Test::Pod Test::Pod::Coverage Pod::Spell
+ sudo cpan File::HomeDir File::Which Readonly Regexp::Parser
+ sudo cpan Perl::Critic Perl::Critic::Bangs Test::Perl::Critic
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/appe_source_code.pod (from r39796, trunk/docs/book/draft/appe_source_code.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/appe_source_code.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/appe_source_code.pod)
@@ -0,0 +1,72 @@
+=pod
+
+=head3 Use the source
+
+X<Parrot;source code>
+The second step to participating in Parrot development is to get a
+copy of the source code. If you just want to try it out--experiment
+with a few features and see how it feels--the best option is to
+download the most recent point release for your system. Point releases
+are usually packaged up for easy download and install for various
+platforms, including Windows, Debian, and Redhat. Point releases are
+available from U<http://www.parrot.org/download>.
+
+If you plan to get involved in development, you'll want to check out
+the source from the subversion repository directly. Anyone can get
+anonymous access to read the files and download a working copy to
+explore and test. For commit access, volunteers need a
+U<https://trac.parrot.org> username, and need to be approved by a
+Metacommitter. To download the most recent version from SVN, type this
+command into your terminal N<This is for Linux users, on Mac or
+Windows systems, follow the instructions from your SVN client>:
+
+ svn co https://svn.parrot.org/parrot/trunk parrot
+
+There's also a web interface for viewing files in the repository at
+U<http://svn.parrot.org/parrot/>.
+
+The repository is large and complex, so it's worth taking a little bit
+of time to explore. The code changes constantly, but most files and
+functions have informative descriptions to help keep track of things.
+
+The most important top-level directory is F<docs/>. The content isn't
+always up to date, but it is a good place to start. F<parrot.pod>
+provides a quick overview of what's in each documentation file. If you're
+a capable writer and know a thing or two about how Parrot works, the
+documentation is a great place to start contributing. This book that
+you're reading right now was created in F<docs/book/> by ordinary
+contributors. Most other documentation files found here are parsed and
+converted to HTML for display at U<http://www.parrot.org>.
+
+There are a number of existing language implementations for Parrot:
+Perl 6, Python ("Pynie"), Ruby ("Cardinal"), PHP ("Pipp"), Lisp, Lua,
+Tcl ("partcl"), WMLScript, Forth, Scheme, Befunge, BASIC, and many
+others. These language compilers are in various stages of partial
+completion. The page L<https://trac.parrot.org/parrot/wiki/Languages>
+provides meta information on these languages and where to find them.
+If you have a language you're particularly interested to see implemented
+on Parrot, you can see how far along the effort is, or you can start the
+work to implement it yourself. We'll talk more about creating new
+compilers in Chapter 10: High-Level Languages, if you're interested.
+
+The F<lib/> directory contains Perl 5 classes currently used in
+developing, building, and testing Parrot. The F<src/pmc/> directory
+contains the C source code for Parrot classes (PMCs, which you'll read
+more about in Chapter 11).
+
+Most Parrot development happens in F<src/> for the C source code, and
+F<include/parrot/> for the C development header files.
+
+Libraries for use by programs running on Parrot are found in F<runtime/>.
+
+The F<examples/> directory contains some example Parrot PIR and Assembly
+code, as well as benchmarks. More discussions about these topics will be
+found in Chapter 3, Chapter 5, and Chapter 7
+respectively.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch01_introduction.pod (from r39796, trunk/docs/book/draft/ch01_introduction.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch01_introduction.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch01_introduction.pod)
@@ -0,0 +1,215 @@
+=pod
+
+=head1 Introduction
+
+Parrot is a language-neutral virtual machine for dynamic languages such as
+Ruby, Python, PHP, and Perl. It hosts a powerful suite of compiler tools
+tailored to dynamic languages and a next generation regular expression engine.
+Its architecture is fundamentally different than existing virtual machines such
+as the JVM or CLR, with optimizations for dynamic languages included, a
+register-based system rather than stack-based, and the use of continuations as
+the core means of flow control.
+
+The name "Parrot" was inspired by Monty Python's Parrot sketch. As an April
+Fools' Day joke in 2001, Simon Cozens published "Programming Parrot", a
+fictional interview between Guido van Rossum and Larry Wall detailing their
+plans to merge Python and Perl into a new language called Parrot
+(U<http://www.perl.com/pub/a/2001/04/01/parrot.htm>).
+
+=head2 Parrot Resources
+
+The starting point for all things related to Parrot is the main website
+U<http://www.parrot.org/>. The site lists additional resources, well as recent
+news and information about the project and the Parrot Foundation, which holds
+the copyright over Parrot and helps guide development and the community.
+
+=head3 Documentation
+
+Parrot includes extensive documentation in the distribution. The full
+documentation for the latest release is available online at
+U<http://docs.parrot.org/>.
+
+=head3 Mailing Lists
+
+X<parrot-dev (Parrot mailing list)>
+X<mailing lists>
+
+The primary mailing list for Parrot is I<parrot-dev at lists.parrot.org>. If
+you're interested in getting involved in development, you may also want to
+follow the I<parrot-commits> and I<parrot-tickets> lists. Information on all
+the Parrot mailing lists and subscription forms for each is available at
+U<http://lists.parrot.org/mailman/listinfo>.
+
+The archives for I<parrot-dev> are also available on Google Groups at
+U<http://groups.google.com/group/parrot-dev> and via NNTP at
+U<nntp://news.gmane.org/gmane.comp.compilers.parrot.devel>.
+
+=head3 IRC
+
+X<#parrot (Parrot IRC channel)>
+X<IRC channel (#parrot)>
+
+Parrot developers and users congregate on IRC at C<#parrot> on the
+U<irc://irc.parrot.org> server. It's a good place to get real-time answers to
+questions or see how things are progressing.
+
+=head3 Issue Tracking & Wiki
+
+X<trac.parrot.org website>
+X<issue tracking (trac.parrot.org)>
+
+Parrot developers track issues with a Trac site at U<https://trac.parrot.org/>.
+Users can submit new tickets and track the status of existing tickets. The
+site also includes a wiki used in project development, a source code browser,
+and the project roadmap.
+
+=head2 Parrot Development
+
+X<development cycles>
+
+Parrot's first release occurred in September 2001. It reached 1.0 in March
+2009. The Parrot project makes releases on the third Tuesday of each month. Two
+releases a year E<mdash> occuring every January and July E<mdash> are
+"supported" releases intended for production use. The other ten releases are
+development releases for language implementers and testers.
+
+Development proceeds in cycles around releases. Activity just before a release
+focuses on closing tickets, fixing bugs, reviewing documentation, and preparing
+for the release. Immediately after the release, larger changes occur, such as
+merging branches, adding large features, or removing deprecated features. This
+allows developers to ensure that changes have sufficient testing time before
+the next release. Releases also encourage feedback as casual users and testers
+explore the newest versions.
+
+=head2 The Parrot Team
+
+Parrot developers fulfill several rules according to their skills and interests.
+
+=over 4
+
+=item Architect
+
+X<architect role>
+
+The architect has primary responsibility for setting the overall direction of
+the project, facilitating team communication, and explaining and evaluating
+architectural issues. The architect makes design decisions and documents them
+in Parrot Design Documents, and oversees design and documentation work
+delegated to other members of the team to provide a coherent vision across the
+project. The architect also works with the release managers to develop and
+maintain the release schedule. Allison Randal currently leads the Parrot
+project as architect.
+
+=item Release Managers
+
+X<release manager role>
+
+Release managers manage and produce monthly releases according to the release
+schedule. Parrot has multiple release managers who rotate the responsibility
+for each monthly release. The release managers develop and maintain the release
+schedule jointly with the project architect.
+
+=item Metacommitter
+
+X<metacommitter role>
+
+Metacommitters manage commit access to the Parrot repository. Once a
+contributor is selected for commit access, a metacommitter gives the new
+committer access to the SVN repository and the bugtracker. The architect is a
+metacommitter, but other team members also hold this role.
+
+=item Committer
+
+X<committer role>
+
+Contributors who submit numerous, high-quality patches may be considered to
+become a committer. Committers have commit access to the full Parrot
+repository, though they often specialize on particular parts of the project.
+Contributors may be considered for commit access either by being nominated by
+another committer, or by requesting it.
+
+=item Core Developer
+
+X<core developer role>
+
+Core developers develop and maintain core subsystems such as the I/O
+subsystem, the exceptions system, or the concurrency scheduler.
+
+=item Compiler Developer
+
+X<compiler developer role>
+
+Compiler developers develop and maintain one or more Parrot front-end
+compilers such as IMCC, PIRC, PGE and TGE.
+
+=item High-Level Language Developer
+
+X<HLL developer role>
+
+Developers who work on any of the high-level languages that target
+ParrotE<mdash>such as Lua, Perl, PHP, Python, Ruby, or TclE<mdash>are
+high-level language developers. The Parrot repository includes a few example
+languages. A full list of languages is available at
+U<https://trac.parrot.org/parrot/wiki/Languages>.
+
+=item Build Manager
+
+X<build manager role>
+
+Build managers maintain and extend configuration and build subsystems.
+They review smoke reports and attempt to extend platform support.
+
+=item Tester
+
+X<tester role>
+
+Testers develop, maintain, and extend the core test suite coverage and testing
+tools. Testers are also responsible for testing goals, including complete
+coverage of core components on targeted platforms.
+
+=item Patch Monsters
+
+X<patch monster role>
+
+Hackers and developers submit patches to Parrot every day, and it takes a keen
+eye and a steady hand to review and apply them all. Patch monsters check
+patches for conformance with coding standards and desirability of features,
+rework them as necessary, verify that the patches work as desired, and apply
+them.
+
+=item Cage Cleaners
+
+X<cage cleaner role>
+
+The cage cleaners ensure that development follows the project's coding
+standards, documentation is complete and accurate, all tests function properly,
+and new users have accurate and comprehensive coding examples. A special class
+of Trac tickets is available for these tasks. Cage cleaning tasks run the
+gamut from entry-level to advanced; this is a good entry point for new users
+to work on Parrot.
+
+=item General Contributor
+
+X<contributor role>
+
+Contributors write code or documentation, report bugs, take part in email or
+online conversations, or contribute to the project in other ways. All volunteer
+contributions are appreciated.
+
+=back
+
+=head2 Licensing
+
+X<license>
+
+The Parrot foundation supports the Parrot development community and holds
+trademarks and copyrights to Parrot. The project is available under the
+Artistic License 2.0, allowing free use in commercial and open source/free
+software contexts.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch02_getting_started.pod (from r39796, trunk/docs/book/draft/ch02_getting_started.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch02_getting_started.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch02_getting_started.pod)
@@ -0,0 +1,182 @@
+=pod
+
+=head1 Getting Started
+
+Before you can use Parrot, you have to get it running on your machine.
+
+=head2 Installing Parrot
+
+The simplest way to install Parrot is to use a pre-compiled binary for your
+operating system or distribution. Packages are available for many packaging
+systems, including Debian, Ubuntu, Fedora, Mandriva, FreeBSD, Cygwin, and
+MacPorts. The Parrot website lists all known packages at
+U<http://www.parrot.org/download>. A binary installer for Windows is also
+available at U<http://parrotwin32.sourceforge.net/>.
+
+If packages aren't available on your system, download the latest supported
+release from U<http://www.parrot.org/release/supported>.
+
+You need a C compiler and a make utility to build Parrot from source code --
+usually C<gcc> and C<make>, but Parrot can build with standard compiler
+toolchains on different operating systems. Perl 5.8 is also a prerequiste for
+configuring and building Parrot.
+
+If you have these dependencies installed, build the core virtual machine and
+compiler toolkit and run the standard test suite with the commands:
+
+ $ B<perl Configure.pl>
+ $ B<make>
+ $ B<make test>
+
+By default, Parrot installs to directories F<bin/>, C<lib/>, et cetera under
+the prefix F</usr/local>. If you have privileges to write to these
+directories, install Parrot with:
+
+ $ B<make install>
+
+To install Parrot beneath a different prefix, use the C<--prefix> option to
+C<Configure.pl>:
+
+ $ B<perl Configure.pl --prefix=/home/me/parrot>
+
+If you intend to I<develop> -- not just I<use> -- a language on Parrot, install
+the Parrot developer tools as well:
+
+ $ B<make install-dev>
+
+=head2 Running Parrot
+
+Once you've installed Parrot, run it. Create a test file called F<news.pasm>.
+C<.pasm> files contain Parrot Assembly Language (PASM) instructions; this is a
+low-level language native to the Parrot virtual machine.
+
+=begin PASM
+
+ say "Here is the news for Parrots."
+ end
+
+=end PASM
+
+Now run this file with:
+
+ $ B<parrot news.pasm>
+
+which will print:
+
+ Here is the news for Parrots.
+
+=head2 Running a Language on Parrot
+
+Next, try out one of Parrot's high-level languages. Create a test file
+called F<more_news.nqp>:
+
+ say "No parrots were involved in an accident on the M1 today..."
+
+Then run it as:
+
+ $ nqp more_news.nqp
+
+which will print:
+
+ No parrots were involved in an accident on the M1 today...
+
+=head2 What Next?
+
+This book describes Parrot in terms of tasks it supports. You may pick and
+choose chapters based on your area of interest:
+
+=over 4
+
+=item Chapter 3, I<Parrot Intermediate Representation>
+
+Parrot Intermediate Representation (PIR) is a mid-level language native to the
+Parrot virtual machine s commonly used for writing extensions and tools for
+Parrot.
+
+=item Chapter 4, I<Compiler Tools>
+
+The Parrot Compiler Toolkit (PCT) provides a common infrastructure and
+utilities for implementing languages on Parrot.
+
+=item Chapter 5, I<Grammar Engine>
+
+The Parrot Grammar Engine (PGE) is a powerful regular expression engine and
+recursive descent parser. PGE is part of the compiler tools; understanding PGE
+is essential to implementing a language on Parrot.
+
+=item Chapter 6, I<Grammar Actions>
+
+NQP (Not Quite Perl) is a lightweight language loosely inspired by Perl 6. NQP
+is part of the compiler tools used for transforming a Parrot-hosted language
+into instructions for Parrot to execute.
+
+=item Chapter 7, I<Dynamic PMCs>
+
+=for author
+
+This chapter suggests the need for a chapter on core PMCs. Alternately, this
+chapter could cover PMCs in general and dynpmcs as a special case of PMCs.
+
+=end for
+
+Parrot allows language developers to extend Parrot's core data types to suit
+the needs of advanced languages.
+
+=item Chapter 8, I<Dynamic Opcodes>
+
+=for author
+
+The same point applies for ops and dynops.
+
+=end for
+
+Parrot allows language developers to extend Parrot's core instruction set --
+again to suit the needs of advanced languages.
+
+=item Chapter 10, I<Instruction Reference>
+
+Parrot's standard instruction set provides powerful behavior for primitive
+operations, control flow, object orientation, exception handling, and more.
+
+=item Chapter 11, I<Directive Reference>
+
+Parrot supports directives used within PIR and PASM code to change the behavior
+of code and to control what happens in bytecode.
+
+=item Chapter 13, I<Operator Reference>
+
+PIR provides several higher-level operators as a convenience to programmers and
+code generators.
+
+=item Appendix A, I<Glossary>
+
+Parrot and its environment have common jargon.
+
+=item Appendix B, I<Command-Line Options>
+
+Parrot supports several flags to control execution modes, debugging, library
+loading, and more.
+
+=item Appendix C, I<Build Options>
+
+Parrot's configuration process gives administrators and developers tremendous
+control over the build system.
+
+=item Appendix D, I<Source Code>
+
+Parrot's source code is organized along logical lines -- logical, once you know
+the layout.
+
+=item Appendix E, I<Patch Submission>
+
+Parrot depends on the combined efforts of numerous volunteers. Your
+contributions are very welcome.
+
+=back
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch03_pir.pod (from r39796, trunk/docs/book/draft/ch03_pir.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch03_pir.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch03_pir.pod)
@@ -0,0 +1,2412 @@
+=pod
+
+=head1 Parrot Intermediate Representation
+
+Z<CHP-3>
+
+X<Parrot Intermediate Representation;;(see PIR)>
+X<PIR (Parrot intermediate representation)>
+
+Parrot Intermediate Representation (PIR) is Parrot's native low-level
+language.N<Parrot has a pure native assembly language called PASM, described in
+Chapter 9.> PIR is fundamentally an assembly language, but it has some
+higher-level features such as operator syntax, syntactic sugar for subroutine
+and method calls, automatic register allocation, and more friendly conditional
+syntax. PIR is commonly used to write Parrot libraries -- including some of
+PCT's compilers -- and is the target form when compiling high-level languages
+to Parrot.
+
+Even so, PIR is more rigid and "close to the machine" then some higher-level
+languages like C. X<.pir files> Files containing PIR code use the F<.pir>
+extension.
+
+=head2 Basics
+
+PIR has a relatively simple syntax. Every line is a comment, a label, a
+statement, or a directive. Each statement or directive stands on its own line.
+There is no end-of-line symbol (such as a semicolon in other languages).
+
+=head3 Comments
+
+X<PIR comments>
+A comment begins with the C<#> symbol, and continues until the end of the line.
+Comments can stand alone on a line or follow a statement or directive.
+
+ # This is a regular comment. The PIR
+ # interpreter ignores this.
+
+X<PIR POD>
+PIR also treats inline documentation in Pod format as a comment. An
+equals sign as the first character of a line marks the start of a Pod
+block. A C<=cut> marker signals the end of a Pod block.
+
+ =head2
+
+ This is Pod documentation, and is treated like a
+ comment. The PIR interpreter ignores this.
+
+ =cut
+
+=head2 Labels
+
+Z<CHP-3-SECT-4>
+
+X<PIR (Parrot intermediate representation);labels> X<labels (PIR)> A label
+attaches to a line of code so other statements can refer to it. Labels can
+contain letters, numbers, and underscores. By convention, labels use all
+capital letters to stand out from the rest of the source code. A label can be
+precede a line of code, though outdenting labels on separate lines improves
+readability:
+
+ GREET:
+ say "'Allo, 'allo, 'allo."
+
+Labels are vital to control flow.
+
+=head3 Statements
+
+Z<CHP-3-SECT-1>
+
+X<statements (PIR)>
+X<PIR (Parrot intermediate representation);statements>
+A statement is either an opcode or syntactic sugar for one or more opcodes. An
+opcode is a native instruction for the virtual machine; it consists of the name
+of the instruction followed by zero or more arguments.
+
+ say "Norwegian Blue"
+
+PIR also provides higher-level constructs, including symbol operators:
+
+ $I1 = 2 + 5
+
+Under the hood, these special statement forms are just syntactic sugar for
+regular opcodes. The C<+> symbol corresponds to the C<add> opcode, the C<->
+symbol to the C<sub> opcode, and so on. The previous example is equivalent to:
+
+ add $I1, 2, 5
+
+=head3 Directives
+
+Directives begin with a period (C<.>); Parrot's parser handles them specially.
+Some directives specify actions that occur at compile time. Other directives
+represent complex operations that require the generation of multiple
+instructions. The C<.local> directive declares a typed register.
+
+ .local string hello
+
+PIR also has a macro facility to create user-defined directives.
+
+=head3 Literals
+
+Integers and floating point numbers are numeric literals. They can be positive
+or negative.
+
+ $I0 = 42 # positive
+ $I1 = -1 # negative
+
+Integer literals can also be binary, octal, or hexadecimal:
+
+ $I3 = 0b01010 # binary
+ $I3 = 0o78 # octal
+ $I2 = 0xA5 # hexadecimal
+
+Floating point number literals have a decimal point, and can use scientific
+notation:
+
+ $N0 = 3.14
+ $N2 = -1.2e+4
+
+X<strings;in PIR>
+String literals are enclosed in single or double-quotes.N<L<Strings>
+explains the differences between the quoting types.>
+
+ $S0 = "This is a valid literal string"
+ $S1 = 'This is also a valid literal string'
+
+=head3 Variables
+
+PIR variables can store four different kinds of valuesE<mdash>integers, numbers
+(floating point), strings, and objects. The simplest way to work with these
+values is through register variables. Register variables always start with a
+dollar sign (C<$>) and a single character which specifies the type of the
+register: integer (C<I>), number (C<N>), string (C<S>), or PMC (C<P>).
+Registers have numbers as well; the "first" string register is
+C<$S0>.N<Register numbers may or may not correspond to the register used
+internally; Parrot's compiler remaps registers as appropriate.>
+
+ $S0 = "Who's a pretty boy, then?"
+ say $S0
+
+PIR also has named variables, which are declared with the C<.local> directive.
+As with registers, there are four valid types for named variables: C<int>,
+C<num>, C<string>, and C<pmc>.N<Again, for "I<P>olyI<M>orphic I<C>ontainer".>
+After declaring a named variable, you can use the name anywhere you would use a
+register:
+
+ .local string hello
+ set hello, "'Allo, 'allo, 'allo."
+ say hello
+
+Integer (C<I>) and Number (C<N>) registers use platform-dependent sizes and
+limitations.N<There are a few exceptions to this; Parrot smooths out some of the
+bumps and inconsistencies so that PIR code behaves the same way on all
+supported platforms.> Internally, Parrot treats both I and N registers as
+signed quantities internally for the purposes of arithmetic. Parrot's floating
+point values and operations all comply with the IEEE 754 standard.
+
+Strings (S) are buffers of variable-sized data. The most common use of S
+registers and variables is to store textual data. S registers I<may> also be
+buffers for binary or other non-textual data, though this is rare.N<In general,
+a custom PMC is mroe useful.> Parrot strings are flexible and powerful, to
+account for all the complexity of human-readable (and computer-representable)
+textual data.
+
+The final data type is the PMC. PMC resemble classes and objects are in
+object-oriented languages. They are the basis for complex data structures and
+object-oriented behavior in Parrot.
+
+=head2 Strings
+
+Strings in double-quotes accept all sorts of escape sequences using
+backslashes. Strings in single-quotes only allow escapes for nested quotes:
+
+ $S0 = "This string is \n on two lines"
+ $S0 = 'This is a \n one-line string with a slash in it'
+
+Parrot supports several escape sequences in double-quoted strings:
+
+ \xhh 1..2 hex digits
+ \ooo 1..3 oct digits
+ \cX Control char X
+ \x{h..h} 1..8 hex digits
+ \uhhhh 4 hex digits
+ \Uhhhhhhhh 8 hex digits
+ \a An ASCII alarm character
+ \b An ASCII backspace character
+ \t A tab
+ \n A newline
+ \v A vertical tab
+ \f
+ \r
+ \e
+ \\ A backslash
+ \" A quote
+
+If you need more flexibility in defining a string, use a X<heredoc string
+literal>. The C<E<lt>E<lt>> operator starts a heredoc. The string terminator
+immediately follows. All text until the terminator is part of the heredoc.
+The terminator must appear on its own line, must appear at the beginning of the
+line, and may not have any trailing whitespace.
+
+ $S2 = << "End_Token"
+
+ This is a multi-line string literal. Notice that
+ it doesn't use quotation marks.
+
+ End_Token
+
+=head3 Strings: Encodings and Charsets
+
+X<charset>
+Strings are complicated; string declarations aren't the whole story. In olden
+times, strings only needed to support the ASCII character set (or charset), a
+mapping of 128 bit patterns to symbols and English-language characters. This
+worked as long as everyone using a computer read and wrote English and used a
+small handful of punctuation symbols.
+
+In other words, it was woefully insufficient for international uses, polyglots, and more.
+
+A modern string system must manage several character encodings and charsets in
+order to make sense out of all the string data in the world. Parrot does this.
+Every string has an associated encoding and an associated character set. The
+default charset is 8-bit ASCII, which is simple to use and is almost
+universally supported.
+
+Double-quoted string constants can have an optional prefix specifying the the
+string's encoding and charset.N<As you might suspect, single-quoted strings do
+not support this.> Parrot will maintain these values internally, and will
+automatically convert strings when necessary to preserve the information.
+String prefixes are specified as C<encoding:charset:> at the front of the
+string. Here are some examples:
+
+ $S0 = utf8:unicode:"Hello UTF8 Unicode World!"
+ $S1 = utf16:unicode:"Hello UTF16 Unicode World!"
+ $S2 = ascii:"This is 8-bit ASCII"
+ $S3 = binary:"This is raw, unformatted binary data"
+
+The C<binary:> charset treats the string as a buffer of raw unformatted binary
+data. It isn't really a string per se, because binary data contains no readable
+characters. As mentioned earlier, this exists to support libraries which
+manipulate binary data that doesn't easily fit into any other primitive data
+type.
+
+When Parrot combines two strings (such as through concatenation), they must
+both use the same character set and encoding. Parrot will automatically
+upgrade one or both of the strings to use the next highest compatible format as
+necessary. ASCII strings will automatically upgrade to UTF-8 strings if needed,
+and UTF-8 will upgrade to UTF-16. All of these conversions happen inside
+Parrot; you the programmer don't need to worry about the details.
+
+=head2 Named Variables
+
+Z<CHP-3-SECT-2.3>
+
+X<named variables (PIR)>
+X<PIR (Parrot intermediate representation);named variables>
+
+=for author
+
+The declaration section earlier alludes to this.
+
+=end for
+
+Calling a value "$S0" isn't very descriptive, and usually it's a lot
+nicer to be able to refer to values using a helpful name. For this
+reason Parrot allows registers to be given temporary variable names to
+use instead. These named variables can be used anywhere a register
+would be used normally.N<...because they actually are registers, but
+with fancier names.> They're declared with the C<.local> statement
+which requires a variable type and a name:
+
+ .local string hello
+ set hello, "Hello, Polly."
+ say hello
+
+This snippet defines a string variable named C<hello>, assigns it the value
+"Hello, Polly.", and then prints the value. Under the hood these named
+variables are just normal registers of course, so any operation that a register
+can be used for a named variable can be used for as well.
+
+X<types;variable (PIR)>
+X<variables;types (PIR)>
+The valid types are C<int>, C<num>, C<string>, and C<pmc>
+It should come as no surprise that these are the same as Parrot's four
+built-in register types. Named variables are valid from the point of
+their definition to the end of the current subroutine.
+
+The name of a variable must be a valid PIR identifier. It can contain letters,
+digits and underscores but the first character has to be a letter or an
+underscore. There is no limit to the length of an identifier, other than good
+taste.
+
+As mentioned earlier, Parrot's internal compiler may remap named registers and
+symbolic registers to actual registers as necessary. This happens
+transparently, and for the most part you never need to know about it. There's
+one exception: when you know something outside of Parrot must refer to a
+specific register exactly.N<For example, when an NCI call takes a pointer to a
+register and returns a value through the pointer.> Use the C<:unique_reg>
+modifier on a variable declaration to prevent potential register allocation
+changes:
+
+ .local pmc MyUniquePMC :unique_reg
+
+This attribute C<:unique_reg> will not affect the behavior of Parrot otherwise.
+
+=head2 PMC variables
+
+Z<CHP-3-SECT-2.4>
+
+PMC registers and variables act much like any integer, floating-point
+number, or string register or variable, but you have to instantiate a
+new PMC object into a type before you use it. The C<new> instruction creates
+a new PMC of the specified type:
+
+ $P0 = new 'String'
+ $P0 = "Hello, Polly."
+ say $P0
+
+This example creates a C<String> object, stores it in the PMC register C<$P0>,
+assigns it the value "Hello, Polly.", and prints it. The type provided to the
+C<.local> directive is either the generic C<pmc> or a type compatible with the
+type passed to C<new>:
+
+ .local String hello # or .local pmc hello
+ hello = new 'String'
+ hello = "Hello, Polly."
+ say hello
+
+PIR is a dynamic language; that dynamicism is evident in how Parrot handles PMC
+values. Primitive registers like strings, numbers, and integers perform a
+special action called X<autoboxing> when assigned to a PMC. Autoboxing is the
+process of converting a primitive type to a PMC object. PMC classes exist for
+String, Number, and Integer; notice that the primitive types are in lower-case,
+while the PMC classes are capitalized. If you want to box a value explicitly,
+use the C<box> opcode:
+
+ $P0 = new 'Integer' # The boxed form of int
+ $P0 = box 42
+ $P1 = new 'Number' # The boxed form of num
+ $P1 = box 3.14
+ $P2 = new 'String' # The boxed form of string
+ $P2 = "This is a string!"
+
+The PMC classes C<Integer>, C<Number>, and C<String> are thin overlays on the
+primitive types they represent. These PMC types have the benefit of the
+X<PMC;VTABLE Interface> VTABLE interface. VTABLEs are a standard API that all
+PMCs conform to for performing standard operations. These PMC types support
+custom methods to perform various operations, may be passed to subroutines that
+expect PMC arguments, and can be subclassed by a user-defined type.
+
+=head2 Named Constants
+
+Z<CHP-3-SECT-2.5>
+
+X<PIR (Parrot intermediate representation);named constants>
+X<named constants (PIR)>
+
+The C<.const> directive declares a named constant. It resembles C<.local>; it
+requires a type and a name. It also requires the assignment of a constant
+value. As with named variables, named constants are visibl only within the
+compilation unit where they're declared. This example declares a named string
+constant C<hello> and prints the value:
+
+ .const string hello = "Hello, Polly."
+ say hello
+
+Named constants may be used in all the same places as literal constants,
+but have to be declared beforehand:
+
+ .const int the_answer = 42 # integer constant
+ .const string mouse = "Mouse" # string constant
+ .const num pi = 3.14159 # floating point constant
+
+In addition to normal local constants, you can also specify a global constant
+which is accessible from everywhere in the current code file:
+
+ .globalconst int days = 365
+
+Currently there is no way to specify a PMC constant in PIR source code.
+
+=for author
+
+Why declare constants?
+
+=end for
+
+=head2 Symbol Operators
+
+Z<CHP-3-SECT-3>
+
+X<symbol operators in PIR>
+
+=for author
+
+An earlier section described this already too.
+
+=end for
+
+PIR has many other symbolic operators: arithmetic, concatenation, comparison,
+bitwise, and logical. All PIR operators are translated into one or more Parrot
+opcodes internally, but the details of this translation stay safely hidden from
+the programmer. Consider this example snippet:
+
+ .local int sum
+ sum = $I42 + 5
+ say sum
+
+The statement C<sum = $I42 + 5> translates to the equivalent statement C<add
+sum, $I42, 5>. PIR symbolic operations are:
+
+ $I0 = $I1 + 5 # Addition
+ $N0 = $N1 - 7 # Subtraction
+ $I3 = 4 * 6 # Multiplication
+ $N7 = 3.14 / $N2 # Division
+ $S0 = $S1 . $S2 # String concatenation
+
+PIR also provides automatic assignment operators such as C<+=>, C<-=>,
+and C<<< >>= >>>. These operators help programmers to perform common
+manipulations on a data value in place, and save a few keystrokes while
+doing them.
+
+A complete list of PIR operators is available in Chapter 13.
+
+=head2 C<=> and Type Conversion
+
+The C<=> operator is very powerful. Its simplest form stores a value into one
+of the Parrot registers. It can assign a string value to a C<string> register,
+an integer value to an C<int> register, a floating point value into a C<number>
+register, etc. However, the C<=> operator can assign I<any> type of value into
+I<any> type of register; Parrot will handle the conversion for you
+automatically:
+
+ $I0 = 5 # Integer. 5
+ $S0 = $I0 # Stringify. "5"
+ $N0 = $S0 # Numify. 5.0
+ $I0 = $N0 # Intify. 5
+
+Notice that conversions between the numeric formats and strings only makes
+sense when the value to convert is a number.
+
+ $S0 = "parrot"
+ $I0 = $S0 # 0
+
+An earlier example showed a string literal assigned to a PMC register of type
+C<String>. This works for all the primitive types and their autoboxed PMC
+equivalents:
+
+ $P0 = new 'Integer'
+ $P0 = 5
+ $S0 = $P0 # Stringify. "5"
+ $N0 = $P0 # Numify. 5.0
+ $I0 = $P0 # Unbox. $I0 = 5
+
+ $P1 = new 'String'
+ $P1 = "5 birds"
+ $S1 = $P1 # Unbox. $S1 = "5 birds"
+ $I1 = $P1 # Intify. 5
+ $N1 = $P1 # Numify. 5.0
+
+ $P2 = new 'Number'
+ $P2 = 3.14
+ $S2 = $P2 # Stringify. "3.14"
+ $I2 = $P2 # Intify. 3
+ $N2 = $P2 # Unbox. $N2 = 3.14
+
+=head2 Compilation Units
+
+Z<CHP-3-SECT-4.1>
+
+X<PIR (Parrot intermediate representation);subroutine> X<subroutine (PIR)>
+Subroutines in PIR are roughly equivalent to the subroutines or methods of a
+high-level language. All code in a PIR source file must appear within a
+subroutine. The simplest syntax for a PIR subroutine starts with the C<.sub>
+directive and ends with the C<.end> directive:
+
+=begin PIR
+
+ .sub 'main'
+ say "Hello, Polly."
+ .end
+
+=end PIR
+
+This example defines a subroutine named C<main> that prints a string C<"Hello,
+Polly.">. Parrot will normally execute the first subroutine it encounters in
+the first file it runs, but you can flag any subroutine as the first one to
+execute with the C<:main> marker:
+
+=begin PIR
+
+ .sub 'first'
+ say "Polly want a cracker?"
+ .end
+
+ .sub 'second' :main
+ say "Hello, Polly."
+ .end
+
+=end PIR
+
+This code prints out "Hello, Polly." but not "Polly want a cracker?". Though
+the C<first> function appears first in the source code, C<second> has the
+C<:main> flag and gets called. C<first> is never called. Revising that
+program produces different results:
+
+=begin PIR
+
+ .sub 'first' :main
+ say "Polly want a cracker?"
+ .end
+
+ .sub 'second'
+ say "Hello, Polly."
+ .end
+
+=end PIR
+
+The output now is "Polly want a cracker?". Execution in PIR starts at the
+C<:main> function and continues until that function ends. To perform other
+operations, you must call other functions explicitly. Chapter 4 describes
+subroutines and their uses.
+
+=head2 Flow Control
+
+Z<CHP-3-SECT-5>
+
+X<PIR (Parrot intermediate representation);flow control>
+X<flow control;in PIR>
+
+Flow control in PIR occurs entirely with conditional and unconditional branches
+to labels. This may seem simplistic and primitive, but here PIR shows its roots
+as a thin overlay on the assembly language of a virtual processor. PIR does
+not support high-level looping structures such as C<while> or C<for> loops. PIR
+has some support for basic C<if> branching constructs, but does not support
+more complicated C<if>/C<then>/C<else> branch structures.
+
+The control structures of high-level languages hew tightly to the semantics of
+those languages; Parrot provides the minimal feature set necessary to implement
+any semantic of an HLL without dictating how that HLL may implement its
+features. Language agnosticism is an important design goal in Parrot, and
+creates a very flexible and powerful development environment for language
+developers.
+
+X<goto instruction (PIR)>
+The most basic branching instruction is the unconditional branch, C<goto>:
+
+=begin PIR
+
+ .sub 'main'
+ goto L1
+ say "never printed"
+
+ L1:
+ say "after branch"
+ end
+ .end
+
+=end PIR
+
+The first C<say> statement never runs because the C<goto> always skips over it
+to the label C<L1>.
+
+The conditional branches combine C<if> or C<unless> with C<goto>.
+
+=begin PIR
+
+ .sub 'main'
+ $I0 = 42
+ if $I0 goto L1
+ say "never printed"
+ L1:
+ say "after branch"
+ end
+ .end
+
+=end PIR
+
+X<if (conditional);instruction (PIR)> X<unless (conditional);instruction (PIR)>
+In this example, the C<goto> branches to the label C<L1> only if the value
+stored in C<$I0> is true. The C<unless> statement is similar, but it branches
+when the tested value is false. You can use PMC and STRING registers with
+C<if> and C<unless>. The op will call the C<get_bool> vtable entry on any PMC
+so used and will convert the STRING to a boolean value. An undefined value, 0,
+or an empty string are all false values. All other values are true.
+
+The comparison operators (C<E<lt>>, C<E<lt>=>, C<==>, C<!=>, C<E<gt>>,
+C<E<gt>=>) can combine with C<if ... goto>. These branch when the
+comparison is true:
+
+=begin PIR
+
+ .sub 'main'
+ $I0 = 42
+ $I1 = 43
+ if $I0 < $I1 goto L1
+ say "never printed"
+ L1:
+ say "after branch"
+ end
+ .end
+
+=end PIR
+
+This example compares C<$I0> to C<$I1> and branches to the label C<L1> if
+C<$I0> is less than C<$I1>. The C<if $I0 E<lt> $I1 goto L1> statement
+translates directly to the C<lt> branch operation.
+
+Chapter 11's "PIR Instructions" section summarizes the other comparison
+operators.
+
+X<loops;PIR>
+X<PIR (Parrot intermediate representation);loop constructs>
+PIR has no special loop constructs. A combination of conditional and
+unconditional branches handle iteration:
+
+=begin PIR
+
+ .sub 'main'
+ $I0 = 1 # product
+ $I1 = 5 # counter
+
+ REDO: # start of loop
+ $I0 = $I0 * $I1
+ dec $I1
+ if $I1 > 0 goto REDO # end of loop
+
+ say $I0
+ end
+ .end
+
+=end PIR
+
+X<do-while style loop;(PIR)>
+This example calculates the factorial C<5!>. Each time through the loop it
+multiplies C<$I0> by the current value of the counter C<$I1>, decrements the
+counter, and branches to the start of the loop. The loop ends when C<$I1>
+counts down to 0. This is a I<do while>-style loop with the condition test at
+the end so that the code always runs at least once through the loop.
+
+X<while-style loop (PIR)>
+For a I<while>-style loop with the condition test at the start, use a
+conditional branch with an unconditional branch:
+
+=begin PIR
+
+ .sub 'main'
+ $I0 = 1 # product
+ $I1 = 5 # counter
+
+ REDO: # start of loop
+ if $I1 <= 0 goto LAST
+ $I0 = $I0 * $I1
+ dec $I1
+ goto REDO
+ LAST: # end of loop
+
+ say $I0
+ end
+ .end
+
+=end PIR
+
+This example tests the counter C<$I1> at the start of the loop. At the end of
+the loop, it unconditionally branches back to the start of the loop and tests
+the condition again. The loop ends when the counter C<$I1> reaches 0 and the
+C<if> branches to the C<LAST> label. If the counter isn't a positive number
+before the loop, the loop will never execute.
+
+You can build any high-level flow control construct from conditional and
+unconditional branches; the lowest level of computer hardware works this way.
+All modern programming languages use branching constructs to implement their
+most complex flow control devices.
+
+That doesn't make complex code easier to write in PIR. Fortunately, a series
+of macros exist to simplify flow control.
+
+=head2 Macros
+
+=for author
+
+Needs supplementing; needs moving.
+
+=end for
+
+=head2 Subroutines
+
+Z<CHP-4>
+
+X<PIR (Parrot intermediate representation);subroutines>
+X<subroutines;in PIR>
+The most basic building block of code reuse in PIR is the subroutine. A large
+program may perform a calculation like "the factorial of a number" several
+times. Subroutines abstract this behavior into a single, named, stand-alone
+unit. PIR is a subroutine-based language in that all code in PIR must exist in
+a subroutine. Execution starts in the C<:main> subroutine, which itself can
+call other subroutines. Subroutines can fit together into more elaborate
+chunks of code reusability such as methods and objects.
+
+Parrot supports multiple high-level languages. Each language uses a different
+syntax for defining and calling subroutines. The goal of PIR is not to be a
+high-level language in itself, but to provide the basic tools that other
+languages can use to implement them. PIR's subroutine syntax may seem very
+primitive for this reason.
+
+=head2 Parrot Calling Conventions
+
+Z<CHP-4-SECT-1>
+
+X<PIR (Parrot intermediate representation);subroutines;Parrot calling conventions>
+X<subroutines;Parrot calling conventions;in PIR>
+
+The way that Parrot calls a subroutine -- passing arguments, altering control
+flow, and returning results -- is the "Parrot Calling Conventions" (PCC).
+Parrot generally hides the details of PCC from the programmer. PIR has several
+constructs to gloss over these details, and the average programmer will not
+need to worry about them. PCC uses the Continuation Passing Style
+X<Continuation Passing Style (CPS)>X<CPS (Continuation Passing Style)> (CPS) to
+pass control to subroutines and back again. Again, the details are irrelevant
+for most uses, but the power is available to anyone who wants to take advantage
+of it.
+
+=head3 Subroutine Calls
+
+X<PIR (Parrot intermediate representation);subroutine calls>
+PIR's simplest subroutine call syntax looks much like a subroutine
+call from a high-level language. This example calls the subroutine
+C<fact> with two arguments and assigns the result to C<$I0>:
+
+ $I0 = 'fact'(count, product)
+
+This simple statement hides much complexity. It generates a subroutine PMC
+object, creates a continuation PMC object to represent the control flow up to
+this point, passes the arguments, looks up the subroutine by name (and by
+signature, if necessary)), calls the subroutine, and assigns the results of the
+call to the appropriate integer register. This is all in addition to the
+computation the subroutine itself performs.
+
+=head3 Expanded Subroutine Syntax
+
+The single line subroutine call is incredibly convenient, but it isn't always
+flexible enough. PIR also has a more verbose call syntax that is still more
+convenient than manual calls. This example looks up the subroutine C<fact> out
+in the global symbol table and calls it:
+
+ find_global $P1, "fact"
+
+ .begin_call
+ .arg count
+ .arg product
+ .call $P1
+ .result $I0
+ .end_call
+
+X<.arg directive>
+X<.result directive>
+The whole chunk of code from C<.begin_call> to C<.end_call> acts as a single
+unit. The C<.arg> directive sets up and passes arguments to the call. The
+C<.call> directive calls the subroutine and identifies the point at which to
+return control flow after the subroutine has completed. The C<.result>
+directive retrieves returned values from the call.
+
+=head3 Subroutine Declarations
+
+X<.param directive> In addition to syntax for subroutine calls, PIR provides
+syntax for subroutine definitions: the C<.sub> and C<.end> directives shown in
+earlier examples. The C<.param> directive defines input parameters and creates
+local named variables for them (similar to C<.local>):
+
+ .param int c
+
+X<.return directive>
+The C<.return> directive allows the subroutine to return control flow
+to the calling subroutine, and optionally returns result output values.
+
+Here's a complete code example that implements the factorial algorithm. The
+subroutine C<fact> is a separate subroutine, assembled and processed after the
+C<main> function. Parrot resolves global symbols like the C<fact> label
+between different units.
+
+=begin PIR
+
+ # factorial.pir
+ .sub 'main' :main
+ .local int count
+ .local int product
+ count = 5
+ product = 1
+
+ $I0 = 'fact'(count, product)
+
+ say $I0
+ end
+ .end
+
+ .sub 'fact'
+ .param int c
+ .param int p
+
+ loop:
+ if c <= 1 goto fin
+ p = c * p
+ dec c
+ branch loop
+ fin:
+ .return (p)
+ .end
+
+=end PIR
+
+This example defines two local named variables, C<count> and C<product>, and
+assigns them the values 1 and 5. It calls the C<fact> subroutine with both
+variables as arguments. The C<fact> subroutine uses C<.param> to retrieve
+these parameters and C<.return> to return the result. The final printed result
+is 120.
+
+As usual, execution of the program starts at the C<:main> subroutine.
+
+=head3 Named Arguments
+
+=for author
+
+We have to get our terms straight here. Which are "arguments" (passed in) and
+which are "parameters" (processed from within)?
+
+=end for
+
+X<positional arguments>
+X<named arguments>
+Parameters passed only by their order are I<positional arguments>. The only
+differentiator between positional arguments is their positions in the function
+call. Putting positional arguments in a different order will produce different
+effects, or may cause errors. Parrot also supports I<named parameters>. Instead
+of passing parameters by their position in the string, parameters are passed by
+name and can be in any order. Here's an example:
+
+=begin PIR
+
+ .sub 'MySub'
+ .param string yrs :named("age")
+ .param string call :named("name")
+ $S0 = "Hello " . call
+ $S1 = "You are " . yrs
+ $S1 .= " years old"
+ say $S0
+ say $S1
+ .end
+
+ .sub 'main' :main
+ 'MySub'("age" => 42, "name" => "Bob")
+ .end
+
+=end PIR
+
+Named arguments are convenient because the order of the pairs does not matter.
+You can also pass these pairs in the opposite order:
+
+=begin PIR
+
+ .sub 'main' :main
+ 'MySub'("name" => "Bob", "age" => 42) # Same!
+ .end
+
+=end PIR
+
+=head3 Optional Arguments
+
+X<optional arguments>
+Some functions have arguments with appropriate default values so that callers
+don't always have to pass them. Parrot provides a mechanism to identify
+optional arguments as well as flag values to determine if the
+caller has passed optional arguments.
+
+Optional parameters appear in PIR as if they're actually I<two> parameters:
+the value and a flag:
+
+ .param string name :optional
+ .param int has_name :opt_flag
+
+The C<:optional> flag specifies that the given parameter is optional. The
+C<:opt_flag> specifies an integer which parameter contains a boolean flag; this
+flag is true if the value was passed, and false otherwise. To provide a default
+value for an optional parameter, you can write:
+
+ .param string name :optional
+ .param int has_name :opt_flag
+
+ if has_name goto we_have_a_name
+ name = "Default value"
+ we_have_a_name:
+
+Optional parameters can be positional or named parameters. Optional positional
+parameters must appear at the end of the list of positional parameters. Also,
+the C<:opt_flag> parameter must always appear directly after the C<:optional>
+parameter.
+
+ .sub 'Foo'
+ .param int optvalue :optional
+ .param int hasvalue :opt_flag
+ .param pmc notoptional # WRONG!
+ ...
+
+ .sub 'Bar'
+ .param int hasvalue :opt_flag
+ .param int optvalue :optional # WRONG!
+ ...
+
+ .sub 'Baz'
+ .param int optvalue :optional
+ .param pmc notoptional
+ .param int hasvalue :opt_flag # WRONG!
+ ...
+
+You may mix optional parameters with named parameters:
+
+ .sub 'MySub'
+ .param int value :named("answer") :optional
+ .param int has_value :opt_flag
+ ...
+
+You can call this function in two ways:
+
+ 'MySub'("answer" => 42) # with a value
+ 'MySub'() # without
+
+=head3 Sub PMCs
+
+Subroutines are a PMC type in Parrot. You can store them in PMC registers and
+manipulate them just as you do the other PMC types. Look up a subroutine in
+the current namespace with the C<get_global> opcode:
+
+ $P0 = get_global "MySubName"
+
+To find a subroutine in a different namespace, first look up the appropriate
+the namespace PMC, then use that with C<get_global>:
+
+ $P0 = get_namespace "MyNameSpace"
+ $P1 = get_global $P0, "MySubName"
+
+You can obviously invoke a Sub PMC:
+
+ $P0(1, 2, 3)
+
+You can get or even I<change> its name:
+
+ $S0 = $P0 # Get the current name
+ $P0 = "MyNewSubName" # Set a new name
+
+You can get a hash of the complete metadata for the subroutine:
+
+ $P1 = inspect $P0
+
+The metadata fields in this hash are
+
+=over 4
+
+=item * pos_required
+
+The number of required positional parameters to the Sub
+
+=item * pos_optional
+
+The number of optional positional parameters to the Sub
+
+=item * named_required
+
+The number of required named parameters to the Sub
+
+=item * named_optional
+
+The number of optional named parameters to the Sub
+
+=item * pos_slurpy
+
+Returns true if the sub has a slurpy parameter to eat up extra positional args
+
+=item * named_slurpy
+
+Returns true if the sub has a slurpy parameter to eat up extra named args
+
+=back
+
+Instead of getting the whole inspection hash, you ask about individual pieces
+of metadata:
+
+ $I0 = inspect $P0, "pos_required"
+
+To discover to get the total number of defined parameters to the Sub, call the
+C<arity> method:
+
+ $I0 = $P0.'arity'()
+
+To fetch the namespace PMC that the Sub was defined into, call the
+C<get_namespace> method:
+
+ $P1 = $P0.'get_namespace'()
+
+=head2 The Commandline
+
+Programs written in Parrot have access to arguments passed on the command
+line like any other program would:
+
+ .sub 'MyMain' :main
+ .param pmc all_args :slurpy
+ ...
+ .end
+
+=for author
+
+Please verify and expand.
+
+=end for
+
+The C<all_args> PMC is a ResizableStringArray PMC, which means you can loop
+over the results, access them individually, or even modify them.
+
+=head2 Continuation Passing Style
+
+X<continuations>
+X<continuation passing style>
+X<CPS>
+Continuations are snapshots of control flow: frozen images of the current
+execution state of the VM. Once you have a continuation, you can invoke it to
+return to the point where the continuation was first created. It's like a
+magical timewarp that allows the developer to arbitrarily move control flow
+back to any previous point in the program.
+
+Continuations are not a new concept; they've boggled the minds of new Lisp and
+Scheme programmers for many years. Despite their power and heritage, they're
+not visible to most other modern programming languages or their runtimes.
+Parrot aims to change that: it performs almost all control flow through the use
+of continuations. PIR and PCT hide most of this complexity from developers,
+but the full power of continuations is available.
+
+When Parrot invokes a function, it creates a continuation representing the
+current point in the program. It passes this continuation as an invisible
+parameter to the function call. When that function returns, it invokes the
+continuation -- in effect, it performs a goto to the point of creation of that
+continuation. If you have a continuation, you can invoke it to return to its
+point of creation any time you want.
+
+This type of flow control -- invoking continuations instead of performing bare
+jumps -- is X<Continuation Passing Style;CPS> Continuation Passing Style (CPS).
+CPS allows parrot to offer all sorts of neat features, such as tail-call
+optimizations and lexical subroutines.
+
+=head3 Tailcalls
+
+A subroutine may set up and call another subroutine, then return the result of
+the second call directly. This is a X<tailcall> tailcall, and is an important
+opportunity for optimization. Here's a contrived example in pseudocode:
+
+ call add_two(5)
+
+ subroutine add_two(value)
+ value = add_one(value)
+ return add_one(value)
+
+In this example, the subroutine C<add_two> makes two calls to c<add_one>. The
+second call to C<add_one> is the return value. C<add_one> gets called; its
+result gets returned to the caller of C<add_two>. Nothing in C<add_two> uses
+that return value directly.
+
+A simple optimization is available for this type of code. The second call to
+C<add_one> will return to the same place that C<add_two> returns; it's
+perfectly safe and correct to use the same return continuation that C<add_two>
+uses. The two subroutine calls can share a return continuation, instead of
+having to create a new continuation for each call.
+
+X<.tailcall directive>
+
+PIR provides the C<.tailcall> directive to identify similar situations. Use it
+in place of the C<.return> directive. C<.tailcall> performs this optimization
+by reusing the return continuation of the parent function to make the tailcall:
+
+=begin PIR
+
+ .sub 'main' :main
+ .local int value
+ value = add_two(5)
+ say value
+ .end
+
+ .sub 'add_two'
+ .param int value
+ .local int val2
+ val2 = add_one(value)
+ .tailcall add_one(val2)
+ .end
+
+ .sub 'add_one'
+ .param int a
+ .local int b
+ b = a + 1
+ .return (b)
+ .end
+
+=end PIR
+
+This example above print the correct value "7".
+
+=head3 Creating and Using Continuations
+
+While Parrot's use of continuations and CPS is invisible to most code, you can
+create and use them explicitly if you like. Continuations are like any other
+PMC. Create one with the C<new> opcode:
+
+ $P0 = new 'Continuation'
+
+The new continuation starts off in an undefined state. If you attempt to invoke
+a new continuation without initializing it, Parrot will raise an exception. To
+prepare the continuation for use, assign it a destination label with the
+C<set_addr> opcode:
+
+ $P0 = new 'Continuation'
+ set_addr $P0, my_label
+
+ my_label:
+ ...
+
+To jump to the continuation's stored label and return the context to the state
+it was in I<at the point of its creation>, invoke the continuation:
+
+ invoke $P0 # Explicit using "invoke" opcode
+ $P0() # Same, but nicer syntax
+
+Even though you can use the subroutine notation C<$P0()> to invoke the
+continuation, it doesn't make any sense to pass arguments or obtain return
+values:
+
+ $P0 = new 'Continuation'
+ set_addr $P0, my_label
+
+ $P0(1, 2) # WRONG!
+
+ $P1 = $P0() # WRONG!
+
+=head2 Lexical Subroutines
+
+X<Lexical Subroutines>
+
+Parrot offers support for lexical subroutines. You can define a subroutine by
+name inside a larger subroutine, where the inner subroutine is only visible and
+callable from the outer. The inner subroutine inherits all the lexical
+variables from the outer subroutine, but can itself define its own lexical
+variables that the outer subroutine cannot access. PIR lacks the concept of
+blocks or nested lexical scopes; this is how it performs the same function.
+
+If a subroutine is lexical, find its C<:outer> Sub with the C<get_outer>
+method:
+
+ $P1 = $P0.'get_outer'()
+
+If there is no C<:outer> PMC, this returns a NULL PMC. Conversely, you can
+set the outer sub:
+
+ $P0.'set_outer'($P1)
+
+=head3 Scope and HLLs
+
+As mentioned previously, X<High Level Languages;HLL> High Level Languages such
+as Perl, Python, and Ruby allow nested scopes, or blocks within blocks that can
+have their own lexical variables. Even this construct is common in the C
+programming language:
+
+ {
+ int x = 0;
+ int y = 1;
+ {
+ int z = 2;
+ /* x, y, and z are all visible here */
+ }
+
+ /* only x and y are visible here */
+ }
+
+In the inner block, all three varaibles are visible. The variable C<z> is only
+visible inside that block. The outer block has no knowledge of C<z>. A very
+direct, naI<iuml>ve translation of this code to PIR might be:
+
+ .param int x
+ .param int y
+ .param int z
+ x = 0
+ y = 1
+ z = 2
+ ...
+
+This PIR code is similar, but the handling of the variable C<z> is different:
+C<z> is visible throughout the entire current subroutine, where it is not
+visible throughout the entire C function. To help approximate this effect, PIR
+supplies lexical subroutines to create nested lexical scopes.
+
+=head3 PIR Scoping
+
+Only one PIR structure supports scoping like this: the subroutine.N<... and
+objects that inherit from subroutines, such as methods, coroutines, and
+multisubs> There are no blocks in PIR that have their own scope besides
+subroutines. Fortunately, we can use these lexical subroutines to simulate this
+behavior that HLLs require:
+
+=begin PIR
+
+ .sub 'MyOuter'
+ .local int x,y
+ .lex 'x', x
+ .lex 'y', y
+ 'MyInner'()
+ # only x and y are visible here
+ .end
+
+ .sub 'MyInner' :outer('MyOuter')
+ .local int z
+ .lex 'z', z
+ # x, y, and z are all "visible" here
+ .end
+
+=end PIR
+
+=for author
+
+This paragraph is unclear.
+
+=end for
+
+This example calls the variables in C<MyInner> "visible". This is because
+lexically-defined variables need to be accessed with the C<get_lex> and
+C<set_lex> opcodes. These two opcodes don't just access the value of a
+register, where the value is stored while it's being used, but they also make
+sure to interact with the C<LexPad> PMC that's storing the data. If the value
+isn't properly stored in the LexPad, then they won't be available in nested
+inner subroutines, or available from C<:outer> subroutines either.
+
+=head3 Lexical Variables
+
+=for author
+
+What's the point of this paragraph?
+
+=end for
+
+As we have seen above, we can declare a new subroutine to be a nested inner
+subroutine of an existing outer subroutine using the C<:outer> flag. The outer
+flag is used to specify the name of the outer subroutine. Where there may be
+multiple subroutines with the same name, we can use the C<:subid> flag on the
+outer subroutine to give it a different--and unique--name that the lexical
+subroutines can reference in their C<:outer> declarations. Within lexical
+subroutines, the C<.lex> command defines a local variable that follows these
+scoping rules.
+
+=head3 LexPad and LexInfo PMCs
+
+X<LexPad PMC>
+X<LexInfo PMC>
+Subs store information about lexical variables in two different PMCs: the
+LexPad PMC and the LexInfo PMC. They're not visible to PIR code; Parrot uses
+them internally to store information about lexical variables.
+
+I<LexInfo> PMCs store read-only information about the lexical variables used in
+a Sub. Parrot creates them when it compiles a Sub. Not all subroutines get a
+LexInfo PMC by default; only those that need it. One way to identify such a
+Sub is its use of the C<.lex> directive, but this only works for languages
+which know the names of lexical variables at compile time. If that's not true
+of your language, declare the Sub with the C<:lex> attribute.
+
+I<LexPad> PMCs store run-time information about lexical variables. This
+includes their current values and their type information. Parrot creates LexPad
+PMCs for Subs that already have a LexInfo PMC. As you can imagine, Parrot must
+create a new LexPad for each I<invocation> of a Sub, lest a recursive call
+overwrite previous lexical values.
+
+Call the C<get_lexinfo> method on a Subroutine PMC to access its associated
+LexInfo PMC:
+
+ $P0 = find_global "MySubroutine"
+ $P1 = $P0.'get_lexinfo'()
+
+Once you have the LexInfo PMC, you can inspect the lexicals it represents:
+
+ $I0 = elements $P1 # the number of lexical variables it holds
+ $P0 = $P1["name"] # the entry for lexical variable "name"
+
+There's not much else you can do (though the PMC behaves like a Hash PMC, so
+you can iterate over its keys and values).
+
+There is no easy way to get a reference to the current LexPad PMC in a given
+subroutine, but they're not useful from PIR anyway. Remember that subroutines
+themselves can be lexical; the lexical environment of a given variable can
+extend to multiple subroutines with their own LexPads. The opcodes C<find_lex>
+and C<store_lex> search through nested LexPads recursively to find the proper
+environment for the given variables.
+
+=head2 Compilation Units Revisited
+
+Z<CHP-4-SECT-1.1>
+
+X<Subroutine>
+A subroutine is a section of code that forms a single unit. The factorial
+calculation example had two separate subroutines: the C<main> subroutine and
+the C<fact> subroutine. Here is that algorithm in a single subroutine:
+
+=begin PIR
+
+ .sub 'main'
+ $I1 = 5 # counter
+ bsr fact
+ say $I0
+ $I1 = 6 # counter
+ bsr fact
+ say $I0
+ end
+
+ fact:
+ $I0 = 1 # product
+ L1:
+ $I0 = $I0 * $I1
+ dec $I1
+ if $I1 > 0 goto L1
+ ret
+ .end
+
+=end PIR
+
+The unit of code from the C<fact> label definition to C<ret> is a reusable
+routine, but is only usable from within the C<main> subroutine. There are
+several problems with this simple approach. In terms of the interface, the
+caller has to know to pass the argument to C<fact> in C<$I1> and to get the
+result from C<$I0>. This differs from Parrot's well-understood calling
+conventions.
+
+Another disadvantage of this approach is that C<main> and C<fact> share the
+same subroutine. Parrot processes them as one piece of code. They share
+registers, and they'd share any LexInfo and LexPad PMCs, if any were needed by
+C<main>. The C<fact> routine is also not easily usable from outside the C<main>
+subroutine, so other parts of your code won't have access to it.
+
+=head2 NameSpaces, Methods, and VTABLES
+
+Z<CHP-4-SECT-2>
+
+X<PIR (Parrot intermediate representation);methods>
+X<methods;in PIR>
+X<classes;methods>
+X<. (dot);. (method call);instruction (PIR)>
+PIR provides syntax to simplify writing methods and method calls for
+object-oriented programming. PIR allows you to define your own classes, and
+with those classes you can define method interfaces to them. Method calls
+follow the Parrot's calling conventions, including the various parameter
+configurations, lexical scoping, and other aspects already shown.
+
+Parrot supports several built-in classes, such as C<ResizablePMCArray> and
+C<Integer>, written in C and compiled with the rest of Parrot. You may also
+declare your own classes in PIR. Like other object oriented systems, Parrot
+classes provide their own I<namespaces> and support I<methods> and
+I<attributes>.
+
+=head3 NameSpaces
+
+Z<CHP-4-SECT-2.1>
+
+X<NameSpaces>
+X<.namespace>
+NameSpaces provide a categorization mechanism to avoid name collisions. This is
+most useful when producing encapsulated libraries or when building large
+systems. Each namespace provides a separate location for function names and
+global variables.
+
+X<namespace collisions>
+X<namespace pollution>
+
+Without a namespace (or in a program that eschews namespaces), all subroutines
+and global variables would live in one big bag, running the risk of
+I<namespace collisions> thanks to I<namespace pollution>. You couldn't tell
+which subroutine performed which operation when two task contexts use the same
+word to mean two different things.
+
+NameSpaces are very effective at hiding private information as well as
+gathering similar things together.
+
+For example, the C<Math> namespace could store subroutines that manipulate
+numbers. The C<Images> namespace could store subroutines create and manipulate
+images. If your program must add two numbers together I<and> perform additive
+image composition, you can use the appropriate namespaced C<add> functions
+without conflict or confusion. Within the C<Image> namespace you could have
+also have sub namespaces for C<jpeg> and C<MRI> and C<schematics>; each of
+these could have its own C<add> subroutine without getting into each other's
+way.
+
+Declare a namespace in PIR with the C<.namespace []> directive. The brackets
+are not optional, but the keys inside them are. For example:
+
+ .namespace [ ] # The root namespace
+ .namespace [ "Foo" ] # The namespace "Foo"
+ .namespace [ "Foo" ; "Bar" ] # NameSpace Foo::Bar
+ .namespace # WRONG! The [] are needed
+
+You may nest namespaces to arbitrary depth by separating name components with
+semicolons. NameSpaces are PMC, so you can access them and manipulate them
+just like other data objects. Get the PMC for the root namespace using the
+C<get_root_namespace> opcode:
+
+ $P0 = get_root_namespace
+
+The current namespace may be different from the root namespace; retrieved it
+with the C<get_namespace> opcode:
+
+ $P0 = get_namespace # get current namespace PMC
+ $P0 = get_namespace ["Foo"] # get PMC for namespace "Foo"
+
+X<HLL namespaces>
+X<namespaces; HLL>
+Parrot arranges its namespaces in a hiarachy. The root namespace is the root
+of the tree. Beneath the root are HLL namespaces; hLL compiler gets its own
+HLL namespace where it can store its data during compilation and runtime. Each
+HLL namespace may itself be the root of a tree of namespaces.
+
+=head3 NameSpace PMC
+
+There are multiple ways to address a namespace in PIR, depending on the
+starting point of the lookup. They may start at the root namespace:
+
+ # Get namespace "a/b/c" starting at the root namespace
+ $P0 = get_root_namespace ["a" ; "b" ; "c"]
+
+... or from the current HLL's namespace as a root:
+
+ # Get namespace "a/b/c" starting in the current HLL namespace.
+ $P0 = get_hll_namespace ["a" ; "b" ; "c"]
+
+... but this is identical to a root namespace lookup with the HLL as the first
+branch:
+
+ $P0 = get_root_namespace ["hll" ; "a" ; "b" ; "c"]
+
+... and, of course, relative to the current namespace without a root:
+
+ # Get namespace "a/b/c" starting in the current namespace
+ $P0 = get_namespace ["a" ; "b" ; "c"]
+
+Given a namespace PMC, retrieve global variables and subroutine PMCs with the
+C<get_global> opcode:
+
+ $P1 = get_global $S0 # Get global in current namespace
+ $P1 = get_global ["Foo"], $S0 # Get global in namespace "Foo"
+ $P1 = get_global $P0, $S0 # Get global in $P0 namespace PMC
+
+=head3 Operations on the NameSpace PMC
+
+You can perform other operations on the NameSpace PMC. You can find methods
+and variables that are stored in the namespace or add new ones.
+
+For example, to add one namespace to another current namespace, use the
+C<add_namespace> method:
+
+ $P0 = get_namespace
+ $P0.'add_namespace'($P1)
+
+You can also find a namespace nested in a namespace with the C<find_namespace>
+method. Note that this finds I<only> a namespace, where the C<find_global>
+opcode will find I<any> PMC stored in that namespace under the given name:
+
+ $P0 = get_namespace
+ $P1 = $P0.'find_namespace'("MyOtherNameSpace")
+
+You may also wish to create a namespace if it doesn't exist and find it
+otherwise. That's the purpose of the C<make_namespace> method:
+
+ $P1 = $P0.'make_namespace'("MyNameSpace")
+
+To manipulate Sub PMCs in a namespace, use the C<add_sub> and C<find_sub>
+methods. As with C<find_namespace>, C<find_sub> returns I<only> a Sub PMC and
+never any other kind of global symbol:
+
+ $P0.'add_sub'("MySub", $P2)
+ $P1 = $P0.'find_sub'("MySub")
+
+Similarly, the C<add_var> and C<find_var> methods work on PMCs of I<any> type:
+
+ $P0.'add_var'("MyVar", $P3) # Add variable "MyVar" in $P3
+ $P1 = $P0.'find_var'("MyVar") # Find it
+
+You can get the name of a namespace with the C<get_name> method; this returns a
+ResizableStringArray of STRINGs:
+
+ $P3 = $P0.'get_name'()
+
+Request a namespace's parent namespace with the C<get_parent> method:
+
+ $P5 = $P0.'get_parent'()
+
+Find a class associated with a namespace with the C<get_class> method:
+
+ $P6 = $P0.'get_class'()
+
+=head3 Calling Methods
+
+Z<CHP-4-SECT-2.2>
+
+X<methods>
+Namespaces enable plenty of interesting behaviors, such as object oriented
+programming and method calls. Methods resemble subroutines with one big
+change: they require an invocant (an object PMC passed as the C<self>
+parameter).
+
+The basic syntax for a method call resembles a subroutine call. Previous
+examples have demonstrated it already. A PIR method call takes a variable for
+the invocant PMC and a string with the name of the method:
+
+ object."methodname"(arguments)
+
+If you forget the quotes around the method's name, PIR will treat the method
+name as a named variable which contains the method's name:
+
+ .local string methname = "Foo"
+ object.methname() # Same as object."Foo"()
+ object."Foo"() # Same
+
+The invocant can be a variable or register, and the method name can be a
+literal string, string variable, or method object PMC.
+
+=head3 Defining Methods
+
+Define a method like any other subroutine, respecting two changes. First, a
+method must be a member of a namespace (the namespace representing the class to
+which the method belongs). Second, they require the C<:method> flag.
+
+ .namespace [ "MyClass" ]
+
+ .sub 'MyMethod' :method
+ ...
+ .end
+
+Inside the method, access the invocant object through the C<self> parameter.
+C<self> isn't the only name you can call this value, however. You can also use
+the C<:invocant> flag to define a new name for the invocant object:
+
+(See TT #483)
+
+=begin PIR_TODO
+
+ .sub 'MyMethod' :method
+ $S0 = self # Already defined as "self"
+ say $S0
+ .end
+
+ .sub 'MyMethod2' :method
+ .param pmc item :invocant # "self" is now "item"
+ $S0 = item
+ say $S0
+ .end
+
+=end PIR_TODO
+
+This example defines two methods in the C<Foo> class. It calls one from the
+main body of the subroutine and the other from within the first method:
+
+=begin PIR
+
+ .sub 'main'
+ .local pmc class
+ .local pmc obj
+ newclass class, "Foo" # create a new Foo class
+ new obj, "Foo" # instantiate a Foo object
+ obj."meth"() # call obj."meth" which is actually
+ say "done" # in the "Foo" namespace
+ end
+ .end
+
+ .namespace [ "Foo" ] # start namespace "Foo"
+
+ .sub 'meth' :method # define Foo::meth global
+ say "in meth"
+ $S0 = "other_meth" # method names can be in a register too
+ self.$S0() # self is the invocant
+ .end
+
+ .sub 'other_meth' :method # define another method
+ say "in other_meth" # as earlier, Parrot provides a return
+ .end # statement
+
+=end PIR
+
+Each method call looks up the method name in the object's class namespace. The
+C<.sub> directive automatically makes a symbol table entry for the subroutine
+in the current namespace.
+
+You can pass multiple arguments to a method and retrieve multiple return values
+just like a single line subroutine call:
+
+ (res1, res2) = obj."method"(arg1, arg2)
+
+=head3 VTABLEs
+
+PMCs all implement a common interface of functions called X<VTABLE> VTABLEs.
+Every PMC implements the same set of these interfaces, which perform very
+specific low-level tasks on the PMC. The term VTABLE was originally a shortened
+form of the name "virtual function table", although that name isn't used any
+more by the developers, or in any of the documentation.N<In fact, if you say
+"virtual function table" to one of the developers, they probably won't know
+what you are talking about.> The virtual functions in the VTABLE, called
+X<VTABLE interfaces> VTABLE interfaces, are similar to ordinary functions and
+methods in many respects. VTABLE interfaces are occasionally called "VTABLE
+functions", or "VTABLE methods" or even "VTABLE entries" in casual
+conversation. A quick comparison shows that VTABLE interfaces are not really
+subroutines or methods in the way that those terms have been used throughout
+the rest of Parrot. Like methods on an object, VTABLE interfaces are defined
+for a specific class of PMC, and can be invoked on any member of that class.
+Likewise, in a VTABLE interface declaration, the C<self> keyword is used to
+describe the object that it is invoked upon. That's where the similarities end,
+however. Unlike ordinary subroutines or methods, VTABLE methods cannot be
+invoked directly, they are also not inherited through class hierarchies like
+how methods are. With all this terminology discussion out of the way, we can
+start talking about what VTABLES are and how they are used in Parrot.
+
+VTABLE interfaces are the primary way that data in the PMC is accessed
+and modified. VTABLES also provide a way to invoke the PMC if it's a
+subroutine or subroutine-like PMC. VTABLE interfaces are not called
+directly from PIR code, but are instead called internally by Parrot to
+implement specific opcodes and behaviors. For instance, the C<invoke>
+opcode calls the C<invoke> VTABLE interface of the subroutine PMC,
+while the C<inc> opcode on a PMC calls the C<increment> VTABLE
+interface on that PMC. What VTABLE interface overrides do, in essence,
+is to allow the programmer to change the very way that Parrot accesses
+PMC data in the most fundamental way, and changes the very way that the
+opcodes act on that data.
+
+PMCs, as we will look at more closely in later chapters, are typically
+implemented using X<PMC Script> PMC Script, a layer of syntax and macros
+over ordinary C code. A X<PMC Compiler> PMC compiler program converts the
+PMC files into C code for compilation as part of the ordinary build
+process. However, VTABLE interfaces can be written I<and overwritten> in
+PIR using the C<:vtable> flag on a subroutine declaration. This technique
+is used most commonly when subclassing an existing PMC class in PIR code
+to create a new data type with custom access methods.
+
+VTABLE interfaces are declared with the C<:vtable> flag:
+
+ .sub 'set_integer' :vtable
+ #set the integer value of the PMC here
+ .end
+
+in which case the subroutine must have the same name as the VTABLE
+interface it is intended to implement. VTABLE interfaces all have very
+specific names, and you can't override one with just any arbitrary name.
+However, if you would like to name the function something different but
+still use it as a VTABLE interface, you could add an additional name
+parameter to the flag:
+
+ .sub 'MySetInteger' :vtable('set_integer')
+ #set the integer value of the PMC here
+ .end
+
+VTABLE interfaces are often given the C<:method> flag also, so that they can
+be used directly in PIR code as methods, in addition to being used by Parrot
+as VTABLE interfaces. This means we can have the following:
+
+ .namespace [ "MyClass" ]
+
+ .sub 'ToString' :vtable('get_string') :method
+ $S0 = "hello!"
+ .return($S0)
+ .end
+
+ .namespace [ "OtherClass" ]
+
+ .local pmc myclass = new "MyClass"
+ say myclass # say converts to string internally
+ $S0 = myclass # Convert to a string, store in $S0
+ $S0 = myclass.'ToString'() # The same
+
+Inside a VTABLE interface definition, the C<self> local variable contains
+the PMC on which the VTABLE interface is invoked, just like in a method
+declaration.
+
+=head2 Roles
+
+As we've seen above and in the previous chapter, Class PMCs and NameSpace
+PMCs work to keep classes and methods together in a logical way. There is
+another factor to add to this mix: The Role PMC.
+
+Roles are like classes, but don't stand on their own. They represent
+collections of methods and VTABLES that can be added into an existing class.
+Adding a role to a class is called I<composing> that role, and any class
+that has been composed with a role C<does> that role.
+
+Roles are created as PMCs and can be manipulated through opcodes and methods
+like other PMCs:
+
+ $P0 = new 'Role'
+ $P1 = get_global "MyRoleSub"
+ $P0.'add_method'("MyRoleSub", $P1)
+
+Once we've created a role and added methods to it, we can add that role to
+a class, or even to another role:
+
+ $P1 = new 'Role'
+ $P2 = new 'Class'
+ $P1.'add_role'($P0)
+ $P2.'add_role'($P0)
+ add_role $P2, $P0 # Same!
+
+Now that we have added the role, we can check whether we implement it:
+
+ $I0 = does $P2, $P0 # Yes
+
+We can get a list of roles from our Class PMC:
+
+ $P3 = $P2.'roles'()
+
+Roles are very useful for ensuring that related classes all implement a common
+interface.
+
+=head2 Coroutines
+
+X<PIR;Coroutines>
+X<Coroutines>
+We've mentioned coroutines several times before, and we're finally going
+to explain what they are. Coroutines are similar to subroutines except
+that they have an internal notion of I<state>.N<And the cool new name!>.
+Coroutines, in addition to performing a normal C<.return> to return
+control flow back to the caller and destroy the lexical environment of
+the subroutine, may also perform a C<.yield> operation. C<.yield> returns
+a value to the caller like C<.return> can, but it does not destroy the
+lexical state of the coroutine. The next time the coroutine is called, it
+continues execution from the point of the last C<.yield>, not at the
+beginning of the coroutine.
+
+In a Coroutine, when we continue from a C<.yield>, the entire lexical
+environment is the same as it was when C<.yield> was called. This
+means that the parameter values don't change, even if we call the
+coroutine with different arguments later.
+
+=head3 Defining Coroutines
+
+Coroutines are defined like any ordinary subroutine. They do not require
+any special flag or any special syntax to mark them as being a
+coroutine. However, what sets them apart is the use of the C<.yield>
+directive. C<.yield> plays several roles:
+
+=over 4
+
+=item * Identifies coroutines
+
+When Parrot sees a yield, it knows to create a Coroutine PMC object
+instead of a Sub PMC.
+
+=item * Creates a continuation
+
+Continuations, as we have already seen, allow us to continue
+execution at the point of the continuation later. It's like a snapshot of
+the current execution environment. C<.yield> creates a continuation in
+the coroutine and stores the continuation object in the coroutine object
+or later resuming from the point of the C<.yield>.
+
+=item * Returns a value
+
+C<.yield> can return a valueN<or many values, or no values> to the caller.
+It is basically the same as a C<.return> in this regard.
+
+=back
+
+Here is a quick example of a simple coroutine:
+
+ .sub 'MyCoro'
+ .yield(1)
+ .yield(2)
+ .yield(3)
+ .return(4)
+ .end
+
+ .sub 'main' :main
+ $I0 = MyCoro() # 1
+ $I0 = MyCoro() # 2
+ $I0 = MyCoro() # 3
+ $I0 = MyCoro() # 4
+ $I0 = MyCoro() # 1
+ $I0 = MyCoro() # 2
+ $I0 = MyCoro() # 3
+ $I0 = MyCoro() # 4
+ $I0 = MyCoro() # 1
+ $I0 = MyCoro() # 2
+ $I0 = MyCoro() # 3
+ $I0 = MyCoro() # 4
+ .end
+
+This is obviously a contrived example, but it demonstrates how the coroutine
+stores it's state. The coroutine stores it's state when we reach a C<.yield>
+directive, and when the coroutine is called again it picks up where it last
+left off. Coroutines also handle parameters in a way that might not be
+intuitive. Here's an example of this:
+
+ .sub 'StoredConstant'
+ .param int x
+ .yield(x)
+ .yield(x)
+ .yield(x)
+ .end
+
+ .sub 'main' :main
+ $I0 = StoredConstant(5) # $I0 = 5
+ $I0 = StoredConstant(6) # $I0 = 5
+ $I0 = StoredConstant(7) # $I0 = 5
+ $I0 = StoredConstant(8) # $I0 = 8
+ .end
+
+Notice how even though we are calling the C<StoredConstant> coroutine with
+different arguments each time, the value of parameter C<x> doesn't change
+until the coroutine's state resets after the last C<.yield>. Remember that
+a continuation takes a snapshot of the current state, and the C<.yield>
+directive takes a continuation. The next time we call the coroutine, it
+invokes the continuation internally, and returns us to the exact same place in
+the exact same condition as we were when we called the C<.yield>. In order
+to reset the coroutine and enable it to take a new parameter, we must either
+execute a C<.return> directive or reach the end of the coroutine.
+
+=head2 Multiple Dispatch
+
+Multiple dispatch is when there are multiple subroutines in a single
+namespace with the same name. These functions must differ, however, in
+their parameter list, or "signature". All subs with the same name get
+put into a single PMC called a MultiSub. The MultiSub is like a list
+of subroutines. When the multisub is invoked, the MultiSub PMC object
+searches through the list of subroutines and searches for the one with
+the closest matching signature. The best match is the sub that gets
+invoked.
+
+=head3 Defining MultiSubs
+
+MultiSubs are subroutines with the C<:multi> flag applied to them.
+MultiSubs (also called "Multis") must all differ from one another in
+the number and/or type of arguments passed to the function. Having
+two multisubs with the same function signature could result in a
+parsing error, or the later function could overwrite the former one
+in the multi.
+
+Multisubs are defined like this:
+
+ .sub 'MyMulti' :multi
+ # does whatever a MyMulti does
+ .end
+
+Multis belong to a specific namespace. Functions in different namespaces with
+the same name do not conflict with each other. It's only when multiple
+functions in a single namespace need to have the same name that a multi is
+used.
+
+Multisubs take a special designator called a I<multi signature>. The multi
+signature tells Parrot what particular combination of input parameters the
+multi accepts. Each multi will have a different signature, and Parrot will
+be able to dispatch to each one depending on the arguments passed. The
+multi signature is specified in the C<:multi> directive:
+
+ .sub 'Add' :multi(I, I)
+ .param int x
+ .param int y
+ .return(x + y)
+ .end
+
+ .sub 'Add' :multi(N, N)
+ .param num x
+ .param num y
+ .return(x + y)
+ .end
+
+ .sub 'Start' :main
+ $I0 = Add(1, 2) # 3
+ $N0 = Add(3.14, 2.0) # 5.14
+ $S0 = Add("a", "b") # ERROR! No (S, S) variant!
+ .end
+
+Multis can take I, N, S, and P types, but they can also use C<_> (underscore)
+to denote a wildcard, and a string that can be the name of a particular PMC
+type:
+
+ .sub 'Add' :multi(I, I) # Two integers
+ ...
+
+ .sub 'Add' :multi(I, 'Float') # An integer and Float PMC
+ ...
+
+ # Two Integer PMCs
+ .sub 'Add' :multi('Integer', _)
+ ...
+
+When we call a multi PMC, Parrot will try to take the most specific
+best-match variant, and will fall back to more general variants if a perfect
+best-match cannot be found. So if we call C<'Add'(1, 2)>, Parrot will dispatch
+to the C<(I, I)> variant. If we call C<'Add'(1, "hi")>, Parrot will match the
+C<(I, _)> variant, since the string in the second argument doesn't match C<I>
+or C<'Float'>. Parrot can also choose to automatically promote one of the I,
+N, or S values to an Integer, Float, or String PMC.
+
+To make the decision about which multi variant to call, Parrot takes a
+I<Manhattan Distance> between the two. Parrot calculates the I<distance>
+between the multi signatures and the argument signature. Every difference
+counts as one step. A difference can be an autobox from a primitive type
+to a PMC, or the conversion from one primitive type to another, or the
+matching of an argument to a C<_> wildcard. After Parrot calculates the
+distance to each variant, it calls the function with the lowest distance.
+Notice that it's possible to define a variant that is impossible to call:
+for every potential combination of arguments there is a better match. This
+isn't necessarily a common occurrence, but it's something to watch out for
+in systems with a lot of multis and a limited number of data types in use.
+
+
+=head2 Classes and Objects
+
+It may seem more appropriate for a discussion of PIR's support for classes
+and objects to reside in its own chapter, instead of appearing in a generic
+chapter about PIR programming "basics". However, part of PIR's core
+functionality is its support for object-oriented programming. PIR doesn't
+use all the fancy syntax as other OO languages, and it doesn't even support
+all the features that most modern OO languages have. What PIR does have is
+support for some of the basic structures and abilities, the necessary subset
+to construct richer and higher-level object systems.
+
+=head2 PMCs as Classes
+
+PMCs aren't exactly "classes" in the way that this term is normally used in
+object-oriented programming languages. They are polymorphic data items that can
+be one of a large variety of predefined types. As we have seen briefly, and as
+we will see in more depth later, PMCs have a standard interface called the
+VTABLE interface. VTABLEs are a standard list of functions that all PMCs
+implement.N<Alternately, PMCs can choose not to implement each interface
+explicitly and instead let Parrot call the default implementations.>
+
+VTABLEs are very strict: There are a fixed number with fixed names and
+fixed argument lists. You can't just create any random VTABLE interface that
+you want to create, you can only make use of the ones that Parrot supplies
+and expects. To circumvent this limitation, PMCs may have METHODS in
+addition to VTABLEs. METHODs are arbitrary code functions that can be
+written in C, may have any name, and may implement any behavior.
+
+=head2 VTABLE Interfaces
+
+Internally, all operations on PMCs are performed by calling various VTABLE
+interfaces.
+
+=head2 Class and Object PMCs
+
+The details about various PMC classes are managed by the Class PMC. Class PMCs
+contain information about the class, available methods, the inheritance
+hierarchy of the class, and various other details. Classes can be created
+with the C<newclass> opcode:
+
+ $P0 = newclass "MyClass"
+
+Once we have created the class PMC, we can instantiate objects of that class
+using the C<new> opcode. The C<new> opcode takes either the class name or the
+Class PMC as an argument:
+
+ $P1 = new $P0 # $P0 is the Class PMC
+ $P2 = new "MyClass" # Same
+
+The C<new> opcode can create two different types of PMC. The first type are
+the built-in core PMC classes. The built-in PMCs are written in C and cannot
+be extended from PIR without subclassing. However, you can also create
+user-defined PMC types in PIR. User-defined PMCs use the Object PMC type for
+instantiation. Object PMCs are used for all user-defined type and keep track
+of the methods and VTABLE override definitions. We're going to talk about
+methods and VTABLE overrides in the next chapter.
+
+=head2 Subclassing PMCs
+
+Existing built-in PMC types can be subclassed to associate additional data
+and methods with that PMC type. Subclassed PMC types act like their PMC
+base types, by sharing the same VTABLE methods and underlying data types.
+However, the subclass can define additional methods and attribute data
+storage. If necessary new VTABLE interfaces can be defined in PIR and old
+VTABLE methods can be overridden using PIR. We'll talk about defining
+methods and VTABLE interface overrides in the next chapter.
+
+Creating a new subclass of an existing PMC class is done using the
+C<subclass> keyword:
+
+ # create an anonymous subclass
+ $P0 = subclass 'ResizablePMCArray'
+
+ # create a subclass named "MyArray"
+ $P0 = subclass 'ResizablePMCArray', 'MyArray'
+
+This returns a C<Class> PMC which can be used to create and modify the
+class by adding attributes or creating objects of that class. You can also
+use the new class PMC to create additional subclasses:
+
+ $P0 = subclass 'ResizablePMCArray', 'MyArray'
+ $P1 = subclass $P0, 'MyOtherArray'
+
+Once you have created these classes, you can create them like normal with
+the C<new> keyword:
+
+ $P0 = new 'MyArray'
+ $P1 = new 'MyOtherArray'
+
+=head2 Attributes
+
+Classes and subclasses can be given attributes which are named data fields.
+Attributes are created with the C<addattribute> opcode, and can be set and
+retrieved with the C<setattribute> and C<getattribute> opcodes respectively:
+
+ # Create the new class with two attributes
+ $P0 = newclass 'MyClass'
+ addattribute $P0, 'First'
+ addattribute $P0, 'Second'
+
+ # Create a new item of type MyClass
+ $P1 = new 'MyClass'
+
+ # Set values to the attributes
+ setattribute $P1, 'First', 'First Value'
+ setattribute $P1, 'Second', 'Second Value'
+
+ # Get the attribute values
+ $S0 = getattribute $P1, 'First'
+ $S1 = getattribute $P1, 'Second'
+
+Those values added as attributes don't need to be strings, even though
+both of the ones in the example are. They can be integers, numbers
+or PMCs too.
+
+=head2 Input and Output
+
+Like almost everything else in Parrot, input and output are handled by PMCs.
+Using the C<print> opcode or the C<say> opcode like we've already seen in
+some examples does this internally without your knowledge. However, we can
+do it explicitly too. First we'll talk about basic I/O, and then we will talk
+about using PMC-based filehandles for more advanced operations.
+
+=head2 Basic I/O Opcodes
+
+We've seen C<print> and C<say>. These are carry-over artifacts from Perl, when
+Parrot was simply the VM backend to the Perl 6 language. C<print> prints
+the given string argument, or the stringified form of the argument, if it's
+not a string, to standard output. C<say> does the same thing but also appends
+a trailing newline to it. Another opcode worth mentioning is the C<printerr>
+opcode, which prints an argument to the standard error output instead.
+
+We can read values from the standard input using the C<read> and C<readline>
+ops. C<read> takes an integer value and returns a string with that many
+characters. C<readline> reads an entire line of input from the standard
+input, and returns the string without the trailing newline. Here is a simple
+echo program that reads in characters from the user and echos them to
+standard output:
+
+=begin PIR
+
+ .sub 'main'
+ loop_top:
+ $S0 = read 10
+ print $S0
+ goto loop_top
+ .end
+
+=end PIR
+
+=head2 Filehandles
+
+The ops we have seen so far are useful if all your I/O operations are limited
+to the standard streams. However, there are plenty of other places where
+you might want to get data from and send data to. Things like files, sockets,
+and databases all might need to have data sent to them. These things can be
+done by using a file handle.
+
+Filehandles are PMCs that describe a file and keep track of an I/O operations
+internal state. We can get Filehandles for the standard streams using dedicated
+opcodes:
+
+ $P0 = getstdin # Standard input handle
+ $P1 = getstdout # Standard output handle
+ $P2 = getstderr # Standard error handle
+
+If we have a file, we can create a handle to it using the C<open> op:
+
+ $P0 = open "my/file/name.txt"
+
+We can also specify the exact mode that the file handle will be in:
+
+ $P0 = open "my/file/name.txt", "wa"
+
+The mode string at the end should be familiar to C programmers, because they
+are mostly the same values:
+
+ r : read
+ w : write
+ wa : append
+ p : pipe
+
+So if we want a handle that we can read and write to, we write the mode string
+C<"rw">. If we want to be able to read and write to it, but we don't want
+write operations to overwrite the existing contents, we use C<"rwa"> instead.
+
+When we are done with a filehandle that we've created, we can shut it down
+with the C<close> op. Notice that we don't want to be closing any of the
+standard streams.
+
+ close $P0
+
+With a filehandle, we can perform all the same operations as we could earlier,
+but we pass the filehandle as an additional argument to tell the op where to
+write or read the data from.
+
+ print "hello" # Write "hello!" to STDOUT
+
+ $P0 = getstdout
+ print $P0, "hello" # Same, but more explicit
+
+ say $P0, " world!" # say to STDOUT
+
+ $P1 = open "myfile.txt", "wa"
+ print $P1, "foo" # Write "foo" to myfile.txt
+
+=head2 Filehandle PMCs
+
+Let's see a little example of a program that reads in data from a file, and
+prints it to STDOUT.
+
+=begin PIR
+
+ .sub 'main'
+ $P0 = getstdout
+ $P1 = open "myfile.txt", "r"
+ loop_top:
+ $S0 = readline $P1
+ print $P0, $S0
+ if $P1 goto loop_top
+ close $P1
+ .end
+
+=end PIR
+
+This example shows that treating a filehandle PMC like a boolean value
+returns whether or not we have reached the end of the file. A true return
+value means there is more file to read. A false return value means we are at
+the end. In addition to this behavior, Filehandle PMCs have a number of methods
+that can be used to perform various operations.
+
+=over 4
+
+=item C<$P0.'open'(STRING filename, STRING mode)>
+
+Opens the filehandle. Takes two optional strings: the name of the file to open
+and the open mode. If no filename is given, the previous filename associated
+with the filehandle is opened. If no mode is given, the previously-used mode
+is used.
+
+ $P0 = new 'Filehandle'
+ $P0.'open'("myfile.txt", "r")
+
+ $P0 = open "myfile.txt", "r" # Same!
+
+The C<open> opcode internally creates a new filehandle PMC and calls the
+C<'open'()> method on it. So even though the above two code snippets act in
+an identical way, the later one is a little more concise to write. The caveat
+is that the C<open> opcode creates a new PMC for every call, while the
+C<'open'()> method call can reuse an existing filehandle PMC for a new file.
+
+=item C<$P0.'isatty'()>
+
+Returns a boolean value whether the filehandle is a TTY terminal
+
+=item C<$P0.'close'()>
+
+Closes the filehandle. Can be reopened with C<.'open'> later.
+
+ $P0.'close'()
+
+ close $P0 # Same
+
+The C<close> opcode calls the C<'close'()> method on the Filehandle PMC
+internally, so these two calls are equivalent.
+
+=item C<$P0.'is_closed'()>
+
+Returns true if the filehandle is closed, false if it is opened.
+
+=item C<$P0.'read'(INTVAL length)>
+
+Reads C<length> bytes from the filehandle.
+
+ $S0 = read $P0, 10
+
+ $P0.'read'(10)
+
+The two calls are equivalent, and the C<read> opcode calls the C<'read'()>
+method internally.
+
+=item C<$P0.'readline'()>
+
+Reads an entire line (up to a newline character or EOF) from the filehandle.
+
+=item C<$P0.'readline_interactive'(STRING prompt)>
+
+Displays the string C<prompt> and then reads a line of input.
+
+=item C<$P0.'readall'(STRING name)>
+
+Reads the entire file C<name> into a string. If the filehandle is closed,
+it will open the file given by C<name>, read the entire file, and then close
+the handle. If the filehandle is already open, C<name> should not be passed
+(it is an optional parameter).
+
+=item C<$P0.'flush'()>
+
+Flushes the buffer
+
+=item C<$P0.'print'(PMC to_print)>
+
+Prints the given value to the filehandle. The C<print> opcode uses the
+C<'print'()> method internally.
+
+ print "Hello"
+
+ $P0 = getstdout
+ print $P0, "Hello!" # Same
+
+ $P0.'print'("Hello!") # Same
+
+=item C<$P0.'puts'(STRING to_print)>
+
+Prints the given string value to the filehandle
+
+=item C<$P0.'buffer_type'(STRING new_type)>
+
+If C<new_type> is given, changes the buffer to the new type. If it is not,
+returns the current type. Acceptable types are:
+
+ unbuffered
+ line-buffered
+ full-buffered
+
+=item C<$P0.'buffer_size'(INTVAL size)>
+
+If C<size> is given, set the size of the buffer. If not, returns the size of
+the current buffer.
+
+=item C<$P0.'mode'()>
+
+Returns the current file access mode.
+
+=item C<$P0.'encoding'(STRING encoding)>
+
+Sets the filehandle's string encoding to C<encoding> if given, returns the
+current encoding otherwise.
+
+=item C<$P0.'eof'()>
+
+Returns true if the filehandle is at the end of the current file, false
+otherwise.
+
+=item C<$P0.'get_fd'()>
+
+Returns the integer file descriptor of the current file, but only on operating
+systems that use file descriptors. Returns C<-1> on systems that do not
+support this.
+
+=back
+
+=head2 Exceptions
+
+Parrot includes a robust exception mechanism that is not only used internally
+to implement a variety of control flow constructs, but is also available for
+use directly from PIR code. Exceptions, in as few words as possible, are
+error conditions in the program. Exceptions are I<thrown> when an error
+occurs, and they can be I<caught> by special routines called I<handlers>. This
+enables Parrot to recover from errors in a controlled way, instead of crashing
+and terminating the process entirely.
+
+Exceptions, like most other data objects in Parrot, are PMCs. They contain
+and provide access to a number of different bits of data about the error,
+such as the location where the error was thrown (including complete
+backtraces), any annotation information from the file, and other data.
+
+=head2 Throwing Exceptions
+
+Many exceptions are used internally in Parrot to indicate error conditions.
+Opcodes such as C<die> and C<warn> throw exceptions internally to do what they
+are supposed to do. Other opcodes such as C<div> throw exceptions only when
+an error occurs, such as an attempted division by zero.
+
+Exceptions can also be thrown manually using the C<throw> opcode. Here's an
+example:
+
+ $P0 = new 'Exception'
+ throw $P0
+
+This throws the exception object as an error. If there are any available
+handlers in scope, the interpreter will pass the exception object to the
+handler and continue execution there. If there are no handlers available,
+Parrot will exit.
+
+=head2 Exception Attributes
+
+Since Exceptions are PMC objects, they can contain a number of useful data
+items. One such data item is the message:
+
+ $P0 = new 'Exception'
+ $P1 = new 'String'
+ $P1 = "this is an error message for the exception"
+ $P0["message"] = $P1
+
+Another is the severity and the type:
+
+ $P0["severity"] = 1 # An integer value
+ $P0["type"] = 2 # Also an Integer
+
+Finally, there is a spot for additional data to be included:
+
+ $P0["payload"] = $P2 # Any arbitrary PMC
+
+=head2 Exception Handlers
+
+Exception handlers are labels in PIR code that can be jumped to when an
+exception is thrown. To list a label as an exception handler, the C<push_eh>
+opcode is used. All handlers exist on a stack. Pushing a new handler adds it
+to the top of the stack, and using the C<pop_eh> opcode pops the handler off
+the top of the stack.
+
+ push_eh my_handler
+ # something that might cause an error
+
+ my_handler:
+ # handle the error here
+
+=head3 Catching Exceptions
+
+The exception PMC that was thrown can be caught using the C<.get_results()>
+directive. This returns the Exception PMC object that was thrown from inside
+the handler:
+
+ my_handler:
+ .local pmc err
+ .get_results(err)
+
+With the exception PMC available, the various attributes of that PMC can be
+accessed and analyzed for additional information about the error.
+
+=head3 Exception Handler PMCs
+
+Like all other interesting data types in Parrot, exception handlers are a PMC
+type. When using the syntax above with C<push_eh LABEL>, the handler PMC
+is created internally by Parrot. However, you can create it explicitly too
+if you want:
+
+ $P0 = new 'ExceptionHandler'
+ set_addr $P0, my_handler
+ push_eh $P0
+ ...
+
+ my_handler:
+ ...
+
+=head2 Rethrowing and Exception Propagation
+
+Exception handlers are nested and are stored in a stack. This is because not
+all handlers are intended to handle all exceptions. If a handler cannot deal
+with a particular exception, it can C<rethrow> the exception to the next
+handler in the stack. Exceptions propagate through the handler stack until it
+reaches the default handler which causes Parrot to exit.
+
+=head2 Annotations
+
+Annotations are pieces of metadata that can be stored in a bytecode file to
+give some information about what the original source code looked like. This
+is especially important when dealing with high-level languages. We'll go into
+detail about annotations and their use in Chapter 10.
+
+Annotations are created using the C<.annotation> keyword. Annotations consist
+of a key/value pair, where the key is a string and the value is an integer,
+a number, or a string. Since annotations are stored compactly as constants in
+the compiled bytecode, PMCs cannot be used.
+
+ .annotation 'file', 'mysource.lang'
+ .annotation 'line', 42
+ .annotation 'compiletime', 0.3456
+
+Annotations exist, or are "in force" throughout the entire subroutine,
+or until they are redefined. Creating a new annotation with the same name as
+an old one overwrites it with the new value. The current hash of annotations
+can be retrieved with the C<annotations> opcode:
+
+ .annotation 'line', 1
+ $P0 = annotations # {'line' => 1}
+ .annotation 'line', 2
+ $P0 = annotations # {'line' => 2}
+
+Or, to retrieve a single annotation by name, you can write:
+
+ $I0 = annotations 'line'
+
+=head3 Annotations in Exceptions
+
+Exception objects contain information about the annotations that were in force
+when the exception was thrown. These can be retrieved with the
+C<'annotation'()> method of the exception PMC object:
+
+ $I0 = $P0.'annotations'('line') # only the 'line' annotation
+ $P1 = $P0.'annotations'() # hash of all annotations
+
+Exceptions can also give out a backtrace to try and follow where the program
+was exactly when the exception was thrown:
+
+ $P1 = $P0.'backtrace'()
+
+The backtrace PMC is an array of hashes. Each element in the array corresponds
+to a function in the current call stack. Each hash has two elements:
+C<'annotation'> which is the hash of annotations that were in effect at that
+point, and C<'sub'> which is the Sub PMC of that function.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch04_compiler_tools.pod (from r39796, trunk/docs/book/draft/ch04_compiler_tools.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch04_compiler_tools.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch04_compiler_tools.pod)
@@ -0,0 +1,273 @@
+=pod
+
+=head1 Parrot Compiler Tools
+
+Z<CHP-4>
+
+The previous chapters demonstrated low-level Parrot programming in PIR. That's
+fun, but Parrot's true power is to host programs written in high level
+languages such as Perl 6, Python, Ruby, Tcl, and PHP.
+
+Parrot's language neutrality was a conscious design decision. Parrot and Perl
+6 hewed closely in the early days; it would have been easy for the two to
+overlap and intermingle.
+
+By keeping the two projects separate and encapsulated, the possibility arose to
+support many other dynamic languages equally well. This modular design also
+benefits designers of future languages. Instead of having to reimplement
+low-level features such as garbage collection and dynamic data types, language
+designers and compiler implementers can leave these details of infrastructure
+to Parrot and focus on the syntax, capabilities, and libraries of their
+high-level languages instead.
+
+Parrot exposes a rich interface for these languages to use, offering several
+important features: a robust exceptions system, compilation into
+platform-independent bytecode, a clean extension and embedding interface,
+just-in-time compilation to machine code, native library interface mechanisms,
+garbage collection, support for objects and classes, and a robust concurrency
+model. Designing a new language or implementing a new compiler for an old
+language is easier with all of these features designed, implemented, tested,
+and supported in a VM already.
+
+Language interoperability is a core goal for Parrot. Different languages are
+suited to different tasks; heated debates explode across the Internet about
+which language is right for which project. There's rarely a perfect fit.
+Developers often settle for one particular language if only because it offers
+the fewest I<disadvantages>. Parrot changes this game by allowing developers
+to combine multiple languages seamlessly within a single project. Well-tested
+libraries written in one languages can interoperate with clean problem-domain
+expression in a second language, glued together by a third language which
+elegantly describes the entire system's architecture. You can use the
+strengths of multiple language and mitigate their weaknesses.
+
+For language hosting and interoperability to work, languages developers need to
+write compilers that convert source code written in high level languages to
+bytecode. This process is analogous to how a compiler such as GCC converts C
+or C++ into machine code -- though instead of targeting machine code for a
+specific hardware platform, compilers written in Parrot produce Parrot code
+which can run on any hardware platform that can run Parrot.
+
+Parrot includes a suite of compiler tools for every step of this conversion:
+lexical analysis, parsing, optimization, resource allocation, and code
+generation. Instead of using traditional low-level languages -- such as the C
+produced by C<lex> and C<yacc> -- to write compilers, Parrot can use any
+language hosted on Parrot in its compiler process. As a practical matter, the
+prevalent tool uses a subset of the Perl 6 programming language called I<Not
+Quite Perl>X<Not Quite Perl> (NQP) and an implementation of the Perl 6 Grammar
+Engine X<Perl 6 Grammar Engine> (PGE) to build compilers for Parrot.
+
+=begin notetip
+
+Yes, the Perl 6 compiler on Parrot is itself written in Perl 6. This
+X<bootstrapping> I<bootstrapping> process is mind-boggling at first.
+
+=end notetip
+
+PGE and NQP are part of the Parrot Compiler Tools. A<CHP-5> Chapter 5
+discusses PGE and A<CHP-6> Chapter 6 explains NQP.
+
+=head2 PCT Overview
+
+The X<Parrot Compiler Tools;PCT> Parrot Compiler Tools (PCT) enable the
+creation of high-level language compilers and runtimes. Though the Perl 6
+development team originally created these tools to produce Rakudo (Perl 6 on
+Parrot), several other Parrot-hosted compilers use them to great effect.
+Writing a compiler using Perl 6 syntax and dynamic language tools is much
+easier than writing a compiler in C, C<lex>, and C<yacc>.
+
+PCT contains several classes that implement various parts of a compiler. HLL
+developers write language-specific subclasses to fill in the details their
+languages require. The X<HLLCompiler> C<PCT::HLLCompiler> class specifies the
+compiler's interface and represents the object used to parse and execute code.
+The X<Parrot Compiler Tools;PCT::Grammar> C<PCT::Grammar> and X<Parrot Compiler
+Tools;PCT::Grammar::Actions> C<PCT::Grammar::Actions> classes represent the
+parser and syntax tree generators, respectively. Creating a new HLL compiler is
+as easy as subclassing these three entities with methods specific to your
+language.
+
+=head3 Grammars and Action Files
+
+A PCT-based compiler requires three basic files: the main entry point file, the
+grammar specification file, and the grammar actions file. In addition,
+compilers and the languages they implement often use large libaries of built-in
+routines to provide language-specific behaviors.
+
+=over 4
+
+=item * The main file
+
+The main file is (often) a PIR program which contains the C<:main> function
+that creates and executes the compiler object. This program instantiates a
+C<PCT::HLLCompiler> subclass, loads any necessary support libraries, and
+initializes any compiler- or languages-specific data.
+
+The main file tends to be short. The guts of the compiler logic is in the
+grammar and actions files. Runtime support and auxiliary functions often
+appear in other files, by convention. This separation of concerns tends to
+make compilers easier to maintain.
+
+=item * A grammar file
+
+The high-level language's grammar appears in a F<.pg> file. This file
+subclasses C<PCT::Grammar> class and implements all of the necessary rules --
+written using PGE -- to parse the languages.
+
+=item * An actions file
+
+Actions contains methods -- written in NQP -- on the C<PCT::Grammar:Actions>
+object which receive parse data from the grammar rules and construct an
+X<Abstract Syntax Tree;Parrot Abstract Syntax Tree;AST;PAST> Abstract Syntax
+Tree (AST).N<The Parrot version of an AST is, of course, the Parrot Abstract
+Syntax Tree, or PAST.>
+
+=back
+
+PCT's workflow is customizable, but simple. The compiler passes the source
+code of the HLL into the grammar engine. The grammer engine parses this code
+and returns a X<PGE;Match Object> special Match object which represents a
+parsed version of the code. The compiler then passes this match object to the
+action methods, which convert it in stages into PAST. The compiler finally
+converts this PAST into PIR code, which it can save to a file, convert to
+bytecode, or execute directly.
+
+=head3 C<mk_language_shell.pl>
+
+The only way creating a new language compiler could be easier is if these files
+created themselves. PCT includes a tool to do just that:
+C<mk_language_shell.pl>. This program automatically creates a new directory in
+F<languages/> for your new language, the necessary three files, starter files
+for libraries, a F<Makefile> to automate the build process, and a basic test
+harness to demonstrate that your language works as expects.
+
+These generated files are all stubs which will require extensive editing to
+implement a full language, but they are a well-understood and working starting
+point. With this single command you can create a working compiler. It's up to
+you to fill the details.
+
+C<mk_language_shell.pl> prefers to run from within a working Parrot repository.
+It requires a single argument, the name of the new project to create. There
+are no hard-and-fast rules about names, but the Parrot developers reccomend
+that Parrot-based implementations of existing languages use unique names.
+
+Consider the names of Perl 5 distributions: Active Perl and Strawberry Perl.
+Python implementations are IronPython (running on the CLR) and Jython (running
+on the JVM). The Ruby-on-Parrot compiler isn't just "Ruby": it's Cardinal.
+The Tcl compiler on Parrot is Partcl.
+
+An entirely new language has no such constraints.
+
+From the Parrot directory, invoke C<mk_language_shell.pl> like:
+
+ $ B<cd languages/>
+ $ B<perl ../tools/build/mk_language_shell.pl <project name>>
+
+=head3 Parsing Fundamentals
+
+An important part of a compiler is the parser and lexical analyzer. The
+lexical analyzer converts the HLL input file into individual tokens. A token
+may consist of an individual punctuation ("+"), an identifier ("myVar"), a
+keyword ("while"), or any other artifact that stands on its own as a single
+unit. The parser attempts to match a stream of these input tokens against a
+given pattern, or grammar. The matching process orders the input tokens into an
+abstract syntax tree which the other portions of the compiler can process.
+
+X<top-down parser>
+X<bottom-up parser>
+X<parsers; top-down>
+X<parsers; bottom-up>
+Parsers come in top-down and bottom-up varieties. Top-down parsers start with a
+top-level rule which represents the entire input. It attempts to match various
+combination of subrules until it has consumed the entire input. Bottom-down
+parsers start with individual tokens from the lexical analyzer and attempt to
+combine them together into larger and larger patterns until they produce a
+top-level token.
+
+PGE is a top-down parser, although it also contains a bottom-up I<operator
+precedence> parser to make processing token clusters such as mathematical
+expressions more efficient.
+
+=head2 Driver Programs
+
+The driver program for the new compiler must create instances of the various
+necessary classes that run the parser. It must also include the standard
+function libraries, create global variables, and handle commandline options.
+PCT provides several useful command-line options, but driver programs may need
+to override several behaviors.
+
+PCT programs can run in two ways. An interactive mode runs one statement at a
+time in the console. A file mode loads and runs an entire file at once. A
+driver program may specificy information about the interactive prompt and
+environment, as well as help and error messages.
+
+=head3 C<HLLCompiler> class
+
+The C<HLLCompiler> class implements a compiler object. This object contains
+references to language-specific parser grammar and actions files, as well as
+the steps involved in the compilation process. The stub compiler created by
+C<mk_language_shell.pl> might resemble:
+
+ .sub 'onload' :anon :load :init
+ load_bytecode 'PCT.pbc'
+ $P0 = get_hll_global ['PCT'], 'HLLCompiler'
+ $P1 = $P0.'new'()
+ $P1.'language'('MyCompiler')
+ $P1.'parsegrammar'('MyCompiler::Grammar')
+ $P1.'parseactions'('MyCompiler::Grammar::Actions')
+ .end
+
+ .sub 'main' :main
+ .param pmc args
+ $P0 = compreg 'MyCompiler'
+ $P1 = $P0.'command_line'(args)
+ .end
+
+The C<:onload> function creates the driver object as an instance of
+C<HLLCompiler>, sets the necessary options, and registers the compiler with
+Parrot. The C<:main> function drives parsing and execution begin. It calls the
+C<compreg> opcode to retrieve the registered compiler object for the language
+"MyCompiler" and invokes that compiler object using the options received from
+the commandline.
+
+The C<compreg> opcode hides some of Parrot's magic; you can use it multiple
+times in a program to compile and run different languages. You can create
+multiple instances of a compiler object for a single language (such as for
+runtime C<eval>) or you can create compiler objects for multiple languages for
+easy interoperability. The Rakudo Perl 6 C<eval> function uses this mechanism
+to allow runtime eval of code snippets in other languages:
+
+ eval("puts 'Konnichiwa'", :lang<Ruby>);
+
+=head3 C<HLLCompiler> methods
+
+The previous example showed the use of several HLLCompiler methods:
+C<language>, C<parsegrammar>, and C<parseactions>. These three methods are the
+bare minimum interface any PCT-based compiler should provide. The C<language>
+method takes a string argument that is the name of the compiler. The
+HLLCompiler object uses this name to register the compiler object with Parrot.
+The C<parsegrammar> method creates a reference to the grammar file that you
+write with PGE. The C<parseactions> method takes the class name of the NQP file
+used to create the AST-generator for the compiler.
+
+If your compiler needs additional features, there are several other available
+methods:
+
+=over 4
+
+=item * C<commandline_prompt>
+
+The C<commandline_prompt> method allows you to specify a custom prompt to
+display to users in interactive mode.
+
+=item * C<commandline_banner>
+
+The C<commandline_banner> method allows you to specify a banner message that
+displays at the beginning of interactive mode.
+
+=back
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch05_pge.pod (from r39796, trunk/docs/book/draft/ch05_pge.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch05_pge.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch05_pge.pod)
@@ -0,0 +1,1558 @@
+=pod
+
+=head1 Grammar Engine
+
+X<Parrot Grammar Engine>
+X<PGE (Parrot Grammar Engine)>
+The Parrot Grammar Engine (PGE) is a parser generator, one of the key
+components of the Parrot Compiler Toolkit. It reads grammar files written in
+the PGE rules format and generates parser modules written in PIR code. PGE
+rules provide the full power of I<recursive descent parsing> and I<operator
+precedence parsing>. Fortunately, you don't need to know what those terms
+mean in order to make good use of PGE. We'll introduce the necessary
+concepts as we talk about various features in this chapter.
+
+=head2 Grammars
+
+The ultimate goal of a parser is to match patterns in a source language and
+convert them to an internal data structure for later manipulations. As a
+programmer, you're probably already familiar with some of these types of
+patterns: function declarations, function calls, statements, and assignments.
+Each of these different concepts have a particular form called a I<syntax>.
+In C for example, the syntax to define a function looks something like this:
+
+ <return_type> <function_name> ( <arguments> ) { <function_body> }
+
+Things that fit this pattern, so long as all the sub-patterns use the proper
+syntax also, are valid subroutines in C. Similarly, we can use a slightly
+different pattern to create a subroutine:
+
+ sub <function_name> { <function_body> }
+
+A grammar is a collection of rules like the ones above that specify all the
+acceptable patterns in a language. Grammars group together these rules in
+much the same way that a groups together related data fields and methods
+N<In languages like Perl 6 for instance, a grammar is just a special kind
+of class and a rule is just a special kind of method.>. Each rule defines
+a pattern for matching one unit of text, and can be made up of various other
+rules which are called recursively to make a complete match.
+
+A rule can contain regular expressions to match patterns of characters:
+
+ rule id { \d+ }
+
+A rule can also contain patterns of references to other rules:
+
+ rule record { <id> <name> <phone> }
+
+A grammar contains a group of rules that work together to match the entire
+language:
+
+ grammar Contacts;
+
+ rule name { 'John' | 'Bob ' | 'Fred' }
+
+ rule id { \d+ }
+
+ rule record { <id> <name> }
+
+ ...
+
+=head3 Rules and Tokens
+
+X<rule>
+X<token>
+There are two different kinds of rules: C<rule>, which we saw above, and
+C<token>. A C<rule> performs smart whitespace matching between the various
+pieces of the pattern. The C<record> rule given previously would match
+"6355 John" or "6355 John" but not "6355John".
+
+A C<token> matches whitespace only if you specifically request it. To get the
+same effect with a token, add the C<\s> (match a space character) and C<+>
+(match the preceding atom -- the space character, in this case -- one or more
+times) pattern to the rule:
+
+ token record { <id> \s+ <name> }
+
+=head3 The Start Rule
+
+X<top>
+X<top-down parser>
+A recursive descent parser is what's called a I<top-down parser>. It starts
+at the highest-level rule, called C<TOP>, and works its way down through
+individual rules to match an entire string or file. Real Perl 6 allows any
+name for the top-level rule, but PCT expects a rule called C<TOP>. If PCT
+was as fully-featured as Perl 6, people would use it instead! Here's an
+example of a TOP rule:
+
+ rule TOP { <record> }
+
+This rule matches a single C<record> pattern in a string or file. Once the
+parser has succeeded in matching the entire string or file passed to the
+start rule, it returns a parse tree. If it cannot match the entire input
+with the rules provided, it can either return a partial match, or it can
+throw a parse error.
+
+=head3 Testing a Grammar
+
+Let's do a small example grammar. Save this example to a file called
+F<Contacts.pg>:
+
+ grammar Contacts is PGE::Grammar;
+
+ rule TOP { <record> }
+ rule record { <id> <name> }
+ token name { 'John' | 'Bob ' | 'Fred' }
+ token id { \d+ }
+
+Then compile the grammar:
+
+ $ B<parrot Perl6Grammar.pbc --output=Contacts.pir Contacts.pg>
+
+=for author
+
+Assume an installed Parrot for all examples? Anyone working from the source
+tree should be able to mangle paths appropriately.
+
+=end for
+
+The path to F<parrot> and to the F<Perl6Grammar.pbc> file will vary on
+different systems. If you compiled Parrot from source, it will be:
+
+ $ B<./parrot runtime/parrot/library/PGE/Perl6Grammar.pbc \>
+ B<--output=Contacts.pir Contacts.pg>
+
+Next, create a small PIR script to run your grammar. Save it as
+F<grammar_test.pir>:
+
+=begin PIR
+
+ .sub main :main
+ load_bytecode 'PGE.pbc' # load some required modules
+ load_bytecode 'dumper.pbc'
+ load_bytecode 'PGE/Dumper.pbc'
+
+ load_bytecode 'Contacts.pir' # load your grammar
+
+ .local string source
+ source = "3 John"
+
+ .local pmc top, grammar, match
+ top = get_hll_global ['Contacts'], 'TOP'
+ grammar = get_class 'Contacts'
+ match = top(source, 'grammar' => grammar)
+
+ _dumper(match, "match")
+ .end
+
+=end PIR
+
+Run the test script:
+
+ $ B<parrot grammar_test.pir>
+
+It will print out a text representation of the raw parse tree stored in the
+C<match> variable:
+
+ "match" => PMC 'Contacts' => "3 John" @ 0 {
+ <record> => PMC 'Contacts' => "3 John" @ 0 {
+ <id> => PMC 'Contacts' => "3" @ 0
+ <name> => PMC 'Contacts' => "John" @ 2
+ }
+ }
+
+Each node in the tree corresponds to a rule in the grammar. The top-level
+match variable contains one child named C<record>, which contains two children
+named C<id> and C<name>. C<id> contains the number 3, and C<name> contains the
+string "John". This is exactly what the simple grammar should have matched.
+
+=head2 Rule Syntax
+
+Every language has a set of basic components (words or parts of words) and
+syntax conventions for combining them. The "words" in rules are literal
+characters or symbols, some X<metacharacters> metacharacters (or metasymbols),
+and X<rules;escape sequences>X<escape sequences, rules> escape sequences, while
+the combining syntax includes other metacharacters, X<quantifiers, rules>
+X<rules;quantifiers> quantifiers, bracketing characters, and assertions.
+
+=head3 Metacharacters
+
+The C<.> metacharacter matches any single character, even a newline character.
+The C<^> and C<$> metacharacters are zero-width matches which represent the
+beginning and end of a string. They each have doubled alternates C<^^> and
+C<$$> that match at the beginning and end of every (newline-delimited) line
+within a string.
+
+The C<|>, C<&>, C<\>, C<#>, and C<:=> metacharacters are all syntax structure
+elements. C<|> alternates between two options. C<&> matches two patterns
+simultaneously (the patterns must be the same length). C<\> turns literal
+characters into metacharacters (producing escape sequences). C<#> starts a
+comment which proceeds until the end of the line. You can start a comment at
+any point on any line in a rule. C<:=> binds a hypothetical variable to the
+result of a subrule or grouped pattern (see L<Hypothetical Variables>).
+
+The metacharacters C<()>, C<[]>, C<{}> and C<E<lt>E<gt>> are bracketing pairs.
+Bracketing pairs must always be balanced within the rule; to use a literal
+character, escape it with a C<\>. The C<()> and C<[]> pairs group patterns as
+a single atom. They often capture a result, mark the boundaries of an
+alternation, or mark a group of patterns with a quantifier. Parentheses C<()>
+capture, but square brackets C<[]> do not. The C<{}> brackets define a section
+of code (a closure) within a rule. These closures are always a successful
+zero-width match. The C<E<lt>...E<gt>> brackets mark assertions, which handle a
+variety of constructs including character classes and user-defined quantifiers
+(see L<Assertions>).
+
+Table 7-2 summarizes the basic metacharacters.
+
+=begin table picture Metacharacters
+
+Z<CHP-7-TABLE-2>
+
+=headrow
+
+=row
+
+=cell Symbol
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<.>
+
+=cell Match any single character, including a newline.
+X<. (dot);. match single character (rules)>
+
+=row
+
+=cell C<^>
+
+=cell Match the beginning of a string.
+X<^ (caret);^ beginning of string (rules)>
+
+=row
+
+=cell C<$>
+
+=cell Match the end of a string.
+X<$ (dollar sign);$ end of string (rules)>
+
+=row
+
+=cell C<^^>
+
+=cell Match the beginning of a line within the string.
+X<^ (caret);^^ beginning of line (rules)>
+
+=row
+
+=cell C<$$>
+
+=cell Match the end of a line within the string.
+X<$ (dollar sign);$$ end of line (rules)>
+
+=row
+
+=cell C<|>
+
+=cell Match alternate patterns (OR).
+
+=row
+
+=cell C<&>
+
+=cell Match multiple patterns (AND).
+
+=row
+
+=cell C<\>
+
+=cell Escape a metacharacter to get a literal character, or escape a
+literal character to get a metacharacter.
+X<\ (backslash);\ escape sequences (rules)>
+X<\ (backslash);\ to escape metacharacters (rules)>
+
+=row
+
+=cell C<#>
+
+=cell Mark a comment (to the end of the line).
+
+=row
+
+=cell C<:=>
+
+=cell Bind the result of a match to a hypothetical variable.
+X<: (colon);:= (binding);in rules>
+
+=row
+
+=cell C<(...)>
+
+=cell Group patterns and capture the result.
+
+=row
+
+=cell C<[...]>
+
+=cell Group patterns without capturing.
+
+=row
+
+=cell C<{...}>
+
+=cell Execute a closure (Perl 6 code) within a rule.
+
+=row
+
+=cell C<E<lt>...E<gt>>
+
+=cell Match an assertion.
+
+=end table
+
+=head3 Escape Sequences
+
+Z<CHP-7-SECT-2.2>
+
+X<escape sequences, rules>
+X<rules;escape sequences>
+X<\ (backslash);\ escape sequences (rules)>
+
+Escape sequences are literal characters acting as metacharacters. A preceding
+backslash (C<\>) identifies them as escapes. Some escape sequences represent
+single characters that are difficult to represent literally, such as C<\t> for
+tab, or C<\x[...]> to specify a character by its hexadecimal number. Some
+represent limited character classes, such as C<\d> for digits or C<\w> for word
+characters. Some represent zero-width positions in a match, such as C<\b> for a
+word boundary.
+
+X<variable interpolation in rules>
+X<rules;variable interpolation>
+If you've used Perl 5 regexps, you may remember the C<\Q> escape sequence which
+treats everything until the following C<\E> sequence as literal text,
+containing no escape sequences. Because ordinary variables now interpolate as
+literal strings by default, the C<\Q> escape sequence is rarely needed.
+
+A<CHP-7-TABLE-3>Table 7-3 shows the escape sequences for rules.
+
+=begin table picture Escape sequences
+
+Z<CHP-7-TABLE-3>
+
+=headrow
+
+=row
+
+=cell Escape
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<\0[...]>
+
+=cell Match a character given in octal (brackets optional).
+
+=row
+
+=cell C<\b>
+
+=cell Match a word boundary.
+
+=row
+
+=cell C<\B>
+
+=cell Match when not on a word boundary.
+
+=row
+
+=cell C<\c[...]>
+
+=cell Match a named character or control character.
+
+=row
+
+=cell C<\C[...]>
+
+=cell Match any character except the bracketed named or control character.
+
+=row
+
+=cell C<\d>
+
+=cell Match a digit.
+
+=row
+
+=cell C<\D>
+
+=cell Match a non-digit.
+
+=row
+
+=cell C<\e>
+
+=cell Match an escape character.
+
+=row
+
+=cell C<\E>
+
+=cell Match anything but an escape character.
+
+=row
+
+=cell C<\f>
+
+=cell Match the form feed character.
+
+=row
+
+=cell C<\F>
+
+=cell Match anything but a form feed.
+
+=row
+
+=cell C<\n>
+
+=cell Match a (logical) newline.
+
+=row
+
+=cell C<\N>
+
+=cell Match anything but a (logical) newline.
+
+=row
+
+=cell C<\h>
+
+=cell Match horizontal whitespace.
+
+=row
+
+=cell C<\H>
+
+=cell Match anything but horizontal whitespace.
+
+=row
+
+=cell C<\L[...]>
+
+=cell Everything within the brackets is lowercase.
+
+=row
+
+=cell C<\Q[...]>
+
+=cell All metacharacters within the brackets match as literal characters.
+
+=row
+
+=cell C<\r>
+
+=cell Match a return.
+
+=row
+
+=cell C<\R>
+
+=cell Match anything but a return.
+
+=row
+
+=cell C<\s>
+
+=cell Match any whitespace character.
+
+=row
+
+=cell C<\S>
+
+=cell Match anything but whitespace.
+
+=row
+
+=cell C<\t>
+
+=cell Match a tab.
+
+=row
+
+=cell C<\T>
+
+=cell Match anything but a tab.
+
+=row
+
+=cell C<\U[...]>
+
+=cell Everything within the brackets is uppercase.
+
+=row
+
+=cell C<\v>
+
+=cell Match vertical whitespace.
+
+=row
+
+=cell C<\V>
+
+=cell Match anything but vertical whitespace.
+
+=row
+
+=cell C<\w>
+
+=cell Match a word character (Unicode alphanumeric characters plus the
+underscore C<_>).
+
+=row
+
+=cell C<\W>
+
+=cell Match anything but a word character.
+
+=row
+
+=cell C<\x[...]>
+
+=cell Match a character given in hexadecimal (brackets optional).
+
+=row
+
+=cell C<\X[...]>
+
+=cell Match anything but the character given in hexadecimal (brackets
+optional).
+
+=end table
+
+=head3 Quantifiers
+
+Z<CHP-7-SECT-2.3>
+
+Quantifiers specify the number of times an atom (a single character,
+metacharacter, escape sequence, grouped pattern, assertion, etc) will match.
+
+X<. (dot);.. (range);quantifier (rules)>
+X<. (dot);... (infinite range);quantifier (rules)>
+The numeric quantifiers use assertion syntax. A single number (C<E<lt>3E<gt>>)
+requires exactly that many matches. A numeric range quantifier
+(C<E<lt>3C<..>5E<gt>>) succeeds if the number of matches is between the minimum
+and maximum numbers, inclusive. A range with three trailing dots
+(C<E<lt>2...E<gt>>) is shorthand for C<E<lt>R<n>..InfE<gt>>; it matches as many
+times as possible.
+
+Each quantifier has a minimal alternate form -- marked with a trailing C<?> --
+which matches the shortest possible sequence first. That is, given the string
+C<aaaaaa>, C<aE<lt>3C<..>5E<gt>> will match C<aaaaa> and C<aE<lt>3C<..>5E<gt>?>
+will match C<aaa>.
+
+A<CHP-7-TABLE-4>Table 7-4 shows the built-in
+X<quantifiers, rules> X<rules;quantifiers> quantifiers.
+
+=begin table picture Quantifiers
+
+Z<CHP-7-TABLE-4>
+
+=headrow
+
+=row
+
+=cell Maximal
+
+=cell Minimal
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<*>
+
+=cell C<*?>
+
+=cell Match 0 or more times.
+
+=row
+
+=cell C<+>
+
+=cell C<+?>
+
+=cell Match 1 or more times.
+
+=row
+
+=cell C<?>
+
+=cell C<??>
+
+=cell Match 0 or 1 times.
+
+=row
+
+=cell C<E<lt>>R<n>C<E<gt>>
+
+=cell C<E<lt>>R<n>C<E<gt>?>
+
+=cell Match exactly R<n> times.
+
+=row
+
+=cell C<E<lt>>R<n>C<..>R<m>C<E<gt>>
+
+=cell C<E<lt>>R<n>C<..>R<m>C<E<gt>?>
+
+=cell Match at least R<n> and no more than R<m> times.
+
+=row
+
+=cell C<E<lt>>R<n>C<...E<gt>>
+
+=cell C<E<lt>>R<n>C<...E<gt>?>
+
+=cell Match at least R<n> times.
+
+=end table
+
+=head3 Assertions
+
+Z<CHP-7-SECT-2.4>
+
+X<assertions, rules>
+X<rules;assertions>
+An assertion states that some condition or state is true. The match fails when
+that assertion is false.
+
+X<variable interpolation in rules>
+X<rules;variable interpolation>
+
+Assertions match named and anonymous rules, arrays or hashes containing
+anonymous rules, and subroutines or closures that return anonymous rules.
+
+To interpolate a variable in assertion rules, enclose it in assertion
+delimiters.
+A bare scalar in a pattern
+interpolates as a literal string, while a scalar variable in assertion
+brackets interpolates as an anonymous rule. A bare array in a pattern
+matches as a series of alternate literal strings, while an array in
+assertion brackets interpolates as a series of alternate anonymous
+rules.
+
+A bare hash in a pattern matches a word (C<\w+>) if and only if that word is
+one of its keysN<The effect is similar to matching the keys as a series of
+alternates, but it prefers to match the longest possible key, instead of the
+first potential match.>, while a hash in assertion brackets also matches the
+associated value as an anonymous rule.
+
+X<fail keyword>
+A bare closure in a pattern always matches (unless it calls C<fail>), but a
+closure in assertion brackets C<E<lt>{...}E<gt>> must return an anonymous rule
+to match.
+
+An assertion with parentheses C<E<lt>(...)E<gt>> resembles a bare closure in a
+pattern in that it allows you to include Perl code within a rule.
+C<E<lt>(...)E<gt>> evaluates the return value of the closure in boolean
+context. The match succeeds or fails based on that return value.
+
+Assertions match character classes, both named and enumerated. A named rule
+character class is often more accurate than an enumerated character class. The
+common C<E<lt>[a-zA-Z]E<gt>> idiom matches ASCII alphabetic characters, but the
+more comprehensive built-in rule C<E<lt>alphaE<gt>> matches the full set of
+Unicode alphabetic characters.
+
+A<CHP-7-TABLE-5>Table 7-5 shows the syntax of assertions.
+
+=begin table picture Assertions
+
+Z<CHP-7-TABLE-5>
+
+=headrow
+
+=row
+
+=cell Syntax
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<E<lt>...E<gt>>
+
+=cell Generic assertion delimiter.
+
+=row
+
+=cell C<E<lt>!...E<gt>>
+
+=cell Negate any assertion.
+
+=row
+
+=cell C<E<lt>>R<name>C<E<gt>>
+
+=cell Match a named rule or character class.
+
+=row
+
+=cell C<E<lt>[...]E<gt>>
+
+=cell Match an enumerated character class.
+
+=row
+
+=cell C<E<lt>-...E<gt>>
+
+=cell Complement a character class (named or enumerated).
+
+=row
+
+=cell C<E<lt>"..."E<gt>>
+
+=cell Match a literal string (interpolated at match time).
+
+=row
+
+=cell C<E<lt>'...'E<gt>>
+
+=cell Match a literal string (not interpolated).
+
+=row
+
+=cell C<E<lt>(...)E<gt>>
+
+=cell Boolean assertion. Execute a closure and match if it returns a true
+result.
+
+=row
+
+=cell C<E<lt>$scalarE<gt>>
+
+=cell Match an anonymous rule.
+
+=row
+
+=cell C<E<lt>@arrayE<gt>>
+
+=cell Match a series of anonymous rules as alternates.
+
+=row
+
+=cell C<E<lt>%hashE<gt>>
+
+=cell Match a key from the hash, then its value (as an anonymous rule).
+
+=row
+
+=cell C<E<lt>E<amp>sub()E<gt>>
+
+=cell Match an anonymous rule returned by a sub.
+
+=row
+
+=cell C<E<lt>{>R<code>C<}E<gt>>
+
+=cell Match an anonymous rule returned by a closure.
+
+=row
+
+=cell C<E<lt>.E<gt>>
+
+=cell Match any logical grapheme, including combining character sequences.
+
+=end table
+
+=head3 Modifiers
+
+Z<CHP-7-SECT-2.5>
+
+X<modifiers>
+X<: (colon);: modifier delimiter in rules>
+Modifiers alter the meaning of a pattern. The standard position for modifiers
+is at the beginning of the rule, right after the C<m>, C<s>, or C<rx>, or after
+the name in a named rule. Modifiers cannot attach to the outside of a bare
+C</.../>. For example:
+
+ m:i/marvin/ # case insensitive
+ rule names :i { marvin | ford | arthur }
+
+You may group single-character modifiers, but you must separate longer
+modifiers by colons:
+
+ m:wig/ zaphod / # OK
+ m:words:ignorecase:globally / zaphod / # OK
+ m:wordsignorecaseglobally / zaphod / # Not OK
+
+Most modifiers can also appear inside the rule when attached to rule or
+grouping delimiters. Internal modifiers are lexically scoped to their enclosing
+delimiters, so can alter subpatterns:
+
+ m/:w I saw [:i zaphod] / # only 'zaphod' is case insensitive
+
+The repetition modifiers (C<:R<N>x>, C<:R<N>th>, C<:once>, C<:globally>, and
+C<:exhaustive>) and the continue modifier (C<:cont>) alter the return value of
+the rule as a whole, so you cannot use them lexically inside a rule.
+
+The C<:R<N>x> modifier matches the rule a specific number of times. If the
+modifier expects more matches than the string has, the match fails. Its
+alternate form (C<:x(R<N>)>) can take a variable in place of the number.
+
+The C<:once> modifier on a rule only allows it to match once. The rule will not
+match again until the you call the C<.reset> method on the rule object.
+
+The C<:globally> modifier matches as many times as possible. The C<:exhaustive>
+modifier also matches as many times as possible, in as many different ways as
+possible.
+
+The C<:R<N>th> modifier preserves one result from a particular counted match.
+If the rule matches fewer times than the modifier expects, the match fails. It
+has several alternate forms. One form, C<:th(R<N>)>, takes a variable in place
+of the number. The other forms -- C<:R<N>st>, C<:R<N>nd>, and C<:R<N>rd> --
+allow you to write more naturally C<:1st>, C<:2nd>, C<:3rd>. The other way is
+valid as well; choose whichever is most comfortable.
+
+By default, rules ignore literal whitespace within the pattern. The C<:w>
+modifier makes rules sensitive to literal whitespace, but in an intelligent
+way. Any cluster of literal whitespace acts like an explicit C<\s+> when it
+separates two identifiers and C<\s*> everywhere else.
+
+I<No> modifiers exist to treat the matched string as a single line or multiple
+lines. Instead, use the "beginning of string" and "end of string" or
+"beginning of line" and "end of line" metacharacters.
+
+A<CHP-7-TABLE-6>Table 7-6 lists the available modifiers.
+
+=begin table picture Modifiers
+
+Z<CHP-7-TABLE-6>
+
+=headrow
+
+=row
+
+=cell Short
+
+=cell Long
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<:i>
+
+=cell C<:ignorecase>
+
+=cell Case-insensitive match.
+
+=row
+
+=cell C<:I>
+
+=cell
+
+=cell Case-sensitive match (on by default).
+
+=row
+
+=cell C<:c>
+
+=cell C<:cont>
+
+=cell Continue where the previous match on the string left off.
+
+=row
+
+=cell C<:w>
+
+=cell C<:words>
+
+=cell Literal whitespace in the pattern matches as C<\s+>
+or C<\s*>.
+
+=row
+
+=cell C<:W>
+
+=cell
+
+=cell Turn off intelligent whitespace matching (return to default).
+
+=row
+
+=cell
+
+=cell :R<N>C<x>/C<:x(>R<N>C<)>
+
+=cell Match the pattern R<N> times.
+
+=row
+
+=cell
+
+=cell C<:>R<N>C<th>/C<:nth(>R<N>C<)>
+
+=cell Match the R<N>th occurrence of a pattern.
+
+=row
+
+=cell
+
+=cell C<:once>
+
+=cell Match the pattern once and only once.
+
+=row
+
+=cell C<:g>
+
+=cell C<:globally>
+
+=cell Match the pattern as many times as possible without overlapping
+possibilities.
+
+=row
+
+=cell C<:e>
+
+=cell C<:exhaustive>
+
+=cell Match every possible occurrence of a pattern, including overlapping
+possibilities.
+
+=row
+
+=cell
+
+=cell C<:u0>
+
+=cell . is a byte.
+
+=row
+
+=cell
+
+=cell C<:u1>
+
+=cell . is a Unicode codepoint.
+
+=row
+
+=cell
+
+=cell C<:u2>
+
+=cell . is a Unicode grapheme.
+
+=row
+
+=cell
+
+=cell C<:u3>
+
+=cell . is language dependent.
+
+=row
+
+=cell
+
+=cell C<:p5>
+
+=cell The pattern uses Perl 5 regex syntax.
+
+=end table
+
+=head3 Built-in Rules
+
+Z<CHP-7-SECT-3>
+
+X<rules;built-in>
+PGE provides several named rules, including a complete set of X<POSIX-style
+classes> POSIX-style classes, and X<Unicode property classes> Unicode property
+classes. The list isn't fully defined yet, but A<CHP-7-TABLE-7>Table 7-7 shows
+a few you're likely to see.
+
+The C<E<lt>nullE<gt>> rule matches a zero-width string (it always matches) and
+C<E<lt>priorE<gt>> matches whatever the most recent successful rule matched.
+These replace the two behaviors of X</ (slash);// invalid null pattern>
+X<invalid null pattern //> the Perl 5 null pattern C<//>, which is no longer
+valid syntax for rules.
+
+=begin table picture Built-in rules
+
+Z<CHP-7-TABLE-7>
+
+=headrow
+
+=row
+
+=cell Rule
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<E<lt>alphaE<gt>>
+
+=cell Match a Unicode alphabetic character.
+
+=row
+
+=cell C<E<lt>digitE<gt>>
+
+=cell Match a Unicode digit.
+
+=row
+
+=cell C<E<lt>spE<gt>>
+
+=cell Match a single space character (the same as C<\s>).
+
+=row
+
+=cell C<E<lt>wsE<gt>>
+
+=cell Match any whitespace (the same as C<\s+>).
+
+=row
+
+=cell C<E<lt>nullE<gt>>
+
+=cell Match the null string.
+
+=row
+
+=cell C<E<lt>priorE<gt>>
+
+=cell Match the same thing as the previous match.
+
+=row
+
+=cell C<E<lt>before ...E<gt>>
+
+=cell Zero-width lookahead. Assert that the current position I<precedes> a
+pattern.
+
+=row
+
+=cell C<E<lt>after ...E<gt>>
+
+=cell Zero-width lookbehind. Assert that the current position I<follows> a
+pattern.
+
+=row
+
+=cell C<E<lt>prop ...E<gt>>
+
+=cell Match any character with the named property.
+
+=row
+
+=cell C<E<lt>replace(...)E<gt>>
+
+=cell Replace everything matched so far in the rule or subrule with the
+given string (under consideration).
+
+=end table
+
+=head3 Backtracking Control
+
+Z<CHP-7-SECT-4>
+
+X<backtracking controls>
+X<fail keyword>
+Whenever part of the pattern fails to match, PGE performs backtracking --
+backing up to the previous point at which the match could succeed and trying
+again. You can explicitly trigger backtracking by calling the C<fail> function
+within a closure. A<CHP-7-TABLE-8>Table 7-8 displays metacharacters and
+built-in rules relevant to backtracking.
+
+=for author
+
+This could use an example.
+
+=end for
+
+=begin table picture Backtracking controls
+
+Z<CHP-7-TABLE-8>
+
+=headrow
+
+=row
+
+=cell Operator
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<:>
+
+=cell Don't retry the previous atom. Instead, fail to the next earlier atom.
+X<: (colon);: fail to atom before last (rules)>
+X<backtracking controls;: fail to atom before last>
+
+=row
+
+=cell C<::>
+
+=cell Don't backtrack over this point. Instead fail out of the closest
+enclosing group (C<(...)>, C<[...]>, or the rule delimiters).
+X<: (colon);:: fail out of group (rules)>
+X<backtracking controls;: fail out of group>
+
+=row
+
+=cell C<:::>
+
+=cell Don't backtrack over this point. Instead, fail out of the current rule
+or subrule.
+X<: (colon);::: fail out of rule (rules)>
+X<backtracking controls;: fail out of rule>
+
+=row
+
+=cell C<E<lt>commitE<gt>>
+
+=cell Don't backtrack over this point. Instead, fail out of the entire match
+(even from within a subrule).
+
+=row
+
+=cell C<E<lt>cutE<gt>>
+
+=cell Like C<E<lt>commitE<gt>>, but also cuts the string matched. The current
+matching position at this point becomes the new beginning of the string.
+
+=end table
+
+=head3 Calling Actions
+
+Once the parser has matched the entire input N<a source code file, or a line of
+input at the terminal in interactive mode> the parse has succeeded. The
+generated AST is now available to the code generator for conversion into PIR.
+
+=for author
+
+Please review. The forward declaration is awkward here, but a little bit of
+explanation might ameliorate this.
+
+=end for
+
+This AST gets built up by actions -- code snippets attached to rules and
+tokens. To call an action, insert the C<{*}> token into the rule. When PGE
+encounters C<{*}>, it will call the associated action method with the current
+match object as an argument.
+
+The best way to demonstrate this is by example. Sprinkle the C<persons_name>
+rule liberally with action calls:
+
+ rule persons_name {
+ {*} <first_name> {*} <last_name> {*}
+ }
+
+The first call to the action method contains an empty match object because the
+parser hasn't matched anything yet. The second call contains only the first
+name of the match. The third and final call contains both the matched first and
+last name.
+
+If the match fails halfway through, PGE will still call the actions that have
+succeeded; it will not call the actions after the failure. If you try to match
+the string "Leia", PGE will call the first two action methods. When the rule
+tries to match the last name, it fails, and PGE will not call the third action
+method.
+
+=head3 Alternations and Keys
+
+In addition to sub-rules, groups, and quantifiers, you can also express
+either-or alternations between options. The vertical bar token (C<|>)
+distinguishes between options where only one may match:
+
+ rule hero {
+ ['Luke' | 'Leia'] 'Skywalker'
+ }
+
+This rule will match either "Luke Skywalker" or "Leia Skywalker" but won't
+match "Luke Leia Skywalker"N<nor anything else.>. Given alternations and
+action methods, it's often important to distinguish which alternation matched:
+
+ rule hero {
+ [
+ 'Luke' {*} #= Luke
+ | 'Leia' {*} #= Leia
+ ]
+ 'Skywalker'
+ }
+
+This is the same rule, except now it passes two arguments to its action method:
+the match object and the name of the person who matched.
+
+=head3 Warning: Left Recursion
+
+If you've worked with parsers before, you may have seen this coming. If not,
+don't fear. Like functions in ordinary procedural or functional languages, the
+methods in the PGE parser grammar can call themselves recursively. Consider
+some rules derived in part from the grammar for the C programming language:
+
+ rule if_statement {
+ 'if' <condition> '{' <statement>* '}' <else_block>?
+ }
+
+ rule statement {
+ <if_statement> | <expression>
+ }
+
+ rule else_block {
+ 'else' '{' <statements>* '}'
+ }
+
+An C<if_statement> can contain a list of C<statement>s, and that each statement
+may itself be an C<if_statement>. This is I<recursion> X<Recursion>; it's one
+of the reasons PGE is a "Recursive descent" parser.
+
+Consider the more direct example of a comma-separated list of integer digits
+which form a list. A recursive definition might be:
+
+ rule list {
+ <list> ',' <digit> | <digit>
+ }
+
+If there is only one digit, the second option in the alternation matches. If
+there are multiple digits, recursion will match them through the first
+alternation.
+
+That's the intention. The results are insidious.
+
+The recursive descent parser enters the C<list> rule. Its first option is to
+enter the list rule again, so it does. Recursive descent is a X<depth-first
+algorithm> depth-first algorithm; PGE will continue to descend down a
+particular path until it finds a successful match or a match failure. In this
+case, it matches C<list>, then it matches C<list> again, then it matches
+C<list> again, and so on. This rule forms an infinite loop -- a pattern called
+X<left recursion> I<left recursion>. The problem is that the left-most item of
+the left-most alternation is itself a recursion.
+
+The rule above does not recurse infinitely when rewritten as:
+
+ rule list {
+ <digit> | <list> ',' <digit>
+ }
+
+... or even:
+
+ rule list {
+ <digit> ',' <list> | <digit>
+ }
+
+Both options ensure that the left-most item in the rule is recursive.
+
+Left recursion may be trickier. It's not immediately obvious in this grammar:
+
+ rule term {
+ <expression> '*' <term> | <digit>
+ }
+
+ rule expression {
+ <term> '+' <expression> | <term>
+ }
+
+Even this common, limited subset of mathematical equations has the same
+problem. To match a C<term>, the parser first tries to match an C<expression>,
+which in turn matches a C<term> and then an C<expression> ....
+
+Again, the solution is simple. Rewrite at least one of the rules so that the
+first condition it tries to match is not itself a recursive situation.
+
+=head3 Operator Precedence Parser
+
+Recursive descent parsing can be inefficient where statements have lots of
+little tokens and many possible options to match. For example, mathematical
+expressions are very open-ended, with many valid forms which are difficult to
+anticipate. Consider the expression:
+
+ a + b * c + d
+
+A recursive descent parser will undergo significant trial and error to parse
+this statement. Recursive descent parsing is not ideal for these situations.
+Instead, a type of bottom-up parser called an I<operator precedence> X<Parser,
+Operator precedence> parser is much better.
+
+=for author
+
+Is this a categorization of all opps or just PGE's opp?
+
+=end for
+
+Operator precedence parsers work similarly to more versatile bottom-up parsers
+such as Lex or Yacc, but are optimized for use with expressions and equations.
+Equations have two subtypes, I<terms> and I<operators>. Operators themselves
+have several subtypes, including prefix (C<-a>), postfix (C<i++>), infix (C<x +
+y>), circumfix (C<[z]>), postcircumfix (C<a[b]>), and list (C<1, 2, 3>). Each
+operator gets its own precedence number that specifies how closely it binds to
+the terms. The previous example should parse as:
+
+ a + (b * c) + d
+
+... because the C<*> operator has a higher precedence -- binding more tightly
+to its terms -- than the C<+> operator.
+
+Within a grammar, switch from the top-down recursive descent parser to the
+bottom-up operator precedence parser with an C<optable> X<Parser, optable>
+rule:
+
+ rule expression is optable { ... }
+
+The C<...> ellipsis isn't an editorial shortcut, it's the Perl 6 operator to to
+define a function signature. The C<...> indicates that this is just a
+signature; the actual implementation is elsewhere. In this case, that location
+in the definition of the optable.
+
+=head3 Protofunction Definitions
+
+X<Protofunctions>
+
+Protofunctions define operators in the optable in the same way that rules and
+tokens make up the grammar. A proto declares a rule, defined elsewhere, which
+other code may override dynamically. In this case, PCT takes information from
+the proto declaration and fills in the details. The "dynamic overriding"
+implies that a high-level language itself itself can modify its own grammar at
+run time, by overriding the proto definitions for its operator table. Some
+languages call this process X<operator overloading> I<operator overloading>.
+
+A proto definition resembles:
+
+ 'proto' <proto_name> [ 'is' <property> ] '{' '...' '}'
+
+The name of the operator, noted as C<< <proto_name> >>, contains both a
+location part and an identifier part. The location is the type of the operator,
+such as infix, postfix, prefix, circumfix, and postcircumfix. The name of the
+operator is the symbol used for the operator in any of the quotes that Perl 6
+understands:
+
+ proto infix:<+> # a + b
+ proto postfix:'--' # i--
+ proto circumfix:«<>» # <x>
+
+The C<is> X<Parser, is> keyword defines a property of the rule. Examples
+include:
+
+ is precedence(1) # Specifies an exact precedence
+ is equiv('+') # Has the same precedence as the "+" operator
+ is assoc('right') # Right associative. May also be "left" or "list"
+ is pirop('add') # Operands are passed to the PIR operator "and"
+ is subname('mySub') # Operands are passed to the function "mySub"
+ is pasttype('if') # Operands are passed as children to an "if" PAST node in
+ # the parse tree
+ is parsed(&myRule) # The token is parsed and identified using the rule
+ # "myRule" from the top-down parser
+
+=for author
+
+Please review.
+
+=end for
+
+Protofunction definitions are function signatures; you can override them with
+multimethod dispatch. This means that you can write functions I<with the same
+name> as the rule to implement the behavior of the operator. Here's a proto:
+
+ rule infix:"+" { ... }
+
+... and its corresponding PIR rule:
+
+=begin PIR
+
+ .sub 'infix:+'
+ .param pmc a
+ .param pmc b
+ .local pmc c
+ c = a + b
+ .return(c)
+ .end
+
+=end PIR
+
+You may ask "Why have an C<is subname()> property, if you can define all
+operators as subroutines?" Using the C<is subname()> property allows PCT to
+call a subroutine of a different name then the operator. This is a good idea
+if there is already a built-in function in the language that duplicates the
+functionality of the operator. There is no sense in duplicating behavior.
+
+The great thing about protos being overloadable is that you can specify
+different functions to call with different signatures:
+
+=begin PIR
+
+ .sub 'infix:+' :multi('Integer', 'Integer')
+ #...
+ .end
+
+ .sub 'infix:+' :multi('CLispRatio', 'Number')
+ #...
+ .end
+
+ .sub 'infix:+' :multi('Perl6Double', 'PythonInteger')
+ #...
+ .end
+
+=end PIR
+
+This list can be a bit intimidating, and it's hard to imagine that it would be
+necessary to write up a new function to handle addition between every
+conceivable pair of operands. Fortunately, this is rarely the case in Parrot,
+because all these data types support common the VTABLE interface. For most data
+types Parrot already has basic arithmetic operations built in, and it's only
+necessary to override for those data types with special needs.
+
+=head3 Hypothetical Variables
+
+Z<CHP-7-SECT-5>
+
+X<variables;hypothetical>
+X<hypothetical variables>
+X<rules;captures>
+Hypothetical variables are a powerful way of building up data structures from
+within a match. Ordinary captures with C<()> store the result of the captures
+in C<$1>, C<$2>, etc. PGE stores values in these variables if the match is
+successful, but throws them away if the match fails. The numbered capture
+variables are accessible outside the match, but only within the immediate
+surrounding lexical scope:
+
+ "Zaphod Beeblebrox" ~~ m:w/ (\w+) (\w+) /;
+
+ print $1; # prints Zaphod
+
+You can also capture into any user-defined variable with the binding operator
+C<:=> -- I<if> you have declared these variables in a lexical scope enclosing
+the rule:
+
+ my $person;
+ "Zaphod's just this guy." ~~ / ^ $person := (\w+) /;
+ print $person; # prints Zaphod
+
+You may capture repeated matches into an array:
+
+ my @words;
+ "feefifofum" ~~ / @words := (f<-[f]>+)* /;
+ # @words contains ("fee", "fi", "fo", "fum")
+
+You may capture pairs of repeated matches into a hash:
+
+ my %customers;
+ $records ~~ m:w/ %customers := [ E<lt>idE<gt> = E<lt>nameE<gt> \n]* /;
+
+If you don't need the captured value outside the rule, use a C<$?> variable
+instead. These are only directly accessible within the rule:
+
+ "Zaphod saw Zaphod" ~~ m:w/ $?name := (\w+) \w+ $?name/;
+
+A match of a named rule stores the result in a C<$?> variable with the same
+name as the rule. These variables are also accessible only within the rule:
+
+ "Zaphod saw Zaphod" ~~ m:w/ E<lt>nameE<gt> \w+ $?name /;
+
+=for author
+
+This next paragraph feels out of place; is there more?
+
+=end for
+
+When a rule matches a sequence of input tokens, PCT calls an associated method
+within NQP to convert that match into an AST node, which it inserts into the
+I<parse tree>.
+
+=head3 Basic Rules
+
+Consider the simple example rule:
+
+ rule persons_name {
+ <first_name> <last_name>
+ }
+
+... and two example tokens:
+
+ token first_name { <alpha>+ }
+ token last_name { <alpha>+ }
+
+The special token C<< <alpha> >> is a built-in construct that only accepts
+upper case and lower case letters. The C<+> after the C<< <alpha> >> tag is a
+short way of saying "one or more". The rule will match names like C<Darth
+Vader>N<It also matches many strings that I<aren't> real names>, but won't
+match something like C<C 3P0>.
+
+This rule I<will> match C<Jar Jar Binks>, but not as you might expect: way you
+would expect: It would match the first "Jar" as C<< <first_name> >>, the second
+"Jar" as C<< <last_name> >>, and ignore "Binks"N<You should ignore the whole
+thing.>.
+
+=for author
+
+The rest seems vestigial. An example like this should precede the rest of the
+chapter. There are forward references, but it's a decent overview for people
+who haven't used similar systems before -- if you avoid going out in the weeds.
+
+=end for
+
+this example shows another new construct, the square brackets. Square
+brackets are ways to group things together. The star at the end means
+that we take all the things inside the brackets zero or more times.
+This is similar to the plus, except the plus matches one or more times.
+Notice, however, that the above rule always matches a comma at the end,
+so we would need to have something like:
+
+ Darth Vader, Luke Skywalker,
+
+Instead of something more natural like:
+
+ Darth Vader, Luke Skywalker
+
+We can modify the rule a little bit so that it always ends with a name
+instead of a comma:
+
+ rule TOP {
+ [ <persons_name> ',' ]* <persons_name>
+ }
+
+Now we don't need a trailing comma, but at the same time we can't match
+an empty file because it always expects to have at least one name at the
+end. If we still want to match empty files successfully, we need to make
+the whole rule optional:
+
+ rule TOP {
+ [ [ <persons_name> ',' ]* <persons_name> ]?
+ }
+
+We've grouped the whole rule together in another set of brackets, and
+put a "?" question mark at the end. The question mark means zero or
+one of the prior item.
+
+The symbols "*" (zero or more), "+" (one or more) and "?" are called
+I<quantifiers>, and allow an item in the rule to match a variable
+number of times. These aren't the only quantifiers, but they are the
+most common. We will talk about other quantifiers later on.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch06_nqp.pod (from r39796, trunk/docs/book/draft/ch06_nqp.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch06_nqp.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch06_nqp.pod)
@@ -0,0 +1,219 @@
+=pod
+
+=head1 Grammar Actions
+
+The job of the grammar is to match input patterns from the source language.
+These patterns then need to get converted to nodes in the abstract syntax
+tree for manipulation in other stages of the compiler. We've already seen
+one example of a subroutine structure that takes a match and produces a
+tree node: Protofunctions. Protofunction signatures aren't the only way to
+apply functions to rules matched by a parser. They are limited and are
+slightly primitive, but effective for handling operators. There is an
+easier and more powerful way to write subroutines to convert match objects
+into parse tree nodes, using a language that's almost, but Not Quite Perl.
+
+X<NQP>
+X<Not Quite Perl>
+NQP (Not Quite Perl) is a small language which offers a limited subset of
+Perl 6's syntax and semantics. Though it originated as a bootstrapping tool
+for the Rakudo Perl 6 compiler, several other Parrot-based compilers use it
+as well. It has become a permanent member of PCT, and therefore a permanent
+part of the Parrot code base.
+
+NQP represets almost the smallest subset of the Perl 6 language necessary to
+implement parser transformations, plus a few syntactic convenience features
+that developers have requested. NQP's Perl 6 subset shows its Perl 5 roots,
+so existing Perl 5 programmers should find much of it familiar and should be
+able to leverage their existing skills for writing compilers.
+
+In PGE, at the time of a match the grammar we can invoke an action using the
+special <code>{*}</code> symbol. In general, these action methods are
+written in NQP, although it is possible for them to be written in PIR N<In
+fact, this is how the NQP compiler itself is written>. We won't discuss the
+PIR case here because it's uncommon and needlessly difficult. NQP is the
+standard and preferred choice for this.
+
+=head2 NQP Basics
+
+X<sigils>
+X<scalar>
+Like all flavors and versions of Perl, NQP uses special prefix symbols called
+I<sigils> to distinguish variable types. The C<$> sigil represents scalars,
+C<@> arrays, and C<%> for hashes. A scalar is any single value which can
+interchangeably contain given a string value, an integer value, or an object
+reference. Simple NQP assignments are:
+
+ $scalar := "This is a string"
+ $x := 123
+ $pi := 3.1415 # rounding
+
+X<bind operator>
+X<operators; binding>
+X<:=>
+The C<:=> I<bind> operator performs reference assignment in NQP. Reference
+assignment makes one variable into an alias for another. This means that
+the two variables are just different names for the same storage location,
+and changes to one will change both. It's important to remember that a bind
+is not a copy!
+
+NQP has hashes and arrays just like other flavors of Perl and various
+dynamic languages. NQP does not have a notion of hash and array context,
+but otherwise it works the way you would expect. Arrays have the C<@> sigil,
+and hashes have the C<%> sigil. Here are some examples:
+
+ @ary[0] := 1;
+ @ary[1] := "foo";
+ ...
+
+ %hsh{'bar'} := 2;
+ %hsh{'baz'} := "parrot";
+ ...
+
+There is also a nice shorthand way to index hashes, using angle brackets:
+
+ %hsh<bar> := "parrot";
+
+It's also possible to assign a list in I<scalar context>:
+
+ $array_but_a_scalar := (1, 2, 3, 4)
+
+Or you could write a new function in PIR to create a new array from a variadic
+argument list:
+
+ @my_array := create_new_array(1, 2, 3, 4)
+
+... which calls the PIR function:
+
+=begin PIR
+
+ .namespace []
+
+ .sub 'create_new_array'
+ .param pmc elems :slurpy
+ .return(elems)
+ .end
+
+=end PIR
+
+=head3 Calling Actions From Rules
+
+=for editor
+
+Needs a link to that section.
+
+=end for
+
+As mentioned in the chapter on grammar rules, the funny little C<{*}> symbol
+calls an action. The action in question is an NQP method with the same name as
+the rule that calls it. NQP rules can have two different signatures:
+
+ method name ($/) { ... }
+ method name($/, $key) { ... }
+
+Where does the key come from? Consider this grammar:
+
+ rule cavepeople {
+ 'Fred' {*} #= Caveman
+ | 'Wilma' {*} #= Cavewoman
+ | 'Dino' {*} #= Dinosaur
+ }
+
+The C<cavepeople> rule demonstrates the result:
+
+ method cavepeople($/, $key) {
+ if $key eq 'Caveman' {
+ say "We've found a caveman!";
+ } elsif $key eq 'Cavewoman' {
+ say "We've found a cavewoman!";
+ } elsif $key eq 'Dinosaur' {
+ say "A dinosaur isn't a caveperson at all!";
+ }
+ }
+
+The key is a string that contains whatever any text following the C<#=> symbol.
+Without a C<#=> following the rule invocation, there's no C<$key> to use in the
+method. If you attempt to use one without the other, the NQP compiler will die
+with error messages about mismatched argument/parameter numbers.
+
+=head3 The Match Object C<$/>
+
+X<match object>
+X<$/>
+The match object C<$/> it's a data structure that's all business: it's both a
+hash and an array. Because it's a special variable used pervasively in PCT, it
+has a special shortcut syntax:
+
+ $/{'Match_item'} is the same as $<Match_item>
+ $/[0] is the same as $[0]
+
+Each key in the match object's hash is the name of a matched rule. Given a
+file containing "C<X + 5>" and a rule:
+
+ rule introductions {
+ <variable> <operator> <number>
+ }
+
+The resulting match object will contain the key/value pairs:
+
+ "variable" => "x"
+ "operator" => "+"
+ "number" => "5"
+
+When the match contains multiple values with the same name, or when rules have
+quantifiers such as C<*> or C<+>, the values in the hash may be arrays. Given
+the input "A A A B B" and the rule:
+
+ rule letters {
+ <vowel>* <consonant>*
+ }
+
+The match object will contain the pairs:
+
+ "vowel" => ["A", "A", "A"]
+ "consonant" => ["B", "B"]
+
+X<$( ) operator>
+
+Use the C<$( )> operator to count the number of matches in each group (by
+casting it to a scalar):
+
+ $($<vowel>) == 3
+
+=head3 Inline PIR
+
+=for author
+
+Needs expansion.
+
+=end for
+
+X<{{ }}>
+X<double curly brackets>
+Sometimes NQP isn't quite flexible enough to handle transforms appropriately.
+In a PGE rule, the C<{{ }}> double curly brackets demarcate inline-PIR mode.
+PGE will execute any PIR code in those brackets. You can access C<$/> directly
+in the grammar without having to jump into NQP.
+
+=head3 PAST Nodes
+
+X<PAST>
+X<PAST nodes>
+NQP's job is to make abstract syntax trees. These trees are all objects -- and
+as such, instances of PAST nodes. Each PAST class represents a unique program
+construct. These constructs are common and simple, but combine to represent
+complicated programming structures.
+
+=head3 Making Trees
+
+Every action has the ability to create a PAST node that represents that action,
+as well as any children of that node. Calling C<make> on that node adds it into
+the growing PAST tree that PCT maintains. Once the C<TOP> rule matches
+successfully and returns, PCT optimizes and converts that tree into PIR and PBC
+for execution.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch07_dynpmcs.pod (from r39796, trunk/docs/book/draft/ch07_dynpmcs.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch07_dynpmcs.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch07_dynpmcs.pod)
@@ -0,0 +1,237 @@
+=pod
+
+=head1 Dynamic C-level Objects
+
+Z<CHP-11>
+
+PMCs are one of the four fundamental data types in Parrot, and definitely one
+of the most useful. A PMC can contain a single scalar value (integer, floating
+point number, string), an array of values, a subroutine, a namespace, or an
+entire list of other data types as well. PMCs are the basis for all higher
+order data types in Parrot, and are flexible enough to be used for any
+purpose that an HLL needs.
+
+All the common PMC types are included in the Parrot repository and built directly
+into libparrot and the parrot executable. However, the system is not rigid; new
+PMC types can be defined externally and loaded into Parrot at a later time. In
+this way, HLLs and libraries and applications can add new data types to Parrot
+at the C code level, which helps to ensure speed and efficiency. PMCs loaded
+this way are called X<dynamic PMCs;dynpmcs> Dynamic PMCs or I<dynpmcs>.
+
+=head2 PIR Classes
+
+It's worth a quick diversion here to talk about the difference between a pure
+PIR class object, and a PMC. Even though classes written in PIR can inherit from
+an existing PMC type, they aren't all their own type of PMC. In fact, classes
+written in PIR are all of the Object PMC type. In order to add a new fundamental
+PMC type to Parrot, it needs to be written in C N<well, a superset of C anyway>
+and it needs to be compiled using the X<PMC compiler> PMC compiler.
+
+=head2 Writing PMCs
+
+In the strictest sense, PMCs are written in C and are compiled by your local
+C compiler into machine code for linking with libparrot or the parrot
+executable. However, Parrot's build process makes use of a special PMC compiler
+program that converts PMCs defined in a special C-like script to ordinary
+C code. The PMC compiler adds all the necessary boiler plate code and installs
+the PMC type into Parrot for use. The PMC script is like a macro superset
+N<although the functionality is a little bit more involved then is available
+in the normal C preprocessor> over the C language. All valid C is valid in
+PMC scripts, but there are also a few additions that help to make common tasks
+a little easier.
+
+The PMC script was born of conflicting necessities. The internals of Parrot
+are all written according to the ISO C89 standard for maximum portability.
+However, PIR and languages that are built on top of Parrot are typically
+object-oriented (or have some OO capabilities). PMCs are like classes,
+they have data and methods, and they can inherit from parent PMCs.
+
+C is low-level and portable, which is desirable. But Parrot needed some
+support for OO features that C doesn't have, and the C preprocessor
+can't support directly. To support the necessary features, and to make
+the task of writing PMCs just a little bit easier, the Parrot developers
+created a PMC compiler program that takes a special PMC script and converts
+it into standard ISO C89.
+
+=head3 PMC Files
+
+PMC files have a C<.pmc> file extension. They're written in a C-like
+language with a few additions to help with creating PMCs. PMC files do
+not natively allow POD documentation, so all such documentation must be
+enclosed in C</* */> comments. All PMC files that ship with Parrot
+include significant file-level and function-level documentation to help
+explain how the PMCs operate.
+
+=head3 C<pmclass> Definitions
+
+A PMC file can contain a single PMC class definition and any other helper
+functions or data structure definitions that are needed to support the
+PMC. To define a PMC class in the PMC file, you use the C<pmclass>
+statement. Everything outside the C<pmclass> definition will be ignored by
+the PMC compiler and passed through verbatim into the generated C<.c> file.
+Inside the C<pmclass> definition are going to be all the VTABLE and METHOD
+declarations for the PMC.
+
+A standard definition can contain a number of parts. Here's a pseudo-grammar
+for them:
+
+ pmclass CLASSNAME [extends PARENT]? [provides INTERFACE] [FLAGS]* {
+ /* Attributes defined here */
+
+ /* VTABLE and METHODs defined here. */
+
+ }
+
+The C<extends> keyword is optional, but allows us to specify that this
+PMC class is a subtype of the given type. If we have an C<extends>
+in the definition, we can use the C<SUPER> keyword throughout the PMC
+file to refer to the parent type.
+
+The C<FLAGS> are a series of flags that can be specified to determine
+how the PMC behaves and how it's constructed internally. The C<need_ext>
+flag assigns a special C<PMC_EXT> data structure to the PMC structure
+internally. C<PMC_EXT> is necessary to handle data sharing between threads
+or interpreters, storing attributes in the PMC, and a few other uses as
+well. The C<singleton> flag means that there can only be one instantiated
+object of this class. The C<is_ro> and C<has_ro> flags indicate that the
+PMC class is read-only or that it contains read-only data, respectively.
+The C<is_shared> flag indicates that the PMC is intended to be shared
+between multiple interpreters, and therefore special synchronization
+logic should be applied. The C<abstract> flag indicates that the PMC
+class cannot be instantiated directly, but can be inherited from by a
+non-abstract PMC class.
+
+The C<provides> keyword is used to show that the PMC provides certain
+standard interfaces. For instance, you can specify C<provides array>
+and then Parrot will enable us to write things like C<$P0[2]> in PIR
+code to access the PMC using integer indices. C<provides hash> means
+that we can use string and PMC keys to access values in the PMC. These
+C<provides> each correspond to a series of VTABLE interfaces that the
+PMC must provide, or must inherit. Without the necessary VTABLE
+interfaces available, Parrot may try to perform illegal operations and
+things will go badly. We'll talk about all the available C<provides>
+interfaces and the VTABLE interfaces that they must define.
+
+=head3 Attributes
+
+PMCs can be given a custom set of data field attributes using the C<ATTR>
+keyword. ATTR allows the PMC to be extended to contain custom data
+structures that are automatically managed by Parrot's memory subsystem.
+Here's an example:
+
+ pmclass Foo {
+ ATTR INTVAL bar;
+ ATTR PMC baz;
+
+ ...
+ }
+
+The attributes are stored in a custom data structure that can be accessed
+using a macro with the same name as the PMC, but all upper-case:
+
+ Parrot_Foo_Attributes * attrs = PARROT_FOO(SELF);
+ attrs->bar = 7; /* it's an INTVAL */
+ attrs->baz = pmc_new( ... ) /* it's a PMC */
+
+Notice how the type name of the attributes structure is C<Parrot_>,
+followed by the name of the PMC with the same capitalization as is used
+in the C<pmclass> definition, followed by C<_Attributes>. The macro to
+return this structure is C<PARROT_> followed by the name of the PMC in
+all caps.
+
+=head3 C<INTERP>, C<SUPER> and C<SELF>
+
+The PMC compiler enables us to use a few pre-defined variable names
+throughout the file to make things easier. The C<INTERP> keyword always
+contains a reference to the current interpreter structure. This keyword is
+included by default in all VTABLE interfaces and all PMC methods. It is not
+automatically included in any extra helper functions that you define in
+the PMC file.
+
+Here's an example of a VTABLE interface function:
+
+ VTABLE Foo(INVAR PMC, INVAR INTVAL)
+ {
+ ...
+ }
+
+The PMC compiler will convert this to the following C function definition:
+
+ void Foo(PARROT_INTERP, PMC *self, PMC *arg_1, INTVAL arg_2)
+ {
+ ...
+ }
+
+The C<interp> and C<self> variables are provided in all VTABLE interfaces,
+even though you don't have to define them explicitly in the PMC file.
+
+If the C<pmclass> definition uses the C<extends> keyword, a reference to
+a member of the parent class is also contained in the C<SUPER> variable.
+The C<SUPER()> function calls the VTABLE interface from the parent class.
+
+ VTABLE destroy()
+ {
+ SUPER(); /* Call the parent PMC's VTABLE */
+ }
+
+The PMC compiler also allows the use of "method syntax" for the C<SELF> and
+C<SUPER> variables:
+
+ SUPER.clone() /* Call the clone VTABLE interface on SUPER */
+ SELF.destroy() /* Call the destroy VTABLE interface on SELF */
+
+Or, you can call the VTABLE interfaces more directly:
+
+ VTABLE_clone(INTERP, SUPER)
+ VTABLE_destroy(INTERP, SELF)
+
+=head3 PMC Compiler
+
+The PMC compiler is a small program written in Perl 5 that's part of the
+normal Parrot build process. It converts all C<.pmc> files to C<.c> files
+for final compilation. The long-term goal for Parrot is to not be dependent
+on Perl 5 for configuration and building, but for now Perl 5 is required
+when building Parrot.
+
+=head2 VTABLE Function Definitions
+
+=head3 VTABLE Functions Parameters
+
+VTABLE functions are defined just like ordinary C functions, almost. Here's
+a normal definition for a VTABLE method:
+
+ VTABLE VTABLENAME (PARAMETERS) {
+ /* ordinary C here, almost */
+ }
+
+You can't just name your VTABLE functions anything you want. There is a
+predefined list of VTABLE function names, and you must name it exactly
+the same as the one you are trying to implement. The PARAMETERS list
+is pretty particular as well: Each VTABLE function type has a specific
+parameter list that must be implemented exactly or else the compiler
+will throw a warning.
+
+=head2 Methods
+
+VTABLES are standard, but they're rigid. They need to have the exact name
+that Parrot expects, and they need to have the exact function signature
+that Parrot expects too. VTABLES are responsible for the low-level basic
+access operations that all data types need to implement. However, to get
+more out of your PMCs, we need a more flexible want to interact with them.
+
+Enter methods, which are ways to extend the functionality of your PMC
+in ways that the PMC needs. Methods allow the developer to add all sorts
+of arbitrary functionality to a PMC that the VTABLE functions themselves
+cannot define.
+
+=head2 Dynpmcs
+
+=head3 Loading dynpmcs
+
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch08_dynops.pod (from r39796, trunk/docs/book/draft/ch08_dynops.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch08_dynops.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch08_dynops.pod)
@@ -0,0 +1,266 @@
+=pod
+
+=head1 Dynamic Opcodes
+
+Z<CHP-12>
+
+The smallest executable component is not the compilation unit or even the
+subroutine, but is actually the I<opcode>. Opcodes in Parrot, like opcodes in
+other machines (both virtual and physical), are individual instructions that
+implement low-level operations in the machine. In the world of
+microprocessors, the word "opcode" typically refers to the numeric identifier
+for each instructions. The human-readable word used in the associated assembly
+language is called the "mnemonic". An assembler, among other tasks, is
+responsible for converting mnemonics into opcodes for execution. In Parrot,
+instead of referring to an instruction by different names depending on what
+form it's in, we just call them all "opcodes".
+
+=head2 Opcodes
+
+Opcodes are the smallest logical execution element in Parrot. An
+individual opcode corresponds, in an abstract kind of way, with a single
+machine code instruction for a particular hardware processor
+architecture. Parrot is a pretty high-level virtual machine, and even though
+its opcodes represent the smallest bits of executable code in Parrot, they
+are hardly small or low-level by themselves. In fact, some Parrot opcodes
+implement some complex operations and algorithms. Other opcodes are more
+traditional, performing basic arithmetic and data manipulating operations.
+
+Parrot comes with about 1,200 opcodes total in a basic install. It also has a
+facility for dynamically loading additional opcode libraries, called
+C<dynops>, as needed.
+
+=head3 Opcode naming
+
+To the PIR and PASM programmers, opcodes appear to be polymorphic. That
+is, some opcodes appear to have multiple allowable argument formats. This is
+just an illusion, however. Parrot opcodes are not polymorphic, although
+certain features enable them to appear that way to the PIR programmer.
+Different argument list formats are detected during parsing and mapped to
+separate, unique opcode names.
+
+During the Parrot build process, opcode definitions called "ops files" are
+translated into C code prior to compilation. This translation process renames
+all ops to use unique names depending on their argument lists. An op "foo"
+that takes two PMCs and returns an integer would be renamed to C<foo_i_p_p>.
+Another op named "foo" that takes one floating point number and returns a
+string would be renamed to C<foo_s_n>. So, when we call the opcode "foo" from
+our PIR program, the PIR compiler will look at the list of arguments and
+call the appropriate opcode to handle it.
+
+=head2 Writing Opcodes
+
+Writing Opcodes, like writing PMCs, is done in a C-like language which is
+later compiled into C code by the X<opcode compiler> opcode compiler. The
+opcode script represents a thin overlay on top of ordinary C code: All
+valid C code is valid opcode script. There are a few neat additions that
+make writing opcodes easier. The C<INTERP> keyword, for instance, contains
+a reference to the current interpreter structure. C<INTERP> is always
+available when writing opcodes, even though it isn't defined anywhere.
+Opcodes are all defined with the C<op> keyword.
+
+Opcodes are written in files with the C<.ops> extension. The core
+operation files are stored in the C<src/ops/> directory.
+
+=head3 Opcode Parameters
+
+Each opcode can take any fixed number of input and output arguments. These
+arguments can be any of the four primary data types--INTVALs, PMCs, NUMBERS
+and STRINGs--but can also be one of several other types of values including
+LABELs, KEYs and INTKEYs.
+
+Each parameter can be an input, an output or both, using the C<in>, C<out>,
+and C<inout> keywords respectively. Here is an example:
+
+ op Foo (out INT, in NUM)
+
+This opcode could be called like this:
+
+ $I0 = Foo $N0 # in PIR syntax
+ Foo I0, N0 # in PASM syntax
+
+When Parrot parses through the file and sees the C<Foo> operation, it
+converts it to the real name C<Foo_i_n>. The real name of an opcode
+is its name followed by an underscore-separated ordered list of
+the parameters to that opcode. This is how Parrot appears to use
+polymorphism: It translates the overloaded opcode common names into
+longer unique names depending on the parameter list of that opcode. Here
+is a list of some of the variants of the C<add> opcode:
+
+ add_i_i # $I0 += $I1
+ add_n_n # $N0 += $N1
+ add_p_p # $P0 += $P1
+ add_i_i_i # $I0 = $I1 + $I2
+ add_p_p_i # $P0 = $P1 + $I0
+ add_p_p_n # $P0 = $P1 + $N0
+
+This isn't a complete list, but you should get the picture. Each different
+combination of parameters translates to a different unique operation, and
+each operation is remarkably simple to implement. In some cases, Parrot
+can even use its multi-method dispatch system to call opcodes which are
+heavily overloaded, or for which there is no exact fit but the parameters
+could be coerced into different types to complete the operation. For
+instance, attempting to add a STRING to a PMC might coerce the string into
+a numerical PMC type first, and then dispatch to the C<add_p_p_n> opcode.
+This is just an example, and the exact mechanisms may change as more opcodes
+are added or old ones are deleted.
+
+Parameters can be one of the following types:
+
+=over 4
+
+=item * INT
+
+A normal integer type, such as one of the I registers
+
+=item * NUM
+
+A floating point number, like is used in the N registers
+
+=item * STR
+
+A string, such as in a S register
+
+=item * PMC
+
+A PMC value, like a P register
+
+=item * KEY
+
+A key value. Something like C<[5 ; "Foo" ; 6 ; "Bar"]>. These are the same
+as indexes that we use in PMC aggregates.
+
+=item * INTKEY
+
+A basic key value that uses only integer values C<[1 ; 2 ; 3 ]>.
+
+=item * LABEL
+
+A label value, which represents a named statement in PIR or PASM code.
+
+=back
+
+In addition to these types, you need to specify the direction that data is
+moving through that parameter:
+
+=over 4
+
+=item * in
+
+The parameter is an input, and should be initialized before calling the op.
+
+=item * out
+
+The parameter is an output
+
+=item * inout
+
+The parameter is an input and an output. It should be initialized before
+calling the op, and it's value will change after the op executes.
+
+=item * invar
+
+The parameter is a reference type like a String or PMC, and it's internals
+might change in the call.
+
+=back
+
+=head3 Opcode Control Flow
+
+Some opcodes have the ability to alter control flow of the program they
+are in. There are a number of control behaviors that can be implemented,
+such as an unconditional jump in the C<goto> opcode, or a subroutine
+call in the C<call> code, or the conditional behavior implemented by C<if>.
+
+At the end of each opcode you can call a C<goto> operation to jump to the
+next opcode to execute. If no C<goto> is performed, control flow will
+continue like normal to the next operation in the program. In this way,
+opcodes can easily manipulate control flow. Opcode script provides a
+number of keywords to alter control flow:
+
+=over 4
+
+=item * NEXT()
+
+The keyword C<NEXT> contains the address of the next opcode in memory. At the
+end of a normal op you don't need to call C<goto NEXT()> because moving to the
+next opcode in the program is the default behavior of Parrot N<You can do
+this if you really want to, but it really wouldn't help you any>. The C<NEXT>
+keyword is frequently used in places like the C<invoke> opcode to create a
+continuation to the next opcode to return to after the subroutine returns.
+
+=item * ADDRESS()
+
+Jumps execution to the given address.
+
+ ADDRESS(x);
+
+Here, C<x> should be an C<opcode_t *> value of the opcode to jump to.
+
+=item * OFFSET()
+
+Jumps to the address given as an offset from the current address.
+
+ OFFSET(x)
+
+Here, C<x> is an offset in C<size_t> units that represents how far forward
+(positive) or how far backwards (negative) to jump to.
+
+=item * POP()
+
+C<POP> pops the next opcode address off the control stack. To put an address
+onto the control stack, use the C<PUSH> keyword instead. C<PUSH> takes a single
+C<opcode_t *> argument to store, and C<POP> returns a single C<opcode_ *>
+value.
+
+=back
+
+=head2 The Opcode Compiler
+
+As we've seen in our discussions above, ops have a number of transformations
+to go through before they can be become C code and compiled into Parrot.
+The various special variables like C<$1>, C<INTERP> and C<ADDRESS> need to be
+converted to normal variable values. Also, each runcore requires the ops be
+compiled into various formats: The slow and fast cores need the ops to be
+compiled into individual subroutines. The switch core needs all the ops to be
+compiled into a single function using a large C<switch> statement. The
+computed goto cores require the ops be compiled into a large function with a
+large array of label addresses.
+
+Parrot's opcode compiler is a tool that's tasked with taking raw opcode files
+with a C<.ops> extension and converting them into several different formats,
+all of which need to be syntactically correct C code for compilation.
+
+=head2 Dynops
+
+Parrot has about 1200 built-in opcodes. These represent operations which are
+sufficiently simple and fundamental, but at the same time are very common.
+However, these do not represent all the possible operations that some
+programmers are going to want to use. Of course, not all of those 1200 ops
+are unique, many of them are overloaded variants of one another. As an example
+there are about 36 variants of the C<set> opcode, to account for all the
+different types of values you may want to set to all the various kinds of
+registers. The number of unique operations therefore is much smaller then 1200.
+
+This is where I<dynops> come in. Dynops are dynamically-loadable libraries of
+ops that can be written and compiled separately from Parrot and loaded in at
+runtime. dynops, along with dynpmcs and runtime libraries are some of the
+primary ways that Parrot can be extended.
+
+Parrot ships with a small number of example dynops libraries in the file
+L<src/dynoplibs/>. These are small libraries of mostly nonsensical but
+demonstrative opcodes that can be used as an example to follow.
+
+Dynops can be written in a C<.ops> file like the normal built-in ops are.
+The ops file should use C<#include "parrot/extend.h"> in addition to any
+other libraries the ops need. They can be compiled into C using the opcode
+compiler, then compiled into a shared library using a normal C compiler. Once
+compiled, the dynops can be loaded into Parrot using the .loadlib directive.
+
+=cut
+
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch10_opcode_reference.pod (from r39796, trunk/docs/book/draft/ch10_opcode_reference.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch10_opcode_reference.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch10_opcode_reference.pod)
@@ -0,0 +1,2953 @@
+=pod
+
+=head1 Instruction Reference
+
+Z<CHP-10>
+
+This chapter contains a condensed reference to the Parrot virtual
+machine's native instruction set, generally called opcodes. All opcodes
+are valid in both PIR and PASM, and correspond to the bytecode
+instructions.
+
+For complete details on each opcode and the latest changes, read the
+documentation in F<docs/ops/>, or look at all the C<.ops> files in the
+F<ops/> directory.
+
+We've followed a few conventions. C<DEST> is always the register where
+the result of the operation is stored. Sometimes the original value of
+C<DEST> is one of the source values. C<VAL> indicates that the actual
+value might be a literal integer, float, or string, or a register
+containing an integer, float, string, or PMC. See the F<.ops> files
+for the combinations allowed with a particular operation.
+
+=head3 abs
+
+X<abs opcode (PASM)>
+
+ abs R<DEST>
+ abs R<DEST>, R<VAL>
+
+Return the absolute value of a number. If R<VAL> is left out, R<DEST>
+gets the absolute value of itself.
+
+I<Arguments: IR or NR or IR, I or IR, N or NR, I or NR, N>
+
+=head3 acos
+
+X<acos opcode (PASM)>
+
+ acos R<DEST>, R<VAL>
+
+The arc cosine of R<VAL> in radians.
+
+I<Arguments: NR, N or NR, I>
+
+=head3 add
+
+X<add opcode (PASM)>
+
+ add R<DEST>, R<VAL>
+ add R<DEST>, R<VAL>, R<VAL>
+
+Add two values and return the sum. If only one R<VAL>, add R<VAL> to
+R<DEST>.
+
+I<Arguments: IR, I or NR, I or NR, N or P, I or P, N or P, P or IR, I, I
+or NR, N, I or NR, N, N or P, P, I or P, P, N or P, P, P>
+
+=head3 addattribute
+
+X<addattribute opcode (PASM)>
+
+ addattribute R<CLASS>, R<ATTR>
+
+Add the attribute name R<ATTR> to class R<CLASS>.
+
+I<Arguments: P, S>
+
+=head3 addparent
+
+X<addparent opcode (PASM)>
+
+ addparent R<CLASS1>, R<CLASS2>
+
+Add class R<CLASS2> to the list of parent classes for R<CLASS1>.
+
+I<Arguments: P, P>
+
+=head3 and
+
+X<and opcode (PASM)>
+
+ and R<DEST>, R<VAL1>, R<VAL2>
+
+Logical AND. Return R<VAL1> if it's false; otherwise, return R<VAL2>.
+
+I<Arguments: IR, I, I or P, P, P>
+
+=head3 asec
+
+X<asec opcode (PASM)>
+
+ asec R<DEST>, R<VAL>
+
+The arc secant of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 asin
+
+X<asin opcode (PASM)>
+
+ asin R<DEST>, R<VAL>
+
+The arc sine of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 assign
+
+X<assign opcode (PASM)>
+
+ assign R<DEST>, R<VAL>
+
+Assign a value to a PMC.
+
+I<Arguments: SR, S or P, I or P, N or P, S or P, P>
+
+=head3 atan
+
+X<atan opcode (PASM)>
+
+ atan R<DEST>, R<VAL>
+ atan R<DEST>, R<VAL1>, R<VAL2>
+
+The arc tangent of R<VAL1> / R<VAL2> in radians (sign significant). If
+R<VAL2> is omitted, then just the arc tangent of R<VAL>.
+
+I<Arguments: NR, I or NR, N or NR, I, I or NR, I, N or NR, N, I or NR,
+N, N>
+
+=head3 band
+
+X<band opcode (PASM)>
+
+ band R<DEST>, R<VAL>
+ band R<DEST>, R<VAL>, R<VAL>
+
+Bitwise AND on two values. If only one R<VAL>, bitwise AND on R<DEST>
+and R<VAL>.
+
+I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
+
+=head3 bands
+
+X<bands opcode (PASM)>
+
+ bands R<DEST>, R<VAL>
+ bands R<DEST>, R<VAL>, R<VAL>
+
+Bitwise AND on two strings. If only one R<VAL>, bitwise AND on R<DEST>
+and R<VAL>.
+
+I<Arguments: SR, S or P, S or P, P or SR, S, S or P, P, S or P, P, P>
+
+=head3 bnot
+
+X<bnot opcode (PASM)>
+
+ bnot R<DEST>, R<VAL>
+
+Bitwise NOT on R<VAL>.
+
+I<Arguments: IR, I or P, P>
+
+=head3 bnots
+
+X<bnots opcode (PASM)>
+
+ bnots R<DEST>, R<VAL>
+
+Bitwise NOT on string R<VAL>.
+
+I<Arguments: SR, S or P, P>
+
+=head3 bor
+
+X<bor opcode (PASM)>
+
+ bor R<DEST>, R<VAL>, R<VAL>
+
+Bitwise OR on two values. If only one R<VAL>, bitwise OR on R<DEST>
+and R<VAL>.
+
+I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
+
+=head3 bors
+
+X<bors opcode (PASM)>
+
+ bors R<DEST>, R<VAL>, R<VAL>
+
+Bitwise OR on two strings. If only one R<VAL>, bitwise OR on R<DEST>
+and R<VAL>.
+
+I<Arguments: SR, S or P, S or P, P or SR, S, S or P, P, S or P, P, P>
+
+=head3 bounds
+
+X<bounds opcode (PASM)>
+
+ bounds R<INT>
+
+Toggle bytecode bounds checking in the interpreter (0 for off, any other
+value for on).
+
+I<Arguments: I>
+
+=head3 branch
+
+X<branch opcode (PASM)>
+
+ branch R<LABEL>
+
+Branch to a label. The label is calculated as a relative offset.
+
+I<Arguments: I>
+
+=head3 branch_cs
+
+X<branch_cs opcode (PASM)>
+
+ branch_cs R<FIXUP_ENTRY>
+
+Intersegment branch to the location of the given fixup table entry.
+
+I<Arguments: S>
+
+=head3 bsr
+
+X<bsr opcode (PASM)>
+
+ bsr R<LABEL>
+
+Branch to a label, like C<branch>, but also push the current location
+onto the call stack so C<ret> can return to it.
+
+I<Arguments: I>
+
+=head3 bxor
+
+X<bxor opcode (PASM)>
+
+ bxor R<DEST>, R<VAL>
+ bxor R<DEST>, R<VAL>, R<VAL>
+
+Bitwise XOR on two values. If only one R<VAL>, bitwise XOR on R<DEST>
+and R<VAL>.
+
+I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
+
+=head3 bxors
+
+X<bxors opcode (PASM)>
+
+ bxors R<DEST>, R<VAL>
+ bxors R<DEST>, R<VAL>, R<VAL>
+
+Bitwise XOR on two strings. If only one R<VAL>, bitwise XOR on R<DEST>
+and R<VAL>.
+
+I<Arguments: SR, S or P, S or P, P or SR, S, S or P, P, S or P, P, P>
+
+=head3 callmethod
+
+X<callmethod opcode (PASM)>
+
+ callmethod
+ callmethod R<METHODNAME>
+
+Call the method named R<METHODNAME> on the object stored in C<P2>
+according to the Parrot Calling Conventions. If no method name, pull the
+name from C<S0>.
+
+I<Arguments: S>
+
+=head3 callmethodcc
+
+X<callmethodcc opcode (PASM)>
+
+ callmethodcc
+ callmethodcc R<METHODNAME>
+
+Call the method named R<METHODNAME> on the object stored in C<P2>
+according to the Parrot Calling Conventions. If no method name, pull the
+name from C<S0>. Also create a return continuation and store it in
+C<P1>.
+
+I<Arguments: S>
+
+=head3 can
+
+X<can opcode (PASM)>
+
+ can R<DEST>, R<OBJECT>, R<METHODNAME>
+
+Return a true value if R<OBJECT> I<can> do the R<METHODNAME> method,
+otherwise return a false value.
+
+I<Arguments: IR, P, S>
+
+=head3 ceil
+
+X<ceil opcode (PASM)>
+
+ ceil R<DEST>
+ ceil R<DEST>, R<VAL>
+
+Set R<DEST> to the smallest integral value less than or equal to R<VAL>
+(if present) or itself (if not).
+
+I<Arguments: NR or IR, N or NR, N>
+
+=head3 checkevents
+
+X<checkevents opcode (PASM)>
+
+ checkevents
+
+Check the interpreter's task queue for unhandled events and run the associated
+event handlers.
+
+=head3 chopn
+
+X<chopn opcode (PASM)>
+
+ chopn R<DEST>, R<VAL1>
+ chopn R<DEST>, R<VAL1>, R<VAL2>
+
+Remove R<VAL2> number of characters from string R<VAL1>. If no
+R<VAL2>, remove R<VAL> number of characters from string R<DEST>.
+
+I<Arguments: SR, I or SR, S, I>
+
+=head3 chr
+
+X<chr opcode (PASM)>
+
+ chr R<DEST>, R<INT>
+
+Return the character represented by the given number.
+
+I<Arguments: SR, I>
+
+=head3 class
+
+X<class opcode (PASM)>
+
+ class R<CLASS>, R<OBJECT>
+
+Return the R<CLASS> of the given R<OBJECT>.
+
+I<Arguments: P, P>
+
+=head3 clear_eh
+
+X<clear_eh>
+
+ clear_eh
+
+Clear the most recent exception handler.
+
+See also: C<set_eh>, C<throw>.
+
+=head3 clearX
+
+X<cleari opcode (PASM)>
+X<clearn opcode (PASM)>
+X<clearp opcode (PASM)>
+X<clears opcode (PASM)>
+
+ cleari
+ clearn
+ clearp
+ clears
+
+Clear all registers of the given type ("i" = integer, "n" = float, "p"
+= PMC, "s" = string). Integer and float registers clear to zero; string
+and PMC registers clear to NULL.
+
+=head3 clone
+
+X<clone opcode (PASM)>
+
+ clone R<DEST>, R<VAL>
+
+Clone (deep copy) a string or PMC and return the result.
+
+I<Arguments: SR, S or P, P>
+
+=head3 close
+
+X<close opcode (PASM)>
+
+ close R<DEST>
+
+Close the filehandle in the given register.
+
+I<Arguments: P>
+
+=head3 cmod
+
+X<cmod opcode (PASM)>
+
+ cmod R<DEST>, R<VAL1>, R<VAL2>
+
+C's built-in mod operator.
+
+See also C<mod>.
+
+I<Arguments: IR, I, I or NR, N, N or P, P, I or P, P, N or P, P, P>
+
+=head3 cmp
+
+X<cmp (comparison);opcode (PASM)>
+
+ cmp R<DEST>, R<VAL1>, R<VAL2>
+
+Set R<DEST> to 1 if R<VAL1> is greater then R<VAL2>, to -1 if it's less then
+R<VAL2> or to zero if both are equal. If R<VAL1> and R<VAL2> are both PMCs,
+then the type of comparison depends on R<VAL1>.
+
+I<Arguments: IR, I, I or IR, N, N or IR, S, S or IR, P, I or IR, P, N
+IR, P, S or IR, P, P>
+
+=head3 cmp_num
+
+X<cmp_num opcode (PASM)>
+
+ cmp_num R<DEST>, R<VAL1>, R<VAL2>
+
+Like C<cmp>, but forces numeric comparison.
+
+I<Arguments: IR, P, P>
+
+=head3 cmp_str
+
+X<cmp_str opcode (PASM)>
+
+ cmp_str R<DEST>, R<VAL1>, R<VAL2>
+
+Like C<cmp>, but forces string comparison.
+
+I<Arguments: IR, P, P>
+
+=head3 cmp_pmc
+
+X<cmp_pmc opcode (PASM)>
+
+ cmp_pmc R<DEST>, R<VAL1>, R<VAL2>
+
+Like C<cmp>, but places a PMC in R<DEST>. This opcode is useful for avoiding
+semipredicate problems in HLLs where two PMCs are not always comparable.
+
+I<Arguments: P, P, P>
+
+=head3 collect
+
+X<collect opcode (PASM)>
+
+ collect
+
+Trigger a garbage collection (GC) run.
+
+=head3 collectoff
+
+X<collectoff opcode (PASM)>
+
+ collectoff
+
+Disable garbage collection runs (nestable).
+
+=head3 collecton
+
+X<collecton opcode (PASM)>
+
+ collecton
+
+Re-enable garbage collection runs.
+
+=head3 compile
+
+X<compile opcode (PASM)>
+
+ compile R<DEST>, R<COMPILER>, R<SOURCE>
+
+Compile a string of source code with a given compiler PMC and store
+the result.
+
+I<Arguments: P, P, S>
+
+=head3 compreg
+
+X<compreg opcode (PASM)>
+
+ compreg R<DEST>, R<TYPE>
+
+Return a compiler PMC for a particular type of source code.
+
+I<Arguments: P, S>
+
+ compreg R<TYPE>, R<SUB>
+
+Register R<SUB> as a compiler for language R<TYPE>.
+
+I<Arguments: S, P>
+
+=head3 concat
+
+X<concat opcode (PASM)>
+
+ concat R<DEST>, R<VAL>
+ concat R<DEST>, R<VAL>, R<VAL>
+
+Concatenate two strings. If only one R<VAL>, concatenate R<VAL> onto
+R<DEST>.
+
+I<Arguments: SR, S or SR, S, S or P, P, S or P, P, P>
+
+=head3 cos
+
+X<cos opcode (PASM)>
+
+ cos R<DEST>, R<VAL>
+
+The cosine of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 cosh
+
+X<cosh opcode (PASM)>
+
+ cosh R<DEST>, R<VAL>
+
+The hyperbolic cosine of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 debug
+
+X<debug opcode (PASM)>
+
+ debug R<FLAG>
+
+Toggle debugging in the interpreter (0 for off, any other value for on).
+
+I<Arguments: I>
+
+=head3 dec
+
+X<dec opcode (PASM)>
+
+ dec R<DEST>
+
+Decrement a value by 1.
+
+I<Arguments: I or N or P>
+
+=head3 decodelocaltime
+
+X<decodelocaltime opcode (PASM)>
+
+ decodelocaltime R<DEST>, R<VAL>
+
+Set R<DEST> to a new array which represents the decoded time of the
+given epoch-seconds value shifted to local time.
+
+I<Arguments: P, I>
+
+=head3 decodetime
+
+X<decodetime opcode (PASM)>
+
+ decodetime R<DEST>, R<VAL>
+
+Set R<DEST> to a new array which represents the decoded time of the
+given epoch-seconds value.
+
+I<Arguments: P, I>
+
+=head3 defined
+
+X<defined opcode (PASM)>
+
+ defined R<DEST>, R<PMC>
+ defined R<DEST>, R<PMC>[R<KEY>]
+
+Test a keyed PMC value for definedness. If no R<KEY>, test a PMC for
+definedness.
+
+I<Arguments: IR, P>
+
+=head3 delete
+
+X<delete opcode (PASM)>
+
+ delete R<DEST>[R<KEY>]
+
+Delete a keyed value from an aggregate PMC.
+
+I<Arguments: P>
+
+=head3 delprop
+
+X<delprop opcode (PASM)>
+
+ delprop R<PMC>, R<NAME>
+
+Delete a named property from a PMC.
+
+I<Arguments: P, S>
+
+See also: C<setprop> and C<getprop>.
+
+=head3 deref
+
+X<deref opcode (PASM)>
+
+ deref R<DEST>, R<REF>
+
+Set R<DEST> to the PMC that R<REF> refers to.
+
+I<Arguments: P, P>
+
+=head3 die_hard
+
+X<die_hard opcode (PASM)>
+
+ die_hard R<LEVEL>, R<ERROR>
+
+Die at a given level of severity, and with the given error code.
+
+I<Arguments: I, I>
+
+See also: C<exit>.
+
+=head3 div
+
+X<div opcode (PASM)>
+
+ div R<DEST>, R<VAL>
+ div R<DEST>, R<VAL1>, R<VAL2>
+
+Divide R<VAL1> by R<VAL2>. If R<VAL2> is left out, divide R<DEST> by
+R<VAL>.
+
+I<Arguments: IR, I or NR, I or NR, N or P, I or P, N or P, P or IR, I, I
+or NR, N, I or NR, N, N or P, P, I or P, P, N or P, P, P>
+
+=head3 dlfunc
+
+X<dlfunc opcode (PASM)>
+
+ dlfunc R<DEST>, R<LIBRARY>, R<SYMBOL>, R<SIGNATURE>
+
+Look up a symbol in a dynamic link library PMC and create a subroutine
+PMC for that symbol with the given signature.
+
+I<Arguments: P, P, S, S>
+
+=head3 dlvar
+
+X<dlvar opcode (PASM)>
+
+ dlvar R<DEST>, R<LIBRARY>, R<SYMBOL>
+
+Look up a symbol in a dynamic link library PMC and create a
+PMC for that symbol.
+
+I<Arguments: P, P, S>
+
+=head3 does
+
+X<does opcode (PASM)>
+
+ does R<DEST>, R<OBJECT>, R<VAL>
+
+Return a true value if R<OBJECT> I<does> provide the interface R<VAL>,
+otherwise return a false value.
+
+I<Arguments: I, P, S>
+
+=head3 downcase
+
+X<downcase opcode (PASM)>
+
+ downcase R<DEST>
+ downcase R<DEST>, R<VAL>
+
+Create a copy of the string in R<VAL> with all characters converted to
+lower case, and store it in R<DEST>. If R<VAL> is omitted, convert and
+replace the string in R<DEST>.
+
+I<Arguments: S or S, S>
+
+See also: C<upcase>, C<titlecase>.
+
+=head3 end
+
+X<end opcode (PASM)>
+
+ end
+
+End execution within the current code segment or halt the interpreter
+if in the main code segment.
+
+=head3 enternative
+
+X<enternative opcode (PASM)>
+
+ enternative
+
+Run the C<run_native> C function.
+
+=head3 eq
+
+X<eq opcode (PASM)>
+
+ eq R<VAL>, R<VAL>, R<LABEL>
+
+Jump to a label if the two values are equal.
+
+I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC
+or P, S, IC or P, P, IC>
+
+=head3 eq_addr
+
+X<eq_addr opcode (PASM)>
+
+ eq_addr R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> and R<VAL2> point to the same string or PMC.
+Note that this op compares the addresses of the two strings or PMCs,
+not simply their values.
+
+I<Arguments: S, S, IC or P, P, IC>
+
+=head3 eq_num
+
+X<eq_num opcode (PASM)>
+
+ eq_num R<VAL>, R<VAL>, R<LABEL>
+
+Jump to a label if the two values are numerically equal.
+
+I<Arguments: P, P, IC>
+
+=head3 eq_str
+
+X<eq_str opcode (PASM)>
+
+ eq_str R<VAL>, R<VAL>, R<LABEL>
+
+Jump to a label if the two strings are equal.
+
+I<Arguments: P, P, IC>
+
+=head3 err
+
+X<err opcode (PASM)>
+
+ err R<DEST>
+ err R<DEST>, R<CODE>
+
+Return the system error code to an integer destination or the system
+error message to a string destination. The two-argument version returns
+the system error message for a given code.
+
+I<Arguments: IR or SR or SR, I>
+
+=head3 errorsoff
+
+X<errorsoff opcode (PASM)>
+
+ errorsoff R<VAL>
+
+Turn off errors of type R<VAL>.
+
+I<Arguments: I>
+
+=head3 errorson
+
+X<errorson opcode (PASM)>
+
+ errorson R<VAL>
+
+Turn on errors of type R<VAL>.
+
+I<Arguments: I>
+
+=head3 exchange
+
+X<exchange opcode (PASM)>
+
+ exchange R<REG>, R<REG>
+
+Exchange the contents of two registers.
+
+I<Arguments: IR, IR or NR, NR or SR, SR or P, P>
+
+=head3 exists
+
+X<exists opcode (PASM)>
+
+ exists R<DEST>, R<PMC>[R<KEY>]
+
+Test a PMC key for existence.
+
+I<Arguments: IR, P>
+
+=head3 exit
+
+X<exit opcode (PASM)>
+
+ exit R<STATUS>
+
+Exit the interpreter with a given R<STATUS>. (For extended exit status,
+throw an exception with severity C<EXCEPT_exit>.)
+
+I<Arguments: I>
+
+See also: C<throw>, C<die_hard>.
+
+=head3 exp
+
+X<exp opcode (PASM)>
+
+ exp R<DEST>, R<VAL>
+
+Base of the natural logarithm, I<e>, to the power of R<VAL>.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 exsec
+
+X<exsec opcode (PASM)>
+
+ exsec R<DEST>, R<VAL>
+
+The exsecant of R<VAL> in radians.
+
+I<Arguments: NR, N>
+
+=head3 fact
+
+X<fact opcode (PASM)>
+
+ fact R<DEST>, R<INT>
+
+Return the factorial of R<INT>.
+
+I<Arguments: IR, I or NR, I>
+
+=head3 fdopen
+
+X<fdopen opcode (PASM)>
+
+ fdopen R<DEST>, R<INT>, R<MODE>
+
+Get a FileHandle object for handle R<INT> with open mode R<MODE>.
+
+I<Arguments: P, I, S>
+
+=head3 find_chartype
+
+X<find_chartype opcode (PASM)>
+
+ find_chartype R<DEST>, R<NAME>
+
+Find the chartype named R<NAME> and return its number in R<DEST>.
+
+I<Arguments: IR, S>
+
+=head3 find_encoding
+
+X<strings;encoding>
+X<find_encoding opcode (PASM)>
+
+ find_encoding R<DEST>, R<NAME>
+
+Find the encoding named R<NAME> and return its number in R<DEST>.
+
+I<Arguments: IR, S>
+
+=head3 find_global
+
+X<find_global opcode (PASM)>
+
+ find_global R<DEST>, R<NAME>
+
+Return a global variable with the given name.
+
+I<Arguments: P, S>
+
+ find_global R<DEST>, R<NAMESPACE>, R<NAME>
+
+Return a global variable with the given name from the given namespace.
+
+I<Arguments: P, S, S or P, P, S>
+
+See also: C<store_global>.
+
+=head3 find_lex
+
+X<find_lex opcode (PASM)>
+
+ find_lex R<DEST>, R<NAME>
+ find_lex R<DEST>, R<DEPTH>, R<NAME>
+ find_lex R<DEST>, R<DEPTH>, R<POSITION>
+
+Return the lexical variable of the given name from a lexical
+scratchpad. If R<DEPTH> is provided, only return a variable from the
+scratchpad at that depth. A find by position returns the variable at a
+particular position in the scratchpad.
+
+I<Arguments: P, S or P, I, S or P, I, I>
+
+See also: C<store_lex>.
+
+=head3 find_method
+
+X<find_method opcode (PASM)>
+
+ find_method R<DEST>, R<PMC>, R<NAME>
+
+Look up a method by name in a PMC's vtable. Return a method PMC.
+
+I<Arguments: P, P, S>
+
+=head3 find_type
+
+X<find_type opcode (PASM)>
+
+ find_type R<DEST>, R<NAME>
+
+Find the integer identifier for a PMC type or native Parrot datatype by name.
+
+I<Arguments: IR, S>
+
+See also: C<typeof>.
+
+=head3 findclass
+
+X<findclass opcode (PASM)>
+
+ findclass R<DEST>, R<NAME>
+
+Return 1 if the class R<NAME> exists, and 0 otherwise.
+
+I<Arguments: IR, S>
+
+See also: C<typeof>.
+
+=head3 floor
+
+X<floor opcode (PASM)>
+
+ floor R<DEST>
+ floor R<DEST>, R<VAL>
+
+Return the largest integral value less than or equal to R<VAL> (if
+present) or itself (if not).
+
+I<Arguments: NR or IR, N or NR, N>
+
+=head3 foldup
+
+X<foldup opcode (PASM)>
+
+ foldup R<DEST>
+ foldup R<DEST>, R<SKIP>
+
+Return a new array holding all passed subroutine parameters. R<SKIP>
+defines an optional offset.
+
+I<Arguments: P or P, I>
+
+=head3 freeze
+
+X<freeze opcode (PASM)>
+
+ freeze R<DEST>, R<VAL>
+
+Create a frozen image R<DEST> from PMC R<VAL>.
+
+I<Arguments: SR, P>
+
+See also: C<thaw>.
+
+=head3 gc_debug
+
+X<gc_debug opcode (PASM)>
+
+ gc_debug R<INT>
+
+Toggle garbage collection debugging in the interpreter (0 for off, any
+other value for on).
+
+I<Arguments: I>
+
+=head3 gcd
+
+X<gcd opcode (PASM)>
+
+ gcd R<DEST>, R<VAL>, R<VAL>
+
+Return the greatest common divisor of two values.
+
+I<Arguments: IR, I, I or IR, N, N>
+
+=head3 ge
+
+X<ge (greater than or equal);opcode (PASM)>
+
+ ge R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is greater than or equal to R<VAL2>.
+
+I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC
+or P, S, IC or P, P, IC>
+
+=head3 ge_num
+
+X<ge_num opcode (PASM)>
+
+ ge_num R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is numerically greater than or equal to R<VAL2>.
+
+I<Arguments: P, P, IC>
+
+=head3 ge_str
+
+X<ge_str opcode (PASM)>
+
+ ge_str R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is stringwise greater than or equal to R<VAL2>.
+
+I<Arguments: P, P, IC>
+
+=head3 get_addr
+
+X<get_addr opcode (PASM)>
+
+ get_addr R<DEST>, R<SUB>
+
+Get the absolute address of a subroutine PMC.
+
+I<Arguments: IR, P>
+
+See also: C<set_addr>.
+
+=head3 getattribute
+
+X<getattribute opcode (PASM)>
+
+ getattribute R<DEST>, R<OBJECT>, R<OFFS>
+
+Get a reference to attribute number R<OFFS> from object R<OBJECT>.
+
+I<Arguments: P, P, I>
+
+See also: C<setattribute>, C<classoffset>.
+
+=head3 get_class
+
+X<get_class opcode (PASM)>
+
+ get_class R<DEST>, R<NAME>
+
+Return the class PMC of the given name.
+
+I<Arguments: P, S>
+
+=head3 getfile
+
+X<getfile opcode (PASM)>
+
+ getfile R<DEST>
+
+Return the name of the current file.
+
+I<Arguments: SR>
+
+=head3 getinterp
+
+X<getinterp opcode (PASM)>
+
+ getinterp R<DEST>
+
+Get a PMC representing the current interpreter.
+
+I<Arguments: P>
+
+=head3 getline
+
+X<getline opcode (PASM)>
+
+ getline R<DEST>
+
+Return the current line number.
+
+I<Arguments: IR>
+
+=head3 getpackage
+
+X<getpackage opcode (PASM)>
+
+ getpackage R<DEST>
+
+Return the current package name.
+
+I<Arguments: SR>
+
+=head3 getprop
+
+X<getprop opcode (PASM)>
+
+ getprop R<DEST>, R<NAME>, R<PMC>
+
+Return the value of a named property on a PMC.
+
+I<Arguments: P, S, P>
+
+See also: C<setprop> and C<prophash>.
+
+=head3 getstd*
+
+X<getstderr opcode (PASM)>
+X<getstdin opcode (PASM)>
+X<getstdout opcode (PASM)>
+
+ getstderr R<DEST>
+ getstdin R<DEST>
+ getstdout R<DEST>
+
+Get a FileHandle object for the given standard handle.
+
+I<Arguments: P>
+
+=head3 gmtime
+
+X<gmtime opcode (PASM)>
+
+ gmtime R<DEST>, R<VAL>
+
+Take the integer, which represents GMT epoch-seconds, and turn it into a
+formatted string.
+
+I<Arguments: SR, I>
+
+See also: C<localtime>.
+
+=head3 gt
+
+X<gt opcode (PASM)>
+
+ gt R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is greater than R<VAL2>.
+
+I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC or
+P, S, IC or P, P, IC>
+
+=head3 gt_num
+
+X<gt_num opcode (PASM)>
+
+ gt_num R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is numerically greater than R<VAL2>.
+
+I<Arguments: P, P, IC>
+
+=head3 gt_str
+
+X<gt_str opcode (PASM)>
+
+ gt_str R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is stringwise greater than R<VAL2>.
+
+I<Arguments: P, P, IC>
+
+=head3 hav
+
+X<hav opcode (PASM)>
+
+ hav R<DEST>, R<VAL>
+
+The haversine of R<VAL> in radians.
+
+I<Arguments: NR, N>
+
+=head3 if
+
+X<if (conditional);opcode (PASM)>
+
+ if R<CONDITION>, R<LABEL>
+
+Jump to a label if the condition is a true value.
+
+I<Arguments: I, IC or N, IC or S, IC or P, IC>
+
+=head3 inc
+
+X<inc opcode (PASM)>
+
+ inc R<DEST>
+
+Increment a value by one.
+
+I<Arguments: IR or NR or P>
+
+=head3 index
+
+X<index opcode (PASM)>
+
+ index R<DEST>, R<STRING>, R<SEARCH>
+ index R<DEST>, R<STRING>, R<SEARCH>, R<POS>
+
+Return the position of the first occurrence of the string R<SEARCH> in
+the string R<STRING>, starting at the position R<POS>. If the starting
+position is unspecified, start at the beginning of the string.
+
+I<Arguments: IR, S, S or IR, S, S, I>
+
+=head3 interpinfo
+
+X<interpinfo opcode (PASM)>
+
+ interpinfo R<DEST>, R<FLAG>
+
+Return information about the interpreter. An integer flag selects
+which information to return, as listed in
+Table 10-1.
+
+=begin table picture Interpinfo flags
+
+Z<CHP-10-TABLE-1>
+
+=headrow
+
+=row
+
+=cell Flag
+
+=cell Returns
+
+=bodyrows
+
+=row
+
+=cell C<1>
+
+=cell Allocated memory, in bytes.
+
+=row
+
+=cell C<2>
+
+=cell Number of GC mark runs performed.
+
+=row
+
+=cell C<3>
+
+=cell Number of GC runs performed.
+
+=row
+
+=cell C<4>
+
+=cell Number of active PMCs.
+
+=row
+
+=cell C<5>
+
+=cell Number of active buffers.
+
+=row
+
+=cell C<6>
+
+=cell Number of allocated PMCs.
+
+=row
+
+=cell C<7>
+
+=cell Number of allocated buffers.
+
+=row
+
+=cell C<8>
+
+=cell Number of new PMC or buffer headers allocated since last mark run.
+
+=row
+
+=cell C<9>
+
+=cell Number of memory blocks allocated since last GC run.
+
+=row
+
+=cell C<10>
+
+=cell Amount of memory copied during GC runs, in bytes.
+
+=end table
+
+I<Arguments: IR, I>
+
+=head3 invoke
+
+X<invoke opcode (PASM)>
+
+ invoke
+ invoke R<SUB>
+
+Call a subroutine, coroutine, or continuation stored in a PMC. If no
+PMC register is specified, it calls the subroutine in C<P0> and uses
+the standard calling conventions. Otherwise, no calling convention is
+defined. Also C<yield> from a coroutine.
+
+I<Arguments: P>
+
+=head3 invokecc
+
+X<invokecc opcode (PASM)>
+
+ invokecc
+ invokecc R<SUB>
+
+Call a subroutine like C<invoke>, but also generate a return
+continuation in C<P1>.
+
+I<Arguments: P>
+
+See also: C<updatecc>.
+
+=head3 isa
+
+X<isa opcode (PASM)>
+
+ isa R<DEST>, R<OBJECT>, R<CLASS>
+
+Return a true value if R<OBJECT> I<isa> member of class R<CLASS>, or of
+one of its subclasses, otherwise return a false value.
+
+I<Arguments: IR, P, S>
+
+=head3 isnull
+
+X<isnull opcode (PASM)>
+
+ isnull R<VAL>, R<LABEL>
+
+Jump to R<LABEL> if the given PMC is a NULL PMC.
+
+I<Arguments: P, IC>
+
+=head3 join
+
+X<join opcode (PASM)>
+
+ join R<DEST>, R<DELIM>, R<ARRAY>
+
+Create a new string by joining all elements from array with the given
+delimiter.
+
+I<Arguments: SR, S, P>
+
+=head3 jsr
+
+X<jsr opcode (PASM)>
+
+ jsr R<ADDRESS>
+
+Jump to an address, like C<jump>, but also push the current location
+onto the call stack so C<ret> can return to it.
+
+I<Arguments: I>
+
+=head3 jump
+
+X<jump opcode (PASM)>
+
+ jump R<ADDRESS>
+
+Jump to a specified absolute address.
+
+I<Arguments: I>
+
+See also: C<set_addr>.
+
+=head3 lcm
+
+X<lcm opcode (PASM)>
+
+ lcm R<DEST>, R<VAL>, R<VAL>
+
+Return the least common multiple of two values.
+
+I<Arguments: IR, I, I or NR, I, I>
+
+=head3 le
+
+X<le (less than or equal);opcode (PASM)>
+
+ le R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is less than or equal to R<VAL2>.
+
+I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC or
+P, S, IC or P, P, IC>
+
+=head3 le_num
+
+X<le_num opcode (PASM)>
+
+ le_num R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is numerically less than or equal to R<VAL2>.
+
+I<Arguments: P, P, IC>
+
+=head3 le_str
+
+X<le_str opcode (PASM)>
+
+ le_str R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is stringwise less than or equal to R<VAL2>.
+
+I<Arguments: P, P, IC>
+
+=head3 length
+
+X<length opcode (PASM)>
+
+ length R<DEST>, R<STRING>
+
+Return the character length of a string.
+
+I<Arguments: IR, S>
+
+=head3 ln
+
+X<ln opcode (PASM)>
+
+ ln R<DEST>, R<VAL>
+
+The natural logarithm of R<VAL>.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 load_bytecode
+
+X<load_bytecode>
+
+ load_bytecode R<FILE>
+
+Load Parrot bytecode from a file.
+
+I<Arguments: S>
+
+=head3 loadlib
+
+X<loadlib opcode (PASM)>
+
+ loadlib R<DEST>, R<LIBRARY>
+
+Load a dynamic link library by name and store it in a PMC.
+
+I<Arguments: P, S>
+
+See also: C<dlfunc>.
+
+=head3 localtime
+
+X<localtime opcode (PASM)>
+
+ localtime R<DEST>, R<VAL>
+
+Take the integer, which represents GMT epoch-seconds, and turn it into a
+formatted string after adjusting to localtime.
+
+I<Arguments: SR, I>
+
+See also: C<gmtime>.
+
+=head3 log10
+
+X<log10 opcode (PASM)>
+
+ log10 R<DEST>, R<VAL>
+
+The base 10 logarithm of R<VAL>.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 log2
+
+X<log2 opcode (PASM)>
+
+ log2 R<DEST>, R<VAL>
+
+The base 2 logarithm of R<VAL>.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 lsr
+
+X<lsr opcode (PASM)>
+
+ lsr R<DEST>, R<BITS>
+ lsr R<DEST>, R<VAL>, R<BITS>
+
+Logically shift a value right by a given number of bits.
+
+I<Arguments: IR, I or IR, I, I>
+
+=head3 lt
+
+X<lt (less than);opcode (PASM)>
+
+ lt R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is less than R<VAL2>.
+
+I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC or
+P, S, IC or P, P, IC>
+
+=head3 lt_num
+
+X<lt_num opcode (PASM)>
+
+ lt_num R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is numerically less than R<VAL2>.
+
+I<Arguments: P, P, IC>
+
+=head3 lt_str
+
+X<lt_str opcode (PASM)>
+
+ lt_str R<VAL1>, R<VAL2>, R<LABEL>
+
+Jump to a label if R<VAL1> is stringwise less than R<VAL2>.
+
+I<Arguments: P, P, IC>
+
+=head3 mod
+
+X<mod opcode (PASM)>
+
+ mod R<DEST>, R<VAL>
+ mod R<DEST>, R<VAL1>, R<VAL2>
+
+Divide R<VAL1> by R<VAL2> and return the remainder. If R<VAL2> is omitted,
+divide R<DEST> by R<VAL>. The operation is defined as:
+
+ x mod y = x - y * floor(x / y)
+
+I<Arguments: P, I or IR, I, I or NR, N, N or P, P, I or P, P, N>
+
+See also: C<cmod>.
+
+=head3 mul
+
+X<mul opcode (PASM)>
+
+ mul R<DEST>, R<VAL>
+ mul R<DEST>, R<VAL>, R<VAL>
+
+Multiply two values and return the result. If only one R<VAL>,
+multiply R<DEST> by R<VAL>.
+
+I<Arguments: IR, I or NR, I or NR, N or P, I or P, N or P, P or IR, I,
+I or NR, N, I or NR, N, N or P, P, I or P, P, N or P, P, P>
+
+=head3 ne
+
+X<ne (not equal);opcode (PASM)>
+
+ ne R<VAL>, R<VAL>, R<LABEL>
+
+Jump to a label if the two values are not equal.
+
+I<Arguments: I, I, IC or N, N, IC or S, S, IC or P, I, IC or P, N, IC or
+P, S, IC or P, P, IC>
+
+=head3 ne_addr
+
+X<ne_addr opcode (PASM)>
+
+ ne_addr R<VAL>, R<VAL>, R<LABEL>
+
+Jump to a label if R<VAL1> and R<VAL2> do not point to the same string
+or PMC.
+
+I<Arguments: S, S, IC or P, P, IC>
+
+=head3 ne_num
+
+X<ne_num opcode (PASM)>
+
+ ne_num R<VAL>, R<VAL>, R<LABEL>
+
+Jump to a label if the two values are numerically different.
+
+I<Arguments: P, P, IC>
+
+=head3 ne_str
+
+X<ne_str opcode (PASM)>
+
+ ne_str R<VAL>, R<VAL>, R<LABEL>
+
+Jump to a label if the two strings are not equal.
+
+I<Arguments: P, P, IC>
+
+=head3 needs_destroy
+
+X<needs_destroy opcode (PASM)>
+
+ needs_destroy R<PMC>
+
+Mark the PMC as requiring timely destruction.
+
+I<Arguments: P>
+
+See also: C<sweep>.
+
+=head3 neg
+
+X<neg opcode (PASM)>
+
+ neg R<DEST>
+ neg R<DEST>, R<VAL>
+
+Return the negative of a number. If there is no R<VAL>, R<DEST> is the
+negative of itself.
+
+I<Arguments: IR or NR or P or IR, I or NR, N or P, P>
+
+=head3 new
+
+X<new opcode (PASM)>
+
+ new R<DEST>, R<TYPE>
+ new R<DEST>, R<TYPE>, R<INITIALIZE>
+ new R<DEST>, R<TYPE>, R<INITIALIZE>, R<PROPS>
+
+Create a new PMC of type R<TYPE>. R<INITIALIZE> is an array PMC
+containing initialization data for the new PMC. R<PROPS> is a property hash.
+
+I<Arguments: P, I or P, I, P or P, I, P, P>
+
+ new R<DEST>
+ new R<DEST>, R<LENGTH>
+ new R<DEST>, R<LENGTH>, R<ENCODING>
+ new R<DEST>, R<LENGTH>, R<ENCODING>, R<TYPE>
+
+Allocate a new empty string with a given R<LENGTH>, R<ENCODING>, and
+R<TYPE>.
+
+I<Arguments: SR or SR, I or SR, I, I or SR, I, I, I>
+
+=head3 new_callback
+
+X<new_callback opcode (PASM)>
+
+ new_callback R<DEST>, R<SUB>, R<DATA>, R<SIG>
+
+Create a callback stub R<DEST> for a PASM subroutine R<SUB> with user
+data R<DATA> and function signature R<SIG>.
+
+I<Arguments: P, P, P, S>
+
+=head3 new_pad
+
+X<new_pad opcode (PASM)>
+
+ new_pad R<DEPTH>
+ new_pad R<DEST>, R<DEPTH>
+
+Create a new lexical scratchpad. If a destination PMC is provided,
+store the pad in the PMC, otherwise push it onto the pad stack.
+R<DEPTH> specifies the static nesting depth for the pad (lower static
+depths are copied from the current static nesting).
+
+I<Arguments: I or P, I>
+
+=head3 newclass
+
+X<newclass opcode (PASM)>
+
+ newclass R<DEST>, R<NAME>
+
+Create a new class with the given name.
+
+I<Arguments: P, S>
+
+=head3 newsub
+
+X<newsub opcode (PASM)>
+
+ newsub R<DEST>, R<CLASS>, R<LABEL>
+
+Generate a new subroutine object of the given R<CLASS>, located at the
+given R<LABEL>, and store the object in the destination PMC.
+
+I<Arguments: P, I, IC>
+
+ newsub R<CLASS>, R<RETCLASS>, R<LABEL>, R<RETADDR>
+
+Generate a new subroutine object of the given R<CLASS>, located at the
+given R<LABEL>, and store the object in C<P0>. Also generate a return
+continuation of class R<RETCLASS> with the return address R<RETADDR> and
+store it in C<P1>.
+
+I<Arguments: I, I, IC, IC>
+
+=head3 noop
+
+X<noop opcode (PASM)>
+
+ noop
+
+Do nothing.
+
+=head3 not
+
+X<not opcode (PASM)>
+
+ not R<DEST>, R<VAL>
+
+Logical NOT. True if R<VAL> is false.
+
+I<Arguments: IR, I or P, P>
+
+=head3 null
+
+X<null opcode (PASM)>
+
+ null R<DEST>
+
+Set R<DEST> (which must be a register) to 0, 0.0 or a NULL pointer,
+depending on its type.
+
+I<Arguments: IR or NR or SR or P>
+
+=head3 open
+
+X<open opcode (PASM)>
+
+ open R<DEST>, R<FILENAME>
+ open R<DEST>, R<FILENAME>, R<MODE>
+
+Open a file in the specified mode ("r", "w", etc.) and return
+a filehandle. Without the mode it defaults to read/write.
+
+I<Arguments: P, S, S or P, S>
+
+=head3 or
+
+X<or opcode (PASM)>
+
+ or R<DEST>, R<VAL1>, R<VAL2>
+
+Logical OR. Return R<VAL1> if it's true; otherwise, return R<VAL2>.
+
+I<Arguments: IR, I, I or P, P, P>
+
+=head3 ord
+
+X<ord opcode (PASM)>
+
+ ord R<DEST>, R<STRING>
+ ord R<DEST>, R<STRING>, R<POS>
+
+Return the character at position R<POS> in R<STRING>. If R<POS> isn't
+specified, return the 0th character.
+
+I<Arguments: IR, S or IR, S, I>
+
+=head3 peek
+
+X<peek opcode (PASM)>
+
+ peek R<DEST>
+ peek R<DEST>, R<PIO>
+
+Read the next byte from the given FileHandle object or from C<stdin> but
+don't remove it.
+
+I<Arguments: SR or SR, P>
+
+=head3 peek_pad
+
+X<peek_pad opcode (PASM)>
+
+ peek_pad R<DEST>
+
+Store the current lexical scope pad in a PMC.
+
+I<Arguments: P>
+
+=head3 pin
+
+X<pin opcode (PASM)>
+
+ pin R<DEST>
+
+Make the string in R<DEST> immobile. This prevents the garbage collector
+from moving it to a different location in memory (which it otherwise may
+choose to do).
+
+I<Arguments: SR>
+
+See also: C<unpin>.
+
+=head3 pop
+
+X<pop opcode (PASM)>
+
+ pop R<DEST>, R<PMC>
+
+Pop the last entry off an aggregate PMC and return it.
+
+I<Arguments: IR, P or NR, P or SR, P or P, P>
+
+=head3 pop_pad
+
+X<pop_pad opcode (PASM)>
+
+ pop_pad
+
+Pop the current lexical scope pad off the lexical scope stack.
+
+See also: C<peek_pad>.
+
+=head3 popX
+
+X<popi opcode (PASM)>
+X<popn opcode (PASM)>
+X<popp opcode (PASM)>
+X<pops opcode (PASM)>
+
+ popi
+ popn
+ popp
+ pops
+
+Restore all the registers of one type from the stack ("i" = integer,
+"n" = float, "p" = PMC, "s" = string).
+
+ popbottomi
+ popbottomn
+ popbottomp
+ popbottoms
+
+Restore registers in the range 0..15.
+
+ poptopi
+ poptopn
+ poptopp
+ poptops
+
+Restore registers in the range 16..31.
+
+See also: C<push>R<X>.
+
+=head3 pow
+
+X<pow opcode (PASM)>
+
+ pow R<DEST>, R<VAL1>, R<VAL2>
+
+Return R<VAL1> raised to the power of R<VAL2>.
+
+I<Arguments: NR, I, I or NR, I, N or NR, N, I or NR, N, N>
+
+=head3 print
+
+X<print opcode (PASM)>
+
+ print R<VAL>
+ print R<IO>, R<VAL>
+
+Print a value to an I/O object or file descriptor. If no R<IO> is
+given, print the value to standard output.
+
+I<Arguments: I or N or S or P or P, I or P, N or P, S or P, P>
+
+=head3 printerr
+
+X<printerr opcode (PASM)>
+
+ printerr R<VAL>
+
+Print a value to C<stderr>.
+
+I<Arguments: I or N or S or P>
+
+=head3 profile
+
+X<profile opcode (PASM)>
+
+ profile R<INT>
+
+Toggle profiling in the interpreter (0 for off, any other value for on).
+
+I<Arguments: I>
+
+=head3 prophash
+
+X<prophash opcode (PASM)>
+
+ prophash R<DEST>, R<PMC>
+
+Return a hash containing all the properties from a PMC.
+
+I<Arguments: P, P>
+
+See also: C<getprop>.
+
+=head3 push
+
+X<push opcode (PASM)>
+
+ push R<PMC>, R<VAL>
+
+Push a value onto the end of an aggregate PMC.
+
+I<Arguments: P, I or P, N or P, S or P, P>
+
+=head3 push_pad
+
+X<push_pad opcode (PASM)>
+
+ push_pad R<PAD>
+
+Push a scratchpad stored in a PMC onto the lexical scope stack.
+
+I<Arguments: P>
+
+=head3 pushX
+
+X<pushi opcode (PASM)>
+X<pushn opcode (PASM)>
+X<pushp opcode (PASM)>
+X<pushs opcode (PASM)>
+
+ pushi
+ pushn
+ pushp
+ pushs
+
+Save all the registers of one type to the stack ("i" = integer, "n" =
+float, "p" = PMC, "s" = string). Restore with C<pop>R<X>.
+
+ pushbottomi
+ pushbottomn
+ pushbottomp
+ pushbottoms
+
+Push registers 0..15.
+
+ pushtopi
+ pushtopn
+ pushtopp
+ pushtops
+
+Push registers 16..31.
+
+=head3 read
+
+X<read opcode (PASM)>
+
+ read R<DEST>, R<BYTES>
+ read R<DEST>, R<IO>, R<BYTES>
+
+Read the specified number of bytes from a Parrot I/O object. Read from
+C<stdin> if no R<IO> is provided.
+
+I<Arguments: SR, I or SR, P, I>
+
+=head3 readline
+
+X<readline opcode (PASM)>
+
+ readline R<DEST>, R<IO>
+
+Read a line from a Parrot I/O object.
+
+I<Arguments: SR, P>
+
+=head3 register
+
+X<register opcode (PASM)>
+
+ register R<PMC>
+
+Register the given PMC in the interpreter's root set, so that it's
+visible during the mark phase.
+
+I<Arguments: P>
+
+See also: C<unregister>.
+
+=head3 removeparent
+
+X<removeparent opcode (PASM)>
+
+ removeparent R<CLASS1>, R<CLASS2>
+
+Remove R<CLASS2> from class C<CLASS1>'s list of parents.
+
+I<Arguments: P, P>
+
+=head3 repeat
+
+X<repeat opcode (PASM)>
+
+ repeat R<DEST>, R<VAL>, R<REPEAT>
+
+Repeat a string R<REPEAT> number of times.
+
+I<Arguments: SR, S, I or P, P, I or P, P, P>
+
+=head3 restoretop
+
+X<restoretop opcode (PASM)>
+
+ restoretop
+
+Restore registers 16..31. Does a C<pop>R<X> for every type.
+
+See also: C<savetop>.
+
+=head3 ret
+
+X<ret opcode (PASM)>
+
+ ret
+
+Pop a location off the top of the call stack, and go there.
+Often used with C<bsr> and C<jsr>.
+
+=head3 rethrow
+
+X<rethrow opcode (PASM)>
+
+ rethrow R<EXCEPTION>
+
+Rethrow an exception. Only valid inside an exception handler.
+
+I<Arguments: P>
+
+See also: C<throw>
+
+=head3 runinterp
+
+X<runinterp opcode (PASM)>
+
+ runinterp R<INTERPRETER>, R<OFFSET>
+
+Use an interpreter stored in PMC to run code starting at a given
+offset.
+
+I<Arguments: P, I>
+
+See also: C<newinterp>.
+
+=head3 say
+
+X<say opcode (PASM)>
+
+ say R<VAL>
+
+Print a value to C<stdout> with a trailing newline.
+
+I<Arguments: I or N or S or P>
+
+=head3 sec
+
+X<sec opcode (PASM)>
+
+ sec R<DEST>, R<VAL>
+
+The secant of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 sech
+
+X<sech opcode (PASM)>
+
+ sech R<DEST>, R<VAL>
+
+The hyperbolic secant of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 seek
+
+X<seek opcode (PASM)>
+
+ seek R<DEST>, R<IO>, R<OFFSET>, R<STARTFLAG>
+ seek R<DEST>, R<IO>, R<UPPER32>, R<LOWER32>, R<STARTFLAG>
+
+Set the file position of a Parrot I/O object to a given offset from a
+starting position (STARTFLAG: 0 is the beginning of the file, 1 is
+current the position, 2 is the end of the file). R<DEST> is the
+success or failure of the seek.
+
+64-bit C<seek> combines R<UPPER32> and R<LOWER32> to get one 64-bit
+R<OFFSET>.
+
+I<Arguments: P, I, I or P, I, I, I>
+
+=head3 set
+
+X<set opcode (PASM)>
+
+ set R<DEST>, R<VAL>
+
+Set a register to a value.
+
+I<Arguments: IR, I or IR, N or IR, S or IR, P or NR, I or NR, N or NR,
+S or NR, P or SR, I or SR, N or SR, S or SR, P or P, I or P, N or P, S
+or P, P>
+
+ set R<DEST[KEY]>, R<VAL>
+
+A keyed set operation on a PMC.
+
+I<Arguments: P, I or P, N or P, S or P, P>
+
+ set R<DEST>, R<PMC[KEY]>
+
+A keyed get operation on a PMC.
+
+I<Arguments: I, P or N, P or S, P or P, P>
+
+=head3 setX_ind
+
+X<seti_ind opcode (PASM)>
+X<setn_ind opcode (PASM)>
+X<sets_ind opcode (PASM)>
+X<setp_ind opcode (PASM)>
+
+ seti_ind R<REG>, R<VAL>
+ setn_ind R<REG>, R<VAL>
+ sets_ind R<REG>, R<VAL>
+ setp_ind R<REG>, R<VAL>
+
+Set register number R<REG> of the specified type to R<VAL>. Bypasses
+the register allocator, so use with care.
+
+I<Arguments: I, I or I, S or I, N or I, P>
+
+=head3 set_addr
+
+X<set_addr opcode (PASM)>
+
+ set_addr R<DEST>, R<LABEL>
+
+Return the current address plus the offset to R<LABEL>. Often used to
+calculate absolute addresses for C<jump> or C<jsr>.
+
+I<Arguments: IR, IC>
+
+ set_addr R<SUB>, R<LABEL>
+
+Set the subroutine address pointing to the given label.
+
+I<Arguments: P, I>
+
+=head3 set_chartype
+
+X<set_chartype opcode (PASM)>
+
+ set_chartype R<STRING>, R<CHARTYPE>
+
+Set the chartype of a string.
+
+I<Arguments: S, I>
+
+=head3 set_eh
+
+X<set_eh opcode (PASM)>
+
+ set_eh R<HANDLER>
+
+Push an exception handler on the control stack.
+
+I<Arguments: P>
+
+See also: C<clear_eh>, C<throw>.
+
+=head3 set_encoding
+
+X<set_encoding opcode (PASM)>
+X<strings;encoding>
+
+ set_encoding R<STRING>, R<ENCODING>
+
+Set the encoding of a string.
+
+I<Arguments: S, I>
+
+=head3 setattribute
+
+X<setattribute opcode (PASM)>
+
+ setattribute R<OBJECT>, R<OFFSET>, R<ATTRIBUTE>
+
+Set the given attribute at R<OFFSET> for object R<OBJECT>.
+
+I<Arguments: P, I, P>
+
+See also: C<getattribute>, C<classoffset>.
+
+=head3 setprop
+
+X<setprop opcode (PASM)>
+
+ setprop R<PMC>, R<NAME>, R<VALUE>
+
+Set the value of a named property on a PMC.
+
+I<Arguments: P, S, P>
+
+See also: C<getprop> and C<delprop>.
+
+=head3 setstd*
+
+X<setstderr opcode (PASM)>
+X<setstdin opcode (PASM)>
+X<setstdout opcode (PASM)>
+
+ setstderr R<DEST>
+ setstdin R<DEST>
+ setstdout R<DEST>
+
+Set a FileHandle object for the given standard handle.
+
+I<Arguments: P>
+
+=head3 shift
+
+X<shift opcode (PASM)>
+
+ shift R<DEST>, R<PMC>
+
+Shift a value off the front of an aggregate PMC.
+
+I<Arguments: IR, P or NR, P or SR, P or P, P>
+
+=head3 shl
+
+X<shl opcode (PASM)>
+
+ shl R<DEST>, R<VAL>, R<BITS>
+
+Bitwise shift a value left by a given number of bits.
+
+I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
+
+=head3 shr
+
+X<shr opcode (PASM)>
+
+ shr R<DEST>, R<VAL>, R<BITS>
+
+Bitwise shift a value right by a given number of bits.
+
+I<Arguments: IR, I or P, I or P, P or IR, I, I or P, P, I or P, P, P>
+
+=head3 sin
+
+X<sin opcode (PASM)>
+
+ sin R<DEST>, R<VAL>
+
+The sine of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 singleton
+
+X<singleton opcode (PASM)>
+
+ singleton R<DEST>
+
+Take the given object and put it into its own singleton class.
+
+I<Arguments: P>
+
+=head3 sinh
+
+X<sinh opcode (PASM)>
+
+ sinh R<DEST>, R<VAL>
+
+The hyperbolic sine of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 sizeof
+
+X<sizeof opcode (PASM)>
+
+ sizeof R<DEST>, R<TYPE>
+
+Set R<DEST> to the size in bytes of the given natural type.
+
+I<Arguments: IR, I>
+
+=head3 sleep
+
+X<sleep opcode (PASM)>
+
+ sleep R<SECONDS>
+
+Sleep for the given number of seconds.
+
+I<Arguments: I or N>
+
+=head3 spawnw
+
+X<spawnw opcode (PASM)>
+
+ spawnw R<DEST>, R<COMMAND>
+
+Spawn a subprocess to run the given R<COMMAND>, wait for it to finish,
+and return the result.
+
+I<Arguments: IR, S>
+
+=head3 splice
+
+X<splice opcode (PASM)>
+
+ splice R<DEST>, R<REPLACE>, R<OFFSET>, R<COUNT>
+
+Starting at R<OFFSET>, replace R<COUNT> number of values in the
+destination PMC with values provided in the R<REPLACE> PMC.
+
+I<Arguments: P, P, I, I>
+
+=head3 sprintf
+
+X<sprintf opcode (PASM)>
+
+ sprintf R<DEST>, R<FORMAT>, R<ARGS>
+
+Format arguments in an aggregate PMC, using format string R<FORMAT>.
+
+I<Arguments: SR, S, P or P, P, P>
+
+=head3 stat
+
+X<stat opcode (PASM)>
+
+ stat R<DEST>, R<VAL>, R<VAL>
+
+Stat the VAL1 file and return stat element VAL2, as listed in
+Table 10-2.
+
+I<Arguments: IR, S, I or IR, I, I>
+
+=begin table picture Stat arguments
+
+Z<CHP-10-TABLE-2>
+
+=headrow
+
+=row
+
+=cell Flag
+
+=cell Flagname
+
+=cell Returns
+
+=bodyrows
+
+=row
+
+=cell C<0>
+
+=cell EXISTS
+
+=cell Does the file exist?
+
+=row
+
+=cell C<1>
+
+=cell FILESIZE
+
+=cell Size of file, in bytes
+
+=row
+
+=cell C<2>
+
+=cell ISDIR
+
+=cell Is the file a directory?
+
+=row
+
+=cell C<3>
+
+=cell ISDEV
+
+=cell Is the file a device?
+
+=row
+
+=cell C<4>
+
+=cell CREATETIME
+
+=cell Time file was created
+
+=row
+
+=cell C<5>
+
+=cell ACCESSTIME
+
+=cell Time file was last accessed
+
+=row
+
+=cell C<6>
+
+=cell MODIFYTIME
+
+=cell Time file data was changed
+
+=row
+
+=cell C<7>
+
+=cell CHANGETIME
+
+=cell Time file metadata was changed
+
+=row
+
+=cell C<8>
+
+=cell BACKUPTIME
+
+=cell Time of last backup
+
+=row
+
+=cell C<9>
+
+=cell UID
+
+=cell ID of file owner
+
+=row
+
+=cell C<10>
+
+=cell GID
+
+=cell ID of file group
+
+=end table
+
+=head3 store_global
+
+X<store_global opcode (PASM)>
+
+ store_global R<NAME>, R<OBJECT>
+ store_global R<NAME>, R<NAMESPACE>, R<OBJECT>
+
+Store a global variable as a named symbol.
+
+I<Arguments: S, P or S, S, P or P, S, P>
+
+See also: C<find_global>.
+
+=head3 store_lex
+
+X<store_lex opcode (PASM)>
+
+ store_lex R<NAME>, R<OBJECT>
+ store_lex R<DEPTH>, R<NAME>, R<OBJECT>
+ store_lex R<DEPTH>, R<POSITION>, R<OBJECT>
+
+Store an object as a lexical variable with a given name. If the symbol
+doesn't exist, it will be created in the lexical scratchpad at the
+specified depth (a negative depth counts back from the current scope).
+If R<DEPTH> isn't provided, the symbol must already exist. If a
+position is provided instead of a name, the symbol will be stored at
+the given position in the scratchpad.
+
+I<Arguments: S, P or I, I, P or I, S, P>
+
+See also: C<find_lex>.
+
+=head3 string_chartype
+
+X<string_chartype opcode (PASM)>
+
+ string_chartype R<DEST>, R<STRING>
+
+Return the chartype of the string.
+
+I<Arguments: IR, S>
+
+=head3 string_encoding
+
+X<string_encoding opcode (PASM)>
+X<strings;encoding>
+
+ string_encoding R<DEST>, R<STRING>
+
+Return the encoding of the string.
+
+I<Arguments: IR, S>
+
+=head3 stringinfo
+
+X<stringinfo opcode (PASM)>
+
+ stringinfo R<DEST>, R<STRING>, R<FLAG>
+
+Return information about a string. An integer flag selects which
+information to return, as listed in Table 10-3.
+
+=begin table picture Stringinfo arguments
+
+Z<CHP-10-TABLE-3>
+
+=headrow
+
+=row
+
+=cell Flag
+
+=cell Returns
+
+=bodyrows
+
+=row
+
+=cell C<1>
+
+=cell Location of string buffer header.
+
+=row
+
+=cell C<2>
+
+=cell Location of start of string memory.
+
+=row
+
+=cell C<3>
+
+=cell Allocated length, in bytes.
+
+=row
+
+=cell C<4>
+
+=cell String flags.
+
+=row
+
+=cell C<5>
+
+=cell Length of string buffer currently used, in bytes.
+
+=row
+
+=cell C<6>
+
+=cell String length, in characters.
+
+=end table
+
+I<Arguments: IR, S, I>
+
+=head3 sub
+
+X<sub opcode (PASM)>
+
+ sub R<DEST>, R<VAL>
+ sub R<DEST>, R<VAL1>, R<VAL2>
+
+Subtract R<VAL2> from R<VAL1>. If no R<VAL2>, subtract R<VAL> from
+R<DEST>.
+
+I<Arguments: IR, I or NR, I or NR, N or P, I or P, N or P, P or IR, I,
+I or NR, N, I or NR, N, N or P, P, I or P, P, N or P, P, P>
+
+=head3 subclass
+
+X<subclass opcode (PASM)>
+
+ subclass R<DEST>, R<CLASS>
+ subclass R<DEST>, R<CLASS>, R<NAME>
+
+Create a subclass of R<CLASS>. Without R<NAME> an anonymous subclass is
+created.
+
+I<Arguments: P, S or P, P or P, S, S or P, P, S>
+
+=head3 substr
+
+X<substr opcode (PASM)>
+
+ substr R<DEST>, R<STRING>, R<OFFSET>
+ substr R<DEST>, R<STRING>, R<OFFSET>, R<LENGTH>
+
+Return a substring of R<STRING>, beginning at R<OFFSET> and with length
+R<LENGTH>.
+
+I<Arguments: SR, S, I or SR, S, I, I or SR, P, I, I>
+
+ substr R<DEST>, R<STRING>, R<OFFSET>, R<LENGTH>, R<REPLACE>
+
+If R<REPLACE> is given, use it to replace the returned substring in
+R<STRING>.
+
+I<Arguments: SR, S, I, I, S>
+
+ substr R<DEST>, R<OFFSET>, R<LENGTH>, R<REPLACE>
+
+If R<STRING> is omitted, operate on the string in R<DEST>.
+
+I<Arguments: SR, I, I, S>
+
+
+=head3 substr_r
+
+X<substr_r opcode (PASM)>
+
+ substr_r R<DEST>, R<STRING>, R<OFFSET>, R<LENGTH>
+
+Acts like C<substr>, but reuses the destination string instead of
+creating a new string. Deprecated.
+
+I<Arguments: SR, S, I, I>
+
+=head3 sweep
+
+X<sweep opcode (PASM)>
+
+ sweep R<LAZY>
+
+Trigger a GC mark run. If R<LAZY> is set to 1, only objects that need timely
+destruction may be destroyed.
+
+I<Arguments: IC>
+
+=head3 sweepoff
+
+X<sweepoff opcode (PASM)>
+
+ sweepoff
+
+Disable GC mark runs (nestable).
+
+=head3 sweepon
+
+X<sweepon opcode (PASM)>
+
+ sweepon
+
+Re-enable GC mark runs.
+
+=head3 sysinfo
+
+X<sysinfo opcode (PASM)>
+
+ sysinfo R<DEST>, R<ITEM>
+
+Return OS-specific details given by C<ITEM>.
+
+I<Arguments: IR, I or SR, I>
+
+=head3 tan
+
+X<tan opcode (PASM)>
+
+ tan R<DEST>, R<VAL>
+
+The tangent of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 tanh
+
+X<tanh opcode (PASM)>
+
+ tanh R<DEST>, R<VAL>
+
+The hyperbolic tangent of R<VAL> in radians.
+
+I<Arguments: NR, I or NR, N>
+
+=head3 tell
+
+X<tell opcode (PASM)>
+
+ tell R<DEST>, R<PIO>
+ tell R<UPPER32>, R<LOWER32>, R<PIO>
+
+Return the file position of the given FileHandle object.
+
+I<Arguments: IR, P or IR, I, P>
+
+See also: C<seek>.
+
+=head3 thaw
+
+X<thaw opcode (PASM)>
+
+ thaw R<DEST>, R<STR>
+
+Create a new PMC representing the frozen image.
+
+I<Arguments: P, S>
+
+See also: C<freeze>.
+
+=head3 throw
+
+X<throw opcode (PASM)>
+
+ throw R<EXCEPTION>
+
+Throw an exception.
+
+I<Arguments: P>
+
+See also: C<rethrow>, C<set_eh>, C<clear_eh>
+
+=head3 time
+
+X<time opcode (PASM)>
+
+ time R<DEST>
+
+Return the current system time.
+
+I<Arguments: IR or NR>
+
+=head3 titlecase
+
+X<titlecase opcode (PASM)>
+
+ titlecase R<DEST>
+ titlecase R<DEST>, R<VAL>
+
+Create a copy of the string in R<VAL> with all characters converted to
+title case, and store it in R<DEST>. If R<VAL> is omitted, convert and
+replace the string in R<DEST>.
+
+I<Arguments: SR or SR, S>
+
+See also: C<upcase>, C<downcase>.
+
+=head3 trace
+
+X<trace opcode (PASM)>
+
+ trace R<INT>
+
+Toggle tracing in the interpreter (0 for off, any other value for on).
+
+I<Arguments: I>
+
+=head3 transcode
+
+X<transcode opcode (PASM)>
+
+ transcode R<DEST>, R<ENCODING>
+ transcode R<DEST>, R<SOURCE>, R<ENCODING>
+ transcode R<DEST>, R<SOURCE>, R<ENCODING>, R<CHARTYPE>
+
+Transcode a string to the given R<CHARTYPE> and R<ENCODING>. If
+R<CHARTYPE> is omitted, it is assumed to be the same as the original.
+
+I<Arguments: SR, I or SR, S, I or SR, S, I, I>
+
+=head3 typeof
+
+X<typeof opcode (PASM)>
+
+ typeof R<DEST>, R<VAL>
+ typeof R<DEST>, R<PMC[KEY]>
+
+Return the type of a PMC or Parrot data type, either its class name (to a
+string destination) or integer identifier (to an integer destination).
+
+I<Arguments: IR, P or SR, I or SR, P>
+
+=head3 unless
+
+X<unless (conditional);opcode (PASM)>
+
+ unless R<CONDITION>, R<LABEL>
+
+Jump to a label unless the condition is a true value.
+
+I<Arguments: I, IC or N, IC or S, IC or P, IC>
+
+=head3 unpin
+
+X<unpin opcode (PASM)>
+
+ unpin R<DEST>
+
+Make the string in R<DEST> movable again. This is the default, so
+C<unpin> is a no-op unless the string has been pinned with C<pin>.
+
+See also: C<pin>.
+
+I<Arguments: SR>
+
+=head3 unregister
+
+X<unregister opcode (PASM)>
+
+ unregister R<PMC>
+
+Remove one reference to PMC from the root set registry.
+
+I<Arguments: P>
+
+See also: C<register>.
+
+=head3 unshift
+
+X<unshift opcode (PASM)>
+
+ unshift R<DEST>, R<VAL>
+
+Unshift a value onto the front of an aggregate PMC.
+
+I<Arguments: P, I or P, N or P, S or P, P>
+
+=head3 upcase
+
+X<upcase opcode (PASM)>
+
+ upcase R<DEST>
+ upcase R<DEST>, R<VAL>
+
+Create a copy of the string in R<VAL> with all characters converted to
+upper case, and store it in R<DEST>. If R<VAL> is omitted, convert and
+replace the string in R<DEST>.
+
+I<Arguments: SR or SR, S>
+
+See also: C<downcase>, C<titlecase>.
+
+=head3 updatecc
+
+X<updatecc>
+
+ updatecc
+
+Update the state of a return continuation stored in C<P1>. Used when
+context information changes after the return continuation is created
+but before it's invoked.
+
+See also: C<invokecc>.
+
+I<Arguments: IR, I>
+
+=head3 vers
+
+X<vers opcode (PASM)>
+
+ vers R<DEST>, R<VAL>
+
+The versine of R<VAL> in radians.
+
+I<Arguments: NR, N>
+
+=head3 warningsoff
+
+X<warningsoff opcode (PASM)>
+
+ warningsoff R<CATEGORY>
+
+Turn off a particular category of warnings by category number. Turning
+off one category will not affect the status of other warnings
+categories. See C<warningson> for the list of categories.
+
+I<Arguments: I>
+
+=head3 warningson
+
+X<warningson opcode (PASM)>
+
+ warningson R<CATEGORY>
+
+Turn on a particular category of warnings by category number. The
+default is all warnings off. Turning on one category will not turn off
+other categories. Combine category numbers with a bitwise OR to turn on
+more than one at a time. If you include F<warnings.pasm>, the category
+numbers are available by name as:
+
+ .PARROT_WARNINGS_ALL_FLAG
+ .PARROT_WARNINGS_UNDEF_FLAG
+ .PARROT_WARNINGS_IO_FLAG
+ .PARROT_WARNINGS_PLATFORM_FLAG
+
+I<Arguments: I>
+
+=head3 xor
+
+X<xor opcode (PASM)>
+
+ xor R<DEST>, R<VAL1>, R<VAL2>
+
+Logical XOR. If R<VAL1> is true and R<VAL2> is false, return R<VAL1>.
+If R<VAL1> is false and R<VAL2> is true, return R<VAL2>. Otherwise,
+return a false value.
+
+I<Arguments: IR, I, I or P, P, P>
+
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch11_directive_reference.pod (from r39796, trunk/docs/book/draft/ch11_directive_reference.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch11_directive_reference.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch11_directive_reference.pod)
@@ -0,0 +1,227 @@
+=pod
+
+=head1 Directive Reference
+
+Z<CHP-13-SECT-2>
+
+X<PIR (Parrot intermediate representation);quick reference;directives>
+This is a summary of PIR directives. Directives are preprocessed by the
+Parrot interpreter. Since PIR and PASM run on the same interpreter, many
+of the directives listed here are also valid in PASM code.
+
+
+=head3 .arg
+
+X<.arg directive>
+
+ .arg R<VAL>
+
+pass a value to a subroutine according to PCC.
+
+=head3 .const
+
+X<.const directive>
+
+ .const R<TYPE>R<NAME> = R<VALUE>
+
+Define a named constant.
+
+=head3 .macro_const
+
+X<.macro_const directive>
+
+ .macro_const R<NAME>R<VALUE>
+
+Define a named macro that expands to a given value. Macros are called
+as directives, i.e. .R<NAME> (PASM code only).
+
+=head3 .emit
+
+X<.emit directive>
+
+ .emit
+
+Define a compilation unit of PASM code. Always paired with C<.eom>.
+
+=head3 .end
+
+X<.end directive>
+
+ .end
+
+End a compilation unit. Always paired with C<.sub>.
+
+=head3 .endm
+
+X<.endm directive>
+
+ .endm
+
+End a macro definition. Always paired with C<.macro>.
+
+=head3 .eom
+
+X<.eom directive>
+
+ .eom
+
+End a compilation unit of PASM code. Always paired with C<.emit>.
+
+=head3 .flatten_arg
+
+X<.flatten_arg directive>
+
+ .flatten_arg R<PArray>
+
+Flatten the passed array PMC and provide args for PCC calls.
+
+=head3 .globalconst
+
+X<.globalconst directive>
+
+ .globalconst R<TYPE>R<NAME> = R<VALUE>
+
+Define a named, file visible constant.
+
+=head3 .include
+
+X<.include directive>
+
+ .include " R<FILENAME> "
+
+Include the contents of an external file by inserting it in place.
+
+=head3 .invocant
+
+X<.invocant directive>
+
+ .invocant R<OBJ>
+
+Set the invocant for a method call.
+
+=head3 .local
+
+X<.local directive>
+
+ .local R<TYPE>R<NAME>
+
+Define a local named variable.
+
+=head3 .macro
+
+X<.macro directive>
+
+ .macro R<NAME> (R<PARAMS>)
+
+Define a named macro with a list of parameters. The macro is called as
+.R<NAME>(R<arg1>,R<arg2>,...). Always paired with C<.endm>.
+
+=head3 .meth_call
+
+X<.meth_call directive>
+
+ .meth_call R<SUB>
+ .meth_call R<SUB>, R<RETCONT>
+
+Create a method call.
+
+=head3 .namespace
+
+X<.namespace directive>
+
+ .namespace R< [ "namespace" ] >
+
+Define a namespace.
+
+=head3 .nci_call
+
+X<.nci_call directive>
+
+ .nci_call R<SUB>
+
+Create an NCI call.
+
+=head3 .param
+
+X<.param directive>
+
+ .param R<DEST>
+ .param R<TYPE>R<NAME>
+
+Define a subroutine parameter.
+
+=head3 .begin_call
+
+X<.begin_call directive>
+
+Start a call sequence. Always paired with C<.end_call>
+
+=head3 .begin_return
+
+X<.begin_return directive>
+
+Start a return sequence. Always paired with C<.end_return>
+
+=head3 .begin_yield
+
+X<.begin_yield directive>
+
+Start a return of a coroutine sequence. Always paired with C<.end_yield>
+
+=head3 .call
+
+X<.call directive>
+
+ .call R<SUB>
+ .call R<SUB>, R<RETCONT>
+
+Create a subroutine call.
+
+=head3 .pcc_sub
+
+X<.pcc_sub directive>
+
+ .pcc_sub R<_LABEL>
+
+Create a symbol entry for subroutine at the _LABEL. This directive is
+for PASM code only.
+
+=head3 .result
+
+X<.result directive>
+
+ .result R<DEST>
+
+Get a return value according to PCC.
+
+=head3 .return
+
+X<.return directive>
+
+ .return R<VAL>
+
+Return a value to the calling subroutine according to PCC.
+
+=head3 .sub
+
+X<.sub directive>
+
+ .sub R<NAME>
+
+Define a compilation unit. Always paired with C<.end>. Names begin
+with "C<_>" by convention.
+
+=head3 .sym
+
+X<.sym directive>
+
+ .sym R<TYPE> R<NAME>
+
+Same as C<.local>.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/draft/ch12_operator_reference.pod (from r39796, trunk/docs/book/draft/ch12_operator_reference.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/draft/ch12_operator_reference.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/draft/ch12_operator_reference.pod)
@@ -0,0 +1,299 @@
+=pod
+
+=head1 PIR Operator Reference
+
+Z<CHP-13-SECT-3>
+
+X<PIR (Parrot intermediate representation);quick reference;instructions>
+This section is a quick reference to PIR instructions. For more details
+and the latest changes, see F<imcc/docs/syntax.pod> or dive into the
+source code in F<imcc/imcc.l> and F<imcc/imcc.y>.
+
+=head3 =
+
+X<= (equal sign);= (assignment);instruction (PIR)>
+
+ R<DEST> = R<VAL>
+
+Assign a value to a particular register, temporary register, or named
+variable.
+
+=head3 +, +=
+
+X<+ (plus sign);+ (addition);instruction (PIR)>
+X<+ (plus sign);+= (addition assignment);instruction (PIR)>
+
+ R<DEST> = R<VAL> + R<VAL>
+ R<DEST> += R<VAL>
+
+Add two numbers or PMCs.
+
+=head3 -, -=
+
+X<- (hyphen);- (subtraction);instruction (PIR)>
+X<- (hyphen);-= (subtraction assignment);instruction (PIR)>
+X<- (hyphen);- (negation);instruction (PIR)>
+
+ R<DEST> = R<VAL1> - R<VAL2>
+ R<DEST> -= R<VAL1>
+ R<DEST> = - R<VAL>
+
+Subtract R<VAL1> from R<VAL2>. The unary "C<->" negates a number.
+
+=head3 *, *=
+
+X<* (asterisk);* (multiplication);instruction (PIR)>
+X<* (asterisk);*= (multiplication assignment);instruction (PIR)>
+
+ R<DEST> = R<VAL> * R<VAL>
+ R<DEST> *= R<VAL>
+
+Multiply two numbers or PMCs.
+
+=head3 /, /=
+
+X</ (slash);/ (division);instruction (PIR)>
+X</ (slash);/= (division assignment);instruction (PIR)>
+
+ R<DEST> = R<VAL1> / R<VAL2>
+ R<DEST> /= R<VAL1>
+
+Divide R<VAL1> by R<VAL2>.
+
+=head3 **
+
+X<* (asterisk);** (exponentiation);instruction (PIR)>
+
+ R<DEST> = R<VAL1> ** R<VAL2>
+
+Raise R<VAL1> to the power of R<VAL2>.
+
+=head3 %, %=
+
+X<% (percent sign);% (modulus);instruction (PIR)>
+X<% (percent sign);%= (modulus assignment);instruction (PIR)>
+
+ R<DEST> = R<VAL1> % R<VAL2>
+ R<DEST> %= R<VAL1>
+
+Divide R<VAL1> by R<VAL2> and return the (C<mod>) remainder.
+
+=head3 ., .=
+
+X<. (dot);. (concatenation) instruction (PIR)>
+X<. (dot);.= (concatenation assignment) instruction (PIR)>
+
+ R<DEST> = R<VAL> . R<VAL>
+ R<DEST> .= R<VAL>
+
+Concatenate two strings. The concat operator must be surrounded by
+whitespace.
+
+=head3 E<lt>
+
+X<E<lt> (left angle bracket);E<lt> (less than);instruction (PIR)>
+
+ if R<VAL1> E<lt> R<VAL2> goto R<LABEL>
+
+Conditionally branch to a label if R<VAL1> is less than R<VAL2>.
+
+=head3 E<lt>=
+
+X<E<lt> (left angle bracket);E<lt>= (less than or equal);instruction (PIR)>
+
+ if R<VAL1> E<lt>= R<VAL2> goto R<LABEL>
+
+Conditionally branch to a label if R<VAL1> is less than or equal to
+R<VAL2>.
+
+=head3 E<gt>
+
+X<E<gt> (right angle bracket);E<gt> (greater than);instruction (PIR)>
+
+ if R<VAL1> E<gt> R<VAL2> goto R<LABEL>
+
+Conditionally branch to a label if R<VAL1> is greater than R<VAL2>.
+
+=head3 E<gt>=
+
+X<E<gt> (right angle bracket);E<gt>= (greater than or equal);instruction (PIR)>
+
+ if R<VAL1> E<gt>= R<VAL2> goto R<LABEL>
+
+Conditionally branch to a label if R<VAL1> is greater than or equal to
+R<VAL2>.
+
+=head3 ==
+
+X<= (equal sign);== (equality);instruction (PIR)>
+
+ if R<VAL1> == R<VAL2> goto R<LABEL>
+
+Conditionally branch to a label if R<VAL1> is equal to R<VAL2>.
+
+=head3 !=
+
+X<! (bang);!= (not equal);instruction (PIR)>
+
+ if R<VAL1> != R<VAL2> goto R<LABEL>
+
+Conditionally branch to a label if R<VAL1> is not equal to R<VAL2>.
+
+=head3 &&
+
+X<& (ampersand);&& (logical AND);instruction (PIR)>
+
+ R<DEST> = R<VAL1> && R<VAL2>
+
+Logical AND. Return R<VAL1> if it's false, otherwise return R<VAL2>.
+
+=head3 ||
+
+X<| (pipe);|| (logical OR);instruction (PIR)>
+
+ R<DEST> = R<VAL1> || R<VAL2>
+
+Logical OR. Return R<VAL1> if it's true, otherwise return R<VAL2>.
+
+=head3 ~~
+
+X<~ (tilde);~~ (logical XOR) instruction (PIR)>
+
+ R<DEST> = R<VAL1> ~~ R<VAL2>
+
+Logical XOR. If R<VAL1> is true and R<VAL2> is false, return R<VAL1>.
+If R<VAL1> is false and R<VAL2> is true, return R<VAL2>. Otherwise,
+return a false value.
+
+=head3 !
+
+X<! (bang);! (not);instruction (PIR)>
+
+ R<DEST> = ! R<VAL>
+
+Logical NOT. Return a true value if R<VAL> is false.
+
+=head3 &, &=
+
+X<& (ampersand);& (bitwise AND) instruction (PIR)>
+X<& (ampersand);&= (bitwise AND assignment) instruction (PIR)>
+
+ R<DEST> = R<VAL> & R<VAL>
+ R<DEST> &= R<VAL>
+
+Bitwise AND on two values.
+
+=head3 |, |=
+
+X<| (pipe);| (bitwise AND) instruction (PIR)>
+X<| (pipe);|= (bitwise AND assignment) instruction (PIR)>
+
+ R<DEST> = R<VAL> | R<VAL>
+ R<DEST> |= R<VAL>
+
+Bitwise OR on two values.
+
+=head3 ~, ~=
+
+X<~ (tilde);~ (bitwise XOR) instruction (PIR)>
+X<~ (tilde);~= (bitwise XOR assignment) instruction (PIR)>
+
+ R<DEST> = R<VAL> ~ R<VAL>
+ R<DEST> ~= R<VAL>
+ R<DEST> = ~ R<VAL>
+
+Bitwise XOR on two values. The unary form is a bitwise NOT on a value.
+
+=head3 E<lt>E<lt>, E<lt>E<lt>=
+
+X<E<lt> (left angle bracket);E<lt>E<lt> (bitwise left shift);instruction (PIR)>
+X<E<lt> (left angle bracket);E<lt>E<lt>= (bitwise left shift assignment);instruction (PIR)>
+
+ R<DEST> = R<VAL1> E<lt>E<lt> R<VAL2>
+ R<DEST> E<lt>E<lt>= R<VAL2>
+
+Bitwise shift R<VAL1> left by R<VAL2> number of bits.
+
+=head3 E<gt>E<gt>, E<gt>E<gt>=
+
+X<E<gt> (right angle bracket);E<gt>E<gt> (bitwise right shift);instruction (PIR)>
+X<E<gt> (right angle bracket);E<gt>E<gt>= (bitwise right shift assignment);instruction (PIR)>
+
+ R<DEST> = R<VAL1> E<gt>E<gt> R<VAL2>
+ R<DEST> E<gt>E<gt>= R<VAL2>
+
+Bitwise shift R<VAL1> right by R<VAL2> number of bits.
+
+=head3 E<gt>E<gt>E<gt>, E<gt>E<gt>E<gt>=
+
+X<E<gt> (right angle bracket);E<gt>E<gt>E<gt> (logical right shift) instruction (PIR)>
+X<E<gt> (right angle bracket);E<gt>E<gt>E<gt>= (logical right shift assignment) instruction (PIR)>
+
+ R<DEST> = R<VAL1> E<gt>E<gt>E<gt> R<VAL2>
+ R<DEST> E<gt>E<gt>E<gt>= R<VAL2>
+
+Logically shift R<VAL1> right by R<VAL2> number of bits.
+
+=head3 [ ]
+
+X<[] (brackets);indexed access to PMC (PIR)>
+
+ R<DEST> = R<PMC> [ R<KEY> ]
+ R<PMC> [ R<KEY> ] = R<VAL>
+
+Indexed access to a PMC and indexed assignment to a PMC.
+
+ DEST = STRING [ OFFSET ]
+ STRING [ OFFSET ] = VAL
+
+Access a one-character substring on a string, starting at a particular
+offset, or assign to that substring.
+
+=head3 call
+
+X<call instruction (PIR)>
+
+ call R<NAME>
+
+Call the named subroutine (a C<.sub> label).
+
+=head3 global
+
+X<global instruction (PIR)>
+
+ R<DEST> = global R<NAME>
+ global R<NAME> = R<VAL>
+
+Access a global variable for read or write.
+
+=head3 goto
+
+X<goto command (PIR)>
+
+ goto R<NAME>
+
+Jump to the named identifier (label or subroutine name).
+
+=head3 if
+
+X<if (conditional);instruction (PIR)>
+
+ if R<EXPR> goto R<NAME>
+
+If the value or expression evaluates as true, jump to the named
+identifier.
+
+=head3 unless
+
+X<unless (conditional);instruction (PIR)>
+
+ unless R<VAL> goto R<NAME>
+
+Unless the value evaluates as true, jump to the named identifier.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/pir/ch01_introduction.pod (from r39796, trunk/docs/book/pir/ch01_introduction.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/pir/ch01_introduction.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/pir/ch01_introduction.pod)
@@ -0,0 +1,109 @@
+=pod
+
+=head1 Introduction
+
+Parrot is a language-neutral virtual machine for dynamic languages such as
+Ruby, Python, PHP, and Perl. It hosts a powerful suite of compiler tools
+tailored to dynamic languages and a next generation regular expression engine.
+Its architecture differs from virtual machines such as the JVM or CLR, with
+optimizations for dynamic languages, the use of registers instead of stacks,
+and pervasive continuations used for all flow control.
+
+The name "Parrot" was inspired by Monty Python's Parrot sketch. As an April
+Fools' Day joke in 2001, Simon Cozens published "Programming Parrot", a
+fictional interview between Guido van Rossum and Larry Wall detailing their
+plans to merge Python and Perl into a new language called Parrot
+(U<http://www.perl.com/pub/a/2001/04/01/parrot.htm>).
+
+Parrot Intermediate Representation (PIR) is Parrot's native low-level language.
+PIR is fundamentally an assembly language, but it has some higher-level
+features such as operator syntax, syntactic sugar for subroutine and method
+calls, automatic register allocation, and more friendly conditional syntax.
+Parrot libraries -- including most of Parrot's compiler tools -- are often
+written in PIR. Even so, PIR is more rigid and "close to the machine" than
+some higher-level languages like C, which makes it a good window into the inner
+workings of the virtual machine.
+
+=head2 Parrot Resources
+
+The starting point for all things related to Parrot is the main website
+U<http://www.parrot.org/>. The site lists additional resources, well as recent
+news and information about the project.
+
+The Parrot Foundation holds the copyright over Parrot and helps support its
+development and community.
+
+=head3 Documentation
+
+Parrot includes extensive documentation in the distribution. The full
+documentation for the latest release is available online at
+U<http://docs.parrot.org/>.
+
+=head3 Mailing Lists
+
+X<parrot-dev (Parrot mailing list)>
+X<mailing lists>
+
+The primary mailing list for Parrot is I<parrot-dev at lists.parrot.org>. If
+you're interested in developing Parrot, the I<parrot-commits> and
+I<parrot-tickets> lists are useful. More information on the Parrot mailing
+lists, as well as subscription options, is available at
+U<http://lists.parrot.org/mailman/listinfo>.
+
+The archives for I<parrot-dev> are also available on Google Groups at
+U<http://groups.google.com/group/parrot-dev> and via NNTP at
+U<nntp://news.gmane.org/gmane.comp.compilers.parrot.devel>.
+
+=head3 IRC
+
+X<#parrot (Parrot IRC channel)>
+X<IRC channel (#parrot)>
+
+Parrot developers and users congregate on IRC at C<#parrot> on the
+U<irc://irc.parrot.org> server. It's a good place to ask questions or discuss
+Parrot in real time.
+
+=head3 Issue Tracking & Wiki
+
+X<trac.parrot.org website>
+X<issue tracking (trac.parrot.org)>
+
+Parrot developers track issues with a Trac site at U<https://trac.parrot.org/>.
+Users can submit new tickets and track the status of existing tickets. The
+site also includes a wiki used in project development, a source code browser,
+and the project roadmap.
+
+=head2 Parrot Development
+
+X<development cycles>
+
+Parrot's first release occurred in September 2001. The 1.0 release took place
+on March 17, 2009. 2009. The Parrot project makes releases on the third
+Tuesday of each month. Two releases a year E<mdash> occuring every January and
+July E<mdash> are "supported" releases intended for production use. The other
+ten releases are development releases intended for language implementers and
+testers.
+
+Development proceeds in cycles around releases. Activity just before a release
+focuses on closing tickets, fixing bugs, reviewing documentation, and preparing
+for the release. Immediately after the release, larger changes occur: merging
+branches, adding large features, or removing deprecated features. This allows
+developers to ensure that changes have sufficient testing time before the next
+release. These regular releases also encourage feedback from casual users and
+testers.
+
+=head2 Licensing
+
+X<license>
+
+The Parrot foundation supports the Parrot development community and holds
+trademarks and copyrights to Parrot. The project is available under the
+Artistic License 2.0, allowing free use in commercial and open source/free
+software contexts.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/pir/ch02_getting_started.pod (from r39796, trunk/docs/book/pir/ch02_getting_started.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/pir/ch02_getting_started.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/pir/ch02_getting_started.pod)
@@ -0,0 +1,74 @@
+=pod
+
+=head1 Getting Started
+
+The simplest way to install Parrot is to use a pre-compiled binary for your
+operating system or distribution. Packages are available for many systems,
+including Debian, Ubuntu, Fedora, Mandriva, FreeBSD, Cygwin, and MacPorts. The
+Parrot website lists all known packages at U<http://www.parrot.org/download>. A
+binary installer for Windows is also available at
+U<http://parrotwin32.sourceforge.net/>.
+
+If packages aren't available on your system, download the latest supported
+release from U<http://www.parrot.org/release/supported>.
+
+You need a C compiler and a make utility to build Parrot from source code --
+usually C<gcc> and C<make>, but Parrot can build with standard compiler
+toolchains on different operating systems. Perl 5.8 is also a prerequiste for
+configuring and building Parrot.
+
+If you have these dependencies installed, build the core virtual machine and
+compiler toolkit and run the standard test suite with the commands:
+
+ $ perl Configure.pl
+ $ make
+ $ make test
+
+By default, Parrot installs to directories F<bin/>, F<lib/>, and
+F<include/> under F</usr/local>. If you have privileges to
+write to these directories, install Parrot with:
+
+ $ make install
+
+To install Parrot in a different location, use the C<--prefix> option to
+F<Configure.pl>:
+
+ $ perl Configure.pl --prefix=/home/me/parrot
+
+Setting the prefix to F</home/me/parrot> installs the Parrot executable
+in F</home/me/parrot/bin/parrot>.
+
+If you intend to develop a language on Parrot, install the Parrot
+developer tools as well:
+
+ $ make install-dev
+
+Once you've installed Parrot, create a test file called
+F<news.pir>.N<Files containing PIR code use the F<.pir> extension.>
+
+=begin PIR
+
+ .sub 'news'
+ say "Here is the news for Parrots."
+ .end
+
+=end PIR
+
+Now run this file with:
+
+ $ parrot news.pir
+
+which will print:
+
+ Here is the news for Parrots.
+
+=cut
+
+The Parrot source distribution includes copious examples in its F<examples/>
+directory. In particular, a PIR tutorial is available in
+F<examples/tutorial/>.
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/pir/ch03_basic_syntax.pod (from r39796, trunk/docs/book/pir/ch03_basic_syntax.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/pir/ch03_basic_syntax.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/pir/ch03_basic_syntax.pod)
@@ -0,0 +1,326 @@
+=pod
+
+=head1 Basic Syntax
+
+Z<CHP-3>
+
+X<PIR syntax>
+
+PIR has a relatively simple syntax. Every line is a comment, a label, a
+statement, or a directive. Each statement or directive stands on its own
+line. There is no end-of-line symbol (such as a semicolon in C).
+
+=head2 Comments
+
+X<comments>
+A comment begins with the C<#> symbol, and continues until the end of the line.
+Comments can stand alone on a line or follow a statement or directive.
+
+=begin PIR
+
+ # This is a regular comment. The PIR
+ # interpreter ignores this.
+
+=end PIR
+
+X<Pod documentation>
+PIR also treats inline documentation in Pod format as a comment. An
+equals sign as the first character of a line marks the start of a Pod
+block. A C<=cut> marker signals the end of a Pod block.
+
+ =head2
+
+ This is Pod documentation, and is treated like a
+ comment. The PIR interpreter ignores this.
+
+ =cut
+
+=head2 Labels
+
+X<PIR (Parrot intermediate representation);labels> X<labels (PIR)>
+A label attaches a name to a line of code so other statements can refer to it.
+Labels can contain letters, numbers, and underscores. By convention, labels use
+all capital letters to stand out from the rest of the source code. It's fine to
+put a label on the same line as a statement or directive:
+
+=begin PIR_FRAGMENT
+
+ GREET: say "'Allo, 'allo, 'allo."
+
+=end PIR_FRAGMENT
+
+Labels on separate lines improve readability, especially when outdented:
+
+=begin PIR_FRAGMENT
+
+ GREET:
+ say "'Allo, 'allo, 'allo."
+
+=end PIR_FRAGMENT
+
+=head2 Statements
+
+Z<CHP-3-SECT-1>
+
+X<statements (PIR)>
+X<PIR (Parrot intermediate representation);statements>
+A statement is either an opcode or syntactic sugar for one or more opcodes. An
+opcode is a native instruction for the virtual machine; it consists of the name
+of the instruction followed by zero or more arguments.
+
+=begin PIR_FRAGMENT
+
+ say "Norwegian Blue"
+
+=end PIR_FRAGMENT
+
+PIR also provides higher-level constructs, including symbolic operators:
+
+=begin PIR_FRAGMENT
+
+ $I1 = 2 + 5
+
+=end PIR_FRAGMENT
+
+These special statement forms are just syntactic sugar for regular opcodes. The
+C<+> symbol corresponds to the C<add> opcode, the C<-> symbol to the C<sub>
+opcode, and so on. The previous example is equivalent to:
+
+=begin PIR_FRAGMENT
+
+ add $I1, 2, 5
+
+=end PIR_FRAGMENT
+
+=head2 Directives
+
+X<directives (PIR)>
+X<PIR (Parrot intermediate representation);directives>
+
+Directives resemble opcodes, but they begin with a period (C<.>). Some
+directives specify actions that occur at compile time. Other directives
+represent complex operations that require the generation of multiple
+instructions. The C<.local> directive, for example, declares a named variable.
+
+=begin PIR_FRAGMENT
+
+ .local string hello
+
+=end PIR_FRAGMENT
+
+=head2 Literals
+
+X<literals (PIR)>
+X<PIR (Parrot intermediate representation);literals>
+
+Integers and floating point numbers are numeric literals. They can be positive
+or negative.
+
+=begin PIR_FRAGMENT
+
+ $I0 = 42 # positive
+ $I1 = -1 # negative
+
+=end PIR_FRAGMENT
+
+Integer literals can also be binary, octal, or hexadecimal:
+
+=begin PIR_FRAGMENT
+
+ $I1 = 0b01010 # binary
+ $I2 = 0o72 # octal
+ $I3 = 0xA5 # hexadecimal
+
+=end PIR_FRAGMENT
+
+Floating point number literals have a decimal point and can use scientific
+notation:
+
+=begin PIR_FRAGMENT
+
+ $N0 = 3.14
+ $N2 = -1.2e+4
+
+=end PIR_FRAGMENT
+
+X<strings;in PIR>
+String literals are enclosed in single or double-quotes.N<See the
+section on L<Strings> in Chapter 4 for an explanation of the differences
+between the quoting types.>
+
+=begin PIR_FRAGMENT
+
+ $S0 = "This is a valid literal string"
+ $S1 = 'This is also a valid literal string'
+
+=end PIR_FRAGMENT
+
+=head2 Variables
+
+X<variables (PIR)>
+X<PIR (Parrot intermediate representation);variables>
+X<PMC; definition>
+
+PIR variables can store four different kinds of valuesE<mdash>integers,
+numbers (floating point), strings, and objects. Parrot's objects are
+called PMCs, for "I<P>olyI<M>orphic I<C>ontainer".
+
+The simplest kind of variable is a register variable. The name of a register
+variable always starts with a dollar sign (C<$>), followed by a single
+character which specifies the type of the variable -- integer (C<I>), number
+(C<N>), string (C<S>), or PMC (C<P>) -- and ends with a unique number. You need
+not predeclare register variables:
+
+=begin PIR_FRAGMENT
+
+ $S0 = "Who's a pretty boy, then?"
+ say $S0
+
+=end PIR_FRAGMENT
+
+PIR also has named variables; the C<.local>
+directive declares them. As with register variables, there are four valid types:
+C<int>, C<num>, C<string>, and C<pmc>. You I<must> declare named variables;
+otherwise they behave exactly the same as register variables.
+
+=begin PIR_FRAGMENT
+
+ .local string hello
+ hello = "'Allo, 'allo, 'allo."
+ say hello
+
+=end PIR_FRAGMENT
+
+=head2 Constants
+
+X<PIR (Parrot intermediate representation);constants>
+X<constants (PIR)>
+
+The C<.const> directive declares a named constant. Named constants are similar
+to named variables, but the values set in the declaration may never change.
+Like C<.local>, C<.const> takes a type and a name. It also requires a literal
+argument to set the value of the constant.
+
+=begin PIR_FRAGMENT
+
+ .const int frog = 4 # integer constant
+ .const string name = "Superintendent Parrot" # string constant
+ .const num pi = 3.14159 # floating point constant
+
+=end PIR_FRAGMENT
+
+You may use a named constant anywhere you may use a literal, but you must
+declare the named constant beforehand. This example declares a named string
+constant C<hello> and prints the value:
+
+=begin PIR_FRAGMENT
+
+ .const string hello = "Hello, Polly."
+ say hello
+
+=end PIR_FRAGMENT
+
+=head2 Keys
+
+X<PIR (Parrot intermediate representation);keys>
+X<keys (PIR)>
+
+A key is a special kind of constant used for accessing elements in complex
+variables (such as an array). A key is either an integer or a string; and it's
+always enclosed in square brackets (C<[> and C<]>). You do not have to declare
+literal keys. This code example stores the string "foo" in $P0 as element 5,
+and then retreives it.
+
+=begin PIR_FRAGMENT
+
+ $P0[5] = "foo"
+ $S1 = $P0[5]
+
+=end PIR_FRAGMENT
+
+PIR supports multi-part keys. Use a semicolon to separate each part.
+
+=begin PIR_FRAGMENT
+
+ $P0['my';'key'] = 472
+ $I1 = $P0['my';'key']
+
+=end PIR_FRAGMENT
+
+=head2 Control Structures
+
+X<PIR (Parrot intermediate representation);control structures>
+X<control structures (PIR)>
+
+Rather than providing a pre-packaged set of control structures like C<if> and
+C<while>, PIR gives you the building blocks to construct your own.N<PIR has
+many advanced features, but at heart it B<is> an assembly language.> The most
+basic of these building blocks is C<goto>, which jumps to a named label.N<This
+is not your father's C<goto>. It can only jump inside a subroutine, and only to
+a named label.> In this code example, the C<say> statement will run immediately
+after the C<goto> statement:
+
+=begin PIR_FRAGMENT
+
+ goto GREET
+ # ... some skipped code ...
+ GREET:
+ say "'Allo, 'allo, 'allo."
+
+=end PIR_FRAGMENT
+
+Variations on the basic C<goto> check whether a particular condition is
+true or false before jumping:
+
+=begin PIR_FRAGMENT
+
+ if $I0 > 5 goto GREET
+
+=end PIR_FRAGMENT
+
+You can construct any traditional control structure from PIR's built-in control structures.
+
+=head2 Subroutines
+
+X<PIR (Parrot intermediate representation);subroutines>
+X<subroutines (PIR)>
+
+A PIR subroutine starts with the C<.sub> directive and ends with the C<.end>
+directive. Parameter declarations use the C<.param> directive; they resemble
+named variable declarations. This example declares a subroutine named
+C<greeting>, that takes a single string parameter named C<hello>:
+
+=begin PIR
+
+ .sub 'greeting'
+ .param string hello
+ say hello
+ .end
+
+=end PIR
+
+=head2 That's All Folks
+
+You now know everything you need to know about PIR. Everything else you
+read or learn about PIR will use one of these fundamental language
+structures. The rest is vocabulary.
+
+=begin sidebar Parrot Assembly Language
+
+Parrot Assembly Language (PASM) is another low-level language native to the
+virtual machine. PASM is a pure assembly language, with none of the syntactic
+sugar that makes PIR friendly for library development. PASM's primary purpose
+is to act as a plain English reprepresention of the bytecode format. Its
+typical use is for debugging, rather than for writing libraries. Use PIR or a
+higher-level language for development tasks.
+
+PASM files use the F<.pasm> file extension.
+
+=end sidebar
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/pir/ch04_variables.pod (from r39796, trunk/docs/book/pir/ch04_variables.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/pir/ch04_variables.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/pir/ch04_variables.pod)
@@ -0,0 +1,1807 @@
+=pod
+
+=head1 Variables
+
+Parrot is a register-based virtual machine. It has four typed register sets --
+integers, floating-point numbers, strings, and objects. All variables in PIR
+are one of these four types. Whether you work with register variables or named
+variables, you're actually working directly with register storage locations in
+the virtual machine.
+
+If you've ever worked with an assembly language before, you may immediately
+jump to the conclusion that C<$I0> is the zeroth integer register in the
+register set, but Parrot is a bit smarter than that. The number of a register
+variable does not necessarily correspond to the register used internally;
+Parrot's compiler maps registers as appropriate for speed and memory
+considerations. The only guarantee Parrot gives you is that you'll always get
+the same storage location when you use C<$I0> in the same subroutine.
+
+=head2 Assignment
+
+X<variable assignment>
+X<PIR operators; =>
+
+The most basic operation on a variable is assignment using the C<=>
+operator:
+
+=begin PIR_FRAGMENT
+
+ $I0 = 42 # set integer variable to the value 42
+ $N3 = 3.14159 # set number variable to an approximation of pi
+ $I1 = $I0 # set $I1 to the value of $I0
+
+=end PIR_FRAGMENT
+
+X<exchange>
+X<opcodes; exchange>
+
+The C<exchange> opcode swaps the contents of two variables of the same type.
+This example sets C<$I0> to the value of C<$I1> and sets C<$I1> to the value
+of C<$I0>.
+
+=begin PIR_FRAGMENT
+
+ exchange $I0, $I1
+
+=end PIR_FRAGMENT
+
+X<null>
+X<opcodes; null>
+
+The C<null> opcode sets an integer or number variable to a zero value,
+and undefines a string or object.
+
+=begin PIR_FRAGMENT
+
+ null $I0 # 0
+ null $N0 # 0.0
+ null $S0 # NULL
+ null $P0 # PMCNULL
+
+=end PIR_FRAGMENT
+
+=head2 Working with Numbers
+
+PIR has an extensive set of instructions that work with integers,
+floating-point numbers, and numeric PMCs. Many of these instructions
+have a variant that modifies the result in place:
+
+=begin PIR_FRAGMENT
+
+ $I0 = $I1 + $I2
+ $I0 += $I1
+
+=end PIR_FRAGMENT
+
+The first form of C<+> stores the sum of the two arguments in the result
+variable, C<$I0>. The second variant, C<+=>, adds the single argument to
+C<$I0> and stores the sum back in C<$I0>.
+
+The arguments can be Parrot literals, variables, or constants. If the
+result is an integer type, like C<$I0>, the arguments must also be
+integers. A number result, like C<$N0>, usually requires number
+arguments, but many numeric instructions also allow the final argument to
+be an integer. Instructions with a PMC result may accept an integer,
+floating-point, or PMC final argument:
+
+=begin PIR_FRAGMENT
+
+ $P0 = $P1 * $P2
+ $P0 = $P1 * $I2
+ $P0 = $P1 * $N2
+ $P0 *= $P1
+ $P0 *= $I1
+ $P0 *= $N1
+
+=end PIR_FRAGMENT
+
+There are many numeric opcodes; a complete list is available in "PIR Opcodes"
+in Chapter 11.
+
+=head3 Unary numeric opcodes
+
+X<unary numeric opcodes>
+
+Unary opcodes have a single argument. They either return a result or modify
+the argument in place. Some of the most common unary numeric opcodes are C<inc>
+(increment), C<dec> (decrement), C<abs> (absolute value), C<neg> (negate), and
+C<fact> (factorial):
+
+=begin PIR_FRAGMENT
+
+ $N0 = abs -5.0 # the absolute value of -5.0 is 5.0
+ $I1 = fact 5 # the factorial of 5 is 120
+ inc $I1 # 120 incremented by 1 is 121
+
+=end PIR_FRAGMENT
+
+=head3 Binary numeric opcodes
+
+X<binary numeric opcodes>
+
+Binary opcodes have two arguments and a result. Parrot provides
+addition (C<+> or C<add>), subtraction (C<-> or C<sub>), multiplication
+(C<*> or C<mul>), division (C</> or C<div>), modulus (C<%> or C<mod>),
+and exponent (C<pow>) opcodes, as well as C<gcd>X<gcd opcode>
+(greatest common divisor) and C<lcm>X<lcm opcode> (least common
+multiple).
+
+=begin PIR_FRAGMENT
+
+ $I0 = 12 / 5
+ $I0 = 12 % 5
+
+=end PIR_FRAGMENT
+
+=head3 Floating-point operations
+
+X<float opcodes>
+
+The most common floating-point operations are C<ln> (natural log), C<log2> (log
+base 2), C<log10> (log base 10), and C<exp> (I<e>G<x>), as well as a full set
+of trigonometric opcodes such as C<sin> (sine), C<cos> (cosine), C<tan>
+(tangent), C<sec> (secant), C<cosh> (hyperbolic cosine), C<tanh> (hyperbolic
+tangent), C<sech> (hyperbolic secant), C<asin> (arc sine), C<acos> (arc
+cosine), C<atan> (arc tangent), C<asec> (arc secant), C<exsec> (exsecant),
+C<hav> (haversine), and C<vers> (versine). All angle arguments for the
+X<trigonometric functions> trigonometric functions are in radians:
+
+=begin PIR_FRAGMENT
+
+ $N0 = sin $N1
+ $N0 = exp 2
+
+=end PIR_FRAGMENT
+
+The majority of the floating-point operations have a single argument and a
+single result. The arguments can generally be either an integer or number, but
+many of these opcodes require the result to be a number.
+
+=head3 Logical and Bitwise Operations
+
+X<logical opcodes>
+
+The logical opcodes evaluate the truth of their arguments. They're most useful
+to make decisions for control flow. Integers and numeric PMCs support logical
+are false if they're 0 and true otherwise. Strings are false if they're the
+empty string or a single character "0", and true otherwise. PMCs are true when
+their C<get_bool>X<get_bool vtable method> vtable method returns a nonzero
+value.
+
+The C<and>X<and opcode> opcode returns the first argument if
+it's false and the second argument otherwise:
+
+=begin PIR_FRAGMENT
+
+ $I0 = and 0, 1 # returns 0
+ $I0 = and 1, 2 # returns 2
+
+=end PIR_FRAGMENT
+
+The C<or>X<or opcode> opcode returns the first argument if
+it's true and the second argument otherwise:
+
+=begin PIR_FRAGMENT
+
+ $I0 = or 1, 0 # returns 1
+ $I0 = or 0, 2 # returns 2
+
+ $P0 = or $P1, $P2
+
+=end PIR_FRAGMENT
+
+Both C<and> and C<or> are short-circuiting ops. If they can determine what
+value to return from the first argument, they'll never evaluate the third.
+This is significant only for PMCs, as they might have side effects on
+evaluation.
+
+The C<xor>X<xor opcode> opcode returns the first argument if it is the only
+true value, returns the second argument if it is the only true value, and
+returns false if both values are true or both are false:
+
+=begin PIR_FRAGMENT
+
+ $I0 = xor 1, 0 # returns 1
+ $I0 = xor 0, 1 # returns 1
+ $I0 = xor 1, 1 # returns 0
+ $I0 = xor 0, 0 # returns 0
+
+=end PIR_FRAGMENT
+
+The C<not>X<not opcode> opcode returns a true value when the argument is false
+and a false value if the argument is true:
+
+=begin PIR_FRAGMENT
+
+ $I0 = not $I1
+ $P0 = not $P1
+
+=end PIR_FRAGMENT
+
+X<bitwise;opcodes>
+
+The bitwise opcodes operate on their values a single bit at a time.
+C<band>X<band opcode>, C<bor>X<bor opcode>, and C<bxor>X<bxor opcode> return a
+value that is the logical AND, OR, or XOR of each bit in the source arguments.
+They each take two arguments.
+
+=begin PIR_FRAGMENT
+
+ $I0 = bor $I1, $I2
+ $P0 = bxor $P1, $I2
+
+=end PIR_FRAGMENT
+
+C<band>, C<bor>, and C<bxor> also have variants that modify the result
+in place.
+
+=begin PIR_FRAGMENT
+
+ $I0 = band $I1
+ $P0 = bor $P1
+
+=end PIR_FRAGMENT
+
+C<bnot>X<bnot opcode> is the logical NOT of each bit in the source argument.
+
+=begin PIR_FRAGMENT
+
+ $I0 = bnot $I1
+
+=end PIR_FRAGMENT
+
+X<shift opcodes>
+
+The logical and arithmetic shift operations shift their values by a specified
+number of bits:
+
+=begin PIR_FRAGMENT
+
+ $I0 = shl $I1, $I2 # shift $I1 left by count $I2
+ $I0 = shr $I1, $I2 # arithmetic shift right
+ $P0 = lsr $P1, $P2 # logical shift right
+
+=end PIR_FRAGMENT
+
+=head2 Working with Strings
+
+Parrot strings are buffers of variable-sized data. The most common use of
+strings is to store text data. Strings can also hold binary or other
+non-textual data, though this is rare.N<In general, a custom PMC is more
+useful.> Parrot strings are flexible and powerful, to handle the complexity of
+human-readable (and computer-representable) text data. String operations work
+with string literals, variables, and constants, and with string-like PMCs.
+
+=head3 Escape Sequences
+
+X<string escapes>
+X<escape sequences>
+
+Strings in double-quotes allow escape sequences using backslashes. Strings in
+single-quotes only allow escapes for nested quotes:
+
+ $S0 = "This string is \n on two lines"
+ $S0 = 'This is a \n one-line string with a slash in it'
+
+Parrot supports several escape sequences in double-quoted strings:
+
+=begin table String Escapes
+
+=headrow
+
+=row
+
+=cell Escape
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<\a>
+
+=cell An ASCII alarm character
+
+=row
+
+=cell C<\b>
+
+=cell An ASCII backspace character
+
+=row
+
+=cell C<\t>
+
+=cell A tab
+
+=row
+
+=cell C<\n>
+
+=cell A newline
+
+=row
+
+=cell C<\v>
+
+=cell A vertical tab
+
+=row
+
+=cell C<\f>
+
+=cell A form feed
+
+=row
+
+=cell C<\r>
+
+=cell A carriage return
+
+=row
+
+=cell C<\e>
+
+=cell An escape
+
+=row
+
+=cell C<\\>
+
+=cell A backslash
+
+=row
+
+=cell C<\">
+
+=cell A quote
+
+=row
+
+=cell C<\x>R<NN>
+
+=cell A character represented by 1-2 hexadecimal digits
+
+=row
+
+=cell C<\x{>R<NNNNNNNN>C<}>
+
+=cell A character represented by 1-8 hexadecimal digits
+
+=row
+
+=cell C<\o>R<NNN>
+
+=cell A character represented by 1-3 octal digits
+
+=row
+
+=cell C<\u>R<NNNN>
+
+=cell A character represented by 4 hexadecimal digits
+
+=row
+
+=cell C<\U>R<NNNNNNNN>
+
+=cell A character represented by 8 hexadecimal digits
+
+=row
+
+=cell C<\c>R<X>
+
+=cell A control character R<X>
+
+=end table
+
+=head3 Heredocs
+
+X<heredocs>
+
+If you need more flexibility in defining a string, use a heredoc string
+literal. The C<E<lt>E<lt>> operator starts a heredoc. The string terminator
+immediately follows. All text until the terminator is part of the string. The
+terminator must appear on its own line, must appear at the beginning of the
+line, and may not have any trailing whitespace.
+
+ $S2 = << "End_Token"
+
+ This is a multi-line string literal. Notice that
+ it doesn't use quotation marks.
+
+ End_Token
+
+=head3 Concatenating strings
+
+X<concat opcode>
+X<string concatenation>
+
+Use the C<.> operator to concatenate strings. The following example
+concatenates the string "cd" onto the string "ab" and stores the result in
+C<$S1>.
+
+=begin PIR_FRAGMENT
+
+ $S0 = "ab"
+ $S1 = $S0 . "cd" # concatenates $S0 with "cd"
+ say $S1 # prints "abcd"
+
+=end PIR_FRAGMENT
+
+Concatenation has a C<.=> variant to modify the result in place. In the
+next example, the C<.=> operation appends "xy" onto the string "abcd" in
+C<$S1>.
+
+=begin PIR_FRAGMENT
+
+ $S1 .= "xy" # appends "xy" to $S1
+ say $S1 # prints "abcdxy"
+
+=end PIR_FRAGMENT
+
+=head3 Repeating strings
+
+The C<repeat> opcode repeats a string a specified number of times:
+
+=begin PIR_FRAGMENT
+
+ $S0 = "a"
+ $S1 = repeat $S0, 5
+ say $S1 # prints "aaaaa"
+
+=end PIR_FRAGMENT
+
+In this example, C<repeat> generates a new string with "a" repeated five
+times and stores it in C<$S1>.
+
+=head3 Length of a string
+
+The C<length> opcode returns the length of a string in characters. This won't
+be the same as the length in I<bytes> for multibyte encoded strings:
+
+=begin PIR_FRAGMENT
+
+ $S0 = "abcd"
+ $I0 = length $S0 # the length is 4
+ say $I0
+
+=end PIR_FRAGMENT
+
+C<length> has no equivalent for PMC strings.
+
+=head3 Substrings
+
+The simplest version of the C<substr>X<substr opcode> opcode takes three
+arguments: a source string, an offset position, and a length. It returns a
+substring of the original string, starting from the offset position (0 is the
+first character) and spanning the length:
+
+=begin PIR_FRAGMENT
+
+ $S0 = substr "abcde", 1, 2 # $S0 is "bc"
+
+=end PIR_FRAGMENT
+
+This example extracts a two-character string from "abcde" at a one-character
+offset from the beginning of the string (starting with the second character).
+It generates a new string, "bc", in the destination register C<$S0>.
+
+When the offset position is negative, it counts backward from the end of the
+string. Thus an offset of -1 starts at the last character of the string.
+
+C<substr> also has a four-argument form, where the fourth argument is a string
+used to replace the substring. This variant modifies the source string and
+returns the removed substring.
+
+This example above replaces the substring "bc" in C<$S1> with the string "XYZ",
+and returns "bc" in C<$S0>:
+
+=begin PIR_FRAGMENT
+
+ $S1 = "abcde"
+ $S0 = substr $S1, 1, 2, "XYZ"
+ say $S0 # prints "bc"
+ say $S1 # prints "aXYZde"
+
+=end PIR_FRAGMENT
+
+When the offset position in a replacing C<substr> is one character beyond the
+original string length, C<substr> appends the replacement string just like the
+concatenation operator. If the replacement string is an empty string, the
+opcode removes the characters from the original string.
+
+If you don't need to capture the replaced string, an optimized version of
+C<substr> performs a replace without returning the removed substring:
+
+=begin PIR_FRAGMENT
+
+ $S1 = "abcde"
+ $S1 = substr 1, 2, "XYZ"
+ say $S1 # prints "aXYZde"
+
+=end PIR_FRAGMENT
+
+=head3 Converting characters
+
+The C<chr>X<chr opcode> opcode takes an integer value and returns the
+corresponding character in the ASCII character set as a one-character string.
+The C<ord>X<ord opcode> opcode takes a single character string and returns the
+integer value of the character at the first position in the string. The integer
+value of the character will differ depending on the current encoding of the
+string:
+
+=begin PIR_FRAGMENT
+
+ $S0 = chr 65 # $S0 is "A"
+ $I0 = ord $S0 # $I0 is 65, if $S0 is ASCII or UTF-8
+
+=end PIR_FRAGMENT
+
+C<ord> has a two-argument variant that takes a character offset to select
+a single character from a multicharacter string. The offset must be within
+the length of the string:
+
+=begin PIR_FRAGMENT
+
+ $I0 = ord "ABC", 2 # $I0 is 67
+
+=end PIR_FRAGMENT
+
+A negative offset counts backward from the end of the string, so -1 is
+the last character.
+
+=begin PIR_FRAGMENT
+
+ $I0 = ord "ABC", -1 # $I0 is 67
+
+=end PIR_FRAGMENT
+
+=head3 Formatting strings
+
+X<string formatting>
+
+The C<sprintf>X<sprintf opcode> opcode generates a formatted string from a
+series of values. It takes two arguments: a string specifying the format, and
+an array PMC containing the values to be formatted. The format string and the
+result can be either strings or PMCs:
+
+=begin PIR_FRAGMENT
+
+ $S0 = sprintf $S1, $P2
+ $P0 = sprintf $P1, $P2
+
+=end PIR_FRAGMENT
+
+The format string is similar to C's C<sprintf> function with extensions for
+Parrot data types. Each format field in the string starts with a C<%> and ends
+with a character specifying the output format. Table 4-2 lists the available
+output format characters.
+
+=begin table Format characters
+
+=headrow
+
+=row
+
+=cell Format
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<%c>
+
+=cell A single character.
+
+=row
+
+=cell C<%d>
+
+=cell A decimal integer.
+
+=row
+
+=cell C<%i>
+
+=cell A decimal integer.
+
+=row
+
+=cell C<%u>
+
+=cell An unsigned integer.
+
+=row
+
+=cell C<%o>
+
+=cell An octal integer.
+
+=row
+
+=cell C<%x>
+
+=cell A hex integer, preceded by 0x (when # is specified).
+
+=row
+
+=cell C<%X>
+
+=cell A hex integer with a capital X (when # is specified).
+
+=row
+
+=cell C<%b>
+
+=cell A binary integer, preceded by 0b (when # is specified).
+
+=row
+
+=cell C<%B>
+
+=cell A binary integer with a capital B (when # is specified).
+
+=row
+
+=cell C<%p>
+
+=cell A pointer address in hex.
+
+=row
+
+=cell C<%f>
+
+=cell A floating-point number.
+
+=row
+
+=cell C<%e>
+
+=cell A floating-point number in scientific notation (displayed with a
+lowercase "e").
+
+=row
+
+=cell C<%E>
+
+=cell The same as C<%e>, but displayed with an uppercase E.
+
+=row
+
+=cell C<%g>
+
+=cell The same as C<%e> or C<%f>, whichever fits best.
+
+=row
+
+=cell C<%G>
+
+=cell The same as C<%g>, but displayed with an uppercase E.
+
+=row
+
+=cell C<%s>
+
+=cell A string.
+
+=end table
+
+Each format field supports several specifier options: R<flags>, R<width>,
+R<precision>, and R<size>. Table 4-3 lists the format flags.
+
+=begin table Format flags
+
+=headrow
+
+=row
+
+=cell Flag
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell 0
+
+=cell Pad with zeros.
+
+=row
+
+=cell E<lt>spaceE<gt>
+
+=cell Pad with spaces.
+
+=row
+
+=cell C<+>
+
+=cell Prefix numbers with a sign.
+
+=row
+
+=cell C<->
+
+=cell Align left.
+
+=row
+
+=cell C<#>
+
+=cell Prefix a leading 0 for octal, 0x for hex, or force a decimal point.
+
+=end table
+
+The R<width> is a number defining the minimum width of the output from
+a field. The R<precision> is the maximum width for strings or
+integers, and the number of decimal places for floating-point fields.
+If either R<width> or R<precision> is an asterisk (C<*>), it takes its
+value from the next argument in the PMC.
+
+The R<size> modifier defines the type of the argument the field takes. Table
+4-4 lists the size flags.
+
+=begin table Size flags
+
+=headrow
+
+=row
+
+=cell Character
+
+=cell Meaning
+
+=bodyrows
+
+=row
+
+=cell C<h>
+
+=cell short integer or single-precision float
+
+=row
+
+=cell C<l>
+
+=cell long
+
+=row
+
+=cell C<H>
+
+=cell huge value (long long or long double)
+
+=row
+
+=cell C<v>
+
+=cell Parrot INTVAL or FLOATVAL
+
+=row
+
+=cell C<O>
+
+=cell opcode_t pointer
+
+=row
+
+=cell C<P>
+
+=cell C<PMC>
+
+=row
+
+=cell C<S>
+
+=cell String
+
+=end table
+
+The values in the aggregate PMC must have a type compatible with the specified
+R<size>.
+
+The format string of this C<sprintf> example has two format fields. The first,
+C<%#Px>, extracts a PMC argument (C<P>) from the aggregate C<$P2> and formats
+it as a hexadecimal integer (C<x>) with a leading 0x (C<#>). The second format
+field, C<%+2.3Pf>, takes a PMC argument (C<P>) and formats it as a
+floating-point number (C<f>) with a minimum of two whole digits and a maximum
+of three decimal places (C<2.3>) and a leading sign (C<+>):
+
+=begin PIR_FRAGMENT
+
+ $S0 = sprintf "int %#Px num %+2.3Pf\n", $P2
+ say $S0 # prints "int 0x2a num +10.000"
+
+=end PIR_FRAGMENT
+
+The test files F<t/op/string.t> and F<t/op/sprintf.t> have many more
+examples of format strings.
+
+=head3 Joining strings
+
+The C<join> opcode joins the elements of an array PMC into a single
+string. The first argument separates the individual elements of the
+PMC in the final string result.
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "Array"
+ push $P0, "hi"
+ push $P0, 0
+ push $P0, 1
+ push $P0, 0
+ push $P0, "parrot"
+ $S0 = join "__", $P0
+ say $S0 # prints "hi__0__1__0__parrot"
+
+=end PIR_FRAGMENT
+
+This example builds a C<Array> in C<$P0> with the values C<"hi">, C<0>, C<1>,
+C<0>, and C<"parrot">. It then joins those values (separated by the string
+C<"__">) into a single string stored in C<$S0>.
+
+=head3 Splitting strings
+
+Splitting a string yields a new array containing the resulting substrings of
+the original string.
+
+This example splits the string "abc" into individual characters and stores them
+in an array in C<$P0>. It then prints out the first and third elements of the
+array.
+
+=begin PIR_FRAGMENT
+
+ $P0 = split "", "abc"
+ $P1 = $P0[0]
+ say $P1 # 'a'
+ $P1 = $P0[2]
+ say $P1 # 'c'
+
+=end PIR_FRAGMENT
+
+=head3 Testing for substrings
+
+The C<index>X<index opcode> opcode searches for a substring
+within a string. If it finds the substring, it returns the position
+where the substring was found as a character offset from the beginning
+of the string. If it fails to find the substring, it returns -1:
+
+=begin PIR_FRAGMENT
+
+ $I0 = index "Beeblebrox", "eb"
+ say $I0 # prints 2
+ $I0 = index "Beeblebrox", "Ford"
+ say $I0 # prints -1
+
+=end PIR_FRAGMENT
+
+C<index> also has a three-argument version, where the final argument
+defines an offset position for starting the search.
+
+This example finds the second "eb" in "Beeblebrox" instead of the first,
+because the search skips the first three characters in the string:
+
+=begin PIR_FRAGMENT
+
+ $I0 = index "Beeblebrox", "eb", 3
+ say $I0 # prints 5
+
+=end PIR_FRAGMENT
+
+=head3 Bitwise Operations
+
+The numeric bitwise opcodes also have string variants for AND, OR, and XOR:
+C<bors>X<bors opcode>, C<bands>X<bands opcode>, and C<bxors>X<bxors opcode>.
+These take string or string-like PMC arguments and perform the logical
+operation on each byte of the strings to produce the result string.
+
+=begin PIR_FRAGMENT
+
+ $S0 = bors $S1
+ $P0 = bands $P1
+ $S0 = bors $S1, $S2
+ $P0 = bxors $P1, $S2
+
+=end PIR_FRAGMENT
+
+The bitwise string opcodes produce meaningful results only when used with
+simple ASCII strings, because Parrot performs bitwise operations per byte.
+
+=head3 Copy-On-Write
+
+Strings use copy-on-write (COW) optimizations. A call to C<$S1 = $S0>
+doesn't immediately make a copy of C<$S0>, it only makes both variables
+point to the same string. Parrot doesn't make a copy of the string until
+one of two strings is modified.
+
+=begin PIR_FRAGMENT
+
+ $S0 = "Ford"
+ $S1 = $S0
+ $S1 = "Zaphod"
+ say $S0 # prints "Ford"
+ say $S1 # prints "Zaphod"
+
+=end PIR_FRAGMENT
+
+Modifying one of the two variables causes Parrot to create a new string. This
+example preserves the existing value in C<$S0> and assigns the new value to the
+new string in C<$S1>. The benefit of copy-on-write is avoiding the cost of
+copying strings until the copies are necessary.
+
+=head3 Encodings and Charsets
+
+X<charset>
+X<ASCII>
+
+Years ago, strings only needed to support the ASCII character set (or charset),
+a mapping of 128 bit patterns to symbols and English-language characters. This
+worked as long as everyone using a computer read and wrote English and only
+used a small handful of punctuation symbols. In other words, it was woefully
+insufficient. A modern string system must manage charsets in order to make
+sense out of all the string data in the world.
+
+X<encoding>
+
+A modern string system must also handle different encodings -- ways to
+represent various charsets in memory and on disk.
+
+Every string in Parrot has an associated encoding and charset. The default
+charset is 8-bit ASCII, which is almost universally supported. Double-quoted
+string constants can have an optional prefix specifying the string's encoding
+and charset.N<As you might suspect, single-quoted strings do not support this.>
+Parrot tracks information about encoding and character set internally, and
+automatically converts strings when necessary to preserve these
+characteristics. Strings may have prefixes of the form C<encoding:charset:>.
+
+=begin PIR_FRAGMENT
+
+ $S0 = utf8:unicode:"Hello UTF-8 Unicode World!"
+ $S1 = utf16:unicode:"Hello UTF-16 Unicode World!"
+ $S2 = ascii:"This is 8-bit ASCII"
+ $S3 = binary:"This is raw, unformatted binary data"
+
+=end PIR_FRAGMENT
+
+Parrot supports the character sets C<ascii>, C<binary>, C<iso-8859-1>
+(Latin 1), and C<unicode> and the encodings C<fixed_8>, C<ucs2>,
+C<utf8>, and C<utf18>.
+
+The C<binary:> charset treats the string as a buffer of raw unformatted
+binary data. It isn't really a string per se, because binary data
+contains no readable characters. This exists to support libraries which
+manipulate binary data that doesn't easily fit into any other primitive
+data type.
+
+When Parrot operates on two strings (as in concatenation or comparison), they
+must both use the same character set and encoding. Parrot will automatically
+upgrade one or both of the strings to the next highest compatible format as
+necessary. ASCII strings will automatically upgrade to UTF-8 strings if needed,
+and UTF-8 will upgrade to UTF-16. All of these conversions happen inside
+Parrot, so the programmer doesn't need to worry about the details.
+
+=head2 Working with PMCs
+
+Polymorphic Containers (PMCs) are the basis for complex data types and
+object-oriented behavior in Parrot. In PIR, any variable that isn't a
+low-level integer, number, or string is a PMC. PMC variables act much
+like the low-level variables, but you have to instantiate a new PMC
+object before you use it. The C<new> opcode creates a new PMC object of
+the specified type.
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'String'
+ $P0 = "That's a bollard and not a parrot"
+ say $P0
+
+=end PIR_FRAGMENT
+
+This example creates a C<String> object, stores it in the PMC register
+variable C<$P0>, assigns it the value "That's a bollard and not a
+parrot", and prints it.
+
+Every PMC has a type that indicates what data it can store and what
+behavior it supports. The C<typeof> opcode reports the type of a PMC.
+When the result is a string variable, C<typeof> returns the name of the
+type:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "String"
+ $S0 = typeof $P0 # $S0 is "String"
+ say $S0 # prints "String"
+
+=end PIR_FRAGMENT
+
+When the result is a PMC variable, C<typeof> returns the C<Class> PMC
+for that object type.
+
+=head3 Scalars
+
+X<scalars>
+X<scalar PMCs>
+
+In most of the examples shown so far, PMCs duplicate the behavior of integers,
+numbers, and strings. Parrot provides a set of PMCs for this exact purpose.
+C<Integer>, C<Number>, and C<String> are thin overlays on Parrot's low-level
+integers, numbers, and strings.
+
+A previous example showed a string literal assigned to a PMC variable of type
+C<String>. Direct assignment of a literal to a PMC works for all the low-level
+types and their PMC equivalents:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'Integer'
+ $P0 = 5
+
+ $P1 = new 'String'
+ $P1 = "5 birds"
+
+ $P2 = new 'Number'
+ $P2 = 3.14
+
+=end PIR_FRAGMENT
+
+X<boxing>
+
+You may also assign non-constant low-level integer, number, or string registers
+directly to a PMC. The PMC handles the conversion from the low-level type to
+its own internal storage.N<This conversion of a simpler type to a more complex
+type is "boxing".>
+
+=begin PIR_FRAGMENT
+
+ $I0 = 5
+ $P0 = new 'Integer'
+ $P0 = $I0
+
+ $S1 = "5 birds"
+ $P1 = new 'String'
+ $P1 = $S1
+
+ $N2 = 3.14
+ $P2 = new 'Number'
+ $P2 = $N2
+
+=end PIR_FRAGMENT
+
+The C<box> opcode is a handy shortcut to create the appropriate PMC
+object from an integer, number, or string literal or variable.
+
+=begin PIR_FRAGMENT
+
+ $P0 = box 3 # $P0 is an "Integer"
+
+ $P1 = box $S1 # $P1 is a "String"
+
+ $P2 = box 3.14 # $P2 is a "Number"
+
+=end PIR_FRAGMENT
+
+X<unboxing>
+
+In the reverse situation, when assigning a PMC to an integer, number, or
+string variable, the PMC also has the ability to convert its value to
+the low-level type.N<The reverse of "boxing" is "unboxing".>
+
+=begin PIR_FRAGMENT
+
+ $P0 = box 5
+ $S0 = $P0 # the string "5"
+ $N0 = $P0 # the number 5.0
+ $I0 = $P0 # the integer 5
+
+ $P1 = box "5 birds"
+ $S1 = $P1 # the string "5 birds"
+ $I1 = $P1 # the integer 5
+ $N1 = $P1 # the number 5.0
+
+ $P2 = box 3.14
+ $S2 = $P2 # the string "3.14"
+ $I2 = $P2 # the integer 3
+ $N2 = $P2 # the number 3.14
+
+=end PIR_FRAGMENT
+
+This example creates C<Integer>, C<Number>, and C<String> PMCs, and
+shows the effect of assigning each one back to a low-level type.
+
+Converting a string to an integer or number only makes sense when the contents
+of the string are a number. The C<String> PMC will attempt to extract a number
+from the beginning of the string, but otherwise will return a false value.
+
+=begin sidebar Type Conversions
+
+Parrot also handles conversions between the low-level types where
+possible, converting integers to strings (C<$S0 = $I1>),
+numbers to strings (C<$S0 = $N1>), numbers to integers (C<$I0 = $N1>),
+integers to numbers (C<$N0 = $I1>), and even strings to integers or
+numbers (C<$I0 = $S1> and C<$N0 = $S1>).
+
+=end sidebar
+
+=head3 Aggregates
+
+X<aggregates>
+X<aggregate PMCs>
+
+PMCs can define complex types that hold multiple values, commonly called
+aggregates. Two basic aggregate types are ordered arrays and associative
+arrays. The primary difference between these is that ordered arrays use integer
+keys for indexes and associative arrays use string keys.
+
+Aggregate PMCs support the use of numeric or string keys. PIR also offers a
+extensive set of operations for manipulating aggregate data types.
+
+=head4 Ordered Arrays
+
+Parrot provides several ordered array PMCs, differentiated by what the array
+should store -- booleans, integers, numbers, strings, or other PMCs -- and
+whether the array should maintain a fixed size or dynamically resize for the
+number of elements it stores.
+
+The core array types are C<FixedPMCArray>, C<ResizablePMCArray>,
+C<FixedIntegerArray>, C<ResizableIntegerArray>, C<FixedFloatArray>,
+C<ResizableFloatArray>, C<FixedStringArray>, C<ResizableStringArray>,
+C<FixedBooleanArray>, and C<ResizableBooleanArray>. The array
+types that start with "Fixed" have a fixed size and do not allow
+elements to be added outside their allocated size. The "Resizable"
+variants automatically extend themselves as more elements are
+added.N<With some additional overhead for checking array bounds and
+reallocating array memory.> The array types that include "String",
+"Integer", or "Boolean" in the name use alternate packing methods for
+greater memory efficiency.
+
+Parrot's core ordered array PMCs all have zero-based integer keys. Extracting
+or inserting an element into the array uses PIR's standard key syntax, with the
+key in square brackets after the variable name. An lvalue key sets the value
+for that key. An rvalue key extracts the value for that key in the aggregate
+to use as the argument value:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "ResizablePMCArray" # create a new array object
+ $P0[0] = 10 # set first element to 10
+ $P0[1] = $I31 # set second element to $I31
+ $I0 = $P0[0] # get the first element
+
+=end PIR_FRAGMENT
+
+Setting the array to an integer value directly (without a key) sets the number
+of elements of the array. Assigning an array directly to an integer retrieves
+the number of elements of the array.
+
+=begin PIR_FRAGMENT
+
+ $P0 = 2 # set array size
+ $I1 = $P0 # get array size
+
+=end PIR_FRAGMENT
+
+This is equivalent to using the C<elements> opcode to retrieve the number of
+items currently in an array:
+
+=begin PIR_FRAGMENT
+
+ elements $I0, $P0 # get element count
+
+=end PIR_FRAGMENT
+
+Some other useful instructions for working with ordered arrays are
+C<push>, C<pop>, C<shift>, and C<unshift>, to add or remove elements.
+C<push> and C<pop> work on the end of the array, the highest numbered
+index. C<shift> and C<unshift> work on the start of the array, adding or
+removing the zeroth element, and renumbering all the following elements.
+
+=begin PIR_FRAGMENT
+
+ push $P0, 'banana' # add to end
+ $S0 = pop $P0 # fetch from end
+
+ unshift $P0, 74 # add to start
+ $I0 = shift $P0 # fetch from start
+
+=end PIR_FRAGMENT
+
+=head4 Associative Arrays
+
+X<associative arrays>
+
+An associative array is an unordered aggregate that uses string keys to
+identify elements. You may know them as "hash tables", "hashes", "maps", or
+"dictionaries". Parrot provides one core associative array PMC, called C<Hash>.
+String keys work very much like integer keys. An lvalue key sets the value of
+an element, and an rvalue key extracts the value of an element. The string in
+the key must always be in single or double quotes.
+
+=begin PIR_FRAGMENT
+
+ new $P1, "Hash" # create a new associative array
+ $P1["key"] = 10 # set key and value
+ $I0 = $P1["key"] # get value for key
+
+=end PIR_FRAGMENT
+
+Assigning a C<Hash> PMC (without a key) to an integer result fetches the number
+of elements in the hash.N<You may not set a C<Hash> PMC directly to an integer
+value.>
+
+=begin PIR_FRAGMENT
+
+ $I1 = $P1 # number of entries
+
+=end PIR_FRAGMENT
+
+The C<exists>X<exists opcode> opcode tests whether a keyed value exists in an
+aggregate. It returns 1 if it finds the key in the aggregate and 0 otherwise.
+It doesn't care if the value itself is true or false, only that an entry exists
+for that key:
+
+=begin PIR_FRAGMENT
+
+ new $P0, "Hash"
+ $P0["key"] = 0
+ exists $I0, $P0["key"] # does a value exist at "key"?
+ say $I0 # prints 1
+
+=end PIR_FRAGMENT
+
+The C<delete>X<delete opcode> opcode removes an element from an associative
+array:
+
+=begin PIR_FRAGMENT
+
+ delete $P0["key"]
+
+=end PIR_FRAGMENT
+
+=head4 Iterators
+
+X<iterators>
+X<PMC iterators>
+
+An iterator extracts values from an aggregate PMC one at a time. Iterators are
+most useful in loops which perform an action on every element in an aggregate.
+The C<iter> opcode creates a new iterator from an aggregate PMC. It takes one
+argument, the PMC over which to iterate:
+
+=begin PIR_FRAGMENT
+
+ $P1 = iter $P2
+
+=end PIR_FRAGMENT
+
+Alternatively, you can also create an iterator by creating a new C<Iterator>
+PMC, passing the aggregate PMC as an initialization parameter to C<new>:
+
+=begin PIR_FRAGMENT
+
+ $P1 = new "Iterator", $P2
+
+=end PIR_FRAGMENT
+
+The C<shift> opcode extracts the next value from the iterator.
+
+=begin PIR_FRAGMENT
+
+ $P5 = shift $P1
+
+=end PIR_FRAGMENT
+
+Evaluating the iterator PMC as a boolean returns whether the iterator has
+reached the end of the aggregate:
+
+=begin PIR_FRAGMENT
+
+ if $P1 goto iter_repeat
+
+=end PIR_FRAGMENT
+
+Parrot provides predefined constants for working with iterators.
+C<.ITERATE_FROM_START> and C<.ITERATE_FROM_END> constants select whether an
+ordered array iterator starts from the beginning or end of the array. These
+two constants have no effect on associative array iterators, as their elements
+are unordered.
+
+Load the iterator constants with the C<.include> directive to include
+the file F<iterator.pasm>. To use them, set the iterator PMC to the
+value of the constant:
+
+=begin PIR_FRAGMENT
+
+ .include "iterator.pasm"
+
+ # ...
+
+ $P1 = .ITERATE_FROM_START
+
+=end PIR_FRAGMENT
+
+With all of those separate pieces in one place, this example loads the iterator
+constants, creates an ordered array of "a", "b", "c", creates an iterator from
+that array, and then loops over the iterator using a conditional C<goto> to
+checks the boolean value of the iterator and another unconditional C<goto>:
+
+=begin PIR_FRAGMENT
+
+ .include "iterator.pasm"
+ $P2 = new "ResizablePMCArray"
+ push $P2, "a"
+ push $P2, "b"
+ push $P2, "c"
+
+ $P1 = iter $P2
+ $P1 = .ITERATE_FROM_START
+
+ iter_loop:
+ unless $P1 goto iter_end
+ $P5 = shift $P1
+ say $P5 # prints "a", "b", "c"
+ goto iter_loop
+ iter_end:
+
+=end PIR_FRAGMENT
+
+Associative array iterators work similarly to ordered array iterators. When
+iterating over associative arrays, the C<shift> opcode extracts keys instead of
+values. The key looks up the value in the original hash PMC.
+
+=begin PIR_FRAGMENT
+
+ $P2 = new "Hash"
+ $P2["a"] = 10
+ $P2["b"] = 20
+ $P2["c"] = 30
+
+ $P1 = iter $P2
+
+ iter_loop:
+ unless $P1 goto iter_end
+ $S5 = shift $P1 # the key "a", "b", or "c"
+ $I9 = $P2[$S5] # the value 10, 20, or 30
+ say $I9
+ goto iter_loop
+ iter_end:
+
+=end PIR_FRAGMENT
+
+This example creates an associative array C<$P2> that contains three
+keys "a", "b", and "c", assigning them the values 10, 20, and 30. It
+creates an iterator (C<$P1>) from the associative array using the
+C<iter> opcode, and then starts a loop over the iterator. At the start
+of each loop, the C<unless> instruction checks whether the iterator has
+any more elements. If there are no more elements, C<goto> jumps to the
+end of the loop, marked by the label C<iter_end>. If there are more
+elements, the C<shift> opcode extracts the next key. Keyed assignment
+stores the integer value of the element indexed by the key in C<$I9>.
+After printing the integer value, C<goto> jumps back to the start of the
+loop, marked by C<iter_loop>.
+
+=head4 Multi-level Keys
+
+Aggregates can hold any data type, including other aggregates.
+Accessing elements deep within nested data structures is a common
+operation, so PIR provides a way to do it in a single instruction.
+Complex keys specify a series of nested data structures, with each
+individual key separated by a semicolon.
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "Hash"
+ $P1 = new "ResizablePMCArray"
+ $P1[2] = 42
+ $P0["answer"] = $P1
+
+ $I1 = 2
+ $I0 = $P0["answer";$I1]
+ say $I0
+
+=end PIR_FRAGMENT
+
+This example builds up a data structure of an associative array
+containing an ordered array. The complex key C<$P0["answer";$I1]>
+retrieves an element of the array within the hash. You can also set a
+value using a complex key:
+
+=begin PIR_FRAGMENT
+
+ $P0["answer";0] = 5
+
+=end PIR_FRAGMENT
+
+The individual keys are integer or string literals, or variables with
+integer or string values.
+
+=head3 Copying and Cloning
+
+X<PMCs; copy>
+X<PMCs; clone>
+
+PMC registers don't directly store the data for a PMC, they only store a
+pointer to the structure that stores the data. As a result, the C<=>
+operator doesn't copy the entire PMC, it only copies the pointer to the
+PMC data. If you later modify the copy of the variable, it will also
+modify the original.
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "String"
+ $P0 = "Ford"
+ $P1 = $P0
+ $P1 = "Zaphod"
+ say $P0 # prints "Zaphod"
+ say $P1 # prints "Zaphod"
+
+=end PIR_FRAGMENT
+
+In this example, C<$P0> and C<$P1> are both pointers to the same
+internal data structure. Setting C<$P1> to the string literal
+"Zaphod", it overwrites the previous value "Ford". Both C<$P0> and
+C<$P1> refer to the C<String> PMC "Zaphod".
+
+The C<clone> X<clone opcode> opcode makes a deep copy of a PMC, instead
+of copying the pointer like C<=> does.
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "String"
+ $P0 = "Ford"
+ $P1 = clone $P0
+ $P0 = "Zaphod"
+ say $P0 # prints "Zaphod"
+ say $P1 # prints "Ford"
+
+=end PIR_FRAGMENT
+
+This example creates an identical, independent clone of the PMC in
+C<$P0> and puts it in C<$P1>. Later changes to C<$P0> have no effect on
+the PMC in C<$P1>.N<With low-level strings, the copies created by
+C<clone> are copy-on-write exactly the same as the copy created by
+C<=>.>
+
+To assign the I<value> of one PMC to another PMC that already exists, use the
+C<assign>X<assign opcode> opcode:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "Integer"
+ $P1 = new "Integer"
+ $P0 = 42
+ assign $P1, $P0 # note: $P1 must exist already
+ inc $P0
+ say $P0 # prints 43
+ say $P1 # prints 42
+
+=end PIR_FRAGMENT
+
+This example creates two C<Integer> PMCs, C<$P1> and C<$P2>, and gives the
+first one the value 42. It then uses C<assign> to pass the same integer value
+on to C<$P1>. Though C<$P0> increments, C<$P1> doesn't change. The result for
+C<assign> must have an existing object of the right type in it, because
+C<assign> neither creates a new duplicate object (as does C<clone>) or reuses
+the source object (as does C<=>).
+
+=head3 Properties
+
+X<properties>
+X<PMCs; properties>
+
+PMCs can have additional values attached to them as "properties" of the
+PMC. Most properties hold extra metadata about the PMC.
+
+The C<setprop>X<setprop opcode> opcode sets the value of a named property on a
+PMC. It takes three arguments: the PMC on which to set a property, the name of
+the property, and a PMC containing the value of the property.
+
+=begin PIR_FRAGMENT
+
+ setprop $P0, "name", $P1
+
+=end PIR_FRAGMENT
+
+The C<getprop>X<getprop opcode> opcode returns the value of a property. It
+takes two arguments: the name of the property and the PMC from which to
+retrieve the property value.
+
+=begin PIR_FRAGMENT
+
+ $P2 = getprop "name", $P0
+
+=end PIR_FRAGMENT
+
+This example creates a C<String> object in C<$P0> and an C<Integer> object with
+the value 1 in C<$P1>. C<setprop> sets a property named "eric" on the object in
+C<$P0> and gives the property the value of C<$P1>. C<getprop> retrieves the
+value of the property "eric" on C<$P0> and stores it in C<$P2>.
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "String"
+ $P0 = "Half-a-Bee"
+ $P1 = new "Integer"
+ $P1 = 1
+
+ setprop $P0, "eric", $P1 # set a property on $P0
+ $P2 = getprop "eric", $P0 # retrieve a property from $P0
+
+ say $P2 # prints 1
+
+=end PIR_FRAGMENT
+
+Parrot stores PMC properties in an associative array where the name of the
+property is the key.
+
+C<delprop>X<delprop opcode> deletes a property from a PMC.
+
+=begin PIR_FRAGMENT
+
+ delprop $P1, "constant" # delete property
+
+=end PIR_FRAGMENT
+
+You can fetch a complete hash of all properties on a PMC with
+C<prophash>X<prophash opcode>:
+
+=begin PIR_FRAGMENT
+
+ $P0 = prophash $P1 # set $P0 to the property hash of $P1
+
+=end PIR_FRAGMENT
+
+Fetching the value of a non-existent property returns an C<Undef> PMC.
+
+=head3 Vtable Functions
+
+X<vtables>
+X<vtable functions>
+
+You may have noticed that a simple operation sometimes has a different effect
+on different PMCs. Assigning a low-level integer value to a C<Integer> PMC sets
+its integer value of the PMC, but assigning that same integer to an ordered
+array sets the size of the array.
+
+Every PMC defines a standard set of low-level operations called vtable
+functions. When you perform an assignment like:
+
+ $P0 = 5
+
+... Parrot calls the C<set_integer_native> vtable function on the PMC referred
+to by register C<$P0>.
+
+Parrot has a fixed set of vtable functions, so that any PMC can stand in for
+any other PMC; they're polymorphic.N<Hence the name "Polymorphic Container".>
+Every PMC defines some behavior for every vtable function. The default behavior
+is to throw an exception reporting that the PMC doesn't implement that vtable
+function. The full set of vtable functions for a PMC defines the PMC's basic
+interface, but PMCs may also define methods to extend their behavior beyond the
+vtable set.
+
+=head2 Namespaces
+
+X<namespaces>
+
+Parrot performs operations on variables stored in small register sets local to
+each subroutine. For more complex tasks,N<...and for most high-level languages
+that Parrot supports.> it's also useful to have variables that live beyond the
+scope of a single subroutine. These variables may be global to the entire
+program or restricted to a particular library. Parrot stores long-lived
+variables in a hierarchy of namespaces.
+
+The opcodes C<set_global> and C<get_global> store and fetch a variable in a
+namespace:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "String"
+ $P0 = "buzz, buzz"
+ set_global "bee", $P0
+ # ...
+ $P1 = get_global "bee"
+ say $P1 # prints "buzz, buzz"
+
+=end PIR_FRAGMENT
+
+The first two statements in this example create a C<String> PMC in
+C<$P0> and assign it a value. In the third statement, C<set_global>
+stores that PMC as the named global variable C<bee>. At some later
+point in the program, C<get_global> retrieves the global variable by
+name, and stores it in C<$P1> to print.
+
+Namespaces can only store PMC variables. Parrot boxes all primitive integer,
+number, or string values into the corresponding PMCs before storing them in a
+namespace.
+
+The name of every variable stored in a particular namespace must be
+unique. You can't have store both an C<Integer> PMC and an array PMC
+both named "bee", stored in the same namespace.N<You may wonder why
+anyone would want to do this. We wonder the same thing, but Perl 5 does
+it all the time. The Perl 6 implementation on Parrot includes type
+sigils in the names of the variables it stores in namespaces so each
+name is unique, e.g. C<$bee>, C<@bee>....>
+
+=head3 Namespace Hierarchy
+
+X<hierarchical namespaces>
+X<namespaces; hierarchy>
+
+A single global namespace would be far too limiting for most languages or
+applications. The risk of accidental collisions -- where two libraries try to
+use the same name for some variable -- would be quite high for larger code
+bases. Parrot maintains a collection of namespaces arranged as a tree, with the
+C<parrot> namespace as the root. Every namespace you declare is a child of the
+C<parrot> namespace (or a child of a child....).
+
+The C<set_global> and C<get_global> opcodes both have alternate forms that take
+a key name to access a variable in a particular namespace within the tree. This
+code example stores a variable as C<bill> in the Duck namespace and retrieves
+it again:
+
+=begin PIR_FRAGMENT
+
+ set_global ["Duck"], "bill", $P0
+ $P1 = get_global ["Duck"], "bill"
+
+=end PIR_FRAGMENT
+
+The key name for the namespace can have multiple levels, which correspond to
+levels in the namespace hierarchy. This example stores a variable as C<bill> in
+the Electric namespace under the General namespace in the hierarchy.
+
+=begin PIR_FRAGMENT
+
+ set_global ["General";"Electric"], "bill", $P0
+ $P1 = get_global ["General";"Electric"], "bill"
+
+=end PIR_FRAGMENT
+
+X<root namespace>
+X<namespaces; root>
+
+The C<set_global> and C<get_global> opcode operate on the currently selected
+namespace. The default top-level namespace is the "root" namespace. The
+C<.namespace> directive allows you to declare any namespace for subsequent
+code. If you select the General Electric namespace, then store or retrieve the
+C<bill> variable without specifying a namespace, you will work with the General
+Electric bill, not the Duck bill.
+
+ .namespace ["General";"Electric"]
+ #...
+ set_global "bill", $P0
+ $P1 = get_global "bill"
+
+Passing an empty key to the C<.namespace> directive resets the selected
+namespace to the root namespace. The brackets are required even when the
+key is empty.
+
+ .namespace [ ]
+
+When you need to be absolutely sure you're working with the root namespace
+regardless of what namespace is currently active, use the C<set_root_global>
+and C<get_root_global> opcodes instead of C<set_global> and C<get_global>. This
+example sets and retrieves the variable C<bill> in the Dollar namespace, which
+is directly under the root namespace:
+
+=begin PIR_FRAGMENT
+
+ set_root_global ["Dollar"], "bill", $P0
+ $P1 = get_root_global ["Dollar"], "bill"
+
+=end PIR_FRAGMENT
+
+To prevent further collisions, each high-level language running on Parrot
+operates within its own virtual namespace root. The default virtual root is
+C<parrot>, and the C<.HLL> directive (for I<H>igh-I<L>evel I<L>anguage) selects
+an alternate virtual root for a particular high-level language:
+
+ .HLL 'ruby'
+
+The C<set_hll_global> and C<get_hll_global> opcodes are like C<set_root_global>
+and C<get_root_global>, except they always operate on the virtual root for the
+currently selected HLL. This example stores and retrieves a C<bill> variable in
+the Euro namespace, under the Dutch HLL namespace root:
+
+ .HLL 'Dutch'
+ #...
+ set_hll_global ["Euro"], "bill", $P0
+ $P1 = get_hll_global ["Euro"], "bill"
+
+=head3 NameSpace PMC
+
+Namespaces are just PMCs. They implement the standard vtable functions
+and a few extra methods. The C<get_namespace> opcode retrieves the
+currently selected namespace as a PMC object:
+
+ $P0 = get_namespace
+
+The C<get_root_namespace> opcode retrieves the namespace object for the root
+namespace. The C<get_hll_namespace> opcode retrieves the virtual root for the
+currently selected HLL.
+
+ $P0 = get_root_namespace
+ $P0 = get_hll_namespace
+
+Each of these three opcodes can take a key argument to retrieve a namespace
+under the currenly selected namespace, root namespace, or HLL root namespace:
+
+ $P0 = get_namespace ["Duck"]
+ $P0 = get_root_namespace ["General";"Electric"]
+ $P0 = get_hll_namespace ["Euro"]
+
+Once you have a namespace object you can use it to retrieve variables from the
+namespace instead of using a keyed lookup. This example first looks up the Euro
+namespace in the currently selected HLL, then retrieves the C<bill> variable
+from that namespace:
+
+ $P0 = get_hll_namespace ["Euro"]
+ $P1 = get_global $P0, "bill"
+
+Namespaces also provide a set of methods to provide more complex behavior than
+the standard vtable functions allow. The C<get_name> method returns the name of
+the namespace as a C<ResizableStringArray>:
+
+ $P3 = $P0.'get_name'()
+
+The C<get_parent> method retrieves a namespace object for the parent
+namespace that contains this one:
+
+ $P5 = $P0.'get_parent'()
+
+The C<get_class> method retrieves any Class PMC associated with the
+namespace:
+
+ $P6 = $P0.'get_class'()
+
+The C<add_var> and C<find_var> methods store and retrieve variables in a
+namespace in a language-neutral way:
+
+ $P0.'add_var'("bee", $P3)
+ $P1 = $P0.'find_var'("bee")
+
+The C<find_namespace> method looks up a namespace, just like the
+C<get_namespace> opcode:
+
+ $P1 = $P0.'find_namespace'("Duck")
+
+The C<add_namespace> method adds a new namespace as a child of the
+namespace object:
+
+ $P0.'add_namespace'($P1)
+
+The C<make_namespace> method looks up a namespace as a child of the
+namespace object and returns it. If the requested namespace doesn't
+exist, C<make_namespace> creates a new one and adds it under that name:
+
+ $P1 = $P0.'make_namespace'("Duck")
+
+=head3 Aliasing
+
+Just like regular assignment, the various operations to store a variable in a
+namespace only store a pointer to the PMC. If you modify the local PMC after
+storing in a namespace, those changes will also appear in the stored global. To
+store a true copy of the PMC, C<clone> it before you store it.
+
+Leaving the global variable as an alias for a local variable has its advantages.
+If you retrieve a stored global into a register and modify it:
+
+=begin PIR_FRAGMENT
+
+ $P1 = get_global "feather"
+ inc $P1
+
+=end PIR_FRAGMENT
+
+... you modify the value of the stored global, so you don't need to call
+C<set_global> again.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/pir/ch05_control_structures.pod (from r39796, trunk/docs/book/pir/ch05_control_structures.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/pir/ch05_control_structures.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/pir/ch05_control_structures.pod)
@@ -0,0 +1,344 @@
+=pod
+
+=head1 Control Structures
+
+The semantics of control structures in high-level languages vary broadly.
+Rather than dictating one particular set of semantics for control structures,
+or attempting to provide multiple implementations of common control structures
+to fit the semantics of all major target languages, PIR provides a simple set
+of conditional and unconditional branch instructions.N<In fact, all control
+structures in all languages ultimately compile down to conditional and
+unconditional branches, so you're just getting a peek into the inner workings
+of your software.>
+
+=head2 Conditionals and Unconditionals
+
+X<goto instruction> An unconditional branch always jumps to a specified label.
+PIR has only one unconditional branch instruction, C<goto>. In this example,
+the first C<print> statement never runs because the C<goto> always skips over
+it to the label C<skip_all_that>:
+
+=begin PIR_FRAGMENT
+
+ goto skip_all_that
+ say "never printed"
+
+ skip_all_that:
+ say "after branch"
+
+=end PIR_FRAGMENT
+
+A conditional branch jumps to a specified label only when a particular
+condition is true. The condition may be as simple as checking the truth of a
+particular variable or as complex as a comparison operation.
+
+In this example, the C<goto> skips to the label C<maybe_skip> only if the value
+stored in C<$I0> is true. If C<$I0> is false, it will print "might be printed"
+and then print "after branch":
+
+=begin PIR_FRAGMENT
+
+ if $I0 goto maybe_skip
+ say "might be printed"
+ maybe_skip:
+ say "after branch"
+
+=end PIR_FRAGMENT
+
+=head3 Boolean Truth
+
+X<boolean truth>
+X<PIR values; boolean>
+
+Parrot's C<if> and C<unless> instructions evaluate a variable as a boolean to
+decide whether to jump. In PIR, an integer is false if it's 0 and true if it's
+any non-zero value. A number is false if it's 0.0 and true otherwise. A string
+is false if it's the empty string (C<"">) or a string containing only a zero
+(C<"0">), and true otherwise. Evaluating a PMC as a boolean calls the vtable
+function C<get_bool> to check if it's true or false, so each PMC is free to
+determine what its boolean value should be.
+
+=head3 Comparisons
+
+X<PIR; comparison operators>
+
+In addition to a simple check for the truth of a variable, PIR provides a
+collection of comparison operations for conditional branches. These jump when
+the comparison is true.
+
+This example compares C<$I0> to C<$I1> and jumps to the label C<success>
+if C<$I0> is less than C<$I1>:
+
+=begin PIR_FRAGMENT
+
+ if $I0 < $I1 goto success
+ say "comparison false"
+ success:
+ say "comparison true"
+
+=end PIR_FRAGMENT
+
+The full set of comparison operators in PIR are C<==> (equal), C<!=>
+(not equal), C<E<lt>> (less than), C<E<lt>=> (less than or equal),
+C<E<gt>> (greater than), and C<E<gt>=> (greater than or equal).
+
+=head3 Complex Conditions
+
+PIR disallows nested expressions. You cannot embed a statement within another
+statement. If you have a more complex condition than a simple truth test or
+comparison, you must build up your condition with a series of instructions that
+produce a final, single truth value.
+
+This example performs two operations, addition and multiplication, then uses
+C<and> to check if the results of both operations were true. The C<and> opcode
+stores a boolean value (0 or 1) in the integer variable C<$I2>; the code uses
+this value in an ordinary truth test:
+
+=begin PIR_FRAGMENT
+
+ $I0 = 4 + 5
+ $I1 = 63 * 0
+ $I2 = and $I0, $I1
+
+ if $I2 goto true
+ say "maybe printed"
+ true:
+
+=end PIR_FRAGMENT
+
+=head2 If/Else Construct
+
+C<PIR; if>
+C<PIR; else>
+
+High-level languages often use the keywords I<if> and I<else> for simple
+conditional control structures. These control structures perform an action when
+a condition is true and skip the action when the condition is false. PIR's
+C<if> instruction can build up simple conditionals.
+
+This example checks the truth of the condition C<$I0>. If C<$I0> is true, it
+jumps to the C<do_it> label, and runs the body of the conditional construct. If
+C<$I0> is false, it continues on to the next statement, a C<goto> instruction
+that skips over the body of the conditional to the label C<dont_do_it>:
+
+=begin PIR_FRAGMENT
+
+ if $I0 goto do_it
+ goto dont_do_it
+ do_it:
+ say "in the body of the if"
+ dont_do_it:
+
+=end PIR_FRAGMENT
+
+The control flow of this example may seem backwards. In a high-level language,
+I<if> often means I<"if the condition is true, run the next few lines of
+code">. In an assembly language, it's often more straightforward to write
+I<"if the condition is true, B<skip> the next few lines of code">. Because of
+the reversed logic, you may find it easier to build a simple conditional
+construct using the C<unless> instruction instead of C<if>.
+
+=begin PIR_FRAGMENT
+
+ unless $I0 goto dont_do_it
+ say "in the body of the if"
+ dont_do_it:
+
+=end PIR_FRAGMENT
+
+This example produces the same output as the previous example, but the logic is
+simpler. When C<$I0> is true, C<unless> does nothing and the body of the
+conditional runs. When C<$I0> is false, C<unless> skips over the body of the
+conditional by jumping to C<dont_do_it>.
+
+An I<if/else> control structure is easier to build using the C<if> instruction
+than C<unless>. To build an I<if/else>, insert the body of the else right
+after the first C<if> instruction.
+
+This example checks if C<$I0> is true. If so, it jumps to the label C<true>
+and runs the body of the I<if> construct. If C<$I0> is false, the C<if>
+instruction does nothing, and the code continues to the body of the I<else>
+construct. When the body of the else has finished, the C<goto> jumps to the end
+of the I<if/else> control structure by skipping over the body of the I<if>
+construct:
+
+ if $I0 goto true
+ say "in the body of the else"
+ goto done
+ true:
+ say "in the body of the if"
+ done:
+
+=head2 Switch Construct
+
+X<switch>
+X<PIR; switch>
+
+A I<switch> control structure selects one action from a list of possible
+actions by comparing a single variable to a series of values until it finds one
+that matches. The simplest way to achieve this in PIR is with a series of
+C<unless> instructions:
+
+=begin PIR_FRAGMENT
+
+ $S0 = 'a'
+
+ option1:
+ unless $S0 == 'a' goto option2
+ say "matched: a"
+ goto end_of_switch
+
+ option2:
+ unless $S0 == 'b' goto default
+ say "matched: b"
+ goto end_of_switch
+
+ default:
+ say "I don't understand"
+
+ end_of_switch:
+
+=end PIR_FRAGMENT
+
+This example uses C<$S0> as the I<case> of the switch construct. It
+compares that case against the first value C<a>. If they match, it prints
+the string "matched: a", then jumps to the end of the switch at the
+label C<end_of_switch>. If the first case doesn't match C<a>, the
+C<goto> jumps to the label C<option2> to check the second option.
+The second option compares the case against the value C<b>. If they
+match, it prints the string "matched: b", then jumps to the end of the
+switch. If the case doesn't match the second option, the C<goto>
+goes on to the default case, prints "I don't understand", and continues
+to the end of the switch.
+
+=head2 Do-While Loop
+
+A I<do-while>X<do-while loop> loop runs the body of the loop once, then
+checks a condition at the end to decide whether to repeat it. A single
+conditional branch can build this style of loop:
+
+=begin PIR_FRAGMENT
+
+ $I0 = 0 # counter
+
+ redo: # start of loop
+ inc $I0
+ say $I0
+ if $I0 < 10 goto redo # end of loop
+
+=end PIR_FRAGMENT
+
+This example prints the numbers 1 to 10. The first time through, it executes
+all statements up to the C<if> instruction. If the condition evaluates as true
+(C<$I0> is less than 10), it jumps to the C<redo> label and runs the loop body
+again. The loop ends when the condition evaluates as false.
+
+Here's a slightly more complex example that calculates the factorial C<5!>:
+
+=begin PIR_FRAGMENT
+
+ .local int product, counter
+
+ product = 1
+ counter = 5
+
+ redo: # start of loop
+ product *= counter
+ dec counter
+ if counter > 0 goto redo # end of loop
+
+ say product
+
+=end PIR_FRAGMENT
+
+Each time through the loop it multiplies C<product> by the current value of the
+C<counter >, decrements the counter, and jumps to the start of the loop. The
+loop ends when C<counter> has counted down to 0.
+
+=head2 While Loop
+
+X<while-style loop> A I<while> loop tests the condition at the start of the
+loop instead of at the end. This style of loop needs a conditional branch
+combined with an unconditional branch. This example also calculates a
+factorial, but with a I<while> loop:
+
+=begin PIR_FRAGMENT
+
+ .local int product, counter
+ product = 1
+ counter = 5
+
+ redo: # start of loop
+ if counter <= 0 goto end_loop
+ product *= counter
+ dec counter
+ goto redo
+ end_loop: # end of loop
+
+ say product
+
+=end PIR_FRAGMENT
+
+This code tests the counter C<counter> at the start of the loop to see if it's
+less than or equal to 0, then multiplies the current product by the counter and
+decrements the counter. At the end of the loop, it unconditionally jumps back
+to the start of the loop and tests the condition again. The loop ends when the
+counter C<counter> reaches 0 and the C<if> jumps to the C<end_loop> label. If
+the counter is a negative number or zero before the loop starts the first time,
+the body of the loop will never execute.
+
+=head2 For Loop
+
+X<for loop>
+
+A I<for> loop is a counter-controlled loop with three declared components: a
+starting value, a condition to determine when to stop, and an operation to step
+the counter to the next iteration. A I<for> loop in C looks something like:
+
+ for (i = 1; i <= 10; i++) {
+ ...
+ }
+
+where C<i> is the counter, C<i = 1> sets the start value, C<<i <= 10>> checks
+the stop condition, and C<i++> steps to the next iteration. A I<for> loop in
+PIR requires one conditional branch and two unconditional branches.
+
+=begin PIR_FRAGMENT
+
+ loop_init:
+ .local int counter
+ counter = 1
+
+ loop_test:
+ if counter <= 10 goto loop_body
+ goto loop_end
+
+ loop_body:
+ say counter
+
+ loop_continue:
+ inc counter
+ goto loop_test
+
+ loop_end:
+
+=end PIR_FRAGMENT
+
+The first time through the loop, this example sets the initial value of the
+counter in C<loop_init>. It then goes on to test that the loop condition is met
+in C<loop_test>. If the condition is true (C<counter> is less than or equal to
+10) it jumps to C<loop_body> and executes the body of the loop. If the the
+condition is false, it will jump straight to C<loop_end> and the loop will end.
+The body of the loop prints the current counter then goes on to
+C<loop_continue>, which increments the counter and jumps back up to
+C<loop_test> to continue on to the next iteration. Each iteration through the
+loop tests the condition and increments the counter, ending the loop when the
+condition is false. If the condition is false on the very first iteration, the
+body of the loop will never run.
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/pir/ch06_subroutines.pod (from r39796, trunk/docs/book/pir/ch06_subroutines.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/pir/ch06_subroutines.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/pir/ch06_subroutines.pod)
@@ -0,0 +1,1288 @@
+=pod
+
+=head1 Subroutines
+
+X<subroutine>
+Subroutines in PIR are roughly equivalent to the subroutines or methods
+of a high-level language. They're the most basic building block of code
+reuse in PIR. Each high-level language has different syntax and
+semantics for defining and calling subroutines, so Parrot's subroutines
+need to be flexible enough to handle a broad array of behaviors.
+
+A subroutine declaration starts with the C<.sub> directive and ends with
+the C<.end> directive. This example defines a subroutine named
+C<hello> that prints a string "Hello, Polly.":
+
+=begin PIR
+
+ .sub 'hello'
+ say "Hello, Polly."
+ .end
+
+=end PIR
+
+The quotes around the subroutine name are optional as long as the name of the
+subroutine uses only plain alphanumeric ASCII characters. You must use quotes
+if the subroutine name uses Unicode characters, characters from some other
+character set or encoding, or is otherwise an invalid PIR identifier.
+
+A subroutine call consists of the name of the subroutine to call followed by a
+list of (zero or more) arguments in parentheses. You may precede the call with
+a list of (zero or more) return values. This example calls the subroutine
+C<fact> with two arguments and assigns the result to C<$I0>:
+
+ $I0 = 'fact'(count, product)
+
+=head2 Modifiers
+
+X<modifier>
+X<subroutines; modifier>
+
+A modifier is an annotation to a basic subroutine declarationN<or parameter
+declaration> that selects an optional feature. Modifiers all start with a colon
+(C<:>). A subroutine can have multiple modifiers.
+
+When you execute a PIR file as a program, Parrot normally runs the first
+subroutine it encounters, but you can mark any subroutine as the first
+one to run with the C<:main> modifier:
+
+=begin PIR
+
+ .sub 'first'
+ say "Polly want a cracker?"
+ .end
+
+ .sub 'second' :main
+ say "Hello, Polly."
+ .end
+
+=end PIR
+
+This code prints "Hello, Polly." but not "Polly want a cracker?". The C<first>
+subroutine is first in the source code, but C<second> has the C<:main> modifier.
+Parrot will never call C<first> in this program. If you remove the C<:main>
+modifier, the code will print "Polly want a cracker?" instead.
+
+The C<:load> modifier tells Parrot to run the subroutine when it loads the
+current file as a library. The C<:init> modifier tells Parrot to run the
+subroutine only when it executes the file as a program (and I<not> as a
+library). The C<:immediate> modifier tells Parrot to run the subroutine as
+soon as it gets compiled. The C<:postcomp> modifier also runs the subroutine
+right after compilation, but only if the subroutine was declared in the main
+program file (when I<not> loaded as a library).
+
+By default, Parrot stores all subroutines in the namespace currently active at
+the point of their declaration. The C<:anon> modifier tells Parrot not to store
+the subroutine in the namespace. The C<:nsentry> modifier stores the subroutine
+in the currenly active namespace with a different name. For example, Parrot
+will store this subroutine in the current namespace as C<bar>, not C<foo>:
+
+=begin PIR
+
+ .sub 'foo' :nsentry('bar')
+ #...
+ .end
+
+=end PIR
+
+Chapter 7 on I<"Classes and Objects"> explains other subroutine modifiers.
+
+=head2 Parameters and Arguments
+
+X<.param directive>
+The C<.param> directive defines the parameters for the subroutine and
+creates local named variables for them (similar to C<.local>):
+
+=begin PIR_FRAGMENT
+
+ .param int c
+
+=end PIR_FRAGMENT
+
+X<.return directive>
+The C<.return> directive returns control flow to the calling subroutine. To
+return results, pass them as arguments to C<.return>.
+
+=begin PIR_FRAGMENT
+
+ .return($P0)
+
+=end PIR_FRAGMENT
+
+This example implements the factorial algorithm using two subroutines, C<main>
+and C<fact>:
+
+=begin PIR
+
+ # factorial.pir
+ .sub 'main' :main
+ .local int count
+ .local int product
+ count = 5
+ product = 1
+
+ $I0 = 'fact'(count, product)
+
+ say $I0
+ .end
+
+ .sub 'fact'
+ .param int c
+ .param int p
+
+ loop:
+ if c <= 1 goto fin
+ p = c * p
+ dec c
+ branch loop
+ fin:
+ .return (p)
+ .end
+
+=end PIR
+
+This example defines two local named variables, C<count> and C<product>, and
+assigns them the values 1 and 5. It calls the C<fact> subroutine with both
+variables as arguments. The C<fact> subroutine uses C<.param> to retrieve
+these parameters and C<.return> to return the result. The final printed result
+is 120.
+
+=head3 Positional Parameters
+
+X<positional parameters>
+The default way of matching the arguments passed in a subroutine call to
+the parameters defined in the subroutine's declaration is by position.
+If you declare three parameters -- an integer, a number, and a string:
+
+=begin PIR
+
+ .sub 'foo'
+ .param int a
+ .param num b
+ .param string c
+ # ...
+ .end
+
+=end PIR
+
+... then calls to this subroutine must also pass three arguments -- an integer,
+a number, and a string:
+
+=begin PIR_FRAGMENT
+
+ 'foo'(32, 5.9, "bar")
+
+=end PIR_FRAGMENT
+
+Parrot will assign each argument to the corresponding parameter in order from
+first to last. Changing the order of the arguments or leaving one out is an
+error.
+
+=head3 Named Parameters
+
+X<named parameters> Named parameters are an alternative to positional
+parameters. Instead of passing parameters by their position in the string,
+Parrot assigns arguments to parameters by their name. Consequencly you may
+pass named parameters in any order. Declare named parameters with with the
+C<:named> modifier.
+
+This example declares two named parameters in the subroutine C<shoutout> --
+C<name> and C<years> -- each declared with C<:named> and followed by the name
+to use when pass arguments. The string name can match the parameter name (as
+with the C<name> parameter), but it can also be different (as with the C<years>
+parameter):
+
+=begin PIR
+
+ .sub 'shoutout'
+ .param string name :named("name")
+ .param string years :named("age")
+ $S0 = "Hello " . name
+ $S1 = "You are " . years
+ $S1 .= " years old"
+ say $S0
+ say $S1
+ .end
+
+=end PIR
+
+Pass named arguments to a subroutine as a series of name/value pairs, with the
+elements of each pair separated by an arrow C<< => >>.
+
+=begin PIR
+
+ .sub 'main' :main
+ 'shoutout'("age" => 42, "name" => "Bob")
+ .end
+
+=end PIR
+
+The order of the arguments does not matter:
+
+=begin PIR
+
+ .sub 'main' :main
+ 'shoutout'("name" => "Bob", "age" => 42)
+ .end
+
+=end PIR
+
+=head3 Optional Parameters
+
+X<optional parameters> Another alternative to the required positional
+parameters is optional parameters. Some parameters are unnecessary for certain
+calls. Parameters marked with the C<:optional> modifier do not produce errors
+about invalid parameter counts if they are not present. A subroutine with
+optional parameters should gracefully handle the missing argument, either by
+providing a default value or by performing an alternate action that doesn't
+need that value.
+
+Checking the value of the optional parameter isn't enough to know whether the
+call passed such an argument, because the user might have passed a null or
+false value intentionally. PIR also provides an C<:opt_flag> modifier for a
+boolean check whether the caller passed an argument:
+
+=begin PIR_FRAGMENT
+
+ .param string name :optional
+ .param int has_name :opt_flag
+
+=end PIR_FRAGMENT
+
+When an integer parameter with the C<:opt_flag> modifier immediately follows an
+C<:optional> parameter, it will be true if the caller passed the argument and
+false otherwise.
+
+This example demonstrates how to provide a default value for an optional
+parameter:
+
+=begin PIR_FRAGMENT
+
+ .param string name :optional
+ .param int has_name :opt_flag
+
+ if has_name goto we_have_a_name
+ name = "default value"
+ we_have_a_name:
+
+=end PIR_FRAGMENT
+
+When the C<has_name> parameter is true, the C<if> control statement jumps to
+the C<we_have_a_name> label, leaving the C<name> parameter unmodified. When
+C<has_name> is false (when the caller passed no argument for C<name>) the C<if>
+statement does nothing. The next line sets the C<name> parameter to a default
+value.
+
+The C<:opt_flag> parameter never takes an argument from the passed-in
+argument list. It's purely for bookkeeping within the subroutine.
+
+Optional parameters can be positional or named parameters. Optional parameters
+must appear at the end of the list of positional parameters after all the
+required parameters. An optional I<and> named parameter must immediately
+precede its C<:opt_flag> parameter:
+
+=begin PIR
+
+ .sub 'question'
+ .param int value :named("answer") :optional
+ .param int has_value :opt_flag
+ #...
+ .end
+
+=end PIR
+
+You can call this subroutine with a named argument or with no argument:
+
+=begin PIR_FRAGMENT
+
+ 'question'("answer" => 42)
+ 'question'()
+
+=end PIR_FRAGMENT
+
+=head3 Aggregating Parameters
+
+X<subroutines; aggregate>
+X<slurpy>
+
+Another alternative to a sequence of positional parameters is an aggregating
+parameter which bundles a list of arguments into a single parameter. The
+C<:slurpy> created a single array parameter containing all the provided
+arguments:
+
+=begin PIR_FRAGMENT
+
+ .param pmc args :slurpy
+ $P0 = args[0] # first argument
+ $P1 = args[1] # second argument
+
+=end PIR_FRAGMENT
+
+As an aggregating parameter will consume all subsequent parameters, you may use
+an aggregating parameter with other positional parameters only after all other
+positional parameters:
+
+=begin PIR_FRAGMENT
+
+ .param string first
+ .param int second
+ .param pmc the_rest :slurpy
+
+ $P0 = the_rest[0] # third argument
+ $P1 = the_rest[1] # fourth argument
+
+=end PIR_FRAGMENT
+
+When you combine C<:named> and C<:slurpy> on a parameter, the result is a
+single associative array containing the named arguments passed into the
+subroutine call:
+
+=begin PIR_FRAGMENT
+
+ .param pmc all_named :slurpy :named
+
+ $P0 = all_named['name'] # 'name' => 'Bob'
+ $P1 = all_named['age'] # 'age' => 42
+
+=end PIR_FRAGMENT
+
+=head3 Flattening Arguments
+
+X<subroutines; flattening>
+X<flattening>
+
+A flattening argument breaks up a single argument to fill multiple parameters.
+It's the complement of an aggregating parameter. The C<:flat> modifier splits
+arguments (and return values) into a flattened list. Passing an array PMC to a
+subroutine with C<:flat>:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "ResizablePMCArray"
+ $P0[0] = "Bob"
+ $P0[1] = 42
+ 'foo'($P0 :flat)
+
+=end PIR_FRAGMENT
+
+... allows the elements of that array to fill the required parameters:
+
+=begin PIR_FRAGMENT
+
+ .param string name # Bob
+ .param int age # 42
+
+=end PIR_FRAGMENT
+
+=head3 Arguments on the Command Line
+
+X<command-line arguments>
+
+Arguments passed to a PIR program on the command line are available to the
+C<:main> subroutine of that program as strings in a C<ResizableStringArray>
+PMC. If you call a program F<args.pir>, passing it three arguments:
+
+ $ parrot args.pir foo bar baz
+
+... they will be accesible at index 1, 2, and 3 of the PMC parameter.N<Index 0
+is unused.>
+
+=begin PIR
+
+ .sub 'main' :main
+ .param pmc all_args
+ $S1 = all_args[1] # foo
+ $S2 = all_args[2] # bar
+ $S3 = all_args[3] # baz
+ # ...
+ .end
+
+=end PIR
+
+Because C<all_args> is a C<ResizableStringArray> PMC, you can loop over the
+results, access them individually, or even modify them.
+
+=head2 Compiling and Loading Libraries
+
+X<PIR; libraries>
+
+In addition to running PIR files on the command-line, you can also load a
+library of pre-compiled bytecode directly into your PIR source file. The
+C<load_bytecode>X<load_bytecode opcode> opcode takes a single argument: the
+name of the bytecode file to load. If you create a file named F<foo_file.pir>
+containing a single subroutine:
+
+=begin PIR
+
+ # foo_file.pir
+ .sub 'foo_sub' # .sub stores a global sub
+ say "in foo_sub"
+ .end
+
+=end PIR
+
+... and compile it to bytecode using the C<-o> command-line switch:
+
+ $ parrot -o foo_file.pbc foo_file.pir
+
+... you can then load the compiled bytecode into F<main.pir> and directly
+call the subroutine defined in F<foo_file.pir>:
+
+=begin PIR
+
+ # main.pir
+ .sub 'main' :main
+ load_bytecode "foo_file.pbc" # compiled foo_file.pir
+ foo_sub()
+ .end
+
+=end PIR
+
+The C<load_bytecode> opcode also works with source files, as long as Parrot has
+a compiler registered for that type of file:
+
+=begin PIR
+
+ # main2.pir
+ .sub 'main' :main
+ load_bytecode "foo_file.pir" # PIR source code
+ foo_sub()
+ .end
+
+=end PIR
+
+=head2 Sub PMC
+
+X<PMCs; Sub>
+
+Subroutines are a PMC type in Parrot. You can store them in PMC registers and
+manipulate them just as you do with other PMCs. Parrot stores subroutines in
+namespaces; retrieve them with the C<get_global> opcode:
+
+=begin PIR_FRAGMENT
+
+ $P0 = get_global "my_sub"
+
+=end PIR_FRAGMENT
+
+To find a subroutine in a different namespace, first look up the appropriate
+the namespace object, then use that as the first parameter to C<get_global>:
+
+=begin PIR_FRAGMENT
+
+ $P0 = get_namespace ["My";"Namespace"]
+ $P1 = get_global $P0, "my_sub"
+
+=end PIR_FRAGMENT
+
+You can invoke a Sub object directly:
+
+=begin PIR_FRAGMENT
+
+ $P0(1, 2, 3)
+
+=end PIR_FRAGMENT
+
+You can get or even I<change> its name:
+
+=begin PIR_FRAGMENT
+
+ $S0 = $P0 # Get the current name
+ $P0 = "my_new_sub" # Set a new name
+
+=end PIR_FRAGMENT
+
+You can get a hash of the complete metadata for the subroutine:
+
+=begin PIR_FRAGMENT
+
+ $P1 = inspect $P0
+
+=end PIR_FRAGMENT
+
+... which contains the fields:
+
+=over 4
+
+=item * pos_required
+
+The number of required positional parameters
+
+=item * pos_optional
+
+The number of optional positional parameters
+
+=item * named_required
+
+The number of required named parameters
+
+=item * named_optional
+
+The number of optional named parameters
+
+=item * pos_slurpy
+
+True if the sub has an aggregating parameter for positional args
+
+=item * named_slurpy
+
+True if the sub has an aggregating parameter for named args
+
+=back
+
+Instead of fetching the entire inspection hash, you can also request
+individual pieces of metadata:
+
+=begin PIR_FRAGMENT
+
+ $P0 = inspect $P0, "pos_required"
+
+=end PIR_FRAGMENT
+
+The C<arity> method on the sub object returns the total number of defined
+parameters of all varieties:
+
+=begin PIR_FRAGMENT
+
+ $I0 = $P0.'arity'()
+
+=end PIR_FRAGMENT
+
+The C<get_namespace> method on the sub object fetches the namespace PMC which
+contains the Sub:
+
+=begin PIR_FRAGMENT
+
+ $P1 = $P0.'get_namespace'()
+
+=end PIR_FRAGMENT
+
+=head2 Evaluating a Code String
+
+X<code strings, evaluating>
+One way of producing a code object during a running program is by compiling a
+code string. In this case, it's a X<bytecode segment object> bytecode
+segment object.
+
+The first step is to fetch a compiler object for the target language:
+
+=begin PIR_FRAGMENT
+
+ $P1 = compreg "PIR"
+
+=end PIR_FRAGMENT
+
+Parrot registers a compiler for PIR by default, so it's always
+available. The following example fetches a compiler object for PIR and
+places it in the named variable C<compiler>. It then generates a code
+object from a string by calling C<compiler> as a subroutine and places
+the resulting bytecode segment object into the named variable
+C<generated> and then invokes it as a subroutine:
+
+=begin PIR_FRAGMENT
+
+ .local pmc compiler, generated
+ compiler = compreg "PIR"
+ generated = compiler(".sub foo\n$S1 = 'in eval'\nprint $S1\n.end")
+ generated()
+ say "back again"
+
+=end PIR_FRAGMENT
+
+You can register a compiler or assembler for any language inside the
+Parrot core and use it to compile and invoke code from that language.
+
+In the following example, the C<compreg> opcode registers the
+subroutine-like object C<$P10> as a compiler for the language
+"MyLanguage":
+
+=begin PIR_FRAGMENT
+
+ compreg "MyLanguage", $P10
+
+=end PIR_FRAGMENT
+
+=head2 Lexicals
+
+X<lexical variables>
+X<scope>
+Variables stored in a namespace are global variables. They're accessible from
+anywhere in the program if you specify the right namespace path. High-level
+languages also have lexical variables which are only accessible from the local
+section of code (or I<scope>) where they appear, or in a section of code
+embedded within that scope.N<A scope is roughly equivalent to a block in
+C.> In PIR, the section of code between a C<.sub> and a C<.end> defines
+a scope for lexical variables.
+
+While Parrot stores global variables in namespaces, it stores lexical variables
+in lexical padsN<Think of a pad like a house.>. Each lexical scope has its own
+pad. The C<store_lex> opcode stores a lexical variable in the current pad. The
+C<find_lex> opcode retrieves a variable from the current pad:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new "Integer" # create a variable
+ $P0 = 10 # assign value to it
+ store_lex "foo", $P0 # store the var with the variable name "foo"
+ # ...
+ $P1 = find_lex "foo" # get the var "foo" into $P1
+ say $P1 # prints 10
+
+=end PIR_FRAGMENT
+
+The C<.lex> command defines a local variable that follows these scoping
+rules:
+
+=begin PIR_FRAGMENT
+
+ .local int foo
+ .lex 'foo', foo
+
+=end PIR_FRAGMENT
+
+=head3 LexPad and LexInfo PMCs
+
+Parrot uses two different PMCs to store information about a subroutine's
+lexical variables: the C<LexPad> PMC and the C<LexInfo> PMC. Neither of these
+PMC types are usable directly from PIR code; Parrot uses them internally to
+store information about lexical variables.
+
+C<LexInfo> PMCs store information about lexical variables at compile time.
+Parrot generates this read-only information during compilation to represent
+what it knows about lexical variables. Not all subroutines get a C<LexInfo> PMC
+by default; subroutines need to indicate to Parrot that they require a
+C<LexInfo> PMC. One way to do this is with the C<.lex> directive. Of course,
+the C<.lex> directive only works for languages that know the names of there
+lexical variables at compile time. Languages where this information is not
+available can mark the subroutine with C<:lex> instead.
+
+C<LexPad> PMCs store run-time information about lexical variables. This
+includes their current values and type information. Parrot creates a new
+C<LexPad> PMC for subs that have a C<LexInfo> PMC already. It does so
+for each invocation of the subroutine, which allows for recursive
+subroutine calls without overwriting lexical variables.
+
+The C<get_lexinfo> method on a sub retrieves its associated C<LexInfo>
+PMC:
+
+=begin PIR_FRAGMENT
+
+ $P0 = get_global "MySubroutine"
+ $P1 = $P0.'get_lexinfo'()
+
+=end PIR_FRAGMENT
+
+The C<LexInfo> PMC supports a few introspection operations:
+
+=begin PIR_FRAGMENT
+
+ $I0 = elements $P1 # Get the number of lexical variables from it
+ $P0 = $P1["name"] # Get the entry for lexical variable "name"
+
+=end PIR_FRAGMENT
+
+There is no easy way to retrieve the current C<LexPad> PMC in a given
+subroutine, but they are of limited use in PIR.
+
+=head3 Nested Scopes
+
+PIR has no separate syntax for blocks or lexical scopes; subroutines
+define lexical scopes in PIR. Because PIR disallows nested
+C<.sub>/C<.end> declarations, it needs a way to identify which lexical
+scopes are the parents of inner lexical scopes. The C<:outer> modifier
+declares a subroutine as a nested inner lexical scope of another
+existing subroutine. The modifier takes one argument, the name of the
+outer subroutine:
+
+=begin PIR
+
+ .sub 'foo'
+ # defines lexical variables
+ .end
+
+ .sub 'bar' :outer('foo')
+ # can access foo's lexical variables
+ .end
+
+=end PIR
+
+Sometimes a name alone isn't sufficient to uniquely identify the outer
+subroutine. The C<:subid> modifier allows the outer subroutine to declare a
+truly unique name usable with C<:outer>:
+
+=begin PIR
+
+ .sub 'foo' :subid('barsouter')
+ # defines lexical variables
+ .end
+
+ .sub 'bar' :outer('barsouter')
+ # can access foo's lexical variables
+ .end
+
+=end PIR
+
+The C<get_outer> method on a C<Sub> PMC retrieves its C<:outer> sub.
+
+=begin PIR_FRAGMENT
+
+ $P1 = $P0.'get_outer'()
+
+=end PIR_FRAGMENT
+
+If there is no C<:outer> sub, this will return a null PMC. The
+C<set_outer> method on a C<Sub> object sets the C<:outer> sub:
+
+=begin PIR_FRAGMENT
+
+ $P0.'set_outer'($P1)
+
+=end PIR_FRAGMENT
+
+=head3 Scope and Visibility
+
+High-level languages such as Perl, Python, and Ruby allow nested scopes,
+or blocks within blocks that have their own lexical variables. This
+construct is common even in C:
+
+ {
+ int x = 0;
+ int y = 1;
+ {
+ int z = 2;
+ /* x, y, and z are all visible here */
+ }
+
+ /* only x and y are visible here */
+ }
+
+In the inner block, all three variables are visible. The variable C<z>
+is only visible inside that block. The outer block has no knowledge of
+C<z>. A naE<iuml>ve translation of this code to PIR might be:
+
+=begin PIR_FRAGMENT
+
+ .param int x
+ .param int y
+ .param int z
+ x = 0
+ y = 1
+ z = 2
+ #...
+
+=end PIR_FRAGMENT
+
+This PIR code is similar, but the handling of the variable C<z> is different:
+C<z> is visible throughout the entire current subroutine. It was not visible
+throughout the entire C function. A more accurate translation of the C scopes
+uses C<:outer> PIR subroutines instead:
+
+=begin PIR
+
+ .sub 'MyOuter'
+ .local pmc x, y
+ .lex 'x', x
+ .lex 'y', y
+ x = new 'Integer'
+ x = 10
+ 'MyInner'()
+ # only x and y are visible here
+ say y # prints 20
+ .end
+
+ .sub 'MyInner' :outer('MyOuter')
+ .local pmc x, new_y, z
+ .lex 'z', z
+ find_lex x, 'x'
+ say x # prints 10
+ new_y = new 'Integer'
+ new_y = 20
+ store_lex 'y', new_y
+ .end
+
+=end PIR
+
+The C<find_lex> and C<store_lex> opcodes don't just access the value of a
+variable directly in the scope where it's declared, they interact with
+the C<LexPad> PMC to find lexical variables within outer lexical scopes.
+All lexical variables from an outer lexical scope are visible from the
+inner lexical scope.
+
+Note that you can only store PMCs -- not primitive types -- as lexicals.
+
+=head2 Multiple Dispatch
+
+X<multiple dispatch>
+X<multis>
+X<signature>
+
+Multiple dispatch subroutines (or I<multis>) have several variants with the
+same name but different sets of parameters. The set of parameters for a
+subroutine is its I<signature>. When a multi is called, the dispatch operation
+compares the arguments passed in to the signatures of all the variants and
+invokes the subroutine with the best match.
+
+Parrot stores all multiple dispatch subs with the same name in a namespace
+within a single PMC called a C<MultiSub>. The C<MultiSub> is an invokable list
+of subroutines. When a multiple dispatch sub is called, the C<MultiSub> PMC
+searches its list of variants for the best matching candidate.
+
+The C<:multi> modifier on a C<.sub> declares a C<MultiSub>:
+
+=begin PIR
+
+ .sub 'MyMulti' :multi()
+ # does whatever a MyMulti does
+ .end
+
+=end PIR
+
+Each variant in a C<MultiSub> must have a unique type or number of parameters
+declared, so the dispatcher can calculate a best match. If you had two variants
+that both took four integer parameters, the dispatcher would never be able to
+decide which one to call when it received four integer arguments.
+
+X<multi signature>
+The C<:multi> modifier takes one or more arguments defining the I<multi
+signature>. The multi signature tells Parrot what particular combination
+of input parameters the multi accepts:
+
+=begin PIR
+
+ .sub 'Add' :multi(I, I)
+ .param int x
+ .param int y
+ $I0 = x + y
+ .return($I0)
+ .end
+
+ .sub 'Add' :multi(N, N)
+ .param num x
+ .param num y
+ $N0 = x + y
+ .return($N0)
+ .end
+
+ .sub 'Start' :main
+ $I0 = Add(1, 2) # 3
+ $N0 = Add(3.14, 2.0) # 5.14
+ $S0 = Add("a", "b") # ERROR! No (S, S) variant!
+ .end
+
+=end PIR
+
+Multis can take I, N, S, and P types, but they can also use C<_> (underscore)
+to denote a wildcard, and a string which names a PMC type:
+
+=begin PIR
+
+ .sub 'Add' :multi(I, I) # Two integers
+ #...
+ .end
+
+ .sub 'Add' :multi(I, 'Float') # An integer and Float PMC
+ #...
+ .end
+
+ .sub 'Add' :multi('Integer', _) # An Integer PMC and a wildcard
+ #...
+ .end
+
+=end PIR
+
+When you call a C<MultiSub>, Parrot will try to take the most specific
+best-match variant, but will fall back to more general variants if it
+cannot find a perfect match. If you call C<'Add'(1, 2)>, Parrot will
+dispatch to the C<(I, I)> variant. If you call C<'Add'(1, "hi")>, Parrot
+will match the C<(I, _)> variant, as the string in the second argument
+doesn't match C<I> or C<Float>. Parrot can also promote one of the I,
+N, or S values to an Integer, Float, or String PMC.
+
+X<Manhattan distance>
+
+To make the decision about which multi variant to call, Parrot
+calculates the I<Manhattan Distance> between the argument signature and
+the parameter signature of each variant. Every difference between each
+element counts as one step. A difference can be a promotion from a
+primitive type to a PMC, the conversion from one primitive type to
+another, or the matching of an argument to a C<_> wildcard. After Parrot
+calculates the distance to each variant, it calls the one with the
+lowest distance. Notice that it's possible to define a variant that is
+impossible to call: for every potential combination of arguments there
+is a better match. This is uncommon, but possible in systems with many
+multis and a limited number of data types.
+
+=head2 Continuations
+
+X<continuations>
+
+Continuations are subroutines that take snapshots of control flow. They are
+frozen images of the current execution state of the VM. Once you have a
+continuation, you can invoke it to return to the point where the continuation
+was first created. It's like a magical timewarp that allows the developer to
+arbitrarily move control flow back to any previous point in the program.
+
+Continuations are like any other PMC; create one with the C<new> opcode:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'Continuation'
+
+=end PIR_FRAGMENT
+
+The new continuation starts in an undefined state. If you attempt to invoke a
+new continuation without initializing it, Parrot will throw an exception. To
+prepare the continuation for use, assign it a destination label with the
+C<set_addr> opcode:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'Continuation'
+ set_addr $P0, my_label
+
+ my_label:
+ # ...
+
+=end PIR_FRAGMENT
+
+To jump to the continuation's stored label and return the context to the state
+it was in I<at the point of its creation>, invoke the continuation:
+
+=begin PIR_FRAGMENT
+
+ $P0()
+
+=end PIR_FRAGMENT
+
+Even though you can use the subroutine call notation C<$P0()> to invoke
+the continuation, you cannot pass arguments or obtain return values.
+
+=head3 Continuation Passing Style
+
+X<continuation passing style>
+X<CPS>
+
+Parrot uses continuations internally for control flow. When Parrot
+invokes a subroutine, it creates a continuation representing the current
+point in the program. It passes this continuation as an invisible
+parameter to the subroutine call. To return from that subroutine, Parrot
+invokes the continuation to return to the point of creation of that
+continuation. If you have a continuation, you can invoke it to return
+to its point of creation any time you want.
+
+This type of flow control -- invoking continuations instead of
+performing bare jumps -- is Continuation Passing Style (CPS).
+
+=head3 Tailcalls
+
+Many subroutines set up and call another subroutine and then return the
+result of the second call directly. This is a X<tailcall> tailcall, and is an
+important opportunity for optimization. Here's a contrived example in
+pseudocode:
+
+ call add_two(5)
+
+ subroutine add_two(value)
+ value = add_one(value)
+ return add_one(value)
+
+In this example, the subroutine C<add_two> makes two calls to C<add_one>. The
+second call to C<add_one> is the return value. C<add_one> gets called; its
+result gets returned to the caller of C<add_two>. Nothing in C<add_two> uses
+that return value directly.
+
+A simple optimization is available for this type of code. The second call to
+C<add_one> can return to the same place that C<add_two> returns; it's perfectly
+safe and correct to use the same return continuation that C<add_two> uses. The
+two subroutine calls can share a return continuation.
+
+X<.tailcall directive>
+
+PIR provides the C<.tailcall> directive to identify similar situations. Use it
+in place of the C<.return> directive. C<.tailcall> performs this optimization
+by reusing the return continuation of the parent subroutine to make the
+tailcall:
+
+=begin PIR
+
+ .sub 'main' :main
+ .local int value
+ value = add_two(5)
+ say value
+ .end
+
+ .sub 'add_two'
+ .param int value
+ .local int val2
+ val2 = add_one(value)
+ .tailcall add_one(val2)
+ .end
+
+ .sub 'add_one'
+ .param int a
+ .local int b
+ b = a + 1
+ .return (b)
+ .end
+
+=end PIR
+
+This example prints the correct value C<7>.
+
+=head2 Coroutines
+
+X<Coroutines>
+X<subroutines; coroutines>
+
+Coroutines are similar to subroutines except that they have an internal
+notion of I<state>. In addition to performing a normal C<.return> to
+return control flow back to the caller and destroy the execution
+environment of the subroutine, coroutines may also perform a C<.yield>
+operation. C<.yield> returns a value to the caller like C<.return> can,
+but it does not destroy the execution state of the coroutine. The next
+call to the coroutine continues execution from the point of the last
+C<.yield>, not at the beginning of the coroutine.
+
+Inside a coroutine continuing from a C<.yield>, the entire execution
+environment is the same as it was when the coroutine C<.yield>ed. This
+means that the parameter values don't change, even if the next
+invocation of the coroutine had different arguments passed in.
+
+Coroutines look like ordinary subroutines. They do not require any special
+modifier or any special syntax to mark them as being a coroutine. What sets
+them apart is the use of the C<.yield> directive. C<.yield> plays several
+roles:
+
+=over 4
+
+=item * Identifies coroutines
+
+When Parrot sees a C<.yield>, it knows to create a Coroutine PMC object instead
+of a C<Sub> PMC.
+
+=item * Creates a continuation
+
+C<.yield> creates a continuation in the coroutine and stores the continuation
+object in the coroutine object for later resuming from the point of the
+C<.yield>.
+
+=item * Returns a value
+
+C<.yield> can return a value N<... or many values, or no values.> to the caller.
+It is basically the same as a C<.return> in this regard.
+
+=back
+
+Here is a simple coroutine example:
+
+=begin PIR
+
+ .sub 'MyCoro'
+ .yield(1)
+ .yield(2)
+ .yield(3)
+ .return(4)
+ .end
+
+ .sub 'main' :main
+ $I0 = MyCoro() # 1
+ $I0 = MyCoro() # 2
+ $I0 = MyCoro() # 3
+ $I0 = MyCoro() # 4
+ $I0 = MyCoro() # 1
+ $I0 = MyCoro() # 2
+ $I0 = MyCoro() # 3
+ $I0 = MyCoro() # 4
+ $I0 = MyCoro() # 1
+ $I0 = MyCoro() # 2
+ $I0 = MyCoro() # 3
+ $I0 = MyCoro() # 4
+ .end
+
+=end PIR
+
+This contrived example demonstrates how the coroutine stores its state. When
+Parrot encounters the C<.yield>, the coroutine stores its current execution
+environment. At the next call to the coroutine, it picks up where it left off.
+
+=head2 Native Call Interface
+
+The X<NCI (Native Call Interface)> Native Call Interface (NCI) is a
+special version of the Parrot calling conventions for calling functions
+with a known signature in shared C libraries. This is a simplified
+version of the first test in F<t/pmc/nci.t>:
+
+=begin PIR_FRAGMENT
+
+ .local pmc library
+ library = loadlib "libnci_test" # get object for a shared lib
+ say "loaded"
+
+ .local pmc ddfunc
+ ddfunc = dlfunc library, "nci_dd", "dd" # obtain the function object
+ say "dlfunced"
+
+ .local num result
+ result = ddfunc( 4.0 ) # the functions doubles its arg
+
+ ne result, 8.0, nok_1
+ say "ok 1"
+ end
+ nok_1:
+ say "not ok 1"
+
+ #...
+
+=end PIR_FRAGMENT
+
+This example shows two new instructions: C<loadlib> and C<dlfunc>. The
+C<loadlib>X<loadlib opcode> opcode obtains a handle for a shared library. It
+searches for the shared library in the current directory, in
+F<runtime/parrot/dynext>, and in a few other configured directories. It also
+tries to load the provided filename unaltered and with appended extensions like
+F<.so> or F<.dll>. Which extensions it tries depends on the operating
+system Parrot is running on.
+
+The C<dlfunc>X<dlfunc opcode> opcode gets a function object from a previously
+loaded library (second argument) of a specified name (third argument) with a
+known function signature (fourth argument). The function signature is a string
+where the first character is the return value and the rest of the parameters
+are the function parameters. Table 6-1 lists the characters used in NCI
+function signatures.
+
+=begin table Function signature letters
+
+Z<CHP-6-TABLE-1>
+
+=headrow
+
+=row
+
+=cell Character
+
+=cell Register set
+
+=cell C type
+
+=bodyrows
+
+=row
+
+=cell C<v>
+
+=cell -
+
+=cell void (no return value)
+
+=row
+
+=cell C<c>
+
+=cell C<I>
+
+=cell char
+
+=row
+
+=cell C<s>
+
+=cell C<I>
+
+=cell short
+
+=row
+
+=cell C<i>
+
+=cell C<I>
+
+=cell int
+
+=row
+
+=cell C<l>
+
+=cell C<I>
+
+=cell long
+
+=row
+
+=cell C<f>
+
+=cell C<N>
+
+=cell float
+
+=row
+
+=cell C<d>
+
+=cell C<N>
+
+=cell double
+
+=row
+
+=cell C<t>
+
+=cell C<S>
+
+=cell char *
+
+=row
+
+=cell C<p>
+
+=cell C<P>
+
+=cell void * (or other pointer)
+
+=row
+
+=cell C<I>
+
+=cell -
+
+=cell Parrot_Interp *interpreter
+
+=row
+
+=cell C<C>
+
+=cell -
+
+=cell a callback function pointer
+
+=row
+
+=cell C<D>
+
+=cell -
+
+=cell a callback function pointer
+
+=row
+
+=cell C<Y>
+
+=cell C<P>
+
+=cell the subroutine C<C> or C<D> calls into
+
+=row
+
+=cell C<Z>
+
+=cell C<P>
+
+=cell the argument for C<Y>
+
+=end table
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/pir/ch07_objects.pod (from r39796, trunk/docs/book/pir/ch07_objects.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/pir/ch07_objects.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/pir/ch07_objects.pod)
@@ -0,0 +1,439 @@
+=pod
+
+=head1 Classes and Objects
+
+Many of Parrot's core classes -- such as C<Integer> and C<ResizablePMCArray> --
+are written in C, but you can also write your own classes in PIR. PIR doesn't
+have the shiny syntax of high-level object-oriented languages, but it provides
+the necessary features to construct well-behaved objects every bit as powerful
+as those of high-level object systems.
+
+Parrot developers often use the word "PMCs" to refer to the objects defined in
+C classes and "objects" to refer to the objects defined in PIR. In truth, all
+PMCs are objects and all objects are PMCs, so the distinction is a community
+tradition with no official meaning.
+
+=head2 Class Declaration
+
+X<classes>
+The C<newclass>X<newclass opcode> opcode defines a new class. It takes a
+single argument, the name of the class to define.
+
+=begin PIR_FRAGMENT
+
+ $P0 = newclass 'Foo'
+
+=end PIR_FRAGMENT
+
+Just as with Parrot's core classes, the C<new> opcode instantiates a new object
+of a named class.
+
+=begin PIR_FRAGMENT
+
+ $P1 = new 'Foo'
+
+=end PIR_FRAGMENT
+
+In addition to a string name for the class, C<new> can also instantiate
+an object from a class object or from a keyed namespace name.
+
+=begin PIR_FRAGMENT
+
+ $P0 = newclass 'Foo'
+ $P1 = new $P0
+
+ $P2 = new ['Bar';'Baz']
+
+=end PIR_FRAGMENT
+
+=head2 Attributes
+
+X<attributes>
+X<classes;attributes>
+The C<addattribute> opcode defines a named attribute -- or I<instance variable> -- in the class:
+
+=begin PIR_FRAGMENT
+
+ $P0 = newclass 'Foo'
+ addattribute $P0, 'bar'
+
+=end PIR_FRAGMENT
+
+The C<setattribute>X<setattribute> opcode sets the value of a declared
+attribute. You must declare an attribute before you may set it. The value of
+an attribute is always a PMC, never an integer, number, or string.N<Though it
+can be an C<Integer>, C<Number>, or C<String> PMC.>
+
+=begin PIR_FRAGMENT
+
+ $P6 = box 42
+ setattribute $P1, 'bar', $P6
+
+=end PIR_FRAGMENT
+
+The C<getattribute>X<getattribute opcode> opcode fetches the value of a
+named attribute. It takes an object and an attribute name as arguments
+and returns the attribute PMC:
+
+=begin PIR_FRAGMENT
+
+ $P10 = getattribute $P1, 'bar'
+
+=end PIR_FRAGMENT
+
+Because PMCs are containers, you may modify an object's attribute by retrieving
+the attribute PMC and modifying its value. You don't need to call
+C<setattribute> for the change to stick:
+
+=begin PIR_FRAGMENT
+
+ $P10 = getattribute $P1, 'bar'
+ $P10 = 5
+
+=end PIR_FRAGMENT
+
+=head2 Methods
+
+X<methods>
+X<classes;methods>
+Methods in PIR are subroutines stored in the class object. Define a method with
+the C<.sub> directive and the C<:method> modifier:
+
+=begin PIR
+
+ .sub half :method
+ $P0 = getattribute self, 'bar'
+ $P1 = $P0 / 2
+ .return($P1)
+ .end
+
+=end PIR
+
+This method returns the integer value of the C<bar> attribute of the object
+divided by two. Notice that the code never declares the named variable C<self>.
+Methods always make the invocant object -- the object on which the method was
+invoked -- available in a local variable called C<self>.
+
+The C<:method> modifier adds the subroutine to the class object associated with
+the currently selected namespace, so every class definition file must contain a
+C<.namespace> declaration. Class files for languages may also contain an
+C<.HLL> declaration to associate the namespace with the appropriate high-level
+language:
+
+=begin PIR
+
+ .HLL 'php'
+ .namespace [ 'Foo' ]
+
+=end PIR
+
+Method calls in PIR use a period (C<.>) to separate the object from the method
+name. The method name is either a literal string in quotes or a string
+variable. The method call looks up the method in the invocant object using the
+string name:
+
+=begin PIR_FRAGMENT
+
+ $P0 = $P1.'half'()
+
+ $S2 = 'double'
+ $P0 = $P1.$S2()
+
+=end PIR_FRAGMENT
+
+You can also pass a method object to the method call instead of looking it up
+by string name:
+
+=begin PIR_FRAGMENT
+
+ $P2 = get_global 'triple'
+ $P0 = $P1.$P2()
+
+=end PIR_FRAGMENT
+
+Parrot always treats a PMC used in the method position as a method object, so
+you can't pass a C<String> PMC as the method name.
+
+Methods can have multiple arguments and multiple return values just like
+subroutine:
+
+=begin PIR_FRAGMENT
+
+ ($P0, $S1) = $P2.'method'($I3, $P4)
+
+=end PIR_FRAGMENT
+
+The C<can> opcode checks whether an object has a particular method. It
+returns 0 (false) or 1 (true):
+
+=begin PIR_FRAGMENT
+
+ $I0 = can $P3, 'add'
+
+=end PIR_FRAGMENT
+
+=head2 Inheritance
+
+X<inheritance>
+X<classes;inheritance>
+The C<subclass>X<subclass opcode> opcode creates a new class that
+inherits methods and attributes from another class. It takes two
+arguments: the name of the parent class and the name of the new class:
+
+=begin PIR_FRAGMENT
+
+ $P3 = subclass 'Foo', 'Bar'
+
+=end PIR_FRAGMENT
+
+C<subclass> can also take a class object as the parent class instead of
+a class name:
+
+=begin PIR_FRAGMENT
+
+ $P3 = subclass $P2, 'Bar'
+
+=end PIR_FRAGMENT
+
+X<multiple inheritance>
+The C<addparent>X<addparent opcode> opcode also adds a parent class to a
+subclass. This is especially useful for multiple inheritance, as
+the C<subclass> opcode only accepts a single parent class:
+
+=begin PIR_FRAGMENT
+
+ $P4 = newclass 'Baz'
+ addparent $P3, $P4
+ addparent $P3, $P5
+
+=end PIR_FRAGMENT
+
+To override an inherited method in the child class, define a method with the
+same name in the subclass. This example code overrides C<Bar>'s C<who_am_i>
+method to return a more meaningful name:
+
+=begin PIR
+
+ .namespace [ 'Bar' ]
+
+ .sub 'who_am_i' :method
+ .return( 'I am proud to be a Bar' )
+ .end
+
+=end PIR
+
+Object creation for subclasses is the same as for ordinary classes:
+
+=begin PIR_FRAGMENT
+
+ $P5 = new 'Bar'
+
+=end PIR_FRAGMENT
+
+Calls to inherited methods are just like calls to methods defined in
+the class:
+
+=begin PIR_FRAGMENT
+
+ $P1.'increment'()
+
+=end PIR_FRAGMENT
+
+The C<isa> opcode checks whether an object is an instance of or inherits
+from a particular class. It returns 0 (false) or 1 (true):
+
+=begin PIR_FRAGMENT
+
+ $I0 = isa $P3, 'Foo'
+ $I0 = isa $P3, 'Bar'
+
+=end PIR_FRAGMENT
+
+=head2 Overriding Vtable Functions
+
+The C<Object> PMC is a core PMC written in C that provides basic
+object-like behavior. Every object instantiated from a PIR class
+inherits a default set of vtable functions from C<Object>, but you can
+override them with your own PIR subroutines.
+
+The C<:vtable> modifier marks a subroutine as a vtable override. As it does
+with methods, Parrot stores vtable overrides in the class associated with the
+currently selected namespace:
+
+=begin PIR
+
+ .sub 'init' :vtable
+ $P6 = new 'Integer'
+ setattribute self, 'bar', $P6
+ .return()
+ .end
+
+=end PIR
+
+Subroutines acting as vtable overrides must either have the name of an actual
+vtable function or include the vtable function name in the C<:vtable> modifier:
+
+=begin PIR
+
+ .sub foozle :vtable('init')
+ # ...
+ .end
+
+=end PIR
+
+You must call methods on objects explicitly, but Parrot calls vtable functions
+implicitly in multiple contexts. For example, creating a new object with C<$P3
+= new 'Foo'> will call C<init> with the new C<Foo> object.
+
+As an example of some of the common vtable overrides, the C<=> operator (or
+C<set> opcode) calls C<Foo>'s C<set_integer_native> vtable function when its
+left-hand side is a C<Foo> object and the argument is an integer literal or
+integer variable:
+
+=begin PIR_FRAGMENT
+
+ $P3 = 30
+
+=end PIR_FRAGMENT
+
+The C<+> operator (or C<add> opcode) calls C<Foo>'s C<add> vtable function
+when it adds two C<Foo> objects:
+
+=begin PIR_FRAGMENT
+
+ $P3 = new 'Foo'
+ $P3 = 3
+ $P4 = new 'Foo'
+ $P4 = 1774
+
+ $P5 = $P3 + $P4
+ # or:
+ add $P5, $P3, $P4
+
+=end PIR_FRAGMENT
+
+The C<inc> opcode calls C<Foo>'s C<increment> vtable function when it
+increments a C<Foo> object:
+
+=begin PIR_FRAGMENT
+
+ inc $P3
+
+=end PIR_FRAGMENT
+
+Parrot calls C<Foo>'s C<get_integer> and C<get_string> vtable functions to
+retrieve an integer or string value from a C<Foo> object:
+
+=begin PIR_FRAGMENT
+
+ $I10 = $P5 # get_integer
+ say $P5 # get_string
+
+=end PIR_FRAGMENT
+
+=head2 Introspection
+
+Classes defined in PIR using the C<newclass> opcode are instances of the
+C<Class> PMC. This PMC contains all the meta-information for the class, such as
+attribute definitions, methods, vtable overrides, and its inheritance
+hierarchy. The C<inspect> opcode provides a way to peek behind the curtain of
+encapsulation to see what makes a class tick. When called with no arguments,
+C<inspect> returns an associative array containing data on all characteristics
+of the class that it chooses to reveal:
+
+=begin PIR_FRAGMENT
+
+ $P1 = inspect $P0
+ $P2 = $P1['attributes']
+
+=end PIR_FRAGMENT
+
+When called with a string argument, C<inspect> only returns the data for
+a specific characteristic of the class:
+
+=begin PIR_FRAGMENT
+
+ $P0 = inspect $P1, 'parents'
+
+=end PIR_FRAGMENT
+
+Table 7-1 shows the introspection characteristics supported by
+C<inspect> and C<inspect_str>.
+
+=begin table Class Introspection
+
+=headrow
+
+=row
+
+=cell Characteristic
+
+=cell Description
+
+=bodyrows
+
+=row
+
+=cell C<attributes>
+
+=cell Information about the attributes the class will instantiate in
+its objects. An associative array, where the keys are the attribute
+names and the values are hashes of metadata.
+
+=row
+
+=cell C<flags>
+
+=cell An C<Integer> PMC containing any integer flags set on the class
+object.
+
+=row
+
+=cell C<methods>
+
+=cell A list of methods provided by the class. An associative array
+where the keys are the method names and the values are the invocable
+method objects.
+
+=row
+
+=cell C<name>
+
+=cell A C<String> PMC containing the name of the class.
+
+=row
+
+=cell C<namespace>
+
+=cell The C<NameSpace> PMC associated with the class.
+
+=row
+
+=cell C<parents>
+
+=cell An array of C<Class> objects that this class inherits from
+directly (via C<subclass> or C<add_parent>). Does not include indirectly
+inherited parents.
+
+=row
+
+=cell C<roles>
+
+=cell An array of C<Role> objects composed into the class.
+
+=row
+
+=cell C<vtable_overrides>
+
+=cell A list of vtable overrides defined by the class. An associative
+array where the keys are the vtable names and the values are the
+invocable sub objects.
+
+=end table
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/pir/ch08_io.pod (from r39796, trunk/docs/book/pir/ch08_io.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/pir/ch08_io.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/pir/ch08_io.pod)
@@ -0,0 +1,386 @@
+=pod
+
+=head1 I/O
+
+X<FileHandle>
+X<PMCs; FileHandle>
+X<Socket>
+X<PMCs; Socket>
+Parrot handles all I/O in Parrot with a set of PMCs. The C<FileHandle> PMC
+takes care of reading from and writing to files and file-like streams. The
+C<Socket> PMC takes care of network I/O.
+
+=head2 FileHandle Opcodes
+
+The C<open> opcode opens a new filehandle. It takes a string argument,
+which is the path to the file:
+
+=begin PIR_FRAGMENT
+
+ $P0 = open 'my/file/name.txt'
+
+=end PIR_FRAGMENT
+
+By default, it opens the filehandle as read-only, but an optional second string
+argument can specify the mode for the file. The modes are C<r> for read, C<w>
+for write, C<a> for append, and C<p> for pipe:N<These are the same as the C
+language read-modes, so may be familiar.>
+
+=begin PIR_FRAGMENT
+
+ $P0 = open 'my/file/name.txt', 'a'
+
+ $P0 = open 'myfile.txt', 'r'
+
+=end PIR_FRAGMENT
+
+You can combine modes; a handle that can read and write uses the mode string
+C<rw>. A handle that can read and write but will not overwrite the existing
+contents uses C<ra> instead.
+
+The C<close> opcode closes a filehandle when it's no longer needed.
+Closing a filehandle doesn't destroy the object, it only makes that
+filehandle object available for opening a different file.N<It's
+generally not a good idea to manually close the standard input, standard
+output, or standard error filehandles, though you can recreate them.>
+
+=begin PIR_FRAGMENT
+
+ close $P0
+
+=end PIR_FRAGMENT
+
+The C<print> opcode prints a string argument or the string form of an
+integer, number, or PMC to a filehandle:
+
+=begin PIR_FRAGMENT
+
+ print $P0, 'Nobody expects'
+
+=end PIR_FRAGMENT
+
+It also has a one-argument variant that always prints to standard
+output:
+
+=begin PIR_FRAGMENT
+
+ print 'the Spanish Inquisition'
+
+=end PIR_FRAGMENT
+
+The C<say> opcode also prints to standard output, but it appends a
+trailing newline to whatever it prints. Another opcode worth mentioning
+is the C<printerr> opcode, which prints an argument to the standard
+error instead of standard output:
+
+=begin PIR_FRAGMENT
+
+ say 'Turnip'
+
+ printerr 'Blancmange'
+
+=end PIR_FRAGMENT
+
+The C<read> and C<readline> opcodes read values from a filehandle. C<read>
+takes an integer value and returns a string with that many characters (if
+possible). C<readline> reads a line of input from a filehandle and returns the
+string without the trailing newline:
+
+=begin PIR_FRAGMENT
+
+ $S0 = read $P0, 10
+
+ $S0 = readline $P0
+
+=end PIR_FRAGMENT
+
+The C<read> opcode has a one-argument variant that reads from standard input:
+
+=begin PIR_FRAGMENT
+
+ $S0 = read 10
+
+=end PIR_FRAGMENT
+
+The C<getstdin>, C<getstdout>, and C<getstderr> opcodes fetch the
+filehandle objects for the standard streams: standard input, standard
+output, and standard error:
+
+=begin PIR_FRAGMENT
+
+ $P0 = getstdin # Standard input handle
+ $P1 = getstdout # Standard output handle
+ $P2 = getstderr # Standard error handle
+
+=end PIR_FRAGMENT
+
+Once you have the filehandle for one of the standard streams, you can use it
+just like any other filehandle object:
+
+=begin PIR_FRAGMENT
+
+ $P0 = getstdout
+ print $P0, 'hello'
+
+=end PIR_FRAGMENT
+
+This following example reads data from the file F<myfile.txt> one line at a
+time using the C<readline> opcode. As it loops over the lines of the file, it
+checks the boolean value of the read-only filehandle C<$P0> to test whether the
+filehandle has reached the end of the file:
+
+=begin PIR
+
+ .sub 'main'
+ $P0 = getstdout
+ $P1 = open 'myfile.txt', 'r'
+ loop_top:
+ $S0 = readline $P1
+ print $P0, $S0
+ if $P1 goto loop_top
+ close $P1
+ .end
+
+=end PIR
+
+=head2 FileHandle Methods
+
+The methods available on a filehandle object are mostly duplicates of the
+opcodes, though sometimes they provide more options. Behind the scenes many of
+the opcodes call the filehandle's methods anyway, so the choice between the two
+is more a matter of style preference than anything else.
+
+=head3 open
+
+The C<open> method opens a stream in an existing filehandle object. It takes
+two optional string arguments: the name of the file to open and the open mode.
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'FileHandle'
+ $P0.'open'('myfile.txt', 'r')
+
+=end PIR_FRAGMENT
+
+The C<open> opcode internally creates a new filehandle PMC and calls its
+C<open> method on it. The opcode version is shorter to write, but it also
+creates a new PMC for every call, while the method can reopen an existing
+filehandle PMC with a new file.
+
+When reopening a filehandle, Parrot will reuse the previous filename associated
+with the filehandle unless you provide a different filename. The same goes for
+the mode.
+
+=head3 close
+
+The C<close> method closes the filehandle. This does not destroy the filehandle
+object; you can reopen it with the C<open> method later.
+
+=begin PIR_FRAGMENT
+
+ $P0.'close'()
+
+=end PIR_FRAGMENT
+
+=head3 is_closed
+
+The C<is_closed> method checks if the filehandle is closed. It returns
+true if the filehandle has been closed or was never opened, and false if
+it is currently open:
+
+=begin PIR_FRAGMENT
+
+ $I0 = $P0.'is_closed'()
+
+=end PIR_FRAGMENT
+
+=head3 print
+
+The C<print> method prints a given value to the filehandle. The argument
+can be an integer, number, string, or PMC.
+
+=begin PIR_FRAGMENT
+
+ $P0.'print'('Hello!')
+
+=end PIR_FRAGMENT
+
+=head3 puts
+
+The C<puts> method is similar to C<print>, but it only takes a string
+argument.
+
+=begin PIR_FRAGMENT
+
+ $P0.'puts'('Hello!')
+
+=end PIR_FRAGMENT
+
+=head3 read
+
+The C<read> method reads a specified number of bytes from the filehandle
+object and returns them in a string.
+
+=begin PIR_FRAGMENT
+
+ $S0 = $P0.'read'(10)
+
+=end PIR_FRAGMENT
+
+If the remaining bytes in the filehandle are fewer than the requested
+number of bytes, returns a string containing the remaining bytes.
+
+=head3 readline
+
+The C<readline> method reads an entire line up to a newline character or
+the end-of-file mark from the filehandle object and returns it in a
+string.
+
+=begin PIR_FRAGMENT
+
+ $S0 = $P0.'readline'()
+
+=end PIR_FRAGMENT
+
+=head3 readline_interactive
+
+The C<readline_interactive> method is useful for command-line scripts.
+It writes the single argument to the method as a prompt to the screen,
+then reads back a line of input.
+
+=begin PIR_FRAGMENT
+
+ $S0 = $P0.'readline_interactive'('Please enter your name:')
+
+=end PIR_FRAGMENT
+
+=head3 readall
+
+The C<readall> method reads an entire file. If the filehandle is closed,
+it will open the file given by the passed in string argument, read the
+entire file, and then close the filehandle.
+
+=begin PIR_FRAGMENT
+
+ $S0 = $P0.'readall'('myfile.txt')
+
+=end PIR_FRAGMENT
+
+If the filehandle is already open, C<readall> will read the contents of the
+file, and won't close the filehandle when it's finished. Don't pass the name
+argument when working with a file you've already opened.
+
+=begin PIR_FRAGMENT
+
+ $S0 = $P0.'readall'()
+
+=end PIR_FRAGMENT
+
+=head3 mode
+
+The C<mode> method returns the current file access mode for the
+filehandle object.
+
+=begin PIR_FRAGMENT
+
+ $S0 = $P0.'mode'()
+
+=end PIR_FRAGMENT
+
+=head3 encoding
+
+The C<encoding> method sets or retrieves the string encoding behavior of the
+filehandle.
+
+=begin PIR_FRAGMENT
+
+ $P0.'encoding'('utf8')
+ $S0 = $P0.'encoding'()
+
+=end PIR_FRAGMENT
+
+See L<Encodings and Charsets> in Chapter 4 for more details on the
+encodings supported in Parrot.
+
+=head3 buffer_type
+
+The C<buffer_type> method sets or retrieves the buffering behavior of the
+filehandle object. The argument or return value is one of: C<unbuffered> to
+disable buffering, C<line-buffered> to read or write when the filehandle
+encounters a line ending, or C<full-buffered> to read or write bytes when the
+buffer is full.
+
+=begin PIR_FRAGMENT
+
+ $P0.'buffer_type'('full-buffered')
+ $S0 = $P0.'buffer_type'()
+
+=end PIR_FRAGMENT
+
+=head3 buffer_size
+
+The C<buffer_size> method sets or retrieves the buffer size of the
+filehandle object.
+
+=begin PIR_FRAGMENT
+
+ $P0.'buffer_size'(1024)
+ $I0 = $P0.'buffer_size'()
+
+=end PIR_FRAGMENT
+
+The buffer size set on the filehandle is only a suggestion. Parrot may
+allocate a larger buffer, but it will never allocate a smaller buffer.
+
+=head3 flush
+
+The C<flush> method flushes the buffer if the filehandle object is
+working in a buffered mode.
+
+=begin PIR_FRAGMENT
+
+ $P0.'flush'()
+
+=end PIR_FRAGMENT
+
+=head3 eof
+
+The C<eof> method checks whether a filehandle object has reached the end of the
+current file. It returns true if the filehandle is at the end of the current
+file and false otherwise.
+
+=begin PIR_FRAGMENT
+
+ $I0 = $P0.'eof'()
+
+=end PIR_FRAGMENT
+
+=head3 isatty
+
+The C<isatty> method returns a boolean value whether the filehandle is a
+TTY terminal.
+
+=begin PIR_FRAGMENT
+
+ $P0.'isatty'()
+
+=end PIR_FRAGMENT
+
+=head3 get_fd
+
+The C<get_fd> method returns the integer file descriptor of the current
+filehandle object. Not all operating systems use integer file
+descriptors. Those that don't simply return C<-1>.
+
+=begin PIR_FRAGMENT
+
+ $I0 = $P0.'get_fd'()
+
+=end PIR_FRAGMENT
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Copied: branches/pmc_pct/docs/book/pir/ch09_exceptions.pod (from r39796, trunk/docs/book/pir/ch09_exceptions.pod)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/docs/book/pir/ch09_exceptions.pod Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/docs/book/pir/ch09_exceptions.pod)
@@ -0,0 +1,383 @@
+=pod
+
+=head1 Exceptions
+
+X<exceptions>
+Exceptions provide a way of subverting the normal flow of control. Their main
+use is error reporting and cleanup tasks, but sometimes exceptions are just a
+funny way to jump from one code location to another one. Parrot uses a robust
+exception mechanism and makes it available to PIR.
+
+Exceptions are objects that hold essential information about an exceptional
+situation: the error message, the severity and type of the error, the location
+of the error, and backtrace information about the chain of calls that led to
+the error. Exception handlers are ordinary subroutines, but user code never
+calls them directly from within user code. Instead, Parrot invokes an
+appropriate exception handler to catch a thrown exception.
+
+=head2 Throwing Exceptions
+
+The C<throw> opcode throws an exception object. This example creates a new
+C<Exception> object in C<$P0> and throws it:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'Exception'
+ throw $P0
+
+=end PIR_FRAGMENT
+
+Setting the string value of an exception object sets its error message:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'Exception'
+ $P0 = "I really had my heart set on halibut."
+ throw $P0
+
+=end PIR_FRAGMENT
+
+Other parts of Parrot throw their own exceptions. The C<die> opcode throws a
+fatal (that is, uncatchable) exception. Many opcodes throw exceptions to
+indicate error conditions. The C</> operator (the C<div> opcode), for example,
+throws an exception on attempted division by zero.
+
+When no appropriate handlers are available to catch an exception, Parrot treats
+it as a fatal error and exits, printing the exception message followed by a
+backtrace showing the location of the thrown exception:
+
+ I really had my heart set on halibut.
+ current instr.: 'main' pc 6 (pet_store.pir:4)
+
+=head2 Catching Exceptions
+
+X<exception handlers>
+X<exceptions;handling>
+Exception handlers catch exceptions, making it possible to recover from
+errors in a controlled way, instead of terminating the process entirely.
+
+The C<push_eh> opcode creates an exception handler and stores it in the list of
+currently active exception handlers. The body of the exception handler is a
+labeled section of code inside the same subroutine as the call to C<push_eh>.
+The opcode takes one argument, the name of the label:
+
+=begin PIR_FRAGMENT
+
+ push_eh my_handler
+ $P0 = new 'Exception'
+ throw $P0
+
+ say 'never printed'
+
+ my_handler:
+ say 'caught an exception'
+
+=end PIR_FRAGMENT
+
+This example creates an exception handler from the C<my_handler> label, then
+creates a new exception and throws it. At this point, Parrot checks to see if
+there are any appropriate exception handlers in the currently active list. It
+finds C<my_handler> and runs it, printing "caught an exception". The "never
+printed" line never runs, because the exceptional control flow skips right over
+it.
+
+Because Parrot scans the list of active handlers from newest to oldest, you
+don't want to leave exception handlers lying around when you're done with them.
+The C<pop_eh> opcode removes an exception handler from the list of currently
+active handlers:
+
+=begin PIR_FRAGMENT
+
+ push_eh my_handler
+ $I0 = $I1 / $I2
+ pop_eh
+
+ say 'maybe printed'
+
+ goto skip_handler
+
+ my_handler:
+ say 'caught an exception'
+ pop_eh
+
+ skip_handler:
+
+=end PIR_FRAGMENT
+
+This example creates an exception handler C<my_handler> and then runs a a
+division operation that will throw a "division by zero" exception if C<$I2> is
+0. When C<$I2> is 0, C<div> throws an exceptoin. The exception handler catches
+it, prints "caught an exception", and then clears itself with C<pop_eh>. When
+C<$I2> is a non-zero value, there is no exception. The code clears the
+exception handler with C<pop_eh>, then prints "maybe printed". The C<goto>
+skips over the code of the exception handler, as it's just a labeled unit of
+code within the subruotine.
+
+The exception object provides access to various attributes of the exception for
+additional information about what kind of error it was, and what might have
+caused it. The C<.get_results()> directive retrieves the C<Exception> object
+from inside the handler:
+
+=begin PIR_FRAGMENT
+
+ my_handler:
+ .get_results($P0)
+
+=end PIR_FRAGMENT
+
+Not all handlers are able to handle all kinds of exceptions. If a handler
+determines that it's caught an exception it can't handle, it can C<rethrow> the
+exception to the next handler in the list of active handlers:
+
+=begin PIR_FRAGMENT
+
+ my_handler:
+ .get_results($P0)
+ rethrow $P0
+
+=end PIR_FRAGMENT
+
+If none of the active handlers can handle the exception, the exception becomes
+a fatal error. Parrot will exit, just as if it could find no handlers.
+
+X<exceptions;resuming>
+X<resumable exceptions>
+
+An exception handler creates a return continuation with a snapshot of the
+current interpreter context. If the handler is successful, it can resume
+running at the instruction immediately after the one that threw the exception.
+This resume continuation is available from the C<resume> attribute of the
+exception object. To resume after the exception handler is complete, call the
+resume handler like an ordinary subroutine:
+
+=begin PIR_FRAGMENT
+
+ my_handler:
+ .get_results($P0)
+ $P1 = $P0['resume']
+ $P1()
+
+=end PIR_FRAGMENT
+
+=head2 Exception PMC
+
+X<exceptions;message>
+C<Exception> objects contain several useful pieces of information about the
+exception. To set and retrieve the exception message, use the C<message> key on
+the exception object:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'Exception'
+ $P0['message'] = "this is an error message for the exception"
+
+=end PIR_FRAGMENT
+
+... or set and retrieve the string value of the exception object directly:
+
+=begin PIR_FRAGMENT
+
+ $S0 = $P0
+
+=end PIR_FRAGMENT
+
+X<exceptions;severity>
+X<exceptions;type>
+The severity and type of the exception are both integer values:
+
+=begin PIR_FRAGMENT
+
+ $P0['severity'] = 1
+ $P0['type'] = 2
+
+=end PIR_FRAGMENT
+
+X<exceptions;payload>
+The payload holds any user-defined data attached to the exception object:
+
+=begin PIR_FRAGMENT
+
+ $P0['payload'] = $P2
+
+=end PIR_FRAGMENT
+
+The attributes of the exception are useful in the handler for making decisions
+about how and whether to handle an exception and report its results:
+
+=begin PIR_FRAGMENT
+
+ my_handler:
+ .get_results($P2)
+ $S0 = $P2['message']
+ print 'caught exception: "'
+ print $S0
+ $I0 = $P2['type']
+ print '", of type '
+ say $I0
+
+=end PIR_FRAGMENT
+
+=head2 Exception Handler PMC
+
+Exception handlers are subroutine-like PMC objects, derived from Parrot's
+C<Continuation> type. When you use C<push_eh> with a label to create an
+exception handler, Parrot creates the handler PMC for you. You can also create
+it directly by creating a new C<ExceptionHandler> object, and setting
+its destination address to the label of the handler using the
+C<set_addr> opcode:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'ExceptionHandler'
+ set_addr $P0, my_handler
+ push_eh $P0
+ # ...
+
+ my_handler:
+ # ...
+
+=end PIR_FRAGMENT
+
+X<can_handle>
+C<ExceptionHandler> PMCs have several methods for setting or checking handler
+attributes. The C<can_handle> method reports whether the handler is willing or
+able to handle a particular exception. It takes one argument, the exception
+object to test:
+
+=begin PIR_FRAGMENT
+
+ $I0 = $P0.'can_handle'($P1)
+
+=end PIR_FRAGMENT
+
+X<min_severity>
+X<max_severity>
+The C<min_severity> and C<max_severity> methods set and retrieve the severity
+attributes of the handler, allowing it to refuse to handle any exceptions whose
+severity is too high or too low. Both take a single optional integer argument
+to set the severity; both return the current value of the attribute as a
+result:
+
+=begin PIR_FRAGMENT
+
+ $P0.'min_severity'(5)
+ $I0 = $P0.'max_severity'()
+
+=end PIR_FRAGMENT
+
+The C<handle_types> and C<handle_types_except> methods tell the
+exception handler what types of exceptions it should or shouldn't
+handle. Both take a list of integer types, which correspond to the
+C<type> attribute set on an exception object:
+
+=begin PIR_FRAGMENT
+
+ $P0.'handle_types'(5, 78, 42)
+
+=end PIR_FRAGMENT
+
+The following example creates an exception handler that only handles
+exception types 1 and 2. Instead of having C<push_eh> create the
+exception handler object, it creates a new C<ExceptionHandler> object
+manually. It then calls C<handle_types> to identify the exception types
+it will handle:
+
+=begin PIR_FRAGMENT
+
+ $P0 = new 'ExceptionHandler'
+ set_addr $P0, my_handler
+ $P0.'handle_types'(1, 2)
+ push_eh $P0
+
+=end PIR_FRAGMENT
+
+This handler can only handle exception objects with a type of 1 or 2. Parrot
+will skip over this handler for all other exception types.
+
+=begin PIR_FRAGMENT
+
+ $P1 = new 'Exception'
+ $P1['type'] = 2
+ throw $P1 # caught
+
+ $P1 = new 'Exception'
+ $P1['type'] = 3
+ throw $P1 # uncaught
+
+=end PIR_FRAGMENT
+
+=head2 Annotations
+
+X<annotations>
+Annotations are pieces of metadata code stored in a bytecode file. This is
+especially important when dealing with high-level languages, where annotations
+contain information about the HLL's source code such as the current line number
+and file name.
+
+Create an annotation with the C<.annotate> keyword. Annotations consist of a
+key/value pair, where the key is a string and the value is an integer, a
+number, or a string. Bytecode stores annotations as constants in the compiled
+bytecode. Consequently, you may not store PMCs.
+
+=begin PIR_FRAGMENT
+
+ .annotate 'file', 'mysource.lang'
+ .annotate 'line', 42
+ .annotate 'compiletime', 0.3456
+
+=end PIR_FRAGMENT
+
+Annotations exist, or are "in force" throughout the entire subroutine or until
+their redefinition. Creating a new annotation with the same name as an old one
+overwrites it with the new value. The C<annotations> opcode retrieves the
+current hash of annotations:
+
+=begin PIR_FRAGMENT
+
+ .annotate 'line', 1
+ $P0 = annotations # {'line' => 1}
+
+ .annotate 'line', 2
+ $P0 = annotations # {'line' => 2}
+
+=end PIR_FRAGMENT
+
+To retrieve a single annotation by name, use the name with C<annotations>:
+
+=begin PIR_FRAGMENT
+
+ $P0 = annotations 'line'
+
+=end PIR_FRAGMENT
+
+Exception objects contain information about the annotations that were in force
+when the exception was thrown. Retrieve them with the C<annotations> method on
+the exception PMC object:
+
+=begin PIR_FRAGMENT
+
+ $I0 = $P0.'annotations'('line') # only the 'line' annotation
+ $P1 = $P0.'annotations'() # hash of all annotations
+
+=end PIR_FRAGMENT
+
+Exceptions can also include a backtrace to display the program flow to the
+point of the throw:
+
+=begin PIR_FRAGMENT
+
+ $P1 = $P0.'backtrace'()
+
+=end PIR_FRAGMENT
+
+The backtrace PMC is an array of hashes. Each element in the array corresponds
+to a function in the current call chain. Each hash has two elements:
+C<annotation> (the hash of annotations in effect at that point) and C<sub> (the
+Sub PMC of that function).
+
+=cut
+
+# Local variables:
+# c-file-style: "parrot"
+# End:
+# vim: expandtab shiftwidth=4:
Modified: branches/pmc_pct/docs/parrothist.pod
==============================================================================
--- branches/pmc_pct/docs/parrothist.pod Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/docs/parrothist.pod Fri Jun 26 08:35:24 2009 (r39797)
@@ -91,5 +91,6 @@
Allison 1.0.0 2009-Mar-17 "Haru Tatsu"
Francois 1.1.0 2009-Apr-21 "Half-moon Conure"
Infinoid 1.2.0 2009-May-19 "Bird Brain"
+ Whiteknight 1.3.0 2009-Jun-16 "Andean Swift"
=cut
Modified: branches/pmc_pct/docs/pdds/pdd19_pir.pod
==============================================================================
--- branches/pmc_pct/docs/pdds/pdd19_pir.pod Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/docs/pdds/pdd19_pir.pod Fri Jun 26 08:35:24 2009 (r39797)
@@ -1171,7 +1171,7 @@
The automatic name munging on C<.macro_local> variables allows for using
multiple macros, like so:
-=begin PIR
+=begin PIR_TODO
.macro foo(a)
.macro_local int $a
@@ -1186,7 +1186,7 @@
.bar("x")
.end
-=end PIR
+=end PIR_TODO
This will result in code for the parser as follows:
@@ -1221,20 +1221,24 @@
=begin PIR_FRAGMENT
+ .macro foo(b)
+ #...
+ .endm
+
.foo("x")
=end PIR_FRAGMENT
there will be two variables: C<b> and C<x>. When the macro is invoked twice:
-=begin PIR
+=begin PIR_TODO
.sub main
.foo("x")
.foo("y")
.end
-=end PIR
+=end PIR_TODO
the resulting code that is given to the parser will read as follows:
@@ -1267,10 +1271,9 @@
.param int b
.param int c
- .begin_return
- .set_return xy
- .end_return
-
+ # ...
+ .local pmc xy
+ .return(xy)
.end
=end PIR
@@ -1303,7 +1306,7 @@
=head3 NCI Call
-=begin PIR_FRAGMENT
+=begin PIR_FRAGMENT_TODO
load_lib $P0, "libname"
dlfunc $P1, $P0, "funcname", "signature"
@@ -1317,7 +1320,7 @@
.get_result r
.end_call
-=end PIR_FRAGMENT
+=end PIR_FRAGMENT_TODO
=head3 Subroutine Call Syntactic Sugar
@@ -1339,16 +1342,16 @@
Instead of the label a subroutine object can be used too:
-=begin PIR_FRAGMENT
+=begin PIR_FRAGMENT_TODO
get_global $P0, "sub_label"
$P0(args)
-=end PIR_FRAGMENT
+=end PIR_FRAGMENT_TODO
=head3 Methods
-=begin PIR
+=begin PIR_TODO
.namespace [ "Foo" ]
@@ -1365,7 +1368,7 @@
...
.end
-=end PIR
+=end PIR_TODO
The variable "self" automatically refers to the invocating object, if the
subroutine declaration contains "method".
@@ -1375,7 +1378,7 @@
The syntax is very similar to subroutine calls. The call is done with
C<.meth_call> which must immediately be preceded by the C<.invocant>:
-=begin PIR_FRAGMENT
+=begin PIR_FRAGMENT_TODO
.local int x, y, z
.local pmc class, obj
@@ -1392,7 +1395,7 @@
.end_call
...
-=end PIR_FRAGMENT
+=end PIR_FRAGMENT_TODO
The return continuation is optional. The method can be a string
Modified: branches/pmc_pct/docs/pdds/pdd27_multiple_dispatch.pod
==============================================================================
--- branches/pmc_pct/docs/pdds/pdd27_multiple_dispatch.pod Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/docs/pdds/pdd27_multiple_dispatch.pod Fri Jun 26 08:35:24 2009 (r39797)
@@ -105,7 +105,7 @@
matching, for a passed in signature. The signature passed in is an array of
PMCs, and the types are extracted from the types of the array elements.
-=item get_pmc_keyed_string
+=item get_pmc_keyed_str
Return an array of matching candidates, sorted from best matching to worst
matching, for a passed in signature. The signature passed in is a simple type
Modified: branches/pmc_pct/docs/project/release_manager_guide.pod
==============================================================================
--- branches/pmc_pct/docs/project/release_manager_guide.pod Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/docs/project/release_manager_guide.pod Fri Jun 26 08:35:24 2009 (r39797)
@@ -33,8 +33,8 @@
For example, you could select a name from
L<http://en.wikipedia.org/wiki/List_of_parrots>.
-Set up your account on L<http://www.parrot.org/> and ask one of Allison, Jerry,
-Jeff, Will, or chromatic to bestow you story-creating powers.
+Set up your account on L<http://www.parrot.org/> and ask an existing release
+manager to provide you with admin privileges if you don't already have them.
=item 1.
@@ -230,14 +230,13 @@
=item 10.
-Update the website. You will need an account on L<http://www.parrot.org>.
+Update the website. You will need an account with administrative rights
+on L<http://www.parrot.org>.
=over 4
=item a
-At this step, the "editor" privilege is needed, "poster" is not enough.
-
Add a new page for the release announcement with "Create content" -> "Story".
There's some additional stuff needed at the top of the page; use one of the
old announcements as a guide.
@@ -265,8 +264,6 @@
=item e
-At this step, the "admin" privilege is needed.
-
Under "Administer" -> "Site building" -> "URL Redirects", change the URL for
"release/current" to the FTP directory for the new release (for example,
F<ftp://ftp.parrot.org/pub/parrot/releases/devel/0.8.1>). Also update
@@ -364,14 +361,13 @@
The starred releases are Parrot's twice-yearly supported releases, see
F<docs/project/support_policy.pod>.
- - June 16, 2009 - 1.3 - whiteknight
- July 21, 2009 - 1.4* - cotto
- August 18, 2009 - 1.5 - rgrjr
- - Sept 21, 2009 - 1.6 -
+ - Sept 15, 2009 - 1.6 - particle
- Oct 20, 2009 - 1.7 -
- - Nov 24, 2009 - 1.8 -
- - Dec 22, 2009 - 1.9 -
- - Jan 18, 2010 - 2.0* -
+ - Nov 17, 2009 - 1.8 -
+ - Dec 15, 2009 - 1.9 -
+ - Jan 19, 2010 - 2.0* -
=cut
Modified: branches/pmc_pct/docs/user/pir/objects.pod
==============================================================================
--- branches/pmc_pct/docs/user/pir/objects.pod Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/docs/user/pir/objects.pod Fri Jun 26 08:35:24 2009 (r39797)
@@ -383,7 +383,7 @@
.sub getname :method
$P0 = getattribute self, "name"
- print $P0
+ .return($P0)
.end
.sub speak :method
Modified: branches/pmc_pct/docs/user/pir/pmcs.pod
==============================================================================
--- branches/pmc_pct/docs/user/pir/pmcs.pod Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/docs/user/pir/pmcs.pod Fri Jun 26 08:35:24 2009 (r39797)
@@ -21,17 +21,18 @@
String register number 15). Parrot programs consist of lines of
text where each line contains one opcode and its arguments.
-Each subroutine will have as many registers
-available as necessary; a simple subroutine will only need
-a few whereas complex subroutines with many calculations will
-need a larger number of registers. This is a fundamental
-difference from the original design of Parrot, in which there
-were 32 registers for each of the built-in types (int, num,
-pmc, string).
-PIR also provides for a more "natural" syntax for opcodes.
-Rather than saying C<set $I1, 0> to assign a zero to the $I1
-register, you may say instead C<$I1 = 0>.
-PIR also provides syntax for easily creating named variables
+Each subroutine will have as many registers available of each basic type
+(int, num, string, and pmc) as necessary; a simple subroutine will only
+need a few whereas complex subroutines with many calculations will need
+a larger number of registers. This is a fundamental difference from
+hardware CPUs (and the original design of Parrot), in which there are a
+fixed number of registers.
+
+PIR also provides for a more "natural" syntax for opcodes than
+the standard assembly language C<op arg, arg> format.
+Rather than writing C<set $I1, 0> to assign a zero to the $I1
+register, you may instead write C<$I1 = 0>.
+PIR also provides easy syntax for creating named variables
and constants, subroutines, passing parameters to subroutines,
accessing parameters by name, etc.
@@ -39,14 +40,12 @@
=head2 What's a PMC?
-Integers, strings, and arbitrary floating point numbers are
-common data types in most programming languages, but what's
-a PMC? PMC stands for "Polymorphic Container". PMCs are how
-Parrot handles more complicated structures and behaviors
-(hence the magic :) Some examples of PMC usage would be for
-arrays, hashes, data structures, objects, etc. Anything that
-can't be expressed using just integers, floating point
-numbers and strings can be expressed with a PMC.
+Integers, strings, and floating point numbers are common data types in
+most programming languages, but what's a PMC? PMC stands for
+"I<P>olyI<M>orphic I<C>ontainer". PMCs are how Parrot handles more
+complicated structures and behaviors, such as arrays, hashes, and
+objects. anything that can't be expressed using just integers,
+floating point numbers and strings can be expressed with a PMC.
Parrot comes with many types of PMC that encapsulate common,
useful behavior.
@@ -63,8 +62,8 @@
Hash A generic, resizable hash
Random Obtain a random number
String Similar to a string register but in PMC form
- Integer Similar to an integer register but in PMC form
- Float Similar to a number register but in PMC form
+ Integer Similar to an int register but in PMC form
+ Float Similar to a num register but in PMC form
Exception The standard exception mechanism
Timer A timer of course :)
Copied: branches/pmc_pct/examples/opengl/math.pir (from r39796, trunk/examples/opengl/math.pir)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/examples/opengl/math.pir Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/examples/opengl/math.pir)
@@ -0,0 +1,99 @@
+# Copyright (C) 2009, Parrot Foundation.
+# $Id$
+
+=head1 TITLE
+
+math.pir - Demo OpenGL::Math module
+
+=head1 SYNOPSIS
+
+ $ cd parrot-home
+ $ ./parrot examples/opengl/math.pir
+
+=head1 DESCRIPTION
+
+NOTE: THIS IS JUST A STUB WHILE OpenGL::Math IS BEING DEVELOPED. IT WILL BE
+ FILLED OUT LATER.
+
+This is a simple demo of functionality available from the C<OpenGL::Math>
+Parrot module.
+
+=cut
+
+.sub main :main
+ # Load OpenGL::Math and data dumping debug module
+ load_bytecode 'OpenGL/Math.pbc'
+ load_bytecode 'dumper.pbc'
+
+ # Create some sample data
+ .local pmc vec1, vec2
+ (vec1, vec2) = make_test_vectors()
+
+ # Run a few simple tests
+ sanity(vec1, vec2)
+ normalize(vec1)
+.end
+
+.sub make_test_vectors
+ # Test some basics
+ $P0 = new 'FixedFloatArray'
+ $P0 = 4
+ $P0[0] = 0.5
+ $P0[1] = 1.0
+ $P0[2] = 2.0
+ $P0[3] = 4.0
+
+ $P1 = new 'FixedFloatArray'
+ $P1 = 4
+ $P1[0] = 1.0
+ $P1[1] = 2.0
+ $P1[2] = 3.0
+ $P1[3] = 4.0
+
+ .local pmc Vec4
+ Vec4 = get_class ['OpenGL';'Math';'Vec4']
+
+ $P2 = new Vec4
+ $P2.'set_vals'($P0)
+
+ $P3 = Vec4.'new'('vals' => $P1)
+
+ .return ($P2, $P3)
+.end
+
+.sub sanity
+ .param pmc vec1
+ .param pmc vec2
+
+ .local pmc vec3
+ vec3 = vec1.'mul'(vec2)
+
+ say "\nvec1 * vec2 => vec3"
+ _dumper(vec1, 'vec1')
+ _dumper(vec2, 'vec2')
+ _dumper(vec3, 'vec3')
+
+ .local pmc scaled
+ scaled = vec1.'mul_num'(3)
+
+ say "\nvector * 3 => scaled"
+ _dumper(vec1, 'vector')
+ _dumper(scaled, 'scaled')
+.end
+
+.sub normalize
+ .param pmc vector
+
+ .local pmc normalized
+ normalized = vector.'normalize'()
+
+ say "\nnormalize(vector) => normalized"
+ _dumper(vector, 'vector')
+ _dumper(normalized, 'normalized')
+.end
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
Modified: branches/pmc_pct/examples/opengl/shapes.p6
==============================================================================
--- branches/pmc_pct/examples/opengl/shapes.p6 Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/opengl/shapes.p6 Fri Jun 26 08:35:24 2009 (r39797)
@@ -8,10 +8,9 @@
=head1 SYNOPSIS
- $ cd parrot-home
- $ make perl6
- $ cd parrot-home/runtime/parrot/library
- $ ../../../perl6 ../../../examples/opengl/shapes.p6
+ $ cd rakudo-home
+ $ export PERL6LIB=rakudo-home:parrot-home/runtime/parrot/library
+ $ ./perl6 parrot-home/examples/opengl/shapes.p6
=head1 DESCRIPTION
@@ -21,7 +20,7 @@
This example is slightly more complex than F<triangle.p6>, and exercises more
of the OpenGL 1.1 and GLUT 3 APIs. It is also a better behaved application,
correctly responding to reshape events, pausing on minimize, and so on. It is
-a fairly direct translation of f<shapes.pir> to Perl 6.
+a fairly direct translation of F<shapes.pir> to Perl 6.
To quit the example, press C<Q> or the C<ESCAPE> key, or close the window using
your window manager (using the X in the corner of the window title bar, for
@@ -29,43 +28,56 @@
=end pod
+use OpenGL:from<parrot>;
+use NCI::Utils:from<parrot>;
-use OpenGL;
-use NCI::call_toolkit_init;
+# XXX: Need a better way to import constants
+# None of these currently work; they all create an inescapable new lexical pad
+# require 'glutconst.p6';
+# 'glutconst.p6'.evalfile;
+# eval open('glutconst.p6').slurp;
+
+# Parrot
+constant DATATYPE_FLOAT = -84;
+
+# GLUT
+constant GLUT_RGBA = 0x0000;
+constant GLUT_DOUBLE = 0x0002;
+constant GLUT_DEPTH = 0x0010;
+constant GLUT_STENCIL = 0x0020;
+
+# OpenGL
+constant GL_DEPTH_BUFFER_BIT = 0x0100;
+constant GL_STENCIL_BUFFER_BIT = 0x0400;
+constant GL_COLOR_BUFFER_BIT = 0x4000;
+
+constant GL_POINTS = 0x0000;
+constant GL_FALSE = 0x0000;
+constant GL_TRUE = 0x0001;
+constant GL_ONE = 0x0001;
+constant GL_TRIANGLES = 0x0004;
+constant GL_EQUAL = 0x0202;
+constant GL_ALWAYS = 0x0207;
+constant GL_SRC_ALPHA = 0x0302;
+constant GL_ONE_MINUS_SRC_ALPHA = 0x0303;
+constant GL_FRONT = 0x0404;
+constant GL_BACK = 0x0405;
+constant GL_LIGHTING = 0x0B50;
+constant GL_DEPTH_TEST = 0x0B71;
+constant GL_STENCIL_TEST = 0x0B90;
+constant GL_NORMALIZE = 0x0BA1;
+constant GL_BLEND = 0x0BE2;
+constant GL_SPECULAR = 0x1202;
+constant GL_POSITION = 0x1203;
+constant GL_SHININESS = 0x1601;
+constant GL_AMBIENT_AND_DIFFUSE = 0x1602;
+constant GL_MODELVIEW = 0x1700;
+constant GL_PROJECTION = 0x1701;
+constant GL_KEEP = 0x1E00;
+constant GL_REPLACE = 0x1E01;
+constant GL_LIGHT0 = 0x4000;
-# .include 'datatypes.pasm'
-
-# .include 'opengl_defines.pasm'
-our $GLUT_RGBA = 0x0000;
-our $GLUT_DOUBLE = 0x0002;
-our $GLUT_DEPTH = 0x0010;
-our $GLUT_STENCIL = 0x0020;
-
-our $GL_DEPTH_BUFFER_BIT = 0x0100;
-our $GL_STENCIL_BUFFER_BIT = 0x0400;
-our $GL_COLOR_BUFFER_BIT = 0x4000;
-
-our $GL_FALSE = 0x0000;
-our $GL_TRUE = 0x0001;
-our $GL_TRIANGLES = 0x0004;
-our $GL_EQUAL = 0x0202;
-our $GL_ALWAYS = 0x0207;
-our $GL_SRC_ALPHA = 0x0302;
-our $GL_ONE_MINUS_SRC_ALPHA = 0x0303;
-our $GL_FRONT = 0x0404;
-our $GL_BACK = 0x0405;
-our $GL_DEPTH_TEST = 0x0B71;
-our $GL_STENCIL_TEST = 0x0B90;
-our $GL_NORMALIZE = 0x0BA1;
-our $GL_BLEND = 0x0BE2;
-our $GL_MODELVIEW = 0x1700;
-our $GL_PROJECTION = 0x1701;
-our $GL_KEEP = 0x1E00;
-our $GL_REPLACE = 0x1E01;
-
-
-our $mode = $GLUT_DOUBLE +| $GLUT_RGBA +| $GLUT_DEPTH +| $GLUT_STENCIL;
-our $glut_window = init_glut($mode, 'Test', @*ARGS);
+our $glut_window;
our $aspect = 1.0;
our $frames = 0;
@@ -76,26 +88,38 @@
our $time_sim = 0.0;
our $time_sim_dt = 0.0;
-glutIdleFunc( &idle );
-glutDisplayFunc( &draw );
-# glutReshapeFunc( &reshape );
-glutKeyboardFunc( &keyboard );
+our (@pfx_pos, @pfx_vel);
+
-glutMainLoop();
+sub MAIN(*@ARGS is rw) {
+ # Initialize GLUT and create GLUT window
+ $glut_window = init_glut(@ARGS, 'Shapes: OpenGL 1.x NCI Test');
+ # Set up GLUT callbacks
+ glutIdleFunc( &idle );
+ glutDisplayFunc( &draw );
+ glutReshapeFunc( &reshape );
+ glutKeyboardFunc( &keyboard );
+
+ # Enter the GLUT main loop
+ glutMainLoop();
+
+ # XXX: Rakudo bug -- glutMainLoop() never returns, but Rakudo dies without this
+ return;
+}
-sub init_glut($display_mode, $window_title, @args is rw) {
- # Import OpenGL and GLUT functions
- OpenGL::_export_all_functions();
+sub init_glut(@args is rw, $window_title) {
+ # We need a full-featured GL environment
+ my $display_mode = [+|] GLUT_DOUBLE, GLUT_RGBA, GLUT_DEPTH, GLUT_STENCIL;
# Set larger default window size
glutInitWindowSize(500, 500);
# Initialize GLUT, fixup command line args
- @args = NCI::call_toolkit_init(&glutInit, @args);
+ @args = call_toolkit_init(&glutInit, @args, $*PROGRAM_NAME);
# Set display mode, create GLUT window, return window handle
- glutInitDisplayMode($GLUT_DOUBLE +| $GLUT_RGBA +| $GLUT_DEPTH +| $GLUT_STENCIL);
+ glutInitDisplayMode($display_mode);
return glutCreateWindow($window_title);
}
@@ -106,10 +130,8 @@
my $dt = $paused ?? 0 !! $time_curr - $time_prev;
- $time_sim_dt = $dt;
- # XXXX: Broken because of Parrot RT #60036
- # $time_sim += $dt;
- $time_sim = $dt + $time_sim;
+ $time_sim_dt = $dt;
+ $time_sim += $dt;
glutPostRedisplay() unless $paused;
}
@@ -118,9 +140,10 @@
$height = $height || 1;
$aspect = $width / $height;
- # say "HELLO1";
glViewport(0, 0, $width, $height);
- say "HELLO2";
+
+ # XXX: Rakudo bug -- Rakudo dies without this
+ return;
}
sub keyboard($key, $x, $y) {
@@ -137,7 +160,7 @@
}
sub draw {
- glClear($GL_COLOR_BUFFER_BIT +| $GL_DEPTH_BUFFER_BIT +| $GL_STENCIL_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT +| GL_DEPTH_BUFFER_BIT +| GL_STENCIL_BUFFER_BIT);
set_3d_view();
update_particle_effect();
@@ -151,12 +174,12 @@
sub set_3d_view {
# Simple 60 degree FOV perspective view
- glMatrixMode($GL_PROJECTION);
+ glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, $aspect, 1, 100);
# Look at origin from (0,2,4), with +Y up
- glMatrixMode($GL_MODELVIEW);
+ glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 2, 4, 0, 0, 0, 0, 1, 0);
@@ -170,32 +193,36 @@
# doesn't "leak out" of the reflective area
# Turn off everything we don't need
- glDisable($GL_DEPTH_TEST);
- glColorMask($GL_FALSE, $GL_FALSE, $GL_FALSE, $GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
# Set stencil for just the reflecting area
- glEnable($GL_STENCIL_TEST);
- glStencilOp($GL_REPLACE, $GL_REPLACE, $GL_REPLACE);
- glStencilFunc($GL_ALWAYS, 1, 0xffffffff);
+ glEnable(GL_STENCIL_TEST);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ # XXX: Rakudo bug - decimalized constant in PIR code does wrong thing
+ # glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
+ glStencilFunc(GL_ALWAYS, 1, +^0);
# Draw the floor as the reflector
draw_floor();
# Now only draw where stencil is set
- glStencilOp($GL_KEEP, $GL_KEEP, $GL_KEEP);
- glStencilFunc($GL_EQUAL, 1, 0xffffffff);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ # XXX: Same Rakudo bug (wrong constant)
+ # glStencilFunc(GL_EQUAL, 1, 0xffffffff);
+ glStencilFunc(GL_EQUAL, 1, +^0);
# Turn back on the stuff we turned off
- glEnable($GL_DEPTH_TEST);
- glColorMask($GL_TRUE, $GL_TRUE, $GL_TRUE, $GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
# Flip reflection through the reflector
glPushMatrix();
glScalef(1, -1, 1);
# Account for the reversed normals
- glEnable($GL_NORMALIZE);
- glCullFace($GL_FRONT);
+ glEnable(GL_NORMALIZE);
+ glCullFace(GL_FRONT);
# Lights need to be reassigned after reflection
set_lights();
@@ -204,23 +231,23 @@
draw_objects();
# Switch back to normal facing
- glDisable($GL_NORMALIZE);
- glCullFace($GL_BACK);
+ glDisable(GL_NORMALIZE);
+ glCullFace(GL_BACK);
glPopMatrix();
# Done with stencil
- glDisable($GL_STENCIL_TEST);
+ glDisable(GL_STENCIL_TEST);
}
sub draw_main_scene {
#Draw floor blended over reflected scene
- glEnable($GL_BLEND);
- glBlendFunc($GL_SRC_ALPHA, $GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
draw_floor();
# Done with blending
- glDisable($GL_BLEND);
+ glDisable(GL_BLEND);
# Set lights for upright view
set_lights();
@@ -238,14 +265,41 @@
glRotatef(90, 1, 0, 0);
# Annulus floor (shapes sit in various spots above it)
-# my $glu_quadric = gluNewQuadric();
-# gluDisk($glu_quadric, 1, 2, 128, 1);
-# gluDeleteQuadric($glu_quadric);
+ my $glu_quadric = gluNewQuadric();
+ gluDisk($glu_quadric, 1, 2, 128, 1);
+ gluDeleteQuadric($glu_quadric);
glPopMatrix();
}
+sub make_float4($a = 0.0, $b = 0.0, $c = 0.0, $d = 1.0) {
+ my @float4_layout = (DATATYPE_FLOAT, 0, 0) xx 4;
+
+ # XXX: How do I do this in pure Perl 6 in Rakudo?
+ return Q:PIR{
+ $P0 = find_lex '@float4_layout'
+ $P1 = new 'ManagedStruct', $P0
+ $P2 = find_lex '$a'
+ $N0 = $P2
+ $P1[0] = $N0
+ $P2 = find_lex '$b'
+ $N0 = $P2
+ $P1[1] = $N0
+ $P2 = find_lex '$c'
+ $N0 = $P2
+ $P1[2] = $N0
+ $P2 = find_lex '$d'
+ $N0 = $P2
+ $P1[3] = $N0
+ %r = $P1
+ };
+}
+
sub set_lights {
+ my $position := make_float4(0.0, 2.0, 0.0, 1.0);
+
+ glEnable(GL_LIGHT0);
+ glLightfv(GL_LIGHT0, GL_POSITION, $position);
}
sub draw_objects {
@@ -263,7 +317,7 @@
glTranslatef(0, 0.04, -1.5);
glRotatef($angle, 0, 1, 0);
- glBegin($GL_TRIANGLES);
+ glBegin(GL_TRIANGLES);
glColor3f(1, 0, 0); glVertex3f(-.5, 0, 0);
glColor3f(0, 1, 0); glVertex3f( .5, 0, 0);
glColor3f(0, 0, 1); glVertex3f(0 , 1, 0);
@@ -273,375 +327,149 @@
}
sub draw_lit_teapot {
-}
-
-sub update_particle_effect {
-}
-
-sub draw_particle_effect {
-}
-
-sub set_2d_view {
- glMatrixMode($GL_PROJECTION);
- glLoadIdentity();
+ # Lit cyan teapot at +X
- glMatrixMode($GL_MODELVIEW);
- glLoadIdentity();
-}
+ glPushMatrix();
+ glTranslatef(1.5, .4, 0);
+ glRotatef(90, 0, 1, 0);
+ glEnable(GL_LIGHTING);
-=begin pod
+ my $color := make_float4(0.0, 0.8, 0.8, 1.0);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, $color);
-.sub main :main
- # Init miscellaneous globals
- init_globals()
-
- # Create particle effect
- init_particle_effect()
-.end
-
-.sub init_globals
- # Create structure definition for float4 structure
- .local pmc float4
- float4 = new 'ResizablePMCArray'
- push float4, .DATATYPE_FLOAT
- push float4, 0
- push float4, 0
- push float4, .DATATYPE_FLOAT
- push float4, 0
- push float4, 0
- push float4, .DATATYPE_FLOAT
- push float4, 0
- push float4, 0
- push float4, .DATATYPE_FLOAT
- push float4, 0
- push float4, 0
- set_global 'float4', float4
-.end
-
-.sub init_particle_effect
- .local pmc pfx_pos, pfx_vel
- pfx_pos = new 'ResizablePMCArray'
- pfx_vel = new 'ResizablePMCArray'
-
- new_particle(0, pfx_pos, pfx_vel)
-
- set_global 'pfx_pos', pfx_pos
- set_global 'pfx_vel', pfx_vel
-.end
-
-.sub set_lights
- glEnable(.GL_LIGHT0)
-
- # Light above origin
- .local pmc float4, position
- float4 = get_global 'float4'
- position = new 'ManagedStruct', float4
- position[0] = 0.0
- position[1] = 2.0
- position[2] = 0.0
- position[3] = 1.0
+ $color := make_float4(1.0, 1.0, 1.0, 1.0);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, $color);
+ glMaterialf( GL_FRONT, GL_SHININESS, 64);
- glLightfv(.GL_LIGHT0, .GL_POSITION, position)
-.end
+ glutSolidTeapot(.5);
-.sub draw_lit_teapot
- # Lit cyan teapot at +X
+ glDisable(GL_LIGHTING);
- glPushMatrix()
- glTranslatef(1.5, .4, 0)
- glRotatef(90, 0, 1, 0)
-
- glEnable(.GL_LIGHTING)
-
- .local pmc float4, color
- float4 = get_global 'float4'
- color = new 'ManagedStruct', float4
- color[0] = 0.0
- color[1] = 0.8
- color[2] = 0.8
- color[3] = 1.0
- glMaterialfv(.GL_FRONT, .GL_AMBIENT_AND_DIFFUSE, color)
-
- color[0] = 1.0
- color[1] = 1.0
- color[2] = 1.0
- color[3] = 1.0
- glMaterialfv(.GL_FRONT, .GL_SPECULAR, color)
- glMaterialf (.GL_FRONT, .GL_SHININESS, 64)
-
- glutSolidTeapot(.5)
-
- glDisable(.GL_LIGHTING)
-
- glPopMatrix()
-.end
-
-.sub new_particle
- .param int particle_num
- .param pmc pfx_pos
- .param pmc pfx_vel
-
- .local num x, y, z, vx, vy, vz
- x = 4.0
- y = 0.0
- z = 0.0
-
- vx = 0.0
- vy = 0.135
- vz = 0.0
-
- .local pmc random
- .local num rand
- random = new 'Random'
- rand = random
- rand *= .1
- x += rand
- rand = random
- rand *= .1
- y += rand
- rand = random
- rand *= .1
- z += rand
-
- rand = random
- rand -= .5
- rand *= .01
- vx += rand
- rand = random
- rand -= .5
- rand *= .01
- vy += rand
- rand = random
- rand -= .5
- rand *= .01
- vz += rand
-
- .local pmc pos
- pos = new 'FixedFloatArray'
- pos = 3
- pos[0] = x
- pos[1] = y
- pos[2] = z
-
- .local pmc vel
- vel = new 'FixedFloatArray'
- vel = 3
- vel[0] = vx
- vel[1] = vy
- vel[2] = vz
-
- pfx_pos[particle_num] = pos
- pfx_vel[particle_num] = vel
-.end
+ glPopMatrix();
+}
-.sub update_particle_effect
- .param num dt
+sub set_2d_view {
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
- # "Black hole" particle effect at +Z
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+}
+sub update_particle_effect {
# Speed up time a little; this effect is *slow*
- dt *= 30.0
-
- # Global particle state arrays
- .local pmc pfx_pos, pfx_vel
- pfx_pos = get_global 'pfx_pos'
- pfx_vel = get_global 'pfx_vel'
+ my $dt = $time_sim_dt * 30;
# Add a particle at random
- .local int count
- count = pfx_pos
- if count > 1000 goto update_particles
- .local pmc random
- .local num rand
- random = new 'Random'
- rand = random
- rand *= 4
- if rand > dt goto update_particles
- new_particle(count, pfx_pos, pfx_vel)
+ my $count = @pfx_pos.elems;
+ new_particle($count) if $count < 1000 && $dt > rand * 4;
# Update all particles
- update_particles:
- dec count
- if count < 0 goto update_particles_end
-
- # Update particle states
- update_particle(pfx_pos, pfx_vel, count, dt)
-
- goto update_particles
- update_particles_end:
-.end
-
-.sub update_particle
- .param pmc pfx_pos
- .param pmc pfx_vel
- .param int particle_num
- .param num dt
-
- .local pmc pos, vel
- pos = pfx_pos[particle_num]
- vel = pfx_vel[particle_num]
+ update_particle($_, $dt) for ^$count;
+}
+sub new_particle($particle_num) {
+ @pfx_pos[$particle_num] = [ 4.0 + rand * .1,
+ 0.0 + rand * .1,
+ 0.0 + rand * .1 ];
+ @pfx_vel[$particle_num] = [ 0.0 + (rand - .5) * .01,
+ 0.135 + (rand - .5) * .01,
+ 0.0 + (rand - .5) * .01 ];
+
+ return;
+}
+
+sub update_particle($particle_num, $dt) {
# Constants
- .const num G = -.075 # Gravitational force constant
- .const num Cd = -.00033 # Coefficient of drag
- .const num event_grav = -.3 # Gravity at "event horizon"
- .const num min_dist2 = .001 # Minimum distance**2 before calc blows up
- .const num escape_dist = 30 # Distance at which "escape" occurs
+ constant G = -.075; # Gravitational force constant
+ constant Cd = -.00033; # Coefficient of drag
+ constant event_grav = -.3; # Gravity at "event horizon"
+ constant min_dist2 = .001; # Minimum distance**2 before calc blows up
+ constant escape_dist = 30; # Distance at which "escape" occurs
# Particle states
- .local num x, y, z, vx, vy, vz
- x = pos[0]
- y = pos[1]
- z = pos[2]
- vx = vel[0]
- vy = vel[1]
- vz = vel[2]
+ my @pos := @pfx_pos[$particle_num];
+ my @vel := @pfx_vel[$particle_num];
# Calculate distance and distance squared
- .local num x2, y2, z2, dist2, dist
- x2 = x * x
- y2 = y * y
- z2 = z * z
- dist2 = x2 + y2
- dist2 += z2
- if dist2 >= min_dist2 goto dist2_ok
- dist2 = min_dist2
- dist2_ok:
- dist = sqrt dist2
+ my $dist_squared = [+] @pos >>*<< @pos;
+ $dist_squared = min_dist2 unless $dist_squared > min_dist2;
+ my $distance = sqrt($dist_squared);
# If distance is too great, particle has "escaped"; regenerate it
- if dist < escape_dist goto dist_ok
- new_particle(particle_num, pfx_pos, pfx_vel)
- .return ()
- dist_ok:
+ return new_particle($particle_num) if $distance > escape_dist;
# Compute gravity force
- .local num grav
- grav = G / dist2
+ my $gravity = G / $dist_squared;
# If gravity is too strong, it has "passed the event horizon"; regenerate it
- if grav > event_grav goto grav_ok
- new_particle(particle_num, pfx_pos, pfx_vel)
- .return ()
- grav_ok:
+ return new_particle($particle_num) if $gravity <= event_grav;
# Calculate gravity vector (always directed toward center of "hole")
- .local num gx, gy, gz
- gx = x / dist
- gy = y / dist
- gz = z / dist
- gx *= grav
- gy *= grav
- gz *= grav
+ my @grav = @pos >>/>> $distance >>*>> $gravity;
# Calculate drag vector (always directed opposite of velocity)
# NOTE: Using drag proportional to velocity, instead of velocity squared
- .local num dragx, dragy, dragz
- dragx = Cd * vx
- dragy = Cd * vy
- dragz = Cd * vz
+ my @drag = @vel >>*>> Cd;
# Acceleration is gravity + drag
- .local num ax, ay, az
- ax = gx + dragx
- ay = gy + dragy
- az = gz + dragz
+ my @acc = @grav >>+<< @drag;
# Update velocity and position with simple Euler integration
- .local num dvx, dvy, dvz
- .local num dx, dy, dz
- dvx = ax * dt
- dvy = ay * dt
- dvz = az * dt
- vx += dvx
- vy += dvy
- vz += dvz
- dx = vx * dt
- dy = vy * dt
- dz = vz * dt
- x += dx
- y += dy
- z += dz
-
- # Save new values back to particle state
- vel[0] = vx
- vel[1] = vy
- vel[2] = vz
- pos[0] = x
- pos[1] = y
- pos[2] = z
-.end
+ @vel = @vel >>+<< @acc >>*>> $dt;
+ @pos = @pos >>+<< @vel >>*>> $dt;
+}
-.sub draw_particle_effect
+sub draw_particle_effect {
# "Black hole" particle effect at +Z
# Make it visually interesting
- glPushMatrix()
- glTranslatef(0, .3, 1.5)
- glRotatef(-20, 0, 0, 1)
- glRotatef( 90, 1, 0, 0)
- glScalef(.15, .15, .15)
+ glPushMatrix();
+ glTranslatef(0, .3, 1.5);
+ glRotatef(-20, 0, 0, 1);
+ glRotatef( 90, 1, 0, 0);
+ glScalef(.15, .15, .15);
# OpenGL state for "glowing transparent particles"
- glEnable(.GL_BLEND)
- glBlendFunc(.GL_SRC_ALPHA, .GL_ONE)
- glDepthMask(.GL_FALSE)
- glPointSize(4)
-
- # XXXX: Disabled for now because it's broken on many systems;
- # will replace later with textured quads
- # glEnable(.GL_POINT_SMOOTH)
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ glDepthMask(GL_FALSE);
+ glPointSize(4);
+
+ # XXX: Disabled for now because it's broken on many systems;
+ # will replace later with textured quads
+ # glEnable(GL_POINT_SMOOTH);
# # Show plane of effect
-# glColor4f(1, 1, 1, .2)
-# glBegin(.GL_QUADS)
-# glVertex3f(-2, -2, 0)
-# glVertex3f( 2, -2, 0)
-# glVertex3f( 2, 2, 0)
-# glVertex3f(-2, 2, 0)
-# glEnd()
-
- # Start drawing particles
- glColor4f(1, 1, 1, .5)
- glBegin(.GL_POINTS)
-
- # Global particle state arrays
- .local pmc pfx_pos, pfx_vel
- pfx_pos = get_global 'pfx_pos'
- pfx_vel = get_global 'pfx_vel'
-
- # Loop over all particles, updating and drawing them
- .local int count
- count = pfx_pos
- draw_particle_loop:
- dec count
- if count < 0 goto draw_particle_loop_end
-
- # Draw particle
- .local pmc pos
- .local num x, y, z
- pos = pfx_pos[count]
- x = pos[0]
- y = pos[1]
- z = pos[2]
- glVertex3f(x, y, z)
-
- goto draw_particle_loop
-
- # Finished with all particles
- draw_particle_loop_end:
- glEnd()
+# glColor4f(1, 1, 1, .2);
+# glBegin(GL_QUADS);
+# glVertex3f(-2, -2, 0);
+# glVertex3f( 2, -2, 0);
+# glVertex3f( 2, 2, 0);
+# glVertex3f(-2, 2, 0);
+# glEnd();
+
+ # White color, but semi-transparent
+ glColor4f(1, 1, 1, .5);
+
+ # Draw all particles
+ glBegin(GL_POINTS);
+ for @pfx_pos -> $pos {
+ # XXX: Rakudo bug - appears not to properly unpack for NCI calls
+ # glVertex3f(|$pos);
+ my ($x, $y, $z) = @($pos)[0..2];
+ glVertex3f($x, $y, $z);
+ }
+ glEnd();
# Done, return to normal OpenGL state
- glDepthMask(.GL_TRUE)
- glDisable(.GL_BLEND)
-
- glPopMatrix()
-.end
+ glDepthMask(GL_TRUE);
+ glDisable(GL_BLEND);
+ glPopMatrix();
+}
-=end pod
# Local Variables:
# mode: pir
Modified: branches/pmc_pct/examples/opengl/shapes.pir
==============================================================================
--- branches/pmc_pct/examples/opengl/shapes.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/opengl/shapes.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -37,7 +37,7 @@
mode |= .GLUT_DEPTH
mode |= .GLUT_STENCIL
window = new 'Integer'
- window = init_glut(argv, mode, 'Test')
+ window = init_glut(argv, mode, 'Shapes: OpenGL 1.x NCI Test')
set_global 'glut_window', window
# Init miscellaneous globals
@@ -69,7 +69,7 @@
# Load OpenGL libary and a helper library for calling glutInit
load_bytecode 'OpenGL.pbc'
- load_bytecode 'NCI/call_toolkit_init.pbc'
+ load_bytecode 'NCI/Utils.pbc'
# Import all OpenGL/GLU/GLUT functions
.local pmc import_gl
@@ -81,7 +81,7 @@
# Initialize GLUT, overwriting argv in place
.local pmc call_toolkit_init
- call_toolkit_init = get_global ['NCI'], 'call_toolkit_init'
+ call_toolkit_init = get_global ['NCI';'Utils'], 'call_toolkit_init'
.const 'Sub' glutInit = 'glutInit'
$P0 = call_toolkit_init(glutInit, argv)
Modified: branches/pmc_pct/examples/opengl/static-triangle.p6
==============================================================================
--- branches/pmc_pct/examples/opengl/static-triangle.p6 Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/opengl/static-triangle.p6 Fri Jun 26 08:35:24 2009 (r39797)
@@ -8,10 +8,9 @@
=head1 SYNOPSIS
- $ cd parrot-home
- $ make perl6
- $ cd parrot-home/runtime/parrot/library
- $ ../../../perl6 ../../../examples/opengl/static-triangle.p6
+ $ cd rakudo-home
+ $ export PERL6LIB=rakudo-home:parrot-home/runtime/parrot/library
+ $ ./perl6 parrot-home/examples/opengl/static-triangle.p6
=head1 DESCRIPTION
@@ -21,43 +20,54 @@
debug problems with the Parrot NCI system and Rakudo's ability to use Parrot
NCI modules.
-To quit the example, close the window using your window manager (using
-the X in the corner of the window title bar, for example), since all
-keyboard handling has been removed.
+To quit the example, close the window using your window manager (using the X
+in the corner of the window title bar, for example), since all keyboard
+handling has been removed.
=end pod
-use OpenGL;
-use NCI::call_toolkit_init;
+# None of these currently work; they all create an inescapable new lexical pad
+# require 'glutconst.p6';
+# 'glutconst.p6'.evalfile;
+# eval open('glutconst.p6').slurp;
+
+constant GLUT_RGBA = 0x0000;
+constant GLUT_DOUBLE = 0x0002;
+constant GL_TRIANGLES = 0x0004;
+constant GL_DEPTH_BUFFER_BIT = 0x0100;
+constant GL_COLOR_BUFFER_BIT = 0x4000;
+
+use OpenGL:from<parrot>;
+use NCI::Utils:from<parrot>;
+
+sub MAIN(*@ARGS is rw) {
+ # Initialize GLUT
+ @ARGS = call_toolkit_init(&glutInit, @ARGS, $*PROGRAM_NAME);
+
+ # Set display mode
+ glutInitDisplayMode(GLUT_DOUBLE +| GLUT_RGBA);
+
+ # Create GLUT window
+ glutCreateWindow('Static Triangle NCI Test');
-# .include 'opengl_defines.pasm'
-my $GL_COLOR_BUFFER_BIT = 0x4000;
-my $GL_DEPTH_BUFFER_BIT = 0x0100;
-my $GL_TRIANGLES = 4;
-my $GLUT_DOUBLE = 2;
-my $GLUT_RGBA = 0;
+ # Set up GLUT callbacks
+ glutDisplayFunc(&draw);
+ # Enter the GLUT main loop
+ glutMainLoop();
-OpenGL::_export_all_functions();
-
-@*ARGS = NCI::call_toolkit_init(&glutInit, @*ARGS);
-
-glutInitDisplayMode($GLUT_DOUBLE +| $GLUT_RGBA);
-
-my $window = glutCreateWindow('Test');
-
-glutDisplayFunc(&draw);
-
-glutMainLoop();
+ # Rakudo bug -- glutMainLoop() never returns, but Rakudo dies without this
+ return;
+}
sub draw {
- glClear($GL_COLOR_BUFFER_BIT +| $GL_DEPTH_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT +| GL_DEPTH_BUFFER_BIT);
- glBegin($GL_TRIANGLES);
- glColor3f(1, 0, 0); glVertex3f(-.5, -.5, 0);
- glColor3f(0, 1, 0); glVertex3f( .5, -.5, 0);
- glColor3f(0, 0, 1); glVertex3f(0 , .5, 0);
+ glBegin(GL_TRIANGLES);
+ glColor3f(1, 0, 0); glVertex3f(-1, -1, 0);
+ glColor3f(0, 1, 0); glVertex3f( 1, -1, 0);
+ glColor3f(0, 0, 1); glVertex3f( 0, 1, 0);
glEnd();
glutSwapBuffers();
Modified: branches/pmc_pct/examples/opengl/static-triangle.pir
==============================================================================
--- branches/pmc_pct/examples/opengl/static-triangle.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/opengl/static-triangle.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -30,7 +30,7 @@
# Load OpenGL libary and a helper library for calling glutInit
load_bytecode 'OpenGL.pbc'
- load_bytecode 'NCI/call_toolkit_init.pbc'
+ load_bytecode 'NCI/Utils.pbc'
# Import all OpenGL/GLU/GLUT functions
.local pmc import_gl
@@ -39,7 +39,7 @@
# Initialize GLUT
.local pmc call_toolkit_init
- call_toolkit_init = get_global ['NCI'], 'call_toolkit_init'
+ call_toolkit_init = get_global ['NCI'; 'Utils'], 'call_toolkit_init'
.const 'Sub' glutInit = 'glutInit'
argv = call_toolkit_init(glutInit, argv)
@@ -51,7 +51,7 @@
.local pmc window
window = new 'Integer'
- window = glutCreateWindow('Test')
+ window = glutCreateWindow('Static Triangle NCI Test')
set_global 'glut_window', window
# Set up GLUT callbacks
Modified: branches/pmc_pct/examples/opengl/triangle.p6
==============================================================================
--- branches/pmc_pct/examples/opengl/triangle.p6 Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/opengl/triangle.p6 Fri Jun 26 08:35:24 2009 (r39797)
@@ -8,10 +8,9 @@
=head1 SYNOPSIS
- $ cd parrot-home
- $ make perl6
- $ cd parrot-home/runtime/parrot/library
- $ ../../../perl6 ../../../examples/opengl/triangle.p6
+ $ cd rakudo-home
+ $ export PERL6LIB=rakudo-home:parrot-home/runtime/parrot/library
+ $ ./perl6 parrot-home/examples/opengl/triangle.p6
=head1 DESCRIPTION
@@ -30,38 +29,50 @@
=end pod
-use OpenGL;
-use NCI::call_toolkit_init;
+# None of these currently work; they all create an inescapable new lexical pad
+# require 'glutconst.p6';
+# 'glutconst.p6'.evalfile;
+# eval open('glutconst.p6').slurp;
+
+constant GLUT_RGBA = 0x0000;
+constant GLUT_DOUBLE = 0x0002;
+constant GL_TRIANGLES = 0x0004;
+constant GL_DEPTH_BUFFER_BIT = 0x0100;
+constant GL_COLOR_BUFFER_BIT = 0x4000;
+
+use OpenGL:from<parrot>;
+use NCI::Utils:from<parrot>;
+
+our $rotating = 1;
+our $prev_time = time();
+our $window;
+
+sub MAIN(*@ARGS is rw) {
+ # Initialize GLUT
+ @ARGS = call_toolkit_init(&glutInit, @ARGS, $*PROGRAM_NAME);
+
+ # Set display mode
+ glutInitDisplayMode(GLUT_DOUBLE +| GLUT_RGBA);
+
+ # Create GLUT window
+ $window = glutCreateWindow('Rotating Triangle NCI Test');
+
+ # Set up GLUT callbacks
+ glutDisplayFunc( &draw );
+ glutIdleFunc( &idle );
+ glutKeyboardFunc( &keyboard );
-# .include 'opengl_defines.pasm'
-my $GL_COLOR_BUFFER_BIT = 0x4000;
-my $GL_DEPTH_BUFFER_BIT = 0x0100;
-my $GL_TRIANGLES = 4;
-my $GLUT_DOUBLE = 2;
-my $GLUT_RGBA = 0;
+ # Enter the GLUT main loop
+ glutMainLoop();
-
-OpenGL::_export_all_functions();
-
-@*ARGS = NCI::call_toolkit_init(&glutInit, @*ARGS);
-
-glutInitDisplayMode($GLUT_DOUBLE +| $GLUT_RGBA);
-
-my $window = glutCreateWindow('Test');
-
-glutDisplayFunc( &draw );
-glutIdleFunc( &idle );
-glutKeyboardFunc( &keyboard );
-
-my $rotating = 1;
-my $prev_time = time();
-
-glutMainLoop();
+ # Rakudo bug -- glutMainLoop() never returns, but Rakudo dies without this
+ return;
+}
sub draw {
- glClear($GL_COLOR_BUFFER_BIT +| $GL_DEPTH_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT +| GL_DEPTH_BUFFER_BIT);
- glBegin($GL_TRIANGLES);
+ glBegin(GL_TRIANGLES);
glColor3f(1, 0, 0); glVertex3f(-.5, -.5, 0);
glColor3f(0, 1, 0); glVertex3f( .5, -.5, 0);
glColor3f(0, 0, 1); glVertex3f(0 , .5, 0);
Modified: branches/pmc_pct/examples/opengl/triangle.pir
==============================================================================
--- branches/pmc_pct/examples/opengl/triangle.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/opengl/triangle.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -25,7 +25,6 @@
=cut
-
.include 'opengl_defines.pasm'
.sub main :main
@@ -33,7 +32,7 @@
# Load OpenGL libary and a helper library for calling glutInit
load_bytecode 'OpenGL.pbc'
- load_bytecode 'NCI/call_toolkit_init.pbc'
+ load_bytecode 'NCI/Utils.pbc'
# Import all OpenGL/GLU/GLUT functions
.local pmc import_gl
@@ -42,7 +41,7 @@
# Initialize GLUT
.local pmc call_toolkit_init
- call_toolkit_init = get_global ['NCI'], 'call_toolkit_init'
+ call_toolkit_init = get_global ['NCI';'Utils'], 'call_toolkit_init'
.const 'Sub' glutInit = 'glutInit'
argv = call_toolkit_init(glutInit, argv)
@@ -54,7 +53,7 @@
.local pmc window
window = new 'Integer'
- window = glutCreateWindow('Test')
+ window = glutCreateWindow('Rotating Triangle NCI Test')
set_global 'glut_window', window
# Set up GLUT callbacks
@@ -145,6 +144,7 @@
.local pmc rotating
rotating = get_global 'rotating'
rotating = not rotating
+ set_global 'rotating', rotating
.end
Modified: branches/pmc_pct/examples/tutorial/01_temp_var.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/01_temp_var.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/01_temp_var.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -23,7 +23,7 @@
$S5 = "Hello" # set temp string var to "Hello"
- $P0 = new 'String'
+ $P0 = new ['String']
$P0 = "Ford" # set temp PMC var to "Ford"
say $I0
Modified: branches/pmc_pct/examples/tutorial/02_local_var.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/02_local_var.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/02_local_var.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -36,7 +36,7 @@
print "\n"
.local pmc player
- player = new 'String'
+ player = new ['String']
player = "Ford" # set temp PMC var to "Ford"
print player
print "\n"
Modified: branches/pmc_pct/examples/tutorial/03_temp_var_basic_pmcs.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/03_temp_var_basic_pmcs.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/03_temp_var_basic_pmcs.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -18,15 +18,15 @@
=cut
.sub main :main
- $P0 = new 'Integer'
+ $P0 = new ['Integer']
$P0 = 42
say $P0
- $P1 = new 'Float'
+ $P1 = new ['Float']
$P1 = 6.35
say $P1
- $P2 = new 'ResizableStringArray'
+ $P2 = new ['ResizableStringArray']
$P2[0] = "Foo"
$P2[1] = "Bar"
$P2[2] = "Baz"
Modified: branches/pmc_pct/examples/tutorial/24_string_ops_clone.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/24_string_ops_clone.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/24_string_ops_clone.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -14,7 +14,7 @@
.sub main :main
.local pmc firstname
- firstname = new 'String'
+ firstname = new ['String']
firstname = "Ford"
say firstname
Modified: branches/pmc_pct/examples/tutorial/30_arrays_basic.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/30_arrays_basic.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/30_arrays_basic.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -18,7 +18,7 @@
.sub main :main
.local pmc myarray
- myarray = new 'ResizableStringArray'
+ myarray = new ['ResizableStringArray']
myarray[0] = "Foo"
push myarray, "Bar"
Modified: branches/pmc_pct/examples/tutorial/32_array_ops_sprintf.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/32_array_ops_sprintf.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/32_array_ops_sprintf.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -14,13 +14,13 @@
.sub main :main
.local pmc myarray
- myarray = new 'ResizablePMCArray'
+ myarray = new ['ResizablePMCArray']
- $P0 = new 'Integer'
+ $P0 = new ['Integer']
$P0 = 42
push myarray, $P0
- $P1 = new 'Float'
+ $P1 = new ['Float']
$P1 = 10.5
push myarray, $P1
Modified: branches/pmc_pct/examples/tutorial/33_hashes.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/33_hashes.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/33_hashes.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -22,7 +22,7 @@
.sub main :main
.local pmc myhash
- myhash = new 'Hash'
+ myhash = new ['Hash']
myhash['foo'] = 5
myhash['bar'] = "Hello"
Modified: branches/pmc_pct/examples/tutorial/34_multikey.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/34_multikey.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/34_multikey.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -17,8 +17,8 @@
.sub main :main
.local pmc myhash, innerarray
- myhash = new 'Hash'
- innerarray = new 'ResizableIntegerArray'
+ myhash = new ['Hash']
+ innerarray = new ['ResizableIntegerArray']
$I0 = 2
innerarray[2] = 42
Modified: branches/pmc_pct/examples/tutorial/40_file_ops.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/40_file_ops.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/40_file_ops.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -20,7 +20,7 @@
close filein
# Be nice and remove the temporary file we created.
- $P1 = new 'OS'
+ $P1 = new ['OS']
$P1.'rm'('40_file_ops_data.txt')
.end
Modified: branches/pmc_pct/examples/tutorial/55_iterator.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/55_iterator.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/55_iterator.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -21,7 +21,7 @@
myarray = split " ", "foo bar baz boz"
- iter = new 'Iterator', myarray
+ iter = new ['Iterator'], myarray
iter_loop:
unless iter goto iter_end
Modified: branches/pmc_pct/examples/tutorial/56_defined.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/56_defined.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/56_defined.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -15,7 +15,7 @@
.sub main :main
- $P1 = new 'String'
+ $P1 = new ['String']
$I0 = defined $P1
if $I0 goto defined_P1
say "$P1 is undefined"
@@ -32,7 +32,7 @@
=cut
end_defined_P1:
- $P3 = new 'Undef'
+ $P3 = new ['Undef']
$I0 = defined $P3
if $I0 goto defined_P3
say "$P3 is undefined"
Modified: branches/pmc_pct/examples/tutorial/57_exists.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/57_exists.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/57_exists.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -23,10 +23,10 @@
# set up an array with two elements
.local pmc my_array
- my_array = new 'ResizablePMCArray'
- $P0 = new 'String'
+ my_array = new ['ResizablePMCArray']
+ $P0 = new ['String']
$P0 = "Hello"
- $P1 = new 'Undef'
+ $P1 = new ['Undef']
push my_array, $P0
push my_array, $P1
Modified: branches/pmc_pct/examples/tutorial/61_namespaces.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/61_namespaces.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/61_namespaces.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -20,7 +20,7 @@
.sub main :main
- $P0 = new 'String'
+ $P0 = new ['String']
$P0 = "Hello"
set_global ["Different"; "Namespace"], "foo", $P0
Modified: branches/pmc_pct/examples/tutorial/70_class_object.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/70_class_object.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/70_class_object.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -37,7 +37,7 @@
addattribute myclass, 'bar'
addattribute myclass, 'baz'
- myobj = new 'Foo'
+ myobj = new ['Foo']
myobj.'set_bar'("Hello")
myobj.'set_baz'(5)
@@ -61,7 +61,7 @@
.sub set_bar :method
.param string value
- $P0 = new 'String'
+ $P0 = new ['String']
$P0 = value
setattribute self, "bar", $P0
.end
@@ -74,7 +74,7 @@
.sub set_baz :method
.param int value
- $P0 = new 'Integer'
+ $P0 = new ['Integer']
$P0 = value
setattribute self, "baz", $P0
.end
Modified: branches/pmc_pct/examples/tutorial/81_continuation.pir
==============================================================================
--- branches/pmc_pct/examples/tutorial/81_continuation.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/examples/tutorial/81_continuation.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -15,7 +15,7 @@
.sub main :main
.local pmc cont
- cont = new 'Continuation'
+ cont = new ['Continuation']
set_addr cont, continued
test_call(4, cont)
Modified: branches/pmc_pct/include/parrot/key.h
==============================================================================
--- branches/pmc_pct/include/parrot/key.h Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/include/parrot/key.h Fri Jun 26 08:35:24 2009 (r39797)
@@ -167,7 +167,7 @@
__attribute__nonnull__(2);
PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
+PARROT_CAN_RETURN_NULL
STRING * key_string(PARROT_INTERP, ARGIN(PMC *key))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
Modified: branches/pmc_pct/include/parrot/memory.h
==============================================================================
--- branches/pmc_pct/include/parrot/memory.h Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/include/parrot/memory.h Fri Jun 26 08:35:24 2009 (r39797)
@@ -70,6 +70,12 @@
size_t size,
size_t old_size);
+PARROT_EXPORT
+PARROT_MALLOC
+PARROT_CANNOT_RETURN_NULL
+char * mem_sys_strdup(ARGIN(const char *src))
+ __attribute__nonnull__(1);
+
PARROT_MALLOC
PARROT_CANNOT_RETURN_NULL
void * mem__internal_allocate(
@@ -116,6 +122,8 @@
#define ASSERT_ARGS_mem_sys_free __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
#define ASSERT_ARGS_mem_sys_realloc __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
#define ASSERT_ARGS_mem_sys_realloc_zeroed __attribute__unused__ int _ASSERT_ARGS_CHECK = 0
+#define ASSERT_ARGS_mem_sys_strdup __attribute__unused__ int _ASSERT_ARGS_CHECK = \
+ PARROT_ASSERT_ARG(src)
#define ASSERT_ARGS_mem__internal_allocate __attribute__unused__ int _ASSERT_ARGS_CHECK = \
PARROT_ASSERT_ARG(file)
#define ASSERT_ARGS_mem__internal_allocate_zeroed __attribute__unused__ int _ASSERT_ARGS_CHECK = \
Modified: branches/pmc_pct/include/parrot/stacks.h
==============================================================================
--- branches/pmc_pct/include/parrot/stacks.h Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/include/parrot/stacks.h Fri Jun 26 08:35:24 2009 (r39797)
@@ -37,7 +37,7 @@
/* #define STACK_ITEMSIZE(chunk) PObj_buflen(chunk) */
-typedef void (*Stack_cleanup_method)(Interp*, Stack_Entry_t *);
+typedef void (*Stack_cleanup_method)(PARROT_INTERP, ARGIN(struct Stack_Entry *));
#define STACK_CLEANUP_NULL ((Stack_cleanup_method)NULLfunc)
Modified: branches/pmc_pct/include/parrot/sub.h
==============================================================================
--- branches/pmc_pct/include/parrot/sub.h Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/include/parrot/sub.h Fri Jun 26 08:35:24 2009 (r39797)
@@ -169,9 +169,10 @@
#define PMC_get_sub(interp, pmc, sub) \
do { \
- if ((pmc)->vtable->base_type == enum_class_Sub || \
- (pmc)->vtable->base_type == enum_class_Coroutine || \
- (pmc)->vtable->base_type == enum_class_Eval) \
+ const INTVAL type = (pmc)->vtable->base_type; \
+ if (type == enum_class_Sub || \
+ type == enum_class_Coroutine || \
+ type == enum_class_Eval) \
{\
GETATTR_Sub_sub((interp), (pmc), (sub)); \
} \
Modified: branches/pmc_pct/lib/Parrot/Docs/Section/Parrot.pm
==============================================================================
--- branches/pmc_pct/lib/Parrot/Docs/Section/Parrot.pm Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/lib/Parrot/Docs/Section/Parrot.pm Fri Jun 26 08:35:24 2009 (r39797)
@@ -60,7 +60,7 @@
'Introduction',
'',
$self->new_item( 'Introduction to Parrot', 'docs/intro.pod'),
- $self->new_item( 'Getting Started', 'docs/book/ch02_getting_started.pod'),
+ $self->new_item( 'Getting Started', 'docs/book/draft/ch02_getting_started.pod'),
$self->new_item( 'Navigating the Docs', 'docs/parrot.pod'),
$self->new_item( 'Roles & Responsibilities', 'docs/project/roles_responsibilities.pod'),
$self->new_item( 'Release History', 'docs/parrothist.pod'),
@@ -80,9 +80,9 @@
$self->new_group(
'Implementing Languages on Parrot',
'',
- $self->new_item( 'Parrot Compiler Tools', 'docs/book/ch04_compiler_tools.pod'),
- $self->new_item( 'Parrot Grammar Engine', 'docs/book/ch05_pge.pod'),
- $self->new_item( 'Not Quite Perl', 'docs/book/ch06_nqp.pod'),
+ $self->new_item( 'Parrot Compiler Tools', 'docs/book/draft/ch04_compiler_tools.pod'),
+ $self->new_item( 'Parrot Grammar Engine', 'docs/book/draft/ch05_pge.pod'),
+ $self->new_item( 'Not Quite Perl', 'docs/book/draft/ch06_nqp.pod'),
$self->new_item( 'Compiler FAQ', 'docs/compiler_faq.pod'),
),
$self->new_group(
@@ -97,24 +97,38 @@
$self->new_item( 'Syntax Highlighting for Vim & Emacs', 'editor/README.pod'),
),
$self->new_group(
- 'Book',
+ 'Book draft',
'',
- $self->new_item( 'Chapter 1 Introduction', 'docs/book/ch01_introduction.pod'),
- $self->new_item( 'Chapter 2 Getting Started', 'docs/book/ch02_getting_started.pod'),
- $self->new_item( 'Chapter 3 Parrot Intermediate Representation', 'docs/book/ch03_pir.pod'),
- $self->new_item( 'Chapter 4 Parrot Compiler Tools', 'docs/book/ch04_compiler_tools.pod'),
- $self->new_item( 'Chapter 5 Parrot Grammar Engine', 'docs/book/ch05_pge.pod'),
- $self->new_item( 'Chapter 6 Not Quite Perl', 'docs/book/ch06_nqp.pod'),
- $self->new_item( 'Chapter 7 Dynamic C-level Objects', 'docs/book/ch07_dynpmcs.pod'),
- $self->new_item( 'Chapter 8 Dynamic Opcodes', 'docs/book/ch08_dynops.pod'),
- $self->new_item( 'Chapter 10 Instruction Reference', 'docs/book/ch10_opcode_reference.pod'),
- $self->new_item( 'Chapter 11 Directive Reference', 'docs/book/ch11_directive_reference.pod'),
- $self->new_item( 'Chapter 12 PIR Operator Reference', 'docs/book/ch12_operator_reference.pod'),
- $self->new_item( 'Appendix A Glossary', 'docs/book/appa_glossary.pod'),
- $self->new_item( 'Appendix B Patch Submission', 'docs/book/appb_patch_submission.pod'),
- $self->new_item( 'Appendix C ', 'docs/book/appc_command_line_options.pod'),
- $self->new_item( 'Appendix D ', 'docs/book/appd_build_options.pod'),
- $self->new_item( 'Appendix E ', 'docs/book/appe_source_code.pod'),
+ $self->new_item( 'Chapter 1 Introduction', 'docs/book/draft/ch01_introduction.pod'),
+ $self->new_item( 'Chapter 2 Getting Started', 'docs/book/draft/ch02_getting_started.pod'),
+ $self->new_item( 'Chapter 3 Parrot Intermediate Representation', 'docs/book/draft/ch03_pir.pod'),
+ $self->new_item( 'Chapter 4 Parrot Compiler Tools', 'docs/book/draft/ch04_compiler_tools.pod'),
+ $self->new_item( 'Chapter 5 Parrot Grammar Engine', 'docs/book/draft/ch05_pge.pod'),
+ $self->new_item( 'Chapter 6 Not Quite Perl', 'docs/book/draft/ch06_nqp.pod'),
+ $self->new_item( 'Chapter 7 Dynamic C-level Objects', 'docs/book/draft/ch07_dynpmcs.pod'),
+ $self->new_item( 'Chapter 8 Dynamic Opcodes', 'docs/book/draft/ch08_dynops.pod'),
+ $self->new_item( 'Chapter 10 Instruction Reference', 'docs/book/draft/ch10_opcode_reference.pod'),
+ $self->new_item( 'Chapter 11 Directive Reference', 'docs/book/draft/ch11_directive_reference.pod'),
+ $self->new_item( 'Chapter 12 PIR Operator Reference', 'docs/book/draft/ch12_operator_reference.pod'),
+ $self->new_item( 'Appendix A Glossary', 'docs/book/draft/appa_glossary.pod'),
+ $self->new_item( 'Appendix B Patch Submission', 'docs/book/draft/appb_patch_submission.pod'),
+ $self->new_item( 'Appendix C ', 'docs/book/draft/appc_command_line_options.pod'),
+ $self->new_item( 'Appendix D ', 'docs/book/draft/appd_build_options.pod'),
+ $self->new_item( 'Appendix E ', 'docs/book/draft/appe_source_code.pod'),
+ ),
+
+ $self->new_group(
+ 'Book PIR',
+ '',
+ $self->new_item( 'Chapter 1 Introduction', 'docs/book/pir/ch01_introduction.pod'),
+ $self->new_item( 'Chapter 2 Getting Started', 'docs/book/pir/ch02_getting_started.pod'),
+ $self->new_item( 'Chapter 3 Basic Syntax', 'docs/book/pir/ch03_basic_syntax.pod'),
+ $self->new_item( 'Chapter 4 Variables', 'docs/book/pir/ch04_variables.pod'),
+ $self->new_item( 'Chapter 5 Control Structures', 'docs/book/pir/ch05_control_structures.pod'),
+ $self->new_item( 'Chapter 6 Subroutines', 'docs/book/pir/ch06_subroutines.pod'),
+ $self->new_item( 'Chapter 7 Objects', 'docs/book/pir/ch07_objects.pod'),
+ $self->new_item( 'Chapter 8 IO', 'docs/book/pir/ch08_io.pod'),
+ $self->new_item( 'Chapter 9 Exceptions', 'docs/book/pir/ch09_exceptions.pod'),
),
# Parrot::Docs::Section::C->new,
Modified: branches/pmc_pct/lib/Parrot/Install.pm
==============================================================================
--- branches/pmc_pct/lib/Parrot/Install.pm Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/lib/Parrot/Install.pm Fri Jun 26 08:35:24 2009 (r39797)
@@ -173,12 +173,16 @@
=cut
sub create_directories {
- my($destdir, $directories) = @_;
+ my ( $destdir, $directories ) = @_;
+
+ my @dirs_to_create = grep { ! -d } map { $destdir . $_ } sort keys %{$directories};
+
+ my $print_the_dirs = 0;
+ my $mode = oct('0777');
+
+ # We must use the legacy interface to support File::Path versions before 2.01.
+ my @dirs_created = mkpath( \@dirs_to_create, $print_the_dirs, $mode );
- my @dirs_created = mkpath(
- ( grep { ! -d } map { $destdir . $_ } keys %$directories ),
- { mode => 0777 },
- );
return 1;
}
Modified: branches/pmc_pct/lib/Parrot/Pmc2c/Attribute.pm
==============================================================================
--- branches/pmc_pct/lib/Parrot/Pmc2c/Attribute.pm Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/lib/Parrot/Pmc2c/Attribute.pm Fri Jun 26 08:35:24 2009 (r39797)
@@ -145,7 +145,7 @@
$decl .= <<"EOA";
PMC * const attr_value = VTABLE_get_attr_str(interp, \\
pmc, Parrot_str_new_constant(interp, "$attrname")); \\
- (dest) = (PMC_IS_NULL(attr_value) ? (STRING *) 0: VTABLE_get_string(interp, attr_value)); \\
+ (dest) = (PMC_IS_NULL(attr_value) ? (STRING *)NULL : VTABLE_get_string(interp, attr_value)); \\
EOA
}
elsif ($attrtype =~ $isptrtopmc) {
Modified: branches/pmc_pct/lib/Parrot/Pmc2c/PMC.pm
==============================================================================
--- branches/pmc_pct/lib/Parrot/Pmc2c/PMC.pm Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/lib/Parrot/Pmc2c/PMC.pm Fri Jun 26 08:35:24 2009 (r39797)
@@ -204,6 +204,11 @@
return $self->{parents};
}
+sub direct_parents {
+ my ($self) = @_;
+ return $self->{direct_parents};
+}
+
sub mixins {
my ($self) = @_;
return $self->{mixins};
@@ -235,7 +240,10 @@
sub set_parents {
my ( $self, $value ) = @_;
$value ||= [];
- $self->{parents} = $value;
+ $self->{parents} = $value;
+ for my $dp (@{ $value }) {
+ push @{$self->{direct_parents}}, $dp;
+ }
return 1;
}
Modified: branches/pmc_pct/lib/Parrot/Pmc2c/PMC/RO.pm
==============================================================================
--- branches/pmc_pct/lib/Parrot/Pmc2c/PMC/RO.pm Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/lib/Parrot/Pmc2c/PMC/RO.pm Fri Jun 26 08:35:24 2009 (r39797)
@@ -44,7 +44,7 @@
my $self = bless Parrot::Pmc2c::PMC->new(
{
parents => [ $parent->name, @{ $parent->parents } ], # prepend self to parrent
- flags => { ( %{ $parent->get_flags } ), 'is_ro' => 1 }, # copy flags, set is_const
+ flags => { ( %{ $parent->get_flags } ), 'is_ro' => 1 }, # copy flags, set is_ro
name => $parent->name . "_ro", # set pmcname
vtable => $parent->vtable, # and alias vtable
parentname => $parent->name, # set parentname
Modified: branches/pmc_pct/lib/Parrot/Pmc2c/PMCEmitter.pm
==============================================================================
--- branches/pmc_pct/lib/Parrot/Pmc2c/PMCEmitter.pm Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/lib/Parrot/Pmc2c/PMCEmitter.pm Fri Jun 26 08:35:24 2009 (r39797)
@@ -94,6 +94,8 @@
$c->emit( $self->update_vtable_func );
$c->emit( $self->get_vtable_func );
+ $c->emit( $self->get_mro_func );
+ $c->emit( $self->get_isa_func );
$c->emit( $self->init_func );
$c->emit( $self->postamble );
@@ -135,6 +137,8 @@
}
$h->emit("${export}VTABLE* Parrot_${name}_get_vtable(PARROT_INTERP);\n");
$h->emit("${export}VTABLE* Parrot_${name}_ro_get_vtable(PARROT_INTERP);\n");
+ $h->emit("${export}PMC* Parrot_${name}_get_mro(PARROT_INTERP, PMC* mro);\n");
+ $h->emit("${export}Hash* Parrot_${name}_get_isa(PARROT_INTERP, Hash* isa);\n");
$self->gen_attributes;
@@ -207,8 +211,6 @@
sub init {
my ($self) = @_;
- $self->fixup_singleton if $self->singleton;
-
#!( singleton or abstract ) everything else gets readonly version of
# methods too.
@@ -216,38 +218,6 @@
unless $self->abstract or $self->singleton;
}
-sub fixup_singleton {
- my ($self) = @_;
-
- # Because singletons are shared between interpreters, we need to make
- # special effort to use the right namespace for method lookups.
- #
- # Note that this trick won't work if the singleton inherits from something
- # else (because the MRO will still be shared).
-
- unless ( $self->implements_vtable('get_namespace')
- or $self->super_method('get_namespace') ne 'default' )
- {
- my $body =
- Parrot::Pmc2c::Emitter->text(
- " return INTERP->vtables[SELF->vtable->base_type]->_namespace;\n");
- $self->add_method(
- Parrot::Pmc2c::Method->new(
- {
- name => 'get_namespace',
- parent_name => $self->name,
- parameters => '',
- body => $body,
- type => Parrot::Pmc2c::Method::VTABLE,
- mmds => [],
- return_type => 'PMC*',
- attrs => {},
- }
- )
- );
- }
-}
-
=item C<gen_includes()>
Returns the C C<#include> for the header file of each of the PMC's superclasses.
@@ -620,32 +590,16 @@
EOC
}
- $cout .= <<"EOC";
- if (pass == 0) {
-EOC
- for my $k ( keys %extra_vt ) {
- $cout .= " VTABLE *vt_$k;\n";
- }
-
my $flags = $self->vtable_flags;
$cout .= <<"EOC";
- Hash *isa_hash = NULL;
+ if (pass == 0) {
VTABLE * const vt = Parrot_${classname}_get_vtable(interp);
vt->base_type = $enum_name;
vt->flags = $flags;
vt->attribute_defs = attr_defs;
+ interp->vtables[entry] = vt;
EOC
- for my $k ( keys %extra_vt ) {
- my $k_flags = $self->$k->vtable_flags;
- $cout .= <<"EOC";
- vt_${k} = Parrot_${classname}_${k}_get_vtable(interp);
- vt_${k}->base_type = $enum_name;
- vt_${k}->flags = $k_flags;
- vt_${k}->attribute_defs = attr_defs;
-
-EOC
- }
# init vtable slot
if ( $self->is_dynamic ) {
@@ -654,7 +608,7 @@
vt->whoami = string_make(interp, "$classname", @{[length($classname)]},
"ascii", PObj_constant_FLAG|PObj_external_FLAG);
vt->provides_str = Parrot_str_append(interp, vt->provides_str,
- string_make(interp, " $provides", @{[length($provides) + 1]}, "ascii",
+ string_make(interp, "$provides", @{[length($provides)]}, "ascii",
PObj_constant_FLAG|PObj_external_FLAG));
EOC
@@ -669,9 +623,7 @@
if (@isa) {
unshift @isa, $classname;
$cout .= <<"EOC";
-
- isa_hash = parrot_new_hash(interp);
- vt->isa_hash = isa_hash;
+ vt->isa_hash = Parrot_${classname}_get_isa(interp, NULL);
EOC
}
else {
@@ -681,28 +633,23 @@
}
for my $k ( keys %extra_vt ) {
+ my $k_flags = $self->$k->vtable_flags;
$cout .= <<"EOC";
- vt_${k}->base_type = entry;
- vt_${k}->whoami = vt->whoami;
- vt_${k}->provides_str = vt->provides_str;
-EOC
- }
-
- for my $k ( keys %extra_vt ) {
- $cout .= <<"EOC";
- vt->${k}_variant_vtable = vt_${k};
- vt_${k}->${k}_variant_vtable = vt;
- vt_${k}->isa_hash = isa_hash;
-EOC
- }
-
- $cout .= <<"EOC";
- interp->vtables[entry] = vt;
-EOC
+ {
+ VTABLE *vt_$k;
+ vt_${k} = Parrot_${classname}_${k}_get_vtable(interp);
+ vt_${k}->base_type = $enum_name;
+ vt_${k}->flags = $k_flags;
+ vt_${k}->attribute_defs = attr_defs;
+
+ vt_${k}->base_type = entry;
+ vt_${k}->whoami = vt->whoami;
+ vt_${k}->provides_str = vt->provides_str;
+ vt->${k}_variant_vtable = vt_${k};
+ vt_${k}->${k}_variant_vtable = vt;
+ vt_${k}->isa_hash = vt->isa_hash;
+ }
- for my $isa (@isa) {
- $cout .= <<"EOC";
- parrot_hash_put(interp, isa_hash, (void *)(CONST_STRING_GEN(interp, "$isa")), PMCNULL);
EOC
}
@@ -735,25 +682,12 @@
$cout .= <<"EOC";
{
- PMC * const mro = pmc_new(interp, enum_class_ResizableStringArray);
VTABLE * const vt = interp->vtables[entry];
- vt->mro = mro;
+ vt->mro = Parrot_${classname}_get_mro(interp, PMCNULL);
if (vt->ro_variant_vtable)
- vt->ro_variant_vtable->mro = mro;
-
-EOC
-
- @isa = $classname unless @isa;
-
- for my $isa (@isa) {
- $cout .= <<"EOC";
- VTABLE_push_string(interp, mro, CONST_STRING_GEN(interp, "$isa"));
-EOC
- }
-
- $cout .= <<"EOC";
+ vt->ro_variant_vtable->mro = vt->mro;
}
/* set up MRO and _namespace */
@@ -764,22 +698,12 @@
foreach my $method ( @{ $self->{methods} } ) {
next unless $method->type eq Parrot::Pmc2c::Method::NON_VTABLE;
- my $proto = proto( $method->return_type, $method->parameters );
my $method_name = $method->name;
- my $symbol_name =
- defined $method->symbol ? $method->symbol : $method->name;
+ my $symbol_name = $method->symbol;
- if ( exists $method->{PCCMETHOD} ) {
- $cout .= <<"EOC";
+ $cout .= <<"EOC";
register_raw_nci_method_in_ns(interp, entry, F2DPTR(Parrot_${classname}_${method_name}), CONST_STRING_GEN(interp, "$symbol_name"));
EOC
- }
- else {
- $cout .= <<"EOC";
- register_nci_method(interp, entry,
- F2DPTR(Parrot_${classname}_${method_name}), "$symbol_name", "$proto");
-EOC
- }
if ( $method->{attrs}{write} ) {
$cout .= <<"EOC";
Parrot_mark_method_writes(interp, entry, "$symbol_name");
@@ -788,12 +712,14 @@
}
# include any class specific init code from the .pmc file
- $cout .= <<"EOC" if $class_init_code;
+ if ($class_init_code) {
+ $cout .= <<"EOC";
/* class_init */
{
$class_init_code
}
EOC
+ }
$cout .= <<"EOC";
{
@@ -876,6 +802,88 @@
$cout;
}
+=item C<get_mro_func()>
+
+Returns the C code for the PMC's get_mro function.
+
+=cut
+
+sub get_mro_func {
+ my ($self) = @_;
+
+ my $cout = "";
+ my $classname = $self->name;
+ my $get_mro = '';
+ my @parent_names;
+ my $export = $self->is_dynamic ? 'PARROT_DYNEXT_EXPORT ' : 'PARROT_EXPORT';
+
+ if ($classname ne 'default') {
+ for my $dp (reverse @{ $self->direct_parents}) {
+ $get_mro .= " mro = Parrot_${dp}_get_mro(interp, mro);\n"
+ unless $dp eq 'default';
+ }
+ }
+
+ $cout .= <<"EOC";
+$export
+PARROT_CANNOT_RETURN_NULL
+PARROT_WARN_UNUSED_RESULT
+PMC* Parrot_${classname}_get_mro(PARROT_INTERP, PMC* mro) {
+ if (PMC_IS_NULL(mro)) {
+ mro = pmc_new(interp, enum_class_ResizableStringArray);
+ }
+$get_mro
+ VTABLE_unshift_string(interp, mro,
+ string_make(interp, "$classname", @{[length($classname)]}, NULL, 0));
+ return mro;
+}
+
+EOC
+
+ $cout;
+}
+
+=item C<get_isa_func()>
+
+Returns the C code for the PMC's get_isa function.
+
+=cut
+
+sub get_isa_func {
+ my ($self) = @_;
+
+ my $cout = "";
+ my $classname = $self->name;
+ my $get_isa = '';
+ my @parent_names;
+ my $export = $self->is_dynamic ? 'PARROT_DYNEXT_EXPORT ' : 'PARROT_EXPORT';
+
+ if ($classname ne 'default') {
+ for my $dp (reverse @{ $self->direct_parents}) {
+ $get_isa .= " isa = Parrot_${dp}_get_isa(interp, isa);\n"
+ unless $dp eq 'default';
+ }
+ }
+
+ $cout .= <<"EOC";
+$export
+PARROT_CANNOT_RETURN_NULL
+PARROT_WARN_UNUSED_RESULT
+Hash* Parrot_${classname}_get_isa(PARROT_INTERP, Hash* isa) {
+ if (isa == NULL) {
+ isa = parrot_new_hash(interp);
+ }
+$get_isa
+ parrot_hash_put(interp, isa, (void *)(CONST_STRING_GEN(interp, "$classname")), PMCNULL);
+ return isa;
+}
+
+EOC
+
+ $cout;
+}
+
+
=item C<get_vtable_func()>
Returns the C code for the PMC's update_vtable method.
@@ -887,17 +895,24 @@
my $cout = "";
my $classname = $self->name;
+ my @other_parents = reverse @{ $self->direct_parents };
+ my $first_parent = shift @other_parents;
my $get_vtable = '';
- foreach my $parent_name ( reverse ($self->name, @{ $self->parents }) ) {
- if ($parent_name eq 'default') {
- $get_vtable .= " vt = Parrot_default_get_vtable(interp);\n";
- }
- else {
- $get_vtable .= " Parrot_${parent_name}_update_vtable(vt);\n";
- }
+
+ if ($first_parent eq 'default') {
+ $get_vtable .= " vt = Parrot_default_get_vtable(interp);\n";
+ }
+ else {
+ $get_vtable .= " vt = Parrot_${first_parent}_get_vtable(interp);\n";
+ }
+
+ foreach my $parent_name ( @other_parents) {
+ $get_vtable .= " Parrot_${parent_name}_update_vtable(vt);\n";
}
+ $get_vtable .= " Parrot_${classname}_update_vtable(vt);\n";
+
$cout .= <<"EOC";
PARROT_EXPORT
PARROT_CANNOT_RETURN_NULL
@@ -911,15 +926,20 @@
EOC
my $get_extra_vtable = '';
- foreach my $parent_name ( reverse ($self->name, @{ $self->parents }) ) {
- if ($parent_name eq 'default') {
- $get_extra_vtable .= " vt = Parrot_default_ro_get_vtable(interp);\n";
- }
- else {
- $get_extra_vtable .= " Parrot_${parent_name}_ro_update_vtable(vt);\n";
- }
+
+ if ($first_parent eq 'default') {
+ $get_extra_vtable .= " vt = Parrot_default_ro_get_vtable(interp);\n";
+ }
+ else {
+ $get_extra_vtable .= " vt = Parrot_${first_parent}_ro_get_vtable(interp);\n";
}
+ foreach my $parent_name ( @other_parents ) {
+ $get_extra_vtable .= " Parrot_${parent_name}_ro_update_vtable(vt);\n";
+ }
+
+ $get_extra_vtable .= " Parrot_${classname}_ro_update_vtable(vt);\n";
+
$cout .= <<"EOC";
PARROT_EXPORT
PARROT_CANNOT_RETURN_NULL
@@ -1000,7 +1020,7 @@
1;
}
-# Generate signle case for switch VTABLE
+# Generate single case for switch VTABLE
sub generate_single_case {
my ($self, $vt_method_name, $multi) = @_;
Modified: branches/pmc_pct/runtime/parrot/languages/parrot/parrot.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/languages/parrot/parrot.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/languages/parrot/parrot.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -16,7 +16,7 @@
.sub 'load_library' :method
.param pmc name
.param pmc extra :named :slurpy
- .local pmc name, library, inc_hash
+ .local pmc name, library, ns, inc_hash
.local string file
$I0 = does name, 'array'
if $I0 goto have_namelist
@@ -29,12 +29,18 @@
library = new 'Hash'
library['name'] = name
library['filename'] = file
- # If this fails, we should build a hash of DEFAULT and ALL => the normal ns
- $P0 = get_hll_namespace name
- $P0 = $P0['EXPORT']
+ ns = get_hll_namespace name
+ library['namespace'] = ns
+ $P0 = ns['EXPORT']
+ if null $P0 goto no_exports
library['symbols'] = $P0
- $P0 = get_hll_namespace name
- library['namespace'] = $P0
+ goto symbols_done
+ no_exports:
+ $P0 = new 'Hash'
+ $P0['ALL'] = ns
+ $P0['DEFAULT'] = ns
+ library['symbols'] = $P0
+ symbols_done:
.return (library)
fail:
# TODO: better fail?
@@ -42,23 +48,64 @@
.end
.sub 'export' :method
- .param string list
- # This should accept a tag...
- .local pmc syms, i, ns, relns, exportns
- # We should default to all symbols when none are specified
- syms = split ' ', list
- i = getinterp
- ns = i['namespace';1]
- relns = new 'ResizablePMCArray'
- relns.'push'('EXPORT')
- # This could be a loop, I guess...
- relns.'push'('ALL')
- exportns = ns.'make_namespace'(relns)
- ns.'export_to'(exportns, syms)
- relns.'pop'()
- relns.'push'('DEFAULT')
- exportns = ns.'make_namespace'(relns)
- ns.'export_to'(exportns, syms)
+ .param pmc symbols
+ .param pmc tags :optional
+ .param pmc from_ns :optional
+
+ # 1. Canonify / default params
+
+ # If space-delimited symbol string, canonify to array;
+ # may also pass a hash to allow symbol rename during export
+ $I0 = does symbols, 'array'
+ $I1 = does symbols, 'hash'
+ $I2 = $I0 | $I1
+ if $I2 goto symbols_ready
+ $S0 = symbols
+ symbols = split ' ', $S0
+ symbols_ready:
+
+ # If space-delimited tag string, canonify to array;
+ # if no tags, use ALL and DEFAULT
+ unless null tags goto have_tags
+ tags = new 'ResizableStringArray'
+ tags.'push'('ALL')
+ tags.'push'('DEFAULT')
+ goto tags_is_array
+ have_tags:
+ $I0 = does tags, 'array'
+ if $I0 goto tags_is_array
+ $S0 = tags
+ tags = split ' ', $S0
+ tags_is_array:
+
+ # If no from_ns, export from caller's namespace
+ unless null from_ns goto has_from_ns
+ $P0 = getinterp
+ from_ns = $P0['namespace'; 1]
+ has_from_ns:
+
+ # 2. Export symbols to each tag namespace
+ # (e.g. ['parrot';'Module';'Name';'EXPORT';'tagname'])
+
+ # rel_ns_key will hold ['EXPORT';'tagname'] for each tagname
+ .local pmc rel_ns_key
+ rel_ns_key = new 'ResizableStringArray'
+ rel_ns_key.'push'('EXPORT')
+
+ # For each tagname, use rel_ns_key to make a new EXPORT namespace
+ # and export all symbols to it, using native NameSpace .export_to()
+ .local pmc tag_iter, export_ns
+ tag_iter = iter tags
+ tag_loop:
+ unless tag_iter goto tag_loop_end
+ $S0 = shift tag_iter
+ rel_ns_key.'push'($S0)
+ export_ns = from_ns.'make_namespace'(rel_ns_key)
+ from_ns.'export_to'(export_ns, symbols)
+ rel_ns_key.'pop'()
+ goto tag_loop
+ tag_loop_end:
+
.end
.sub 'import' :method :multi(_,_)
Modified: branches/pmc_pct/runtime/parrot/library/CGI/QueryHash.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/library/CGI/QueryHash.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/library/CGI/QueryHash.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -93,7 +93,7 @@
unless query goto END
.local pmc query_hash, items, items_tmp_1, items_tmp_2
- .local string query, kv, k, v, item_tmp_1, item_tmp_2, last_chars_of_k
+ .local string kv, k, v, item_tmp_1, item_tmp_2, last_chars_of_k
.local int i, j, n, o, len_of_k
query_hash = new 'Hash'
Copied: branches/pmc_pct/runtime/parrot/library/Curses.pir (from r39796, trunk/runtime/parrot/library/Curses.pir)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/runtime/parrot/library/Curses.pir Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/runtime/parrot/library/Curses.pir)
@@ -0,0 +1,670 @@
+# Copyright (C) 2004-2009, Parrot Foundation.
+# $Id$
+
+.namespace ['Curses']
+.sub __ncurses_init :load
+
+loadlib $P1, 'libform'
+if $P1 goto has_lib
+loadlib $P1, 'cygform-8'
+has_lib:
+dlfunc $P2, $P1, 'new_field', 'piiiiii'
+set_global 'new_field', $P2
+dlfunc $P2, $P1, 'dup_field', 'ppii'
+set_global 'dup_field', $P2
+dlfunc $P2, $P1, 'link_field', 'ppii'
+set_global 'link_field', $P2
+dlfunc $P2, $P1, 'free_field', 'ip'
+set_global 'free_field', $P2
+dlfunc $P2, $P1, 'field_info', 'ip333333'
+set_global 'field_info', $P2
+dlfunc $P2, $P1, 'dynamic_field_info', 'ip333'
+set_global 'dynamic_field_info', $P2
+dlfunc $P2, $P1, 'set_max_field', 'ipi'
+set_global 'set_max_field', $P2
+dlfunc $P2, $P1, 'move_field', 'ipii'
+set_global 'move_field', $P2
+dlfunc $P2, $P1, 'set_new_page', 'ipl'
+set_global 'set_new_page', $P2
+dlfunc $P2, $P1, 'set_field_just', 'ipi'
+set_global 'set_field_just', $P2
+dlfunc $P2, $P1, 'field_just', 'ip'
+set_global 'field_just', $P2
+dlfunc $P2, $P1, 'set_field_fore', 'ipl'
+set_global 'set_field_fore', $P2
+dlfunc $P2, $P1, 'set_field_back', 'ipl'
+set_global 'set_field_back', $P2
+dlfunc $P2, $P1, 'set_field_pad', 'ipi'
+set_global 'set_field_pad', $P2
+dlfunc $P2, $P1, 'field_pad', 'ip'
+set_global 'field_pad', $P2
+dlfunc $P2, $P1, 'set_field_buffer', 'ipit'
+set_global 'set_field_buffer', $P2
+dlfunc $P2, $P1, 'set_field_status', 'ipl'
+set_global 'set_field_status', $P2
+dlfunc $P2, $P1, 'set_field_userptr', 'ipp'
+set_global 'set_field_userptr', $P2
+dlfunc $P2, $P1, 'set_field_opts', 'ipi'
+set_global 'set_field_opts', $P2
+dlfunc $P2, $P1, 'field_opts_on', 'ipi'
+set_global 'field_opts_on', $P2
+dlfunc $P2, $P1, 'field_opts_off', 'ipi'
+set_global 'field_opts_off', $P2
+dlfunc $P2, $P1, 'field_fore', 'lp'
+set_global 'field_fore', $P2
+dlfunc $P2, $P1, 'field_back', 'ip'
+set_global 'field_back', $P2
+dlfunc $P2, $P1, 'new_page', 'lp'
+set_global 'new_page', $P2
+dlfunc $P2, $P1, 'field_status', 'lp'
+set_global 'field_status', $P2
+dlfunc $P2, $P1, 'field_arg', 'pp'
+set_global 'field_arg', $P2
+dlfunc $P2, $P1, 'field_userptr', 'pp'
+set_global 'field_userptr', $P2
+dlfunc $P2, $P1, 'field_type', 'pp'
+set_global 'field_type', $P2
+dlfunc $P2, $P1, 'field_buffer', 'tpi'
+set_global 'field_buffer', $P2
+dlfunc $P2, $P1, 'field_opts', 'lp'
+set_global 'field_opts', $P2
+dlfunc $P2, $P1, 'new_form', 'pb'
+set_global 'new_form', $P2
+dlfunc $P2, $P1, 'current_field', 'pp'
+set_global 'current_field', $P2
+dlfunc $P2, $P1, 'form_win', 'pp'
+set_global 'form_win', $P2
+dlfunc $P2, $P1, 'form_sub', 'pp'
+set_global 'form_sub', $P2
+dlfunc $P2, $P1, 'free_form', 'ip'
+set_global 'free_form', $P2
+dlfunc $P2, $P1, 'set_form_fields', 'ipb'
+set_global 'set_form_fields', $P2
+dlfunc $P2, $P1, 'field_count', 'ip'
+set_global 'field_count', $P2
+dlfunc $P2, $P1, 'set_form_win', 'ipp'
+set_global 'set_form_win', $P2
+dlfunc $P2, $P1, 'set_form_sub', 'ipp'
+set_global 'set_form_sub', $P2
+dlfunc $P2, $P1, 'set_current_field', 'ipp'
+set_global 'set_current_field', $P2
+dlfunc $P2, $P1, 'field_index', 'ip'
+set_global 'field_index', $P2
+dlfunc $P2, $P1, 'set_form_page', 'ipi'
+set_global 'set_form_page', $P2
+dlfunc $P2, $P1, 'form_page', 'ip'
+set_global 'form_page', $P2
+dlfunc $P2, $P1, 'scale_form', 'ip33'
+set_global 'scale_form', $P2
+dlfunc $P2, $P1, 'post_form', 'ip'
+set_global 'post_form', $P2
+dlfunc $P2, $P1, 'unpost_form', 'ip'
+set_global 'unpost_form', $P2
+dlfunc $P2, $P1, 'pos_form_cursor', 'ip'
+set_global 'pos_form_cursor', $P2
+dlfunc $P2, $P1, 'form_driver', 'ipi'
+set_global 'form_driver', $P2
+dlfunc $P2, $P1, 'set_form_userptr', 'ipp'
+set_global 'set_form_userptr', $P2
+dlfunc $P2, $P1, 'set_form_opts', 'ipi'
+set_global 'set_form_opts', $P2
+dlfunc $P2, $P1, 'form_opts_on', 'ipi'
+set_global 'form_opts_on', $P2
+dlfunc $P2, $P1, 'form_opts_off', 'ipi'
+set_global 'form_opts_off', $P2
+dlfunc $P2, $P1, 'form_request_by_name', 'it'
+set_global 'form_request_by_name', $P2
+dlfunc $P2, $P1, 'form_request_name', 'ti'
+set_global 'form_request_name', $P2
+dlfunc $P2, $P1, 'form_userptr', 'pp'
+set_global 'form_userptr', $P2
+dlfunc $P2, $P1, 'form_opts', 'ip'
+set_global 'form_opts', $P2
+dlfunc $P2, $P1, 'data_ahead', 'lp'
+set_global 'data_ahead', $P2
+dlfunc $P2, $P1, 'data_behind', 'lp'
+set_global 'data_behind', $P2
+
+loadlib $P1, 'libncurses'
+if $P1 goto has_lib1
+loadlib $P1, 'cygncurses-8'
+has_lib1:
+dlfunc $P2, $P1, 'keybound', 'tii'
+set_global 'keybound', $P2
+
+dlfunc $P2, $P1, 'curses_version', 't'
+set_global 'curses_version', $P2
+dlfunc $P2, $P1, 'assume_default_colors', 'iii'
+set_global 'assume_default_colors', $P2
+dlfunc $P2, $P1, 'define_key', 'iti'
+set_global 'define_key', $P2
+dlfunc $P2, $P1, 'keyok', 'iii'
+set_global 'keyok', $P2
+dlfunc $P2, $P1, 'resizeterm', 'iii'
+set_global 'resizeterm', $P2
+dlfunc $P2, $P1, 'use_default_colors', 'i'
+set_global 'use_default_colors', $P2
+dlfunc $P2, $P1, 'use_extended_names', 'ii'
+set_global 'use_extended_names', $P2
+dlfunc $P2, $P1, 'wresize', 'ipii'
+set_global 'wresize', $P2
+dlfunc $P2, $P1, 'addch', 'il'
+set_global 'addch', $P2
+dlfunc $P2, $P1, 'addchnstr', 'i4i'
+set_global 'addchnstr', $P2
+dlfunc $P2, $P1, 'addchstr', 'i4'
+set_global 'addchstr', $P2
+dlfunc $P2, $P1, 'addnstr', 'iti'
+set_global 'addnstr', $P2
+dlfunc $P2, $P1, 'addstr', 'it'
+set_global 'addstr', $P2
+dlfunc $P2, $P1, 'attroff', 'il'
+set_global 'attroff', $P2
+dlfunc $P2, $P1, 'attron', 'il'
+set_global 'attron', $P2
+dlfunc $P2, $P1, 'attrset', 'il'
+set_global 'attrset', $P2
+dlfunc $P2, $P1, 'attr_get', 'i42p'
+set_global 'attr_get', $P2
+dlfunc $P2, $P1, 'attr_off', 'ilp'
+set_global 'attr_off', $P2
+dlfunc $P2, $P1, 'attr_on', 'ilp'
+set_global 'attr_on', $P2
+dlfunc $P2, $P1, 'attr_set', 'ilsp'
+set_global 'attr_set', $P2
+dlfunc $P2, $P1, 'baudrate', 'i'
+set_global 'baudrate', $P2
+dlfunc $P2, $P1, 'beep', 'i'
+set_global 'beep', $P2
+dlfunc $P2, $P1, 'bkgd', 'il'
+set_global 'bkgd', $P2
+dlfunc $P2, $P1, 'bkgdset', 'vl'
+set_global 'bkgdset', $P2
+dlfunc $P2, $P1, 'border', 'villllllll'
+set_global 'border', $P2
+dlfunc $P2, $P1, 'box', 'ipll'
+set_global 'box', $P2
+dlfunc $P2, $P1, 'can_change_color', 'l'
+set_global 'can_change_color', $P2
+dlfunc $P2, $P1, 'cbreak', 'i'
+set_global 'cbreak', $P2
+dlfunc $P2, $P1, 'chgat', 'iilsp'
+set_global 'chgat', $P2
+dlfunc $P2, $P1, 'clear', 'i'
+set_global 'clear', $P2
+dlfunc $P2, $P1, 'clearok', 'ipl'
+set_global 'clearok', $P2
+dlfunc $P2, $P1, 'clrtobot', 'i'
+set_global 'clrtobot', $P2
+dlfunc $P2, $P1, 'clrtoeol', 'i'
+set_global 'clrtoeol', $P2
+dlfunc $P2, $P1, 'color_content', 'is222'
+set_global 'color_content', $P2
+dlfunc $P2, $P1, 'color_set', 'isp'
+set_global 'color_set', $P2
+dlfunc $P2, $P1, 'COLOR_PAIR', 'ii'
+set_global 'COLOR_PAIR', $P2
+dlfunc $P2, $P1, 'copywin', 'ippiiiiiiii'
+set_global 'copywin', $P2
+dlfunc $P2, $P1, 'curs_set', 'ii'
+set_global 'curs_set', $P2
+dlfunc $P2, $P1, 'def_prog_mode', 'i'
+set_global 'def_prog_mode', $P2
+dlfunc $P2, $P1, 'def_shell_mode', 'i'
+set_global 'def_shell_mode', $P2
+dlfunc $P2, $P1, 'delay_output', 'ii'
+set_global 'delay_output', $P2
+dlfunc $P2, $P1, 'delch', 'i'
+set_global 'delch', $P2
+dlfunc $P2, $P1, 'delscreen', 'vp'
+set_global 'delscreen', $P2
+dlfunc $P2, $P1, 'delwin', 'ip'
+set_global 'delwin', $P2
+dlfunc $P2, $P1, 'deleteln', 'i'
+set_global 'deleteln', $P2
+dlfunc $P2, $P1, 'derwin', 'ppiiii'
+set_global 'derwin', $P2
+dlfunc $P2, $P1, 'doupdate', 'i'
+set_global 'doupdate', $P2
+dlfunc $P2, $P1, 'dupwin', 'pp'
+set_global 'dupwin', $P2
+dlfunc $P2, $P1, 'echo', 'i'
+set_global 'echo', $P2
+dlfunc $P2, $P1, 'echochar', 'il'
+set_global 'echochar', $P2
+dlfunc $P2, $P1, 'erase', 'i'
+set_global 'erase', $P2
+dlfunc $P2, $P1, 'endwin', 'i'
+set_global 'endwin', $P2
+dlfunc $P2, $P1, 'erasechar', 'c'
+set_global 'erasechar', $P2
+dlfunc $P2, $P1, 'filter', 'v'
+set_global 'filter', $P2
+dlfunc $P2, $P1, 'flash', 'i'
+set_global 'flash', $P2
+dlfunc $P2, $P1, 'flushinp', 'i'
+set_global 'flushinp', $P2
+dlfunc $P2, $P1, 'getbkgd', 'lp'
+set_global 'getbkgd', $P2
+dlfunc $P2, $P1, 'getch', 'i'
+set_global 'getch', $P2
+dlfunc $P2, $P1, 'getnstr', 'iti'
+set_global 'getnstr', $P2
+dlfunc $P2, $P1, 'getstr', 'it'
+set_global 'getstr', $P2
+dlfunc $P2, $P1, 'getwin', 'pp'
+set_global 'getwin', $P2
+dlfunc $P2, $P1, 'halfdelay', 'ii'
+set_global 'halfdelay', $P2
+dlfunc $P2, $P1, 'has_colors', 'i'
+set_global 'has_colors', $P2
+dlfunc $P2, $P1, 'has_ic', 'i'
+set_global 'has_ic', $P2
+dlfunc $P2, $P1, 'has_il', 'i'
+set_global 'has_il', $P2
+dlfunc $P2, $P1, 'hline', 'ili'
+set_global 'hline', $P2
+dlfunc $P2, $P1, 'idcok', 'vpl'
+set_global 'idcok', $P2
+dlfunc $P2, $P1, 'idlok', 'ipl'
+set_global 'idlok', $P2
+dlfunc $P2, $P1, 'immedok', 'vpl'
+set_global 'immedok', $P2
+dlfunc $P2, $P1, 'inch', 'l'
+set_global 'inch', $P2
+dlfunc $P2, $P1, 'inchnstr', 'i4i'
+set_global 'inchnstr', $P2
+dlfunc $P2, $P1, 'inchstr', 'i4'
+set_global 'inchstr', $P2
+dlfunc $P2, $P1, 'initscr', 'p'
+set_global 'initscr', $P2
+dlfunc $P2, $P1, 'init_color', 'issss'
+set_global 'init_color', $P2
+dlfunc $P2, $P1, 'init_pair', 'isss'
+set_global 'init_pair', $P2
+dlfunc $P2, $P1, 'innstr', 'iti'
+set_global 'innstr', $P2
+dlfunc $P2, $P1, 'insstr', 'it'
+set_global 'insstr', $P2
+dlfunc $P2, $P1, 'instr', 'it'
+set_global 'instr', $P2
+dlfunc $P2, $P1, 'intrflush', 'ipl'
+set_global 'intrflush', $P2
+dlfunc $P2, $P1, 'isendwin', 'l'
+set_global 'isendwin', $P2
+dlfunc $P2, $P1, 'is_linetouched', 'lpi'
+set_global 'is_linetouched', $P2
+dlfunc $P2, $P1, 'is_wintouched', 'lp'
+set_global 'is_wintouched', $P2
+dlfunc $P2, $P1, 'keyname', 'ti'
+set_global 'keyname', $P2
+dlfunc $P2, $P1, 'keypad', 'ipl'
+set_global 'keypad', $P2
+dlfunc $P2, $P1, 'killchar', 'c'
+set_global 'killchar', $P2
+dlfunc $P2, $P1, 'leaveok', 'ipl'
+set_global 'leaveok', $P2
+dlfunc $P2, $P1, 'longname', 't'
+set_global 'longname', $P2
+dlfunc $P2, $P1, 'meta', 'ipl'
+set_global 'meta', $P2
+dlfunc $P2, $P1, 'move', 'iii'
+set_global 'move', $P2
+dlfunc $P2, $P1, 'mvaddch', 'iiil'
+set_global 'mvaddch', $P2
+dlfunc $P2, $P1, 'mvaddchnstr', 'iii4i'
+set_global 'mvaddchnstr', $P2
+dlfunc $P2, $P1, 'mvaddchstr', 'iii4'
+set_global 'mvaddchstr', $P2
+dlfunc $P2, $P1, 'mvaddnstr', 'iiiti'
+set_global 'mvaddnstr', $P2
+dlfunc $P2, $P1, 'mvaddstr', 'iiit'
+set_global 'mvaddstr', $P2
+dlfunc $P2, $P1, 'mvchgat', 'iiiilsp'
+set_global 'mvchgat', $P2
+#dlfunc $P2, $P1, 'mvcur', 'iiiii'
+#set_global 'mvcur', $P2
+dlfunc $P2, $P1, 'mvdelch', 'iii'
+set_global 'mvdelch', $P2
+dlfunc $P2, $P1, 'mvderwin', 'ipii'
+set_global 'mvderwin', $P2
+dlfunc $P2, $P1, 'mvgetch', 'iii'
+set_global 'mvgetch', $P2
+dlfunc $P2, $P1, 'mvgetnstr', 'iiiti'
+set_global 'mvgetnstr', $P2
+dlfunc $P2, $P1, 'mvgetstr', 'iiit'
+set_global 'mvgetstr', $P2
+dlfunc $P2, $P1, 'mvhline', 'iiili'
+set_global 'mvhline', $P2
+dlfunc $P2, $P1, 'mvinch', 'lii'
+set_global 'mvinch', $P2
+dlfunc $P2, $P1, 'mvinchnstr', 'iiiti'
+set_global 'mvinchnstr', $P2
+dlfunc $P2, $P1, 'mvinchstr', 'iii4'
+set_global 'mvinchstr', $P2
+dlfunc $P2, $P1, 'mvinnstr', 'iiiti'
+set_global 'mvinnstr', $P2
+dlfunc $P2, $P1, 'mvinsch', 'iiil'
+set_global 'mvinsch', $P2
+dlfunc $P2, $P1, 'mvinsnstr', 'iiiti'
+set_global 'mvinsnstr', $P2
+dlfunc $P2, $P1, 'mvinsstr', 'iiit'
+set_global 'mvinsstr', $P2
+dlfunc $P2, $P1, 'mvvline', 'iiili'
+set_global 'mvvline', $P2
+dlfunc $P2, $P1, 'mvwaddch', 'ipiil'
+set_global 'mvwaddch', $P2
+dlfunc $P2, $P1, 'mvwaddchnstr', 'ipii4i'
+set_global 'mvwaddchnstr', $P2
+dlfunc $P2, $P1, 'mvwaddchstr', 'ipii4'
+set_global 'mvwaddchstr', $P2
+dlfunc $P2, $P1, 'mvwaddnstr', 'ipiiti'
+set_global 'mvwaddnstr', $P2
+dlfunc $P2, $P1, 'mvwaddstr', 'ipiit'
+set_global 'mvwaddstr', $P2
+dlfunc $P2, $P1, 'mvwchgat', 'ipiiilsp'
+set_global 'mvwchgat', $P2
+dlfunc $P2, $P1, 'mvwdelch', 'ipii'
+set_global 'mvwdelch', $P2
+dlfunc $P2, $P1, 'mvwgetch', 'ipii'
+set_global 'mvwgetch', $P2
+dlfunc $P2, $P1, 'mvwgetnstr', 'ipiiti'
+set_global 'mvwgetnstr', $P2
+dlfunc $P2, $P1, 'mvwgetstr', 'ipiit'
+set_global 'mvwgetstr', $P2
+dlfunc $P2, $P1, 'mvwhline', 'ipiili'
+set_global 'mvwhline', $P2
+dlfunc $P2, $P1, 'mvwin', 'ipii'
+set_global 'mvwin', $P2
+dlfunc $P2, $P1, 'mvwinch', 'lpii'
+set_global 'mvwinch', $P2
+dlfunc $P2, $P1, 'mvwinchnstr', 'ipii4i'
+set_global 'mvwinchnstr', $P2
+dlfunc $P2, $P1, 'mvwinchstr', 'ipii4'
+set_global 'mvwinchstr', $P2
+dlfunc $P2, $P1, 'mvwinnstr', 'ipiiti'
+set_global 'mvwinnstr', $P2
+dlfunc $P2, $P1, 'mvwinsch', 'ipiil'
+set_global 'mvwinsch', $P2
+dlfunc $P2, $P1, 'mvwinsnstr', 'ipiiti'
+set_global 'mvwinsnstr', $P2
+dlfunc $P2, $P1, 'mvwinsstr', 'ipiit'
+set_global 'mvwinsstr', $P2
+dlfunc $P2, $P1, 'mvwinstr', 'ipiit'
+set_global 'mvwinstr', $P2
+dlfunc $P2, $P1, 'mvwvline', 'ipiili'
+set_global 'mvwvline', $P2
+dlfunc $P2, $P1, 'napms', 'ii'
+set_global 'napms', $P2
+dlfunc $P2, $P1, 'newpad', 'pii'
+set_global 'newpad', $P2
+dlfunc $P2, $P1, 'newterm', 'ptpp'
+set_global 'newterm', $P2
+dlfunc $P2, $P1, 'newwin', 'piiii'
+set_global 'newwin', $P2
+dlfunc $P2, $P1, 'nl', 'i'
+set_global 'nl', $P2
+dlfunc $P2, $P1, 'nocbreak', 'i'
+set_global 'nocbreak', $P2
+dlfunc $P2, $P1, 'nodelay', 'ipl'
+set_global 'nodelay', $P2
+dlfunc $P2, $P1, 'noecho', 'i'
+set_global 'noecho', $P2
+dlfunc $P2, $P1, 'nonl', 'i'
+set_global 'nonl', $P2
+dlfunc $P2, $P1, 'noqiflush', 'v'
+set_global 'noqiflush', $P2
+dlfunc $P2, $P1, 'noraw', 'i'
+set_global 'noraw', $P2
+dlfunc $P2, $P1, 'notimeout', 'ipl'
+set_global 'notimeout', $P2
+dlfunc $P2, $P1, 'overlay', 'ipp'
+set_global 'overlay', $P2
+dlfunc $P2, $P1, 'overwrite', 'ipp'
+set_global 'overwrite', $P2
+dlfunc $P2, $P1, 'pair_content', 'is22'
+set_global 'pair_content', $P2
+dlfunc $P2, $P1, 'PAIR_NUMBER', 'ii'
+set_global 'PAIR_NUMBER', $P2
+dlfunc $P2, $P1, 'pechochar', 'ipl'
+set_global 'pechochar', $P2
+dlfunc $P2, $P1, 'pnoutrefresh', 'ipiiiiii'
+set_global 'pnoutrefresh', $P2
+dlfunc $P2, $P1, 'prefresh', 'ipiiiiii'
+set_global 'prefresh', $P2
+dlfunc $P2, $P1, 'putp', 'it'
+set_global 'putp', $P2
+dlfunc $P2, $P1, 'putwin', 'ipp'
+set_global 'putwin', $P2
+dlfunc $P2, $P1, 'qiflush', 'v'
+set_global 'qiflush', $P2
+dlfunc $P2, $P1, 'raw', 'i'
+set_global 'raw', $P2
+dlfunc $P2, $P1, 'redrawwin', 'ip'
+set_global 'redrawwin', $P2
+dlfunc $P2, $P1, 'refresh', 'i'
+set_global 'refresh', $P2
+dlfunc $P2, $P1, 'resetty', 'i'
+set_global 'resetty', $P2
+dlfunc $P2, $P1, 'reset_prog_mode', 'i'
+set_global 'reset_prog_mode', $P2
+dlfunc $P2, $P1, 'reset_shell_mode', 'i'
+set_global 'reset_shell_mode', $P2
+dlfunc $P2, $P1, 'ripoffline', 'iiip'
+set_global 'ripoffline', $P2
+dlfunc $P2, $P1, 'savetty', 'i'
+set_global 'savetty', $P2
+dlfunc $P2, $P1, 'scr_dump', 'it'
+set_global 'scr_dump', $P2
+dlfunc $P2, $P1, 'scr_init', 'it'
+set_global 'scr_init', $P2
+dlfunc $P2, $P1, 'scrl', 'ii'
+set_global 'scrl', $P2
+dlfunc $P2, $P1, 'scroll', 'ip'
+set_global 'scroll', $P2
+dlfunc $P2, $P1, 'scrollok', 'ipl'
+set_global 'scrollok', $P2
+dlfunc $P2, $P1, 'scr_restore', 'it'
+set_global 'scr_restore', $P2
+dlfunc $P2, $P1, 'scr_set', 'it'
+set_global 'scr_set', $P2
+dlfunc $P2, $P1, 'setscrreg', 'iii'
+set_global 'setscrreg', $P2
+dlfunc $P2, $P1, 'set_term', 'pp'
+set_global 'set_term', $P2
+dlfunc $P2, $P1, 'slk_attroff', 'il'
+set_global 'slk_attroff', $P2
+dlfunc $P2, $P1, 'slk_attron', 'il'
+set_global 'slk_attron', $P2
+dlfunc $P2, $P1, 'slk_attrset', 'il'
+set_global 'slk_attrset', $P2
+dlfunc $P2, $P1, 'slk_attr', 'l'
+set_global 'slk_attr', $P2
+dlfunc $P2, $P1, 'slk_attr_set', 'ilsp'
+set_global 'slk_attr_set', $P2
+dlfunc $P2, $P1, 'slk_clear', 'i'
+set_global 'slk_clear', $P2
+dlfunc $P2, $P1, 'slk_color', 'is'
+set_global 'slk_color', $P2
+dlfunc $P2, $P1, 'slk_init', 'ii'
+set_global 'slk_init', $P2
+dlfunc $P2, $P1, 'slk_label', 'ti'
+set_global 'slk_label', $P2
+dlfunc $P2, $P1, 'slk_noutrefresh', 'i'
+set_global 'slk_noutrefresh', $P2
+dlfunc $P2, $P1, 'slk_refresh', 'i'
+set_global 'slk_refresh', $P2
+dlfunc $P2, $P1, 'slk_restore', 'i'
+set_global 'slk_restore', $P2
+dlfunc $P2, $P1, 'slk_set', 'iiti'
+set_global 'slk_set', $P2
+dlfunc $P2, $P1, 'slk_touch', 'i'
+set_global 'slk_touch', $P2
+dlfunc $P2, $P1, 'standout', 'i'
+set_global 'standout', $P2
+dlfunc $P2, $P1, 'standend', 'i'
+set_global 'standend', $P2
+dlfunc $P2, $P1, 'start_color', 'i'
+set_global 'start_color', $P2
+dlfunc $P2, $P1, 'subpad', 'ppiiii'
+set_global 'subpad', $P2
+dlfunc $P2, $P1, 'subwin', 'ppiiii'
+set_global 'subwin', $P2
+dlfunc $P2, $P1, 'syncok', 'ipl'
+set_global 'syncok', $P2
+dlfunc $P2, $P1, 'termattrs', 'l'
+set_global 'termattrs', $P2
+dlfunc $P2, $P1, 'termname', 't'
+set_global 'termname', $P2
+dlfunc $P2, $P1, 'tigetflag', 'it'
+set_global 'tigetflag', $P2
+dlfunc $P2, $P1, 'tigetnum', 'it'
+set_global 'tigetnum', $P2
+dlfunc $P2, $P1, 'tigetstr', 'tt'
+set_global 'tigetstr', $P2
+dlfunc $P2, $P1, 'timeout', 'vi'
+set_global 'timeout', $P2
+dlfunc $P2, $P1, 'typeahead', 'ii'
+set_global 'typeahead', $P2
+dlfunc $P2, $P1, 'ungetch', 'ii'
+set_global 'ungetch', $P2
+dlfunc $P2, $P1, 'untouchwin', 'ip'
+set_global 'untouchwin', $P2
+dlfunc $P2, $P1, 'use_env', 'vl'
+set_global 'use_env', $P2
+dlfunc $P2, $P1, 'vidattr', 'il'
+set_global 'vidattr', $P2
+dlfunc $P2, $P1, 'vidputs', 'ilp'
+set_global 'vidputs', $P2
+dlfunc $P2, $P1, 'vline', 'ili'
+set_global 'vline', $P2
+dlfunc $P2, $P1, 'waddch', 'ipl'
+set_global 'waddch', $P2
+dlfunc $P2, $P1, 'waddchnstr', 'ip4i'
+set_global 'waddchnstr', $P2
+dlfunc $P2, $P1, 'waddchstr', 'ip4'
+set_global 'waddchstr', $P2
+dlfunc $P2, $P1, 'waddnstr', 'ipti'
+set_global 'waddnstr', $P2
+dlfunc $P2, $P1, 'waddstr', 'ipt'
+set_global 'waddstr', $P2
+dlfunc $P2, $P1, 'wattron', 'ipi'
+set_global 'wattron', $P2
+dlfunc $P2, $P1, 'wattroff', 'ipi'
+set_global 'wattroff', $P2
+dlfunc $P2, $P1, 'wattrset', 'ipi'
+set_global 'wattrset', $P2
+dlfunc $P2, $P1, 'wattr_get', 'ip42p'
+set_global 'wattr_get', $P2
+dlfunc $P2, $P1, 'wattr_on', 'iplp'
+set_global 'wattr_on', $P2
+dlfunc $P2, $P1, 'wattr_off', 'iplp'
+set_global 'wattr_off', $P2
+dlfunc $P2, $P1, 'wattr_set', 'iplsp'
+set_global 'wattr_set', $P2
+dlfunc $P2, $P1, 'wbkgd', 'ipl'
+set_global 'wbkgd', $P2
+dlfunc $P2, $P1, 'wbkgdset', 'vpl'
+set_global 'wbkgdset', $P2
+dlfunc $P2, $P1, 'wborder', 'ipllllllll'
+set_global 'wborder', $P2
+dlfunc $P2, $P1, 'wchgat', 'ipilsp'
+set_global 'wchgat', $P2
+dlfunc $P2, $P1, 'wclear', 'ip'
+set_global 'wclear', $P2
+dlfunc $P2, $P1, 'wclrtobot', 'ip'
+set_global 'wclrtobot', $P2
+dlfunc $P2, $P1, 'wclrtoeol', 'ip'
+set_global 'wclrtoeol', $P2
+dlfunc $P2, $P1, 'wcolor_set', 'ipsp'
+set_global 'wcolor_set', $P2
+dlfunc $P2, $P1, 'wcursyncup', 'vp'
+set_global 'wcursyncup', $P2
+dlfunc $P2, $P1, 'wdelch', 'ip'
+set_global 'wdelch', $P2
+dlfunc $P2, $P1, 'wdeleteln', 'ip'
+set_global 'wdeleteln', $P2
+dlfunc $P2, $P1, 'wechochar', 'ipl'
+set_global 'wechochar', $P2
+dlfunc $P2, $P1, 'werase', 'ip'
+set_global 'werase', $P2
+dlfunc $P2, $P1, 'wgetch', 'ip'
+set_global 'wgetch', $P2
+dlfunc $P2, $P1, 'wgetnstr', 'ipti'
+set_global 'wgetnstr', $P2
+dlfunc $P2, $P1, 'wgetstr', 'ipt'
+set_global 'wgetstr', $P2
+dlfunc $P2, $P1, 'whline', 'ipli'
+set_global 'whline', $P2
+dlfunc $P2, $P1, 'winch', 'lp'
+set_global 'winch', $P2
+dlfunc $P2, $P1, 'winchnstr', 'ip4i'
+set_global 'winchnstr', $P2
+dlfunc $P2, $P1, 'winnstr', 'ipti'
+set_global 'winnstr', $P2
+dlfunc $P2, $P1, 'winsch', 'ipl'
+set_global 'winsch', $P2
+dlfunc $P2, $P1, 'winsdelln', 'ipi'
+set_global 'winsdelln', $P2
+dlfunc $P2, $P1, 'winsertln', 'ip'
+set_global 'winsertln', $P2
+dlfunc $P2, $P1, 'winsnstr', 'ipti'
+set_global 'winsnstr', $P2
+dlfunc $P2, $P1, 'winsstr', 'ipt'
+set_global 'winsstr', $P2
+dlfunc $P2, $P1, 'winstr', 'ipt'
+set_global 'winstr', $P2
+dlfunc $P2, $P1, 'wmove', 'ipii'
+set_global 'wmove', $P2
+dlfunc $P2, $P1, 'wnoutrefresh', 'ip'
+set_global 'wnoutrefresh', $P2
+dlfunc $P2, $P1, 'wredrawln', 'ipii'
+set_global 'wredrawln', $P2
+dlfunc $P2, $P1, 'wrefresh', 'ip'
+set_global 'wrefresh', $P2
+dlfunc $P2, $P1, 'wscrl', 'ipi'
+set_global 'wscrl', $P2
+dlfunc $P2, $P1, 'wsetscrreg', 'ipii'
+set_global 'wsetscrreg', $P2
+dlfunc $P2, $P1, 'wstandout', 'ip'
+set_global 'wstandout', $P2
+dlfunc $P2, $P1, 'wstandend', 'ip'
+set_global 'wstandend', $P2
+dlfunc $P2, $P1, 'wsyncdown', 'vp'
+set_global 'wsyncdown', $P2
+dlfunc $P2, $P1, 'wsyncup', 'vp'
+set_global 'wsyncup', $P2
+dlfunc $P2, $P1, 'wtimeout', 'vpi'
+set_global 'wtimeout', $P2
+dlfunc $P2, $P1, 'wtouchln', 'ipiii'
+set_global 'wtouchln', $P2
+dlfunc $P2, $P1, 'wvline', 'ipli'
+set_global 'wvline', $P2
+dlfunc $P2, $P1, 'getmouse', 'ip'
+set_global 'getmouse', $P2
+dlfunc $P2, $P1, 'ungetmouse', 'ip'
+set_global 'ungetmouse', $P2
+dlfunc $P2, $P1, 'mousemask', 'll4'
+set_global 'mousemask', $P2
+dlfunc $P2, $P1, 'wenclose', 'lpii'
+set_global 'wenclose', $P2
+dlfunc $P2, $P1, 'mouseinterval', 'ii'
+set_global 'mouseinterval', $P2
+dlfunc $P2, $P1, 'wmouse_trafo', 'lp33l'
+set_global 'wmouse_trafo', $P2
+dlfunc $P2, $P1, 'mouse_trafo', 'l33l'
+set_global 'mouse_trafo', $P2
+dlfunc $P2, $P1, 'mcprint', 'iti'
+set_global 'mcprint', $P2
+dlfunc $P2, $P1, 'has_key', 'ii'
+set_global 'has_key', $P2
+
+.begin_return
+.end_return
+.end
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
Modified: branches/pmc_pct/runtime/parrot/library/Getopt/Obj.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/library/Getopt/Obj.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/library/Getopt/Obj.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -202,7 +202,6 @@
key = name
- .local string type
type = spec."type"()
$I2 = length val
@@ -220,7 +219,6 @@
(name, spec) = self."getNameForKey"(key)
if null name goto redofor
- .local string type
type = spec."type"()
unless type == 'Boolean' goto error_2
@@ -263,7 +261,6 @@
beginstore_1:
# Store the value...
- .local string type
type = spec."type"()
if_null val, undef
if type == 'String' goto str
@@ -286,7 +283,6 @@
array:
$P0 = return[name]
if null $P0 goto not_set
- .local string type
type = typeof $P0
unless type != 'ResizableStringArray' goto endif_5
not_set:
@@ -297,7 +293,6 @@
hash:
$P0 = return[name]
if null $P0 goto not_set_hash
- .local string type
type = typeof $P0
unless type != 'Hash' goto endif_7
not_set_hash:
Modified: branches/pmc_pct/runtime/parrot/library/MIME/Base64.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/library/MIME/Base64.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/library/MIME/Base64.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -200,7 +200,7 @@
goto START_5
END_5:
- .local int len, len_mod_4
+ .local int len_mod_4
len = length base64_cleaned
len_mod_4 = len % 4
Copied: branches/pmc_pct/runtime/parrot/library/NCI/Utils.pir (from r39796, trunk/runtime/parrot/library/NCI/Utils.pir)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/runtime/parrot/library/NCI/Utils.pir Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/runtime/parrot/library/NCI/Utils.pir)
@@ -0,0 +1,161 @@
+# Copyright (C) 2008-2009, Parrot Foundation.
+# $Id$
+
+=head1 TITLE
+
+NCI/Utils.pir - Utility functions to make Parrot NCI work easier
+
+=head1 SYNOPSIS
+
+ # Perl 6:
+ # Load this library and the NCI wrapper for a framework/toolkit
+ use NCI::Utils:from<parrot>;
+ use FooTK:from<parrot>;
+
+ sub MAIN(*@ARGS is rw) {
+ # Call toolkit's init function, overwriting @ARGS with mangled copy
+ @ARGS = call_toolkit_init(&fooInit, @ARGS, $*PROGRAM_NAME);
+
+ # Alternately, you can save both the original @ARGS and mangled copy
+ my @mangled_args = call_toolkit_init(&fooInit, @ARGS);
+
+ # ...
+ }
+
+ # PIR:
+ .sub main :main
+ .param pmc argv
+
+ # Load this library and the NCI wrapper for a framework/toolkit
+ load_bytecode 'NCI/Utils.pbc'
+ load_bytecode 'FooTK.pbc'
+
+ # Find Subs for call_toolkit_init() and the toolkit's init function
+ .local pmc call_toolkit_init, fooInit
+ call_toolkit_init = get_global ['NCI';'Utils'], 'call_toolkit_init'
+ fooInit = get_global ['FooTK'], 'fooInit'
+
+ # Call toolkit's init function, overwriting argv with mangled copy
+ argv = call_toolkit_init(fooInit, argv)
+
+ # Alternately, you can save both the original argv and mangled copy
+ .local pmc mangled_argv
+ mangled_argv = call_toolkit_init(fooInit, argv)
+
+ # ...
+ .end
+
+=head1 DESCRIPTION
+
+Some Parrot NCI coding tasks are relatively common, but usually result in
+a relatively grotty bit of code that no one should have to write twice.
+Hence this library, which provides utilities to handle these common tasks
+more cleanly (or at least collect all the grotty code in one place).
+
+Currently, there is just one such utility implemented:
+
+=over 4
+
+=item new_argv = call_toolkit_init(pmc init_func, pmc orig_argv, string program_name?)
+
+Call an NCI void function with params C<(&argc, argv)> (and thus having
+Parrot signature C<'v3p'>). This is a very common signature for toolkit
+(AKA framework) init functions that want to filter out command line
+options that the toolkit itself should process. Since it is expected
+that the init call will remove some arguments, C<call_toolkit_init>
+returns an updated C<argv>. C<orig_argv> is never changed; the NCI call
+is performed using a copy. When calling from an HLL that removes the
+program name from C<argv> automatically, provide the program_name argument
+so that C<call_toolkit_init()> can adjust C<argv> alignment internally;
+this will tend to make the toolkit init function much happier.
+
+=back
+
+=cut
+
+
+.namespace ['NCI'; 'Utils']
+
+.include 'datatypes.pasm'
+
+.sub _init_nci_utils :load
+ # Mark all functions for export
+ .local pmc parrot
+ load_language 'parrot'
+ parrot = compreg 'parrot'
+ parrot.'export'('call_toolkit_init')
+.end
+
+.sub call_toolkit_init
+ .param pmc init_func
+ .param pmc orig_argv
+ .param string program_name :optional
+ .param int has_program_name :opt_flag
+
+ # If program name supplied separately, stuff it into front of argv
+ unless has_program_name goto argv_includes_program_name
+ unshift orig_argv, program_name
+ argv_includes_program_name:
+
+ # Calculate argc
+ .local int count
+ .local pmc argc
+ count = orig_argv
+ argc = new 'Integer'
+ argc = count
+
+ # Declare structure of a raw C string array with proper element count
+ .local pmc argv_decl
+ argv_decl = new 'ResizablePMCArray'
+ push argv_decl, .DATATYPE_CSTR
+ push argv_decl, count
+ push argv_decl, 0
+ # XXX: This is unportably wrong; it assumes sizeof(INT) = sizeof(PTR)
+ push argv_decl, .DATATYPE_INT
+ push argv_decl, 0
+ push argv_decl, 0
+
+ # Create C string array from struct declaration and Parrot string array
+ .local pmc argv
+ .local int i
+ argv = new 'ManagedStruct', argv_decl
+ i = 0
+ argv_loop:
+ unless i < count goto add_null
+ # It seems like this should be possible in one op
+ $S0 = orig_argv[i]
+ argv[0;i] = $S0
+ inc i
+ goto argv_loop
+ add_null:
+ # XXX: This is unportably wrong; it assumes sizeof(INT) = sizeof(PTR)
+ argv[1] = 0
+
+ # Call the NCI framework init function
+ init_func(argc, argv)
+
+ # Build a new_argv array to match the init function's return
+ .local int new_count
+ .local pmc new_argv
+ new_count = argc
+ new_argv = new 'ResizableStringArray'
+ # If program_name was supplied separately from argv, skip it on output
+ i = has_program_name
+ new_argv_loop:
+ unless i < new_count goto done
+ $S0 = argv[0;i]
+ push new_argv, $S0
+ inc i
+ goto new_argv_loop
+
+ # Finally, return the new (and adjusted) argv
+ done:
+ .return (new_argv)
+.end
+
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
Modified: branches/pmc_pct/runtime/parrot/library/OpenGL.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/library/OpenGL.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/library/OpenGL.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -90,7 +90,8 @@
.sub _opengl_init :load
load_bytecode 'OpenGL_funcs.pbc'
_load_opengl_libs()
- _wrap_all_opengl_entry_points()
+ _wrap_opengl_entry_points()
+ _export_opengl_functions()
.end
@@ -107,6 +108,9 @@
.local pmc libnames
libnames = new 'ResizableStringArray'
+ # The following line brought to you by proprietary driver packages
+ # that don't update the libGL.so symlink properly, causing FAIL
+ push libnames, 'libGL.so.1'
push libnames, 'libGL'
push libnames, 'opengl32'
push libnames, '/System/Library/Frameworks/OpenGL.framework/OpenGL'
@@ -173,13 +177,13 @@
.end
-=item _wrap_all_opengl_entry_points()
+=item _wrap_opengl_entry_points()
Create NCI wrappers for all GL, GLU, and GLUT functions
=cut
-.sub _wrap_all_opengl_entry_points
+.sub _wrap_opengl_entry_points
.local pmc namespace
namespace = get_namespace
@@ -246,6 +250,59 @@
=over 4
+=item _export_opengl_functions()
+
+Marks all OpenGL/GLU/GLUT functions as exported (to the default export tags,
+currently ALL and DEFAULT). Unmangles callback names, so that the importing
+namespaces see the standard names instead of the mangled versions. Called
+at :load time by _opengl_init().
+
+=cut
+
+.sub _export_opengl_functions
+ .local pmc gl_namespace
+ gl_namespace = get_namespace
+
+ .local pmc gl_ns_iterator, export_list, export_renames
+ .local string symbol, prefix
+ gl_ns_iterator = iter gl_namespace
+ export_list = new 'ResizableStringArray'
+ export_renames = new 'Hash'
+
+ # Prepare list of symbols and hash of renames for export
+ symbol_loop:
+ unless gl_ns_iterator goto symbol_loop_end
+ symbol = shift gl_ns_iterator
+
+ # For now, only handle symbols starting with 'gl'
+ prefix = substr symbol, 0, 2
+ unless prefix == 'gl' goto symbol_loop
+
+ # Special-case callbacks
+ prefix = substr symbol, 0, 6
+ if prefix == 'glutcb' goto rename_callbacks
+
+ # Add all other matching symbols to export list
+ push export_list, symbol
+ goto symbol_loop
+
+ # Rename all 'glutcb*' symbols to 'glut*'
+ rename_callbacks:
+ .local string renamed
+ renamed = clone symbol
+ substr renamed, 4, 2, ''
+ export_renames[symbol] = renamed
+ goto symbol_loop
+ symbol_loop_end:
+
+ # Mark all symbols and renames for export
+ .local pmc parrot
+ load_language 'parrot'
+ parrot = compreg 'parrot'
+ parrot.'export'(export_list)
+ parrot.'export'(export_renames)
+.end
+
=item _export_all_functions(pmc to_namespace :optional)
Export all OpenGL/GLU/GLUT functions to the target C<namespace>. Unmangles
@@ -268,24 +325,24 @@
.local pmc gl_namespace
gl_namespace = get_namespace
- .local pmc iterator, export_list, export_renames
- .local string symbol, tag
- iterator = iter gl_namespace
+ .local pmc gl_ns_iterator, export_list, export_renames
+ .local string symbol, prefix
+ gl_ns_iterator = iter gl_namespace
export_list = new 'ResizableStringArray'
export_renames = new 'Hash'
# Prepare list of symbols and hash of renames for export
symbol_loop:
- unless iterator goto symbol_loop_end
- symbol = shift iterator
+ unless gl_ns_iterator goto symbol_loop_end
+ symbol = shift gl_ns_iterator
# For now, only handle symbols starting with 'gl'
- tag = substr symbol, 0, 2
- unless tag == 'gl' goto symbol_loop
+ prefix = substr symbol, 0, 2
+ unless prefix == 'gl' goto symbol_loop
# Special-case callbacks
- tag = substr symbol, 0, 6
- if tag == 'glutcb' goto rename_callbacks
+ prefix = substr symbol, 0, 6
+ if prefix == 'glutcb' goto rename_callbacks
# Add all other matching symbols to export list
push export_list, symbol
Copied: branches/pmc_pct/runtime/parrot/library/OpenGL/Math.pir (from r39796, trunk/runtime/parrot/library/OpenGL/Math.pir)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ branches/pmc_pct/runtime/parrot/library/OpenGL/Math.pir Fri Jun 26 08:35:24 2009 (r39797, copy of r39796, trunk/runtime/parrot/library/OpenGL/Math.pir)
@@ -0,0 +1,549 @@
+# Copyright (C) 2009, Parrot Foundation.
+# $Id$
+
+=head1 NAME
+
+OpenGL;Math - Parrot extension for linear algebra following OpenGL conventions
+
+=head1 SYNOPSIS
+
+For more examples, look in F<examples/opengl/>, starting with
+F<examples/opengl/math.pir>.
+
+ # During init ...
+ load_bytecode 'OpenGL/Math.pbc'
+
+ # Later ...
+ XXX - NEED CODE HERE
+
+=head1 DESCRIPTION
+
+NOTE: THIS IS A WORK IN PROGRESS, AND SHOULD NOT BE CONSIDERED USABLE YET.
+
+Any 3D API has to pick certain conventions for handling of vectors and
+matrices, such as the handedness of the default coordinate systems,
+whether matrices are packed in column-major or row-major order, and
+so forth.
+
+This module implements the basic operations of linear algebra according
+to the conventions chosen by OpenGL, and attempts to do so efficiently
+within the bounds set by a pure PIR implementation. It also provides
+efficient packing and unpacking of matrix and vector elements so that
+users need not directly understand the vagaries of OpenGL NCI structures.
+
+Finally, it is a primary goal that users of this module should not need to
+provide any hand-written versions of standard OpenGL matrix manipulations.
+Thus, methods are provided to perform rotations, translations, projections,
+etc.
+
+=cut
+
+.namespace ['OpenGL';'Math']
+
+=head2 OpenGL;Math
+
+The OpenGL;Math class/namespace handles the necessary housekeeping to make
+everything else work smoothly.
+
+=head3 Initialization
+
+The initialization routines are mostly for internal use only. They
+include:
+
+=over 4
+
+=cut
+
+=item _opengl_math_init()
+
+At module load time, calls the other initialization routines in the proper
+order.
+
+=cut
+
+.sub _opengl_math_init :load
+ _create_classes()
+.end
+
+=item _create_classes()
+
+Creates Parrot classes to match each of the OpenGL;Math namespaces, and
+sets up their attributes.
+
+=cut
+
+.sub _create_classes
+ .local pmc Vec4
+ Vec4 = newclass ['OpenGL';'Math';'Vec4']
+ addattribute Vec4, 'vals'
+.end
+
+=back
+
+=cut
+
+
+.namespace ['OpenGL';'Math';'Vec4']
+
+=head2 OpenGL;Math;Vec4
+
+=head3 Instantiation
+
+=over 4
+
+=item Vec4 vec4 = new Vec4
+
+Create a new object representing a four-element vector. You will need
+to set the initial values using the C<set_vals()> method.
+
+=item Vec4 vec4 = Vec4.'new'('vals' => vals)
+
+Create a new object representing a four-element vector, setting the
+initial values to the array PMC C<vals>.
+
+=back
+
+
+=head3 Accessors
+
+=over 4
+
+=item pmc vals = vector.get_vals()
+
+Return a four element array representing the current vector value.
+
+=cut
+
+.sub get_vals :method
+ $P0 = getattribute self, 'vals'
+ .return($P0)
+.end
+
+=item vector.set_vals(pmc vals)
+
+Set the current vector value to a four element array.
+
+=cut
+.sub set_vals :method
+ .param pmc vals
+
+ $I0 = vals
+ unless $I0 == 4 goto wrong_vector_length
+
+ setattribute self, 'vals', vals
+ .return()
+
+ wrong_vector_length:
+ $S0 = 'Input vector is wrong length ('
+ $S1 = $I0
+ $S0 .= $S1
+ $S0 .= ')'
+ die $S0
+.end
+
+=back
+
+
+=head3 Elementwise Operations
+
+=cut
+
+# Standard header for vec4-vec4 binop methods
+.macro vec4_extract_self_plus_vec_arg
+ .param pmc vec2
+
+ .local pmc v1, v2
+ v1 = getattribute self, 'vals'
+ v2 = getattribute vec2, 'vals'
+
+ $N10 = v1[0]
+ $N11 = v1[1]
+ $N12 = v1[2]
+ $N13 = v1[3]
+
+ $N20 = v2[0]
+ $N21 = v2[1]
+ $N22 = v2[2]
+ $N23 = v2[3]
+.endm
+
+# Standard header for vec3-vec3 binop methods
+.macro vec3_extract_self_plus_vec_arg
+ .param pmc vec2
+
+ .local pmc v1, v2
+ v1 = getattribute self, 'vals'
+ v2 = getattribute vec2, 'vals'
+
+ $N10 = v1[0]
+ $N11 = v1[1]
+ $N12 = v1[2]
+
+ $N20 = v2[0]
+ $N21 = v2[1]
+ $N22 = v2[2]
+.endm
+
+# Standard header for vec4-num binop methods
+.macro vec4_extract_self_plus_num_arg
+ .param num N
+
+ .local pmc v1
+ v1 = getattribute self, 'vals'
+
+ $N10 = v1[0]
+ $N11 = v1[1]
+ $N12 = v1[2]
+ $N13 = v1[3]
+.endm
+
+# Standard header for vec3-num binop methods
+.macro vec3_extract_self_plus_num_arg
+ .param num N
+
+ .local pmc v1
+ v1 = getattribute self, 'vals'
+
+ $N10 = v1[0]
+ $N11 = v1[1]
+ $N12 = v1[2]
+.endm
+
+# Standard footer for binop methods returning a vec4
+.macro vec4_return_new_result
+ .local pmc v3
+ v3 = new 'FixedFloatArray'
+ v3 = 4
+
+ v3[0] = $N30
+ v3[1] = $N31
+ v3[2] = $N32
+ v3[3] = $N33
+
+ .local pmc result
+ $P0 = typeof self
+ result = new $P0
+ setattribute result, 'vals', v3
+
+ .return(result)
+.endm
+
+# Standard footer for binop methods returning a vec4 = (vec3, w)
+.macro vec4_return_new_result_with_w(w)
+ .local pmc v3
+ v3 = new 'FixedFloatArray'
+ v3 = 4
+
+ v3[0] = $N30
+ v3[1] = $N31
+ v3[2] = $N32
+ v3[3] = .w
+
+ .local pmc result
+ $P0 = typeof self
+ result = new $P0
+ setattribute result, 'vals', v3
+
+ .return(result)
+.endm
+
+# A standard elementwise vec4 binop (vec4 op vec4 --> vec4)
+.macro vec4_vec4_vec4_binop(name, op)
+.sub .name :method
+ .vec4_extract_self_plus_vec_arg
+
+ $N30 = $N10 .op $N20
+ $N31 = $N11 .op $N21
+ $N32 = $N12 .op $N22
+ $N33 = $N13 .op $N23
+
+ .vec4_return_new_result
+.end
+.endm
+
+
+# A standard elementwise vec4-num binop (vec4 op num --> vec4)
+.macro vec4_num_vec4_binop(name, op)
+.sub .name :method
+ .vec4_extract_self_plus_num_arg
+
+ $N30 = $N10 .op N
+ $N31 = $N11 .op N
+ $N32 = $N12 .op N
+ $N33 = $N13 .op N
+
+ .vec4_return_new_result
+.end
+.endm
+
+
+=over 4
+
+=item Vec4 result = vec1.add(Vec4 vec2)
+
+=item Vec4 result = vec1.sub(Vec4 vec2)
+
+=item Vec4 result = vec1.mul(Vec4 vec2)
+
+=item Vec4 result = vec1.div(Vec4 vec2)
+
+=item Vec4 result = vec1.mod(Vec4 vec2)
+
+Calculate the elementwise addition, subtraction, multiplication, division,
+or modulus (C<vec1 [ + - * / % ] vec2>) and return a new C<Vec4> vector
+C<result>. No attempt is made in C<div> and C<mod> to prevent division by
+zero, XXX - SO WHAT HAPPENS?
+
+=cut
+
+.vec4_vec4_vec4_binop(add, +)
+
+.vec4_vec4_vec4_binop(sub, -)
+
+.vec4_vec4_vec4_binop(mul, *)
+
+.vec4_vec4_vec4_binop(div, /)
+
+.vec4_vec4_vec4_binop(mod, %)
+
+
+=item Vec4 result = vector.add_num(num N)
+
+=item Vec4 result = vector.sub_num(num N)
+
+=item Vec4 result = vector.mul_num(num N)
+
+=item Vec4 result = vector.div_num(num N)
+
+=item Vec4 result = vector.mod_num(num N)
+
+Calculate the elementwise addition, subtraction, multiplication, division,
+or modulus (C<vector [ + - * / % ] N>) and return a new C<Vec4> vector
+C<result>. No attempt is made in C<div_num> and C<mod_num> to prevent
+division by zero, XXX - SO WHAT HAPPENS?
+
+=cut
+
+.vec4_num_vec4_binop(add_num, +)
+
+.vec4_num_vec4_binop(sub_num, -)
+
+.vec4_num_vec4_binop(mul_num, *)
+
+.vec4_num_vec4_binop(div_num, /)
+
+.vec4_num_vec4_binop(mod_num, %)
+
+
+=back
+
+
+=head3 Other Operations
+
+=over 4
+
+=item Vec4 cp = vec1.cross(Vec4 vec2)
+
+Calculate the cross product C<vec1 cross vec2> (using only the first three
+elements of each vector), and return the result as a new C<Vec4> whose
+first three elements are the cross product and whose last element is 1.0.
+
+=cut
+
+.sub cross :method
+ .vec3_extract_self_plus_vec_arg
+
+ $N0 = $N11 * $N22
+ $N1 = $N21 * $N12
+ $N30 = $N0 - $N1
+
+ $N2 = $N20 * $N12
+ $N3 = $N10 * $N22
+ $N31 = $N2 - $N3
+
+ $N4 = $N10 * $N21
+ $N5 = $N20 * $N11
+ $N32 = $N4 - $N5
+
+ .vec4_return_new_result_with_w(1.0)
+.end
+
+
+=item num dp = vec1.dot(Vec4 vec2)
+
+Calculate the dot product C<vec1 dot vec2> and return the result as a num.
+
+=cut
+
+.sub dot :method
+ .vec4_extract_self_plus_vec_arg
+
+ $N30 = $N10 * $N20
+ $N31 = $N11 * $N21
+ $N32 = $N12 * $N22
+ $N33 = $N13 * $N23
+
+ .local num result
+ result = $N30 + $N31
+ result += $N32
+ result += $N33
+
+ .return(result)
+.end
+
+
+=item num dp3 = vec1.dot3(Vec4 vec2)
+
+Calculate the dot product C<vec1 dot vec2>, considering only the first
+three elements of each vector, and return the result as a num.
+
+=cut
+
+.sub dot3 :method
+ .vec3_extract_self_plus_vec_arg
+
+ $N30 = $N10 * $N20
+ $N31 = $N11 * $N21
+ $N32 = $N12 * $N22
+
+ .local num result
+ result = $N30 + $N31
+ result += $N32
+
+ .return(result)
+.end
+
+
+=item num len = vector.length()
+
+Calculate the length of C<vector> as C<sqrt(vector dot vector)>, and return
+the result as a num.
+
+=cut
+
+.sub length :method
+ $N0 = self.'dot'(self)
+ $N1 = sqrt $N0
+
+ .return($N1)
+.end
+
+
+=item num len3 = vector.length3()
+
+Calculate the length of C<vector> as C<sqrt(vector dot3 vector)> (thus
+considering only the first three elements), and return the result as a num.
+
+=cut
+
+.sub length3 :method
+ $N0 = self.'dot3'(self)
+ $N1 = sqrt $N0
+
+ .return($N1)
+.end
+
+
+=item Vec4 result = vector.normalize()
+
+Calculate a normalized version of C<vector> as C<vector / length(vector)>,
+returning the result as a new C<Vec4>.
+
+=cut
+
+.sub normalize :method
+ $N0 = self.'length'()
+ $P0 = self.'div_num'($N0)
+
+ .return($P0)
+.end
+
+=item num dist = vec1.distance(vec2)
+
+Treat two vectors C<vec1> and C<vec2> as points and determine the distance
+between them as C<length(vec1 - vec2)>, returning the result as a num.
+
+=cut
+
+.sub distance :method
+ .param pmc vec2
+
+ $P0 = self.'sub'(vec2)
+ $N0 = $P0.'length'()
+
+ .return($N0)
+.end
+
+
+=item num dist3 = vec1.distance3(vec2)
+
+Treat two vectors C<vec1> and C<vec2> as points and determine the distance
+between them as C<length3(vec1 - vec2)> (thus considering only the first
+three elements), and returning the result as a num.
+
+=cut
+
+.sub distance3 :method
+ .param pmc vec2
+
+ $P0 = self.'sub'(vec2)
+ $N0 = $P0.'length3'()
+
+ .return($N0)
+.end
+
+=back
+
+
+
+=head3 Miscellaneous Methods
+
+=over 4
+
+=item __dump(pmc dumper, str label)
+
+Callback function for Parrot's C<Data::Dumper> clone.
+
+=cut
+
+.sub __dump :method
+ .param pmc dumper
+ .param string label
+
+ $P0 = getattribute self, 'vals'
+
+ print '[ '
+ $I0 = 0
+ dump_loop:
+ $S0 = $P0[$I0]
+ print $S0
+ inc $I0
+ if $I0 >= 4 goto dump_loop_end
+ print ', '
+ goto dump_loop
+ dump_loop_end:
+ print ' ]'
+.end
+
+=back
+
+
+=head1 ROADMAP
+
+Over time, the API provided by this module will grow to incorporate
+related low-level operations, such as quaternion ops. However, it will
+B<not> include high level components such as particle systems and physics
+simulations. These are properly the domain of other modules that use
+this one, or NCI wrappers for libraries such as ODE (L<http://www.ode.org/>)
+and Bullet (L<http://www.bulletphysics.com/wordpress/>).
+
+In order to allow the greatest audience of users, this module will track
+the evolving experimental API for HLL access to PIR modules.
+
+=cut
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
Modified: branches/pmc_pct/runtime/parrot/library/P6object.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/library/P6object.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/library/P6object.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -453,7 +453,7 @@
setattribute how, 'parrotclass', parrotclass
## create an anonymous class for the protoobject
- .local pmc protoclass, protoobject, iter
+ .local pmc protoclass, protoobject
protoclass = new 'Class'
$P0 = get_class 'P6protoobject'
## P6protoobject methods override parrotclass methods...
Modified: branches/pmc_pct/runtime/parrot/library/PGE/Util.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/library/PGE/Util.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/library/PGE/Util.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -160,7 +160,7 @@
have_pos:
# count newlines to the current position of the parse
- .local int pos, npos, lines
+ .local int npos, lines
.local string target
$P99 = getattribute match, '$.target'
target = $P99
Modified: branches/pmc_pct/runtime/parrot/library/Range.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/library/Range.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/library/Range.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -16,9 +16,9 @@
=cut
.macro exhausted_check()
- .local pmc exhausted
- exhausted = getattribute self, 'exhausted'
- unless exhausted goto .$more
+ .local pmc exhausted_check
+ exhausted_check = getattribute self, 'exhausted'
+ unless exhausted_check goto .$more
.local pmc exception
exception = new 'Exception'
exception[0] = 'Exhausted Range'
@@ -155,7 +155,7 @@
.sub 'shift' :vtable('shift_pmc') :method
.exhausted_check()
- .local pmc exhausted, from, to, by
+ .local pmc from, to, by
from = getattribute self, 'from'
to = getattribute self, 'to'
by = getattribute self, 'by'
Modified: branches/pmc_pct/runtime/parrot/library/Test/Builder/Output.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/library/Test/Builder/Output.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/library/Test/Builder/Output.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -138,7 +138,6 @@
i = 0
.local string first_char
- .local string line
LOOP:
if i == 0 goto LINE_OK
Modified: branches/pmc_pct/runtime/parrot/library/Test/More.pir
==============================================================================
--- branches/pmc_pct/runtime/parrot/library/Test/More.pir Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/runtime/parrot/library/Test/More.pir Fri Jun 26 08:35:24 2009 (r39797)
@@ -468,8 +468,7 @@
structure. It passes if they are equal and fails otherwise. This will
report the results with the optional test description in C<description>.
-This only handles comparisons of array-like structures. It shouldn't be too
-hard to extend it for hash-like structures, too.
+This handles comparisons of array-like and hash-like structures.
=cut
@@ -640,27 +639,22 @@
compare_contents:
.local pmc l_iter
- .local pmc r_iter
.local int count
l_iter = new 'Iterator', l_hash
- r_iter = new 'Iterator', r_hash
l_iter = 0
- r_iter = 0
count = 0
- .local pmc l_key
- .local pmc r_key
+ .local pmc key
.local pmc l_elem
.local pmc r_elem
.local int elems_equal
iter_start:
unless l_iter goto iter_end
- l_key = shift l_iter
- r_key = shift r_iter
- l_elem = l_hash[ l_key ]
- r_elem = r_hash[ r_key ]
+ key = shift l_iter
+ l_elem = l_hash[ key ]
+ r_elem = r_hash[ key ]
elems_equal = compare_elements( l_elem, r_elem, position )
unless elems_equal goto elems_not_equal
@@ -669,7 +663,7 @@
goto iter_start
elems_not_equal:
- unshift position, l_key
+ unshift position, key
.return( 0 )
iter_end:
Modified: branches/pmc_pct/src/debug.c
==============================================================================
--- branches/pmc_pct/src/debug.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/debug.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -3344,8 +3344,12 @@
PDB_info(PARROT_INTERP)
{
ASSERT_ARGS(PDB_info)
- Parrot_Interp itdeb = interp->pdb->debugger;
- Parrot_Interp itp = interp->pdb->debugee;
+
+ /* If a debugger is created, use it for printing and use the
+ * data in his debugee. Otherwise, use current interpreter
+ * for both */
+ Parrot_Interp itdeb = interp->pdb ? interp->pdb->debugger : interp;
+ Parrot_Interp itp = interp->pdb ? interp->pdb->debugee : interp;
Parrot_io_eprintf(itdeb, "Total memory allocated = %ld\n",
interpinfo(itp, TOTAL_MEM_ALLOC));
Modified: branches/pmc_pct/src/gc/alloc_memory.c
==============================================================================
--- branches/pmc_pct/src/gc/alloc_memory.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/gc/alloc_memory.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -343,6 +343,32 @@
/*
+=item C<char * mem_sys_strdup(const char *src)>
+
+Copy a C string to a new block of memory allocated with mem_sys_allocate,
+that can be later deallocated with mem_sys_free.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+PARROT_MALLOC
+PARROT_CANNOT_RETURN_NULL
+char *
+mem_sys_strdup(ARGIN(const char *src))
+{
+ ASSERT_ARGS(mem_sys_strdup)
+
+ size_t l = strlen(src);
+ char *result = (char *)mem_sys_allocate(l + 1);
+ memcpy(result, src, l);
+ result[l] = '\0';
+ return result;
+}
+
+/*
+
=back
=cut
Modified: branches/pmc_pct/src/gc/api.c
==============================================================================
--- branches/pmc_pct/src/gc/api.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/gc/api.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -325,7 +325,8 @@
{
ASSERT_ARGS(Parrot_gc_add_pmc_ext)
Small_Object_Pool * const pool = interp->arena_base->pmc_ext_pool;
- pmc->pmc_ext = (PMC_EXT *)pool->get_free_object(interp, pool);
+ if (!pmc->pmc_ext)
+ pmc->pmc_ext = (PMC_EXT *)pool->get_free_object(interp, pool);
if (!pmc->pmc_ext)
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_ALLOCATION_ERROR,
"Parrot VM: PMC_EXT allocation failed!\n");
@@ -362,17 +363,16 @@
Arenas * const arena_base = interp->arena_base;
Small_Object_Pool * const ext_pool = arena_base->pmc_ext_pool;
+ if (!p->pmc_ext)
+ return;
+
if (PObj_is_PMC_shared_TEST(p) && PMC_sync(p)) {
MUTEX_DESTROY(PMC_sync(p)->pmc_lock);
mem_internal_free(PMC_sync(p));
PMC_sync(p) = NULL;
}
-
- if (p->pmc_ext) {
- ext_pool->add_free_object(interp, ext_pool, p->pmc_ext);
- ext_pool->num_free_objects++;
- }
-
+ ext_pool->add_free_object(interp, ext_pool, p->pmc_ext);
+ ext_pool->num_free_objects++;
p->pmc_ext = NULL;
}
@@ -394,6 +394,9 @@
ASSERT_ARGS(Parrot_gc_add_pmc_sync)
if (!PObj_is_PMC_EXT_TEST(pmc))
Parrot_gc_add_pmc_ext(interp, pmc);
+ if (PMC_sync(pmc))
+ /* This mutex already exists, leave it alone. */
+ return;
PMC_sync(pmc) = mem_allocate_typed(Sync);
if (!PMC_sync(pmc))
Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_ALLOCATION_ERROR,
Modified: branches/pmc_pct/src/gc/gc_ms.c
==============================================================================
--- branches/pmc_pct/src/gc/gc_ms.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/gc/gc_ms.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -369,18 +369,15 @@
pool->skip = 0;
else {
Small_Object_Arena * const arena = pool->last_Arena;
- if (arena) {
- if (arena->used == arena->total_objects)
+ if (arena
+ && arena->used == arena->total_objects)
Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG);
-
- if (pool->num_free_objects > pool->replenish_level)
- pool->skip = 1;
- }
}
/* requires that num_free_objects be updated in Parrot_gc_mark_and_sweep.
If gc is disabled, then we must check the free list directly. */
- if (!pool->free_list)
+ if (!pool->free_list
+ || pool->num_free_objects < pool->replenish_level)
(*pool->alloc_objects) (interp, pool);
}
Modified: branches/pmc_pct/src/hash.c
==============================================================================
--- branches/pmc_pct/src/hash.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/hash.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -720,6 +720,7 @@
HashBucket *bs, *b;
void * const old_mem = hash->bs;
+ HashBucket *old_offset = (HashBucket*)((char*)hash + sizeof (Hash));
const UINTVAL old_size = hash->mask + 1;
const UINTVAL new_size = old_size << 1;
const UINTVAL old_nb = N_BUCKETS(old_size);
@@ -737,8 +738,16 @@
*/
/* resize mem */
- HashBucket * const new_mem =
- (HashBucket *)mem_sys_realloc(old_mem, HASH_ALLOC_SIZE(new_size));
+ HashBucket *new_mem;
+ if (old_offset != old_mem) {
+ /* This buffer has been reallocated at least once before. */
+ new_mem = (HashBucket *)mem_sys_realloc(old_mem, HASH_ALLOC_SIZE(new_size));
+ }
+ else {
+ /* Allocate a new buffer. */
+ new_mem = (HashBucket *)mem_sys_allocate(HASH_ALLOC_SIZE(new_size));
+ memcpy(new_mem, old_mem, HASH_ALLOC_SIZE(old_size));
+ }
/*
+---+---+---+---+---+---+-+-+-+-+-+-+-+-+
@@ -954,7 +963,8 @@
{
ASSERT_ARGS(parrot_create_hash)
HashBucket *bp;
- Hash * const hash = mem_allocate_typed(Hash);
+ void *alloc = mem_sys_allocate(sizeof (Hash) + HASH_ALLOC_SIZE(INITIAL_BUCKETS));
+ Hash * const hash = (Hash*)alloc;
size_t i;
PARROT_ASSERT(INITIAL_BUCKETS % 4 == 0);
@@ -974,7 +984,7 @@
* - use the bucket store and bi inside this structure
* - when reallocate copy this part
*/
- bp = (HashBucket *)mem_sys_allocate(HASH_ALLOC_SIZE(INITIAL_BUCKETS));
+ bp = (HashBucket *)((char*)alloc + sizeof (Hash));
hash->free_list = NULL;
/* fill free_list from hi addresses so that we can use
@@ -1015,7 +1025,9 @@
parrot_hash_destroy(SHIM_INTERP, ARGMOD(Hash *hash))
{
ASSERT_ARGS(parrot_hash_destroy)
- mem_sys_free(hash->bs);
+ HashBucket *bp = (HashBucket*)((char*)hash + sizeof (Hash));
+ if (bp != hash->bs)
+ mem_sys_free(hash->bs);
mem_sys_free(hash);
}
Modified: branches/pmc_pct/src/interp/inter_create.c
==============================================================================
--- branches/pmc_pct/src/interp/inter_create.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/interp/inter_create.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -466,6 +466,7 @@
interp->thread_data = NULL;
}
+ parrot_free_vtables(interp);
mem_sys_free(interp);
}
}
Modified: branches/pmc_pct/src/io/unix.c
==============================================================================
--- branches/pmc_pct/src/io/unix.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/io/unix.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -551,7 +551,7 @@
size_t to_write = s->bufused;
size_t written = 0;
- write_through:
+ write_through:
while (to_write > 0) {
const int err = write(file_descriptor, ptr, to_write);
if (err >= 0) {
Modified: branches/pmc_pct/src/jit/i386/jit_defs.c
==============================================================================
--- branches/pmc_pct/src/jit/i386/jit_defs.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/jit/i386/jit_defs.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -2277,13 +2277,13 @@
case 'b': /* buffer (void*) pass PObj_bufstart(SReg) */
emitm_call_cfunc(pc, get_nci_S);
emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1,
- (size_t) &PObj_bufstart((STRING *) 0));
+ (size_t) &PObj_bufstart((STRING *) NULL));
emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
break;
case 'B': /* buffer (void**) pass &PObj_bufstart(SReg) */
emitm_call_cfunc(pc, get_nci_S);
emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1,
- (size_t) &PObj_bufstart((STRING *) 0));
+ (size_t) &PObj_bufstart((STRING *) NULL));
emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
break;
case 'S':
Modified: branches/pmc_pct/src/key.c
==============================================================================
--- branches/pmc_pct/src/key.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/key.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -440,13 +440,11 @@
*/
PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
+PARROT_CAN_RETURN_NULL
STRING *
key_string(PARROT_INTERP, ARGIN(PMC *key))
{
ASSERT_ARGS(key_string)
- INTVAL int_key;
- FLOATVAL num_key;
switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
/* remember to COW strings instead of returning them directly */
@@ -460,6 +458,7 @@
}
case KEY_string_FLAG | KEY_register_FLAG:
{
+ INTVAL int_key;
STRING *s;
GETATTR_Key_int_key(interp, key, int_key);
s = REG_STR(interp, int_key);
@@ -469,25 +468,36 @@
}
case KEY_pmc_FLAG | KEY_register_FLAG:
{
+ INTVAL int_key;
PMC *reg;
GETATTR_Key_int_key(interp, key, int_key);
reg = REG_PMC(interp, int_key);
return VTABLE_get_string(interp, reg);
}
case KEY_integer_FLAG:
+ {
+ INTVAL int_key;
GETATTR_Key_int_key(interp, key, int_key);
return Parrot_str_from_int(interp, int_key);
+ }
case KEY_integer_FLAG | KEY_register_FLAG:
+ {
+ INTVAL int_key;
GETATTR_Key_int_key(interp, key, int_key);
return Parrot_str_from_int(interp, REG_INT(interp, int_key));
-
+ }
case KEY_number_FLAG:
+ {
+ FLOATVAL num_key;
GETATTR_Key_num_key(interp, key, num_key);
return Parrot_str_from_num(interp, num_key);
+ }
case KEY_number_FLAG | KEY_register_FLAG:
+ {
+ INTVAL int_key;
GETATTR_Key_int_key(interp, key, int_key);
return Parrot_str_from_num(interp, REG_NUM(interp, int_key));
-
+ }
default:
case KEY_pmc_FLAG:
return VTABLE_get_string(interp, key);
@@ -607,11 +617,13 @@
{
ASSERT_ARGS(key_mark)
const UINTVAL flags = PObj_get_FLAGS(key) & KEY_type_FLAGS;
- PMC *next_key;
- STRING *str_key;
if (flags == KEY_string_FLAG) {
+ STRING *str_key;
GETATTR_Key_str_key(interp, key, str_key);
+
+ /* XXX str_key can be NULL from GETATTR_Key_str_key, */
+ /* so shouldn't be marked. */
Parrot_gc_mark_PObj_alive(interp, (PObj *)str_key);
}
@@ -620,13 +632,13 @@
* the bucket_index and not the next key component
* Note to self: shoot whoever thought this was a good idea.
*/
- if (flags == KEY_hash_iterator_FLAGS)
- return;
-
- /* if iteration hasn't started, above flag isn't set yet */
- GETATTR_Key_next_key(interp, key, next_key);
- if (next_key && (void *)next_key != (void *)INITBucketIndex)
- Parrot_gc_mark_PObj_alive(interp, (PObj *)next_key);
+ if (flags != KEY_hash_iterator_FLAGS) {
+ PMC *next_key;
+ /* if iteration hasn't started, above flag isn't set yet */
+ GETATTR_Key_next_key(interp, key, next_key);
+ if (next_key && (void *)next_key != (void *)INITBucketIndex)
+ Parrot_gc_mark_PObj_alive(interp, (PObj *)next_key);
+ }
}
@@ -657,7 +669,7 @@
INTVAL int_key;
STRING *str_key;
- for (;key;) {
+ while (key != NULL) {
switch (PObj_get_FLAGS(key) & KEY_type_FLAGS) {
case KEY_integer_FLAG:
GETATTR_Key_int_key(interp, key, int_key);
Modified: branches/pmc_pct/src/library.c
==============================================================================
--- branches/pmc_pct/src/library.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/library.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -788,7 +788,7 @@
char * const env = Parrot_getenv("PARROT_RUNTIME", &free_it);
if (env)
- return free_it ? env : str_dup(env);
+ return free_it ? env : mem_sys_strdup(env);
else {
PMC * const config_hash =
VTABLE_get_pmc_keyed_int(interp, interp->iglobals, (INTVAL) IGLOBALS_CONFIG_HASH);
@@ -799,7 +799,7 @@
return Parrot_str_to_cstring(interp, s);
}
else
- return str_dup(".");
+ return mem_sys_strdup(".");
}
}
Modified: branches/pmc_pct/src/main.c
==============================================================================
--- branches/pmc_pct/src/main.c Fri Jun 26 05:10:43 2009 (r39796)
+++ branches/pmc_pct/src/main.c Fri Jun 26 08:35:24 2009 (r39797)
@@ -19,7 +19,6 @@
*/
#include <s