Qore Programming Language 1.19.2
Loading...
Searching...
No Matches
VarRefNode.h
1/* -*- mode: c++; indent-tabs-mode: nil -*- */
2/*
3 VarRefNode.h
4
5 Qore Programming Language
6
7 Copyright (C) 2003 - 2023 Qore Technologies, s.r.o.
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 and/or sell copies of the Software, and to permit persons to whom the
14 Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26
27 Note that the Qore library is released under a choice of three open-source
28 licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
29 information.
30*/
31
32#ifndef _QORE_VARREFNODE_H
33#define _QORE_VARREFNODE_H
34
35#include "qore/intern/FunctionCallNode.h"
36
37class VarRefNewObjectNode;
38class LocalVar;
39class LocalVarValue;
40class Var;
41hashdecl ClosureVarValue;
42
43class VarRefNode : public ParseNode {
44public:
45 union var_u {
46 LocalVar* id; // for local variables
47 Var* var; // for global variables
48 ClosureVarValue* cvv; // for immediate values; used with references
49 } ref;
50
51 // takes over memory for "n"
52 DLLLOCAL VarRefNode(const QoreProgramLocation* loc, char* n, qore_var_t t, bool n_has_effect = false)
53 : ParseNode(loc, NT_VARREF, true, n_has_effect), name(n), type(t), new_decl(t == VT_LOCAL),
54 explicit_scope(false) {
55 if (type == VT_LOCAL)
56 ref.id = nullptr;
57 assert(type != VT_GLOBAL);
58 }
59
60 DLLLOCAL VarRefNode(const QoreProgramLocation* loc, char* n, LocalVar* n_id, bool in_closure)
61 : ParseNode(loc, NT_VARREF, true, false), name(n), new_decl(false), explicit_scope(false) {
62 ref.id = n_id;
63 if (in_closure) {
64 setClosureIntern();
65 } else {
66 type = VT_LOCAL;
67 }
68 }
69
71
73 DLLLOCAL bool parseEqualTo(const VarRefNode& other) const;
74
75 DLLLOCAL virtual int getAsString(QoreString& str, int foff, ExceptionSink* xsink) const;
76 DLLLOCAL virtual QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const;
77
78 DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
79 if (type == VT_LOCAL || type == VT_CLOSURE || type == VT_LOCAL_TS)
80 return ref.id->getTypeInfo();
81 if (type == VT_GLOBAL || type == VT_THREAD_LOCAL)
82 return ref.var->getTypeInfo();
83 return 0;
84 }
85
86 // returns the type name as a c string
87 DLLLOCAL virtual const char* getTypeName() const;
88
89 DLLLOCAL virtual bool stayInTree() const {
90 return !(type == VT_GLOBAL);
91 }
92
93 DLLLOCAL virtual bool parseIsDecl() const { return type != VT_UNRESOLVED; }
94 DLLLOCAL virtual bool isDecl() const { return false; }
95 DLLLOCAL bool explicitScope() const { return explicit_scope; }
96 DLLLOCAL void setExplicitScope() { explicit_scope = true; }
97
98 // will only be called on *VarRefNewObjectNode objects, but this is their common class
99 DLLLOCAL virtual const char* parseGetTypeName() const {
100 assert(false);
101 return nullptr;
102 }
103
104 // for checking for new object calls
105 DLLLOCAL virtual AbstractQoreNode* makeNewCall(QoreValue args);
106
107 DLLLOCAL bool isGlobalDecl() const { return new_decl; }
108
109 DLLLOCAL bool isGlobalVar() const { return type == VT_GLOBAL; }
110
111 //DLLLOCAL VarRefNode* isOptimized(const QoreTypeInfo*& typeInfo) const;
112 DLLLOCAL int getLValue(LValueHelper& lvh, bool for_remove) const;
113
114 DLLLOCAL bool isRef() const {
115 if (type == VT_LOCAL)
116 return ref.id->isRef();
117 if (type == VT_IMMEDIATE)
118 return true;
119 assert(type == VT_GLOBAL);
120 return ref.var->isRef();
121 }
122
123 DLLLOCAL void remove(LValueRemoveHelper& lvrh);
124
125 DLLLOCAL qore_var_t getType() const { return type; }
126 DLLLOCAL const char* getName() const { return name.ostr; }
127 // called when a list of variables is declared
128 DLLLOCAL void makeLocal() {
129 assert(type != VT_GLOBAL);
130 type = VT_LOCAL;
131 new_decl = true;
132 ref.id = nullptr;
133 }
134 // called when a list of variables is declared
135 DLLLOCAL virtual void makeGlobal(qore_var_t type);
136
137 // takes the name - caller owns the memory
138 DLLLOCAL char* takeName() {
139 assert(name.ostr);
140 return name.takeName();
141 }
142
143 DLLLOCAL void setThreadSafe() {
144 if (type == VT_LOCAL)
145 setThreadSafeIntern();
146 }
147
148 DLLLOCAL void setClosure() {
149 if (type == VT_LOCAL || type == VT_LOCAL_TS)
150 setClosureIntern();
151 }
152
153 DLLLOCAL void setPublic() {
154 assert(type == VT_GLOBAL);
155 ref.var->setPublic();
156 }
157
158 DLLLOCAL void parseAssigned() {
159 assert(type != VT_IMMEDIATE);
160 if (type == VT_LOCAL || type == VT_CLOSURE || type == VT_LOCAL_TS)
161 ref.id->parseAssigned();
162 }
163
164 DLLLOCAL bool scanMembers(RSetHelper& rsh);
165
166protected:
167 NamedScope name;
168 qore_var_t type : 4;
169 bool new_decl : 1; // is this a new variable declaration
170 bool explicit_scope : 1; // scope was explicitly provided
171
172 DLLLOCAL ~VarRefNode() {
173 //printd(5, "VarRefNode::~VarRefNode() deleting variable reference %p %s\n", this, name.ostr ? name.ostr : "<taken>");
174 assert(type != VT_IMMEDIATE || !ref.cvv);
175 assert(type != VT_IMMEDIATE || !ref.cvv);
176 }
177
178 DLLLOCAL virtual bool derefImpl(ExceptionSink* xsink) {
179 if (type == VT_IMMEDIATE) {
180 assert(false);
181 ref.cvv->deref(xsink);
182#ifdef DEBUG
183 ref.cvv = nullptr;
184#endif
185 }
186 return true;
187 }
188
189 DLLLOCAL virtual QoreValue evalImpl(bool& needs_deref, ExceptionSink* xsink) const;
190
191 DLLLOCAL void resolve(const QoreTypeInfo* typeInfo);
192 DLLLOCAL int parseInitIntern(QoreParseContext& parse_context, bool is_new = false);
193 DLLLOCAL VarRefNewObjectNode* globalMakeNewCall(QoreValue args);
194
195 // initializes during parsing
196 DLLLOCAL virtual int parseInitImpl(QoreValue& val, QoreParseContext& parse_context);
197
198 DLLLOCAL virtual const QoreTypeInfo* parseGetTypeInfo() const {
199 if (type == VT_LOCAL || type == VT_CLOSURE || type == VT_LOCAL_TS)
200 return ref.id->parseGetTypeInfo();
201 if (type == VT_GLOBAL || type == VT_THREAD_LOCAL)
202 return ref.var->parseGetTypeInfo();
203 return 0;
204 }
205
206 DLLLOCAL virtual const QoreTypeInfo* parseGetTypeInfoForInitialAssignment() const {
207 const QoreTypeInfo* rv;
208 if (type == VT_LOCAL || type == VT_CLOSURE || type == VT_LOCAL_TS) {
209 rv = ref.id->parseGetTypeInfoForInitialAssignment();
210 } else if (type == VT_GLOBAL || type == VT_THREAD_LOCAL) {
211 rv = ref.var->parseGetTypeInfoForInitialAssignment();
212 } else {
213 rv = nullptr;
214 }
215 if (rv && QoreTypeInfo::isReference(rv)) {
216 return QoreTypeInfo::getHardReference(rv);
217 }
218 return rv;
219 }
220
221 DLLLOCAL void setThreadSafeIntern() {
222 ref.id->setClosureUse();
223 type = VT_LOCAL_TS;
224 }
225
226 DLLLOCAL void setClosureIntern() {
227 ref.id->setClosureUse();
228 type = VT_CLOSURE;
229 }
230
231 DLLLOCAL VarRefNode(const QoreProgramLocation* loc, char* n, ClosureVarValue* cvv)
232 : ParseNode(loc, NT_VARREF, true, false), name(n), type(VT_IMMEDIATE), new_decl(false),
233 explicit_scope(false) {
234 ref.cvv = cvv;
235 cvv->ref();
236 }
237
238 DLLLOCAL VarRefNode(const QoreProgramLocation* loc, char* n, Var* n_var, bool n_has_effect = false,
239 bool n_new_decl = true, qore_var_t type = VT_GLOBAL) : ParseNode(loc, NT_VARREF, true, n_has_effect),
240 name(n), type(type),
241 new_decl(n_new_decl), explicit_scope(false) {
242 ref.var = n_var;
243 }
244};
245
246class GlobalVarRefNode : public VarRefNode {
247protected:
248public:
249 DLLLOCAL GlobalVarRefNode(const QoreProgramLocation* loc, char* n, Var* v)
250 : VarRefNode(loc, n, v, false, false, v && v->isThreadLocal() ? VT_THREAD_LOCAL : VT_GLOBAL) {
251 explicit_scope = true;
252 }
253
254 DLLLOCAL GlobalVarRefNode(const QoreProgramLocation* loc, char* n, const QoreTypeInfo* typeInfo = nullptr,
255 qore_var_t type = VT_GLOBAL);
256 DLLLOCAL GlobalVarRefNode(const QoreProgramLocation* loc, char* n, QoreParseTypeInfo* parseTypeInfo,
257 qore_var_t type = VT_GLOBAL);
258
259 DLLLOCAL void reg();
260};
261
262class RSetHelper;
263
264class VarRefDeclNode : public VarRefNode {
265public:
266 DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, const QoreTypeInfo* n_typeInfo) :
267 VarRefNode(loc, n, t), parseTypeInfo(nullptr), typeInfo(n_typeInfo) {
268 //printd(5, "VarRefDeclNode::VarRefDeclNode() typeInfo: %p %s type: %d (%s)\n", typeInfo, n, n_qt,
269 // getBuiltinTypeName(n_qt));
270 }
271
272 // takes over ownership of class_name
273 DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, char* class_name) :
274 VarRefNode(loc, n, t), parseTypeInfo(new QoreParseTypeInfo(class_name)), typeInfo(0) {
275 //printd(5, "VarRefDeclNode::VarRefDeclNode() this: %p typeInfo: %p %s type: %d class: %s\n", this, typeInfo,
276 // n, type, class_name);
277 }
278
279 // takes over ownership of QoreParseTypeInfo ptr
280 DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, QoreParseTypeInfo* n_parseTypeInfo) :
281 VarRefNode(loc, n, t), parseTypeInfo(n_parseTypeInfo), typeInfo(0) {
282 //printd(5, "VarRefDeclNode::VarRefDeclNode() this: %p typeInfo: %p %s type: %d class: %s\n", this, typeInfo,
283 // n, type, class_name);
284 }
285
286 // takes over ownership of QoreParseTypeInfo ptr
287 DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, const QoreTypeInfo* n_typeInfo,
288 QoreParseTypeInfo* n_parseTypeInfo) :
289 VarRefNode(loc, n, t), parseTypeInfo(n_parseTypeInfo), typeInfo(n_typeInfo) {
290 //printd(5, "VarRefDeclNode::VarRefDeclNode() typeInfo: %p %s type: %d (%s)\n", typeInfo, n, n_qt,
291 // getBuiltinTypeName(n_qt));
292 }
293
294 DLLLOCAL ~VarRefDeclNode() {
295 delete parseTypeInfo;
296 }
297 DLLLOCAL virtual bool parseIsDecl() const {
298 return true;
299 }
300 DLLLOCAL virtual bool isDecl() const {
301 return true;
302 }
303
304 // for checking for new object calls
305 DLLLOCAL virtual AbstractQoreNode* makeNewCall(QoreValue args);
306
307 DLLLOCAL QoreParseTypeInfo* takeParseTypeInfo() {
308 QoreParseTypeInfo* ti = parseTypeInfo;
309 parseTypeInfo = nullptr;
310 return ti;
311 }
312 DLLLOCAL QoreParseTypeInfo* getParseTypeInfo() {
313 return parseTypeInfo;
314 }
315 DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
316 assert(!parseTypeInfo);
317 return typeInfo;
318 }
319 DLLLOCAL virtual void makeGlobal(qore_var_t type);
320
321 DLLLOCAL int parseInitCommon(QoreParseContext& parse_context, bool is_new = false);
322
323protected:
324 QoreParseTypeInfo* parseTypeInfo;
325 const QoreTypeInfo* typeInfo;
326
327 DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, const QoreTypeInfo* n_typeInfo,
328 QoreParseTypeInfo* n_parseTypeInfo, bool n_has_effect) :
329 VarRefNode(loc, n, t, n_has_effect), parseTypeInfo(n_parseTypeInfo), typeInfo(n_typeInfo) {
330 //printd(5, "VarRefDeclNode::VarRefDeclNode() typeInfo: %p %s type: %d (%s)\n", typeInfo, n, n_qt,
331 // getBuiltinTypeName(n_qt));
332 }
333
334 DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, Var* var, const QoreTypeInfo* n_typeInfo,
335 QoreParseTypeInfo* n_parseTypeInfo) :
336 VarRefNode(loc, n, var, true), parseTypeInfo(n_parseTypeInfo), typeInfo(n_typeInfo) {
337 }
338
339 // initializes during parsing
340 DLLLOCAL virtual int parseInitImpl(QoreValue& val, QoreParseContext& parse_context);
341
342 DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, ClosureVarValue* cvv,
343 const QoreTypeInfo* n_typeInfo) : VarRefNode(loc, n, cvv), parseTypeInfo(0), typeInfo(n_typeInfo) {
344 }
345};
346
347class VarRefImmediateNode : public VarRefDeclNode {
348public:
349 DLLLOCAL VarRefImmediateNode(const QoreProgramLocation* loc, char* n, ClosureVarValue* cvv,
350 const QoreTypeInfo* n_typeInfo) : VarRefDeclNode(loc, n, cvv, n_typeInfo) {
351 //printd(5, "VarRefImmediateNode::VarRefImmediateNode() this: %p '%s' cvv: %p\n", this, name.ostr, cvv);
352 }
353
354 DLLLOCAL virtual ~VarRefImmediateNode() {
355 //printd(5, "VarRefImmediateNode::~VarRefImmediateNode() this: %p '%s'\n", this, name.ostr);
356 assert(!ref.cvv);
357 }
358
359protected:
360 DLLLOCAL virtual bool derefImpl(ExceptionSink* xsink) {
361 //printd(5, "VarRefImmediateNode::derefImpl() this: %p '%s' cvv: %p\n", this, name.ostr, ref.cvv);
362 ref.cvv->deref(xsink);
363#ifdef DEBUG
364 ref.cvv = nullptr;
365#endif
366 return true;
367 }
368
369private:
370 DLLLOCAL void deref() {
371 assert(false);
372 if (ROdereference()) {
373 delete this;
374 }
375 }
376};
377
378// special thread-local variables with global scope used to handle module loading errors
381class VarRefTryModuleErrorNode : public VarRefDeclNode {
382public:
383 DLLLOCAL VarRefTryModuleErrorNode(const QoreProgramLocation* loc, char* n)
384 : VarRefDeclNode(loc, n, VT_LOCAL, hashTypeInfo) {
385 }
386
387 DLLLOCAL virtual ~VarRefTryModuleErrorNode() {
388 }
389};
390
391class VarRefNewObjectNode : public VarRefDeclNode, public FunctionCallBase {
392public:
393 DLLLOCAL VarRefNewObjectNode(const QoreProgramLocation* loc, char* n, const QoreTypeInfo* n_typeInfo,
394 QoreParseTypeInfo* n_parseTypeInfo, QoreParseListNode* n_args, qore_var_t t) :
395 VarRefDeclNode(loc, n, t, n_typeInfo, n_parseTypeInfo, true), FunctionCallBase(n_args) {
396 }
397
398 DLLLOCAL VarRefNewObjectNode(const QoreProgramLocation* loc, char* n, Var* var, QoreParseListNode* n_args,
399 const QoreTypeInfo* n_typeInfo, QoreParseTypeInfo* n_parseTypeInfo) :
400 VarRefDeclNode(loc, n, var, n_typeInfo, n_parseTypeInfo), FunctionCallBase(n_args) {
401 }
402
403 DLLLOCAL virtual ~VarRefNewObjectNode() {
404 //printd(5, "VarRefNewObjectNode::~VarRefNewObjectNode() this: %p (%s)\n", this, getName());
405 new_args.discard(nullptr);
406 }
407
408 DLLLOCAL virtual bool stayInTree() const {
409 return true;
410 }
411
412 DLLLOCAL const char* parseGetTypeName() const {
413 return typeInfo ? QoreTypeInfo::getName(typeInfo) : parseTypeInfo->cscope->getIdentifier();
414 }
415
416 DLLLOCAL QoreParseListNode* takeParseArgs() {
417 QoreParseListNode* rv = parse_args;
418 parse_args = nullptr;
419 return rv;
420 }
421
422protected:
423 enum vrn_type_e : unsigned char {
424 VRN_NONE = 0,
425 VRN_OBJECT = 1,
426 VRN_HASHDECL = 2,
427 VRN_COMPLEXHASH = 3,
428 VRN_COMPLEXLIST = 4,
429 } vrn_type = VRN_NONE;
430 QoreValue new_args;
431 bool runtime_check = false;
432
433 DLLLOCAL virtual QoreValue evalImpl(bool& needs_deref, ExceptionSink* xsink) const;
434
435 // initializes during parsing
436 DLLLOCAL virtual int parseInitImpl(QoreValue& val, QoreParseContext& parse_context);
437
438 DLLLOCAL int parseInitConstructorCall(const QoreProgramLocation* loc, QoreParseContext& parse_context,
439 const QoreClass* qc);
440
441 DLLLOCAL int parseInitHashDeclInitialization(const QoreProgramLocation* loc, QoreParseContext& parse_context,
442 const TypedHashDecl* hd);
443
444 DLLLOCAL int parseInitComplexHashInitialization(const QoreProgramLocation* loc, QoreParseContext& parse_context);
445
446 DLLLOCAL int parseInitComplexListInitialization(const QoreProgramLocation* loc, QoreParseContext& parse_context);
447};
448
449#endif
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:57
DLLEXPORT void ref() const
increments the reference count
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:50
defines a Qore-language class
Definition: QoreClass.h:253
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and deletes the object when references = 0
typed hash declaration
Definition: TypedHashDecl.h:44
Definition: VarRefNode.h:381
const qore_type_t NT_VARREF
type value for VarRefNode
Definition: node_types.h:56
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:276