While I didn't implement everything I thought I would, there is now a basic framework for bytecode generation in the nqp_pct branch. I'm uncertain if it should be merged... While the bytecode generation doesn't fully work, it doesn't interfere with the existing usage of PCT and does have the nice feature that PAST::Compiler is now written in NQP for ease of hacking. I'll leave that up to the rest of the community to decide. The rest of this blog post is the contents of docs/pct/bytecode.pod
, which I hope will be helpful if anyone want to explore what I've been working on all summer.
NAME
Compiling to Bytecode with the Parrot Compiler Tools
DESCRIPTION
This document describes the steps needed to use the Parrot Compiler Tools
(PCT) to directly generate bytecode files (.pbc). This feature is both
experimental and incomplete, but assistance from experienced language
authors is requested to help find the limitations.
GETTING STARTED
If you have created a high-level language with PCT via
mk_language_shell.pl
or by hand, then you're most of the way towards
using this new feature. It requires no changes to the grammar or actions,
as all the changes to the process occur after you hand off a PAST tree to
the library.
To generate bytecode directly, you need to alter the stages that your
compiler runs. Generally this is found in src/HLLName/Compiler.pm
(in
this, and all further examples, replace HLLName
with the name of
your language (i.e. src/Squaak/Compiler.pm
). This file contains
all the configuration for your compiler inside an INIT
block. To change
from the default compilation chain to the new chain, add the following
line:
HLLName::Compiler.stages(<parse past newpost pbc>);
This assumes that your language is written in NQP, as generated by
mk_language_shell.pl
. If you have replaced this file with another
language or created your compiler by hand, you need to do the equivalent of
the following PIR:
$P0 = get_hll_global ['HLLName'], 'Compiler' # Get compiler object $P1 = split ' ', 'parse past newpost pbc' $P0.'stages'($P1)
NEW STAGES
The above code replaces the post, pir, and evalpmc stages with two new
ones described below:
- newpost
Uses
PAST::NewCompiler
to convert the PAST tree from your actions into a
"newPOST" tree. newPOST contains additional information required to
generate bytecode and is not supposed to contain any raw PIR source. - pbc
Uses
POST::PBCCompiler
to create a Packfile from the PAST tree. This
returns the main method from the source for execution by the compiler.
Using--output file.pbc
will allow you to save the generated packfile to
a file.
KNOWN ISSUES
newPOST is known to only compile fairly simple PAST trees at the moment.
As more specific issues are found, they should be added to this list, and
as features are implemented, they should be removed.
- Exceptions
Null PMC access in find_method('new')
inPAST::Compiler.try
- Inline PIR
Because PIR is not generated when using these stages, inline PIR can not be
used. To add this, a more fine-grained PIR parser would need to be addthat
outputs newPOST trees.
UNKNOWN ISSUES
If attempting to compile your program, you encounter an error message and
the backtrace includes parrot;POST;PBCCompiler
, then likely you have
attempted to use something not yet implemented. Here are a few of the
common errors:
- Method 'type' not found for invocant of class 'String'
This likely means that some portion of PIR text made its way into
POST::PBCCompiler
. An additional override inPAST::NewCompiler
will
probably be needed to replace/alter the generated POST tree.