GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
pt-binop.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2015 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include "error.h"
28 #include "defun.h"
29 #include "oct-obj.h"
30 #include "ov.h"
31 #include "profiler.h"
32 #include "pt-binop.h"
33 #include "pt-bp.h"
34 #include "pt-walk.h"
35 #include "variables.h"
36 
37 // TRUE means we mark | and & expressions for braindead short-circuit
38 // behavior.
40 
41 // Binary expressions.
42 
45 {
46  octave_value_list retval;
47 
48  if (nargout > 1)
49  error ("binary operator '%s': invalid number of output arguments",
50  oper () . c_str ());
51  else
52  retval = rvalue1 (nargout);
53 
54  return retval;
55 }
56 
57 void
59 {
60  warning_with_id ("Octave:possible-matlab-short-circuit-operator",
61  "Matlab-style short-circuit operation performed for operator %s",
62  op);
63 
65 }
66 
69 {
70  octave_value retval;
71 
72  if (error_state)
73  return retval;
74 
77  {
78  if (op_lhs)
79  {
80  octave_value a = op_lhs->rvalue1 ();
81 
82  if (! error_state)
83  {
84  if (a.ndims () == 2 && a.rows () == 1 && a.columns () == 1)
85  {
86  bool result = false;
87 
88  bool a_true = a.is_true ();
89 
90  if (! error_state)
91  {
92  if (a_true)
93  {
95  {
97  result = true;
98  goto done;
99  }
100  }
101  else
102  {
104  {
106  goto done;
107  }
108  }
109 
110  if (op_rhs)
111  {
112  octave_value b = op_rhs->rvalue1 ();
113 
114  if (! error_state)
115  result = b.is_true ();
116  }
117 
118  done:
119 
120  if (! error_state)
121  return octave_value (result);
122  }
123  }
124  }
125  }
126  }
127 
128  if (op_lhs)
129  {
130  octave_value a = op_lhs->rvalue1 ();
131 
132  if (! error_state && a.is_defined () && op_rhs)
133  {
134  octave_value b = op_rhs->rvalue1 ();
135 
136  if (! error_state && b.is_defined ())
137  {
139 
140  // Note: The profiler does not catch the braindead
141  // short-circuit evaluation code above, but that should be
142  // ok. The evaluation of operands and the operator itself
143  // is entangled and it's not clear where to start/stop
144  // timing the operator to make it reasonable.
145 
146  retval = ::do_binary_op (etype, a, b);
147 
148  if (error_state)
149  retval = octave_value ();
150 
152  }
153  }
154  }
155 
156  return retval;
157 }
158 
159 std::string
161 {
163 }
164 
168 {
169  tree_binary_expression *new_be
170  = new tree_binary_expression (op_lhs ? op_lhs->dup (scope, context) : 0,
171  op_rhs ? op_rhs->dup (scope, context) : 0,
172  line (), column (), etype);
173 
174  new_be->copy_base (*this);
175 
176  return new_be;
177 }
178 
179 void
181 {
182  tw.visit_binary_expression (*this);
183 }
184 
185 // Boolean expressions.
186 
189 {
190  octave_value_list retval;
191 
192  if (nargout > 1)
193  error ("binary operator '%s': invalid number of output arguments",
194  oper () . c_str ());
195  else
196  retval = rvalue1 (nargout);
197 
198  return retval;
199 }
200 
203 {
204  octave_value retval;
205 
206  if (error_state)
207  return retval;
208 
209  bool result = false;
210 
211  // This evaluation is not caught by the profiler, since we can't find
212  // a reasonable place where to time. Note that we don't want to
213  // include evaluation of LHS or RHS into the timing, but this is
214  // entangled together with short-circuit evaluation here.
215 
216  if (op_lhs)
217  {
218  octave_value a = op_lhs->rvalue1 ();
219 
220  if (! error_state)
221  {
222  bool a_true = a.is_true ();
223 
224  if (! error_state)
225  {
226  if (a_true)
227  {
228  if (etype == bool_or)
229  {
230  result = true;
231  goto done;
232  }
233  }
234  else
235  {
236  if (etype == bool_and)
237  goto done;
238  }
239 
240  if (op_rhs)
241  {
242  octave_value b = op_rhs->rvalue1 ();
243 
244  if (! error_state)
245  result = b.is_true ();
246  }
247 
248  done:
249 
250  if (! error_state)
251  retval = octave_value (result);
252  }
253  }
254  }
255 
256  return retval;
257 }
258 
259 std::string
261 {
262  std::string retval = "<unknown>";
263 
264  switch (etype)
265  {
266  case bool_and:
267  retval = "&&";
268  break;
269 
270  case bool_or:
271  retval = "||";
272  break;
273 
274  default:
275  break;
276  }
277 
278  return retval;
279 }
280 
284 {
286  = new tree_boolean_expression (op_lhs ? op_lhs->dup (scope, context) : 0,
287  op_rhs ? op_rhs->dup (scope, context) : 0,
288  line (), column (), etype);
289 
290  new_be->copy_base (*this);
291 
292  return new_be;
293 }
294 
295 DEFUN (do_braindead_shortcircuit_evaluation, args, nargout,
296  "-*- texinfo -*-\n\
297 @deftypefn {Built-in Function} {@var{val} =} do_braindead_shortcircuit_evaluation ()\n\
298 @deftypefnx {Built-in Function} {@var{old_val} =} do_braindead_shortcircuit_evaluation (@var{new_val})\n\
299 @deftypefnx {Built-in Function} {} do_braindead_shortcircuit_evaluation (@var{new_val}, \"local\")\n\
300 Query or set the internal variable that controls whether Octave will\n\
301 do short-circuit evaluation of @samp{|} and @samp{&} operators inside the\n\
302 conditions of if or while statements.\n\
303 \n\
304 This feature is only provided for compatibility with @sc{matlab} and should\n\
305 not be used unless you are porting old code that relies on this feature.\n\
306 \n\
307 To obtain short-circuit behavior for logical expressions in new programs,\n\
308 you should always use the @samp{&&} and @samp{||} operators.\n\
309 \n\
310 When called from inside a function with the @qcode{\"local\"} option, the\n\
311 variable is changed locally for the function and any subroutines it calls.\n\
312 The original variable value is restored when exiting the function.\n\
313 @end deftypefn")
314 {
315  static bool warned = false;
316  if (! warned)
317  {
318  warned = true;
319  warning_with_id ("Octave:deprecated-function",
320  "do_braindead_shortcircuit_evaluation is obsolete and will be removed from a future version of Octave");
321  }
322 
323  return SET_INTERNAL_VARIABLE (do_braindead_shortcircuit_evaluation);
324 }
325 
326 /*
327 %!test
328 %! x = 0;
329 %! do_braindead_shortcircuit_evaluation (0);
330 %! if (1 | (x = 1))
331 %! endif
332 %! assert (x, 1);
333 %! do_braindead_shortcircuit_evaluation (1);
334 %! if (1 | (x = 0))
335 %! endif
336 %! assert (x, 1);
337 */
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:696
int ndims(void) const
Definition: ov.h:479
octave_value::binary_op etype
Definition: pt-binop.h:115
octave_idx_type rows(void) const
Definition: ov.h:473
static std::string binary_op_as_string(binary_op)
Definition: ov.cc:190
std::string oper(void) const
Definition: pt-binop.cc:260
bool is_defined(void) const
Definition: ov.h:520
void matlab_style_short_circuit_warning(const char *op)
Definition: pt-binop.cc:58
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
virtual tree_expression * dup(symbol_table::scope_id, symbol_table::context_id context) const =0
void error(const char *fmt,...)
Definition: error.cc:476
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:120
octave_value_list rvalue(int nargout)
Definition: pt-binop.cc:188
virtual void copy_base(const tree_expression &e)
Definition: pt-exp.h:129
octave_value rvalue1(int nargout=1)
Definition: pt-binop.cc:68
#define END_PROFILER_BLOCK
Definition: profiler.h:213
octave_value rvalue1(int nargout=1)
Definition: pt-binop.cc:202
octave_value_list rvalue(int nargout)
Definition: pt-binop.cc:44
virtual void visit_binary_expression(tree_binary_expression &)=0
std::string oper(void) const
Definition: pt-binop.cc:160
octave_idx_type columns(void) const
Definition: ov.h:475
tree_expression * dup(symbol_table::scope_id scope, symbol_table::context_id context) const
Definition: pt-binop.cc:282
bool eligible_for_braindead_shortcircuit
Definition: pt-binop.h:119
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:76
tree_expression * dup(symbol_table::scope_id scope, symbol_table::context_id context) const
Definition: pt-binop.cc:166
int error_state
Definition: error.cc:101
bool braindead_shortcircuit_warning_issued
Definition: pt-binop.h:123
tree_expression * op_rhs
Definition: pt-binop.h:110
tree_binary_expression(int l=-1, int c=-1, octave_value::binary_op t=octave_value::unknown_binary_op)
Definition: pt-binop.h:45
virtual int line(void) const
Definition: pt.h:45
bool is_true(void) const
Definition: ov.h:671
virtual octave_value rvalue1(int nargout=1)
Definition: pt-exp.cc:58
static bool Vdo_braindead_shortcircuit_evaluation
Definition: pt-binop.cc:39
void accept(tree_walker &tw)
Definition: pt-binop.cc:180
tree_expression * op_lhs
Definition: pt-binop.h:109
virtual int column(void) const
Definition: pt.h:47
tree_boolean_expression(int l=-1, int c=-1, type t=unknown)
Definition: pt-binop.h:148
#define BEGIN_PROFILER_BLOCK(classname)
Definition: profiler.h:209
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
octave_value do_binary_op(octave_value::binary_op op, const octave_value &v1, const octave_value &v2)
Definition: ov.cc:1978