Qore Programming Language 1.19.1
Loading...
Searching...
No Matches
QoreOperatorNode.h
1/* -*- mode: c++; indent-tabs-mode: nil -*- */
2/*
3 QoreOperatorNode.h
4
5 Qore Programming Language
6
7 Copyright (C) 2003 - 2023 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
37DLLLOCAL QoreValue copy_value_and_resolve_lvar_refs(const QoreValue& n, ExceptionSink* xsink);
38
39// type of logical operator function
40typedef bool (*op_log_func_t)(QoreValue l, QoreValue r, ExceptionSink* xsink);
41
42class QoreOperatorNode : public ParseNode {
43private:
44 bool in_parentheses;
45protected:
46 bool ref_rv;
47
48 DLLLOCAL virtual ~QoreOperatorNode() {}
49
50 DLLLOCAL virtual void ignoreReturnValueImpl() {}
51
52public:
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
79class LValueOperatorNode : public QoreOperatorNode {
80public:
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
108template <class T = QoreOperatorNode>
109class QoreSingleExpressionOperatorNode : public T {
110protected:
111 QoreValue exp;
112
113 DLLLOCAL ~QoreSingleExpressionOperatorNode() {
114 exp.discard(nullptr);
115 }
116
117public:
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
159template <class T = QoreOperatorNode>
160class QoreSingleValueExpressionOperatorNode : public T {
161protected:
162 QoreValue exp;
163
164 DLLLOCAL ~QoreSingleValueExpressionOperatorNode() {
165 exp.discard(nullptr);
166 }
167
168public:
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
210template <class T = QoreOperatorNode>
211class QoreBinaryOperatorNode : public T {
212protected:
213 QoreValue left, right;
214
215public:
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
275class QoreBoolBinaryOperatorNode : public QoreBinaryOperatorNode<> {
276public:
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
285class QoreIntBinaryOperatorNode : public QoreBinaryOperatorNode<> {
286public:
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;\
297public:\
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
302template <unsigned int N, class T = QoreOperatorNode>
303class QoreNOperatorNodeBase : public T {
304protected:
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
313public:
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:50
Base value class; parent of QoreValue; designed to be passed by value.
Definition: QoreValue.h:113
DLLLOCAL detail::QoreValueCastHelper< T >::Result get()
returns the value as the given type
Definition: QoreValue.h:214
DLLEXPORT qore_type_t getType() const
returns the type of value contained
DLLEXPORT const char * getTypeName() const
returns a string type description of the value contained (ex: "nothing" for a null AbstractQoreNode p...
DLLEXPORT bool hasEffect() const
return true if the value needs evaluation and has a side effect
DLLEXPORT void clear()
unconditionally set the QoreValue to QoreNothingNode (does not dereference any possible contained Abs...
manages a reference count of a pointer to a class that takes a simple "deref()" call with no argument...
Definition: ReferenceHolder.h:127
holds an object and dereferences it in the destructor
Definition: QoreValue.h:487
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:276
DLLEXPORT void discard(ExceptionSink *xsink)
dereferences any contained AbstractQoreNode pointer and sets to 0; does not modify other values