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