32 #ifndef _QORE_VARIABLE_H
33 #define _QORE_VARIABLE_H
42 VT_GLOBAL_THREAD_LOCAL = 7
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 {
97 class LValueRemoveHelper;
103 const QoreProgramLocation* loc;
104 QoreLValue<qore_gvar_ref_u> val;
106 mutable QoreVarRWLock rwl;
107 QoreParseTypeInfo* parseTypeInfo;
108 const QoreTypeInfo* typeInfo;
109 const QoreTypeInfo* refTypeInfo =
nullptr;
116 Var(
const Var&) =
delete;
119 bool builtin =
false;
121 DLLLOCAL ~Var() {
delete parseTypeInfo; }
125 xsink->
raiseException(
"DESTRUCTOR-ERROR",
"illegal variable assignment after second phase of variable destruction");
132 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) {
135 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) {
138 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) {
141 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) {
143 val.v.setPtr(ref, ro);
146 DLLLOCAL
const char* getName()
const;
148 DLLLOCAL
const std::string& getNameStr()
const {
152 DLLLOCAL
bool isBuiltin()
const {
156 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove)
const;
157 DLLLOCAL
void remove(LValueRemoveHelper& lvrh);
160 if (val.type != QV_Ref) {
162 QoreAutoVarRWWriteLocker al(rwl);
165 printd(5,
"Var::clearLocal() clearing '%s' %p\n", name.c_str(),
this);
170 h = val.assign(QoreTypeInfo::getDefaultQoreValue(typeInfo));
172 h = val.removeValue(
true);
178 printd(5,
"Var::clearLocal() skipping imported var '%s' %p\n", name.c_str(),
this);
183 assert(val.type == QV_Node);
186 discard(val.assignInitial(v),
nullptr);
189 DLLLOCAL
const Var* parseGetVar()
const {
190 return (val.type == QV_Ref) ? val.v.getPtr()->parseGetVar() :
this;
193 DLLLOCAL
bool isImported()
const;
199 DLLLOCAL
void doDoubleDeclarationError(
const QoreProgramLocation* loc) {
202 parse_error(*loc,
"global variable '%s' previously declared with type '%s'", name.c_str(), QoreParseTypeInfo::getName(parseTypeInfo));
206 parse_error(*loc,
"global variable '%s' previously declared with type '%s'", name.c_str(), QoreTypeInfo::getName(typeInfo));
207 assert(!parseTypeInfo);
211 DLLLOCAL
void checkAssignType(
const QoreProgramLocation* loc,
const QoreTypeInfo *n_typeInfo) {
213 if (!QoreTypeInfo::hasType(n_typeInfo))
216 if (val.type == QV_Ref) {
217 val.v.getPtr()->checkAssignType(loc, n_typeInfo);
223 if (parseTypeInfo || typeInfo) {
224 doDoubleDeclarationError(loc);
228 typeInfo = n_typeInfo;
229 refTypeInfo = QoreTypeInfo::getReferenceTarget(typeInfo);
231 assert(!val.removeValue(
true));
234 DLLLOCAL
void parseInit() {
235 if (val.type == QV_Ref)
239 typeInfo = QoreParseTypeInfo::resolveAndDelete(parseTypeInfo, loc);
240 refTypeInfo = QoreTypeInfo::getReferenceTarget(typeInfo);
241 parseTypeInfo =
nullptr;
247 discard(val.assignInitial(QoreTypeInfo::getDefaultQoreValue(typeInfo)),
nullptr);
251 DLLLOCAL QoreParseTypeInfo* copyParseTypeInfo()
const {
252 return parseTypeInfo ? parseTypeInfo->copy() :
nullptr;
255 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfoForInitialAssignment() {
257 if (val.type == QV_Ref)
258 return val.v.getPtr()->getTypeInfo();
264 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfo() {
266 if (val.type == QV_Ref)
267 return val.v.getPtr()->getTypeInfo();
270 return refTypeInfo ? refTypeInfo : typeInfo;
273 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const {
274 assert(!parseTypeInfo);
275 if (val.type == QV_Ref)
276 return val.v.getPtr()->getTypeInfo();
281 DLLLOCAL
bool hasTypeInfo()
const {
282 if (val.type == QV_Ref)
283 return val.v.getPtr()->hasTypeInfo();
285 return parseTypeInfo || typeInfo;
288 DLLLOCAL
bool isRef()
const {
289 return val.type == QV_Ref;
293 DLLLOCAL
const char* getClassName()
const {
294 if (val.type == QV_Ref)
295 return val.v.getPtr()->getClassName();
298 assert(QoreTypeInfo::getUniqueReturnClass(typeInfo));
299 return QoreTypeInfo::getUniqueReturnClass(typeInfo)->getName();
301 assert(parseTypeInfo);
302 assert(parseTypeInfo->cscope);
303 return parseTypeInfo->cscope->getIdentifier();
306 DLLLOCAL
bool isPublic()
const {
310 DLLLOCAL
void setPublic() {
315 DLLLOCAL
const QoreProgramLocation* getParseLocation()
const {
320 DLLLOCAL
void delete_global_variables();
325 typedef vector_set_t<const void*> lvid_set_t;
328 hashdecl ObjCountRec {
337 DLLLOCAL
int getDifference();
340 typedef std::vector<ObjCountRec> ocvec_t;
345 friend class LValueRemoveHelper;
346 friend class LValueLockHandoffHelper;
350 DLLLOCAL LValueHelper(
const LValueHelper&) =
delete;
351 DLLLOCAL LValueHelper& operator=(
const LValueHelper&) =
delete;
364 DLLLOCAL
int doListLValue(
const QoreSquareBracketsOperatorNode* op,
bool for_remove);
365 DLLLOCAL
int doHashLValue(
qore_type_t t,
const char* mem,
bool for_remove);
366 DLLLOCAL
int doHashObjLValue(
const QoreHashObjectDereferenceOperatorNode* op,
bool for_remove);
368 DLLLOCAL
int makeInt(
const char* desc);
369 DLLLOCAL
int makeFloat(
const char* desc);
370 DLLLOCAL
int makeNumber(
const char* desc);
372 DLLLOCAL
int doRecursiveException() {
373 vl.xsink->raiseException(
"REFERENCE-ERROR",
"recursive reference detected in assignment");
382 typedef std::vector<AbstractQoreNode*> nvec_t;
384 lvid_set_t* lvid_set =
nullptr;
394 RObject* robj =
nullptr;
397 QoreLValueGeneric* val =
nullptr;
399 const QoreTypeInfo* typeInfo =
nullptr;
406 DLLLOCAL LValueHelper(LValueHelper&& o);
411 DLLLOCAL ~LValueHelper();
413 DLLLOCAL
void setClosure(RObject* c) {
421 return tvec[tvec.size() - 1];
424 DLLLOCAL
int doLValue(
const QoreValue exp,
bool for_remove);
426 DLLLOCAL
int doLValue(
const ReferenceNode* ref,
bool for_remove);
428 DLLLOCAL
void setAndLock(QoreVarRWLock& rwl);
429 DLLLOCAL
void set(QoreVarRWLock& rwl);
435 DLLLOCAL
void setTypeInfo(
const QoreTypeInfo* ti) {
439 DLLLOCAL
void setValue(QoreLValueGeneric& nv,
const QoreTypeInfo* ti =
nullptr) {
446 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
451 DLLLOCAL
void setValue(
QoreValue& nqv,
const QoreTypeInfo* ti =
nullptr) {
457 before = needs_scan(nqv);
462 DLLLOCAL
void resetValue(QoreLValueGeneric& nv,
const QoreTypeInfo* ti =
nullptr) {
472 before = nv.assigned && nv.type == QV_Node ? needs_scan(nv.v.n) : false;
477 DLLLOCAL
void resetValue(
QoreValue& nqv,
const QoreTypeInfo* ti =
nullptr) {
487 before = needs_scan(nqv);
492 DLLLOCAL
void clearPtr() {
501 DLLLOCAL
operator bool()
const {
505 DLLLOCAL
bool isOptimized()
const {
506 return val && val->optimized();
509 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const {
514 return val ? val->getType() : qv->getType();
517 DLLLOCAL
const QoreValue getValue()
const {
518 return val ? val->getValue() : *qv;
522 return val ? val->getValue() : *qv;
526 assert((val && val->getInternalNode()) || (qv && qv->getInternalNode()));
527 return val ? val->getInternalNode() : qv->getInternalNode();
530 DLLLOCAL
const char* getTypeName()
const {
531 return val ? val->getTypeName() : qv->getTypeName();
534 DLLLOCAL
bool checkType(
const qore_type_t t)
const {
535 return getType() == t;
538 DLLLOCAL
bool isNothing()
const {
542 DLLLOCAL
void setObjectContext(qore_object_private* obj);
544 DLLLOCAL
QoreValue getReferencedValue()
const;
548 DLLLOCAL
void ensureUnique() {
555 assignNodeIntern(current_value->
realCopy());
560 DLLLOCAL
int64 getAsBigInt()
const;
561 DLLLOCAL
bool getAsBool()
const;
562 DLLLOCAL
double getAsFloat()
const;
564 DLLLOCAL
int64 plusEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
565 DLLLOCAL
int64 minusEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
566 DLLLOCAL
int64 multiplyEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
567 DLLLOCAL
int64 divideEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
568 DLLLOCAL
int64 orEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
569 DLLLOCAL
int64 andEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
570 DLLLOCAL
int64 xorEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
571 DLLLOCAL
int64 modulaEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
572 DLLLOCAL
int64 shiftLeftEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
573 DLLLOCAL
int64 shiftRightEqualsBigInt(
int64 v,
const char* desc =
"<lvalue>");
574 DLLLOCAL
int64 preIncrementBigInt(
const char* desc =
"<lvalue>");
575 DLLLOCAL
int64 preDecrementBigInt(
const char* desc =
"<lvalue>");
576 DLLLOCAL
int64 postIncrementBigInt(
const char* desc =
"<lvalue>");
577 DLLLOCAL
int64 postDecrementBigInt(
const char* desc =
"<lvalue>");
579 DLLLOCAL
double plusEqualsFloat(
double v,
const char* desc =
"<lvalue>");
580 DLLLOCAL
double minusEqualsFloat(
double v,
const char* desc =
"<lvalue>");
581 DLLLOCAL
double multiplyEqualsFloat(
double v,
const char* desc =
"<lvalue>");
582 DLLLOCAL
double divideEqualsFloat(
double v,
const char* desc =
"<lvalue>");
583 DLLLOCAL
double preIncrementFloat(
const char* desc =
"<lvalue>");
584 DLLLOCAL
double preDecrementFloat(
const char* desc =
"<lvalue>");
585 DLLLOCAL
double postIncrementFloat(
const char* desc =
"<lvalue>");
586 DLLLOCAL
double postDecrementFloat(
const char* desc =
"<lvalue>");
588 DLLLOCAL
void plusEqualsNumber(
QoreValue r,
const char* desc =
"<lvalue>");
589 DLLLOCAL
void minusEqualsNumber(
QoreValue r,
const char* desc =
"<lvalue>");
590 DLLLOCAL
void multiplyEqualsNumber(
QoreValue r,
const char* desc =
"<lvalue>");
591 DLLLOCAL
void divideEqualsNumber(
QoreValue r,
const char* desc =
"<lvalue>");
592 DLLLOCAL
void preIncrementNumber(
const char* desc =
"<lvalue>");
593 DLLLOCAL
void preDecrementNumber(
const char* desc =
"<lvalue>");
594 DLLLOCAL
QoreNumberNode* postIncrementNumber(
bool ref_rv,
const char* desc =
"<lvalue>");
595 DLLLOCAL
QoreNumberNode* postDecrementNumber(
bool ref_rv,
const char* desc =
"<lvalue>");
597 DLLLOCAL
QoreNumberNode* ensureUniqueNumber(
const char* desc =
"<lvalue>") {
600 if (makeNumber(desc))
606 if (makeNumber(desc))
612 if (!(*p)->is_unique()) {
620 DLLLOCAL
int assign(
QoreValue val,
const char* desc =
"<lvalue>",
bool check_types =
true,
bool weak_assignment =
false);
622 DLLLOCAL
QoreValue removeValue(
bool for_del);
623 DLLLOCAL
QoreValue remove(
bool& static_assignment);
625 DLLLOCAL
void setDelta(
int dt) {
631 class LValueRemoveHelper {
634 LValueRemoveHelper(
const LValueRemoveHelper&) =
delete;
635 LValueRemoveHelper& operator=(
const LValueRemoveHelper&) =
delete;
636 void*
operator new(size_t) =
delete;
638 DLLLOCAL
void doRemove(
const QoreSquareBracketsOperatorNode* op);
639 DLLLOCAL
void doRemove(
const QoreSquareBracketsOperatorNode* op,
const QoreParseListNode* l);
640 DLLLOCAL
void doRemove(
const QoreSquareBracketsRangeOperatorNode* op);
644 QoreLValueGeneric rv;
654 DLLLOCAL
operator bool()
const {
662 DLLLOCAL
bool forDel()
const {
666 DLLLOCAL
void doRemove(QoreLValueGeneric& qv,
const QoreTypeInfo* ti) {
670 rv.assignSetTakeInitial(qv, QoreTypeInfo::getDefaultQoreValue(ti));
672 rv.assignSetTakeInitial(qv);
677 DLLLOCAL
QoreValue remove(
bool& static_assignment);
679 DLLLOCAL
void deleteLValue();
682 #endif // _QORE_VARIABLE_H