Day 165 (r5671): jspugs.pl and PIL redesign.

autrijus on 2005-07-18T17:37:16

Following eric256's suggestion, I'm adding the current revision number as part of the journal title. He also would like to reply to my journal with code examples and pick up things I missed; I think that's a great idea, and all lambdacamel are welcome to join the fun. :-)

Today iblech introduced a jspugs.pl, a nice shell for Perl6/JS development. Here is a screenshot:

% cd perl5/PIL2JS/
Welcome to JSPugs -- Perl6 User's Golfing System
Type :h for help.

* Path to pugs:                           ../../pugs           [OK]
* Path to pil2js:                         ./pil2js.pl          [OK]
* Path to the precompiled Prelude:        preludepc.js         [NOT FOUND]
* Path to PIL2JS's lib6/:                 lib6                 [OK]
* Path to the JavaScript output:          output.html          [OK]

jspugs> :h
Commands available from the prompt:
:h                      = show this help message
:q                      = quit
:conf thing [new_value] = set the path to thing
                          (pugs|pil2js|preludepc|lib6|output)
:precomp                = precompile the Prelude
:pil               = show PIL of expression
:pil.yaml          = show PIL of expression dumped as YAML
                   = compile expression and save as HTML
:js                = compile expression and show it
:l filename.p6          = compile file and save as HTML

jspugs> :precomp
# ../../pugs -Ilib6 -CPIL -MPrelude::JS -e ''
# ./pil2js.pl --no-jsprelude > preludepc.js
* Path to the precompiled Prelude:        preludepc.js         [OK]

jspugs> say "Hello, JSPugs!"
# ../../pugs -Ilib6 -CPIL -e say "Hello, JSPugs!"
# ./pil2js.pl --html --preludepc preludepc.js > output.html
* Path to the JavaScript output:          output.html          [OK]

Neat, no? The output.html contains a link to <script type="text/javascript" src="preludepc.js"></script>. Because the Javascript prelude is shared, code generation is quite fast now. Errors in the code generator are annotated with line/column info, thanks to the source ranges information preserved in PIL.

There is no JSAN support yet, but I suspect that one day we may compile use jsan:Form::Validator; and unite with the rhinocamel world.

In order to get tests passing and mandel.p6 to run, iblech fixed many corner cases in Pugs.Compile, including invocant handling, delayed evaluation and prettyprinting, with helpful feedback from Arathorn and other #perl6 people. Already there is talks about generating SWF/ActionScript and PDF/ECMAScript in addition to HTML output...

iblech also added YAML serialization for PIL structures. It is purely positional and not as concise as I'd like, so I talked with him and putter about how the redesigned PIL should be serialized. The consensus seems to favor a YAML-style model, with all nodes carrying a type, and with a payload of a scalar, a list of nodes, or a hash of named subnodes. For example, pugs -P YAML example.p6 would dump the PIL structure of example.p6 as YAML nodes.

On the MetaModel front, Stevan implemented the C3 Method Resolution Order for multiple-inherited objects. I like C3 a lot, and I agree with Stevan that it should be made into the default Perl 6 method dispatch order. The core idea is that, in a diamond inheritance tree:

              class A;
class B is A;        class C is A;
class BB is B;       class CC is C;
        class Z is BB is CC;
The call to Z.new.method should look up in the order of Z, BB, B, CC, C, A, instead of (as in Perl 5) Z, BB, B, A, CC, C; the latter dispatches to A happend before its subclass C -- this is part of the reason I considered multiple inheritance as insane. C3 restores much sanity here.

mugwump added a trivial implementation of &is_deeply in Test.pm by simply compare their .perl serializations. Clever.

Aankhen fixed &uri_escape in URI::Escape, and reported that printf did not handle upper-case variants of format codes, such as %X. putter fixed that promptly in Prelude.pm.

fglock refactored the infinite recurrence set structure from Span::Code into Recurrence.pm.

putter added Pugs::Internals::rule_pattern to extract the rule string out from an rule object, for his plan of writing a Rule parser in Perl 6. He worked some more on the Perl 6 Rules Grammar, but sadly PGE can't handle it yet.

Zero commits from me today to Pugs, as I'm still in paper-reading and discussion mode. I'm also picking up more $work for post-sabbatical livelihood, until I can find some sort of sponsorship for Pugs; in any case, I will try to keep about 3 days a week for Pugs. No promises, though -- as usual, all I can promise is a committer bit. :-)


Small Example.

eric256 on 2005-07-18T18:13:33

Most commits this time around were related to javascript ouput but burried in the commit log was a little addition to .as() For those who haven't noticed perl 6 now lets you format strings with a .as method that takes the same arguments as sprintf. A recent commit extends this to include a few more options.

use v6;

# ------------------------------------------------------------------------ # r5666 | putter | 2005-07-18 09:49:34 -0600 (Mon, 18 Jul 2005) | 1 line # sprintf now handles X D U O E G F specifiers without crashing. Aankhen++.

my $x = "500"; $x.as("%X").say;


I'm hoping to provide examples both to teach myself more pugs and provide a more hands on approach to following developments. I love the journal, but an example here or there is nice.

Re:Small Example.

autrijus on 2005-07-19T04:11:30

Please use <ecode> instead of <code> tags for verbatim code blocks... Here is your post, reformatted. :)

Most commits this time around were related to javascript ouput but burried in the commit log was a little addition to .as() For those who haven't noticed perl 6 now lets you format strings with the .as method that takes the same arguments as sprintf. A recent commit extends this to include a few more options.

use v6;

# ------------------------------------------------------------------------
# r5666 | putter | 2005-07-18 09:49:34 -0600 (Mon, 18 Jul 2005) | 1 line
# sprintf now handles X D U O E G F specifiers without crashing.  Aankhen++.

my $x = "500";
$x.as("%X").say;
I'm hoping to provide examples both to teach myself more pugs and provide a more hands on approach to following developments. I love the journal, but an example here or there is nice.

PIL2JS runs mandel.p6!

iblech on 2005-07-18T19:10:09

PIL2JS is able to compile mandel.p6 to valid JavaScript now, and it actually runs! :)

http://m19s28.vlinux.de/iblech/stuff/not_perm/pil2js-demo/mandel.p6.html

(I've only tested it with Firefox 1.0.5, though. And beware, the script might take 100% CPU, crash your browser, etc, but it does work! :))

Re:PIL2JS runs mandel.p6!

iblech on 2005-07-18T19:29:30

FYI, Arathorn just informed us that it works with Opera, too :)

C3 method resolution order

leo on 2005-07-18T21:06:02

This should exactly match my implementation on the Parrot side. There is just one test showing init order (which is reverse MRO). Please grep for "constructor - diamond parents" in t/pmc/object-meths.t

Re:C3 method resolution order

Stevan on 2005-07-18T21:59:11

Leo,

Our orderings do not match. However, most of my tests are for destruction order (normal MRO), and are all examples taken directly from the papers on C3 (so I expect they would be correct). I think it would be good to compare our implementations and possibly add some destruction order tests to parrot to see if those match up or not.

- Stevan

Re:C3 method resolution order

Stevan on 2005-07-19T00:12:20

Leo,

I have been looking over your MRO test, and I have to say, I think your algoritm might be wrong, or at least not the C3 algorithm we are talking about. I cannot tell for sure until I have seen it tested in destruction order. But my reasoning for this conclusion is as follows.

Take your reverse MRO (E A D B C F) for this class structure (both extracted from the test you mention):

A   B A   E
\ /   \ /
  C     D
   \   /
    \ /
     F

If we reverse this ordering for our regular MRO we get (F C B D A E). The first problem I see with this is that it violates local precedence order. F followed by C followed by B violates C's local precendence ordering since A comes before B in C's superclass ordering.

The MRO I get for this particular class tree is (F C D A B E) which as you can see preserves all the local precendence rules involved. The reverse MRO I get is (E B A D C F). To be totally honest, I do not know as much about the reverse MRO as I do the regular MRO, so I cannot comment on this really.

Also, it seems to me that Parrot (the VM) should not dictate things like MRO, that it should be a language level descision. Surely choosing the native Parrot version will be faster than implementing our own, in the end I don't think it wise to let something so central to a language be dictated by the VM. Of course I am happy to discuss this further, and can help with constructing more tests for Parrot to check the normal MRO order as well.

-Stevan

Re:C3 method resolution order

leo on 2005-07-19T11:14:08

If now implemented C3 MRO (r8650 in trunk). It's of course true that the VM shouldn't dictate a particular MRO, but we have to provide one, so why not that of our major users. If more flexibility is needed, we can always use the current HLL setting and select something different.

There is one additional test in t/pmc/object-meths.t, showing how to print the MRO of a class.

Re:C3 method resolution order

Stevan on 2005-07-19T12:46:20

Leo,

Excellent, we now match! Your test example is now in the metamodel test suite. If I find time, I will try to port my other C3 tests to Parrot for you.

- Stevan