NAME
build_tools/pmc2c.pl - PMC compiler (Version 2)
SYNOPSIS
Create classes/foo.dump:
% perl build_tools/pmc2c.pl --dump classes/foo.pmc ...
Create vtable.dump:
% perl build_tools/pmc2c.pl --vtable
Print a class tree for the specified PMCs:
% perl build_tools/pmc2c.pl --tree classes/*.pmc
Create classes/foo.c and pmc_foo.h
from classes/foo.dump:
% perl build_tools/pmc2c.pl -c classes/foo.pmc ...
Create fooX.c and pmc_fooX.h from fooX.dump files, also create libfoo.c containing the initialization function for all fooX PMCs.
% perl build_tools/pmc2c.pl --library libfoo -c \
classes/foo1.pmc classes/foo2.pmc ...
DESCRIPTION
The job of the PMC compiler is to take .pmc files and create C files which can be compiled for use with the Parrot interpreter.
Command-line Options
--debug
-
Increase debug level
--verbose
-
Increase verbose level
--no-lines
-
Omit source line info
--no-body
-
Emit an empty body in the dump. This may be useful for debugging.
--include=/path/to/pmc
-
Specify include path where to find PMCs.
--library=libname
-
Specifiy the library name. This will create <libname>.c and pmc_<libname>.h. The initialization function will be named after libname and will initialize all PMCs in the library.
Internals
To see the internal data structures please run:
% perl build_tools/pmc2c.pl --c --deb --deb sarray.pmc | less
Compiling PMCs
First, the program determines the names of the .c and .h files from the basename of the .pmc file (e.g. perlint.pmc -> perlint.c and perlint.h).
Next, the file is searched for /pmclass \w*/ which attempts to find the class being declared.
Once the class is found, all of its superclasses are scanned and their methods added to the methods of the current PMC. PMCs default to inheriting from 'default'. Only single inheritance is supported.
Once the superclass is determined, it is processed and its method names are extracted and saved.
Next, each method body is processed with various directives (see below) getting replaced by their appropriate values.
Finally, the .c and .h files are generated. The appropriate base class header files are included.
If the noinit
flag was used, then no init function is generated. Otherwise, one is generated which sets up the vtable and enters it into the Parrot_base_vtables
array.
The .c file is generated by appending the functions after the various directives have been replaced.
PMC File Syntax
The basic syntax of a PMC file is
A preamble, consisting of code to be copied directly to the .c file
The
pmclass
declaration:pmclass PMCNAME [flags] {
where
flags
are:extends PMCPARENT
-
All methods not defined in PMCNAME are inherited from the PMCPARENT class. If no parent class is defined, methods from default.pmc are used.
abstract
-
This class cannot be instantiated. Abstract classes are shown with lower case class names in the class tree.
noinit
-
Used with
abstract
: Noclass_init
code is generated. const_too
-
Classes with this flag get 2 vtables and 2 enums, one pair with read/write set methods, and one with read-only set methods.
need_ext
-
The class needs a
PMC_EXT
structure. For instance, any class usingPMC_data
will haveneed_ext
. does interface
-
The class 'does' the given interfaces (the collection of methods which the class implements).
The default is "scalar". Other currently used interfaces are:
array : container PMC with numerically-keyed elements event : PMC that can be used with event queue hash : container PMC with string-keyed elements library : PMC that corresponds to a dynamic library ref : PMC that references another PMC scalar : (only used by the sample dynclasses/foo.pmc)
This is not a canonical list, but merely a snapshot of what's in use.
dynpmc
-
The class is a dynamic class. These have a special
class_init
routine suitable for dynamic loading at runtime. See the dynclasses directory for an example. group GROUP
-
The class is part of a group of interrelated PMCs that should be compiled together into a single shared library of the given name. Only valid for dynamic PMCs.
lib LIB
-
The class needs an external library.
A list of vtable method implementations
The final close
}
Method Body Substitutions
The vtable method bodies can use the following substitutions:
SELF
-
Converted to the current PMC object of type
PMC *
. INTERP
-
Converted to the interpreter object.
OtherClass.SELF.method(a,b,c)
-
Calls the static vtable method 'method' in
OtherClass
. SELF.method(a,b,c)
-
Calls the vtable method 'method' using the static type of
SELF
(in other words, calls another method defined in the same file). DYNSELF.method(a,b,c)
-
Calls the vtable method 'method' using the dynamic type of
SELF
. DYNSELF(a,b,c)
-
Same as above, but calls the current method.
OtherClass.SUPER(a,b,c)
-
Calls the overridden implementation of the current method in
OtherClass
. SUPER(a,b,c)
-
Calls the overridden implementation of the current method in the nearest superclass, using the static type of
SELF
. DYNSUPER(a,b,c)
-
As above, but uses the actual dynamic type of
SELF
.
AUTHOR
Leopold Toetsch.
Cleaned up by Matt Diephouse.
Many thanks to the author of pmc2c.pl, many useful code pieces got reused.