Qore Programming Language  0.9.4.6
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, const QoreTypeInfo* ti = 0, bool n_pub = false, bool n_init = false, bool n_builtin = false, ClassAccess n_access = Public);
106  DLLLOCAL ConstantEntry(const ConstantEntry& old);
107 
108  DLLLOCAL void deref(ExceptionSink* xsink) {
109  if (ROdereference()) {
110  del(xsink);
111  delete this;
112  }
113  }
114 
115  DLLLOCAL void deref(QoreListNode& l) {
116  if (ROdereference()) {
117  del(l);
118  delete this;
119  }
120  }
121 
122  DLLLOCAL void ref() {
123  ROreference();
124  }
125 
126  DLLLOCAL ConstantEntry* refSelf() {
127  ref();
128  return this;
129  }
130 
131  DLLLOCAL int parseInit(ClassNs ptr);
132 
133  DLLLOCAL QoreValue get(const QoreProgramLocation* loc, const QoreTypeInfo*& constantTypeInfo, ClassNs ptr) {
134  if (in_init) {
135  parse_error(*loc, "recursive constant reference found to constant '%s'", name.c_str());
136  constantTypeInfo = nothingTypeInfo;
137  return QoreValue();
138  }
139 
140  if (!init && parseInit(ptr)) {
141  constantTypeInfo = nothingTypeInfo;
142  return QoreValue();
143  }
144 
145  constantTypeInfo = typeInfo;
146  return val;
147  }
148 
149  DLLLOCAL const char* getName() const {
150  return name.c_str();
151  }
152 
153  DLLLOCAL const std::string& getNameStr() const {
154  return name;
155  }
156 
157  DLLLOCAL bool isPublic() const {
158  return pub;
159  }
160 
161  DLLLOCAL bool isUserPublic() const {
162  return pub && !builtin;
163  }
164 
165  DLLLOCAL bool isSystem() const {
166  return builtin;
167  }
168 
169  DLLLOCAL bool isUser() const {
170  return !builtin;
171  }
172 
173  DLLLOCAL ClassAccess getAccess() const {
174  return access;
175  }
176 
177 protected:
178  AbstractQoreNode* saved_node = nullptr;
179  ClassAccess access;
180 
181  DLLLOCAL int scanValue(const QoreValue& n) const;
182 
183  DLLLOCAL void del(ExceptionSink* xsink);
184  DLLLOCAL void del(QoreListNode& l);
185 
186  DLLLOCAL ~ConstantEntry() {
187  assert(!saved_node);
188  assert(val.isNothing());
189  }
190 };
191 
192 class ConstantEntryInitHelper {
193 protected:
194  ConstantEntry &ce;
195 
196 public:
197  DLLLOCAL ConstantEntryInitHelper(ConstantEntry& n_ce) : ce(n_ce) {
198  assert(!ce.in_init);
199  assert(!ce.init);
200  ce.in_init = true;
201  //printd(5, "ConstantEntryInitHelper::ConstantEntryInitHelper() '%s'\n", ce.getName());
202  }
203 
204  DLLLOCAL ~ConstantEntryInitHelper() {
205  ce.in_init = false;
206  ce.init = true;
207  //printd(5, "ConstantEntryInitHelper::~ConstantEntryInitHelper() '%s'\n", ce.getName());
208  }
209 };
210 
211 // we use a vector map as the number of constants is generally relatively small
212 // and lookups are only performed during parsing
213 #include <qore/vector_map>
214 typedef vector_map_t<const char*, ConstantEntry*> cnemap_t;
215 /*
216 #ifdef HAVE_QORE_HASH_MAP
217 //#warning compiling with hash_map
218 #include <qore/hash_map_include.h>
219 #include "qore/intern/xxhash.h"
220 
221 typedef HASH_MAP<const char*, ConstantEntry*, qore_hash_str, eqstr> cnemap_t;
222 #else
223 #include <map>
224 typedef std::map<const char*, ConstantEntry*, ltstr> cnemap_t;
225 #endif
226 */
227 
228 class ConstantList {
229  friend class ConstantListIterator;
230  friend class ConstConstantListIterator;
231 
232 private:
233  // not implemented
234  DLLLOCAL ConstantList& operator=(const ConstantList&);
235 
236  DLLLOCAL void clearIntern(ExceptionSink* xsink);
237 
238 protected:
239  // the object that owns the list (either a class or a namespace)
240  ClassNs ptr;
241 
242 public:
243  vector_map_t<std::string, ConstantEntry*> new_cnemap;
244  cnemap_t cnemap;
245 
246  DLLLOCAL ~ConstantList();
247 
248  DLLLOCAL ConstantList(ClassNs p) : ptr(p) {
249  //printd(5, "ConstantList::ConstantList() this: %p cls: %p ns: %p\n", this, ptr.getClass(), ptr.getNs());
250  }
251 
252  DLLLOCAL ConstantList(const ConstantList& old, int64 po, ClassNs p);
253 
254  // do not delete the object returned by this function
255  DLLLOCAL cnemap_t::iterator add(const char* name, QoreValue val, const QoreTypeInfo* typeInfo = nullptr, ClassAccess access = Public);
256 
257  DLLLOCAL cnemap_t::iterator parseAdd(const QoreProgramLocation* loc, const char* name, QoreValue val, const QoreTypeInfo* typeInfo = nullptr, bool pub = false, ClassAccess access = Public);
258 
259  DLLLOCAL ConstantEntry* findEntry(const char* name);
260 
261  DLLLOCAL const ConstantEntry* findEntry(const char* name) const;
262 
263  DLLLOCAL QoreValue find(const char* name, const QoreTypeInfo*& constantTypeInfo, ClassAccess& access, bool& found);
264 
265  DLLLOCAL QoreValue find(const char* name, const QoreTypeInfo*& constantTypeInfo, bool& found) {
266  ClassAccess access;
267  return find(name, constantTypeInfo, access, found);
268  }
269 
270  DLLLOCAL bool inList(const char* name) const;
271  DLLLOCAL bool inList(const std::string& name) const;
272  //DLLLOCAL ConstantList *copy();
273 
274  // assimilate the list without any duplicate checking
275  DLLLOCAL void assimilate(ConstantList& n);
276 
277  // assimilate a constant list in a namespace with duplicate checking (also in pending list)
278  DLLLOCAL void assimilate(ConstantList& n, const char* type, const char* name);
279 
280  // copy all user/public elements of the source list to the target, assuming no duplicates
281  DLLLOCAL void mergeUserPublic(const ConstantList& src);
282 
283  DLLLOCAL int importSystemConstants(const ConstantList& src, ExceptionSink* xsink);
284 
285  // add a constant to a list with duplicate checking (pub & priv + pending)
286  DLLLOCAL void parseAdd(const QoreProgramLocation* loc, const std::string& name, QoreValue val, ClassAccess access, const char* cname);
287 
288  DLLLOCAL void parseInit();
289  DLLLOCAL QoreHashNode* getInfo();
290  DLLLOCAL void parseDeleteAll();
291  DLLLOCAL void clear(QoreListNode& l);
292  DLLLOCAL void deleteAll(ExceptionSink* xsink);
293  DLLLOCAL void reset();
294 
295  DLLLOCAL bool empty() const {
296  return cnemap.empty();
297  }
298 
299  DLLLOCAL cnemap_t::iterator end() {
300  return cnemap.end();
301  }
302 
303  DLLLOCAL cnemap_t::const_iterator end() const {
304  return cnemap.end();
305  }
306 
307  DLLLOCAL void setAccess(ClassAccess access) {
308  for (auto& i : cnemap)
309  i.second->access = access;
310  }
311 };
312 
313 class ConstantListIterator {
314 protected:
315  cnemap_t& cl;
316  cnemap_t::iterator i;
317 
318 public:
319  DLLLOCAL ConstantListIterator(ConstantList& n_cl) : cl(n_cl.cnemap), i(cl.end()) {
320  }
321 
322  DLLLOCAL bool next() {
323  if (i == cl.end())
324  i = cl.begin();
325  else
326  ++i;
327  return i != cl.end();
328  }
329 
330  DLLLOCAL const std::string& getName() const {
331  return i->second->getNameStr();
332  }
333 
334  DLLLOCAL QoreValue getValue() const {
335  return i->second->val;
336  }
337 
338  DLLLOCAL ConstantEntry* getEntry() const {
339  return i->second;
340  }
341 
342  DLLLOCAL ClassAccess getAccess() const {
343  return i->second->getAccess();
344  }
345 
346  DLLLOCAL bool isPublic() const {
347  return i->second->isPublic();
348  }
349 
350  DLLLOCAL bool isUserPublic() const {
351  return i->second->isUserPublic();
352  }
353 };
354 
355 class ConstConstantListIterator {
356 protected:
357  const cnemap_t& cl;
358  cnemap_t::const_iterator i;
359 
360 public:
361  DLLLOCAL ConstConstantListIterator(const ConstantList& n_cl) : cl(n_cl.cnemap), i(cl.end()) {
362  }
363 
364  DLLLOCAL bool next() {
365  if (i == cl.end())
366  i = cl.begin();
367  else
368  ++i;
369  return i != cl.end();
370  }
371 
372  DLLLOCAL const std::string& getName() const {
373  return i->second->getNameStr();
374  }
375 
376  DLLLOCAL const QoreValue getValue() const {
377  return i->second->val;
378  }
379 
380  DLLLOCAL const ConstantEntry* getEntry() const {
381  return i->second;
382  }
383 
384  DLLLOCAL bool isPublic() const {
385  return i->second->isPublic();
386  }
387 
388  DLLLOCAL bool isUserPublic() const {
389  return i->second->isUserPublic();
390  }
391 };
392 
393 class RuntimeConstantRefNode : public ParseNode {
394 protected:
395  ConstantEntry* ce;
396 
397  DLLLOCAL virtual void parseInitImpl(QoreValue& val, LocalVar* oflag, int pflag, int& lvids, const QoreTypeInfo*& typeInfo) {
398  }
399 
400  DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
401  assert(ce->saved_node);
402  return getTypeInfoForValue(ce->saved_node);
403  }
404 
405  DLLLOCAL virtual QoreValue evalImpl(bool& needs_deref, ExceptionSink* xsink) const {
406  assert(ce->saved_node);
407  return ce->saved_node->eval(needs_deref, xsink);
408  }
409 
410  DLLLOCAL ~RuntimeConstantRefNode() {
411  }
412 
413 public:
414  DLLLOCAL RuntimeConstantRefNode(const QoreProgramLocation* loc, ConstantEntry* n_ce) : ParseNode(loc, NT_RTCONSTREF, true, false), ce(n_ce) {
415  assert(ce->saved_node);
416  }
417 
418  DLLLOCAL virtual int getAsString(QoreString& str, int foff, ExceptionSink* xsink) const {
419  assert(ce->saved_node);
420  return ce->saved_node->getAsString(str, foff, xsink);
421  }
422 
423  DLLLOCAL virtual QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const {
424  assert(ce->saved_node);
425  return ce->saved_node->getAsString(del, foff, xsink);
426  }
427 
428  DLLLOCAL virtual const char* getTypeName() const {
429  return ce->saved_node ? ce->saved_node->getTypeName() : "nothing";
430  }
431 };
432 
433 #endif // _QORE_CONSTANTLIST_H
This is the hash or associative list container type in Qore, dynamically allocated only...
Definition: QoreHashNode.h:50
const qore_type_t NT_RTCONSTREF
type value for RuntimeConstantRefNode
Definition: node_types.h:82
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:54
Qore&#39;s string type supported by the QoreEncoding class.
Definition: QoreString.h:81
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
provides atomic reference counting to Qore objects
Definition: QoreReferenceCounter.h:44
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
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