Qore Programming Language  0.9.16
VarRefNode.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  VarRefNode.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2020 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 protected:
45  NamedScope name;
46  qore_var_t type : 4;
47  bool new_decl : 1; // is this a new variable declaration
48  bool explicit_scope : 1; // scope was explicitly provided
49 
50  DLLLOCAL ~VarRefNode() {
51  //printd(5, "VarRefNode::~VarRefNode() deleting variable reference %p %s\n", this, name.ostr ? name.ostr : "<taken>");
52  assert(type != VT_IMMEDIATE || !ref.cvv);
53  assert(type != VT_IMMEDIATE || !ref.cvv);
54  }
55 
56  DLLLOCAL virtual bool derefImpl(ExceptionSink* xsink) {
57  if (type == VT_IMMEDIATE) {
58  assert(false);
59  ref.cvv->deref(xsink);
60 #ifdef DEBUG
61  ref.cvv = 0;
62 #endif
63  }
64  return true;
65  }
66 
67  DLLLOCAL virtual QoreValue evalImpl(bool& needs_deref, ExceptionSink* xsink) const;
68 
69  DLLLOCAL void resolve(const QoreTypeInfo* typeInfo);
70  DLLLOCAL void parseInitIntern(LocalVar* oflag, int pflag, int& lvids, const QoreTypeInfo* typeInfo, bool is_new = false);
71  DLLLOCAL VarRefNewObjectNode* globalMakeNewCall(QoreValue args);
72 
73  // initializes during parsing
74  DLLLOCAL virtual void parseInitImpl(QoreValue& val, LocalVar *oflag, int pflag, int &lvids, const QoreTypeInfo *&typeInfo);
75 
76  DLLLOCAL virtual const QoreTypeInfo* parseGetTypeInfo() const {
77  if (type == VT_LOCAL || type == VT_CLOSURE || type == VT_LOCAL_TS)
78  return ref.id->parseGetTypeInfo();
79  if (type == VT_GLOBAL)
80  return ref.var->parseGetTypeInfo();
81  return 0;
82  }
83 
84  DLLLOCAL virtual const QoreTypeInfo* parseGetTypeInfoForInitialAssignment() const {
85  const QoreTypeInfo* rv;
86  if (type == VT_LOCAL || type == VT_CLOSURE || type == VT_LOCAL_TS) {
87  rv = ref.id->parseGetTypeInfoForInitialAssignment();
88  } else if (type == VT_GLOBAL) {
89  rv = ref.var->parseGetTypeInfoForInitialAssignment();
90  } else {
91  rv = nullptr;
92  }
93  if (rv && QoreTypeInfo::isReference(rv)) {
94  return QoreTypeInfo::getHardReference(rv);
95  }
96  return rv;
97  }
98 
99  DLLLOCAL void setThreadSafeIntern() {
100  ref.id->setClosureUse();
101  type = VT_LOCAL_TS;
102  }
103 
104  DLLLOCAL void setClosureIntern() {
105  ref.id->setClosureUse();
106  type = VT_CLOSURE;
107  }
108 
109  DLLLOCAL VarRefNode(const QoreProgramLocation* loc, char* n, ClosureVarValue* cvv) : ParseNode(loc, NT_VARREF, true, false), name(n), type(VT_IMMEDIATE), new_decl(false), explicit_scope(false) {
110  ref.cvv = cvv;
111  cvv->ref();
112  }
113 
114  DLLLOCAL VarRefNode(const QoreProgramLocation* loc, char* n, Var* n_var, bool n_has_effect = false, bool n_new_decl = true) : ParseNode(loc, NT_VARREF, true, n_has_effect), name(n), type(VT_GLOBAL), new_decl(n_new_decl), explicit_scope(false) {
115  ref.var = n_var;
116  }
117 
118 public:
119  union var_u {
120  LocalVar* id; // for local variables
121  Var* var; // for global variables
122  ClosureVarValue* cvv; // for immediate values; used with references
123  } ref;
124 
125  // takes over memory for "n"
126  DLLLOCAL VarRefNode(const QoreProgramLocation* loc, char* n, qore_var_t t, bool n_has_effect = false) : ParseNode(loc, NT_VARREF, true, n_has_effect), name(n), type(t), new_decl(t == VT_LOCAL), explicit_scope(false) {
127  if (type == VT_LOCAL)
128  ref.id = nullptr;
129  assert(type != VT_GLOBAL);
130  }
131 
132  DLLLOCAL VarRefNode(const QoreProgramLocation* loc, char* n, LocalVar* n_id, bool in_closure) : ParseNode(loc, NT_VARREF, true, false), name(n), new_decl(false), explicit_scope(false) {
133  ref.id = n_id;
134  if (in_closure) {
135  setClosureIntern();
136  } else {
137  type = VT_LOCAL;
138  }
139  }
140 
142 
144  DLLLOCAL bool parseEqualTo(const VarRefNode& other) const;
145 
146  DLLLOCAL virtual int getAsString(QoreString& str, int foff, ExceptionSink* xsink) const;
147  DLLLOCAL virtual QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const;
148 
149  DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
150  if (type == VT_LOCAL || type == VT_CLOSURE || type == VT_LOCAL_TS)
151  return ref.id->getTypeInfo();
152  if (type == VT_GLOBAL)
153  return ref.var->getTypeInfo();
154  return 0;
155  }
156 
157  // returns the type name as a c string
158  DLLLOCAL virtual const char* getTypeName() const;
159 
160  DLLLOCAL virtual bool stayInTree() const {
161  return !(type == VT_GLOBAL);
162  }
163 
164  DLLLOCAL virtual bool parseIsDecl() const { return type != VT_UNRESOLVED; }
165  DLLLOCAL virtual bool isDecl() const { return false; }
166  DLLLOCAL bool explicitScope() const { return explicit_scope; }
167  DLLLOCAL void setExplicitScope() { explicit_scope = true; }
168 
169  // will only be called on *VarRefNewObjectNode objects, but this is their common class
170  DLLLOCAL virtual const char* parseGetTypeName() const {
171  assert(false);
172  return nullptr;
173  }
174 
175  // for checking for new object calls
176  DLLLOCAL virtual AbstractQoreNode* makeNewCall(QoreValue args);
177 
178  DLLLOCAL bool isGlobalDecl() const { return new_decl; }
179 
180  DLLLOCAL bool isGlobalVar() const { return type == VT_GLOBAL; }
181 
182  //DLLLOCAL VarRefNode* isOptimized(const QoreTypeInfo*& typeInfo) const;
183  DLLLOCAL int getLValue(LValueHelper& lvh, bool for_remove) const;
184 
185  DLLLOCAL bool isRef() const {
186  if (type == VT_LOCAL)
187  return ref.id->isRef();
188  if (type == VT_IMMEDIATE)
189  return true;
190  assert(type == VT_GLOBAL);
191  return ref.var->isRef();
192  }
193 
194  DLLLOCAL void remove(LValueRemoveHelper& lvrh);
195 
196  DLLLOCAL qore_var_t getType() const { return type; }
197  DLLLOCAL const char* getName() const { return name.ostr; }
198  // called when a list of variables is declared
199  DLLLOCAL void makeLocal() {
200  assert(type != VT_GLOBAL);
201  type = VT_LOCAL;
202  new_decl = true;
203  ref.id = nullptr;
204  }
205  // called when a list of variables is declared
206  DLLLOCAL virtual void makeGlobal();
207 
208  // takes the name - caller owns the memory
209  DLLLOCAL char* takeName() {
210  assert(name.ostr);
211  return name.takeName();
212  }
213 
214  DLLLOCAL void setThreadSafe() {
215  if (type == VT_LOCAL)
216  setThreadSafeIntern();
217  }
218 
219  DLLLOCAL void setClosure() {
220  if (type == VT_LOCAL || type == VT_LOCAL_TS)
221  setClosureIntern();
222  }
223 
224  DLLLOCAL void setPublic() {
225  assert(type == VT_GLOBAL);
226  ref.var->setPublic();
227  }
228 
229  DLLLOCAL void parseAssigned() {
230  assert(type != VT_IMMEDIATE);
231  if (type == VT_LOCAL || type == VT_CLOSURE || type == VT_LOCAL_TS)
232  ref.id->parseAssigned();
233  }
234 
235  DLLLOCAL bool scanMembers(RSetHelper& rsh);
236 };
237 
238 class GlobalVarRefNode : public VarRefNode {
239 protected:
240 public:
241  DLLLOCAL GlobalVarRefNode(const QoreProgramLocation* loc, char* n, Var* v) : VarRefNode(loc, n, v, false, false) {
242  explicit_scope = true;
243  }
244 
245  DLLLOCAL GlobalVarRefNode(const QoreProgramLocation* loc, char* n, const QoreTypeInfo* typeInfo = 0);
246  DLLLOCAL GlobalVarRefNode(const QoreProgramLocation* loc, char* n, QoreParseTypeInfo* parseTypeInfo);
247 
248  DLLLOCAL void reg();
249 };
250 
251 class RSetHelper;
252 
253 class VarRefDeclNode : public VarRefNode {
254 protected:
255  QoreParseTypeInfo* parseTypeInfo;
256  const QoreTypeInfo* typeInfo;
257 
258  DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, const QoreTypeInfo* n_typeInfo, QoreParseTypeInfo* n_parseTypeInfo, bool n_has_effect) :
259  VarRefNode(loc, n, t, n_has_effect), parseTypeInfo(n_parseTypeInfo), typeInfo(n_typeInfo) {
260  //printd(5, "VarRefDeclNode::VarRefDeclNode() typeInfo: %p %s type: %d (%s)\n", typeInfo, n, n_qt, getBuiltinTypeName(n_qt));
261  }
262 
263  DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, Var* var, const QoreTypeInfo* n_typeInfo, QoreParseTypeInfo* n_parseTypeInfo) :
264  VarRefNode(loc, n, var, true), parseTypeInfo(n_parseTypeInfo), typeInfo(n_typeInfo) {
265  }
266 
267  // initializes during parsing
268  DLLLOCAL virtual void parseInitImpl(QoreValue& val, LocalVar *oflag, int pflag, int &lvids, const QoreTypeInfo *&typeInfo);
269 
270  DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, ClosureVarValue* cvv, const QoreTypeInfo* n_typeInfo) : VarRefNode(loc, n, cvv), parseTypeInfo(0), typeInfo(n_typeInfo) {
271  }
272 
273 public:
274  DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, const QoreTypeInfo* n_typeInfo) :
275  VarRefNode(loc, n, t), parseTypeInfo(nullptr), typeInfo(n_typeInfo) {
276  //printd(5, "VarRefDeclNode::VarRefDeclNode() typeInfo: %p %s type: %d (%s)\n", typeInfo, n, n_qt, getBuiltinTypeName(n_qt));
277  }
278 
279  // takes over ownership of class_name
280  DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, char* class_name) :
281  VarRefNode(loc, n, t), parseTypeInfo(new QoreParseTypeInfo(class_name)), typeInfo(0) {
282  //printd(5, "VarRefDeclNode::VarRefDeclNode() this: %p typeInfo: %p %s type: %d class: %s\n", this, typeInfo, n, type, class_name);
283  }
284 
285  // takes over ownership of QoreParseTypeInfo ptr
286  DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, QoreParseTypeInfo* n_parseTypeInfo) :
287  VarRefNode(loc, n, t), parseTypeInfo(n_parseTypeInfo), typeInfo(0) {
288  //printd(5, "VarRefDeclNode::VarRefDeclNode() this: %p typeInfo: %p %s type: %d class: %s\n", this, typeInfo, n, type, class_name);
289  }
290 
291  // takes over ownership of QoreParseTypeInfo ptr
292  DLLLOCAL VarRefDeclNode(const QoreProgramLocation* loc, char* n, qore_var_t t, const QoreTypeInfo* n_typeInfo, QoreParseTypeInfo* n_parseTypeInfo) :
293  VarRefNode(loc, n, t), parseTypeInfo(n_parseTypeInfo), typeInfo(n_typeInfo) {
294  //printd(5, "VarRefDeclNode::VarRefDeclNode() typeInfo: %p %s type: %d (%s)\n", typeInfo, n, n_qt, getBuiltinTypeName(n_qt));
295  }
296 
297  DLLLOCAL ~VarRefDeclNode() {
298  delete parseTypeInfo;
299  }
300  DLLLOCAL virtual bool parseIsDecl() const {
301  return true;
302  }
303  DLLLOCAL virtual bool isDecl() const {
304  return true;
305  }
306 
307  // for checking for new object calls
308  DLLLOCAL virtual AbstractQoreNode* makeNewCall(QoreValue args);
309 
310  DLLLOCAL QoreParseTypeInfo* takeParseTypeInfo() {
311  QoreParseTypeInfo* ti = parseTypeInfo;
312  parseTypeInfo = nullptr;
313  return ti;
314  }
315  DLLLOCAL QoreParseTypeInfo* getParseTypeInfo() {
316  return parseTypeInfo;
317  }
318  DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
319  assert(!parseTypeInfo);
320  return typeInfo;
321  }
322  DLLLOCAL virtual void makeGlobal();
323 
324  DLLLOCAL void parseInitCommon(LocalVar* oflag, int pflag, int& lvids, bool is_new = false);
325 };
326 
327 class VarRefImmediateNode : public VarRefDeclNode {
328 private:
329  DLLLOCAL void deref() {
330  assert(false);
331  if (ROdereference())
332  delete this;
333  }
334 
335 protected:
336  DLLLOCAL virtual bool derefImpl(ExceptionSink* xsink) {
337  //printd(5, "VarRefImmediateNode::derefImpl() this: %p '%s' cvv: %p\n", this, name.ostr, ref.cvv);
338  ref.cvv->deref(xsink);
339 #ifdef DEBUG
340  ref.cvv = 0;
341 #endif
342  return true;
343  }
344 
345 public:
346  DLLLOCAL VarRefImmediateNode(const QoreProgramLocation* loc, char* n, ClosureVarValue* cvv, const QoreTypeInfo* n_typeInfo) : VarRefDeclNode(loc, n, cvv, n_typeInfo) {
347  //printd(5, "VarRefImmediateNode::VarRefImmediateNode() this: %p '%s' cvv: %p\n", this, name.ostr, cvv);
348  }
349 
350  DLLLOCAL virtual ~VarRefImmediateNode() {
351  //printd(5, "VarRefImmediateNode::~VarRefImmediateNode() this: %p '%s'\n", this, name.ostr);
352  assert(!ref.cvv);
353  }
354 };
355 
356 // special thread-local variables with global scope used to handle module loading errors, created by the %try-module parse directive if module loading fails
357 class VarRefTryModuleErrorNode : public VarRefDeclNode {
358 public:
359  DLLLOCAL VarRefTryModuleErrorNode(const QoreProgramLocation* loc, char* n) : VarRefDeclNode(loc, n, VT_LOCAL, hashTypeInfo) {
360  }
361 
362  DLLLOCAL virtual ~VarRefTryModuleErrorNode() {
363  }
364 };
365 
366 class VarRefNewObjectNode : public VarRefDeclNode, public FunctionCallBase {
367 public:
368  DLLLOCAL VarRefNewObjectNode(const QoreProgramLocation* loc, char* n, const QoreTypeInfo* n_typeInfo, QoreParseTypeInfo* n_parseTypeInfo, QoreParseListNode* n_args, qore_var_t t) :
369  VarRefDeclNode(loc, n, t, n_typeInfo, n_parseTypeInfo, true), FunctionCallBase(n_args) {
370  }
371 
372  DLLLOCAL VarRefNewObjectNode(const QoreProgramLocation* loc, char* n, Var* var, QoreParseListNode* n_args, const QoreTypeInfo* n_typeInfo, QoreParseTypeInfo* n_parseTypeInfo) :
373  VarRefDeclNode(loc, n, var, n_typeInfo, n_parseTypeInfo), FunctionCallBase(n_args) {
374  }
375 
376  DLLLOCAL virtual ~VarRefNewObjectNode() {
377  //printd(5, "VarRefNewObjectNode::~VarRefNewObjectNode() this: %p (%s)\n", this, getName());
378  new_args.discard(nullptr);
379  }
380 
381  DLLLOCAL virtual bool stayInTree() const {
382  return true;
383  }
384 
385  DLLLOCAL const char* parseGetTypeName() const {
386  return typeInfo ? QoreTypeInfo::getName(typeInfo) : parseTypeInfo->cscope->getIdentifier();
387  }
388 
389  DLLLOCAL QoreParseListNode* takeParseArgs() {
390  QoreParseListNode* rv = parse_args;
391  parse_args = nullptr;
392  return rv;
393  }
394 
395 protected:
396  enum vrn_type_e : unsigned char {
397  VRN_NONE = 0,
398  VRN_OBJECT = 1,
399  VRN_HASHDECL = 2,
400  VRN_COMPLEXHASH = 3,
401  VRN_COMPLEXLIST = 4,
402  } vrn_type = VRN_NONE;
403  QoreValue new_args;
404  bool runtime_check = false;
405 
406  DLLLOCAL virtual QoreValue evalImpl(bool& needs_deref, ExceptionSink* xsink) const;
407 
408  // initializes during parsing
409  DLLLOCAL virtual void parseInitImpl(QoreValue& val, LocalVar *oflag, int pflag, int &lvids, const QoreTypeInfo *&typeInfo);
410 
411  DLLLOCAL void parseInitConstructorCall(const QoreProgramLocation* loc, LocalVar* oflag, int pflag, int& lvids, const QoreClass* qc);
412 
413  DLLLOCAL void parseInitHashDeclInitialization(const QoreProgramLocation* loc, LocalVar* oflag, int pflag, int& lvids, const TypedHashDecl* hd);
414 
415  DLLLOCAL void parseInitComplexHashInitialization(const QoreProgramLocation* loc, LocalVar* oflag, int pflag, int& lvids, const QoreTypeInfo* ti);
416 
417  DLLLOCAL void parseInitComplexListInitialization(const QoreProgramLocation* loc, LocalVar* oflag, int pflag, int& lvids, const QoreTypeInfo* ti);
418 };
419 
420 #endif
QoreValue
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
QoreClass
defines a Qore-language class
Definition: QoreClass.h:239
QoreReferenceCounter::ROdereference
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
QoreString
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
TypedHashDecl
typed hash declaration
Definition: TypedHashDecl.h:44
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
AbstractQoreNode::ref
DLLEXPORT void ref() const
increments the reference count
AbstractQoreNode::deref
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
NT_VARREF
const qore_type_t NT_VARREF
type value for VarRefNode
Definition: node_types.h:56
AbstractQoreNode
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:54