Blog Closed

This blog has moved to Github. This page will not be updated and is not open for comments. Please go to the new site for updated content.

Thursday, July 2, 2009

Writing PMCs in NQP

So the question has arisen lately, what is L1 going to look like, and how hard is it going to be to write ops and PMCs in it? The answer is that we aren't going to be writing in L1 directly, we have PCT and will be writing it in a higher level language and compiling it down directly to Parrot bytecode. Here is an example of what the FixedPMCArray PMC type will look like rewritten in NQP:

class FixedPMCArray :need_ext :provides('array') {
has $.size as int;
has @.pmc_array as pmc;

vtable elements() as int {
return $this.size;
}

vtable destroy() {
if $this.pmc_array != null
Parrot::mem_sys_free($this.pmc_array);
}

vtable get_integer() as int {
return $this.elements();
}

vtable get_bool() as bool {
return $this.elements() != 0;
}

vtable get_integer_keyed_int($idx as int) as int {
my $intval as int = +( $this.pmc_array[$idx] );
return $intval;
}

vtable set_integer_keyed_int($idx as int, $val as pmc) {
if $this.elements < $idx
$this.set_integer_native($idx);
$this.pmc_array[$idx] = $val;
}

vtable get_string_keyed_int($idx as int) as str {
my $strval as str = ~( $this.pmc_array[$idx] );
return $strval;
}

vtable mark() {
for(my $i = 0; $i < $this.size; $i++) {
my $pmc = $this.pmc_array[$i];
if !Parrot::PMC_IS_NULL($pmc)
Parrot::Parrot_gc_mark_PObj_alive($INTERP, $pmc);
}
}

vtable set_integer_native($size as int) {
if $this.size >= $size
return;

my $pmc_size = Parrot::sizeof_pmc_ptr();
my @new_pmc_array = Parrot::mem_sys_allocate($size * $pmc_size);
loop (my $i = 0; $i < $this.size; i++) {
@new_pmc_array[$i] = $this.pmc_array[$i];
}
$this.size = $size;
$this.pmc_array = new_pmc_array;
}
}


There are a few points to note here: First, I know this isn't perfect Perl 6 and I'm sure I screwed up some syntax here and there. I apologize for that, but I'm not really interested in going back line-by-line to fix it. This is just a thought experiment after all, and the important point isn't getting the syntax correct but instead proving the efficacy of this method. Second, I'm treating NQP here as just a particular syntax over very low-level semantics. The code has @.pmc_array as pmc is going to be equivalent to the C-ish code ATTR PMC** pmc_array. That is, we just assume that everywhere we see as pmc, that will become the equivalent C code PMC* and the @ sigil just adds another * to it.

One more thing worth noting is that I am assuming the management of the ATTR structure will be automated. The PMC compiler will recognize that this PMC type has attributes and will automatically allocate them on initialization and automatically deallocate them on destruction.

Since NQP is going to be compiled down into a very low-level bytecode that should be capably equivalent to C code, it is going to have direct access to C functions in libparrot. It will not be calling functions through NCI, it will be constructing machine-level call frames and executing functions directly. I show this using the syntax Parrot::FUNCNAME. The $INTERP contant is a reference to the current interpreter. This helps to differentiate functions which must be called with C semantics (pushing arguments onto the system stack) and those functions which can be called with L1 semantics instead (and I'm not entirely sure what those will look like anyway, but they won't be stack-based you can be sure of that). Instead of writing Parrot::, we could easily write C:: instead

So that's a quick look at what a basic core PMC could look like in NQP. If we all remember that in this particular case the NQP is going to be compiled down to low-level code and not into higher-level PIR/PASM, this all starts to make a lot more sense. Think of it like writing C but with slightly different syntax (and different underlying semantics), and without any of the high-level features that you would expect from Perl6.

2 comments:

  1. suggestions (for staying closer to Perl 6 syntax):

    "has $.size as int" is really "has int $.size"

    "vtable elements() as int" is really "method int elements() is vtable"

    Pm

    ReplyDelete
  2. I forgot to mention that I expect NQP to receive the "my int $foo", "my str $bar", etc. syntaxes in a relatively short period of time.

    Pm

    ReplyDelete

Note: Only a member of this blog may post a comment.