Qore Programming Language  1.12.0
ConstantList.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  ConstantList.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2022 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  delayed_eval : 1 // delayed evaluation
104  ;
105 
106  DLLLOCAL ConstantEntry(const QoreProgramLocation* loc, const char* n, QoreValue v,
107  const QoreTypeInfo* ti = nullptr, bool n_pub = false, bool n_init = false, bool n_builtin = false,
108  ClassAccess n_access = Public);
109 
110  DLLLOCAL ConstantEntry(const ConstantEntry& old);
111 
112  DLLLOCAL void deref(ExceptionSink* xsink) {
113  if (ROdereference()) {
114  del(xsink);
115  delete this;
116  }
117  }
118 
119  DLLLOCAL void deref(QoreListNode& l) {
120  if (ROdereference()) {
121  del(l);
122  delete this;
123  }
124  }
125 
126  DLLLOCAL void ref() const {
127  ROreference();
128  }
129 
130  DLLLOCAL ConstantEntry* refSelf() const {
131  ref();
132  return const_cast<ConstantEntry*>(this);
133  }
134 
135  DLLLOCAL QoreValue getReferencedValue() const;
136 
137  DLLLOCAL int parseInit(ClassNs ptr);
138 
139  DLLLOCAL int parseCommitRuntimeInit();
140 
141  DLLLOCAL QoreValue get(const QoreProgramLocation* loc, const QoreTypeInfo*& constantTypeInfo, ClassNs ptr) {
142  if (in_init) {
143  parse_error(*loc, "recursive constant reference found to constant '%s'", name.c_str());
144  constantTypeInfo = nothingTypeInfo;
145  return QoreValue();
146  }
147 
148  if (!init && parseInit(ptr)) {
149  constantTypeInfo = nothingTypeInfo;
150  return QoreValue();
151  }
152 
153  constantTypeInfo = typeInfo;
154  return val;
155  }
156 
157  DLLLOCAL const char* getName() const {
158  return name.c_str();
159  }
160 
161  DLLLOCAL const std::string& getNameStr() const {
162  return name;
163  }
164 
165  DLLLOCAL bool isPublic() const {
166  return pub;
167  }
168 
169  DLLLOCAL bool isUserPublic() const {
170  return pub && !builtin;
171  }
172 
173  DLLLOCAL bool isSystem() const {
174  return builtin;
175  }
176 
177  DLLLOCAL bool isUser() const {
178  return !builtin;
179  }
180 
181  DLLLOCAL ClassAccess getAccess() const {
182  return access;
183  }
184 
185  DLLLOCAL const char* getModuleName() const {
186  return from_module.empty() ? nullptr : from_module.c_str();
187  }
188 
189 protected:
190  QoreValue saved_val;
191  ClassAccess access;
192  std::string from_module;
193 
194  DLLLOCAL ~ConstantEntry() {
195  assert(saved_val.isNothing());
196  assert(val.isNothing());
197  }
198 
199  DLLLOCAL void del(ExceptionSink* xsink);
200  DLLLOCAL void del(QoreListNode& l);
201 };
202 
203 class ConstantEntryInitHelper {
204 protected:
205  ConstantEntry &ce;
206 
207 public:
208  DLLLOCAL ConstantEntryInitHelper(ConstantEntry& n_ce) : ce(n_ce) {
209  assert(!ce.in_init);
210  assert(!ce.init);
211  ce.in_init = true;
212  //printd(5, "ConstantEntryInitHelper::ConstantEntryInitHelper() '%s'\n", ce.getName());
213  }
214 
215  DLLLOCAL ~ConstantEntryInitHelper() {
216  ce.in_init = false;
217  ce.init = true;
218  //printd(5, "ConstantEntryInitHelper::~ConstantEntryInitHelper() '%s'\n", ce.getName());
219  }
220 };
221 
222 // we use a vector map as the number of constants is generally relatively small
223 // and lookups are only performed during parsing
224 #include <qore/vector_map>
225 typedef vector_map_t<const char*, ConstantEntry*> cnemap_t;
226 /*
227 #ifdef HAVE_QORE_HASH_MAP
228 //#warning compiling with hash_map
229 #include <qore/hash_map_include.h>
230 #include "qore/intern/xxhash.h"
231 
232 typedef HASH_MAP<const char*, ConstantEntry*, qore_hash_str, eqstr> cnemap_t;
233 #else
234 #include <map>
235 typedef std::map<const char*, ConstantEntry*, ltstr> cnemap_t;
236 #endif
237 */
238 
239 class ConstantList {
240  friend class ConstantListIterator;
241  friend class ConstConstantListIterator;
242 
243 private:
244  // not implemented
245  DLLLOCAL ConstantList& operator=(const ConstantList&);
246 
247  DLLLOCAL void clearIntern(ExceptionSink* xsink);
248 
249 protected:
250  // the object that owns the list (either a class or a namespace)
251  ClassNs ptr;
252 
253 public:
254  vector_map_t<std::string, ConstantEntry*> new_cnemap;
255  cnemap_t cnemap;
256 
257  DLLLOCAL ~ConstantList();
258 
259  DLLLOCAL ConstantList(ClassNs p) : ptr(p) {
260  //printd(5, "ConstantList::ConstantList() this: %p cls: %p ns: %p\n", this, ptr.getClass(), ptr.getNs());
261  }
262 
263  DLLLOCAL ConstantList(const ConstantList& old, int64 po, ClassNs p);
264 
265  // do not delete the object returned by this function
266  DLLLOCAL cnemap_t::iterator add(const char* name, QoreValue val, const QoreTypeInfo* typeInfo = nullptr,
267  ClassAccess access = Public);
268 
269  DLLLOCAL cnemap_t::iterator parseAdd(const QoreProgramLocation* loc, const char* name, QoreValue val,
270  const QoreTypeInfo* typeInfo = nullptr, bool pub = false, ClassAccess access = Public);
271 
272  DLLLOCAL ConstantEntry* findEntry(const char* name);
273 
274  DLLLOCAL const ConstantEntry* findEntry(const char* name) const;
275 
276  DLLLOCAL QoreValue find(const char* name, const QoreTypeInfo*& constantTypeInfo, ClassAccess& access,
277  bool& found);
278 
279  DLLLOCAL QoreValue find(const char* name, const QoreTypeInfo*& constantTypeInfo, bool& found) {
280  ClassAccess access;
281  return find(name, constantTypeInfo, access, found);
282  }
283 
284  DLLLOCAL bool inList(const char* name) const;
285  DLLLOCAL bool inList(const std::string& name) const;
286  //DLLLOCAL ConstantList *copy();
287 
288  // assimilate the list without any duplicate checking
289  DLLLOCAL void assimilate(ConstantList& n);
290 
291  // assimilate a constant list in a namespace with duplicate checking (also in pending list)
292  DLLLOCAL void assimilate(ConstantList& n, const char* type, const char* name);
293 
294  // copy all user/public elements of the source list to the target, assuming no duplicates
295  DLLLOCAL void mergeUserPublic(const ConstantList& src);
296 
297  DLLLOCAL int importSystemConstants(const ConstantList& src, ExceptionSink* xsink);
298 
299  // add a constant to a list with duplicate checking (pub & priv + pending)
300  DLLLOCAL void parseAdd(const QoreProgramLocation* loc, const std::string& name, QoreValue val, ClassAccess access,
301  const char* cname);
302 
303  DLLLOCAL int parseInit();
304  DLLLOCAL int parseCommitRuntimeInit();
305 
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 int parseInitImpl(QoreValue& val, QoreParseContext& parse_context) {
415  parse_context.typeInfo = ce->typeInfo;
416  return 0;
417  }
418 
419  DLLLOCAL virtual const QoreTypeInfo* getTypeInfo() const {
420  return ce->typeInfo;
421  }
422 
423  DLLLOCAL virtual QoreValue evalImpl(bool& needs_deref, ExceptionSink* xsink) const {
424  return ce->saved_val.eval(needs_deref, xsink);
425  }
426 
427  DLLLOCAL ~RuntimeConstantRefNode() {
428  }
429 
430 public:
431  DLLLOCAL RuntimeConstantRefNode(const QoreProgramLocation* loc, ConstantEntry* n_ce) : ParseNode(loc,
432  NT_RTCONSTREF, true, false), ce(n_ce) {
433  assert(ce->saved_val);
434  }
435 
436  DLLLOCAL ConstantEntry* getConstantEntry() const {
437  return ce;
438  }
439 
440  DLLLOCAL virtual int getAsString(QoreString& str, int foff, ExceptionSink* xsink) const {
441  assert(ce->saved_val);
442  return ce->saved_val.getAsString(str, foff, xsink);
443  }
444 
445  DLLLOCAL virtual QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const {
446  assert(ce->saved_val);
447  return ce->saved_val.getAsString(del, foff, xsink);
448  }
449 
450  DLLLOCAL virtual const char* getTypeName() const {
451  return ce->saved_val.getTypeName();
452  }
453 };
454 
455 #endif // _QORE_CONSTANTLIST_H
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
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
DLLEXPORT void ROreference() const
atomically increments the reference count
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
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
const qore_type_t NT_RTCONSTREF
type value for RuntimeConstantRefNode
Definition: node_types.h:82
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:275
DLLEXPORT QoreValue eval(ExceptionSink *xsink) const
evaluates the node and returns the result