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 LocalRefHelper :
public RuntimeReferenceHelper {
53 : RuntimeReferenceHelper(ref, xsink),
57 DLLLOCAL
operator bool()
const {
63 class LValueRefHelper :
public LocalRefHelper<T> {
68 DLLLOCAL LValueRefHelper(T* val,
ExceptionSink* xsink) : LocalRefHelper<T>(val, xsink), valp(this->valid ? new LValueHelper(*((
ReferenceNode*)val->v.n), xsink) : nullptr) {
71 DLLLOCAL ~LValueRefHelper() {
75 DLLLOCAL
operator bool()
const {
79 DLLLOCAL LValueHelper* operator->() {
88 xsink->
raiseException(
"DESTRUCTOR-ERROR",
"illegal variable assignment after second phase of variable destruction");
95 QoreLValueGeneric val;
98 bool frame_boundary : 1;
100 DLLLOCAL VarValueBase(
const char* n_id, valtype_t t = QV_Node) : val(t), id(n_id), finalized(false), frame_boundary(false) {
103 DLLLOCAL VarValueBase(
const char* n_id,
const QoreTypeInfo* varTypeInfo) : val(varTypeInfo), id(n_id), finalized(false), frame_boundary(false) {
106 DLLLOCAL VarValueBase() : val(QV_Bool), id(nullptr), finalized(false), frame_boundary(false) {
109 DLLLOCAL
void setFrameBoundary() {
110 assert(!frame_boundary);
111 frame_boundary =
true;
115 val.removeValue(
true).discard(xsink);
118 DLLLOCAL
bool isRef()
const {
128 return val.removeValue(
true);
132 class LocalVarValue :
public VarValueBase {
134 DLLLOCAL
void set(
const char* n_id,
const QoreTypeInfo* varTypeInfo,
QoreValue nval,
bool assign,
bool static_assignment) {
141 val.set(varTypeInfo);
146 discard(val.assignAssumeInitial(nval, static_assignment),
nullptr);
148 assert(!val.assigned);
157 DLLLOCAL
void uninstantiateSelf() {
158 val.unassignIgnore();
161 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove,
const QoreTypeInfo* typeInfo,
const QoreTypeInfo* refTypeInfo)
const;
162 DLLLOCAL
void remove(LValueRemoveHelper& lvrh,
const QoreTypeInfo* typeInfo);
168 LocalRefHelper<LocalVarValue> helper(
this, *ref, xsink);
173 return erh.takeValue(needs_deref);
178 return val.get<WeakReferenceNode>()->get();
181 return val.getReferencedValue(needs_deref);
187 LocalRefHelper<LocalVarValue> helper(
this, *ref, xsink);
192 return *xsink ?
QoreValue() : erh.takeReferencedValue();
196 return val.get<WeakReferenceNode>()->get()->refSelf();
199 return val.getReferencedValue();
203 hashdecl ClosureVarValue :
public VarValueBase,
public RObject {
205 const QoreTypeInfo* typeInfo =
nullptr;
206 const QoreTypeInfo* refTypeInfo;
208 mutable std::atomic_int references;
210 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) {
215 val.set(varTypeInfo);
220 discard(val.assignAssumeInitial(nval),
nullptr);
223 assert(!val.assigned);
227 DLLLOCAL
virtual ~ClosureVarValue() {
231 DLLLOCAL
void ref()
const;
235 DLLLOCAL
const void* getLValueId()
const;
238 DLLLOCAL
virtual bool needsScan(
bool scan_now) {
239 return QoreTypeInfo::needsScan(typeInfo);
242 DLLLOCAL
virtual bool scanMembers(RSetHelper& rsh);
244 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove)
const;
245 DLLLOCAL
void remove(LValueRemoveHelper& lvrh);
247 DLLLOCAL ClosureVarValue* refSelf()
const {
249 return const_cast<ClosureVarValue*
>(
this);
254 QoreSafeVarRWWriteLocker sl(rml);
255 return VarValueBase::finalize();
259 QoreSafeVarRWReadLocker sl(rml);
263 LocalRefHelper<ClosureVarValue> helper(
this, **ref, xsink);
264 return helper ? lvalue_ref::get(*ref)->vexp.eval(needs_deref, xsink) :
QoreValue();
269 return val.get<WeakReferenceNode>()->get();
272 return val.getReferencedValue();
276 QoreSafeVarRWReadLocker sl(rml);
280 LocalRefHelper<ClosureVarValue> helper(
this, **ref, xsink);
281 return helper ? lvalue_ref::get(*ref)->vexp.eval(xsink) :
QoreValue();
285 return val.get<WeakReferenceNode>()->get()->refSelf();
288 return val.getReferencedValue();
291 DLLLOCAL
AbstractQoreNode* getReference(
const QoreProgramLocation* loc,
const char* name,
const void*& lvalue_id);
294 DLLLOCAL
virtual void deleteObject() {
299 DLLLOCAL
virtual const char* getName()
const {
307 DLLLOCAL LocalVar(
const char* n_name,
const QoreTypeInfo* ti)
308 : name(n_name), typeInfo(ti), refTypeInfo(QoreTypeInfo::getReferenceTarget(ti)) {
311 DLLLOCAL LocalVar(
const LocalVar& old) : name(old.name), closure_use(old.closure_use),
312 parse_assigned(old.parse_assigned), typeInfo(old.typeInfo), refTypeInfo(old.refTypeInfo) {
315 DLLLOCAL ~LocalVar() {
318 DLLLOCAL
void parseAssigned() {
320 parse_assigned =
true;
323 DLLLOCAL
void parseUnassigned() {
325 parse_assigned =
false;
328 DLLLOCAL
void instantiate() {
331 instantiateIntern(QoreTypeInfo::getDefaultQoreValue(typeInfo),
true);
338 DLLLOCAL
void instantiate(
QoreValue nval) {
339 instantiateIntern(nval,
true);
342 DLLLOCAL
void instantiateIntern(
QoreValue nval,
bool assign) {
346 LocalVarValue* val = thread_instantiate_lvar();
347 val->set(name.c_str(), typeInfo, nval, assign,
false);
349 thread_instantiate_closure_var(name.c_str(), typeInfo, nval, assign);
352 DLLLOCAL
void instantiateSelf(
QoreObject* value)
const {
353 printd(5,
"LocalVar::instantiateSelf(%p) this: %p '%s'\n", value,
this, name.c_str());
355 LocalVarValue* val = thread_instantiate_lvar();
356 val->set(name.c_str(), typeInfo, value,
true,
true);
359 thread_instantiate_closure_var(name.c_str(), typeInfo, val,
true);
367 thread_uninstantiate_lvar(xsink);
369 thread_uninstantiate_closure_var(xsink);
372 DLLLOCAL
void uninstantiateSelf()
const {
374 thread_uninstantiate_self();
376 thread_uninstantiate_closure_var(0);
381 LocalVarValue* val = get_var();
383 return val->eval(needs_deref, xsink);
386 ClosureVarValue* val = thread_find_closure_var(name.c_str());
387 return val->eval(needs_deref, xsink);
391 DLLLOCAL
bool needsScan()
const {
392 return QoreTypeInfo::needsScan(typeInfo);
395 DLLLOCAL
const char* getName()
const {
399 DLLLOCAL
const std::string& getNameStr()
const {
403 DLLLOCAL
void setClosureUse() {
407 DLLLOCAL
bool closureUse()
const {
411 DLLLOCAL
bool isRef()
const {
412 return !closure_use ? get_var()->isRef() : thread_find_closure_var(name.c_str())->isRef();
415 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove,
bool initial_assignment)
const {
419 return get_var()->getLValue(lvh, for_remove, typeInfo, refTypeInfo);
422 return thread_find_closure_var(name.c_str())->getLValue(lvh, for_remove);
425 DLLLOCAL
void remove(LValueRemoveHelper& lvrh) {
427 return get_var()->remove(lvrh, typeInfo);
429 return thread_find_closure_var(name.c_str())->remove(lvrh);
432 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const {
436 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfo()
const {
437 return parse_assigned && refTypeInfo ? refTypeInfo : typeInfo;
440 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfoForInitialAssignment()
const {
445 return !closure_use ? get_var()->val.getType() : thread_find_closure_var(name.c_str())->val.getType();
448 DLLLOCAL
const char* getValueTypeName()
const {
449 return !closure_use ? get_var()->val.getTypeName() : thread_find_closure_var(name.c_str())->val.getTypeName();
454 bool closure_use =
false,
455 parse_assigned =
false;
456 const QoreTypeInfo* typeInfo =
nullptr;
457 const QoreTypeInfo* refTypeInfo =
nullptr;
459 DLLLOCAL LocalVarValue* get_var()
const {
460 return thread_find_lvar(name.c_str());
464 typedef LocalVar* lvar_ptr_t;
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
DLLEXPORT AbstractQoreNode * refSelf() const
returns "this" with an incremented reference count
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
the implementation of Qore's object data type, reference counted, dynamically-allocated only
Definition: QoreObject.h:60
a templated class to manage a reference count of an object that can throw a Qore-language exception w...
Definition: ReferenceHolder.h:52
parse type: reference to a lvalue expression
Definition: ReferenceNode.h:45
DLLEXPORT ReferenceNode * refRefSelf() const
returns a reference to itself
evaluates an AbstractQoreNode and dereferences the stored value in the destructor
Definition: QoreValue.h:613
int16_t qore_type_t
used to identify unique Qore data and parse types (descendents of AbstractQoreNode)
Definition: common.h:70
const qore_type_t NT_WEAKREF
type value for WeakReferenceNode
Definition: node_types.h:87
const qore_type_t NT_REFERENCE
type value for ReferenceNode
Definition: node_types.h:64
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:275