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"
59class ScopedObjectCallNode;
60class QoreSquareBracketsOperatorNode;
61class QoreSquareBracketsRangeOperatorNode;
62class QoreHashObjectDereferenceOperatorNode;
65union qore_gvar_ref_u {
73 DLLLOCAL
void setPtr(Var* refptr,
bool readonly =
false) {
74 _refptr = (size_t)refptr;
79 DLLLOCAL Var* getPtr()
const {
80#ifndef HAVE_LLVM_BUG_22050
83 return (Var*)((_refptr & 1L) ? (_refptr ^ 1L) : _refptr);
85 return (Var*)(_refptr & (~1L));
89 DLLLOCAL
bool isReadOnly()
const {
97DLLLOCAL
void get_thread_local_lvalue(
void* ptr, QoreLValue<qore_gvar_ref_u>*& lvar,
bool& is_new,
bool& finalized);
100class LValueRemoveHelper;
106 const QoreProgramLocation* loc;
107 QoreLValue<qore_gvar_ref_u> val;
109 mutable QoreVarRWLock rwl;
110 QoreParseTypeInfo* parseTypeInfo =
nullptr;
111 const QoreTypeInfo* typeInfo =
nullptr;
112 const QoreTypeInfo* refTypeInfo =
nullptr;
113 const QoreTypeInfo* narrowedTypeInfo =
nullptr;
114 const QoreProgramLocation* narrowedLoc =
nullptr;
115 bool is_auto_type =
false;
116 bool no_narrowing =
false;
118 mutable bool finalized;
119 bool is_thread_local;
123 Var(
const Var&) =
delete;
126 bool builtin =
false;
128 DLLLOCAL ~Var() {
delete parseTypeInfo; }
132 xsink->
raiseException(
"DESTRUCTOR-ERROR",
"illegal variable assignment after second phase of variable " \
139 QoreLValue<qore_gvar_ref_u>& getVal()
const {
140 if (is_thread_local) {
141 QoreLValue<qore_gvar_ref_u>* lvar;
143 get_thread_local_lvalue((
void*)
this, lvar, is_new, finalized);
147 lvar->v.setPtr(val.v.getPtr(), val.v.isReadOnly());
148 }
else if (typeInfo) {
154 return const_cast<QoreLValue<qore_gvar_ref_u>&
>(val);
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) {
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) {
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);
178 DLLLOCAL Var(Var* ref,
bool ro =
false,
bool is_thread_local =
false,
const char* import_as =
nullptr);
180 DLLLOCAL
const char* getName()
const;
182 DLLLOCAL
const std::string& getNameStr()
const {
186 DLLLOCAL
bool isBuiltin()
const {
190 DLLLOCAL
bool isThreadLocal()
const {
191 return is_thread_local;
194 DLLLOCAL
bool isGlobal()
const {
195 return !is_thread_local;
198 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove)
const;
199 DLLLOCAL
void remove(LValueRemoveHelper& lvrh);
202 QoreLValue<qore_gvar_ref_u>& val = getVal();
205 QoreAutoVarRWWriteLocker al(rwl);
208 printd(5,
"Var::clearLocal() clearing '%s' %p\n", name.c_str(),
this);
210 h = val.removeValue(
true);
215 printd(5,
"Var::clearLocal() skipping imported var '%s' %p\n", name.c_str(),
this);
220 QoreLValue<qore_gvar_ref_u>& val = getVal();
224 discard(val.assignInitial(v),
nullptr);
227 DLLLOCAL
const Var* parseGetVar()
const;
229 DLLLOCAL
bool isImported()
const;
235 DLLLOCAL
void doDoubleDeclarationError(
const QoreProgramLocation* loc) {
238 parse_error(*loc,
"global variable '%s' previously declared with type '%s'", name.c_str(),
239 QoreParseTypeInfo::getName(parseTypeInfo));
243 parse_error(*loc,
"global variable '%s' previously declared with type '%s'", name.c_str(),
244 QoreTypeInfo::getName(typeInfo));
245 assert(!parseTypeInfo);
249 DLLLOCAL
void checkAssignType(
const QoreProgramLocation* loc,
const QoreTypeInfo *n_typeInfo);
251 DLLLOCAL
int parseInit() {
252 QoreLValue<qore_gvar_ref_u>& val = getVal();
261 typeInfo = QoreParseTypeInfo::resolveAndDelete(parseTypeInfo, loc, err);
262 refTypeInfo = QoreTypeInfo::getReferenceTarget(typeInfo);
263 parseTypeInfo =
nullptr;
269 const QoreTypeInfo* base_ti;
270 if (isNoNarrowMarkerType(typeInfo, base_ti)) {
273 refTypeInfo = QoreTypeInfo::getReferenceTarget(typeInfo);
278 is_auto_type = isAutoTypeInfo(typeInfo);
283 DLLLOCAL
static bool isAutoTypeInfo(
const QoreTypeInfo* ti);
286 DLLLOCAL
static bool isNoNarrowMarkerType(
const QoreTypeInfo* ti,
const QoreTypeInfo*& base_ti);
288 DLLLOCAL QoreParseTypeInfo* copyParseTypeInfo()
const {
289 return parseTypeInfo ? parseTypeInfo->copy() :
nullptr;
292 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfoForInitialAssignment();
294 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfo();
296 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const;
298 DLLLOCAL
bool hasTypeInfo()
const;
300 DLLLOCAL
bool isRef()
const;
303 DLLLOCAL
const char* getClassName()
const;
305 DLLLOCAL
bool isPublic()
const {
309 DLLLOCAL
void setPublic() {
314 DLLLOCAL
const QoreProgramLocation* getParseLocation()
const {
318 DLLLOCAL
bool isAutoType()
const {
322 DLLLOCAL
bool isNoNarrowing()
const {
326 DLLLOCAL
void setNoNarrowing() {
330 DLLLOCAL
void parseSetNarrowedType(
const QoreTypeInfo* ti,
const QoreProgramLocation* loc =
nullptr);
331 DLLLOCAL
void parseMergeNarrowedType(
const QoreTypeInfo* ti);
333 DLLLOCAL
const QoreTypeInfo* parseGetNarrowedType()
const {
334 return narrowedTypeInfo;
337 DLLLOCAL
const QoreProgramLocation* parseGetNarrowedLoc()
const {
341 DLLLOCAL
void parseResetNarrowedType() {
342 narrowedTypeInfo =
nullptr;
343 narrowedLoc =
nullptr;
347DLLLOCAL
void delete_global_variables();
352typedef vector_set_t<const void*> lvid_set_t;
355hashdecl ObjCountRec {
364 DLLLOCAL
int getDifference();
367typedef std::vector<ObjCountRec> ocvec_t;
372 friend class LValueRemoveHelper;
373 friend class LValueLockHandoffHelper;
377 DLLLOCAL LValueHelper(
const LValueHelper&) =
delete;
378 DLLLOCAL LValueHelper& operator=(
const LValueHelper&) =
delete;
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);
400 DLLLOCAL
int makeIntQv(
const char* desc);
401 DLLLOCAL
int makeIntVal(
const char* desc);
403 DLLLOCAL
int makeFloat(
const char* desc);
404 DLLLOCAL
int makeNumber(
const char* desc);
406 DLLLOCAL
int doRecursiveException() {
407 vl.xsink->raiseException(
"REFERENCE-ERROR",
"recursive reference detected in assignment");
415 typedef std::vector<AbstractQoreNode*> nvec_t;
417 lvid_set_t* lvid_set =
nullptr;
427 RObject* robj =
nullptr;
430 QoreLValueGeneric* val =
nullptr;
432 const QoreTypeInfo* typeInfo =
nullptr;
441 DLLLOCAL LValueHelper(LValueHelper&& o);
446 DLLLOCAL ~LValueHelper();
448 DLLLOCAL
int set(
const ReferenceNode& ref,
bool for_remove =
false);
450 DLLLOCAL
void setClosure(RObject* c) {
458 DLLLOCAL
int doLValue(
const QoreValue& exp,
bool for_remove);
460 DLLLOCAL
int doLValue(
const ReferenceNode* ref,
bool for_remove);
464 DLLLOCAL
void setAndLock(QoreVarRWLock& rwl);
465 DLLLOCAL
void set(QoreVarRWLock& rwl);
471 DLLLOCAL
void setTypeInfo(
const QoreTypeInfo* ti) {
477 DLLLOCAL
void setValue(QoreLValueGeneric& nv,
const QoreTypeInfo* ti =
nullptr) {
484 before = nv.assigned && nv.type ==
QV_Node ? needs_scan(nv.v.n) : false;
489 DLLLOCAL
void setValue(
QoreValue& nqv,
const QoreTypeInfo* ti =
nullptr) {
497 before = needs_scan(nqv);
502 DLLLOCAL
void resetValue(QoreLValueGeneric& nv,
const QoreTypeInfo* ti =
nullptr) {
512 before = nv.assigned && nv.type ==
QV_Node ? needs_scan(nv.v.n) : false;
517 DLLLOCAL
void resetValue(
QoreValue& nqv,
const QoreTypeInfo* ti =
nullptr) {
527 before = needs_scan(nqv);
532 DLLLOCAL
void clearPtr() {
542 DLLLOCAL
operator bool()
const {
546 DLLLOCAL
bool isOptimized()
const {
547 return val && val->optimized();
550 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const {
555 return val ? val->getType() : qv->
getType();
560 return val->getReference();
566 DLLLOCAL
const QoreValue getValue()
const {
567 return val ? val->getValue() : *qv;
571 return val ? val->getValue() : *qv;
575 assert((val && val->getInternalNode()) || (qv && qv->
getInternalNode()));
579 DLLLOCAL
const char* getTypeName()
const {
580 return val ? val->getTypeName() : qv->
getTypeName();
583 DLLLOCAL
bool checkType(
const qore_type_t t)
const {
584 return getType() == t;
587 DLLLOCAL
bool isNothing()
const {
591 DLLLOCAL
void setObjectContext(qore_object_private* obj);
593 DLLLOCAL
QoreValue getReferencedValue()
const;
597 DLLLOCAL
void ensureUnique() {
604 assignNodeIntern(current_value->
realCopy());
609 DLLLOCAL
int64 getAsBigInt()
const;
610 DLLLOCAL
bool getAsBool()
const;
611 DLLLOCAL
double getAsFloat()
const;
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>");
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>");
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>");
646 DLLLOCAL
QoreNumberNode* ensureUniqueNumber(
const char* desc =
"<lvalue>") {
647 if (makeNumber(desc))
654 if (!(*p)->is_unique()) {
665 assert(get_node_type(node) ==
NT_NUMBER);
677 DLLLOCAL
int assign(
QoreValue val,
const char* desc =
"<lvalue>",
bool check_types =
true,
bool weak_assignment =
false);
679 DLLLOCAL
QoreValue removeValue(
bool for_del);
680 DLLLOCAL
QoreValue remove(
bool& static_assignment);
682 DLLLOCAL
void setDelta(
int dt) {
688class LValueRemoveHelper {
691 LValueRemoveHelper(
const LValueRemoveHelper&) =
delete;
692 LValueRemoveHelper& operator=(
const LValueRemoveHelper&) =
delete;
693 void*
operator new(size_t) =
delete;
695 DLLLOCAL
void doRemove(
const QoreSquareBracketsOperatorNode* op);
696 DLLLOCAL
void doRemove(
const QoreSquareBracketsOperatorNode* op,
const QoreParseListNode* l);
697 DLLLOCAL
void doRemove(
const QoreSquareBracketsRangeOperatorNode* op);
701 QoreLValueGeneric rv;
711 DLLLOCAL
operator bool()
const {
719 DLLLOCAL
bool forDel()
const {
723 DLLLOCAL
void doRemove(QoreLValueGeneric& qv,
const QoreTypeInfo* ti) {
724 rv.assignSetTakeInitial(qv);
728 DLLLOCAL
QoreValue remove(
bool& static_assignment);
730 DLLLOCAL
void deleteLValue();
734 QoreLValueGeneric* val;
735 const QoreTypeInfo* typeInfo;
737 DLLLOCAL lvinfo(QoreLValueGeneric* val,
const QoreTypeInfo* typeInfo) : val(val), typeInfo(typeInfo) {
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