Qore Programming Language 1.19.1
Loading...
Searching...
No Matches
ConstantList.h
1/* -*- mode: c++; indent-tabs-mode: nil -*- */
2/*
3 ConstantList.h
4
5 Qore Programming Language
6
7 Copyright (C) 2003 - 2023 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
46class qore_ns_private;
47class 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
51hashdecl 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
86class RuntimeConstantRefNode;
87
88class ConstantEntry : public QoreReferenceCounter {
89 friend class ConstantEntryInitHelper;
90 friend class RuntimeConstantRefNode;
91 friend class ConstantList;
92
93public:
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
189protected:
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
203class ConstantEntryInitHelper {
204protected:
205 ConstantEntry &ce;
206
207public:
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>
225typedef 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
232typedef HASH_MAP<const char*, ConstantEntry*, qore_hash_str, eqstr> cnemap_t;
233#else
234#include <map>
235typedef std::map<const char*, ConstantEntry*, ltstr> cnemap_t;
236#endif
237*/
238
239class ConstantList {
240 friend class ConstantListIterator;
241 friend class ConstConstantListIterator;
242
243private:
244 // not implemented
245 DLLLOCAL ConstantList& operator=(const ConstantList&);
246
247 DLLLOCAL void clearIntern(ExceptionSink* xsink);
248
249protected:
250 // the object that owns the list (either a class or a namespace)
251 ClassNs ptr;
252
253public:
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
330class ConstantListIterator {
331protected:
332 cnemap_t& cl;
333 cnemap_t::iterator i;
334
335public:
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
372class ConstConstantListIterator {
373protected:
374 const cnemap_t& cl;
375 cnemap_t::const_iterator i;
376
377public:
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
410class RuntimeConstantRefNode : public ParseNode {
411protected:
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
430public:
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:50
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
DLLEXPORT bool isNothing() const
returns true if the object contains NOTHING
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:276
DLLEXPORT QoreValue eval(ExceptionSink *xsink) const
evaluates the node and returns the result