On Thu, Mar 27, 2008 at 6:48 PM, Ovid
<[EMAIL PROTECTED]> wrote:
> Hi all,
>
> Trying to work through the tutorial
> (http://www.parrotblog.org/search/label/tutorial) and am trying to
> finish Episode 4 with catch blocks. The grammar in Episode 3 has this:
>
> try-statement ::= 'try' block 'catch' identifier
> block
> 'end'
>
> I've translated it to this:
>
> rule try_statement {
> 'try' <block>
> 'catch' <identifier> $<catch_block>=<block>
> 'end'
> {*}
> }
I did this myself the first time, but I got into problems, couldn't
get this working. Not sure why.
In any case, in my own implementation, the catch block is written (in
the grammar) as <statement>*, not <block>.
I posted my implementation a few days ago to the list; you could check
that for yourself.
>
> In searching through code, I've come up with this method for that:
>
> method try_statement($/) {
> my $try := $( $<block> );
> my $identifier := $( $<identifier> );
> my $catch := $( $<catch_block> );
>
> my $past := PAST::Op.new(
> :pasttype('try'),
> :node($/)
> );
> $past.push($try);
>
> # Create the catch
> my $catchpir := " .get_results (%r, $S0)\n store_lex '" ~
> $identifier.name() ~ "', %r";
> $catch.unshift( PAST::Op.new( :inline( $catchpir ) ) );
>
> $past.push($catch);
> make $past;
> }
>
> However, when I try it with this: "try x=4 catch e y=2 end", my pir
> doesn't appear to have any logic to catch an exception (or I just know
> pir very well).
See marker "[1]" below. The PIR that does the catching of the
exception is ".get_results..." (this is the string in $catchpir,
above)
The action method looks pretty good to me, except that it won't run (I
think). the "store_lex 'e' ... " will fail (in my experience) because
"e" wasn't declared as a ".lex". Again, see the reference
implementation that was sent to the mailing list.
So, what I did myself was, also adding a PAST::Var to the catch block,
that specifies a "lexical" (scope) that has the name of the exception
object (don't reuse the PAST node for the exception identifier), and
set the "isdecl" flag on it.
Also, how do I know that the exception object is in
> $S0? My pir is below. Is this actually correct and all will become
> clear later?
So, catching an exception in Parrot is done like this:
.get_results($P0, $S0)
where the actual exception object (printing the output of the "typeof"
instr will print "Exception") is stored in $P0, and the exception
message is stored in $S0. So, Parrot always (currently!) provides 2
things: the exceptino object and the exception message. The message
can actually be retrieved from the exception object, so it seems
superfluous. I don't know why it is implemented like this (but my
personal preference would be to remove the need for $S0). In any case,
$S0 is just a dummy, we don't use the message, just using the
exception object (which will be stored in $P0) is fine.
hope this helps, let me know if you're still having trouble.
kjs
>
> Cheers,
> Ovid
>
> .namespace
> .sub "_block10"
> push_eh catch_11
> get_global $P15, "_block12"
> newclosure $P15, $P15
> $P14 = $P15()
> pop_eh
> goto catch_11_end
> catch_11:
> get_global $P19, "_block16"
> newclosure $P19, $P19
> $P19()
> catch_11_end:
> .return ($P14)
> .end
>
>
> .namespace
> .sub "_block16" :outer("_block10")
[1]:
============================
> .get_results ($P17, $S0)
> store_lex 'e', $P17
============================
> new $P18, "Integer"
> assign $P18, 2
> set_global "y", $P18
> .return ($P18)
> .end
>
>
> .namespace
> .sub "_block12" :outer("_block10")
> new $P13, "Integer"
> assign $P13, 4
> set_global "x", $P13
> .return ($P13)
> .end
>
>
> --
> Buy the book - http://www.oreilly.com/catalog/perlhks/
> Perl and CGI - http://users.easystreet.com/ovid/cgi_course/
> Personal blog - http://publius-ovidius.livejournal.com/
> Tech blog - http://use.perl.org/~Ovid/journal/
>