# HG changeset patch # User John W. Eaton # Date 1286565767 14400 # Node ID 5677f3f7b5fac3042528bea7d13fd97922d14ff7 # Parent 2adf4736dafa570d675c93dfbf6d5bfb0be312bb Matlab compatible short-circuit behavior for & and | operators diff -r 2adf4736dafa -r 5677f3f7b5fa src/ChangeLog --- a/src/ChangeLog Fri Oct 08 07:39:31 2010 -0400 +++ b/src/ChangeLog Fri Oct 08 15:22:47 2010 -0400 @@ -1,3 +1,24 @@ +2010-10-08 John W. Eaton + + * octave.cc (maximum_braindamage): + Set do_braindead_shortcircuit_evaluation to true. + Disable Octave:possible-matlab-short-circuit-operator warning. + * oct-parse.yy (if_cmd_list1, elseif_clause, loop_command): + Mark conditions in IF and WHILE statements for braindead + short-circuit behavior. + * pt-binop.cc (Vdo_braindead_shortcircuit_evaluation): New + static variable. + (Fdo_braindead_shortcircuit_evaluation): New function. + (tree_binary_expression::rvalue1): Perform short-circuit + evaluation of | and & expressions that are conditions of WHILE + and IF statements if Vdo_braindead_shortcircuit_evaluation is true. + * pt-binop.h + (tree_binary_expression::eligible_for_braindead_shortcircuit): + New data member. Initialize it in class constructors. + (tree_binary_expression::mark_braindead_shortcircuit): New function. + * pt-exp.h (tree_expression::mark_braindead_shortcircuit): + New virtual function. + 2010-10-08 Ben Abbott * graphics.h.in: Properly set image pixel size when unique(x/ydata) diff -r 2adf4736dafa -r 5677f3f7b5fa src/oct-parse.yy --- a/src/oct-parse.yy Fri Oct 08 07:39:31 2010 -0400 +++ b/src/oct-parse.yy Fri Oct 08 15:22:47 2010 -0400 @@ -1066,7 +1066,11 @@ ; if_cmd_list1 : expression opt_sep opt_list - { $$ = start_if_command ($1, $3); } + { + $1->mark_braindead_shortcircuit (curr_fcn_file_full_name); + + $$ = start_if_command ($1, $3); + } | if_cmd_list1 elseif_clause { $1->append ($2); @@ -1075,7 +1079,11 @@ ; elseif_clause : ELSEIF stash_comment opt_sep expression opt_sep opt_list - { $$ = make_elseif_clause ($1, $4, $6, $2); } + { + $4->mark_braindead_shortcircuit (curr_fcn_file_full_name); + + $$ = make_elseif_clause ($1, $4, $6, $2); + } ; else_clause : ELSE stash_comment opt_sep opt_list @@ -1129,6 +1137,8 @@ loop_command : WHILE stash_comment expression opt_sep opt_list END { + $3->mark_braindead_shortcircuit (curr_fcn_file_full_name); + if (! ($$ = make_while_command ($1, $3, $5, $6, $2))) ABORT_PARSE; } diff -r 2adf4736dafa -r 5677f3f7b5fa src/octave.cc --- a/src/octave.cc Fri Oct 08 07:39:31 2010 -0400 +++ b/src/octave.cc Fri Oct 08 15:22:47 2010 -0400 @@ -569,6 +569,7 @@ bind_internal_variable ("confirm_recursive_rmdir", false); bind_internal_variable ("crash_dumps_octave_core", false); bind_internal_variable ("default_save_options", "-mat-binary"); + bind_internal_variable ("do_braindead_shortcircuit_evaluation", true); bind_internal_variable ("fixed_point_format", true); bind_internal_variable ("history_timestamp_format_string", "%%-- %D %I:%M %p --%%"); @@ -579,6 +580,7 @@ disable_warning ("Octave:fopen-file-in-path"); disable_warning ("Octave:function-name-clash"); disable_warning ("Octave:load-file-in-path"); + disable_warning ("Octave:possible-matlab-short-circuit-operator"); } // You guessed it. diff -r 2adf4736dafa -r 5677f3f7b5fa src/pt-binop.cc --- a/src/pt-binop.cc Fri Oct 08 07:39:31 2010 -0400 +++ b/src/pt-binop.cc Fri Oct 08 15:22:47 2010 -0400 @@ -26,11 +26,17 @@ #endif #include "error.h" +#include "defun.h" #include "oct-obj.h" #include "ov.h" #include "pt-binop.h" #include "pt-bp.h" #include "pt-walk.h" +#include "variables.h" + +// TRUE means we mark | and & expressions for braindead short-circuit +// behavior. +static bool Vdo_braindead_shortcircuit_evaluation; // Binary expressions. @@ -56,6 +62,55 @@ if (error_state) return retval; + if (Vdo_braindead_shortcircuit_evaluation + && eligible_for_braindead_shortcircuit) + { + if (op_lhs) + { + octave_value a = op_lhs->rvalue1 (); + + if (! error_state) + { + if (a.ndims () == 2 && a.rows () == 1 && a.columns () == 1) + { + bool result = false; + + bool a_true = a.is_true (); + + if (! error_state) + { + if (a_true) + { + if (etype == octave_value::op_el_or) + { + result = true; + goto done; + } + } + else + { + if (etype == octave_value::op_el_and) + goto done; + } + + if (op_rhs) + { + octave_value b = op_rhs->rvalue1 (); + + if (! error_state) + result = b.is_true (); + } + + done: + + if (! error_state) + return octave_value (result); + } + } + } + } + } + if (op_lhs) { octave_value a = op_lhs->rvalue1 (); @@ -207,3 +262,21 @@ return new_be; } + +DEFUN (do_braindead_shortcircuit_evaluation, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {@var{val} =} do_braindead_shortcircuit_evaluation ()\n\ +@deftypefnx {Built-in Function} {@var{old_val} =} do_braindead_shortcircuit_evaluation (@var{new_val})\n\ +Query or set the internal variable that controls whether Octave will\n\ +do short-circuit evaluation of @samp{|} and @samp{&} operators inside the\n\ +conditions of if or while statements.\n\ +\n\ +This feature is only provided for compatibility with Matlab and should\n\ +not be used unless you are porting old code that relies on this feature.\n\ +\n\ +To obtain short-circuit behavior for logical expressions in new programs,\n\ +you should always use the @samp{&&} and @samp{||} operators.\n\ +@end deftypefn") +{ + return SET_INTERNAL_VARIABLE (do_braindead_shortcircuit_evaluation); +} diff -r 2adf4736dafa -r 5677f3f7b5fa src/pt-binop.h --- a/src/pt-binop.h Fri Oct 08 07:39:31 2010 -0400 +++ b/src/pt-binop.h Fri Oct 08 15:22:47 2010 -0400 @@ -46,13 +46,15 @@ tree_binary_expression (int l = -1, int c = -1, octave_value::binary_op t = octave_value::unknown_binary_op) - : tree_expression (l, c), op_lhs (0), op_rhs (0), etype (t) { } + : tree_expression (l, c), op_lhs (0), op_rhs (0), etype (t), + eligible_for_braindead_shortcircuit (false) { } tree_binary_expression (tree_expression *a, tree_expression *b, int l = -1, int c = -1, octave_value::binary_op t = octave_value::unknown_binary_op) - : tree_expression (l, c), op_lhs (a), op_rhs (b), etype (t) { } + : tree_expression (l, c), op_lhs (a), op_rhs (b), etype (t), + eligible_for_braindead_shortcircuit (false) { } ~tree_binary_expression (void) { @@ -60,6 +62,27 @@ delete op_rhs; } + void mark_braindead_shortcircuit (const std::string& file) + { + if (etype == octave_value::op_el_and + || etype == octave_value::op_el_or) + { + if (file.empty ()) + warning_with_id ("Octave:possible-matlab-short-circuit-operator", + "possible Matlab-style short-circuit operator at line %d, column %d", + line (), column ()); + else + warning_with_id ("Octave:possible-matlab-short-circuit-operator", + "%s: possible Matlab-style short-circuit operator at line %d, column %d", + file.c_str (), line (), column ()); + + eligible_for_braindead_shortcircuit = true; + + op_lhs->mark_braindead_shortcircuit (file); + op_rhs->mark_braindead_shortcircuit (file); + } + } + bool has_magic_end (void) const { return ((op_lhs && op_lhs->has_magic_end ()) @@ -97,6 +120,10 @@ // The type of the expression. octave_value::binary_op etype; + // TRUE if this is an | or & expression in the condition of an IF + // or WHILE statement. + bool eligible_for_braindead_shortcircuit; + // No copying! tree_binary_expression (const tree_binary_expression&); diff -r 2adf4736dafa -r 5677f3f7b5fa src/pt-exp.h --- a/src/pt-exp.h Fri Oct 08 07:39:31 2010 -0400 +++ b/src/pt-exp.h Fri Oct 08 15:22:47 2010 -0400 @@ -96,6 +96,8 @@ virtual std::string original_text (void) const; + virtual void mark_braindead_shortcircuit (const std::string&) { } + tree_expression *mark_in_parens (void) { num_parens++;