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