Qore Programming Language  0.9.16
ConstantList.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  ConstantList.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2020 Qore Technologies, s.r.o.
8 
9  constants can only be defined when parsing
10  constants values will be substituted during the 2nd parse phase
11 
12  reads and writes are (must be) wrapped under the program-level parse lock
13 
14  Permission is hereby granted, free of charge, to any person obtaining a
15  copy of this software and associated documentation files (the "Software"),
16  to deal in the Software without restriction, including without limitation
17  the rights to use, copy, modify, merge, publish, distribute, sublicense,
18  and/or sell copies of the Software, and to permit persons to whom the
19  Software is furnished to do so, subject to the following conditions:
20 
21  The above copyright notice and this permission notice shall be included in
22  all copies or substantial portions of the Software.
23 
24  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30  DEALINGS IN THE SOFTWARE.
31 
32  Note that the Qore library is released under a choice of three open-source
33  licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
34  information.
35 */
36 
37 #ifndef _QORE_CONSTANTLIST_H
38 
39 #define _QORE_CONSTANTLIST_H
40 
41 #include <qore/common.h>
42 #include "qore/intern/ParseNode.h"
43 
44 #include <string>
45 
46 class qore_ns_private;
47 class qore_class_private;
48 
49 // tricky structure that holds 2 types of pointers and a flag in the space of 1 pointer
50 // the flag is in the low bit since memory has to be aligned anyway we have at a few bits of space for flags
51 hashdecl ClassNs {
52  // if the low bit is set, then ptr is a qore_ns_priv*, otherwise it's a qore_class_private
53  size_t ptr;
54 
55  DLLLOCAL ClassNs(qore_class_private* qc) : ptr((size_t)qc) {
56  }
57 
58  DLLLOCAL ClassNs(qore_ns_private* ns) {
59  ptr = ((size_t)ns) | (size_t)1;
60  }
61 
62  DLLLOCAL ClassNs(const ClassNs& old) : ptr(old.ptr) {
63  }
64 
65  DLLLOCAL qore_class_private* getClass() const {
66  return (!(ptr & (size_t)1)) ? (qore_class_private*)ptr : nullptr;
67  }
68 
69  DLLLOCAL qore_ns_private* getNs() const {
70  return (ptr & (size_t)1) ? (qore_ns_private*)(ptr & ~(size_t)1) : nullptr;
71  }
72 
73  DLLLOCAL bool isNs() const {
74  return (bool)(ptr & (size_t)1);
75  }
76 
77 #ifdef DEBUG
78  DLLLOCAL const char* getType() const {
79  return isNs() ? "namespace" : "class";
80  }
81 
82  DLLLOCAL const char* getName() const;
83 #endif
84 };
85 
86 class RuntimeConstantRefNode;
87 
88 class ConstantEntry : public QoreReferenceCounter {
89  friend class ConstantEntryInitHelper;
90  friend class RuntimeConstantRefNode;
91  friend class ConstantList;
92 
93 public:
94  const QoreProgramLocation* loc;
95  ParseWarnOptions pwo;
96  std::string name;
97  const QoreTypeInfo* typeInfo;
98  QoreValue val;
99  bool in_init : 1, // being initialized
100  pub : 1, // public constant (modules only)
101  init : 1, // already initialized
102  builtin : 1 // builtin vs user
103  ;
104 
105  DLLLOCAL ConstantEntry(const QoreProgramLocation* loc, const char* n, QoreValue v,
106  const QoreTypeInfo* ti = nullptr, bool n_pub = false, bool n_init = false, bool n_builtin = false,
107  ClassAccess n_access = Public);
108 
109  DLLLOCAL ConstantEntry(const ConstantEntry& old);
110 
111  DLLLOCAL void deref(ExceptionSink* xsink) {
112  if (ROdereference()) {
113  del(xsink);
114  delete this;
115  }
116  }
117 
118  DLLLOCAL void deref(QoreListNode& l) {
119  if (ROdereference()) {
120  del(l);
121  delete this;
122  }
123  }
124 
125  DLLLOCAL void ref() {
126  ROreference();
127  }
128 
129  DLLLOCAL ConstantEntry* refSelf() {
130  ref();
131  return this;
132  }
133 
134  DLLLOCAL int parseInit(ClassNs ptr);
135 
136  DLLLOCAL QoreValue get(const QoreProgramLocation* loc, const QoreTypeInfo*& constantTypeInfo, ClassNs ptr) {
137  if (in_init) {
138  parse_error(*loc, "recursive constant reference found to constant '%s'", name.c_str());
139  constantTypeInfo = nothingTypeInfo;
140  return QoreValue();
141  }
142 
143  if (!init && parseInit(ptr)) {
144  constantTypeInfo = nothingTypeInfo;
145  return QoreValue();
146  }
147 
148  constantTypeInfo = typeInfo;
149  return val;
150  }
151 
152  DLLLOCAL const char* getName() const {
153  return name.c_str();
154  }
155 
156  DLLLOCAL const std::string& getNameStr() const {
157  return name;
158  }
159 
160  DLLLOCAL bool isPublic() const {
161  return pub;
162  }
163 
164  DLLLOCAL bool isUserPublic() const {
165  return pub && !builtin;
166  }
167 
168  DLLLOCAL bool isSystem() const {
169  return builtin;
170  }
171 
172  DLLLOCAL bool isUser() const {
173  return !builtin;
174  }
175 
176  DLLLOCAL ClassAccess getAccess() const {
177  return access;
178  }
179 
180  DLLLOCAL const char* getModuleName() const {
181  return from_module.empty() ? nullptr : from_module.c_str();
182  }
183 
184 protected:
185  AbstractQoreNode* saved_node = nullptr;
186  ClassAccess access;
187  std::string from_module;
188 
189  DLLLOCAL ~ConstantEntry() {
190  assert(!saved_node);
191  assert(val.isNothing());
192  }
193 
194  DLLLOCAL int scanValue(const QoreValue& n) const;
195 
196  DLLLOCAL void del(ExceptionSink* xsink);
197  DLLLOCAL void del(QoreListNode& l);
198 
199  DLLLOCAL void setModuleName() {
200  assert(from_module.empty());
201  const char* mod_name = get_module_context_name();
202  if (mod_name) {
203  from_module = mod_name;
204  }
205  //printd(5, "qore_ns_private::setModuleName() this: %p mod: %s\n", this, mod_name ? mod_name : "n/a");
206  }
207 };
208 
209 class ConstantEntryInitHelper {
210 protected:
211  ConstantEntry &ce;
212 
213 public:
214  DLLLOCAL ConstantEntryInitHelper(ConstantEntry& n_ce) : ce(n_ce) {
215  assert(!ce.in_init);
216  assert(!ce.init);
217  ce.in_init = true;
218  //printd(5, "ConstantEntryInitHelper::ConstantEntryInitHelper() '%s'\n", ce.getName());
219  }
220 
221  DLLLOCAL ~ConstantEntryInitHelper() {
222  ce.in_init = false;
223  ce.init = true;
224  //printd(5, "ConstantEntryInitHelper::~ConstantEntryInitHelper() '%s'\n", ce.getName());
225  }
226 };
227 
228 // we use a vector map as the number of constants is generally relatively small
229 // and lookups are only performed during parsing
230 #include <qore/vector_map>
231 typedef vector_map_t<const char*, ConstantEntry*> cnemap_t;
232 /*
233 #ifdef HAVE_QORE_HASH_MAP
234 //#warning compiling with hash_map
235 #include <qore/hash_map_include.h>
236 #include "qore/intern/xxhash.h"
237 
238 typedef HASH_MAP<const char*, ConstantEntry*, qore_hash_str, eqstr> cnemap_t;
239 #else
240 #include <map>
241 typedef std::map<const char*, ConstantEntry*, ltstr> cnemap_t;
242 #endif
243 */
244 
245 class ConstantList {
246  friend class ConstantListIterator;
247  friend class ConstConstantListIterator;
248 
249 private:
250  // not implemented
251  DLLLOCAL ConstantList& operator=(const ConstantList&);
252 
253  DLLLOCAL void clearIntern(ExceptionSink* xsink);
254 
255 protected:
256  // the object that owns the list (either a class or a namespace)
257  ClassNs ptr;
258 
259 public:
260  vector_map_t<std::string, ConstantEntry*> new_cnemap;
261  cnemap_t cnemap;
262 
263  DLLLOCAL ~ConstantList();
264 
265  DLLLOCAL ConstantList(ClassNs p) : ptr(p) {
266  //printd(5, "ConstantList::ConstantList() this: %p cls: %p ns: %p\n", this, ptr.getClass(), ptr.getNs());
267  }
268 
269  DLLLOCAL ConstantList(const ConstantList& old, int64 po, ClassNs p);
270 
271  // do not delete the object returned by this function
272  DLLLOCAL cnemap_t::iterator add(const char* name, QoreValue val, const QoreTypeInfo* typeInfo = nullptr, ClassAccess access = Public);
273 
274  DLLLOCAL cnemap_t::iterator parseAdd(const QoreProgramLocation* loc, const char* name, QoreValue val, const QoreTypeInfo* typeInfo = nullptr, bool pub = false, ClassAccess access = Public);
275 
276  DLLLOCAL ConstantEntry* findEntry(const char* name);
277 
278  DLLLOCAL const ConstantEntry* findEntry(const char* name) const;
279 
280  DLLLOCAL QoreValue find(const char* name, const QoreTypeInfo*& constantTypeInfo, ClassAccess& access, bool& found);
281 
282  DLLLOCAL QoreValue find(const char* name, const QoreTypeInfo*& constantTypeInfo, bool& found) {
283  ClassAccess access;
284  return find(name, constantTypeInfo, access, found);
285  }
286 
287  DLLLOCAL bool inList(const char* name) const;
288  DLLLOCAL bool inList(const std::string& name) const;
289  //DLLLOCAL ConstantList *copy();
290 
291  // assimilate the list without any duplicate checking
292  DLLLOCAL void assimilate(ConstantList& n);
293 
294  // assimilate a constant list in a namespace with duplicate checking (also in pending list)
295  DLLLOCAL void assimilate(ConstantList& n, const char* type, const char* name);
296 
297  // copy all user/public elements of the source list to the target, assuming no duplicates
298  DLLLOCAL void mergeUserPublic(const ConstantList& src);
299 
300  DLLLOCAL int importSystemConstants(const ConstantList& src, ExceptionSink* xsink);
301 
302  // add a constant to a list with duplicate checking (pub & priv + pending)
303  DLLLOCAL void parseAdd(const QoreProgramLocation* loc, const std::string& name, QoreValue val, ClassAccess access, const char* cname);
304 
305  DLLLOCAL void parseInit();
306  DLLLOCAL QoreHashNode* getInfo();
307  DLLLOCAL void parseDeleteAll();
308  DLLLOCAL void clear(QoreListNode& l);
309  DLLLOCAL void deleteAll(ExceptionSink* xsink);
310  DLLLOCAL void reset();
311 
312  DLLLOCAL bool empty() const {
313  return cnemap.empty();
314  }
315 
316  DLLLOCAL cnemap_t::iterator end() {
317  return cnemap.end();
318  }
319 
320  DLLLOCAL cnemap_t::const_iterator end() const {
321  return cnemap.end();
322  }
323 
324  DLLLOCAL void setAccess(ClassAccess access) {
325  for (auto& i : cnemap)
326  i.second->access = access;
327  }
328 };
329 
330 class ConstantListIterator {
331 protected:
332  cnemap_t& cl;
333  cnemap_t::iterator i;
334 
335 public:
336  DLLLOCAL ConstantListIterator(ConstantList& n_cl) : cl(n_cl.cnemap), i(cl.end()) {
337  }
338 
339  DLLLOCAL bool next() {
340  if (i == cl.end())
341  i = cl.begin();
342  else
343  ++i;
344  return i != cl.end();
345  }
346 
347  DLLLOCAL const std::string& getName() const {
348  return i->second->getNameStr();
349  }
350 
351  DLLLOCAL QoreValue getValue() const {
352  return i->second->val;
353  }
354 
355  DLLLOCAL ConstantEntry* getEntry() const {
356  return i->second;
357  }
358 
359  DLLLOCAL ClassAccess getAccess() const {
360  return i->second->getAccess();
361  }
362 
363  DLLLOCAL bool isPublic() const {
364  return i->second->isPublic();
365  }
366 
367  DLLLOCAL bool isUserPublic() const {
368  return i->second->isUserPublic();
369  }
370 };
371 
372 class ConstConstantListIterator {
373 protected:
374  const cnemap_t& cl;
375  cnemap_t::const_iterator i;
376 
377 public:
378  DLLLOCAL ConstConstantListIterator(const ConstantList& n_cl) : cl(n_cl.cnemap), i(cl.end()) {
379  }
380 
381  DLLLOCAL bool next() {
382  if (i == cl.end())
383  i = cl.begin();
384  else
385  ++i;
386  return i != cl.end();
387  }
388 
389  DLLLOCAL const std::string& getName() const {
390  return i->second->getNameStr();
391  }
392 
393  DLLLOCAL const QoreValue getValue() const {
394  return i->second->val;
395  }
396 
397  DLLLOCAL const ConstantEntry* getEntry() const {
398  return i->second;
399  }
400 
401  DLLLOCAL bool isPublic() const {
402  return i->second->isPublic();
403  }
404 
405  DLLLOCAL bool isUserPublic() const {
406  return i->second->isUserPublic();
407  }
408 };
409 
410 class RuntimeConstantRefNode : public ParseNode {
411 protected:
412  ConstantEntry* ce;
413 
414  DLLLOCAL virtual void parseInitImpl(QoreValue& val, LocalVar* oflag, int pflag, int& lvids, const QoreTypeInfo*& typeInfo) {
415  }
416 
417  DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
418  assert(ce->saved_node);
419  return getTypeInfoForValue(ce->saved_node);
420  }
421 
422  DLLLOCAL virtual QoreValue evalImpl(bool& needs_deref, ExceptionSink* xsink) const {
423  assert(ce->saved_node);
424  return ce->saved_node->eval(needs_deref, xsink);
425  }
426 
427  DLLLOCAL ~RuntimeConstantRefNode() {
428  }
429 
430 public:
431  DLLLOCAL RuntimeConstantRefNode(const QoreProgramLocation* loc, ConstantEntry* n_ce) : ParseNode(loc, NT_RTCONSTREF, true, false), ce(n_ce) {
432  assert(ce->saved_node);
433  }
434 
435  DLLLOCAL virtual int getAsString(QoreString& str, int foff, ExceptionSink* xsink) const {
436  assert(ce->saved_node);
437  return ce->saved_node->getAsString(str, foff, xsink);
438  }
439 
440  DLLLOCAL virtual QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const {
441  assert(ce->saved_node);
442  return ce->saved_node->getAsString(del, foff, xsink);
443  }
444 
445  DLLLOCAL virtual const char* getTypeName() const {
446  return ce->saved_node ? ce->saved_node->getTypeName() : "nothing";
447  }
448 };
449 
450 #endif // _QORE_CONSTANTLIST_H
QoreValue
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
QoreHashNode
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
QoreListNode
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
int64
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
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
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
QoreReferenceCounter::ROreference
DLLEXPORT void ROreference() const
atomically increments the reference count
QoreReferenceCounter
provides atomic reference counting to Qore objects
Definition: QoreReferenceCounter.h:44
NT_RTCONSTREF
const qore_type_t NT_RTCONSTREF
type value for RuntimeConstantRefNode
Definition: node_types.h:82
common.h
AbstractQoreNode
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:54