Qore Programming Language  1.12.0
VarRefNode.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  VarRefNode.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2022 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 
37 class VarRefNewObjectNode;
38 class LocalVar;
39 class LocalVarValue;
40 class Var;
41 hashdecl ClosureVarValue;
42 
43 class VarRefNode : public ParseNode {
44 public:
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 
166 protected:
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 
246 class GlobalVarRefNode : public VarRefNode {
247 protected:
248 public:
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 
262 class RSetHelper;
263 
264 class VarRefDeclNode : public VarRefNode {
265 public:
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 
323 protected:
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 
347 class VarRefImmediateNode : public VarRefDeclNode {
348 public:
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 
359 protected:
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 
369 private:
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
381 class VarRefTryModuleErrorNode : public VarRefDeclNode {
382 public:
383  DLLLOCAL VarRefTryModuleErrorNode(const QoreProgramLocation* loc, char* n)
384  : VarRefDeclNode(loc, n, VT_LOCAL, hashTypeInfo) {
385  }
386 
387  DLLLOCAL virtual ~VarRefTryModuleErrorNode() {
388  }
389 };
390 
391 class VarRefNewObjectNode : public VarRefDeclNode, public FunctionCallBase {
392 public:
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 
422 protected:
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
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
defines a Qore-language class
Definition: QoreClass.h:249
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
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:275