Qore Programming Language 2.3.0
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 - 2025 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
168 DLLLOCAL Var(Var* ref, bool ro = false, bool is_thread_local = false, const char* import_as = nullptr);
169
170 DLLLOCAL const char* getName() const;
171
172 DLLLOCAL const std::string& getNameStr() const {
173 return name;
174 }
175
176 DLLLOCAL bool isBuiltin() const {
177 return builtin;
178 }
179
180 DLLLOCAL bool isThreadLocal() const {
181 return is_thread_local;
182 }
183
184 DLLLOCAL bool isGlobal() const {
185 return !is_thread_local;
186 }
187
188 DLLLOCAL int getLValue(LValueHelper& lvh, bool for_remove) const;
189 DLLLOCAL void remove(LValueRemoveHelper& lvrh);
190
191 DLLLOCAL void clearLocal(ExceptionSink* xsink) {
192 QoreLValue<qore_gvar_ref_u>& val = getVal();
193 if (val.type != QV_Ref) {
194 ValueHolder h(xsink);
195 QoreAutoVarRWWriteLocker al(rwl);
196 if (!finalized)
197 finalized = true;
198 printd(5, "Var::clearLocal() clearing '%s' %p\n", name.c_str(), this);
199 {
200 QoreProgram* pgm = getProgram();
201 // when Qore is terminating, this may be nullptr
202 if (pgm && (pgm->getParseOptions64() & PO_STRICT_TYPES)) {
203 h = val.assign(QoreTypeInfo::getDefaultQoreValue(typeInfo));
204 } else {
205 h = val.removeValue(true);
206 }
207 }
208 }
209#ifdef DEBUG
210 else
211 printd(5, "Var::clearLocal() skipping imported var '%s' %p\n", name.c_str(), this);
212#endif
213 }
214
215 DLLLOCAL void setInitial(AbstractQoreNode* v) {
216 QoreLValue<qore_gvar_ref_u>& val = getVal();
217 assert(val.type == QV_Node);
218 // try to set an optimized value type for the value holder if possible
219 val.set(typeInfo);
220 discard(val.assignInitial(v), nullptr);
221 }
222
223 DLLLOCAL const Var* parseGetVar() const;
224
225 DLLLOCAL bool isImported() const;
226
227 DLLLOCAL void deref(ExceptionSink* xsink);
228
229 DLLLOCAL QoreValue eval() const;
230
231 DLLLOCAL void doDoubleDeclarationError(const QoreProgramLocation* loc) {
232 // make sure types are identical or throw an exception
233 if (parseTypeInfo) {
234 parse_error(*loc, "global variable '%s' previously declared with type '%s'", name.c_str(),
235 QoreParseTypeInfo::getName(parseTypeInfo));
236 assert(!typeInfo);
237 }
238 if (typeInfo) {
239 parse_error(*loc, "global variable '%s' previously declared with type '%s'", name.c_str(),
240 QoreTypeInfo::getName(typeInfo));
241 assert(!parseTypeInfo);
242 }
243 }
244
245 DLLLOCAL void checkAssignType(const QoreProgramLocation* loc, const QoreTypeInfo *n_typeInfo);
246
247 DLLLOCAL int parseInit() {
248 QoreLValue<qore_gvar_ref_u>& val = getVal();
249
250 if (val.type == QV_Ref) {
251 return 0;
252 }
253
254 int err = 0;
255
256 if (parseTypeInfo) {
257 typeInfo = QoreParseTypeInfo::resolveAndDelete(parseTypeInfo, loc, err);
258 refTypeInfo = QoreTypeInfo::getReferenceTarget(typeInfo);
259 parseTypeInfo = nullptr;
260
261 val.set(typeInfo);
262 }
263
264 if ((getProgram()->getParseOptions64() & PO_STRICT_TYPES) && !val.hasValue()) {
265 discard(val.assignInitial(QoreTypeInfo::getDefaultQoreValue(typeInfo)), nullptr);
266 }
267
268 return err;
269 }
270
271 DLLLOCAL QoreParseTypeInfo* copyParseTypeInfo() const {
272 return parseTypeInfo ? parseTypeInfo->copy() : nullptr;
273 }
274
275 DLLLOCAL const QoreTypeInfo* parseGetTypeInfoForInitialAssignment();
276
277 DLLLOCAL const QoreTypeInfo* parseGetTypeInfo();
278
279 DLLLOCAL const QoreTypeInfo* getTypeInfo() const;
280
281 DLLLOCAL bool hasTypeInfo() const;
282
283 DLLLOCAL bool isRef() const;
284
285 // only called with a new object declaration expression (ie our <class> $x())
286 DLLLOCAL const char* getClassName() const;
287
288 DLLLOCAL bool isPublic() const {
289 return pub;
290 }
291
292 DLLLOCAL void setPublic() {
293 assert(!pub);
294 pub = true;
295 }
296
297 DLLLOCAL const QoreProgramLocation* getParseLocation() const {
298 return loc;
299 }
300};
301
302DLLLOCAL void delete_global_variables();
303
304DLLLOCAL extern QoreHashNode* ENV;
305
306//typedef std::set<const void*> lvid_set_t;
307typedef vector_set_t<const void*> lvid_set_t;
308
309// track obj count changes
310hashdecl ObjCountRec {
311 // container
312 const AbstractQoreNode* con;
313 // initial count (true = possible recursive cycle, false = no cycle possible)
314 bool before;
315
316 DLLLOCAL ObjCountRec(const QoreListNode* c);
317 DLLLOCAL ObjCountRec(const QoreHashNode* c);
318 DLLLOCAL ObjCountRec(const QoreObject* c);
319 DLLLOCAL int getDifference();
320};
321
322typedef std::vector<ObjCountRec> ocvec_t;
323
324// this class grabs global variable or object locks for the duration of the scope of the object
325// no evaluations can be done while this object is in scope or a deadlock may result
326class LValueHelper {
327 friend class LValueRemoveHelper;
328 friend class LValueLockHandoffHelper;
329
330private:
331 // not implemented
332 DLLLOCAL LValueHelper(const LValueHelper&) = delete;
333 DLLLOCAL LValueHelper& operator=(const LValueHelper&) = delete;
334
335protected:
336 DLLLOCAL void assignNodeIntern(AbstractQoreNode* n) {
337 //printd(5, "LValueHelper::assignNodeIntern() this: %p n: %p '%s'\n", this, n, get_type_name(n));
338
339 assert(val || qv);
340 if (val) {
341 val->assign(n);
342 } else {
343 *qv = n;
344 }
345 }
346
347 DLLLOCAL int doListLValue(const QoreSquareBracketsOperatorNode* op, bool for_remove);
348 DLLLOCAL int doHashLValue(qore_type_t t, const char* mem, bool for_remove);
349 DLLLOCAL int doObjLValue(QoreObject* o, const char* mem, bool for_remove);
350 DLLLOCAL int doHashObjLValue(const QoreHashObjectDereferenceOperatorNode* op, bool for_remove);
351
352 DLLLOCAL int makeIntQv(const char* desc);
353 DLLLOCAL int makeIntVal(const char* desc);
354
355 DLLLOCAL int makeFloat(const char* desc);
356 DLLLOCAL int makeNumber(const char* desc);
357
358 DLLLOCAL int doRecursiveException() {
359 vl.xsink->raiseException("REFERENCE-ERROR", "recursive reference detected in assignment");
360 return -1;
361 }
362
363public:
364 AutoVLock vl;
365
366private:
367 typedef std::vector<AbstractQoreNode*> nvec_t;
368 nvec_t tvec;
369 lvid_set_t* lvid_set = nullptr;
370 // to track object count changes
371 ocvec_t ocvec;
372
373 // flag if the changed value was a container before the assignment
374 bool before = false;
375
376 // recursive delta: change to recursive reference count
377 int rdt = 0;
378
379 RObject* robj = nullptr;
380
381public:
382 QoreLValueGeneric* val = nullptr;
383 QoreValue* qv = nullptr;
384 const QoreTypeInfo* typeInfo = nullptr;
385
386 DLLLOCAL LValueHelper(const ReferenceNode& ref, ExceptionSink* xsink, bool for_remove = false);
387 DLLLOCAL LValueHelper(const QoreValue& exp, ExceptionSink* xsink, bool for_remove = false);
388
389 DLLLOCAL LValueHelper(ExceptionSink* xsink);
390
391 DLLLOCAL LValueHelper(LValueHelper&& o);
392
393 // to scan objects after initialization
394 DLLLOCAL LValueHelper(QoreObject& obj, ExceptionSink* xsink);
395
396 DLLLOCAL ~LValueHelper();
397
398 DLLLOCAL int set(const ReferenceNode& ref, bool for_remove = false);
399
400 DLLLOCAL void setClosure(RObject* c) {
401 robj = c;
402 }
403
404 DLLLOCAL void saveTemp(QoreValue n);
405
406 DLLLOCAL void saveTempRef(QoreValue& n);
407
408 DLLLOCAL int doLValue(const QoreValue& exp, bool for_remove);
409
410 DLLLOCAL int doLValue(const ReferenceNode* ref, bool for_remove);
411
412 DLLLOCAL void setAndLock(QoreVarRWLock& rwl);
413 DLLLOCAL void set(QoreVarRWLock& rwl);
414
415 DLLLOCAL AutoVLock& getAutoVLock() {
416 return vl;
417 }
418
419 DLLLOCAL void setTypeInfo(const QoreTypeInfo* ti) {
420 //printd(5, "LValueHelper::setTypeInfo() this: %p ti: %s\n", this, QoreTypeInfo::getName(ti));
421
422 typeInfo = ti;
423 }
424
425 DLLLOCAL void setValue(QoreLValueGeneric& nv, const QoreTypeInfo* ti = nullptr) {
426 //printd(5, "LValueHelper::setValue() this: %p nv: %s ti: %s\n", this, nv.getFixedTypeName(),
427 // QoreTypeInfo::getName(ti));
428 assert(!val);
429 assert(!qv);
430 val = &nv;
431
432 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
433
434 typeInfo = ti;
435 }
436
437 DLLLOCAL void setValue(QoreValue& nqv, const QoreTypeInfo* ti = nullptr) {
438 //printd(5, "LValueHelper::setValue() this: %p nqv: %s ti: %s\n", this, nqv.getFullTypeName(),
439 // QoreTypeInfo::getName(ti));
440
441 assert(!val);
442 assert(!qv);
443 qv = &nqv;
444
445 before = needs_scan(nqv);
446
447 typeInfo = ti;
448 }
449
450 DLLLOCAL void resetValue(QoreLValueGeneric& nv, const QoreTypeInfo* ti = nullptr) {
451 //printd(5, "LValueHelper::resetValue() this: %p new val: %p ti: %s\n", this, &nv, QoreTypeInfo::getName(ti));
452
453 if (qv) {
454 qv = nullptr;
455 } else {
456 assert(val);
457 }
458 val = &nv;
459
460 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
461
462 typeInfo = ti;
463 }
464
465 DLLLOCAL void resetValue(QoreValue& nqv, const QoreTypeInfo* ti = nullptr) {
466 //printd(5, "LValueHelper::resetValue() this: %p nqv: %s ti: %s\n", this, nqv.getFullTypeName(),
467 // QoreTypeInfo::getName(ti));
468 if (val) {
469 val = nullptr;
470 } else {
471 assert(qv);
472 }
473 qv = &nqv;
474
475 before = needs_scan(nqv);
476
477 typeInfo = ti;
478 }
479
480 DLLLOCAL void clearPtr() {
481 if (val) {
482 val = nullptr;
483 } else if (qv) {
484 qv = nullptr;
485 }
486 typeInfo = nullptr;
487 before = false;
488 }
489
490 DLLLOCAL operator bool() const {
491 return val || qv;
492 }
493
494 DLLLOCAL bool isOptimized() const {
495 return val && val->optimized();
496 }
497
498 DLLLOCAL const QoreTypeInfo* getTypeInfo() const {
499 return typeInfo;
500 }
501
502 DLLLOCAL qore_type_t getType() const {
503 return val ? val->getType() : qv->getType();
504 }
505
506 DLLLOCAL const ReferenceNode* getReference() const {
507 if (val) {
508 return val->getReference();
509 }
510 assert(qv);
511 return qv->getType() == NT_REFERENCE ? qv->get<const ReferenceNode>() : nullptr;
512 }
513
514 DLLLOCAL const QoreValue getValue() const {
515 return val ? val->getValue() : *qv;
516 }
517
518 DLLLOCAL QoreValue getValue() {
519 return val ? val->getValue() : *qv;
520 }
521
522 DLLLOCAL AbstractQoreNode* getNodeValue() {
523 assert((val && val->getInternalNode()) || (qv && qv->getInternalNode()));
524 return val ? val->getInternalNode() : qv->getInternalNode();
525 }
526
527 DLLLOCAL const char* getTypeName() const {
528 return val ? val->getTypeName() : qv->getTypeName();
529 }
530
531 DLLLOCAL bool checkType(const qore_type_t t) const {
532 return getType() == t;
533 }
534
535 DLLLOCAL bool isNothing() const {
536 return checkType(NT_NOTHING);
537 }
538
539 DLLLOCAL void setObjectContext(qore_object_private* obj);
540
541 DLLLOCAL QoreValue getReferencedValue() const;
542
543 // only call if there is a reference-counted AbstractQoreNode value in place
544 // FIXME: port operators to LValueHelper instead and remove this function
545 DLLLOCAL void ensureUnique() {
546 AbstractQoreNode* current_value = getNodeValue();
547 assert(current_value && current_value->getType() != NT_OBJECT);
548
549 if (!current_value->is_unique()) {
550 //printd(5, "LValueHelper::ensureUnique() this: %p saving old value: %p '%s'\n", this, current_value, get_type_name(current_value));
551 AbstractQoreNode* old = current_value;
552 assignNodeIntern(current_value->realCopy());
553 saveTemp(old);
554 }
555 }
556
557 DLLLOCAL int64 getAsBigInt() const;
558 DLLLOCAL bool getAsBool() const;
559 DLLLOCAL double getAsFloat() const;
560
561 DLLLOCAL int64 plusEqualsBigInt(int64 v, const char* desc = "<lvalue>");
562 DLLLOCAL int64 minusEqualsBigInt(int64 v, const char* desc = "<lvalue>");
563 DLLLOCAL int64 multiplyEqualsBigInt(int64 v, const char* desc = "<lvalue>");
564 DLLLOCAL int64 divideEqualsBigInt(int64 v, const char* desc = "<lvalue>");
565 DLLLOCAL int64 orEqualsBigInt(int64 v, const char* desc = "<lvalue>");
566 DLLLOCAL int64 andEqualsBigInt(int64 v, const char* desc = "<lvalue>");
567 DLLLOCAL int64 xorEqualsBigInt(int64 v, const char* desc = "<lvalue>");
568 DLLLOCAL int64 modulaEqualsBigInt(int64 v, const char* desc = "<lvalue>");
569 DLLLOCAL int64 shiftLeftEqualsBigInt(int64 v, const char* desc = "<lvalue>");
570 DLLLOCAL int64 shiftRightEqualsBigInt(int64 v, const char* desc = "<lvalue>");
571 DLLLOCAL int64 preIncrementBigInt(const char* desc = "<lvalue>");
572 DLLLOCAL int64 preDecrementBigInt(const char* desc = "<lvalue>");
573 DLLLOCAL int64 postIncrementBigInt(const char* desc = "<lvalue>");
574 DLLLOCAL int64 postDecrementBigInt(const char* desc = "<lvalue>");
575
576 DLLLOCAL double plusEqualsFloat(double v, const char* desc = "<lvalue>");
577 DLLLOCAL double minusEqualsFloat(double v, const char* desc = "<lvalue>");
578 DLLLOCAL double multiplyEqualsFloat(double v, const char* desc = "<lvalue>");
579 DLLLOCAL double divideEqualsFloat(double v, const char* desc = "<lvalue>");
580 DLLLOCAL double preIncrementFloat(const char* desc = "<lvalue>");
581 DLLLOCAL double preDecrementFloat(const char* desc = "<lvalue>");
582 DLLLOCAL double postIncrementFloat(const char* desc = "<lvalue>");
583 DLLLOCAL double postDecrementFloat(const char* desc = "<lvalue>");
584
585 DLLLOCAL void plusEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
586 DLLLOCAL void minusEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
587 DLLLOCAL void multiplyEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
588 DLLLOCAL void divideEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
589 DLLLOCAL void preIncrementNumber(const char* desc = "<lvalue>");
590 DLLLOCAL void preDecrementNumber(const char* desc = "<lvalue>");
591 DLLLOCAL QoreNumberNode* postIncrementNumber(bool ref_rv, const char* desc = "<lvalue>");
592 DLLLOCAL QoreNumberNode* postDecrementNumber(bool ref_rv, const char* desc = "<lvalue>");
593
594 DLLLOCAL QoreNumberNode* ensureUniqueNumber(const char* desc = "<lvalue>") {
596 if (val) {
597 if (makeNumber(desc))
598 return nullptr;
599 p = &val->v.n;
600 }
601 else {
602 assert(qv);
603 if (makeNumber(desc))
604 return nullptr;
605 p = &qv->v.n;
606 }
607
608 assert(get_node_type(*p) == NT_NUMBER);
609 if (!(*p)->is_unique()) {
610 AbstractQoreNode* old = (*p);
611 (*p) = (*p)->realCopy();
612 saveTemp(old);
613 }
614 return reinterpret_cast<QoreNumberNode*>(*p);
615 }
616
617 DLLLOCAL int assign(QoreValue val, const char* desc = "<lvalue>", bool check_types = true, bool weak_assignment = false);
618
619 DLLLOCAL QoreValue removeValue(bool for_del);
620 DLLLOCAL QoreValue remove(bool& static_assignment);
621
622 DLLLOCAL void setDelta(int dt) {
623 assert(!rdt);
624 rdt = dt;
625 }
626};
627
628class LValueRemoveHelper {
629private:
630 // not implemented
631 LValueRemoveHelper(const LValueRemoveHelper&) = delete;
632 LValueRemoveHelper& operator=(const LValueRemoveHelper&) = delete;
633 void* operator new(size_t) = delete;
634
635 DLLLOCAL void doRemove(const QoreSquareBracketsOperatorNode* op);
636 DLLLOCAL void doRemove(const QoreSquareBracketsOperatorNode* op, const QoreParseListNode* l);
637 DLLLOCAL void doRemove(const QoreSquareBracketsRangeOperatorNode* op);
638
639protected:
640 ExceptionSink* xsink;
641 QoreLValueGeneric rv;
642 bool for_del,
643 direct_list = false;
644
645public:
646 DLLLOCAL LValueRemoveHelper(const ReferenceNode& ref, ExceptionSink* n_xsink, bool fd);
647 DLLLOCAL LValueRemoveHelper(const QoreValue& exp, ExceptionSink* n_xsink, bool fd);
648
649 DLLLOCAL void doRemove(QoreValue exp);
650
651 DLLLOCAL operator bool() const {
652 return !*xsink;
653 }
654
655 DLLLOCAL ExceptionSink* getExceptionSink() const {
656 return xsink;
657 }
658
659 DLLLOCAL bool forDel() const {
660 return for_del;
661 }
662
663 DLLLOCAL void doRemove(QoreLValueGeneric& qv, const QoreTypeInfo* ti) {
664 QoreProgram* pgm = getProgram();
665 // when Qore is terminating, this may be nullptr
666 if (pgm && (pgm->getParseOptions64() & PO_STRICT_TYPES)) {
667 rv.assignSetTakeInitial(qv, QoreTypeInfo::getDefaultQoreValue(ti));
668 } else {
669 rv.assignSetTakeInitial(qv);
670 }
671 }
672
673 DLLLOCAL QoreValue removeValue();
674 DLLLOCAL QoreValue remove(bool& static_assignment);
675
676 DLLLOCAL void deleteLValue();
677};
678
679hashdecl lvinfo {
680 QoreLValueGeneric* val;
681 const QoreTypeInfo* typeInfo;
682
683 DLLLOCAL lvinfo(QoreLValueGeneric* val, const QoreTypeInfo* typeInfo) : val(val), typeInfo(typeInfo) {
684 }
685};
686
687#endif // _QORE_VARIABLE_H
static void discard(AbstractQoreNode *n, ExceptionSink *xsink)
to deref an AbstractQoreNode (when the pointer may be 0)
Definition QoreLib.h:324
#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:51
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:61
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
DLLLOCAL detail::QoreValueCastHelper< T >::Result get()
returns the value as the given type
Definition QoreValue.h:214
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:76
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:266
#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
const qore_type_t NT_REFERENCE
type value for ReferenceNode
Definition node_types.h:64
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
The main value class in Qore, designed to be passed by value.
Definition QoreValue.h:279
AbstractQoreNode * n
for all heap-allocated values
Definition QoreValue.h:60