Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include "error.h"
00028 #include "defun.h"
00029 #include "oct-obj.h"
00030 #include "ov.h"
00031 #include "profiler.h"
00032 #include "pt-binop.h"
00033 #include "pt-bp.h"
00034 #include "pt-walk.h"
00035 #include "variables.h"
00036
00037
00038
00039 static bool Vdo_braindead_shortcircuit_evaluation;
00040
00041
00042
00043 octave_value_list
00044 tree_binary_expression::rvalue (int nargout)
00045 {
00046 octave_value_list retval;
00047
00048 if (nargout > 1)
00049 error ("binary operator '%s': invalid number of output arguments",
00050 oper () . c_str ());
00051 else
00052 retval = rvalue1 (nargout);
00053
00054 return retval;
00055 }
00056
00057 octave_value
00058 tree_binary_expression::rvalue1 (int)
00059 {
00060 octave_value retval;
00061
00062 if (error_state)
00063 return retval;
00064
00065 if (Vdo_braindead_shortcircuit_evaluation
00066 && eligible_for_braindead_shortcircuit)
00067 {
00068 if (op_lhs)
00069 {
00070 octave_value a = op_lhs->rvalue1 ();
00071
00072 if (! error_state)
00073 {
00074 if (a.ndims () == 2 && a.rows () == 1 && a.columns () == 1)
00075 {
00076 bool result = false;
00077
00078 bool a_true = a.is_true ();
00079
00080 if (! error_state)
00081 {
00082 if (a_true)
00083 {
00084 if (etype == octave_value::op_el_or)
00085 {
00086 result = true;
00087 goto done;
00088 }
00089 }
00090 else
00091 {
00092 if (etype == octave_value::op_el_and)
00093 goto done;
00094 }
00095
00096 if (op_rhs)
00097 {
00098 octave_value b = op_rhs->rvalue1 ();
00099
00100 if (! error_state)
00101 result = b.is_true ();
00102 }
00103
00104 done:
00105
00106 if (! error_state)
00107 return octave_value (result);
00108 }
00109 }
00110 }
00111 }
00112 }
00113
00114 if (op_lhs)
00115 {
00116 octave_value a = op_lhs->rvalue1 ();
00117
00118 if (! error_state && a.is_defined () && op_rhs)
00119 {
00120 octave_value b = op_rhs->rvalue1 ();
00121
00122 if (! error_state && b.is_defined ())
00123 {
00124 BEGIN_PROFILER_BLOCK ("binary " + oper ())
00125
00126
00127
00128
00129
00130
00131
00132 retval = ::do_binary_op (etype, a, b);
00133
00134 if (error_state)
00135 retval = octave_value ();
00136
00137 END_PROFILER_BLOCK
00138 }
00139 }
00140 }
00141
00142 return retval;
00143 }
00144
00145 std::string
00146 tree_binary_expression::oper (void) const
00147 {
00148 return octave_value::binary_op_as_string (etype);
00149 }
00150
00151 tree_expression *
00152 tree_binary_expression::dup (symbol_table::scope_id scope,
00153 symbol_table::context_id context) const
00154 {
00155 tree_binary_expression *new_be
00156 = new tree_binary_expression (op_lhs ? op_lhs->dup (scope, context) : 0,
00157 op_rhs ? op_rhs->dup (scope, context) : 0,
00158 line (), column (), etype);
00159
00160 new_be->copy_base (*this);
00161
00162 return new_be;
00163 }
00164
00165 void
00166 tree_binary_expression::accept (tree_walker& tw)
00167 {
00168 tw.visit_binary_expression (*this);
00169 }
00170
00171
00172
00173 octave_value_list
00174 tree_boolean_expression::rvalue (int nargout)
00175 {
00176 octave_value_list retval;
00177
00178 if (nargout > 1)
00179 error ("binary operator '%s': invalid number of output arguments",
00180 oper () . c_str ());
00181 else
00182 retval = rvalue1 (nargout);
00183
00184 return retval;
00185 }
00186
00187 octave_value
00188 tree_boolean_expression::rvalue1 (int)
00189 {
00190 octave_value retval;
00191
00192 if (error_state)
00193 return retval;
00194
00195 bool result = false;
00196
00197
00198
00199
00200
00201
00202 if (op_lhs)
00203 {
00204 octave_value a = op_lhs->rvalue1 ();
00205
00206 if (! error_state)
00207 {
00208 bool a_true = a.is_true ();
00209
00210 if (! error_state)
00211 {
00212 if (a_true)
00213 {
00214 if (etype == bool_or)
00215 {
00216 result = true;
00217 goto done;
00218 }
00219 }
00220 else
00221 {
00222 if (etype == bool_and)
00223 goto done;
00224 }
00225
00226 if (op_rhs)
00227 {
00228 octave_value b = op_rhs->rvalue1 ();
00229
00230 if (! error_state)
00231 result = b.is_true ();
00232 }
00233
00234 done:
00235
00236 if (! error_state)
00237 retval = octave_value (result);
00238 }
00239 }
00240 }
00241
00242 return retval;
00243 }
00244
00245 std::string
00246 tree_boolean_expression::oper (void) const
00247 {
00248 std::string retval = "<unknown>";
00249
00250 switch (etype)
00251 {
00252 case bool_and:
00253 retval = "&&";
00254 break;
00255
00256 case bool_or:
00257 retval = "||";
00258 break;
00259
00260 default:
00261 break;
00262 }
00263
00264 return retval;
00265 }
00266
00267 tree_expression *
00268 tree_boolean_expression::dup (symbol_table::scope_id scope,
00269 symbol_table::context_id context) const
00270 {
00271 tree_boolean_expression *new_be
00272 = new tree_boolean_expression (op_lhs ? op_lhs->dup (scope, context) : 0,
00273 op_rhs ? op_rhs->dup (scope, context) : 0,
00274 line (), column (), etype);
00275
00276 new_be->copy_base (*this);
00277
00278 return new_be;
00279 }
00280
00281 DEFUN (do_braindead_shortcircuit_evaluation, args, nargout,
00282 "-*- texinfo -*-\n\
00283 @deftypefn {Built-in Function} {@var{val} =} do_braindead_shortcircuit_evaluation ()\n\
00284 @deftypefnx {Built-in Function} {@var{old_val} =} do_braindead_shortcircuit_evaluation (@var{new_val})\n\
00285 @deftypefnx {Built-in Function} {} do_braindead_shortcircuit_evaluation (@var{new_val}, \"local\")\n\
00286 Query or set the internal variable that controls whether Octave will\n\
00287 do short-circuit evaluation of @samp{|} and @samp{&} operators inside the\n\
00288 conditions of if or while statements.\n\
00289 \n\
00290 This feature is only provided for compatibility with @sc{matlab} and should\n\
00291 not be used unless you are porting old code that relies on this feature.\n\
00292 \n\
00293 To obtain short-circuit behavior for logical expressions in new programs,\n\
00294 you should always use the @samp{&&} and @samp{||} operators.\n\
00295 \n\
00296 When called from inside a function with the \"local\" option, the variable is\n\
00297 changed locally for the function and any subroutines it calls. The original\n\
00298 variable value is restored when exiting the function.\n\
00299 @end deftypefn")
00300 {
00301 return SET_INTERNAL_VARIABLE (do_braindead_shortcircuit_evaluation);
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318