Promised docs/summary of recent adventures with Parrot/Squaak

Jay Emerson jayemerson at gmail.com
Thu Jun 30 13:48:08 UTC 2011


As promised, I wanted to summarize my recent experience trying to
implement a function return for Squaak in version 3.3.0.  I'll
do this by modifying the subroutine grammar/actions (though I would
also recommend calling such a modified beast a 'function' rather
than a 'sub' or 'subroutine' -- personal preference I guess).  I was
previously successful doing this using Squaak version 2.8.0,
along the lines of KJS's post:

http://www.parrotblog.org/2008_06_11_archive.html

Here, I contrast the old and new solutions and provide a few notes
that might (sorry, no promises) help a newbie puzzled by grammar
changes over the last few years.

This is essentially a follow-up to a post I made, appearing in
'parrot-dev Digest, Vol 34, Issue 16'.  I hereby give permission for
anyone to steal and edit any of this if they think it could be helpful
someplace else.  No attribution is necessary.

-------------------------------------------------------------------------

First, we extend the grammar of Squaak.  In 2.8.0, the following
was recommended:

rule statement { # 2.8.0
   ...
   | <return_statement> {*}  #= return_statement
}

rule return_statement { # 2.8.0
   'return' <expression>
   {*}
}

IMHO, the grammar of 3.3.0 has been simplified and improved with
things like proto rules and the avoidance of the puzzling {*}.
In 3.3.0, the various types of statements follow this 'proto rule',
the new return statement is just one of several (such as
sub_call and throw), and there is no extra 'or' required as in the
2.8.0 statement rule:

rule statement:sym<return_statement> { # 3.3.0
    'return' <EXPR>
}

Secondly, we need to support assigning the result of the
function to an object.  In 2.8.0, this was achieved by
an addition to rule term:

rule term { # 2.8.0
   ...
   | <sub_call>   #= sub_call
   | <primary>    #= primary
   ...
}

In 3.3.0, this posed the real stumbling block for me.  Eventually,
I settled on the following addition to the terms (and wondered
why there is no 'proto term' statement?):

token term:sym<termsub_call> { # 3.3.0
  <primary> <arguments>
}

I had tried something similar but with 'sub_call' instead of
defining a new 'termsub_call'.  This produced errors, because
(I think) sub_call is defined as a statement sub_call and not
a generic rule; there might be some sort of name conflict.
I'm doubtful that what I did above is ideal, but it led to a
working solution.

Finally (almost) we add methods for the return_statement and
the termsub_call to Actions.pm.  In 2.8.0, only a method for the
return statement was needed:

method return_statement($/) { # 2.8.0
    my $expr := $( $<expression> );
    make PAST::Op.new( $expr,
                       :pasttype('return'),
                       :node($/) );
}

The corresponding method in 3.3.0, a type of statement method:

method statement:sym<return_statement>($/) { # 3.3.0
    my $expr := $<EXPR>.ast;
    make PAST::Op.new( $expr,
                       :pasttype('return'),
                       :node($/) );
}

And in 3.3.0, I basically have two copies of the same method for the
subroutine call (one for sub_call, and the following new one for termsub_call):

method term:sym<termsub_call>($/) { # 3.3.0
    my $invocant := $<primary>.ast;
    my $past     := $<arguments>.ast;
    $past.unshift($invocant);
    make $past;
}

One final change was needed, as noted in KJS's blog, the addition
of a line to the action method for sub_definition (appearing
immediately before the 'make $past'):

$past.control('return_pir'); # 2.8.0 and 3.3.0

That's it! I modified the function test to 00-sanity.t as well
as testing it interactively:

sub foo(a)
    return a
end

a = foo(5)
print("ok ", a)




-- 
John W. Emerson (Jay)
Associate Professor of Statistics
Department of Statistics
Yale University
http://www.stat.yale.edu/~jay


More information about the parrot-dev mailing list