32 #ifndef _QORE_VARIABLE_H
33 #define _QORE_VARIABLE_H
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"
59 class ScopedObjectCallNode;
60 class QoreSquareBracketsOperatorNode;
61 class QoreSquareBracketsRangeOperatorNode;
62 class QoreHashObjectDereferenceOperatorNode;
64 union qore_gvar_ref_u {
72 DLLLOCAL
void setPtr(Var* refptr,
bool readonly =
false) {
73 _refptr = (size_t)refptr;
78 DLLLOCAL Var* getPtr()
const {
79 #ifndef HAVE_LLVM_BUG_22050
82 return (Var*)((_refptr & 1L) ? (_refptr ^ 1L) : _refptr);
84 return (Var*)(_refptr & (~1L));
88 DLLLOCAL
bool isReadOnly()
const {
96 DLLLOCAL
void get_thread_local_lvalue(
void* ptr, QoreLValue<qore_gvar_ref_u>*& lvar,
bool& is_new,
bool& finalized);
99 class LValueRemoveHelper;
105 const QoreProgramLocation* loc;
106 QoreLValue<qore_gvar_ref_u> val;
108 mutable QoreVarRWLock rwl;
109 QoreParseTypeInfo* parseTypeInfo =
nullptr;
110 const QoreTypeInfo* typeInfo =
nullptr;
111 const QoreTypeInfo* refTypeInfo =
nullptr;
113 mutable bool finalized;
114 bool is_thread_local;
118 Var(
const Var&) =
delete;
121 bool builtin =
false;
123 DLLLOCAL ~Var() {
delete parseTypeInfo; }
127 xsink->
raiseException(
"DESTRUCTOR-ERROR",
"illegal variable assignment after second phase of variable " \
134 QoreLValue<qore_gvar_ref_u>& getVal()
const {
135 if (is_thread_local) {
136 QoreLValue<qore_gvar_ref_u>* lvar;
138 get_thread_local_lvalue((
void*)
this, lvar, is_new, finalized);
140 if (val.type == QV_Ref) {
142 lvar->v.setPtr(val.v.getPtr(), val.v.isReadOnly());
143 }
else if (typeInfo) {
149 return const_cast<QoreLValue<qore_gvar_ref_u>&
>(val);
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) {
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) {
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) {
167 DLLLOCAL Var(Var* ref,
bool ro =
false,
bool is_thread_local =
false);
169 DLLLOCAL
const char* getName()
const;
171 DLLLOCAL
const std::string& getNameStr()
const {
175 DLLLOCAL
bool isBuiltin()
const {
179 DLLLOCAL
bool isThreadLocal()
const {
180 return is_thread_local;
183 DLLLOCAL
bool isGlobal()
const {
184 return !is_thread_local;
187 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove)
const;
188 DLLLOCAL
void remove(LValueRemoveHelper& lvrh);
191 QoreLValue<qore_gvar_ref_u>& val = getVal();
192 if (val.type != QV_Ref) {
194 QoreAutoVarRWWriteLocker al(rwl);
197 printd(5,
"Var::clearLocal() clearing '%s' %p\n", name.c_str(),
this);
202 h = val.assign(QoreTypeInfo::getDefaultQoreValue(typeInfo));
204 h = val.removeValue(
true);
210 printd(5,
"Var::clearLocal() skipping imported var '%s' %p\n", name.c_str(),
this);
215 QoreLValue<qore_gvar_ref_u>& val = getVal();
216 assert(val.type == QV_Node);
219 discard(val.assignInitial(v),
nullptr);
222 DLLLOCAL
const Var* parseGetVar()
const;
224 DLLLOCAL
bool isImported()
const;
230 DLLLOCAL
void doDoubleDeclarationError(
const QoreProgramLocation* loc) {
233 parse_error(*loc,
"global variable '%s' previously declared with type '%s'", name.c_str(), QoreParseTypeInfo::getName(parseTypeInfo));
237 parse_error(*loc,
"global variable '%s' previously declared with type '%s'", name.c_str(), QoreTypeInfo::getName(typeInfo));
238 assert(!parseTypeInfo);
242 DLLLOCAL
void checkAssignType(
const QoreProgramLocation* loc,
const QoreTypeInfo *n_typeInfo);
244 DLLLOCAL
int parseInit() {
245 QoreLValue<qore_gvar_ref_u>& val = getVal();
247 if (val.type == QV_Ref)
253 typeInfo = QoreParseTypeInfo::resolveAndDelete(parseTypeInfo, loc, err);
254 refTypeInfo = QoreTypeInfo::getReferenceTarget(typeInfo);
255 parseTypeInfo =
nullptr;
261 discard(val.assignInitial(QoreTypeInfo::getDefaultQoreValue(typeInfo)),
nullptr);
267 DLLLOCAL QoreParseTypeInfo* copyParseTypeInfo()
const {
268 return parseTypeInfo ? parseTypeInfo->copy() :
nullptr;
271 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfoForInitialAssignment();
273 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfo();
275 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const;
277 DLLLOCAL
bool hasTypeInfo()
const;
279 DLLLOCAL
bool isRef()
const;
282 DLLLOCAL
const char* getClassName()
const;
284 DLLLOCAL
bool isPublic()
const {
288 DLLLOCAL
void setPublic() {
293 DLLLOCAL
const QoreProgramLocation* getParseLocation()
const {
298 DLLLOCAL
void delete_global_variables();
303 typedef vector_set_t<const void*> lvid_set_t;
306 hashdecl ObjCountRec {
315 DLLLOCAL
int getDifference();
318 typedef std::vector<ObjCountRec> ocvec_t;
323 friend class LValueRemoveHelper;
324 friend class LValueLockHandoffHelper;
328 DLLLOCAL LValueHelper(
const LValueHelper&) =
delete;
329 DLLLOCAL LValueHelper& operator=(
const LValueHelper&) =
delete;
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);
346 DLLLOCAL
int makeInt(
const char* desc);
347 DLLLOCAL
int makeFloat(
const char* desc);
348 DLLLOCAL
int makeNumber(
const char* desc);
350 DLLLOCAL
int doRecursiveException() {
351 vl.xsink->raiseException(
"REFERENCE-ERROR",
"recursive reference detected in assignment");
360 typedef std::vector<AbstractQoreNode*> nvec_t;
362 lvid_set_t* lvid_set =
nullptr;
372 RObject* robj =
nullptr;
375 QoreLValueGeneric* val =
nullptr;
377 const QoreTypeInfo* typeInfo =
nullptr;
384 DLLLOCAL LValueHelper(LValueHelper&& o);
389 DLLLOCAL ~LValueHelper();
391 DLLLOCAL
void setClosure(RObject* c) {
399 return tvec[tvec.size() - 1];
402 DLLLOCAL
int doLValue(
const QoreValue exp,
bool for_remove);
404 DLLLOCAL
int doLValue(
const ReferenceNode* ref,
bool for_remove);
406 DLLLOCAL
void setAndLock(QoreVarRWLock& rwl);
407 DLLLOCAL
void set(QoreVarRWLock& rwl);
413 DLLLOCAL
void setTypeInfo(
const QoreTypeInfo* ti) {
417 DLLLOCAL
void setValue(QoreLValueGeneric& nv,
const QoreTypeInfo* ti =
nullptr) {
424 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
429 DLLLOCAL
void setValue(
QoreValue& nqv,
const QoreTypeInfo* ti =
nullptr) {
435 before = needs_scan(nqv);
440 DLLLOCAL
void resetValue(QoreLValueGeneric& nv,
const QoreTypeInfo* ti =
nullptr) {
450 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
455 DLLLOCAL
void resetValue(
QoreValue& nqv,
const QoreTypeInfo* ti =
nullptr) {
465 before = needs_scan(nqv);
470 DLLLOCAL
void clearPtr() {
479 DLLLOCAL
operator bool()
const {
483 DLLLOCAL
bool isOptimized()
const {
484 return val && val->optimized();
487 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const {
492 return val ? val->getType() : qv->getType();
495 DLLLOCAL
const QoreValue getValue()
const {
496 return val ? val->getValue() : *qv;
500 return val ? val->getValue() : *qv;
504 assert((val && val->getInternalNode()) || (qv && qv->getInternalNode()));
505 return val ? val->getInternalNode() : qv->getInternalNode();
508 DLLLOCAL
const char* getTypeName()
const {
509 return val ? val->getTypeName() : qv->getTypeName();
512 DLLLOCAL
bool checkType(
const qore_type_t t)
const {
513 return getType() == t;
516 DLLLOCAL
bool isNothing()
const {
520 DLLLOCAL
void setObjectContext(qore_object_private* obj);
522 DLLLOCAL
QoreValue getReferencedValue()
const;
526 DLLLOCAL
void ensureUnique() {
533 assignNodeIntern(current_value->
realCopy());
538 DLLLOCAL
int64 getAsBigInt()
const;
539 DLLLOCAL
bool getAsBool()
const;
540 DLLLOCAL
double getAsFloat()
const;
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>");
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>");
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>");
575 DLLLOCAL
QoreNumberNode* ensureUniqueNumber(
const char* desc =
"<lvalue>") {
578 if (makeNumber(desc))
584 if (makeNumber(desc))
590 if (!(*p)->is_unique()) {
598 DLLLOCAL
int assign(
QoreValue val,
const char* desc =
"<lvalue>",
bool check_types =
true,
bool weak_assignment =
false);
600 DLLLOCAL
QoreValue removeValue(
bool for_del);
601 DLLLOCAL
QoreValue remove(
bool& static_assignment);
603 DLLLOCAL
void setDelta(
int dt) {
609 class LValueRemoveHelper {
612 LValueRemoveHelper(
const LValueRemoveHelper&) =
delete;
613 LValueRemoveHelper& operator=(
const LValueRemoveHelper&) =
delete;
614 void*
operator new(size_t) =
delete;
616 DLLLOCAL
void doRemove(
const QoreSquareBracketsOperatorNode* op);
617 DLLLOCAL
void doRemove(
const QoreSquareBracketsOperatorNode* op,
const QoreParseListNode* l);
618 DLLLOCAL
void doRemove(
const QoreSquareBracketsRangeOperatorNode* op);
622 QoreLValueGeneric rv;
632 DLLLOCAL
operator bool()
const {
640 DLLLOCAL
bool forDel()
const {
644 DLLLOCAL
void doRemove(QoreLValueGeneric& qv,
const QoreTypeInfo* ti) {
648 rv.assignSetTakeInitial(qv, QoreTypeInfo::getDefaultQoreValue(ti));
650 rv.assignSetTakeInitial(qv);
655 DLLLOCAL
QoreValue remove(
bool& static_assignment);
657 DLLLOCAL
void deleteLValue();
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