Mercurial > octave-nkf
changeset 17249:923ce8b42db2
improve try-catch-statement to save exception to a variable (bug #33217)
* oct-parse.in.yy (except_command): Handle exception identifiers.
* oct-parse.in.yy, parse.h (octave_base_parser::make_try_command):
New arg, ID.
* pt-except.cc, pt-except.h (tree_try_catch_command::expr_id): New
data member.
(tree_command::tree_command): Initialize it.
(tree_command::~tree_command): Delete it.
(tree_command::identifier): New function.
* pt-check.cc (tree_checker::visit_try_catch_command): Check for valid
expr_id.
* pt-pr-code.cc (tree_print_code::visit_try_catch_command):
Print expr_id.
* pt-eval.cc (tree_evaluator::visit_try_catch_command): Assign message
and identifier to variable.
* try.tst: New test.
* NEWS: Note change.
author | Stefan Mahr <dac922@gmx.de> |
---|---|
date | Tue, 13 Aug 2013 19:35:53 +0200 |
parents | 0b2a0acd0315 |
children | afd235a206a2 |
files | NEWS libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/parse.h libinterp/parse-tree/pt-check.cc libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-except.cc libinterp/parse-tree/pt-except.h libinterp/parse-tree/pt-pr-code.cc test/try.tst |
diffstat | 9 files changed, 121 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Tue Aug 13 19:31:59 2013 -0400 +++ b/NEWS Tue Aug 13 19:35:53 2013 +0200 @@ -100,6 +100,29 @@ will be consistent with other binary operators. + ** Octave now has limited support for named exceptions + + The following syntax is now accepted: + + try + statements + catch exception-id + statements + end + + The exception-id is a structure with the fields "message" and + "identifier". For example + + try + error ("Octave:error-id", "error message"); + catch myerr + printf ("identifier: %s\n", myerr.identifier); + printf ("message: %s\n", myerr.message); + end_try_catch + + When classdef-style classes are added to Octave, the exception-id + will become an MException object. + ** Warning IDs renamed: Octave:array-as-scalar => Octave:array-to-scalar
--- a/libinterp/parse-tree/oct-parse.in.yy Tue Aug 13 19:31:59 2013 -0400 +++ b/libinterp/parse-tree/oct-parse.in.yy Tue Aug 13 19:35:53 2013 +0200 @@ -240,7 +240,7 @@ %type <tree_expression_type> matrix cell %type <tree_expression_type> primary_expr oper_expr %type <tree_expression_type> simple_expr colon_expr assign_expr expression -%type <tree_identifier_type> identifier fcn_name magic_tilde +%type <tree_identifier_type> identifier fcn_name magic_tilde opt_identifier %type <tree_identifier_type> superclass_identifier meta_identifier %type <octave_user_function_type> function1 function2 classdef1 %type <tree_index_expression_type> word_list_cmd @@ -975,19 +975,30 @@ if (! ($$ = parser.make_unwind_command ($1, $4, $8, $9, $2, $6))) ABORT_PARSE; } - | TRY stash_comment opt_sep opt_list CATCH + | TRY stash_comment opt_sep opt_list CATCH list END + { + if (! ($$ = parser.make_try_command ($1, $4, $6, 0, $7, $2, 0))) + ABORT_PARSE; + } + | TRY stash_comment opt_sep opt_list CATCH opt_identifier stash_comment opt_sep opt_list END { - if (! ($$ = parser.make_try_command ($1, $4, $8, $9, $2, $6))) + if (! ($$ = parser.make_try_command ($1, $4, $9, $6, $10, $2, $7))) ABORT_PARSE; } | TRY stash_comment opt_sep opt_list END { - if (! ($$ = parser.make_try_command ($1, $4, 0, $5, $2, 0))) + if (! ($$ = parser.make_try_command ($1, $4, 0, 0, $5, $2, 0))) ABORT_PARSE; } ; +opt_identifier: // empty + { $$ = 0; } + | identifier sep + { $$ = $1; } + ; + // =========================================== // Some 'subroutines' for function definitions // =========================================== @@ -2191,6 +2202,7 @@ octave_base_parser::make_try_command (token *try_tok, tree_statement_list *body, tree_statement_list *cleanup_stmts, + tree_identifier *id, token *end_tok, octave_comment_list *lc, octave_comment_list *mc) @@ -2204,7 +2216,7 @@ int l = try_tok->line (); int c = try_tok->column (); - retval = new tree_try_catch_command (body, cleanup_stmts, + retval = new tree_try_catch_command (body, cleanup_stmts, id, lc, mc, tc, l, c); }
--- a/libinterp/parse-tree/parse.h Tue Aug 13 19:31:59 2013 -0400 +++ b/libinterp/parse-tree/parse.h Tue Aug 13 19:35:53 2013 +0200 @@ -201,7 +201,7 @@ // Build a try-catch command. tree_command * make_try_command (token *try_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok, + tree_statement_list *cleanup, tree_identifier *id, token *end_tok, octave_comment_list *lc, octave_comment_list *mc); // Build a while command.
--- a/libinterp/parse-tree/pt-check.cc Tue Aug 13 19:31:59 2013 -0400 +++ b/libinterp/parse-tree/pt-check.cc Tue Aug 13 19:35:53 2013 +0200 @@ -499,6 +499,15 @@ { tree_statement_list *try_code = cmd.body (); + tree_identifier *expr_id = cmd.identifier (); + + if (expr_id) + { + if (! expr_id->lvalue_ok ()) + gripe ("invalid lvalue used for identifier in try-catch command", + cmd.line ()); + } + if (try_code) try_code->accept (*this);
--- a/libinterp/parse-tree/pt-eval.cc Tue Aug 13 19:31:59 2013 -0400 +++ b/libinterp/parse-tree/pt-eval.cc Tue Aug 13 19:35:53 2013 +0200 @@ -921,6 +921,27 @@ buffer_error_messages--; + tree_identifier *expr_id = cmd.identifier (); + octave_lvalue ult; + + if (expr_id) + { + + octave_scalar_map err; + + ult = expr_id->lvalue (); + + if (error_state) + return; + + err.assign ("message", last_error_message ()); + err.assign ("identifier", last_error_id ()); + + if (! error_state) + ult.assign (octave_value::op_asn_eq, err); + + } + if (catch_code) catch_code->accept (*this); }
--- a/libinterp/parse-tree/pt-except.cc Tue Aug 13 19:31:59 2013 -0400 +++ b/libinterp/parse-tree/pt-except.cc Tue Aug 13 19:35:53 2013 +0200 @@ -33,6 +33,7 @@ #include "pt-cmd.h" #include "pt-except.h" #include "pt-exp.h" +#include "pt-id.h" #include "pt-jump.h" #include "pt-stmt.h" #include "pt-walk.h" @@ -43,6 +44,7 @@ tree_try_catch_command::~tree_try_catch_command (void) { + delete expr_id; delete try_code; delete catch_code; delete lead_comm; @@ -57,6 +59,7 @@ return new tree_try_catch_command (try_code ? try_code->dup (scope, context) : 0, catch_code ? catch_code->dup (scope, context) : 0, + expr_id ? expr_id->dup (scope, context) : 0, lead_comm ? lead_comm->dup () : 0, mid_comm ? mid_comm->dup () : 0, trail_comm ? trail_comm->dup () : 0,
--- a/libinterp/parse-tree/pt-except.h Tue Aug 13 19:31:59 2013 -0400 +++ b/libinterp/parse-tree/pt-except.h Tue Aug 13 19:35:53 2013 +0200 @@ -29,6 +29,7 @@ #include "comment-list.h" #include "pt-cmd.h" +#include "pt-id.h" #include "symtab.h" // Simple exception handling. @@ -39,19 +40,22 @@ public: tree_try_catch_command (int l = -1, int c = -1) - : tree_command (l, c), try_code (0), catch_code (0), lead_comm (0), + : tree_command (l, c), try_code (0), catch_code (0), expr_id (0), lead_comm (0), mid_comm (0), trail_comm (0) { } tree_try_catch_command (tree_statement_list *tc, tree_statement_list *cc, + tree_identifier *id, octave_comment_list *cl = 0, octave_comment_list *cm = 0, octave_comment_list *ct = 0, int l = -1, int c = -1) - : tree_command (l, c), try_code (tc), catch_code (cc), + : tree_command (l, c), try_code (tc), catch_code (cc), expr_id (id), lead_comm (cl), mid_comm (cm), trail_comm (ct) { } ~tree_try_catch_command (void); + tree_identifier *identifier (void) { return expr_id; } + tree_statement_list *body (void) { return try_code; } tree_statement_list *cleanup (void) { return catch_code; } @@ -75,6 +79,9 @@ // The code to execute if an error occurs in the first block. tree_statement_list *catch_code; + // Identifier to modify. + tree_identifier *expr_id; + // Comment preceding TRY token. octave_comment_list *lead_comm;
--- a/libinterp/parse-tree/pt-pr-code.cc Tue Aug 13 19:31:59 2013 -0400 +++ b/libinterp/parse-tree/pt-pr-code.cc Tue Aug 13 19:35:53 2013 +0200 @@ -993,6 +993,7 @@ newline (); tree_statement_list *try_code = cmd.body (); + tree_identifier *expr_id = cmd.identifier (); if (try_code) { @@ -1009,6 +1010,12 @@ os << "catch"; + if (expr_id) + { + os << " "; + expr_id->accept (*this); + } + newline (); tree_statement_list *catch_code = cmd.cleanup ();
--- a/test/try.tst Tue Aug 13 19:31:59 2013 -0400 +++ b/test/try.tst Tue Aug 13 19:35:53 2013 +0200 @@ -127,3 +127,34 @@ %! assert (lasterr()(1:22), "rethrow: 'a' undefined"); %! end_try_catch +%!test +%! clear myerr; +%! try +%! error ("user-defined error"); +%! catch myerr +%! assert (myerr.message, "user-defined error"); +%! end_try_catch + +%!test +%! try +%! clear a; +%! error ("user-defined error"); +%! catch a=1; +%! assert (lasterr, "user-defined error"); +%! assert (a, 1); +%! end_try_catch + +%!test +%! clear myerr1 +%! clear myerr2 +%! try +%! try +%! clear a; +%! a; +%! catch myerr1 +%! error (myerr1); +%! end_try_catch +%! catch myerr2 +%! assert (myerr1.message, myerr2.message); +%! assert (myerr1.identifier, myerr2.identifier); +%! end_try_catch