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"
46class LocalRefHelper :
public RuntimeReferenceHelper {
53 : RuntimeReferenceHelper(ref, xsink),
57 DLLLOCAL
operator bool()
const {
63class LValueRefHelper :
public LocalRefHelper<T> {
68 DLLLOCAL LValueRefHelper(T* val,
ExceptionSink* xsink) : LocalRefHelper<T>(val, xsink),
69 valp(this->valid ? new LValueHelper(*((
ReferenceNode*)val->v.n), xsink) : nullptr) {
72 DLLLOCAL ~LValueRefHelper() {
76 DLLLOCAL
operator bool()
const {
80 DLLLOCAL LValueHelper* operator->() {
89 xsink->
raiseException(
"DESTRUCTOR-ERROR",
"illegal variable assignment after second phase of variable "
97 QoreLValueGeneric val;
100 bool frame_boundary : 1;
102 DLLLOCAL VarValueBase(
const char* n_id, valtype_t t =
QV_Node) : val(t), id(n_id), finalized(false), frame_boundary(false) {
105 DLLLOCAL VarValueBase(
const char* n_id,
const QoreTypeInfo* varTypeInfo) : val(varTypeInfo), id(n_id), finalized(false), frame_boundary(false) {
108 DLLLOCAL VarValueBase() : val(
QV_Bool), id(nullptr), finalized(false), frame_boundary(false) {
111 DLLLOCAL
void setFrameBoundary() {
112 assert(!frame_boundary);
113 frame_boundary =
true;
117 val.removeValue(
true).discard(xsink);
120 DLLLOCAL
bool isRef()
const {
130 return val.removeValue(
true);
134class LocalVarValue :
public VarValueBase {
136 DLLLOCAL
void set(
const char* n_id,
const QoreTypeInfo* varTypeInfo,
QoreValue nval,
bool assign,
137 bool static_assignment) {
145 val.set(varTypeInfo);
150 discard(val.assignAssumeInitial(nval, static_assignment),
nullptr);
152 assert(!val.assigned);
161 DLLLOCAL
void uninstantiateSelf() {
162 val.unassignIgnore();
165 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove,
const QoreTypeInfo* typeInfo,
166 const QoreTypeInfo* refTypeInfo)
const;
167 DLLLOCAL
void remove(LValueRemoveHelper& lvrh,
const QoreTypeInfo* typeInfo);
174 LocalRefHelper<LocalVarValue> helper(
this, *ref, xsink);
179 return erh.takeValue(needs_deref);
184 return val.get<WeakReferenceNode>()->get();
187 return val.getReferencedValue(needs_deref);
193 LocalRefHelper<LocalVarValue> helper(
this, *ref, xsink);
198 return *xsink ?
QoreValue() : erh.takeReferencedValue();
202 return val.get<WeakReferenceNode>()->get()->refSelf();
205 return val.getReferencedValue();
209hashdecl ClosureVarValue :
public VarValueBase,
public RObject {
211 const QoreTypeInfo* typeInfo =
nullptr;
212 const QoreTypeInfo* refTypeInfo;
214 mutable std::atomic_int references;
216 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) {
221 val.set(varTypeInfo);
226 discard(val.assignAssumeInitial(nval),
nullptr);
229 assert(!val.assigned);
233 DLLLOCAL
virtual ~ClosureVarValue() {
237 DLLLOCAL
void ref()
const;
241 DLLLOCAL
const void* getLValueId()
const;
244 DLLLOCAL
virtual bool needsScan(
bool scan_now) {
245 return QoreTypeInfo::needsScan(typeInfo);
248 DLLLOCAL
virtual bool scanMembers(RSetHelper& rsh);
250 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove)
const;
251 DLLLOCAL
void remove(LValueRemoveHelper& lvrh);
253 DLLLOCAL ClosureVarValue* refSelf()
const {
255 return const_cast<ClosureVarValue*
>(
this);
260 QoreSafeVarRWWriteLocker sl(rml);
261 return VarValueBase::finalize();
265 QoreSafeVarRWReadLocker sl(rml);
269 LocalRefHelper<ClosureVarValue> helper(
this, **ref, xsink);
270 return helper ? lvalue_ref::get(*ref)->vexp.eval(needs_deref, xsink) :
QoreValue();
275 return val.get<WeakReferenceNode>()->get();
278 return val.getReferencedValue();
282 QoreSafeVarRWReadLocker sl(rml);
286 LocalRefHelper<ClosureVarValue> helper(
this, **ref, xsink);
287 return helper ? lvalue_ref::get(*ref)->vexp.eval(xsink) :
QoreValue();
291 return val.get<WeakReferenceNode>()->get()->refSelf();
294 return val.getReferencedValue();
297 DLLLOCAL
AbstractQoreNode* getReference(
const QoreProgramLocation* loc,
const char* name,
const void*& lvalue_id);
300 DLLLOCAL
virtual void deleteObject() {
305 DLLLOCAL
virtual const char* getName()
const {
313 DLLLOCAL LocalVar(
const char* n_name,
const QoreTypeInfo* ti)
314 : name(n_name), typeInfo(ti), refTypeInfo(QoreTypeInfo::getReferenceTarget(ti)) {
317 DLLLOCAL LocalVar(
const LocalVar& old) : name(old.name), closure_use(old.closure_use),
318 parse_assigned(old.parse_assigned), is_self(old.is_self), typeInfo(old.typeInfo),
319 refTypeInfo(old.refTypeInfo) {
322 DLLLOCAL ~LocalVar() {
325 DLLLOCAL
void parseAssigned() {
326 if (!parse_assigned) {
327 parse_assigned =
true;
331 DLLLOCAL
void parseUnassigned() {
332 if (parse_assigned) {
333 parse_assigned =
false;
337 DLLLOCAL
bool isAssigned()
const {
338 return parse_assigned;
341 DLLLOCAL
void instantiate(
int64 parse_options) {
345 instantiateIntern(QoreTypeInfo::getDefaultQoreValue(typeInfo),
true);
353 DLLLOCAL
void instantiate(
QoreValue nval) {
354 instantiateIntern(nval,
true);
357 DLLLOCAL
void instantiateIntern(
QoreValue nval,
bool assign) {
364 LocalVarValue* val = thread_instantiate_lvar();
365 val->set(name.c_str(), typeInfo, nval, assign,
false);
367 thread_instantiate_closure_var(name.c_str(), typeInfo, nval, assign);
371 DLLLOCAL
void instantiateSelf(
QoreObject* value)
const {
372 printd(5,
"LocalVar::instantiateSelf(%p) this: %p '%s'\n", value,
this, name.c_str());
374 LocalVarValue* val = thread_instantiate_lvar();
375 val->set(name.c_str(), typeInfo, value,
true,
true);
378 thread_instantiate_closure_var(name.c_str(), typeInfo, val,
true);
387 thread_uninstantiate_lvar(xsink);
389 thread_uninstantiate_closure_var(xsink);
393 DLLLOCAL
void uninstantiateSelf()
const {
395 thread_uninstantiate_self();
397 thread_uninstantiate_closure_var(
nullptr);
403 LocalVarValue* val = get_var();
406 return val->eval(needs_deref, xsink);
409 ClosureVarValue* val = thread_find_closure_var(name.c_str());
410 return val->eval(needs_deref, xsink);
414 DLLLOCAL
bool needsScan()
const {
415 return QoreTypeInfo::needsScan(typeInfo);
418 DLLLOCAL
const char* getName()
const {
422 DLLLOCAL
const std::string& getNameStr()
const {
426 DLLLOCAL
void setClosureUse() {
430 DLLLOCAL
bool closureUse()
const {
434 DLLLOCAL
bool isRef()
const {
435 return !closure_use ? get_var()->isRef() : thread_find_closure_var(name.c_str())->isRef();
438 DLLLOCAL
int getLValue(LValueHelper& lvh,
bool for_remove,
bool initial_assignment)
const {
442 return get_var()->getLValue(lvh, for_remove, typeInfo, refTypeInfo);
445 return thread_find_closure_var(name.c_str())->getLValue(lvh, for_remove);
448 DLLLOCAL
void remove(LValueRemoveHelper& lvrh) {
450 return get_var()->remove(lvrh, typeInfo);
453 return thread_find_closure_var(name.c_str())->remove(lvrh);
456 DLLLOCAL
const QoreTypeInfo* getTypeInfo()
const {
460 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfo()
const {
461 return parse_assigned && refTypeInfo ? refTypeInfo : typeInfo;
464 DLLLOCAL
const QoreTypeInfo* parseGetTypeInfoForInitialAssignment()
const {
469 return !closure_use ? get_var()->val.getType() : thread_find_closure_var(name.c_str())->val.getType();
472 DLLLOCAL
const char* getValueTypeName()
const {
473 return !closure_use ? get_var()->val.getTypeName() : thread_find_closure_var(name.c_str())->val.getTypeName();
476 DLLLOCAL
bool isSelf()
const {
480 DLLLOCAL
void setSelf() {
482 assert(name ==
"self");
488 bool closure_use =
false,
489 parse_assigned =
false,
491 const QoreTypeInfo* typeInfo =
nullptr;
492 const QoreTypeInfo* refTypeInfo =
nullptr;
494 DLLLOCAL LocalVarValue* get_var()
const {
495 return thread_find_lvar(name.c_str());
499typedef 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:50
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:61
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:672
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
#define QV_Node
for heap-allocated values
Definition: QoreValue.h:46
#define QV_Bool
for boolean values
Definition: QoreValue.h:43
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
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:279