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/ >