GNU Octave  4.2.1
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-2017 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 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include "error.h"
28 #include "defun.h"
29 #include "ovl.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 {
47 
48  if (nargout > 1)
49  error ("binary operator '%s': invalid number of output arguments",
50  oper ().c_str ());
51 
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 {
71 
72  if (Vdo_braindead_shortcircuit_evaluation
74  {
75  if (op_lhs)
76  {
78 
79  if (a.ndims () == 2 && a.rows () == 1 && a.columns () == 1)
80  {
81  bool result = false;
82 
83  bool a_true = a.is_true ();
84 
85  if (a_true)
86  {
88  {
90  return octave_value (true);
91  }
92  }
93  else
94  {
96  {
98  return octave_value (false);
99  }
100  }
101 
102  if (op_rhs)
103  {
105 
106  result = b.is_true ();
107  }
108 
109  return octave_value (result);
110  }
111  }
112  }
113 
114  if (op_lhs)
115  {
117 
118  if (a.is_defined () && op_rhs)
119  {
121 
122  if (b.is_defined ())
123  {
125 
126  // Note: The profiler does not catch the braindead
127  // short-circuit evaluation code above, but that should be
128  // ok. The evaluation of operands and the operator itself
129  // is entangled and it's not clear where to start/stop
130  // timing the operator to make it reasonable.
131 
132  retval = ::do_binary_op (etype, a, b);
133 
135  }
136  }
137  }
138 
139  return retval;
140 }
141 
144 {
146 }
147 
151 {
152  tree_binary_expression *new_be
153  = new tree_binary_expression (op_lhs ? op_lhs->dup (scope, context) : 0,
154  op_rhs ? op_rhs->dup (scope, context) : 0,
155  line (), column (), etype);
156 
157  new_be->copy_base (*this);
158 
159  return new_be;
160 }
161 
162 void
164 {
165  tw.visit_binary_expression (*this);
166 }
167 
168 // Boolean expressions.
169 
172 {
174 
175  if (nargout > 1)
176  error ("binary operator '%s': invalid number of output arguments",
177  oper ().c_str ());
178 
179  retval = rvalue1 (nargout);
180 
181  return retval;
182 }
183 
186 {
188 
189  bool result = false;
190 
191  // This evaluation is not caught by the profiler, since we can't find
192  // a reasonable place where to time. Note that we don't want to
193  // include evaluation of LHS or RHS into the timing, but this is
194  // entangled together with short-circuit evaluation here.
195 
196  if (op_lhs)
197  {
199 
200  bool a_true = a.is_true ();
201 
202  if (a_true)
203  {
204  if (etype == bool_or)
205  return octave_value (true);
206  }
207  else
208  {
209  if (etype == bool_and)
210  return octave_value (false);
211  }
212 
213  if (op_rhs)
214  {
216 
217  result = b.is_true ();
218  }
219 
220  retval = octave_value (result);
221  }
222 
223  return retval;
224 }
225 
228 {
229  std::string retval = "<unknown>";
230 
231  switch (etype)
232  {
233  case bool_and:
234  retval = "&&";
235  break;
236 
237  case bool_or:
238  retval = "||";
239  break;
240 
241  default:
242  break;
243  }
244 
245  return retval;
246 }
247 
251 {
253  = new tree_boolean_expression (op_lhs ? op_lhs->dup (scope, context) : 0,
254  op_rhs ? op_rhs->dup (scope, context) : 0,
255  line (), column (), etype);
256 
257  new_be->copy_base (*this);
258 
259  return new_be;
260 }
261 
262 DEFUN (do_braindead_shortcircuit_evaluation, args, nargout,
263  doc: /* -*- texinfo -*-
264 @deftypefn {} {@var{val} =} do_braindead_shortcircuit_evaluation ()
265 @deftypefnx {} {@var{old_val} =} do_braindead_shortcircuit_evaluation (@var{new_val})
266 @deftypefnx {} {} do_braindead_shortcircuit_evaluation (@var{new_val}, "local")
267 Query or set the internal variable that controls whether Octave will
268 do short-circuit evaluation of @samp{|} and @samp{&} operators inside the
269 conditions of if or while statements.
270 
271 This feature is only provided for compatibility with @sc{matlab} and should
272 not be used unless you are porting old code that relies on this feature.
273 
274 To obtain short-circuit behavior for logical expressions in new programs,
275 you should always use the @samp{&&} and @samp{||} operators.
276 
277 When called from inside a function with the @qcode{"local"} option, the
278 variable is changed locally for the function and any subroutines it calls.
279 The original variable value is restored when exiting the function.
280 @end deftypefn */)
281 {
282  static bool warned = false;
283  if (! warned)
284  {
285  warned = true;
286  warning_with_id ("Octave:deprecated-function",
287  "do_braindead_shortcircuit_evaluation is obsolete and will be removed from a future version of Octave");
288  }
289 
290  return SET_INTERNAL_VARIABLE (do_braindead_shortcircuit_evaluation);
291 }
292 
293 /*
294 %!test
295 %! x = 0;
296 %! do_braindead_shortcircuit_evaluation (0);
297 %! if (1 | (x = 1))
298 %! endif
299 %! assert (x, 1);
300 %! do_braindead_shortcircuit_evaluation (1);
301 %! if (1 | (x = 0))
302 %! endif
303 %! assert (x, 1);
304 */
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:803
int ndims(void) const
Definition: ov.h:495
octave_value::binary_op etype
Definition: pt-binop.h:116
octave_idx_type rows(void) const
Definition: ov.h:489
static std::string binary_op_as_string(binary_op)
Definition: ov.cc:175
std::string oper(void) const
Definition: pt-binop.cc:227
bool is_defined(void) const
Definition: ov.h:536
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:46
virtual tree_expression * dup(symbol_table::scope_id, symbol_table::context_id context) const =0
void error(const char *fmt,...)
Definition: error.cc:570
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:126
octave_value_list rvalue(int nargout)
Definition: pt-binop.cc:171
virtual void copy_base(const tree_expression &e)
Definition: pt-exp.h:131
octave_value rvalue1(int nargout=1)
Definition: pt-binop.cc:68
#define END_PROFILER_BLOCK
Definition: profiler.h:215
octave_value rvalue1(int nargout=1)
Definition: pt-binop.cc:185
octave_value_list rvalue(int nargout)
Definition: pt-binop.cc:44
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:398
virtual void visit_binary_expression(tree_binary_expression &)=0
JNIEnv void * args
Definition: ov-java.cc:67
std::string oper(void) const
Definition: pt-binop.cc:143
octave_idx_type columns(void) const
Definition: ov.h:491
tree_expression * dup(symbol_table::scope_id scope, symbol_table::context_id context) const
Definition: pt-binop.cc:249
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:935
bool eligible_for_braindead_shortcircuit
Definition: pt-binop.h:120
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:149
octave_value retval
Definition: data.cc:6294
bool braindead_shortcircuit_warning_issued
Definition: pt-binop.h:124
tree_expression * op_rhs
Definition: pt-binop.h:111
tree_binary_expression(int l=-1, int c=-1, octave_value::binary_op t=octave_value::unknown_binary_op)
Definition: pt-binop.h:47
virtual int line(void) const
Definition: pt.h:49
With real return the complex result
Definition: data.cc:3375
bool is_true(void) const
Definition: ov.h:687
virtual octave_value rvalue1(int nargout=1)
Definition: pt-exp.cc:54
static bool Vdo_braindead_shortcircuit_evaluation
Definition: pt-binop.cc:39
void accept(tree_walker &tw)
Definition: pt-binop.cc:163
tree_expression * op_lhs
Definition: pt-binop.h:110
b
Definition: cellfun.cc:398
virtual int column(void) const
Definition: pt.h:51
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
tree_boolean_expression(int l=-1, int c=-1, type t=unknown)
Definition: pt-binop.h:149
#define BEGIN_PROFILER_BLOCK(classname)
Definition: profiler.h:211
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:2214