Qore Programming Language  0.9.16
QoreOperatorNode.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  QoreOperatorNode.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2020 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), in_parentheses(false), ref_rv(n_ref_rv) {
54  }
55 
56  // returns the type name as a c string
57  DLLLOCAL virtual const char *getTypeName() const = 0;
58 
59  DLLLOCAL void ignoreReturnValue() {
60  ref_rv = false;
61  ignoreReturnValueImpl();
62  }
63 
64  DLLLOCAL bool getInParentheses() const {
65  return in_parentheses;
66  }
67 
68  DLLLOCAL void setInParentheses() {
69  in_parentheses = true;
70  }
71 
72  DLLLOCAL virtual bool hasEffect() const = 0;
73  DLLLOCAL virtual bool hasEffectAsRoot() const = 0;
74 
75  DLLLOCAL virtual QoreOperatorNode* copyBackground(ExceptionSink *xsink) const = 0;
76 };
77 
78 class LValueOperatorNode : public QoreOperatorNode {
79 public:
80  DLLLOCAL LValueOperatorNode(const QoreProgramLocation* loc) : QoreOperatorNode(loc) {
81  }
82 
83  DLLLOCAL virtual bool hasEffect() const {
84  return true;
85  }
86 
87  DLLLOCAL virtual bool hasEffectAsRoot() const {
88  return true;
89  }
90 
91  DLLLOCAL int checkLValue(QoreValue exp, int pflag, bool assignment = true) {
92  if (exp) {
93  if (check_lvalue(exp, assignment)) {
94  parse_error(*loc, "expecting lvalue for %s, got '%s' instead", getTypeName(), exp.getTypeName());
95  return -1;
96  }
97  else if ((pflag & PF_BACKGROUND) && exp.getType() == NT_VARREF && exp.get<const VarRefNode>()->getType() == VT_LOCAL) {
98  parse_error(*loc, "illegal local variable modification with the background operator in %s", getTypeName());
99  return -1;
100  }
101  }
102  return 0;
103  }
104 };
105 
106 template <class T = QoreOperatorNode>
107 class QoreSingleExpressionOperatorNode : public T {
108 protected:
109  QoreValue exp;
110 
111  DLLLOCAL ~QoreSingleExpressionOperatorNode() {
112  exp.discard(nullptr);
113  }
114 
115 public:
116  DLLLOCAL QoreSingleExpressionOperatorNode(const QoreProgramLocation* loc, QoreValue exp) : T(loc), exp(exp) {
117  }
118 
119  DLLLOCAL QoreValue getExp() const {
120  return exp;
121  }
122 
123  DLLLOCAL QoreValue takeExp() {
124  QoreValue rv = exp;
125  exp = QoreValue();
126  return rv;
127  }
128 
129  template <class O>
130  DLLLOCAL QoreSingleExpressionOperatorNode* makeSpecialization() {
131  QoreValue e = exp;
132  exp = QoreValue();
134  O* rv = new O(this->loc, e);
135  if (!this->ref_rv)
136  rv->ignoreReturnValue();
137  return rv;
138  }
139 
140  DLLLOCAL virtual bool hasEffect() const {
141  return exp.hasEffect();
142  }
143 
144  DLLLOCAL virtual bool hasEffectAsRoot() const {
145  return dynamic_cast<const LValueOperatorNode*>(this);
146  }
147 
148  template <class O>
149  DLLLOCAL O* copyBackgroundExplicit(ExceptionSink* xsink) const {
150  ValueHolder n_exp(copy_value_and_resolve_lvar_refs(exp, xsink), xsink);
151  if (*xsink)
152  return nullptr;
153  return new O(this->loc, n_exp.release());
154  }
155 };
156 
157 template <class T = QoreOperatorNode>
158 class QoreSingleValueExpressionOperatorNode : public T {
159 protected:
160  QoreValue exp;
161 
162  DLLLOCAL ~QoreSingleValueExpressionOperatorNode() {
163  exp.discard(nullptr);
164  }
165 
166 public:
167  DLLLOCAL QoreSingleValueExpressionOperatorNode(const QoreProgramLocation* loc, QoreValue exp) : T(loc), exp(exp) {
168  }
169 
170  DLLLOCAL QoreValue getExp() const {
171  return exp;
172  }
173 
174  DLLLOCAL QoreValue takeExp() {
175  QoreValue rv = exp;
176  exp.clear();
177  return rv;
178  }
179 
180  template <class O>
181  DLLLOCAL QoreSingleValueExpressionOperatorNode* makeSpecialization() {
182  QoreValue e = exp;
183  exp.clear();
185  O* rv = new O(this->loc, e);
186  if (!this->ref_rv)
187  rv->ignoreReturnValue();
188  return rv;
189  }
190 
191  DLLLOCAL virtual bool hasEffect() const {
192  return exp.hasEffect();
193  }
194 
195  DLLLOCAL virtual bool hasEffectAsRoot() const {
196  return dynamic_cast<const LValueOperatorNode*>(this);
197  }
198 
199  template <class O>
200  DLLLOCAL O* copyBackgroundExplicit(ExceptionSink* xsink) const {
201  ValueHolder n_exp(copy_value_and_resolve_lvar_refs(exp, xsink), xsink);
202  if (*xsink)
203  return nullptr;
204  return new O(this->loc, n_exp.release());
205  }
206 };
207 
208 template <class T = QoreOperatorNode>
209 class QoreBinaryOperatorNode : public T {
210 protected:
211  QoreValue left, right;
212 
213 public:
214  DLLLOCAL QoreBinaryOperatorNode(const QoreProgramLocation* loc, QoreValue left, QoreValue right) : T(loc), left(left), right(right) {
215  }
216 
217  DLLLOCAL ~QoreBinaryOperatorNode() {
218  left.discard(nullptr);
219  right.discard(nullptr);
220  }
221 
222  template<typename U>
223  DLLLOCAL QoreBinaryOperatorNode* makeSpecialization() {
224  QoreValue l = left, r = right;
225  left = right = QoreValue();
227  U* rv = new U(this->loc, l, r);
228  if (!this->ref_rv)
229  rv->ignoreReturnValue();
230  return rv;
231  }
232 
233  DLLLOCAL QoreValue swapLeft(QoreValue n_left) {
234  QoreValue old_l = left;
235  left = n_left;
236  return old_l;
237  }
238 
239  DLLLOCAL QoreValue swapRight(QoreValue n_right) {
240  QoreValue old_r = right;
241  right = n_right;
242  return old_r;
243  }
244 
245  DLLLOCAL QoreValue getLeft() const {
246  return left;
247  }
248 
249  DLLLOCAL QoreValue getRight() const {
250  return right;
251  }
252 
253  DLLLOCAL virtual bool hasEffect() const {
254  return left.hasEffect() || right.hasEffect();
255  }
256 
257  DLLLOCAL virtual bool hasEffectAsRoot() const {
258  return dynamic_cast<const LValueOperatorNode*>(this);
259  }
260 
261  template <class O>
262  DLLLOCAL O* copyBackgroundExplicit(ExceptionSink* xsink) const {
263  ValueHolder n_left(copy_value_and_resolve_lvar_refs(left, xsink), xsink);
264  if (*xsink)
265  return nullptr;
266  ValueHolder n_right(copy_value_and_resolve_lvar_refs(right, xsink), xsink);
267  if (*xsink)
268  return nullptr;
269  return new O(this->loc, n_left.release(), n_right.release());
270  }
271 };
272 
273 class QoreBoolBinaryOperatorNode : public QoreBinaryOperatorNode<> {
274 public:
275  DLLLOCAL QoreBoolBinaryOperatorNode(const QoreProgramLocation* loc, QoreValue left, QoreValue right) : QoreBinaryOperatorNode<>(loc, left, right) {
276  }
277 
278  DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
279  return boolTypeInfo;
280  }
281 };
282 
283 class QoreIntBinaryOperatorNode : public QoreBinaryOperatorNode<> {
284 public:
285  DLLLOCAL QoreIntBinaryOperatorNode(const QoreProgramLocation* loc, QoreValue left, QoreValue right) : QoreBinaryOperatorNode<>(loc, left, right) {
286  }
287 
288  DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
289  return bigIntTypeInfo;
290  }
291 };
292 
293 #define OP_COMMON protected:\
294  DLLLOCAL static QoreString op_str;\
295 public:\
296  DLLLOCAL virtual QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const {del = false;return &op_str;}\
297  DLLLOCAL virtual int getAsString(QoreString& str, int foff, ExceptionSink* xsink) const {str.concat(&op_str);return 0;}\
298  DLLLOCAL virtual const char* getTypeName() const {return op_str.getBuffer();}
299 
300 template <unsigned int N, class T = QoreOperatorNode>
301 class QoreNOperatorNodeBase : public T {
302 protected:
303  QoreValue e[N];
304 
305  DLLLOCAL virtual ~QoreNOperatorNodeBase() {
306  for (unsigned i = 0; i < N; ++i) {
307  e[i].discard(nullptr);
308  }
309  }
310 
311 public:
312  DLLLOCAL QoreNOperatorNodeBase(const QoreProgramLocation* loc, QoreValue a0, ...) : T(loc) {
313  e[0] = a0;
314  va_list ap;
315  va_start(ap, a0);
316  for (unsigned int i = 1; i < N; ++i)
317  e[i] = va_arg(ap, QoreSimpleValue);
318  va_end(ap);
319  }
320 
321  DLLLOCAL QoreValue get(unsigned i) const {
322  assert(i < N);
323  return e[i];
324  }
325 
326  DLLLOCAL virtual bool hasEffect() const {
327  for (unsigned int i = 0; i < N; ++i)
328  if (e[i].hasEffect())
329  return true;
330  return false;
331  }
332 
333  DLLLOCAL virtual bool hasEffectAsRoot() const {
334  return dynamic_cast<const LValueOperatorNode*>(this);
335  }
336 };
337 
338 // include operator headers
339 #include "qore/intern/QoreDeleteOperatorNode.h"
340 #include "qore/intern/QoreRemoveOperatorNode.h"
341 #include "qore/intern/QoreSpliceOperatorNode.h"
342 #include "qore/intern/QoreExtractOperatorNode.h"
343 #include "qore/intern/QoreCastOperatorNode.h"
344 #include "qore/intern/QoreKeysOperatorNode.h"
345 #include "qore/intern/QoreUnaryMinusOperatorNode.h"
346 #include "qore/intern/QoreUnaryPlusOperatorNode.h"
347 #include "qore/intern/QoreLogicalNotOperatorNode.h"
348 #include "qore/intern/QoreDotEvalOperatorNode.h"
349 #include "qore/intern/QoreLogicalEqualsOperatorNode.h"
350 #include "qore/intern/QoreLogicalAbsoluteEqualsOperatorNode.h"
351 #include "qore/intern/QoreLogicalNotEqualsOperatorNode.h"
352 #include "qore/intern/QoreLogicalAbsoluteNotEqualsOperatorNode.h"
353 #include "qore/intern/QoreModuloOperatorNode.h"
354 #include "qore/intern/QoreBinaryAndOperatorNode.h"
355 #include "qore/intern/QoreBinaryOrOperatorNode.h"
356 #include "qore/intern/QoreBinaryXorOperatorNode.h"
357 #include "qore/intern/QoreBinaryNotOperatorNode.h"
358 #include "qore/intern/QoreShiftLeftOperatorNode.h"
359 #include "qore/intern/QoreShiftRightOperatorNode.h"
360 #include "qore/intern/QoreExistsOperatorNode.h"
361 #include "qore/intern/QoreElementsOperatorNode.h"
362 #include "qore/intern/QoreInstanceOfOperatorNode.h"
363 #include "qore/intern/QoreHashObjectDereferenceOperatorNode.h"
364 #include "qore/intern/QoreRegexMatchOperatorNode.h"
365 #include "qore/intern/QoreRegexNMatchOperatorNode.h"
366 #include "qore/intern/QoreRegexExtractOperatorNode.h"
367 #include "qore/intern/QoreRegexSubstOperatorNode.h"
368 #include "qore/intern/QoreTransliterationOperatorNode.h"
369 #include "qore/intern/QoreBinaryLValueOperatorNode.h"
370 #include "qore/intern/QoreAssignmentOperatorNode.h"
371 #include "qore/intern/QoreListAssignmentOperatorNode.h"
372 #include "qore/intern/QorePlusEqualsOperatorNode.h"
373 #include "qore/intern/QoreIntPlusEqualsOperatorNode.h"
374 #include "qore/intern/QoreMinusEqualsOperatorNode.h"
375 #include "qore/intern/QoreIntMinusEqualsOperatorNode.h"
376 #include "qore/intern/QoreOrEqualsOperatorNode.h"
377 #include "qore/intern/QoreAndEqualsOperatorNode.h"
378 #include "qore/intern/QoreModuloEqualsOperatorNode.h"
379 #include "qore/intern/QoreMultiplyEqualsOperatorNode.h"
380 #include "qore/intern/QoreDivideEqualsOperatorNode.h"
381 #include "qore/intern/QoreXorEqualsOperatorNode.h"
382 #include "qore/intern/QoreShiftLeftEqualsOperatorNode.h"
383 #include "qore/intern/QoreShiftRightEqualsOperatorNode.h"
384 #include "qore/intern/QorePostIncrementOperatorNode.h"
385 #include "qore/intern/QoreIntPostIncrementOperatorNode.h"
386 #include "qore/intern/QorePostDecrementOperatorNode.h"
387 #include "qore/intern/QoreIntPostDecrementOperatorNode.h"
388 #include "qore/intern/QorePreIncrementOperatorNode.h"
389 #include "qore/intern/QoreIntPreIncrementOperatorNode.h"
390 #include "qore/intern/QorePreDecrementOperatorNode.h"
391 #include "qore/intern/QoreIntPreDecrementOperatorNode.h"
392 #include "qore/intern/QoreLogicalLessThanOperatorNode.h"
393 #include "qore/intern/QoreLogicalGreaterThanOrEqualsOperatorNode.h"
394 #include "qore/intern/QoreLogicalGreaterThanOperatorNode.h"
395 #include "qore/intern/QoreLogicalLessThanOrEqualsOperatorNode.h"
396 #include "qore/intern/QoreDivisionOperatorNode.h"
397 #include "qore/intern/QoreQuestionMarkOperatorNode.h"
398 #include "qore/intern/QoreMapOperatorNode.h"
399 #include "qore/intern/QoreMapSelectOperatorNode.h"
400 #include "qore/intern/QoreHashMapOperatorNode.h"
401 #include "qore/intern/QoreHashMapSelectOperatorNode.h"
402 #include "qore/intern/QoreFoldlOperatorNode.h"
403 #include "qore/intern/QoreSelectOperatorNode.h"
404 #include "qore/intern/QoreNullCoalescingOperatorNode.h"
405 #include "qore/intern/QoreValueCoalescingOperatorNode.h"
406 #include "qore/intern/QoreChompOperatorNode.h"
407 #include "qore/intern/QoreTrimOperatorNode.h"
408 #include "qore/intern/QoreSquareBracketsOperatorNode.h"
409 #include "qore/intern/QoreShiftOperatorNode.h"
410 #include "qore/intern/QoreUnshiftOperatorNode.h"
411 #include "qore/intern/QorePopOperatorNode.h"
412 #include "qore/intern/QorePushOperatorNode.h"
413 #include "qore/intern/QoreLogicalAndOperatorNode.h"
414 #include "qore/intern/QoreLogicalOrOperatorNode.h"
415 #include "qore/intern/QoreLogicalComparisonOperatorNode.h"
416 #include "qore/intern/QorePlusOperatorNode.h"
417 #include "qore/intern/QoreMinusOperatorNode.h"
418 #include "qore/intern/QoreMultiplicationOperatorNode.h"
419 #include "qore/intern/QoreBackgroundOperatorNode.h"
420 #include "qore/intern/QoreRangeOperatorNode.h"
421 #include "qore/intern/QoreSquareBracketsRangeOperatorNode.h"
422 
423 #endif
SimpleRefHolder
manages a reference count of a pointer to a class that takes a simple "deref()" call with no argument...
Definition: ReferenceHolder.h:118
QoreValue
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
QoreValue::discard
DLLEXPORT void discard(ExceptionSink *xsink)
dereferences any contained AbstractQoreNode pointer and sets to 0; does not modify other values
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
NT_OPERATOR
const qore_type_t NT_OPERATOR
type value for QoreOperatorNode (private class)
Definition: node_types.h:76
ValueHolder
holds an object and dereferences it in the destructor
Definition: QoreValue.h:452
NT_VARREF
const qore_type_t NT_VARREF
type value for VarRefNode
Definition: node_types.h:56