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;
63class RuntimeConfig;
64
65union qore_gvar_ref_u {
66 bool b;
67 int64 i;
68 double f;
70 // note that the "readonly" flag is stored in bit 0 of this pointer - do not read directly
71 size_t _refptr;
72
73 DLLLOCAL void setPtr(Var* refptr, bool readonly = false) {
74 _refptr = (size_t)refptr;
75 if (readonly)
76 _refptr |= 1;
77 }
78
79 DLLLOCAL Var* getPtr() const {
80#ifndef HAVE_LLVM_BUG_22050
81 // there is a bug in clang++ 3.5.[0|1] where the conditional expression below is executed with the opposite expressions
82 // when compiled with -O1 or greater: http://llvm.org/bugs/show_bug.cgi?id=22050
83 return (Var*)((_refptr & 1L) ? (_refptr ^ 1L) : _refptr);
84#else
85 return (Var*)(_refptr & (~1L));
86#endif
87 }
88
89 DLLLOCAL bool isReadOnly() const {
90 return _refptr & 1;
91 }
92
93 // checks if the reference can be written to, returns -1 if an exception was thrown
94 DLLLOCAL int write(ExceptionSink* xsink) const;
95};
96
97DLLLOCAL void get_thread_local_lvalue(void* ptr, QoreLValue<qore_gvar_ref_u>*& lvar, bool& is_new, bool& finalized);
98
99class LValueHelper;
100class LValueRemoveHelper;
101class RSetHelper;
102
103// structure for global variables
104class Var : protected QoreReferenceCounter {
105private:
106 const QoreProgramLocation* loc; // location of the initial definition
107 QoreLValue<qore_gvar_ref_u> val;
108 std::string name;
109 mutable QoreVarRWLock rwl;
110 QoreParseTypeInfo* parseTypeInfo = nullptr;
111 const QoreTypeInfo* typeInfo = nullptr;
112 const QoreTypeInfo* refTypeInfo = nullptr;
113 const QoreTypeInfo* narrowedTypeInfo = nullptr; // narrowed type from assignment
114 const QoreProgramLocation* narrowedLoc = nullptr; // location where narrowing occurred
115 bool is_auto_type = false; // true if declared type is an auto type
116 bool no_narrowing = false; // true if declared with auto! to disable type narrowing
117 bool pub; // is this global var public (valid and set for modules only)
118 mutable bool finalized; // has this var already been cleared during Program destruction?
119 bool is_thread_local; // is this a thread_local var?
120 DLLLOCAL void del(ExceptionSink* xsink);
121
122 // not implemented
123 Var(const Var&) = delete;
124
125protected:
126 bool builtin = false;
127
128 DLLLOCAL ~Var() { delete parseTypeInfo; }
129
130 DLLLOCAL int checkFinalized(ExceptionSink* xsink) const {
131 if (finalized) {
132 xsink->raiseException("DESTRUCTOR-ERROR", "illegal variable assignment after second phase of variable " \
133 "destruction");
134 return -1;
135 }
136 return 0;
137 }
138
139 QoreLValue<qore_gvar_ref_u>& getVal() const {
140 if (is_thread_local) {
141 QoreLValue<qore_gvar_ref_u>* lvar;
142 bool is_new;
143 get_thread_local_lvalue((void*)this, lvar, is_new, finalized);
144 if (is_new) {
145 if (val.type == QV_Ref) {
146 lvar->set(QV_Ref);
147 lvar->v.setPtr(val.v.getPtr(), val.v.isReadOnly());
148 } else if (typeInfo) {
149 lvar->set(typeInfo);
150 }
151 }
152 return *lvar;
153 }
154 return const_cast<QoreLValue<qore_gvar_ref_u>&>(val);
155 }
156
157public:
158 DLLLOCAL Var(const QoreProgramLocation* loc, const char* n_name, bool is_thread_local = false)
159 : loc(loc), name(n_name), pub(false), finalized(false), is_thread_local(is_thread_local) {
160 }
161
162 DLLLOCAL Var(const QoreProgramLocation* loc, const char* n_name, QoreParseTypeInfo* n_parseTypeInfo,
163 bool is_thread_local = false) : loc(loc), name(n_name), parseTypeInfo(n_parseTypeInfo),
164 pub(false), finalized(false), is_thread_local(is_thread_local) {
165 }
166
167 DLLLOCAL Var(const QoreProgramLocation* loc, const char* n_name, const QoreTypeInfo* n_typeInfo,
168 bool builtin = false, bool is_thread_local = false)
169 : loc(loc), name(n_name), pub(false), finalized(false),
170 is_thread_local(is_thread_local), builtin(builtin) {
171 const QoreTypeInfo* base_ti;
172 no_narrowing = isNoNarrowMarkerType(n_typeInfo, base_ti);
173 typeInfo = base_ti;
174 val.set(base_ti);
175 }
176
178 DLLLOCAL Var(Var* ref, bool ro = false, bool is_thread_local = false, const char* import_as = nullptr);
179
180 DLLLOCAL const char* getName() const;
181
182 DLLLOCAL const std::string& getNameStr() const {
183 return name;
184 }
185
186 DLLLOCAL bool isBuiltin() const {
187 return builtin;
188 }
189
190 DLLLOCAL bool isThreadLocal() const {
191 return is_thread_local;
192 }
193
194 DLLLOCAL bool isGlobal() const {
195 return !is_thread_local;
196 }
197
198 DLLLOCAL int getLValue(LValueHelper& lvh, bool for_remove) const;
199 DLLLOCAL void remove(LValueRemoveHelper& lvrh);
200
201 DLLLOCAL void clearLocal(ExceptionSink* xsink) {
202 QoreLValue<qore_gvar_ref_u>& val = getVal();
203 if (val.type != QV_Ref) {
204 ValueHolder h(xsink);
205 QoreAutoVarRWWriteLocker al(rwl);
206 if (!finalized)
207 finalized = true;
208 printd(5, "Var::clearLocal() clearing '%s' %p\n", name.c_str(), this);
209 {
210 h = val.removeValue(true);
211 }
212 }
213#ifdef DEBUG
214 else
215 printd(5, "Var::clearLocal() skipping imported var '%s' %p\n", name.c_str(), this);
216#endif
217 }
218
219 DLLLOCAL void setInitial(AbstractQoreNode* v) {
220 QoreLValue<qore_gvar_ref_u>& val = getVal();
221 assert(val.type == QV_Node);
222 // try to set an optimized value type for the value holder if possible
223 val.set(typeInfo);
224 discard(val.assignInitial(v), nullptr);
225 }
226
227 DLLLOCAL const Var* parseGetVar() const;
228
229 DLLLOCAL bool isImported() const;
230
231 DLLLOCAL void deref(ExceptionSink* xsink);
232
233 DLLLOCAL QoreValue eval() const;
234
235 DLLLOCAL void doDoubleDeclarationError(const QoreProgramLocation* loc) {
236 // make sure types are identical or throw an exception
237 if (parseTypeInfo) {
238 parse_error(*loc, "global variable '%s' previously declared with type '%s'", name.c_str(),
239 QoreParseTypeInfo::getName(parseTypeInfo));
240 assert(!typeInfo);
241 }
242 if (typeInfo) {
243 parse_error(*loc, "global variable '%s' previously declared with type '%s'", name.c_str(),
244 QoreTypeInfo::getName(typeInfo));
245 assert(!parseTypeInfo);
246 }
247 }
248
249 DLLLOCAL void checkAssignType(const QoreProgramLocation* loc, const QoreTypeInfo *n_typeInfo);
250
251 DLLLOCAL int parseInit() {
252 QoreLValue<qore_gvar_ref_u>& val = getVal();
253
254 if (val.type == QV_Ref) {
255 return 0;
256 }
257
258 int err = 0;
259
260 if (parseTypeInfo) {
261 typeInfo = QoreParseTypeInfo::resolveAndDelete(parseTypeInfo, loc, err);
262 refTypeInfo = QoreTypeInfo::getReferenceTarget(typeInfo);
263 parseTypeInfo = nullptr;
264
265 val.set(typeInfo);
266 }
267
268 // Check if this is a no-narrow marker type (disables type narrowing)
269 const QoreTypeInfo* base_ti;
270 if (isNoNarrowMarkerType(typeInfo, base_ti)) {
271 no_narrowing = true;
272 typeInfo = base_ti;
273 refTypeInfo = QoreTypeInfo::getReferenceTarget(typeInfo);
274 val.set(typeInfo);
275 }
276
277 // Set is_auto_type flag based on the resolved typeInfo
278 is_auto_type = isAutoTypeInfo(typeInfo);
279
280 return err;
281 }
282
283 DLLLOCAL static bool isAutoTypeInfo(const QoreTypeInfo* ti);
284
286 DLLLOCAL static bool isNoNarrowMarkerType(const QoreTypeInfo* ti, const QoreTypeInfo*& base_ti);
287
288 DLLLOCAL QoreParseTypeInfo* copyParseTypeInfo() const {
289 return parseTypeInfo ? parseTypeInfo->copy() : nullptr;
290 }
291
292 DLLLOCAL const QoreTypeInfo* parseGetTypeInfoForInitialAssignment();
293
294 DLLLOCAL const QoreTypeInfo* parseGetTypeInfo();
295
296 DLLLOCAL const QoreTypeInfo* getTypeInfo() const;
297
298 DLLLOCAL bool hasTypeInfo() const;
299
300 DLLLOCAL bool isRef() const;
301
302 // only called with a new object declaration expression (ie our <class> $x())
303 DLLLOCAL const char* getClassName() const;
304
305 DLLLOCAL bool isPublic() const {
306 return pub;
307 }
308
309 DLLLOCAL void setPublic() {
310 assert(!pub);
311 pub = true;
312 }
313
314 DLLLOCAL const QoreProgramLocation* getParseLocation() const {
315 return loc;
316 }
317
318 DLLLOCAL bool isAutoType() const {
319 return is_auto_type;
320 }
321
322 DLLLOCAL bool isNoNarrowing() const {
323 return no_narrowing;
324 }
325
326 DLLLOCAL void setNoNarrowing() {
327 no_narrowing = true;
328 }
329
330 DLLLOCAL void parseSetNarrowedType(const QoreTypeInfo* ti, const QoreProgramLocation* loc = nullptr);
331 DLLLOCAL void parseMergeNarrowedType(const QoreTypeInfo* ti);
332
333 DLLLOCAL const QoreTypeInfo* parseGetNarrowedType() const {
334 return narrowedTypeInfo;
335 }
336
337 DLLLOCAL const QoreProgramLocation* parseGetNarrowedLoc() const {
338 return narrowedLoc;
339 }
340
341 DLLLOCAL void parseResetNarrowedType() {
342 narrowedTypeInfo = nullptr;
343 narrowedLoc = nullptr;
344 }
345};
346
347DLLLOCAL void delete_global_variables();
348
349DLLLOCAL extern QoreHashNode* ENV;
350
351//typedef std::set<const void*> lvid_set_t;
352typedef vector_set_t<const void*> lvid_set_t;
353
354// track obj count changes
355hashdecl ObjCountRec {
356 // container
357 const AbstractQoreNode* con;
358 // initial count (true = possible recursive cycle, false = no cycle possible)
359 bool before;
360
361 DLLLOCAL ObjCountRec(const QoreListNode* c);
362 DLLLOCAL ObjCountRec(const QoreHashNode* c);
363 DLLLOCAL ObjCountRec(const QoreObject* c);
364 DLLLOCAL int getDifference();
365};
366
367typedef std::vector<ObjCountRec> ocvec_t;
368
369// this class grabs global variable or object locks for the duration of the scope of the object
370// no evaluations can be done while this object is in scope or a deadlock may result
371class LValueHelper {
372 friend class LValueRemoveHelper;
373 friend class LValueLockHandoffHelper;
374
375private:
376 // not implemented
377 DLLLOCAL LValueHelper(const LValueHelper&) = delete;
378 DLLLOCAL LValueHelper& operator=(const LValueHelper&) = delete;
379
380protected:
381 DLLLOCAL void assignNodeIntern(AbstractQoreNode* n) {
382 //printd(5, "LValueHelper::assignNodeIntern() this: %p n: %p '%s'\n", this, n, get_type_name(n));
383
384 assert(val || qv);
385 if (val) {
386 val->assign(n);
387 } else {
388 *qv = n;
389 }
390 }
391
392 DLLLOCAL int doListLValue(const QoreSquareBracketsOperatorNode* op, bool for_remove);
393 DLLLOCAL int doListLValue(const QoreSquareBracketsOperatorNode* op, RuntimeConfig& rc, bool for_remove);
394 DLLLOCAL int doHashLValue(qore_type_t t, const char* mem, bool for_remove);
395 DLLLOCAL int doObjLValue(QoreObject* o, const char* mem, bool for_remove);
396 DLLLOCAL int doObjLValue(QoreObject* o, const char* mem, bool for_remove, const qore_class_private* class_ctx);
397 DLLLOCAL int doHashObjLValue(const QoreHashObjectDereferenceOperatorNode* op, bool for_remove);
398 DLLLOCAL int doHashObjLValue(const QoreHashObjectDereferenceOperatorNode* op, RuntimeConfig& rc, bool for_remove);
399
400 DLLLOCAL int makeIntQv(const char* desc);
401 DLLLOCAL int makeIntVal(const char* desc);
402
403 DLLLOCAL int makeFloat(const char* desc);
404 DLLLOCAL int makeNumber(const char* desc);
405
406 DLLLOCAL int doRecursiveException() {
407 vl.xsink->raiseException("REFERENCE-ERROR", "recursive reference detected in assignment");
408 return -1;
409 }
410
411public:
412 AutoVLock vl;
413
414private:
415 typedef std::vector<AbstractQoreNode*> nvec_t;
416 nvec_t tvec;
417 lvid_set_t* lvid_set = nullptr;
418 // to track object count changes
419 ocvec_t ocvec;
420
421 // flag if the changed value was a container before the assignment
422 bool before = false;
423
424 // recursive delta: change to recursive reference count
425 int rdt = 0;
426
427 RObject* robj = nullptr;
428
429public:
430 QoreLValueGeneric* val = nullptr;
431 QoreValue* qv = nullptr;
432 const QoreTypeInfo* typeInfo = nullptr;
433
434 DLLLOCAL LValueHelper(const ReferenceNode& ref, ExceptionSink* xsink, bool for_remove = false);
435 DLLLOCAL LValueHelper(const QoreValue& exp, ExceptionSink* xsink, bool for_remove = false);
436 DLLLOCAL LValueHelper(const ReferenceNode& ref, RuntimeConfig& rc, ExceptionSink* xsink, bool for_remove = false);
437 DLLLOCAL LValueHelper(const QoreValue& exp, RuntimeConfig& rc, ExceptionSink* xsink, bool for_remove = false);
438
439 DLLLOCAL LValueHelper(ExceptionSink* xsink);
440
441 DLLLOCAL LValueHelper(LValueHelper&& o);
442
443 // to scan objects after initialization
444 DLLLOCAL LValueHelper(QoreObject& obj, ExceptionSink* xsink);
445
446 DLLLOCAL ~LValueHelper();
447
448 DLLLOCAL int set(const ReferenceNode& ref, bool for_remove = false);
449
450 DLLLOCAL void setClosure(RObject* c) {
451 robj = c;
452 }
453
454 DLLLOCAL void saveTemp(QoreValue n);
455
456 DLLLOCAL void saveTempRef(QoreValue& n);
457
458 DLLLOCAL int doLValue(const QoreValue& exp, bool for_remove);
459
460 DLLLOCAL int doLValue(const ReferenceNode* ref, bool for_remove);
461 DLLLOCAL int doLValue(const QoreValue& exp, RuntimeConfig& rc, bool for_remove);
462 DLLLOCAL int doLValue(const ReferenceNode* ref, RuntimeConfig& rc, bool for_remove);
463
464 DLLLOCAL void setAndLock(QoreVarRWLock& rwl);
465 DLLLOCAL void set(QoreVarRWLock& rwl);
466
467 DLLLOCAL AutoVLock& getAutoVLock() {
468 return vl;
469 }
470
471 DLLLOCAL void setTypeInfo(const QoreTypeInfo* ti) {
472 //printd(5, "LValueHelper::setTypeInfo() this: %p ti: %s\n", this, QoreTypeInfo::getName(ti));
473
474 typeInfo = ti;
475 }
476
477 DLLLOCAL void setValue(QoreLValueGeneric& nv, const QoreTypeInfo* ti = nullptr) {
478 //printd(5, "LValueHelper::setValue() this: %p nv: %s ti: %s\n", this, nv.getFixedTypeName(),
479 // QoreTypeInfo::getName(ti));
480 assert(!val);
481 assert(!qv);
482 val = &nv;
483
484 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
485
486 typeInfo = ti;
487 }
488
489 DLLLOCAL void setValue(QoreValue& nqv, const QoreTypeInfo* ti = nullptr) {
490 //printd(5, "LValueHelper::setValue() this: %p nqv: %s ti: %s\n", this, nqv.getFullTypeName(),
491 // QoreTypeInfo::getName(ti));
492
493 assert(!val);
494 assert(!qv);
495 qv = &nqv;
496
497 before = needs_scan(nqv);
498
499 typeInfo = ti;
500 }
501
502 DLLLOCAL void resetValue(QoreLValueGeneric& nv, const QoreTypeInfo* ti = nullptr) {
503 //printd(5, "LValueHelper::resetValue() this: %p new val: %p ti: %s\n", this, &nv, QoreTypeInfo::getName(ti));
504
505 if (qv) {
506 qv = nullptr;
507 } else {
508 assert(val);
509 }
510 val = &nv;
511
512 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
513
514 typeInfo = ti;
515 }
516
517 DLLLOCAL void resetValue(QoreValue& nqv, const QoreTypeInfo* ti = nullptr) {
518 //printd(5, "LValueHelper::resetValue() this: %p nqv: %s ti: %s\n", this, nqv.getFullTypeName(),
519 // QoreTypeInfo::getName(ti));
520 if (val) {
521 val = nullptr;
522 } else {
523 assert(qv);
524 }
525 qv = &nqv;
526
527 before = needs_scan(nqv);
528
529 typeInfo = ti;
530 }
531
532 DLLLOCAL void clearPtr() {
533 if (val) {
534 val = nullptr;
535 } else if (qv) {
536 qv = nullptr;
537 }
538 typeInfo = nullptr;
539 before = false;
540 }
541
542 DLLLOCAL operator bool() const {
543 return val || qv;
544 }
545
546 DLLLOCAL bool isOptimized() const {
547 return val && val->optimized();
548 }
549
550 DLLLOCAL const QoreTypeInfo* getTypeInfo() const {
551 return typeInfo;
552 }
553
554 DLLLOCAL qore_type_t getType() const {
555 return val ? val->getType() : qv->getType();
556 }
557
558 DLLLOCAL const ReferenceNode* getReference() const {
559 if (val) {
560 return val->getReference();
561 }
562 assert(qv);
563 return qv->getType() == NT_REFERENCE ? qv->get<const ReferenceNode>() : nullptr;
564 }
565
566 DLLLOCAL const QoreValue getValue() const {
567 return val ? val->getValue() : *qv;
568 }
569
570 DLLLOCAL QoreValue getValue() {
571 return val ? val->getValue() : *qv;
572 }
573
574 DLLLOCAL AbstractQoreNode* getNodeValue() {
575 assert((val && val->getInternalNode()) || (qv && qv->getInternalNode()));
576 return val ? val->getInternalNode() : qv->getInternalNode();
577 }
578
579 DLLLOCAL const char* getTypeName() const {
580 return val ? val->getTypeName() : qv->getTypeName();
581 }
582
583 DLLLOCAL bool checkType(const qore_type_t t) const {
584 return getType() == t;
585 }
586
587 DLLLOCAL bool isNothing() const {
588 return checkType(NT_NOTHING);
589 }
590
591 DLLLOCAL void setObjectContext(qore_object_private* obj);
592
593 DLLLOCAL QoreValue getReferencedValue() const;
594
595 // only call if there is a reference-counted AbstractQoreNode value in place
596 // FIXME: port operators to LValueHelper instead and remove this function
597 DLLLOCAL void ensureUnique() {
598 AbstractQoreNode* current_value = getNodeValue();
599 assert(current_value && current_value->getType() != NT_OBJECT);
600
601 if (!current_value->is_unique()) {
602 //printd(5, "LValueHelper::ensureUnique() this: %p saving old value: %p '%s'\n", this, current_value, get_type_name(current_value));
603 AbstractQoreNode* old = current_value;
604 assignNodeIntern(current_value->realCopy());
605 saveTemp(old);
606 }
607 }
608
609 DLLLOCAL int64 getAsBigInt() const;
610 DLLLOCAL bool getAsBool() const;
611 DLLLOCAL double getAsFloat() const;
612
613 DLLLOCAL int64 plusEqualsBigInt(int64 v, const char* desc = "<lvalue>");
614 DLLLOCAL int64 minusEqualsBigInt(int64 v, const char* desc = "<lvalue>");
615 DLLLOCAL int64 multiplyEqualsBigInt(int64 v, const char* desc = "<lvalue>");
616 DLLLOCAL int64 divideEqualsBigInt(int64 v, const char* desc = "<lvalue>");
617 DLLLOCAL int64 orEqualsBigInt(int64 v, const char* desc = "<lvalue>");
618 DLLLOCAL int64 andEqualsBigInt(int64 v, const char* desc = "<lvalue>");
619 DLLLOCAL int64 xorEqualsBigInt(int64 v, const char* desc = "<lvalue>");
620 DLLLOCAL int64 modulaEqualsBigInt(int64 v, const char* desc = "<lvalue>");
621 DLLLOCAL int64 shiftLeftEqualsBigInt(int64 v, const char* desc = "<lvalue>");
622 DLLLOCAL int64 shiftRightEqualsBigInt(int64 v, const char* desc = "<lvalue>");
623 DLLLOCAL int64 preIncrementBigInt(const char* desc = "<lvalue>");
624 DLLLOCAL int64 preDecrementBigInt(const char* desc = "<lvalue>");
625 DLLLOCAL int64 postIncrementBigInt(const char* desc = "<lvalue>");
626 DLLLOCAL int64 postDecrementBigInt(const char* desc = "<lvalue>");
627
628 DLLLOCAL double plusEqualsFloat(double v, const char* desc = "<lvalue>");
629 DLLLOCAL double minusEqualsFloat(double v, const char* desc = "<lvalue>");
630 DLLLOCAL double multiplyEqualsFloat(double v, const char* desc = "<lvalue>");
631 DLLLOCAL double divideEqualsFloat(double v, const char* desc = "<lvalue>");
632 DLLLOCAL double preIncrementFloat(const char* desc = "<lvalue>");
633 DLLLOCAL double preDecrementFloat(const char* desc = "<lvalue>");
634 DLLLOCAL double postIncrementFloat(const char* desc = "<lvalue>");
635 DLLLOCAL double postDecrementFloat(const char* desc = "<lvalue>");
636
637 DLLLOCAL void plusEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
638 DLLLOCAL void minusEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
639 DLLLOCAL void multiplyEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
640 DLLLOCAL void divideEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
641 DLLLOCAL void preIncrementNumber(const char* desc = "<lvalue>");
642 DLLLOCAL void preDecrementNumber(const char* desc = "<lvalue>");
643 DLLLOCAL QoreNumberNode* postIncrementNumber(bool ref_rv, const char* desc = "<lvalue>");
644 DLLLOCAL QoreNumberNode* postDecrementNumber(bool ref_rv, const char* desc = "<lvalue>");
645
646 DLLLOCAL QoreNumberNode* ensureUniqueNumber(const char* desc = "<lvalue>") {
647 if (makeNumber(desc))
648 return nullptr;
649
650 if (val) {
651 // For QoreLValue, we can use direct access to v.n
652 AbstractQoreNode** p = &val->v.n;
653 assert(get_node_type(*p) == NT_NUMBER);
654 if (!(*p)->is_unique()) {
655 AbstractQoreNode* old = (*p);
656 (*p) = (*p)->realCopy();
657 saveTemp(old);
658 }
659 return reinterpret_cast<QoreNumberNode*>(*p);
660 }
661 else {
662 // For QoreValue, we need to use accessor methods
663 assert(qv);
664 AbstractQoreNode* node = qv->getInternalNode();
665 assert(get_node_type(node) == NT_NUMBER);
666 if (!node->is_unique()) {
667 AbstractQoreNode* old = node;
668 node = node->realCopy();
669 saveTemp(old);
670 // Update qv to point to the new node
671 qv->set(node);
672 }
673 return reinterpret_cast<QoreNumberNode*>(node);
674 }
675 }
676
677 DLLLOCAL int assign(QoreValue val, const char* desc = "<lvalue>", bool check_types = true, bool weak_assignment = false);
678
679 DLLLOCAL QoreValue removeValue(bool for_del);
680 DLLLOCAL QoreValue remove(bool& static_assignment);
681
682 DLLLOCAL void setDelta(int dt) {
683 assert(!rdt);
684 rdt = dt;
685 }
686};
687
688class LValueRemoveHelper {
689private:
690 // not implemented
691 LValueRemoveHelper(const LValueRemoveHelper&) = delete;
692 LValueRemoveHelper& operator=(const LValueRemoveHelper&) = delete;
693 void* operator new(size_t) = delete;
694
695 DLLLOCAL void doRemove(const QoreSquareBracketsOperatorNode* op);
696 DLLLOCAL void doRemove(const QoreSquareBracketsOperatorNode* op, const QoreParseListNode* l);
697 DLLLOCAL void doRemove(const QoreSquareBracketsRangeOperatorNode* op);
698
699protected:
700 ExceptionSink* xsink;
701 QoreLValueGeneric rv;
702 bool for_del,
703 direct_list = false;
704
705public:
706 DLLLOCAL LValueRemoveHelper(const ReferenceNode& ref, ExceptionSink* n_xsink, bool fd);
707 DLLLOCAL LValueRemoveHelper(const QoreValue& exp, ExceptionSink* n_xsink, bool fd);
708
709 DLLLOCAL void doRemove(QoreValue exp);
710
711 DLLLOCAL operator bool() const {
712 return !*xsink;
713 }
714
715 DLLLOCAL ExceptionSink* getExceptionSink() const {
716 return xsink;
717 }
718
719 DLLLOCAL bool forDel() const {
720 return for_del;
721 }
722
723 DLLLOCAL void doRemove(QoreLValueGeneric& qv, const QoreTypeInfo* ti) {
724 rv.assignSetTakeInitial(qv);
725 }
726
727 DLLLOCAL QoreValue removeValue();
728 DLLLOCAL QoreValue remove(bool& static_assignment);
729
730 DLLLOCAL void deleteLValue();
731};
732
733hashdecl lvinfo {
734 QoreLValueGeneric* val;
735 const QoreTypeInfo* typeInfo;
736
737 DLLLOCAL lvinfo(QoreLValueGeneric* val, const QoreTypeInfo* typeInfo) : val(val), typeInfo(typeInfo) {
738 }
739};
740
741#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
The base class for all value and parse types in Qore expression trees.
Definition AbstractQoreNode.h:60
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:204
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
Provides atomic reference counting to Qore objects.
Definition QoreReferenceCounter.h:44
DLLEXPORT bool is_unique() const
Returns true if the reference count is 1.
The main value class in Qore, designed to be passed by value.
Definition QoreValue.h:264
DLLEXPORT const char * getTypeName() const
Returns the type name as a string.
DLLLOCAL void set(int64 i)
Sets an integer value (any current value is overwritten without dereferencing)
Definition QoreValue.h:568
DLLEXPORT qore_type_t getType() const
Returns the type code of the value.
DLLLOCAL std::enable_if< std::is_pointer< T >::value, T >::type get()
Definition QoreValue.h:658
DLLEXPORT AbstractQoreNode * getInternalNode()
Returns the internal AbstractQoreNode pointer (nullptr if not a node type)
parse type: reference to a lvalue expression
Definition ReferenceNode.h:47
Runtime configuration passed through the evaluation call chain.
Definition RuntimeConfig.h:49
holds an object and dereferences it in the destructor
Definition QoreValue.h:846
int16_t qore_type_t
used to identify unique Qore data and parse types (descendents of AbstractQoreNode)
Definition common.h:77
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:267
#define QV_Node
for heap-allocated values
Definition QoreValue.h:58
#define QV_Ref
for references (when used with lvalues)
Definition QoreValue.h:59
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