Qore Programming Language 1.19.2
Loading...
Searching...
No Matches
Variable.h
1/* -*- mode: c++; indent-tabs-mode: nil -*- */
2/*
3 Variable.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_VARIABLE_H
33#define _QORE_VARIABLE_H
34
35enum qore_var_t {
36 VT_UNRESOLVED = 1,
37 VT_LOCAL = 2,
38 VT_GLOBAL = 3,
39 VT_CLOSURE = 4,
40 VT_LOCAL_TS = 5, // thread-safe variables, not closure-bound
41 VT_IMMEDIATE = 6, // used in references with immediate variable storage
42 VT_THREAD_LOCAL = 7
43};
44
45#include "qore/intern/RSet.h"
46#include "qore/intern/VRMutex.h"
47#include "qore/intern/QoreLValue.h"
48#include "qore/intern/qore_var_rwlock_priv.h"
49#include "qore/vector_set"
50
51#include <cstdlib>
52#include <cstring>
53#include <memory>
54#include <set>
55#include <string>
56
57// forward references
58class Var;
59class ScopedObjectCallNode;
60class QoreSquareBracketsOperatorNode;
61class QoreSquareBracketsRangeOperatorNode;
62class QoreHashObjectDereferenceOperatorNode;
63
64union qore_gvar_ref_u {
65 bool b;
66 int64 i;
67 double f;
69 // note that the "readonly" flag is stored in bit 0 of this pointer - do not read directly
70 size_t _refptr;
71
72 DLLLOCAL void setPtr(Var* refptr, bool readonly = false) {
73 _refptr = (size_t)refptr;
74 if (readonly)
75 _refptr |= 1;
76 }
77
78 DLLLOCAL Var* getPtr() const {
79#ifndef HAVE_LLVM_BUG_22050
80 // there is a bug in clang++ 3.5.[0|1] where the conditional expression below is executed with the opposite expressions
81 // when compiled with -O1 or greater: http://llvm.org/bugs/show_bug.cgi?id=22050
82 return (Var*)((_refptr & 1L) ? (_refptr ^ 1L) : _refptr);
83#else
84 return (Var*)(_refptr & (~1L));
85#endif
86 }
87
88 DLLLOCAL bool isReadOnly() const {
89 return _refptr & 1;
90 }
91
92 // checks if the reference can be written to, returns -1 if an exception was thrown
93 DLLLOCAL int write(ExceptionSink* xsink) const;
94};
95
96DLLLOCAL void get_thread_local_lvalue(void* ptr, QoreLValue<qore_gvar_ref_u>*& lvar, bool& is_new, bool& finalized);
97
98class LValueHelper;
99class LValueRemoveHelper;
100class RSetHelper;
101
102// structure for global variables
103class Var : protected QoreReferenceCounter {
104private:
105 const QoreProgramLocation* loc; // location of the initial definition
106 QoreLValue<qore_gvar_ref_u> val;
107 std::string name;
108 mutable QoreVarRWLock rwl;
109 QoreParseTypeInfo* parseTypeInfo = nullptr;
110 const QoreTypeInfo* typeInfo = nullptr;
111 const QoreTypeInfo* refTypeInfo = nullptr;
112 bool pub; // is this global var public (valid and set for modules only)
113 mutable bool finalized; // has this var already been cleared during Program destruction?
114 bool is_thread_local; // is this a thread_local var?
115 DLLLOCAL void del(ExceptionSink* xsink);
116
117 // not implemented
118 Var(const Var&) = delete;
119
120protected:
121 bool builtin = false;
122
123 DLLLOCAL ~Var() { delete parseTypeInfo; }
124
125 DLLLOCAL int checkFinalized(ExceptionSink* xsink) const {
126 if (finalized) {
127 xsink->raiseException("DESTRUCTOR-ERROR", "illegal variable assignment after second phase of variable " \
128 "destruction");
129 return -1;
130 }
131 return 0;
132 }
133
134 QoreLValue<qore_gvar_ref_u>& getVal() const {
135 if (is_thread_local) {
136 QoreLValue<qore_gvar_ref_u>* lvar;
137 bool is_new;
138 get_thread_local_lvalue((void*)this, lvar, is_new, finalized);
139 if (is_new) {
140 if (val.type == QV_Ref) {
141 lvar->set(QV_Ref);
142 lvar->v.setPtr(val.v.getPtr(), val.v.isReadOnly());
143 } else if (typeInfo) {
144 lvar->set(typeInfo);
145 }
146 }
147 return *lvar;
148 }
149 return const_cast<QoreLValue<qore_gvar_ref_u>&>(val);
150 }
151
152public:
153 DLLLOCAL Var(const QoreProgramLocation* loc, const char* n_name, bool is_thread_local = false)
154 : loc(loc), name(n_name), pub(false), finalized(false), is_thread_local(is_thread_local) {
155 }
156
157 DLLLOCAL Var(const QoreProgramLocation* loc, const char* n_name, QoreParseTypeInfo* n_parseTypeInfo,
158 bool is_thread_local = false) : loc(loc), name(n_name), parseTypeInfo(n_parseTypeInfo),
159 pub(false), finalized(false), is_thread_local(is_thread_local) {
160 }
161
162 DLLLOCAL Var(const QoreProgramLocation* loc, const char* n_name, const QoreTypeInfo* n_typeInfo,
163 bool builtin = false, bool is_thread_local = false) : loc(loc), val(n_typeInfo), name(n_name),
164 typeInfo(n_typeInfo), pub(false), finalized(false), is_thread_local(is_thread_local), builtin(builtin) {
165 }
166
167 DLLLOCAL Var(Var* ref, bool ro = false, bool is_thread_local = false);
168
169 DLLLOCAL const char* getName() const;
170
171 DLLLOCAL const std::string& getNameStr() const {
172 return name;
173 }
174
175 DLLLOCAL bool isBuiltin() const {
176 return builtin;
177 }
178
179 DLLLOCAL bool isThreadLocal() const {
180 return is_thread_local;
181 }
182
183 DLLLOCAL bool isGlobal() const {
184 return !is_thread_local;
185 }
186
187 DLLLOCAL int getLValue(LValueHelper& lvh, bool for_remove) const;
188 DLLLOCAL void remove(LValueRemoveHelper& lvrh);
189
190 DLLLOCAL void clearLocal(ExceptionSink* xsink) {
191 QoreLValue<qore_gvar_ref_u>& val = getVal();
192 if (val.type != QV_Ref) {
193 ValueHolder h(xsink);
194 QoreAutoVarRWWriteLocker al(rwl);
195 if (!finalized)
196 finalized = true;
197 printd(5, "Var::clearLocal() clearing '%s' %p\n", name.c_str(), this);
198 {
199 QoreProgram* pgm = getProgram();
200 // when Qore is terminating, this may be nullptr
201 if (pgm && (pgm->getParseOptions64() & PO_STRICT_TYPES)) {
202 h = val.assign(QoreTypeInfo::getDefaultQoreValue(typeInfo));
203 } else {
204 h = val.removeValue(true);
205 }
206 }
207 }
208#ifdef DEBUG
209 else
210 printd(5, "Var::clearLocal() skipping imported var '%s' %p\n", name.c_str(), this);
211#endif
212 }
213
214 DLLLOCAL void setInitial(AbstractQoreNode* v) {
215 QoreLValue<qore_gvar_ref_u>& val = getVal();
216 assert(val.type == QV_Node);
217 // try to set an optimized value type for the value holder if possible
218 val.set(typeInfo);
219 discard(val.assignInitial(v), nullptr);
220 }
221
222 DLLLOCAL const Var* parseGetVar() const;
223
224 DLLLOCAL bool isImported() const;
225
226 DLLLOCAL void deref(ExceptionSink* xsink);
227
228 DLLLOCAL QoreValue eval() const;
229
230 DLLLOCAL void doDoubleDeclarationError(const QoreProgramLocation* loc) {
231 // make sure types are identical or throw an exception
232 if (parseTypeInfo) {
233 parse_error(*loc, "global variable '%s' previously declared with type '%s'", name.c_str(), QoreParseTypeInfo::getName(parseTypeInfo));
234 assert(!typeInfo);
235 }
236 if (typeInfo) {
237 parse_error(*loc, "global variable '%s' previously declared with type '%s'", name.c_str(), QoreTypeInfo::getName(typeInfo));
238 assert(!parseTypeInfo);
239 }
240 }
241
242 DLLLOCAL void checkAssignType(const QoreProgramLocation* loc, const QoreTypeInfo *n_typeInfo);
243
244 DLLLOCAL int parseInit() {
245 QoreLValue<qore_gvar_ref_u>& val = getVal();
246
247 if (val.type == QV_Ref)
248 return 0;
249
250 int err = 0;
251
252 if (parseTypeInfo) {
253 typeInfo = QoreParseTypeInfo::resolveAndDelete(parseTypeInfo, loc, err);
254 refTypeInfo = QoreTypeInfo::getReferenceTarget(typeInfo);
255 parseTypeInfo = nullptr;
256
257 val.set(typeInfo);
258 }
259
260 if ((getProgram()->getParseOptions64() & PO_STRICT_TYPES) && !val.hasValue()) {
261 discard(val.assignInitial(QoreTypeInfo::getDefaultQoreValue(typeInfo)), nullptr);
262 }
263
264 return err;
265 }
266
267 DLLLOCAL QoreParseTypeInfo* copyParseTypeInfo() const {
268 return parseTypeInfo ? parseTypeInfo->copy() : nullptr;
269 }
270
271 DLLLOCAL const QoreTypeInfo* parseGetTypeInfoForInitialAssignment();
272
273 DLLLOCAL const QoreTypeInfo* parseGetTypeInfo();
274
275 DLLLOCAL const QoreTypeInfo* getTypeInfo() const;
276
277 DLLLOCAL bool hasTypeInfo() const;
278
279 DLLLOCAL bool isRef() const;
280
281 // only called with a new object declaration expression (ie our <class> $x())
282 DLLLOCAL const char* getClassName() const;
283
284 DLLLOCAL bool isPublic() const {
285 return pub;
286 }
287
288 DLLLOCAL void setPublic() {
289 assert(!pub);
290 pub = true;
291 }
292
293 DLLLOCAL const QoreProgramLocation* getParseLocation() const {
294 return loc;
295 }
296};
297
298DLLLOCAL void delete_global_variables();
299
300DLLLOCAL extern QoreHashNode* ENV;
301
302//typedef std::set<const void*> lvid_set_t;
303typedef vector_set_t<const void*> lvid_set_t;
304
305// track obj count changes
306hashdecl ObjCountRec {
307 // container
308 const AbstractQoreNode* con;
309 // initial count (true = possible recursive cycle, false = no cycle possible)
310 bool before;
311
312 DLLLOCAL ObjCountRec(const QoreListNode* c);
313 DLLLOCAL ObjCountRec(const QoreHashNode* c);
314 DLLLOCAL ObjCountRec(const QoreObject* c);
315 DLLLOCAL int getDifference();
316};
317
318typedef std::vector<ObjCountRec> ocvec_t;
319
320// this class grabs global variable or object locks for the duration of the scope of the object
321// no evaluations can be done while this object is in scope or a deadlock may result
322class LValueHelper {
323 friend class LValueRemoveHelper;
324 friend class LValueLockHandoffHelper;
325
326private:
327 // not implemented
328 DLLLOCAL LValueHelper(const LValueHelper&) = delete;
329 DLLLOCAL LValueHelper& operator=(const LValueHelper&) = delete;
330
331protected:
332 DLLLOCAL void assignNodeIntern(AbstractQoreNode* n) {
333 //printd(5, "LValueHelper::assignNodeIntern() this: %p n: %p '%s'\n", this, n, get_type_name(n));
334
335 assert(val || qv);
336 if (val)
337 val->assign(n);
338 else
339 *qv = n;
340 }
341
342 DLLLOCAL int doListLValue(const QoreSquareBracketsOperatorNode* op, bool for_remove);
343 DLLLOCAL int doHashLValue(qore_type_t t, const char* mem, bool for_remove);
344 DLLLOCAL int doHashObjLValue(const QoreHashObjectDereferenceOperatorNode* op, bool for_remove);
345
346 DLLLOCAL int makeInt(const char* desc);
347 DLLLOCAL int makeFloat(const char* desc);
348 DLLLOCAL int makeNumber(const char* desc);
349
350 DLLLOCAL int doRecursiveException() {
351 vl.xsink->raiseException("REFERENCE-ERROR", "recursive reference detected in assignment");
352 return -1;
353 }
354
355public:
356 AutoVLock vl;
357 //AbstractQoreNode** v = nullptr; // ptr to ptr for lvalue expression
358
359private:
360 typedef std::vector<AbstractQoreNode*> nvec_t;
361 nvec_t tvec;
362 lvid_set_t* lvid_set = nullptr;
363 // to track object count changes
364 ocvec_t ocvec;
365
366 // flag if the changed value was a container before the assignment
367 bool before = false;
368
369 // recursive delta: change to recursive reference count
370 int rdt = 0;
371
372 RObject* robj = nullptr;
373
374public:
375 QoreLValueGeneric* val = nullptr;
376 QoreValue* qv = nullptr;
377 const QoreTypeInfo* typeInfo = nullptr;
378
379 DLLLOCAL LValueHelper(const ReferenceNode& ref, ExceptionSink* xsink, bool for_remove = false);
380 DLLLOCAL LValueHelper(QoreValue exp, ExceptionSink* xsink, bool for_remove = false);
381
382 DLLLOCAL LValueHelper(ExceptionSink* xsink);
383
384 DLLLOCAL LValueHelper(LValueHelper&& o);
385
386 // to scan objects after initialization
387 DLLLOCAL LValueHelper(QoreObject& obj, ExceptionSink* xsink);
388
389 DLLLOCAL ~LValueHelper();
390
391 DLLLOCAL void setClosure(RObject* c) {
392 robj = c;
393 }
394
395 DLLLOCAL void saveTemp(QoreValue n);
396
397 DLLLOCAL AbstractQoreNode*& getTempRef() {
398 tvec.push_back(0);
399 return tvec[tvec.size() - 1];
400 }
401
402 DLLLOCAL int doLValue(const QoreValue exp, bool for_remove);
403
404 DLLLOCAL int doLValue(const ReferenceNode* ref, bool for_remove);
405
406 DLLLOCAL void setAndLock(QoreVarRWLock& rwl);
407 DLLLOCAL void set(QoreVarRWLock& rwl);
408
409 DLLLOCAL AutoVLock& getAutoVLock() {
410 return vl;
411 }
412
413 DLLLOCAL void setTypeInfo(const QoreTypeInfo* ti) {
414 typeInfo = ti;
415 }
416
417 DLLLOCAL void setValue(QoreLValueGeneric& nv, const QoreTypeInfo* ti = nullptr) {
418 //printd(5, "LValueHelper::setValue() this: %p new val: %p\n", this, &nv);
419
420 assert(!val);
421 assert(!qv);
422 val = &nv;
423
424 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
425
426 typeInfo = ti;
427 }
428
429 DLLLOCAL void setValue(QoreValue& nqv, const QoreTypeInfo* ti = nullptr) {
430 //printd(5, "LValueHelper::setValue() this: %p new qv: %p\n", this, &nqv);
431 assert(!val);
432 assert(!qv);
433 qv = &nqv;
434
435 before = needs_scan(nqv);
436
437 typeInfo = ti;
438 }
439
440 DLLLOCAL void resetValue(QoreLValueGeneric& nv, const QoreTypeInfo* ti = nullptr) {
441 //printd(5, "LValueHelper::resetValue() this: %p new val: %p\n", this, &nv);
442 if (qv) {
443 qv = nullptr;
444 } else {
445 assert(val);
446 }
447 val = &nv;
448
449 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
450
451 typeInfo = ti;
452 }
453
454 DLLLOCAL void resetValue(QoreValue& nqv, const QoreTypeInfo* ti = nullptr) {
455 //printd(5, "LValueHelper::resetValue() this: %p new qv: %p\n", this, &nqv);
456 if (val) {
457 val = nullptr;
458 } else {
459 assert(qv);
460 }
461 qv = &nqv;
462
463 before = needs_scan(nqv);
464
465 typeInfo = ti;
466 }
467
468 DLLLOCAL void clearPtr() {
469 if (val) {
470 val = nullptr;
471 } else if (qv) {
472 qv = nullptr;
473 }
474 typeInfo = nullptr;
475 before = false;
476 }
477
478 DLLLOCAL operator bool() const {
479 return val || qv;
480 }
481
482 DLLLOCAL bool isOptimized() const {
483 return val && val->optimized();
484 }
485
486 DLLLOCAL const QoreTypeInfo* getTypeInfo() const {
487 return typeInfo;
488 }
489
490 DLLLOCAL qore_type_t getType() const {
491 return val ? val->getType() : qv->getType();
492 }
493
494 DLLLOCAL const QoreValue getValue() const {
495 return val ? val->getValue() : *qv;
496 }
497
498 DLLLOCAL QoreValue getValue() {
499 return val ? val->getValue() : *qv;
500 }
501
502 DLLLOCAL AbstractQoreNode* getNodeValue() {
503 assert((val && val->getInternalNode()) || (qv && qv->getInternalNode()));
504 return val ? val->getInternalNode() : qv->getInternalNode();
505 }
506
507 DLLLOCAL const char* getTypeName() const {
508 return val ? val->getTypeName() : qv->getTypeName();
509 }
510
511 DLLLOCAL bool checkType(const qore_type_t t) const {
512 return getType() == t;
513 }
514
515 DLLLOCAL bool isNothing() const {
516 return checkType(NT_NOTHING);
517 }
518
519 DLLLOCAL void setObjectContext(qore_object_private* obj);
520
521 DLLLOCAL QoreValue getReferencedValue() const;
522
523 // only call if there is a reference-counted AbstractQoreNode value in place
524 // FIXME: port operators to LValueHelper instead and remove this function
525 DLLLOCAL void ensureUnique() {
526 AbstractQoreNode* current_value = getNodeValue();
527 assert(current_value && current_value->getType() != NT_OBJECT);
528
529 if (!current_value->is_unique()) {
530 //printd(5, "LValueHelper::ensureUnique() this: %p saving old value: %p '%s'\n", this, current_value, get_type_name(current_value));
531 AbstractQoreNode* old = current_value;
532 assignNodeIntern(current_value->realCopy());
533 saveTemp(old);
534 }
535 }
536
537 DLLLOCAL int64 getAsBigInt() const;
538 DLLLOCAL bool getAsBool() const;
539 DLLLOCAL double getAsFloat() const;
540
541 DLLLOCAL int64 plusEqualsBigInt(int64 v, const char* desc = "<lvalue>");
542 DLLLOCAL int64 minusEqualsBigInt(int64 v, const char* desc = "<lvalue>");
543 DLLLOCAL int64 multiplyEqualsBigInt(int64 v, const char* desc = "<lvalue>");
544 DLLLOCAL int64 divideEqualsBigInt(int64 v, const char* desc = "<lvalue>");
545 DLLLOCAL int64 orEqualsBigInt(int64 v, const char* desc = "<lvalue>");
546 DLLLOCAL int64 andEqualsBigInt(int64 v, const char* desc = "<lvalue>");
547 DLLLOCAL int64 xorEqualsBigInt(int64 v, const char* desc = "<lvalue>");
548 DLLLOCAL int64 modulaEqualsBigInt(int64 v, const char* desc = "<lvalue>");
549 DLLLOCAL int64 shiftLeftEqualsBigInt(int64 v, const char* desc = "<lvalue>");
550 DLLLOCAL int64 shiftRightEqualsBigInt(int64 v, const char* desc = "<lvalue>");
551 DLLLOCAL int64 preIncrementBigInt(const char* desc = "<lvalue>");
552 DLLLOCAL int64 preDecrementBigInt(const char* desc = "<lvalue>");
553 DLLLOCAL int64 postIncrementBigInt(const char* desc = "<lvalue>");
554 DLLLOCAL int64 postDecrementBigInt(const char* desc = "<lvalue>");
555
556 DLLLOCAL double plusEqualsFloat(double v, const char* desc = "<lvalue>");
557 DLLLOCAL double minusEqualsFloat(double v, const char* desc = "<lvalue>");
558 DLLLOCAL double multiplyEqualsFloat(double v, const char* desc = "<lvalue>");
559 DLLLOCAL double divideEqualsFloat(double v, const char* desc = "<lvalue>");
560 DLLLOCAL double preIncrementFloat(const char* desc = "<lvalue>");
561 DLLLOCAL double preDecrementFloat(const char* desc = "<lvalue>");
562 DLLLOCAL double postIncrementFloat(const char* desc = "<lvalue>");
563 DLLLOCAL double postDecrementFloat(const char* desc = "<lvalue>");
564
565 DLLLOCAL void plusEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
566 DLLLOCAL void minusEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
567 DLLLOCAL void multiplyEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
568 DLLLOCAL void divideEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
569 DLLLOCAL void preIncrementNumber(const char* desc = "<lvalue>");
570 DLLLOCAL void preDecrementNumber(const char* desc = "<lvalue>");
571 DLLLOCAL QoreNumberNode* postIncrementNumber(bool ref_rv, const char* desc = "<lvalue>");
572 DLLLOCAL QoreNumberNode* postDecrementNumber(bool ref_rv, const char* desc = "<lvalue>");
573
574 DLLLOCAL QoreNumberNode* ensureUniqueNumber(const char* desc = "<lvalue>") {
576 if (val) {
577 if (makeNumber(desc))
578 return nullptr;
579 p = &val->v.n;
580 }
581 else {
582 assert(qv);
583 if (makeNumber(desc))
584 return nullptr;
585 p = &qv->v.n;
586 }
587
588 assert(get_node_type(*p) == NT_NUMBER);
589 if (!(*p)->is_unique()) {
590 AbstractQoreNode* old = (*p);
591 (*p) = (*p)->realCopy();
592 saveTemp(old);
593 }
594 return reinterpret_cast<QoreNumberNode*>(*p);
595 }
596
597 DLLLOCAL int assign(QoreValue val, const char* desc = "<lvalue>", bool check_types = true, bool weak_assignment = false);
598
599 DLLLOCAL QoreValue removeValue(bool for_del);
600 DLLLOCAL QoreValue remove(bool& static_assignment);
601
602 DLLLOCAL void setDelta(int dt) {
603 assert(!rdt);
604 rdt = dt;
605 }
606};
607
608class LValueRemoveHelper {
609private:
610 // not implemented
611 LValueRemoveHelper(const LValueRemoveHelper&) = delete;
612 LValueRemoveHelper& operator=(const LValueRemoveHelper&) = delete;
613 void* operator new(size_t) = delete;
614
615 DLLLOCAL void doRemove(const QoreSquareBracketsOperatorNode* op);
616 DLLLOCAL void doRemove(const QoreSquareBracketsOperatorNode* op, const QoreParseListNode* l);
617 DLLLOCAL void doRemove(const QoreSquareBracketsRangeOperatorNode* op);
618
619protected:
620 ExceptionSink* xsink;
621 QoreLValueGeneric rv;
622 bool for_del,
623 direct_list = false;
624
625public:
626 DLLLOCAL LValueRemoveHelper(const ReferenceNode& ref, ExceptionSink* n_xsink, bool fd);
627 DLLLOCAL LValueRemoveHelper(const QoreValue exp, ExceptionSink* n_xsink, bool fd);
628
629 DLLLOCAL void doRemove(QoreValue exp);
630
631 DLLLOCAL operator bool() const {
632 return !*xsink;
633 }
634
635 DLLLOCAL ExceptionSink* getExceptionSink() const {
636 return xsink;
637 }
638
639 DLLLOCAL bool forDel() const {
640 return for_del;
641 }
642
643 DLLLOCAL void doRemove(QoreLValueGeneric& qv, const QoreTypeInfo* ti) {
644 QoreProgram* pgm = getProgram();
645 // when Qore is terminating, this may be nullptr
646 if (pgm && (pgm->getParseOptions64() & PO_STRICT_TYPES)) {
647 rv.assignSetTakeInitial(qv, QoreTypeInfo::getDefaultQoreValue(ti));
648 } else {
649 rv.assignSetTakeInitial(qv);
650 }
651 }
652
653 DLLLOCAL QoreValue removeValue();
654 DLLLOCAL QoreValue remove(bool& static_assignment);
655
656 DLLLOCAL void deleteLValue();
657};
658
659#endif // _QORE_VARIABLE_H
static void discard(AbstractQoreNode *n, ExceptionSink *xsink)
to deref an AbstractQoreNode (when the pointer may be 0)
Definition: QoreLib.h:327
#define PO_STRICT_TYPES
enforce strict type checking and setting default values
Definition: Restrictions.h:98
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:57
virtual DLLEXPORT AbstractQoreNode * realCopy() const =0
returns a copy of the object; the caller owns the reference count
DLLLOCAL qore_type_t getType() const
returns the data type
Definition: AbstractQoreNode.h:175
AutoVLock is a container for safely managing global variable and object lock handovers,...
Definition: AutoVLock.h:80
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:50
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
Qore's arbitrary-precision number value type, dynamically-allocated only, reference counted.
Definition: QoreNumberNode.h:51
the implementation of Qore's object data type, reference counted, dynamically-allocated only
Definition: QoreObject.h:60
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:128
DLLEXPORT int64 getParseOptions64() const
returns the parse options currently set for this program
provides atomic reference counting to Qore objects
Definition: QoreReferenceCounter.h:44
DLLEXPORT bool is_unique() const
returns true if the reference count is 1
qore_value_u v
the actual value is stored here
Definition: QoreValue.h:116
DLLEXPORT AbstractQoreNode * getInternalNode()
returns any AbstractQoreNode value held; if type != QV_Node, returns nullptr
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...
parse type: reference to a lvalue expression
Definition: ReferenceNode.h:45
holds an object and dereferences it in the destructor
Definition: QoreValue.h:487
int16_t qore_type_t
used to identify unique Qore data and parse types (descendents of AbstractQoreNode)
Definition: common.h:70
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
#define QV_Node
for heap-allocated values
Definition: QoreValue.h:46
#define QV_Ref
for references (when used with lvalues)
Definition: QoreValue.h:47
const qore_type_t NT_NUMBER
type value for QoreNumberNode
Definition: node_types.h:53
const qore_type_t NT_NOTHING
type value for QoreNothingNode
Definition: node_types.h:42
const qore_type_t NT_OBJECT
type value for QoreObject
Definition: node_types.h:52
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:276
AbstractQoreNode * n
for all heap-allocated values
Definition: QoreValue.h:60