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