parrotcode: PMC compiler (Old Version) | |
Contents | PMCs |
classes/pmc2c.pl - PMC compiler (Old Version)
This script has now been superceeded by classes/pmc2c2.pl.
% perl pmc2c.pl [--no-lines] [--tree] foo.pmc [foo2.pmc...]
% perl pmc2c.pl B<-f> method *.pmc
The first class.pmc should be the name of the class you wish to create. Normally, the pmc2c.pl translator uses #line
pragmas to tell the C compiler where each function in the .pmc file begins (line number). This allows the compiler to issue warnings and errors based on the .pmc file instead of on the .c file which should not be edited. However, there are times when this is not desirable and therefore the --no-lines
option is provided.
If --tree
is set, the inheritance tree of given classes is printed, no further processing is done. The common base class 'default' is not printed.
If -f is set, the pmcs are printed, where this method is implemented.
The pmc2c program's job is to take .pmc files and create .c files which can be compiled for use with the Parrot interpreter.
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.
The basic syntax of a PMC file is
pmclass
declaration: pmclass PMCNAME [extends PMCPARENT] [flags] {
where flags
are:
extends PMCPARENT
abstract
noinit
abstract
: No class_init
code is generated.dynpmc
class_init
routine suitable for dynamic loading at runtime. See the dynclasses directory for an example.const_too
need_ext
PMC_EXT
structure (its using e.g. PMC_data
).does interface
array
hash
}
The vtable method bodies can use the following substitutions:
SELF
PMC *
.INTERP
Otherclass.SELF.method(a,b,c)
OtherClass
.SELF.method(a,b,c)
SELF
(in other words, calls another method defined in the same file).DYNSELF.method(a,b,c)
SELF
.DYNSELF(a,b,c)
OtherClass.SUPER(a,b,c)
OtherClass
.SUPER(a,b,c)
SELF
.DYNSUPER(a,b,c)
SELF
.extract_balanced($code)
void f( int x ) {
if( x == 9 ) {
printf( "Hello!" );
}
else {
printf( "Goodbye!" );
}
}
q{ if( x == 9 ) {
printf( "Hello!" );
}
else {
printf( "Goodbye!" );
}
}
parse_superpmc($data)
superpmc_info($class)
parse_superpmc()
.scan_inheritance_tree($classname)
superpmc_info()
passing in the current class name. superpmc_info()
will return a tuple containing all of the defined methods (not default) in that class as well as the name of the superclass that was processed. This function stops when the default superclass is processed. It returns a hash that maps the method name to the most derived class it was defined in.count_newlines($string)
$string
.filter($contents, $file, $cfile)
filter()
function choreographs the previous functions actions on the pmcfile in question. It first scans the inheritance hierarchy to get all of the methods and their corresponding class of definition. Next, it skips over the extends clause and processes any flags (such as noinit
). Afterwards, it loops through each function declared and replaces directives with the appropriate values. Finally, it generates the .c and .h files for the .pmc file being analyzed.
|