Qore Programming Language  1.12.0
QoreOperatorNode.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  QoreOperatorNode.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2022 Qore Technologies, s.r.o.
8 
9  Permission is hereby granted, free of charge, to any person obtaining a
10  copy of this software and associated documentation files (the "Software"),
11  to deal in the Software without restriction, including without limitation
12  the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  and/or sell copies of the Software, and to permit persons to whom the
14  Software is furnished to do so, subject to the following conditions:
15 
16  The above copyright notice and this permission notice shall be included in
17  all copies or substantial portions of the Software.
18 
19  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  DEALINGS IN THE SOFTWARE.
26 
27  Note that the Qore library is released under a choice of three open-source
28  licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
29  information.
30 */
31 
32 #ifndef _QORE_QOREOPERATORNODE_H
33 #define _QORE_QOREOPERATORNODE_H
34 
35 #include <cstdarg>
36 
37 DLLLOCAL QoreValue copy_value_and_resolve_lvar_refs(const QoreValue& n, ExceptionSink* xsink);
38 
39 // type of logical operator function
40 typedef bool (*op_log_func_t)(QoreValue l, QoreValue r, ExceptionSink* xsink);
41 
42 class QoreOperatorNode : public ParseNode {
43 private:
44  bool in_parentheses;
45 protected:
46  bool ref_rv;
47 
48  DLLLOCAL virtual ~QoreOperatorNode() {}
49 
50  DLLLOCAL virtual void ignoreReturnValueImpl() {}
51 
52 public:
53  DLLLOCAL QoreOperatorNode(const QoreProgramLocation* loc, bool n_ref_rv = true) : ParseNode(loc, NT_OPERATOR),
54  in_parentheses(false), ref_rv(n_ref_rv) {
55  }
56 
57  // returns the type name as a c string
58  DLLLOCAL virtual const char *getTypeName() const = 0;
59 
60  DLLLOCAL void ignoreReturnValue() {
61  ref_rv = false;
62  ignoreReturnValueImpl();
63  }
64 
65  DLLLOCAL bool getInParentheses() const {
66  return in_parentheses;
67  }
68 
69  DLLLOCAL void setInParentheses() {
70  in_parentheses = true;
71  }
72 
73  DLLLOCAL virtual bool hasEffect() const = 0;
74  DLLLOCAL virtual bool hasEffectAsRoot() const = 0;
75 
76  DLLLOCAL virtual QoreOperatorNode* copyBackground(ExceptionSink *xsink) const = 0;
77 };
78 
79 class LValueOperatorNode : public QoreOperatorNode {
80 public:
81  DLLLOCAL LValueOperatorNode(const QoreProgramLocation* loc) : QoreOperatorNode(loc) {
82  }
83 
84  DLLLOCAL virtual bool hasEffect() const {
85  return true;
86  }
87 
88  DLLLOCAL virtual bool hasEffectAsRoot() const {
89  return true;
90  }
91 
92  DLLLOCAL int checkLValue(QoreValue exp, int pflag, bool assignment = true) {
93  if (exp) {
94  if (check_lvalue(exp, assignment)) {
95  parse_error(*loc, "expecting lvalue for %s, got '%s' instead", getTypeName(), exp.getTypeName());
96  return -1;
97  } else if ((pflag & PF_BACKGROUND) && exp.getType() == NT_VARREF
98  && exp.get<const VarRefNode>()->getType() == VT_LOCAL) {
99  parse_error(*loc, "illegal local variable modification with the background operator in %s",
100  getTypeName());
101  return -1;
102  }
103  }
104  return 0;
105  }
106 };
107 
108 template <class T = QoreOperatorNode>
109 class QoreSingleExpressionOperatorNode : public T {
110 protected:
111  QoreValue exp;
112 
113  DLLLOCAL ~QoreSingleExpressionOperatorNode() {
114  exp.discard(nullptr);
115  }
116 
117 public:
118  DLLLOCAL QoreSingleExpressionOperatorNode(const QoreProgramLocation* loc, QoreValue exp) : T(loc), exp(exp) {
119  }
120 
121  DLLLOCAL QoreValue getExp() const {
122  return exp;
123  }
124 
125  DLLLOCAL QoreValue takeExp() {
126  QoreValue rv = exp;
127  exp = QoreValue();
128  return rv;
129  }
130 
131  template <class O>
132  DLLLOCAL QoreSingleExpressionOperatorNode* makeSpecialization() {
133  QoreValue e = exp;
134  exp = QoreValue();
136  O* rv = new O(this->loc, e);
137  if (!this->ref_rv)
138  rv->ignoreReturnValue();
139  return rv;
140  }
141 
142  DLLLOCAL virtual bool hasEffect() const {
143  return exp.hasEffect();
144  }
145 
146  DLLLOCAL virtual bool hasEffectAsRoot() const {
147  return dynamic_cast<const LValueOperatorNode*>(this);
148  }
149 
150  template <class O>
151  DLLLOCAL O* copyBackgroundExplicit(ExceptionSink* xsink) const {
152  ValueHolder n_exp(copy_value_and_resolve_lvar_refs(exp, xsink), xsink);
153  if (*xsink)
154  return nullptr;
155  return new O(this->loc, n_exp.release());
156  }
157 };
158 
159 template <class T = QoreOperatorNode>
160 class QoreSingleValueExpressionOperatorNode : public T {
161 protected:
162  QoreValue exp;
163 
164  DLLLOCAL ~QoreSingleValueExpressionOperatorNode() {
165  exp.discard(nullptr);
166  }
167 
168 public:
169  DLLLOCAL QoreSingleValueExpressionOperatorNode(const QoreProgramLocation* loc, QoreValue exp) : T(loc), exp(exp) {
170  }
171 
172  DLLLOCAL QoreValue getExp() const {
173  return exp;
174  }
175 
176  DLLLOCAL QoreValue takeExp() {
177  QoreValue rv = exp;
178  exp.clear();
179  return rv;
180  }
181 
182  template <class O>
183  DLLLOCAL QoreSingleValueExpressionOperatorNode* makeSpecialization() {
184  QoreValue e = exp;
185  exp.clear();
187  O* rv = new O(this->loc, e);
188  if (!this->ref_rv)
189  rv->ignoreReturnValue();
190  return rv;
191  }
192 
193  DLLLOCAL virtual bool hasEffect() const {
194  return exp.hasEffect();
195  }
196 
197  DLLLOCAL virtual bool hasEffectAsRoot() const {
198  return dynamic_cast<const LValueOperatorNode*>(this);
199  }
200 
201  template <class O>
202  DLLLOCAL O* copyBackgroundExplicit(ExceptionSink* xsink) const {
203  ValueHolder n_exp(copy_value_and_resolve_lvar_refs(exp, xsink), xsink);
204  if (*xsink)
205  return nullptr;
206  return new O(this->loc, n_exp.release());
207  }
208 };
209 
210 template <class T = QoreOperatorNode>
211 class QoreBinaryOperatorNode : public T {
212 protected:
213  QoreValue left, right;
214 
215 public:
216  DLLLOCAL QoreBinaryOperatorNode(const QoreProgramLocation* loc, QoreValue left, QoreValue right) : T(loc), left(left), right(right) {
217  }
218 
219  DLLLOCAL ~QoreBinaryOperatorNode() {
220  left.discard(nullptr);
221  right.discard(nullptr);
222  }
223 
224  template<typename U>
225  DLLLOCAL QoreBinaryOperatorNode* makeSpecialization() {
226  QoreValue l = left, r = right;
227  left = right = QoreValue();
229  U* rv = new U(this->loc, l, r);
230  if (!this->ref_rv)
231  rv->ignoreReturnValue();
232  return rv;
233  }
234 
235  DLLLOCAL QoreValue swapLeft(QoreValue n_left) {
236  QoreValue old_l = left;
237  left = n_left;
238  return old_l;
239  }
240 
241  DLLLOCAL QoreValue swapRight(QoreValue n_right) {
242  QoreValue old_r = right;
243  right = n_right;
244  return old_r;
245  }
246 
247  DLLLOCAL QoreValue getLeft() const {
248  return left;
249  }
250 
251  DLLLOCAL QoreValue getRight() const {
252  return right;
253  }
254 
255  DLLLOCAL virtual bool hasEffect() const {
256  return left.hasEffect() || right.hasEffect();
257  }
258 
259  DLLLOCAL virtual bool hasEffectAsRoot() const {
260  return dynamic_cast<const LValueOperatorNode*>(this);
261  }
262 
263  template <class O>
264  DLLLOCAL O* copyBackgroundExplicit(ExceptionSink* xsink) const {
265  ValueHolder n_left(copy_value_and_resolve_lvar_refs(left, xsink), xsink);
266  if (*xsink)
267  return nullptr;
268  ValueHolder n_right(copy_value_and_resolve_lvar_refs(right, xsink), xsink);
269  if (*xsink)
270  return nullptr;
271  return new O(this->loc, n_left.release(), n_right.release());
272  }
273 };
274 
275 class QoreBoolBinaryOperatorNode : public QoreBinaryOperatorNode<> {
276 public:
277  DLLLOCAL QoreBoolBinaryOperatorNode(const QoreProgramLocation* loc, QoreValue left, QoreValue right) : QoreBinaryOperatorNode<>(loc, left, right) {
278  }
279 
280  DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
281  return boolTypeInfo;
282  }
283 };
284 
285 class QoreIntBinaryOperatorNode : public QoreBinaryOperatorNode<> {
286 public:
287  DLLLOCAL QoreIntBinaryOperatorNode(const QoreProgramLocation* loc, QoreValue left, QoreValue right) : QoreBinaryOperatorNode<>(loc, left, right) {
288  }
289 
290  DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
291  return bigIntTypeInfo;
292  }
293 };
294 
295 #define OP_COMMON protected:\
296  DLLLOCAL static QoreString op_str;\
297 public:\
298  DLLLOCAL virtual QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const {del = false;return &op_str;}\
299  DLLLOCAL virtual int getAsString(QoreString& str, int foff, ExceptionSink* xsink) const {str.concat(&op_str);return 0;}\
300  DLLLOCAL virtual const char* getTypeName() const {return op_str.getBuffer();}
301 
302 template <unsigned int N, class T = QoreOperatorNode>
303 class QoreNOperatorNodeBase : public T {
304 protected:
305  QoreValue e[N];
306 
307  DLLLOCAL virtual ~QoreNOperatorNodeBase() {
308  for (unsigned i = 0; i < N; ++i) {
309  e[i].discard(nullptr);
310  }
311  }
312 
313 public:
314  DLLLOCAL QoreNOperatorNodeBase(const QoreProgramLocation* loc, QoreValue a0, ...) : T(loc) {
315  e[0] = a0;
316  va_list ap;
317  va_start(ap, a0);
318  for (unsigned int i = 1; i < N; ++i)
319  e[i] = va_arg(ap, QoreSimpleValue);
320  va_end(ap);
321  }
322 
323  DLLLOCAL QoreValue get(unsigned i) const {
324  assert(i < N);
325  return e[i];
326  }
327 
328  DLLLOCAL virtual bool hasEffect() const {
329  for (unsigned int i = 0; i < N; ++i)
330  if (e[i].hasEffect())
331  return true;
332  return false;
333  }
334 
335  DLLLOCAL virtual bool hasEffectAsRoot() const {
336  return dynamic_cast<const LValueOperatorNode*>(this);
337  }
338 };
339 
340 // include operator headers
341 #include "qore/intern/QoreDeleteOperatorNode.h"
342 #include "qore/intern/QoreRemoveOperatorNode.h"
343 #include "qore/intern/QoreSpliceOperatorNode.h"
344 #include "qore/intern/QoreExtractOperatorNode.h"
345 #include "qore/intern/QoreCastOperatorNode.h"
346 #include "qore/intern/QoreKeysOperatorNode.h"
347 #include "qore/intern/QoreUnaryMinusOperatorNode.h"
348 #include "qore/intern/QoreUnaryPlusOperatorNode.h"
349 #include "qore/intern/QoreLogicalNotOperatorNode.h"
350 #include "qore/intern/QoreDotEvalOperatorNode.h"
351 #include "qore/intern/QoreLogicalEqualsOperatorNode.h"
352 #include "qore/intern/QoreLogicalAbsoluteEqualsOperatorNode.h"
353 #include "qore/intern/QoreLogicalNotEqualsOperatorNode.h"
354 #include "qore/intern/QoreLogicalAbsoluteNotEqualsOperatorNode.h"
355 #include "qore/intern/QoreModuloOperatorNode.h"
356 #include "qore/intern/QoreBinaryAndOperatorNode.h"
357 #include "qore/intern/QoreBinaryOrOperatorNode.h"
358 #include "qore/intern/QoreBinaryXorOperatorNode.h"
359 #include "qore/intern/QoreBinaryNotOperatorNode.h"
360 #include "qore/intern/QoreShiftLeftOperatorNode.h"
361 #include "qore/intern/QoreShiftRightOperatorNode.h"
362 #include "qore/intern/QoreExistsOperatorNode.h"
363 #include "qore/intern/QoreElementsOperatorNode.h"
364 #include "qore/intern/QoreInstanceOfOperatorNode.h"
365 #include "qore/intern/QoreHashObjectDereferenceOperatorNode.h"
366 #include "qore/intern/QoreRegexMatchOperatorNode.h"
367 #include "qore/intern/QoreRegexNMatchOperatorNode.h"
368 #include "qore/intern/QoreRegexExtractOperatorNode.h"
369 #include "qore/intern/QoreRegexSubstOperatorNode.h"
370 #include "qore/intern/QoreTransliterationOperatorNode.h"
371 #include "qore/intern/QoreBinaryLValueOperatorNode.h"
372 #include "qore/intern/QoreAssignmentOperatorNode.h"
373 #include "qore/intern/QoreListAssignmentOperatorNode.h"
374 #include "qore/intern/QorePlusEqualsOperatorNode.h"
375 #include "qore/intern/QoreIntPlusEqualsOperatorNode.h"
376 #include "qore/intern/QoreMinusEqualsOperatorNode.h"
377 #include "qore/intern/QoreIntMinusEqualsOperatorNode.h"
378 #include "qore/intern/QoreOrEqualsOperatorNode.h"
379 #include "qore/intern/QoreAndEqualsOperatorNode.h"
380 #include "qore/intern/QoreModuloEqualsOperatorNode.h"
381 #include "qore/intern/QoreMultiplyEqualsOperatorNode.h"
382 #include "qore/intern/QoreDivideEqualsOperatorNode.h"
383 #include "qore/intern/QoreXorEqualsOperatorNode.h"
384 #include "qore/intern/QoreShiftLeftEqualsOperatorNode.h"
385 #include "qore/intern/QoreShiftRightEqualsOperatorNode.h"
386 #include "qore/intern/QorePostIncrementOperatorNode.h"
387 #include "qore/intern/QoreIntPostIncrementOperatorNode.h"
388 #include "qore/intern/QorePostDecrementOperatorNode.h"
389 #include "qore/intern/QoreIntPostDecrementOperatorNode.h"
390 #include "qore/intern/QorePreIncrementOperatorNode.h"
391 #include "qore/intern/QoreIntPreIncrementOperatorNode.h"
392 #include "qore/intern/QorePreDecrementOperatorNode.h"
393 #include "qore/intern/QoreIntPreDecrementOperatorNode.h"
394 #include "qore/intern/QoreLogicalLessThanOperatorNode.h"
395 #include "qore/intern/QoreLogicalGreaterThanOrEqualsOperatorNode.h"
396 #include "qore/intern/QoreLogicalGreaterThanOperatorNode.h"
397 #include "qore/intern/QoreLogicalLessThanOrEqualsOperatorNode.h"
398 #include "qore/intern/QoreDivisionOperatorNode.h"
399 #include "qore/intern/QoreQuestionMarkOperatorNode.h"
400 #include "qore/intern/QoreMapOperatorNode.h"
401 #include "qore/intern/QoreMapSelectOperatorNode.h"
402 #include "qore/intern/QoreHashMapOperatorNode.h"
403 #include "qore/intern/QoreHashMapSelectOperatorNode.h"
404 #include "qore/intern/QoreFoldlOperatorNode.h"
405 #include "qore/intern/QoreSelectOperatorNode.h"
406 #include "qore/intern/QoreNullCoalescingOperatorNode.h"
407 #include "qore/intern/QoreValueCoalescingOperatorNode.h"
408 #include "qore/intern/QoreChompOperatorNode.h"
409 #include "qore/intern/QoreTrimOperatorNode.h"
410 #include "qore/intern/QoreSquareBracketsOperatorNode.h"
411 #include "qore/intern/QoreShiftOperatorNode.h"
412 #include "qore/intern/QoreUnshiftOperatorNode.h"
413 #include "qore/intern/QorePopOperatorNode.h"
414 #include "qore/intern/QorePushOperatorNode.h"
415 #include "qore/intern/QoreLogicalAndOperatorNode.h"
416 #include "qore/intern/QoreLogicalOrOperatorNode.h"
417 #include "qore/intern/QoreLogicalComparisonOperatorNode.h"
418 #include "qore/intern/QorePlusOperatorNode.h"
419 #include "qore/intern/QoreMinusOperatorNode.h"
420 #include "qore/intern/QoreMultiplicationOperatorNode.h"
421 #include "qore/intern/QoreBackgroundOperatorNode.h"
422 #include "qore/intern/QoreRangeOperatorNode.h"
423 #include "qore/intern/QoreSquareBracketsRangeOperatorNode.h"
424 
425 #endif
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
manages a reference count of a pointer to a class that takes a simple "deref()" call with no argument...
Definition: ReferenceHolder.h:118
holds an object and dereferences it in the destructor
Definition: QoreValue.h:476
const qore_type_t NT_OPERATOR
type value for QoreOperatorNode (private class)
Definition: node_types.h:76
const qore_type_t NT_VARREF
type value for VarRefNode
Definition: node_types.h:56
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:275
DLLEXPORT void discard(ExceptionSink *xsink)
dereferences any contained AbstractQoreNode pointer and sets to 0; does not modify other values