Qore Programming Language  1.12.0
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  }
445  else {
446  assert(val);
447  }
448  val = &nv;
449 
450  before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
451 
452  typeInfo = ti;
453  }
454 
455  DLLLOCAL void resetValue(QoreValue& nqv, const QoreTypeInfo* ti = nullptr) {
456  //printd(5, "LValueHelper::resetValue() this: %p new qv: %p\n", this, &nqv);
457  if (val) {
458  val = nullptr;
459  }
460  else {
461  assert(qv);
462  }
463  qv = &nqv;
464 
465  before = needs_scan(nqv);
466 
467  typeInfo = ti;
468  }
469 
470  DLLLOCAL void clearPtr() {
471  if (val)
472  val = nullptr;
473  else if (qv)
474  qv = nullptr;
475  typeInfo = nullptr;
476  before = false;
477  }
478 
479  DLLLOCAL operator bool() const {
480  return val || qv;
481  }
482 
483  DLLLOCAL bool isOptimized() const {
484  return val && val->optimized();
485  }
486 
487  DLLLOCAL const QoreTypeInfo* getTypeInfo() const {
488  return typeInfo;
489  }
490 
491  DLLLOCAL qore_type_t getType() const {
492  return val ? val->getType() : qv->getType();
493  }
494 
495  DLLLOCAL const QoreValue getValue() const {
496  return val ? val->getValue() : *qv;
497  }
498 
499  DLLLOCAL QoreValue getValue() {
500  return val ? val->getValue() : *qv;
501  }
502 
503  DLLLOCAL AbstractQoreNode* getNodeValue() {
504  assert((val && val->getInternalNode()) || (qv && qv->getInternalNode()));
505  return val ? val->getInternalNode() : qv->getInternalNode();
506  }
507 
508  DLLLOCAL const char* getTypeName() const {
509  return val ? val->getTypeName() : qv->getTypeName();
510  }
511 
512  DLLLOCAL bool checkType(const qore_type_t t) const {
513  return getType() == t;
514  }
515 
516  DLLLOCAL bool isNothing() const {
517  return checkType(NT_NOTHING);
518  }
519 
520  DLLLOCAL void setObjectContext(qore_object_private* obj);
521 
522  DLLLOCAL QoreValue getReferencedValue() const;
523 
524  // only call if there is a reference-counted AbstractQoreNode value in place
525  // FIXME: port operators to LValueHelper instead and remove this function
526  DLLLOCAL void ensureUnique() {
527  AbstractQoreNode* current_value = getNodeValue();
528  assert(current_value && current_value->getType() != NT_OBJECT);
529 
530  if (!current_value->is_unique()) {
531  //printd(5, "LValueHelper::ensureUnique() this: %p saving old value: %p '%s'\n", this, current_value, get_type_name(current_value));
532  AbstractQoreNode* old = current_value;
533  assignNodeIntern(current_value->realCopy());
534  saveTemp(old);
535  }
536  }
537 
538  DLLLOCAL int64 getAsBigInt() const;
539  DLLLOCAL bool getAsBool() const;
540  DLLLOCAL double getAsFloat() const;
541 
542  DLLLOCAL int64 plusEqualsBigInt(int64 v, const char* desc = "<lvalue>");
543  DLLLOCAL int64 minusEqualsBigInt(int64 v, const char* desc = "<lvalue>");
544  DLLLOCAL int64 multiplyEqualsBigInt(int64 v, const char* desc = "<lvalue>");
545  DLLLOCAL int64 divideEqualsBigInt(int64 v, const char* desc = "<lvalue>");
546  DLLLOCAL int64 orEqualsBigInt(int64 v, const char* desc = "<lvalue>");
547  DLLLOCAL int64 andEqualsBigInt(int64 v, const char* desc = "<lvalue>");
548  DLLLOCAL int64 xorEqualsBigInt(int64 v, const char* desc = "<lvalue>");
549  DLLLOCAL int64 modulaEqualsBigInt(int64 v, const char* desc = "<lvalue>");
550  DLLLOCAL int64 shiftLeftEqualsBigInt(int64 v, const char* desc = "<lvalue>");
551  DLLLOCAL int64 shiftRightEqualsBigInt(int64 v, const char* desc = "<lvalue>");
552  DLLLOCAL int64 preIncrementBigInt(const char* desc = "<lvalue>");
553  DLLLOCAL int64 preDecrementBigInt(const char* desc = "<lvalue>");
554  DLLLOCAL int64 postIncrementBigInt(const char* desc = "<lvalue>");
555  DLLLOCAL int64 postDecrementBigInt(const char* desc = "<lvalue>");
556 
557  DLLLOCAL double plusEqualsFloat(double v, const char* desc = "<lvalue>");
558  DLLLOCAL double minusEqualsFloat(double v, const char* desc = "<lvalue>");
559  DLLLOCAL double multiplyEqualsFloat(double v, const char* desc = "<lvalue>");
560  DLLLOCAL double divideEqualsFloat(double v, const char* desc = "<lvalue>");
561  DLLLOCAL double preIncrementFloat(const char* desc = "<lvalue>");
562  DLLLOCAL double preDecrementFloat(const char* desc = "<lvalue>");
563  DLLLOCAL double postIncrementFloat(const char* desc = "<lvalue>");
564  DLLLOCAL double postDecrementFloat(const char* desc = "<lvalue>");
565 
566  DLLLOCAL void plusEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
567  DLLLOCAL void minusEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
568  DLLLOCAL void multiplyEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
569  DLLLOCAL void divideEqualsNumber(QoreValue r, const char* desc = "<lvalue>");
570  DLLLOCAL void preIncrementNumber(const char* desc = "<lvalue>");
571  DLLLOCAL void preDecrementNumber(const char* desc = "<lvalue>");
572  DLLLOCAL QoreNumberNode* postIncrementNumber(bool ref_rv, const char* desc = "<lvalue>");
573  DLLLOCAL QoreNumberNode* postDecrementNumber(bool ref_rv, const char* desc = "<lvalue>");
574 
575  DLLLOCAL QoreNumberNode* ensureUniqueNumber(const char* desc = "<lvalue>") {
576  AbstractQoreNode** p;
577  if (val) {
578  if (makeNumber(desc))
579  return nullptr;
580  p = &val->v.n;
581  }
582  else {
583  assert(qv);
584  if (makeNumber(desc))
585  return nullptr;
586  p = &qv->v.n;
587  }
588 
589  assert(get_node_type(*p) == NT_NUMBER);
590  if (!(*p)->is_unique()) {
591  AbstractQoreNode* old = (*p);
592  (*p) = (*p)->realCopy();
593  saveTemp(old);
594  }
595  return reinterpret_cast<QoreNumberNode*>(*p);
596  }
597 
598  DLLLOCAL int assign(QoreValue val, const char* desc = "<lvalue>", bool check_types = true, bool weak_assignment = false);
599 
600  DLLLOCAL QoreValue removeValue(bool for_del);
601  DLLLOCAL QoreValue remove(bool& static_assignment);
602 
603  DLLLOCAL void setDelta(int dt) {
604  assert(!rdt);
605  rdt = dt;
606  }
607 };
608 
609 class LValueRemoveHelper {
610 private:
611  // not implemented
612  LValueRemoveHelper(const LValueRemoveHelper&) = delete;
613  LValueRemoveHelper& operator=(const LValueRemoveHelper&) = delete;
614  void* operator new(size_t) = delete;
615 
616  DLLLOCAL void doRemove(const QoreSquareBracketsOperatorNode* op);
617  DLLLOCAL void doRemove(const QoreSquareBracketsOperatorNode* op, const QoreParseListNode* l);
618  DLLLOCAL void doRemove(const QoreSquareBracketsRangeOperatorNode* op);
619 
620 protected:
621  ExceptionSink* xsink;
622  QoreLValueGeneric rv;
623  bool for_del,
624  direct_list = false;
625 
626 public:
627  DLLLOCAL LValueRemoveHelper(const ReferenceNode& ref, ExceptionSink* n_xsink, bool fd);
628  DLLLOCAL LValueRemoveHelper(const QoreValue exp, ExceptionSink* n_xsink, bool fd);
629 
630  DLLLOCAL void doRemove(QoreValue exp);
631 
632  DLLLOCAL operator bool() const {
633  return !*xsink;
634  }
635 
636  DLLLOCAL ExceptionSink* getExceptionSink() const {
637  return xsink;
638  }
639 
640  DLLLOCAL bool forDel() const {
641  return for_del;
642  }
643 
644  DLLLOCAL void doRemove(QoreLValueGeneric& qv, const QoreTypeInfo* ti) {
645  QoreProgram* pgm = getProgram();
646  // when Qore is terminating, this may be nullptr
647  if (pgm && (pgm->getParseOptions64() & PO_STRICT_TYPES)) {
648  rv.assignSetTakeInitial(qv, QoreTypeInfo::getDefaultQoreValue(ti));
649  } else {
650  rv.assignSetTakeInitial(qv);
651  }
652  }
653 
654  DLLLOCAL QoreValue removeValue();
655  DLLLOCAL QoreValue remove(bool& static_assignment);
656 
657  DLLLOCAL void deleteLValue();
658 };
659 
660 #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