Day 183/184 (r6131): New PIL implementation begins!

autrijus on 2005-08-09T20:19:30

Gradually but surely, the neccessary pieces for the self-hosting Perl 6 implementation are falling into place from all five fronts:

Perl6
Perl5
JavaScript
Parrot
Haskell

The ultimate goal is, of course, to get all pieces implemented into the Perl6 slot. However, before that can happen, I would like to see a formal semantic of how Perl 6 operates, so I'm porting all pieces over to Haskell first, due to its strong intolerance of vagueness. This phase centers around the design of PIL2, the desugared version of Perl 6, the one data structure common to all components (except for the Parser).

Once we are reasonably sure that the parts work as specified, we can then port runtime parts (containers, intrinsic types, primitive functions) to various virtual machines out there. Perl 5 will be my primary target, but I'm sure other people will have their pet backends.

On the other hand, I see the compile-time parts (parser, compiler, grammars) ported directly to Perl 6, to the point that you can eval Perl 6 code in Perl 5 just by using a pure-perl5 module that happens to be the Perl 6 compiler compiled to Perl 5. The same applies to other backends, of course.

As for code generators (the thing that turns PIL into backend-specific code), most of them will be implemented natively at first, but it would also be cool to have one backend cross-compile to another, by porting codegens to Perl 6.

The situation with the object model is the reverse. I expect a common implemtation in pure Perl 6, using closure-based objects. That way, the runtime need only to implement the intrinsic types and primitive functions, then it can bootstrap the object system and the standard prelude. We can then incrementally port the model to native code to improve its performance.

Following this plan, tonight I implemented the first step toward the new Haskell runcore, targetting for Punie compatibility -- that is, able to parse and execute print 0, print 1 and so on to print 9, i.e. the ten programs Punie can currently handle. It did that, along with a pretty printer, an interactive REPL loop, and nested expressions such as say print 123.

More seriously, the new runcore represents a fertile ground to link container types, object metamodel, and a type checker together. Those three are deeply intertwined in Perl 6, and we can't release 6.28.0 without them working in harmony, preferably with a cheap and cheerful inferencing engine.

To that end, PIL makes all types explicit in its compiled form, so the code generator can choose the most efficient way to emit target code. Even Scalar of Int ($x) and Int (3) are distinguished with explicit casting between them (i.e. store and fetch), so we can make obvious optimizations in strides.

In other news, iblech implemented continuation-passing style in JavaScript, paving the way to support more advanced control flows (coro, call/cc) in the JS runtime. Amazing stuff.

Finally, below is some not-yet-working Perl 6 code to implement generic coercion, making use of parametric roles, dependent types, and arrow types. Enjoy!

role Coerce[::to] {
    method coerce (--> ::to) { ... }
}

multi *coerce: ((
    Coerceable[T] $from
    : Type ::T
) --> T) { $from.coerce }


Yay, way to go

nicholas on 2005-08-09T21:00:22

I continue to be amazed by what you conspire to create, and just how much you continue to achieve.

print 0, print 1 and so on to print 9, i.e. the ten programs Punie can currently handle.

And string constants are coming soon, so that print "1..0\n" would be a valid punie program? Followed by the more advanced print "1..1\nok 1\n" ?

Re:Yay, way to go

autrijus on 2005-08-10T05:09:50

Thank-you for your kind words. :-)

String constants are indeed coming soon to Pugs's new runcore, but I don't know about Punie... You'd have to ask its maintainer. :)