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