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