32 #ifndef _QORE_LOCALVAR_H 34 #define _QORE_LOCALVAR_H 36 #include "qore/intern/qore_thread_intern.h" 37 #include "qore/intern/QoreLValue.h" 38 #include "qore/intern/RSection.h" 39 #include "qore/intern/RSet.h" 40 #include "qore/ReferenceNode.h" 41 #include "qore/intern/WeakReferenceNode.h" 46 class VarStackPointerHelper {
50 DLLLOCAL VarStackPointerHelper(
const T* v) : orig(v) {
53 DLLLOCAL ~VarStackPointerHelper() {
59 class LocalRefHelper :
public RuntimeReferenceHelper {
62 VarStackPointerHelper<T> helper;
66 DLLLOCAL LocalRefHelper(
const T* val,
ReferenceNode& ref,
ExceptionSink* xsink) : RuntimeReferenceHelper(ref, xsink), helper(val), valid(!*xsink) {
69 DLLLOCAL
operator bool()
const {
75 class LValueRefHelper :
public LocalRefHelper<T> {
80 DLLLOCAL LValueRefHelper(T* val,
ExceptionSink* xsink) : LocalRefHelper<T>(val, xsink), valp(this->valid ? new LValueHelper(*((
ReferenceNode*)val->v.n), xsink) : nullptr) {
83 DLLLOCAL ~LValueRefHelper() {
87 DLLLOCAL
operator bool()
const {
91 DLLLOCAL LValueHelper* operator->() {
100 xsink->
raiseException(
"DESTRUCTOR-ERROR",
"illegal variable assignment after second phase of variable destruction");
107 QoreLValueGeneric val;
109 mutable bool skip : 1;
111 bool frame_boundary : 1;
113 DLLLOCAL VarValueBase(
const char* n_id, valtype_t t =
QV_Node,
bool n_skip =
false) : val(t), id(n_id), skip(n_skip), finalized(false), frame_boundary(false) {
116 DLLLOCAL VarValueBase(
const char* n_id,
const QoreTypeInfo* varTypeInfo) : val(varTypeInfo), id(n_id), skip(false), finalized(false), frame_boundary(false) {
119 DLLLOCAL VarValueBase() : val(
QV_Bool), id(0), skip(false), finalized(false), frame_boundary(false) {
122 DLLLOCAL
void setFrameBoundary() {
123 assert(!frame_boundary);
124 frame_boundary =
true;
128 val.removeValue(
true).discard(xsink);
131 DLLLOCAL
bool isRef()
const {
141 return val.removeValue(
true);
145 hashdecl SkipHelper {
148 DLLLOCAL SkipHelper(VarValueBase* n_vvb) : vvb(n_vvb) {
153 DLLLOCAL ~SkipHelper() {
158 class LocalVarValue :
public VarValueBase {
160 DLLLOCAL
void set(
const char* n_id,
const QoreTypeInfo* varTypeInfo,
QoreValue nval,
bool assign,
bool static_assignment) {
168 val.set(varTypeInfo);
173 discard(val.assignAssumeInitial(nval, static_assignment),
nullptr);
176 assert(!val.assigned);
184 DLLLOCAL
void uninstantiateSelf() {
185 val.unassignIgnore();
188 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove,
const QoreTypeInfo* typeInfo,
const QoreTypeInfo* refTypeInfo)
const;
189 DLLLOCAL
void remove(LValueRemoveHelper& lvrh,
const QoreTypeInfo* typeInfo);
195 LocalRefHelper<LocalVarValue> helper(
this, *ref, xsink);
200 return erh.takeValue(needs_deref);
205 return val.get<WeakReferenceNode>()->
get();
208 return val.getReferencedValue(needs_deref);
214 LocalRefHelper<LocalVarValue> helper(
this, *ref, xsink);
219 return *xsink ?
QoreValue() : erh.takeReferencedValue();
223 return val.get<WeakReferenceNode>()->
get()->refSelf();
226 return val.getReferencedValue();
230 hashdecl ClosureVarValue :
public VarValueBase,
public RObject {
232 const QoreTypeInfo* typeInfo =
nullptr;
233 const QoreTypeInfo* refTypeInfo;
235 mutable std::atomic_int references;
237 DLLLOCAL ClosureVarValue(
const char* n_id,
const QoreTypeInfo* varTypeInfo,
QoreValue& nval,
bool assign) : VarValueBase(n_id, varTypeInfo), RObject(references), typeInfo(varTypeInfo), refTypeInfo(QoreTypeInfo::getReferenceTarget(varTypeInfo)), references(1) {
242 val.set(varTypeInfo);
247 discard(val.assignAssumeInitial(nval),
nullptr);
250 assert(!val.assigned);
254 DLLLOCAL
virtual ~ClosureVarValue() {
258 DLLLOCAL
void ref()
const;
262 DLLLOCAL
const void* getLValueId()
const;
265 DLLLOCAL
virtual bool needsScan(
bool scan_now) {
266 return QoreTypeInfo::needsScan(typeInfo);
269 DLLLOCAL
virtual bool scanMembers(RSetHelper& rsh);
271 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove)
const;
272 DLLLOCAL
void remove(LValueRemoveHelper& lvrh);
274 DLLLOCAL ClosureVarValue* refSelf()
const {
276 return const_cast<ClosureVarValue*
>(
this);
281 QoreSafeVarRWWriteLocker sl(rml);
282 return VarValueBase::finalize();
286 QoreSafeVarRWReadLocker sl(rml);
290 LocalRefHelper<ClosureVarValue> helper(
this, **ref, xsink);
291 return helper ? lvalue_ref::get(*ref)->vexp.eval(needs_deref, xsink) :
QoreValue();
296 return val.get<WeakReferenceNode>()->
get();
299 return val.getReferencedValue();
303 QoreSafeVarRWReadLocker sl(rml);
307 LocalRefHelper<ClosureVarValue> helper(
this, **ref, xsink);
308 return helper ? lvalue_ref::get(*ref)->vexp.eval(xsink) :
QoreValue();
312 return val.get<WeakReferenceNode>()->
get()->refSelf();
315 return val.getReferencedValue();
318 DLLLOCAL
AbstractQoreNode* getReference(
const QoreProgramLocation* loc,
const char* name,
const void*& lvalue_id);
321 DLLLOCAL
virtual void deleteObject() {
326 DLLLOCAL
virtual const char* getName()
const {
335 bool closure_use =
false,
336 parse_assigned =
false;
337 const QoreTypeInfo* typeInfo;
338 const QoreTypeInfo* refTypeInfo;
340 DLLLOCAL LocalVarValue* get_var()
const {
341 return thread_find_lvar(name.c_str());
345 DLLLOCAL LocalVar(
const char* n_name,
const QoreTypeInfo* ti) : name(n_name), typeInfo(ti), refTypeInfo(QoreTypeInfo::getReferenceTarget(ti)) {
348 DLLLOCAL LocalVar(
const LocalVar& old) : name(old.name), closure_use(old.closure_use), parse_assigned(old.parse_assigned), typeInfo(old.typeInfo), refTypeInfo(old.refTypeInfo) {
351 DLLLOCAL ~LocalVar() {
354 DLLLOCAL
void parseAssigned() {
356 parse_assigned =
true;
359 DLLLOCAL
void parseUnassigned() {
361 parse_assigned =
false;
364 DLLLOCAL
void instantiate() {
365 #ifdef QORE_ENFORCE_DEFAULT_LVALUE 366 instantiateIntern(QoreTypeInfo::getDefaultQoreValue(typeInfo),
false);
372 DLLLOCAL
void instantiate(
QoreValue nval) {
373 instantiateIntern(nval,
true);
376 DLLLOCAL
void instantiateIntern(
QoreValue nval,
bool assign) {
380 LocalVarValue* val = thread_instantiate_lvar();
381 val->set(name.c_str(), typeInfo, nval, assign,
false);
384 thread_instantiate_closure_var(name.c_str(), typeInfo, nval, assign);
387 DLLLOCAL
void instantiateSelf(
QoreObject* value)
const {
388 printd(5,
"LocalVar::instantiateSelf(%p) this: %p '%s'\n", value,
this, name.c_str());
390 LocalVarValue* val = thread_instantiate_lvar();
391 val->set(name.c_str(), typeInfo, value,
true,
true);
395 thread_instantiate_closure_var(name.c_str(), typeInfo, val,
true);
403 thread_uninstantiate_lvar(xsink);
405 thread_uninstantiate_closure_var(xsink);
408 DLLLOCAL
void uninstantiateSelf()
const {
410 thread_uninstantiate_self();
412 thread_uninstantiate_closure_var(0);
417 LocalVarValue* val = get_var();
419 return val->eval(needs_deref, xsink);
422 ClosureVarValue* val = thread_find_closure_var(name.c_str());
423 return val->eval(needs_deref, xsink);
427 DLLLOCAL
bool needsScan()
const {
428 return QoreTypeInfo::needsScan(typeInfo);
431 DLLLOCAL
const char* getName()
const {
435 DLLLOCAL
const std::string& getNameStr()
const {
439 DLLLOCAL
void setClosureUse() {
443 DLLLOCAL
bool closureUse()
const {
447 DLLLOCAL
bool isRef()
const {
448 return !closure_use ? get_var()->isRef() : thread_find_closure_var(name.c_str())->isRef();
451 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove,
bool initial_assignment)
const {
454 return get_var()->getLValue(lvh, for_remove, typeInfo, refTypeInfo);
457 return thread_find_closure_var(name.c_str())->getLValue(lvh, for_remove);
460 DLLLOCAL
void remove(LValueRemoveHelper& lvrh) {
462 return get_var()->remove(lvrh, typeInfo);
464 return thread_find_closure_var(name.c_str())->
remove(lvrh);
467 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const {
471 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfo()
const {
472 return parse_assigned && refTypeInfo ? refTypeInfo : typeInfo;
475 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfoForInitialAssignment()
const {
480 return !closure_use ? get_var()->val.getType() : thread_find_closure_var(name.c_str())->val.getType();
483 DLLLOCAL
const char* getValueTypeName()
const {
484 return !closure_use ? get_var()->val.getTypeName() : thread_find_closure_var(name.c_str())->val.getTypeName();
488 typedef LocalVar* lvar_ptr_t;
const qore_type_t NT_WEAKREF
type value for WeakReferenceNode
Definition: node_types.h:87
evaluates an AbstractQoreNode and dereferences the stored value in the destructor ...
Definition: QoreValue.h:593
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:54
static void discard(AbstractQoreNode *n, ExceptionSink *xsink)
to deref an AbstractQoreNode (when the pointer may be 0)
Definition: QoreLib.h:326
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
DLLEXPORT AbstractQoreNode * refSelf() const
returns "this" with an incremented reference count
#define QV_Node
for heap-allocated values
Definition: QoreValue.h:46
#define QV_Bool
for boolean values
Definition: QoreValue.h:43
parse type: reference to a lvalue expression
Definition: ReferenceNode.h:45
DLLEXPORT ReferenceNode * refRefSelf() const
returns a reference to itself
const qore_type_t NT_REFERENCE
type value for ReferenceNode
Definition: node_types.h:64
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
the implementation of Qore's object data type, reference counted, dynamically-allocated only ...
Definition: QoreObject.h:61
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:46
int16_t qore_type_t
used to identify unique Qore data and parse types (descendents of AbstractQoreNode) ...
Definition: common.h:70
a templated class to manage a reference count of an object that can throw a Qore-language exception w...
Definition: ReferenceHolder.h:52