Qore Programming Language  0.9.16
QoreNamespaceIntern.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  QoreNamespaceIntern.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2020 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_QORENAMESPACEINTERN_H
33 #define _QORE_QORENAMESPACEINTERN_H
34 
35 #include "qore/intern/QoreClassList.h"
36 #include "qore/intern/HashDeclList.h"
37 #include "qore/intern/QoreNamespaceList.h"
38 #include "qore/intern/ConstantList.h"
39 #include "qore/intern/FunctionList.h"
40 #include "qore/intern/GlobalVariableList.h"
41 #include "qore/intern/typed_hash_decl_private.h"
42 #include "qore/vector_map"
43 
44 #include <map>
45 #include <vector>
46 #include <list>
47 
48 class qore_root_ns_private;
49 class qore_ns_private;
50 
51 typedef std::list<const qore_ns_private*> nslist_t;
52 
53 class qore_ns_private {
54 public:
55  const QoreProgramLocation* loc;
56  std::string name;
57 
58  QoreClassList classList; // class map
59  HashDeclList hashDeclList; // hashdecl map
60  ConstantList constant; // constant map
61  QoreNamespaceList nsl; // namespace map
62  FunctionList func_list; // function map
63  GlobalVariableList var_list; // global variable map
64  gvblist_t pend_gvblist; // global variable declaration list
65 
66  // 0 = root namespace, ...
67  unsigned depth = 0;
68 
69  bool root = false, // is this the root namespace?
70  pub, // is this namespace public (inherited by child programs or programs importing user modules)
71  builtin, // is this namespace builtin?
72  imported = false; // was this namespace imported?
73 
74  const qore_ns_private* parent = nullptr; // pointer to parent namespace (0 if this is the root namespace or an unattached namespace)
75  q_ns_class_handler_t class_handler = nullptr;
76  QoreNamespace* ns;
77 
78  // used with builtin namespaces
79  DLLLOCAL qore_ns_private(QoreNamespace* n_ns, const char* n) : name(n), constant(this), pub(true), builtin(true), ns(n_ns) {
80  }
81 
82  // called when assimilating
83  DLLLOCAL qore_ns_private(const char* n, const qore_ns_private& old) : name(n), constant(this), pub(old.pub),
84  builtin(false), ns(new QoreNamespace(this)), from_module(old.from_module) {
85  }
86 
87  // called when parsing
88  DLLLOCAL qore_ns_private(const QoreProgramLocation* loc);
89 
90  DLLLOCAL qore_ns_private(const qore_ns_private& old, int64 po)
91  : name(old.name),
92  classList(old.classList, po, this),
93  hashDeclList(old.hashDeclList, po, this),
94  constant(old.constant, po, this),
95  nsl(old.nsl, po, *this),
96  func_list(old.func_list, this, po),
97  var_list(old.var_list, po),
98  depth(old.depth),
99  root(old.root),
100  pub(old.builtin ? true : false),
101  builtin(old.builtin),
102  imported(old.imported),
103  class_handler(old.class_handler), ns(nullptr) {
104  if (!old.from_module.empty()) {
105  from_module = old.from_module;
106  } else {
107  setModuleName();
108  }
109  }
110 
111  DLLLOCAL ~qore_ns_private() {
112  }
113 
114  DLLLOCAL void getPath(std::string& str, bool anchored = false) const {
115  const qore_ns_private* w = parent;
116  while (w && (anchored || w->parent)) {
117  //printd(5, "qore_ns_private::getPath() this: %p name: '%s' parent: %p root: %d\n", w, w->name.c_str(), parent, root);
118  str.insert(0, "::");
119  str.insert(0, w->name);
120  w = w->parent;
121  }
122 
123  // append this namespace's name
124  str += name;
125  }
126 
127  DLLLOCAL const char* getModuleName() const {
128  return from_module.empty() ? nullptr : from_module.c_str();
129  }
130 
131  DLLLOCAL void getNsList(nslist_t& nsl) const {
132  //printd(5, "qore_ns_private::getNsList() this: %p '%s::' root: %d\n", this, name.c_str(), root);
133  if (root)
134  return;
135 
136  const qore_ns_private* w = this;
137  while (w && w->parent) {
138  nsl.push_front(w);
139  w = w->parent;
140  }
141  }
142 
143  DLLLOCAL static QoreNamespace* newNamespace(const qore_ns_private& old, int64 po) {
144  qore_ns_private* p = new qore_ns_private(old, po);
145  return new QoreNamespace(p);
146  }
147 
148  // destroys the object and frees all associated memory
149  DLLLOCAL void purge() {
150  constant.reset();
151 
152  classList.reset();
153 
154  hashDeclList.reset();
155 
156  nsl.reset();
157  }
158 
159  DLLLOCAL qore_root_ns_private* getRoot() {
160  qore_ns_private* w = this;
161  while (w->parent) {
162  w = (qore_ns_private*)w->parent;
163  }
164 
165  return w->root ? reinterpret_cast<qore_root_ns_private*>(w) : nullptr;
166  }
167 
168  DLLLOCAL const qore_root_ns_private* getRoot() const {
169  const qore_ns_private* w = this;
170  while (w->parent) {
171  w = (qore_ns_private*)w->parent;
172  }
173 
174  return w->root ? reinterpret_cast<const qore_root_ns_private*>(w) : nullptr;
175  }
176 
177  DLLLOCAL QoreProgram* getProgram() const;
178 
179  DLLLOCAL void setClassHandler(q_ns_class_handler_t n_class_handler);
180 
181  // finds a local class in the committed class list, if not found executes the class handler
182  DLLLOCAL QoreClass* findLoadClass(const char* cname) {
183  //printd(5, "qore_ns_private::findLoadClass('%s') this: %p ('%s') class_handler: %p found: %d\n", cname, this, name.c_str(), class_handler, classList.find(cname));
184  QoreClass* qc = classList.find(cname);
185  if (!qc && class_handler)
186  qc = class_handler(ns, cname);
187  return qc;
188  }
189 
190  DLLLOCAL void getGlobalVars(QoreHashNode& h) const {
191  std::string path;
192  getPath(path);
193  var_list.getGlobalVars(path, h);
194  nsl.getGlobalVars(h);
195  }
196 
197  DLLLOCAL void clearConstants(QoreListNode& l);
198  DLLLOCAL void clearData(ExceptionSink* xsink);
199  DLLLOCAL void deleteData(bool deref_vars, ExceptionSink* xsink);
200  //DLLLOCAL void deleteClearData(ExceptionSink* xsink);
201 
202  DLLLOCAL void parseAssimilate(QoreNamespace* ns);
203  DLLLOCAL void runtimeAssimilate(QoreNamespace* ns);
204 
205  DLLLOCAL void updateDepthRecursive(unsigned ndepth);
206 
207  DLLLOCAL int parseAddPendingClass(const QoreProgramLocation* loc, const NamedScope& n, QoreClass* oc);
208  DLLLOCAL int parseAddPendingClass(const QoreProgramLocation* loc, QoreClass* oc);
209 
210  DLLLOCAL int parseAddPendingHashDecl(const QoreProgramLocation* loc, const NamedScope& n, TypedHashDecl* hashdecl);
211  DLLLOCAL int parseAddPendingHashDecl(const QoreProgramLocation* loc, TypedHashDecl* hashdecl);
212 
213  DLLLOCAL bool addGlobalVars(qore_root_ns_private& rns);
214 
215  DLLLOCAL cnemap_t::iterator parseAddConstant(const QoreProgramLocation* loc, const char* name, QoreValue value, bool pub);
216 
217  DLLLOCAL void parseAddConstant(const QoreProgramLocation* loc, const NamedScope& name, QoreValue value, bool pub);
218 
219  DLLLOCAL int parseAddMethodToClass(const QoreProgramLocation* loc, const NamedScope& name, MethodVariantBase* qcmethod, bool static_flag);
220 
221  DLLLOCAL int checkImportFunction(const char* name, ExceptionSink* xsink) {
222  //printd(5, "qore_ns_private::checkImportFunction(%s) this: %p\n", name, this);
223 
224  if (func_list.findNode(name)) {
225  xsink->raiseException("FUNCTION-IMPORT-ERROR", "function '%s' already exists in this namespace", name);
226  return -1;
227  }
228 
229  return 0;
230  }
231 
232  DLLLOCAL FunctionEntry* runtimeImportFunction(ExceptionSink* xsink, QoreFunction* u, const char* new_name = nullptr, bool inject = false) {
233  const char* fn = new_name ? new_name : u->getName();
234  if (checkImportFunction(fn, xsink))
235  return 0;
236 
237  return func_list.import(fn, u, this, inject);
238  }
239 
240  DLLLOCAL int checkImportClass(const char* cname, ExceptionSink* xsink) {
241  //printd(5, "qore_ns_private::checkImportClass(%s) this: %p\n", name, this);
242 
243  if (classList.find(cname)) {
244  xsink->raiseException("CLASS-IMPORT-ERROR", "class '%s' already exists in namespace '%s'", cname, name.c_str());
245  return -1;
246  }
247  if (hashDeclList.find(cname)) {
248  xsink->raiseException("CLASS-IMPORT-ERROR", "hashdecl '%s' already exists in namespace '%s'", cname, name.c_str());
249  return -1;
250  }
251  if (nsl.find(cname)) {
252  xsink->raiseException("CLASS-IMPORT-ERROR", "a subnamespace named '%s' already exists in namespace '%s'", cname, name.c_str());
253  return -1;
254  }
255 
256  return 0;
257  }
258 
259  DLLLOCAL int checkImportHashDecl(const char* hdname, ExceptionSink* xsink) {
260  //printd(5, "qore_ns_private::checkImportHashDecl(%s) this: %p\n", hdname, this);
261 
262  if (hashDeclList.find(hdname)) {
263  xsink->raiseException("HASHDECL-IMPORT-ERROR", "hashdecl '%s' already exists in namespace '%s'", hdname, name.c_str());
264  return -1;
265  }
266  if (classList.find(hdname)) {
267  xsink->raiseException("HASHDECL-IMPORT-ERROR", "class '%s' already exists in namespace '%s'", hdname, name.c_str());
268  return -1;
269  }
270 
271  return 0;
272  }
273 
274  DLLLOCAL QoreClass* runtimeImportClass(ExceptionSink* xsink, const QoreClass* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr, bool inject = false, const qore_class_private* injectedClass = nullptr);
275 
276  DLLLOCAL TypedHashDecl* runtimeImportHashDecl(ExceptionSink* xsink, const TypedHashDecl* hd, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr);
277 
278  DLLLOCAL const FunctionEntry* runtimeFindFunctionEntry(const char* name) {
279  return func_list.findNode(name, true);
280  }
281 
282  DLLLOCAL const QoreFunction* runtimeFindFunction(const char* name) {
283  return func_list.find(name, true);
284  }
285 
286  DLLLOCAL const QoreFunction* findAnyFunction(const char* name) {
287  return func_list.find(name, false);
288  }
289 
290  DLLLOCAL QoreNamespace* findCreateNamespace(const char* nme, bool user, bool& is_new, qore_root_ns_private* rns);
291  DLLLOCAL QoreNamespace* findCreateNamespacePath(const nslist_t& nsl, bool user, bool& is_new);
292  DLLLOCAL QoreNamespace* findCreateNamespacePath(const NamedScope& nspath, bool pub, bool user, bool& is_new, int ignore_end = 1);
293 
294  DLLLOCAL TypedHashDecl* parseFindLocalHashDecl(const char* name) {
295  return hashDeclList.find(name);
296  }
297 
298  DLLLOCAL QoreValue getConstantValue(const char* name, const QoreTypeInfo*& typeInfo, bool& found);
299  DLLLOCAL QoreClass* parseFindLocalClass(const char* name);
300  DLLLOCAL qore_ns_private* parseAddNamespace(QoreNamespace* nns);
301 
302  DLLLOCAL void addModuleNamespace(qore_ns_private* nns, QoreModuleContext& qmc);
303  DLLLOCAL void addCommitNamespaceIntern(qore_ns_private* nns);
304  DLLLOCAL void addNamespace(qore_ns_private* nns);
305 
306  DLLLOCAL void parseInit();
307  DLLLOCAL void parseResolveHierarchy();
308  DLLLOCAL void parseResolveClassMembers();
309  DLLLOCAL void parseResolveAbstract();
310  DLLLOCAL void parseInitConstants();
311  DLLLOCAL void parseRollback(ExceptionSink* xsink);
312  DLLLOCAL void parseCommit();
313  DLLLOCAL void parseCommitRuntimeInit(ExceptionSink* xsink);
314 
315  DLLLOCAL Var* runtimeMatchGlobalVar(const NamedScope& nscope, const qore_ns_private*& rns) const;
316  DLLLOCAL const ConstantEntry* runtimeMatchNamespaceConstant(const NamedScope& nscope, const qore_ns_private*& rns) const;
317  DLLLOCAL const QoreClass* runtimeMatchScopedClassWithMethod(const NamedScope& nscope) const;
318  DLLLOCAL const QoreClass* runtimeMatchClass(const NamedScope& nscope, const qore_ns_private*& rns) const;
319  DLLLOCAL const qore_ns_private* runtimeMatchNamespace(const NamedScope& nscope, int offset = 0) const;
320  DLLLOCAL const qore_ns_private* runtimeMatchAddClass(const NamedScope& nscope, bool& fnd) const;
321 
322  DLLLOCAL const TypedHashDecl* runtimeMatchHashDecl(const NamedScope& nscope, const qore_ns_private*& rns) const;
323 
324  DLLLOCAL const FunctionEntry* runtimeMatchFunctionEntry(const NamedScope& nscope) const;
325  DLLLOCAL const qore_ns_private* runtimeMatchAddFunction(const NamedScope& nscope, bool& fnd) const;
326 
327  //DLLLOCAL const QoreFunction* parseMatchFunction(const NamedScope& nscope, unsigned& match) const;
328 
329  DLLLOCAL const FunctionEntry* parseMatchFunctionEntry(const NamedScope& nscope, unsigned& match) const;
330 
331  DLLLOCAL QoreNamespace* resolveNameScope(const QoreProgramLocation* loc, const NamedScope& name) const;
332  DLLLOCAL QoreNamespace* parseMatchNamespace(const NamedScope& nscope, unsigned& matched) const;
333 
334  DLLLOCAL TypedHashDecl* parseMatchScopedHashDecl(const NamedScope& name, unsigned& matched);
335 
336  DLLLOCAL QoreClass* parseMatchScopedClass(const NamedScope& name, unsigned& matched);
337  DLLLOCAL QoreClass* parseMatchScopedClassWithMethod(const NamedScope& nscope, unsigned& matched);
338 
339  DLLLOCAL QoreValue parseCheckScopedReference(const QoreProgramLocation* loc, const NamedScope& ns, unsigned& m, const QoreTypeInfo*& typeInfo, bool& found, bool abr) const;
340 
341  DLLLOCAL QoreValue parseFindLocalConstantValue(const QoreProgramLocation* loc, const NamedScope& ns, unsigned& m, const QoreTypeInfo*& typeInfo, bool& found, bool abr) const;
342 
343  DLLLOCAL QoreValue parseFindLocalConstantValue(const char* cname, const QoreTypeInfo*& typeInfo, bool& found);
344  DLLLOCAL QoreNamespace* parseFindLocalNamespace(const char* nname);
345 
346  DLLLOCAL QoreValue parseMatchScopedConstantValue(const NamedScope& name, unsigned& matched, const QoreTypeInfo*& typeInfo, bool& found);
347 
348  DLLLOCAL FunctionEntry* addPendingVariantIntern(const char* fname, AbstractQoreFunctionVariant* v, bool& new_func);
349 
350  DLLLOCAL void addBuiltinVariant(const char* name, AbstractQoreFunctionVariant* v);
351  DLLLOCAL void addBuiltinModuleVariant(const char* name, AbstractQoreFunctionVariant* v, QoreModuleContext& qmc);
352  DLLLOCAL void addBuiltinVariantIntern(const char* name, AbstractQoreFunctionVariant* v);
353 
354  template <typename T, class B>
355  DLLLOCAL void addBuiltinVariant(const char* name, T f, int64 flags, int64 functional_domain, const QoreTypeInfo* returnTypeInfo, unsigned num_params, va_list args) {
356  //printd(5, "qore_ns_private::addBuiltinVariant('%s', %p, flags=%lld) BEFORE\n", name, f, flags);
357  type_vec_t typeList;
358  arg_vec_t defaultArgList;
359  name_vec_t nameList;
360  if (num_params)
361  qore_process_params(num_params, typeList, defaultArgList, nameList, args);
362 
363  //printd(5, "qore_ns_private::addBuiltinVariant('%s', %p, flags=%lld, domain=%lld, ret=%s, num_params=%d, ...)\n", name, f, flags, functional_domain, QoreTypeInfo::getName(returnTypeInfo), num_params);
364  addBuiltinVariant(name, new B(f, flags, functional_domain, returnTypeInfo, typeList, defaultArgList, nameList));
365  }
366 
367  template <typename T, class B>
368  DLLLOCAL void addBuiltinVariant(void* ptr, const char* name, T f, int64 flags, int64 functional_domain, const QoreTypeInfo* returnTypeInfo, unsigned num_params, va_list args) {
369  //printd(5, "qore_ns_private::addBuiltinVariant('%s', %p, flags=%lld) BEFORE\n", name, f, flags);
370  type_vec_t typeList;
371  arg_vec_t defaultArgList;
372  name_vec_t nameList;
373  if (num_params)
374  qore_process_params(num_params, typeList, defaultArgList, nameList, args);
375 
376  //printd(5, "qore_ns_private::addBuiltinVariant('%s', %p, flags=%lld, domain=%lld, ret=%s, num_params=%d, ...)\n", name, f, flags, functional_domain, QoreTypeInfo::getName(returnTypeInfo), num_params);
377  addBuiltinVariant(name, new B(ptr, f, flags, functional_domain, returnTypeInfo, typeList, defaultArgList, nameList));
378  }
379 
380  DLLLOCAL void scanMergeCommittedNamespace(const qore_ns_private& mns, QoreModuleContext& qmc) const;
381  DLLLOCAL void copyMergeCommittedNamespace(const qore_ns_private& mns);
382 
383  DLLLOCAL void parseInitGlobalVars();
384 
385  DLLLOCAL void checkGlobalVarDecl(Var* v, const NamedScope& vname);
386  DLLLOCAL void parseAddGlobalVarDecl(const QoreProgramLocation* loc, char* name, const QoreTypeInfo* typeInfo, QoreParseTypeInfo* parseTypeInfo, bool pub);
387 
388  DLLLOCAL void setPublic();
389 
390  DLLLOCAL void runtimeImportSystemClasses(const qore_ns_private& source, qore_root_ns_private& rns, ExceptionSink* xsink);
391  DLLLOCAL void runtimeImportSystemHashDecls(const qore_ns_private& source, qore_root_ns_private& rns, ExceptionSink* xsink);
392  DLLLOCAL void runtimeImportSystemConstants(const qore_ns_private& source, qore_root_ns_private& rns, ExceptionSink* xsink);
393  DLLLOCAL void runtimeImportSystemFunctions(const qore_ns_private& source, qore_root_ns_private& rns, ExceptionSink* xsink);
394 
395  DLLLOCAL static void addNamespace(QoreNamespace& ns, QoreNamespace* nns) {
396  ns.priv->addNamespace(nns->priv);
397  }
398 
399  DLLLOCAL static QoreValue parseResolveReferencedClassConstant(const QoreProgramLocation* loc, QoreClass* qc, const char* name, const QoreTypeInfo*& typeInfo, bool& found);
400 
401  DLLLOCAL static ConstantList& getConstantList(const QoreNamespace* ns) {
402  return ns->priv->constant;
403  }
404 
405  DLLLOCAL static const QoreFunction* runtimeFindFunction(QoreNamespace& ns, const char* name) {
406  return ns.priv->runtimeFindFunction(name);
407  }
408 
409  DLLLOCAL static const FunctionEntry* runtimeFindFunctionEntry(QoreNamespace& ns, const char* name) {
410  return ns.priv->runtimeFindFunctionEntry(name);
411  }
412 
413  DLLLOCAL static QoreListNode* getUserFunctionList(QoreNamespace& ns) {
414  return ns.priv->func_list.getList();
415  }
416 
417  DLLLOCAL static void parseAddPendingClass(QoreNamespace& ns, const QoreProgramLocation* loc, const NamedScope& n, QoreClass* oc) {
418  ns.priv->parseAddPendingClass(loc, n, oc);
419  }
420 
421  DLLLOCAL static void parseAddNamespace(QoreNamespace& ns, QoreNamespace* nns) {
422  ns.priv->parseAddNamespace(nns);
423  }
424 
425  DLLLOCAL static void parseAddConstant(QoreNamespace& ns, const QoreProgramLocation* loc, const NamedScope& name, QoreValue value, bool pub) {
426  ns.priv->parseAddConstant(loc, name, value, pub);
427  }
428 
429  DLLLOCAL static void parseCommit(QoreNamespace& ns) {
430  ns.priv->parseCommit();
431  }
432 
433  DLLLOCAL static void purge(QoreNamespace& ns) {
434  ns.priv->purge();
435  }
436 
437  DLLLOCAL static qore_ns_private* get(QoreNamespace& ns) {
438  return ns.priv;
439  }
440 
441  DLLLOCAL static const qore_ns_private* get(const QoreNamespace& ns) {
442  return ns.priv;
443  }
444 
445  DLLLOCAL static bool isPublic(const QoreNamespace& ns) {
446  return ns.priv->pub;
447  }
448 
449  DLLLOCAL static bool isUserPublic(const QoreNamespace& ns) {
450  return ns.priv->pub && !ns.priv->builtin;
451  }
452 
453 private:
454  // not implemented
455  DLLLOCAL qore_ns_private(const qore_ns_private&) = delete;
456  // not implemented
457  DLLLOCAL qore_ns_private& operator=(const qore_ns_private&) = delete;
458 
459 protected:
460  // the module that defined this class, if any
461  std::string from_module;
462 
463  // called from the root namespace constructor only
464  DLLLOCAL qore_ns_private(QoreNamespace* n_ns) : constant(this), root(true), pub(true), builtin(true),
465  ns(n_ns) {
466  }
467 
468  DLLLOCAL void setModuleName() {
469  assert(from_module.empty());
470  const char* mod_name = get_module_context_name();
471  if (mod_name) {
472  from_module = mod_name;
473  }
474  //printd(5, "qore_ns_private::setModuleName() this: %p mod: %s\n", this, mod_name ? mod_name : "n/a");
475  }
476 };
477 
478 hashdecl namespace_iterator_element {
479  qore_ns_private* ns;
480  nsmap_t::iterator i;
481 
482  DLLLOCAL namespace_iterator_element(qore_ns_private* ns) : ns(ns) {
483  assert(ns);
484 
485  i = ns->nsl.nsmap.begin();
486  }
487 
488  DLLLOCAL bool atEnd() const {
489  return i == ns->nsl.nsmap.end();
490  }
491 
492  DLLLOCAL QoreNamespace* next() {
493  ++i;
494  if (atEnd()) {
495  return nullptr;
496  }
497  return i->second;
498  }
499 };
500 
501 class QorePrivateNamespaceIterator {
502 protected:
503  typedef std::vector<namespace_iterator_element> nsv_t;
504  nsv_t nsv; // stack of namespaces
505  qore_ns_private* root; // for starting over when done
506 
507  DLLLOCAL void set(qore_ns_private* rns) {
508  nsv.push_back(namespace_iterator_element(rns));
509 
510  //printd(5, "QorePrivateNamespaceIterator::set() %p:%s committed: %d\n", rns, rns->name.c_str(), committed);
511  while (!(rns->nsl.empty())) {
512  rns = qore_ns_private::get(*((rns->nsl.nsmap.begin()->second)));
513  //printd(5, "QorePrivateNamespaceIterator::set() -> %p:%s committed: %d\n", rns, rns->name.c_str(), committed);
514  nsv.push_back(namespace_iterator_element(rns));
515  }
516  }
517 
518 public:
519  DLLLOCAL QorePrivateNamespaceIterator(qore_ns_private* rns) : root(rns) {
520  assert(rns);
521  }
522 
523  DLLLOCAL bool next() {
524  // reset when starting over
525  if (nsv.empty()) {
526  set(root);
527  return true;
528  }
529 
530  namespace_iterator_element* nie = &(nsv.back());
531 
532  // if the last element of the current namespace list has been iterated, take it off the stack
533  if (nie->atEnd()) {
534  nsv.pop_back();
535  if (nsv.empty())
536  return false;
537 
538  nie = &(nsv.back());
539  }
540 
541  QoreNamespace* next = nie->next();
542  if (next)
543  set(qore_ns_private::get(*next));
544 
545  return true;
546  }
547 
548  DLLLOCAL qore_ns_private* operator->() {
549  return nsv.back().ns;
550  }
551 
552  DLLLOCAL qore_ns_private* operator*() {
553  return nsv.back().ns;
554  }
555 
556  DLLLOCAL qore_ns_private* get() {
557  return nsv.back().ns;
558  }
559 };
560 
561 hashdecl NSOInfoBase {
562  qore_ns_private* ns = nullptr;
563 
564  DLLLOCAL NSOInfoBase() {
565  }
566 
567  DLLLOCAL NSOInfoBase(qore_ns_private* n_ns) : ns(n_ns) {
568  }
569 
570  DLLLOCAL unsigned depth() const {
571  return ns->depth;
572  }
573 };
574 
575 template <typename T>
576 hashdecl NSOInfo : public NSOInfoBase {
577  // object
578  T* obj = nullptr;
579 
580  DLLLOCAL NSOInfo() {
581  }
582 
583  DLLLOCAL NSOInfo(qore_ns_private* n_ns, T* n_obj) : NSOInfoBase(n_ns), obj(n_obj) {
584  }
585 
586  DLLLOCAL void assign(qore_ns_private* n_ns, T* n_obj) {
587  ns = n_ns;
588  obj = n_obj;
589  }
590 };
591 
592 // cannot use vector_map here for performance reasons
593 template <typename T>
594 class RootMap : public std::map<const std::string, NSOInfo<T>> {
595 private:
596  // not implemented
597  DLLLOCAL RootMap(const RootMap& old);
598  // not implemented
599  DLLLOCAL RootMap& operator=(const RootMap& m);
600 
601 public:
602  typedef NSOInfo<T> info_t;
603  typedef std::map<const std::string, NSOInfo<T>> map_t;
604 
605  DLLLOCAL RootMap() {
606  }
607 
608  DLLLOCAL void update(const std::string& name, qore_ns_private* ns, T* obj) {
609  // get current lookup map entry for this object
610  typename map_t::iterator i = this->lower_bound(name);
611  if (i == this->end() || i->first != name) {
612  this->insert(i, typename map_t::value_type(name, info_t(ns, obj)));
613  } else { // if the old depth is > the new depth, then replace
614  if (i->second.depth() > ns->depth) {
615  i->second.assign(ns, obj);
616  }
617  }
618  }
619 
620  DLLLOCAL void update(typename map_t::const_iterator ni) {
621  // get current lookup map entry for this object
622  typename map_t::iterator i = this->lower_bound(ni->first);
623  if (i == this->end() || i->first != ni->first) {
624  //printd(5, "RootMap::update(iterator) inserting '%s' new depth: %d\n", ni->first, ni->second.depth());
625  this->insert(i, typename map_t::value_type(ni->first, ni->second));
626  } else {
627  // if the old depth is > the new depth, then replace
628  if (i->second.depth() > ni->second.depth()) {
629  //printd(5, "RootMap::update(iterator) replacing '%s' current depth: %d new depth: %d\n", ni->first, i->second.depth(), ni->second.depth());
630  i->second = ni->second;
631  }
632  //else
633  //printd(5, "RootMap::update(iterator) ignoring '%s' current depth: %d new depth: %d\n", ni->first, i->second.depth(), ni->second.depth());
634  }
635  }
636 
637  T* findObj(const std::string& name) {
638  typename map_t::iterator i = this->find(name);
639  return i == this->end() ? nullptr : i->second.obj;
640  }
641 };
642 
643 hashdecl FunctionEntryInfo {
644  FunctionEntry* obj = nullptr;
645 
646  DLLLOCAL FunctionEntryInfo() {
647  }
648 
649  DLLLOCAL FunctionEntryInfo(FunctionEntry* o) : obj(o) {
650  }
651 
652  DLLLOCAL unsigned depth() const {
653  return getNamespace()->depth;
654  }
655 
656  DLLLOCAL qore_ns_private* getNamespace() const {
657  return obj->getNamespace();
658  }
659 
660  DLLLOCAL void assign(FunctionEntry* n_obj) {
661  obj = n_obj;
662  }
663 };
664 
665 // cannot use vector_map here for performance reasons
666 typedef std::map<const char*, FunctionEntryInfo, ltstr> femap_t;
667 class FunctionEntryRootMap : public femap_t {
668 private:
669  // not implemented
670  DLLLOCAL FunctionEntryRootMap(const FunctionEntryRootMap& old);
671  // not implemented
672  DLLLOCAL FunctionEntryRootMap& operator=(const FunctionEntryRootMap& m);
673 
674 public:
675  DLLLOCAL FunctionEntryRootMap() {
676  }
677 
678  DLLLOCAL void update(const char* name, FunctionEntry* obj) {
679  // get current lookup map entry for this object
680  femap_t::iterator i = find(name);
681  if (i == end())
682  insert(femap_t::value_type(name, FunctionEntryInfo(obj)));
683  else // if the old depth is > the new depth, then replace
684  if (i->second.depth() > obj->getNamespace()->depth)
685  i->second.assign(obj);
686  }
687 
688  DLLLOCAL void update(femap_t::const_iterator ni) {
689  // get current lookup map entry for this object
690  femap_t::iterator i = find(ni->first);
691  if (i == end()) {
692  //printd(5, "FunctionEntryRootMap::update(iterator) inserting '%s' new depth: %d\n", ni->first, ni->second.depth());
693  insert(femap_t::value_type(ni->first, ni->second));
694  }
695  else {
696  // if the old depth is > the new depth, then replace
697  if (i->second.depth() > ni->second.depth()) {
698  //printd(5, "FunctionEntryRootMap::update(iterator) replacing '%s' current depth: %d new depth: %d\n", ni->first, i->second.depth(), ni->second.depth());
699  i->second = ni->second;
700  }
701  //else
702  //printd(5, "FunctionEntryRootMap::update(iterator) ignoring '%s' current depth: %d new depth: %d\n", ni->first, i->second.depth(), ni->second.depth());
703  }
704  }
705 
706  FunctionEntry* findObj(const char* name) {
707  femap_t::iterator i = find(name);
708  return i == end() ? 0 : i->second.obj;
709  }
710 };
711 
712 class NamespaceDepthList {
713  friend class NamespaceDepthListIterator;
714 protected:
715  // map from depth to namespace
716  typedef std::multimap<unsigned, qore_ns_private*> nsdmap_t;
717  nsdmap_t nsdmap;
718 
719 public:
720  DLLLOCAL NamespaceDepthList() {
721  }
722 
723  DLLLOCAL void add(qore_ns_private* ns) {
724  nsdmap.insert(nsdmap_t::value_type(ns->depth, ns));
725  }
726 
727  DLLLOCAL void clear() {
728  nsdmap.clear();
729  }
730 };
731 
732 class NamespaceDepthListIterator {
733  NamespaceDepthList::nsdmap_t::iterator i, e;
734 public:
735  DLLLOCAL NamespaceDepthListIterator(NamespaceDepthList& m) : i(m.nsdmap.begin()), e(m.nsdmap.end()) {
736  }
737 
738  DLLLOCAL bool next() {
739  if (i == e)
740  return false;
741  ++i;
742  return i != e;
743  }
744 
745  DLLLOCAL qore_ns_private* get() const {
746  assert(i->second);
747  return i->second;
748  }
749 };
750 
751 class NamespaceMap {
752  friend class NamespaceMapIterator;
753  friend class ConstNamespaceMapIterator;
754  friend class ConstAllNamespacesIterator;
755 
756 protected:
757  // map from depth to namespace
758  typedef std::multimap<unsigned, qore_ns_private*> nsdmap_t;
759  // map from name to depth map
760  //typedef std::map<const char*, nsdmap_t, ltstr> nsmap_t;
761  typedef vector_map_t<const char*, nsdmap_t> nsmap_t;
762  // map from namespace to depth for reindexing
763  //typedef std::map<qore_ns_private*, unsigned> nsrmap_t;
764  typedef vector_map_t<qore_ns_private*, unsigned> nsrmap_t;
765 
766  nsmap_t nsmap; // name to depth to namespace map
767  nsrmap_t nsrmap; // namespace to depth map (for fast reindexing)
768 
769  // not implemented
770  DLLLOCAL NamespaceMap(const NamespaceMap& old);
771  // not implemented
772  DLLLOCAL NamespaceMap& operator=(const NamespaceMap& m);
773 
774 public:
775  DLLLOCAL NamespaceMap() {
776  }
777 
778  DLLLOCAL void update(qore_ns_private* ns) {
779  // if this namespace is already indexed, then reindex
780  nsrmap_t::iterator ri = nsrmap.find(ns);
781  if (ri != nsrmap.end()) {
782  // if the depth is the same, then do nothing
783  if (ns->depth == ri->second)
784  return;
785 
786  // otherwise get the depth -> namespace map under this name
787  nsmap_t::iterator i = nsmap.find(ns->name.c_str());
788  assert(i != nsmap.end());
789 
790  // now get the namespace entry
791  nsdmap_t::iterator di = i->second.find(ri->second);
792  assert(di != i->second.end());
793 
794  // remove from depth -> namespace map
795  i->second.erase(di);
796 
797  // remove from reverse map
798  nsrmap.erase(ri);
799 
800  // add new entry to depth -> namespace map
801  i->second.insert(nsdmap_t::value_type(ns->depth, ns));
802 
803  return;
804  }
805  else {
806  // insert depth -> ns map entry
807  nsmap_t::iterator i = nsmap.find(ns->name.c_str());
808  if (i == nsmap.end())
809  i = nsmap.insert(nsmap_t::value_type(ns->name.c_str(), nsdmap_t())).first;
810 
811  i->second.insert(nsdmap_t::value_type(ns->depth, ns));
812  }
813 
814  // add new entry to reverse map
815  nsrmap.insert(nsrmap_t::value_type(ns, ns->depth));
816  }
817 
818  DLLLOCAL void commit(NamespaceMap& pend) {
819  // commit entries
820  for (nsrmap_t::iterator i = pend.nsrmap.begin(), e = pend.nsrmap.end(); i != e; ++i)
821  update(i->first);
822  pend.clear();
823  }
824 
825  DLLLOCAL void clear() {
826  nsmap.clear();
827  nsrmap.clear();
828  }
829 
830  // find the first namespace with the given name
831  DLLLOCAL QoreNamespace* findFirst(const char* name) {
832  nsmap_t::iterator mi = nsmap.find(name);
833  if (mi != nsmap.end()) {
834  nsdmap_t::iterator i = mi->second.begin();
835  if (i != mi->second.end()) {
836  return i->second->ns;
837  }
838  }
839  return nullptr;
840  }
841 };
842 
843 class NamespaceMapIterator {
844 protected:
845  NamespaceMap::nsmap_t::iterator mi;
846  NamespaceMap::nsdmap_t::iterator i;
847  bool valid;
848 
849 public:
850  DLLLOCAL NamespaceMapIterator(NamespaceMap& nsm, const char* name) : mi(nsm.nsmap.find(name)), valid(mi != nsm.nsmap.end()) {
851  if (valid)
852  i = mi->second.end();
853  }
854 
855  DLLLOCAL bool next() {
856  if (!valid)
857  return false;
858 
859  if (i == mi->second.end())
860  i = mi->second.begin();
861  else
862  ++i;
863 
864  return i != mi->second.end();
865  }
866 
867  DLLLOCAL qore_ns_private* get() {
868  return i->second;
869  }
870 };
871 
872 class ConstNamespaceMapIterator {
873 protected:
874  NamespaceMap::nsmap_t::const_iterator mi;
875  NamespaceMap::nsdmap_t::const_iterator i;
876  bool valid;
877 
878 public:
879  DLLLOCAL ConstNamespaceMapIterator(const NamespaceMap& nsm, const char* name) : mi(nsm.nsmap.find(name)), valid(mi != nsm.nsmap.end()) {
880  if (valid)
881  i = mi->second.end();
882  }
883 
884  DLLLOCAL bool next() {
885  if (!valid)
886  return false;
887 
888  if (i == mi->second.end())
889  i = mi->second.begin();
890  else
891  ++i;
892 
893  return i != mi->second.end();
894  }
895 
896  DLLLOCAL const qore_ns_private* get() {
897  return i->second;
898  }
899 };
900 
901 class ConstAllNamespacesIterator {
902 public:
903  DLLLOCAL ConstAllNamespacesIterator(const NamespaceMap& nsmap) : nsrmap(nsmap.nsrmap), i(nsmap.nsrmap.end()) {
904  }
905 
906  DLLLOCAL bool next() {
907  if (i == nsrmap.end()) {
908  i = nsrmap.begin();
909  }
910  else {
911  ++i;
912  }
913 
914  return i != nsrmap.end();
915  }
916 
917  DLLLOCAL const QoreNamespace* get() const {
918  assert(i != nsrmap.end());
919  return i->first->ns;
920  }
921 
922 private:
923  const NamespaceMap::nsrmap_t& nsrmap;
924  NamespaceMap::nsrmap_t::const_iterator i;
925 };
926 
927 typedef FunctionEntryRootMap fmap_t;
928 
929 typedef RootMap<ConstantEntry> cnmap_t;
930 
931 typedef RootMap<QoreClass> clmap_t;
932 
933 typedef RootMap<TypedHashDecl> thdmap_t;
934 
935 typedef RootMap<Var> varmap_t;
936 
937 hashdecl deferred_new_check_t {
938  const qore_class_private* qc;
939  const QoreProgramLocation* loc;
940 
941  DLLLOCAL deferred_new_check_t(const qore_class_private* qc, const QoreProgramLocation* loc) : qc(qc), loc(loc) {
942  }
943 };
944 
945 class qore_root_ns_private : public qore_ns_private {
946  friend class qore_ns_private;
947  friend class QoreNamespace;
948 
949 protected:
950  typedef std::vector<deferred_new_check_t> deferred_new_check_vec_t;
951  deferred_new_check_vec_t deferred_new_check_vec;
952 
953  DLLLOCAL int addPendingVariantIntern(qore_ns_private& ns, const char* name, AbstractQoreFunctionVariant* v) {
954  // try to add function variant to given namespace
955  bool new_func = false;
956  FunctionEntry* fe = ns.addPendingVariantIntern(name, v, new_func);
957  if (!fe)
958  return -1;
959 
960  assert(fe->getNamespace() == &ns);
961 
962  if (new_func) {
963  fmap_t::iterator i = fmap.find(fe->getName());
964  // only add to pending map if either not in the committed map or the depth is higher in the committed map
965  if (i == fmap.end() || i->second.depth() > ns.depth)
966  pend_fmap.update(fe->getName(), fe);
967  }
968 
969  return 0;
970  }
971 
972  DLLLOCAL int addPendingVariantIntern(qore_ns_private& ns, const NamedScope& nscope, AbstractQoreFunctionVariant* v) {
973  assert(nscope.size() > 1);
975 
976  QoreNamespace* fns = ns.ns;
977  for (unsigned i = 0; i < nscope.size() - 1; ++i) {
978  fns = fns->priv->parseFindLocalNamespace(nscope[i]);
979  if (!fns) {
980  parse_error(*v->getUserVariantBase()->getUserSignature()->getParseLocation(), "cannot find namespace '%s::' in '%s()' as a child of namespace '%s::'", nscope[i], nscope.ostr, ns.name.c_str());
981  return -1;
982  }
983  }
984 
985  return addPendingVariantIntern(*fns->priv, nscope.getIdentifier(), vh.release());
986  }
987 
988  // performed at runtime
989  DLLLOCAL int runtimeImportClass(ExceptionSink* xsink, qore_ns_private& ns, const QoreClass* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr, bool inject = false, const qore_class_private* injectedClass = nullptr) {
990  QoreClass* nc = ns.runtimeImportClass(xsink, c, spgm, set_pub, new_name, inject, injectedClass);
991  if (!nc)
992  return -1;
993 
994  //printd(5, "qore_root_ns_private::runtimeImportClass() this: %p ns: %p '%s' (depth %d) class: %p %s\n", this, &ns, ns.name.c_str(), ns.depth, nc, nc->getName());
995 
996  clmap.update(nc->getName(), &ns, nc);
997  return 0;
998  }
999 
1000  // performed at runtime
1001  DLLLOCAL int runtimeImportHashDecl(ExceptionSink* xsink, qore_ns_private& ns, const TypedHashDecl* hd, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr) {
1002  TypedHashDecl* nhd = ns.runtimeImportHashDecl(xsink, hd, spgm, set_pub, new_name);
1003  if (!nhd)
1004  return -1;
1005 
1006  //printd(5, "qore_root_ns_private::thdmap() this: %p ns: %p '%s' (depth %d) hashdecl: %p %s\n", this, &ns, ns.name.c_str(), ns.depth, nc, nc->getName());
1007 
1008  thdmap.update(nhd->getName(), &ns, nhd);
1009  return 0;
1010  }
1011 
1012  // performed at runtime
1013  DLLLOCAL int runtimeImportFunction(ExceptionSink* xsink, qore_ns_private& ns, QoreFunction* u, const char* new_name = nullptr, bool inject = false) {
1014  FunctionEntry* fe = ns.runtimeImportFunction(xsink, u, new_name, inject);
1015  if (!fe)
1016  return -1;
1017 
1018  assert(fe->getNamespace() == &ns);
1019 
1020  //printd(5, "qore_root_ns_private::runtimeImportFunction() this: %p ns: %p '%s' (depth %d) func: %p %s\n", this, &ns, ns.name.c_str(), ns.depth, u, fe->getName());
1021 
1022  fmap.update(fe->getName(), fe);
1023  return 0;
1024  }
1025 
1026  DLLLOCAL bool runtimeExistsFunctionIntern(const char* name) {
1027  return fmap.find(name) != fmap.end();
1028  }
1029 
1030  DLLLOCAL const QoreClass* runtimeFindClassIntern(const char* name, const qore_ns_private*& ns) const {
1031  clmap_t::const_iterator i = clmap.find(name);
1032 
1033  if (i != clmap.end()) {
1034  ns = i->second.ns;
1035  //printd(5, "qore_root_ns_private::runtimeFindClassIntern() this: %p %s found in ns: '%s' depth: %d\n", this, name, ns->name.c_str(), ns->depth);
1036  return i->second.obj;
1037  }
1038 
1039  return nullptr;
1040  }
1041 
1042  DLLLOCAL const QoreClass* runtimeFindClassIntern(const NamedScope& name, const qore_ns_private*& ns) const;
1043 
1044  DLLLOCAL const TypedHashDecl* runtimeFindHashDeclIntern(const char* name, const qore_ns_private*& ns) {
1045  thdmap_t::iterator i = thdmap.find(name);
1046 
1047  if (i != thdmap.end()) {
1048  ns = i->second.ns;
1049  //printd(5, "qore_root_ns_private::runtimeFindHashDeclIntern() this: %p %s found in ns: '%s' depth: %d\n", this, name, ns->name.c_str(), ns->depth);
1050  return i->second.obj;
1051  }
1052 
1053  return nullptr;
1054  }
1055 
1056  DLLLOCAL const FunctionEntry* runtimeFindFunctionEntryIntern(const char* name) {
1057  fmap_t::const_iterator i = fmap.find(name);
1058  return i != fmap.end() ? i->second.obj : nullptr;
1059  }
1060 
1061  DLLLOCAL const FunctionEntry* runtimeFindFunctionEntryIntern(const NamedScope& name);
1062 
1063  DLLLOCAL FunctionEntry* parseFindFunctionEntryIntern(const char* name) {
1064  {
1065  // try to check in current namespace first
1066  qore_ns_private* nscx = parse_get_ns();
1067  if (nscx) {
1068  FunctionEntry* fe = nscx->func_list.findNode(name);
1069  if (fe)
1070  return fe;
1071  }
1072  }
1073 
1074  fmap_t::iterator i = fmap.find(name);
1075  fmap_t::iterator ip = pend_fmap.find(name);
1076 
1077  if (i != fmap.end()) {
1078  if (ip != pend_fmap.end()) {
1079  if (i->second.depth() < ip->second.depth())
1080  return i->second.obj;
1081 
1082  return ip->second.obj;
1083  }
1084 
1085  return i->second.obj;
1086  }
1087 
1088  if (ip != pend_fmap.end())
1089  return ip->second.obj;
1090 
1091  return 0;
1092  }
1093 
1094  DLLLOCAL QoreFunction* parseFindFunctionIntern(const char* name) {
1095  FunctionEntry* fe = parseFindFunctionEntryIntern(name);
1096  return !fe ? 0 : fe->getFunction();
1097  }
1098 
1099  DLLLOCAL const FunctionEntry* parseResolveFunctionEntryIntern(const QoreProgramLocation* loc, const char* fname) {
1100  QORE_TRACE("qore_root_ns_private::parseResolveFunctionEntryIntern()");
1101 
1102  const FunctionEntry* f = parseFindFunctionEntryIntern(fname);
1103  if (!f)
1104  // cannot find function, throw exception
1105  parse_error(*loc, "function '%s()' cannot be found", fname);
1106 
1107  return f;
1108  }
1109 
1110  // called during parsing (plock already grabbed)
1111  DLLLOCAL AbstractCallReferenceNode* parseResolveCallReferenceIntern(UnresolvedProgramCallReferenceNode* fr);
1112 
1113  DLLLOCAL void parseCommit() {
1114  // commit pending function lookup entries
1115  for (fmap_t::iterator i = pend_fmap.begin(), e = pend_fmap.end(); i != e; ++i)
1116  fmap.update(i);
1117  pend_fmap.clear();
1118 
1119  qore_ns_private::parseCommit();
1120  // exceptions can be through thrown when performing runtime initialization
1121  qore_ns_private::parseCommitRuntimeInit(getProgram()->getParseExceptionSink());
1122  }
1123 
1124  DLLLOCAL ConstantEntry* parseFindOnlyConstantEntryIntern(const char* cname, qore_ns_private*& ns) {
1125  {
1126  // first try to look in current namespace context
1127  qore_ns_private* nscx = parse_get_ns();
1128  if (nscx) {
1129  ConstantEntry* ce = nscx->constant.findEntry(cname);
1130  if (ce) {
1131  ns = nscx;
1132  return ce;
1133  }
1134  }
1135  }
1136 
1137  // look up in global constant map
1138  cnmap_t::iterator i = cnmap.find(cname);
1139 
1140  if (i != cnmap.end()) {
1141  ns = i->second.ns;
1142  return i->second.obj;;
1143  }
1144 
1145  return 0;
1146  }
1147 
1148  DLLLOCAL QoreValue parseFindOnlyConstantValueIntern(const QoreProgramLocation* loc, const char* cname, const QoreTypeInfo*& typeInfo, bool& found) {
1149  assert(!found);
1150  qore_ns_private* ns;
1151  ConstantEntry* ce = parseFindOnlyConstantEntryIntern(cname, ns);
1152  if (!ce)
1153  return QoreValue();
1154 
1155  //printd(5, "qore_root_ns_private::parseFindOnlyConstantValueIntern() const: %s ns: %p %s\n", cname, ns, ns->name.c_str());
1156 
1157  found = true;
1158  NamespaceParseContextHelper nspch(ns);
1159  return ce->get(loc, typeInfo, ns);
1160  }
1161 
1162  DLLLOCAL QoreValue parseFindConstantValueIntern(const QoreProgramLocation* loc, const char* cname, const QoreTypeInfo*& typeInfo, bool& found, bool error) {
1163  assert(!found);
1164  // look up class constants first
1165  QoreClass* pc = parse_get_class();
1166  if (pc) {
1167  QoreValue rv = qore_class_private::parseFindConstantValue(pc, cname, typeInfo, found, pc ? qore_class_private::get(*pc) : nullptr);
1168  if (found) {
1169  return rv;
1170  }
1171  }
1172 
1173  QoreValue rv = parseFindOnlyConstantValueIntern(loc, cname, typeInfo, found);
1174  if (found) {
1175  return rv;
1176  }
1177 
1178  if (error) {
1179  parse_error(*loc, "constant '%s' cannot be resolved in any namespace", cname);
1180  }
1181 
1182  return QoreValue();
1183  }
1184 
1185  DLLLOCAL ResolvedCallReferenceNode* runtimeGetCallReference(const char* fname, ExceptionSink* xsink) {
1186  fmap_t::iterator i = fmap.find(fname);
1187  if (i == fmap.end()) {
1188  xsink->raiseException("NO-SUCH-FUNCTION", "callback function '%s()' does not exist", fname);
1189  return 0;
1190  }
1191 
1192  return i->second.obj->makeCallReference(get_runtime_location());
1193  }
1194 
1195  DLLLOCAL TypedHashDecl* parseFindScopedHashDeclIntern(const NamedScope& nscope, unsigned& matched);
1196 
1197  DLLLOCAL TypedHashDecl* parseFindHashDeclIntern(const char* hdname) {
1198  {
1199  // try to check in current namespace first
1200  qore_ns_private* nscx = parse_get_ns();
1201  if (nscx) {
1202  TypedHashDecl* hd = nscx->parseFindLocalHashDecl(hdname);
1203  if (hd)
1204  return hd;
1205  }
1206  }
1207 
1208  thdmap_t::iterator i = thdmap.find(hdname);
1209 
1210  if (i != thdmap.end()) {
1211  return i->second.obj;
1212  }
1213 
1214  //printd(5, "qore_root_ns_private::parseFindHashDeclIntern() this: %p '%s' not found\n", this, cname);
1215  return nullptr;
1216  }
1217 
1218  DLLLOCAL QoreClass* parseFindScopedClassIntern(const QoreProgramLocation* loc, const NamedScope& name, bool raise_error);
1219  DLLLOCAL QoreClass* parseFindScopedClassIntern(const NamedScope& name, unsigned& matched);
1220  DLLLOCAL QoreClass* parseFindScopedClassWithMethodInternError(const QoreProgramLocation* loc, const NamedScope& name, bool error);
1221  DLLLOCAL QoreClass* parseFindScopedClassWithMethodIntern(const NamedScope& name, unsigned& matched);
1222 
1223  DLLLOCAL QoreClass* parseFindClassIntern(const char* cname) {
1224  assert(cname);
1225  {
1226  // try to check in current namespace first
1227  qore_ns_private* nscx = parse_get_ns();
1228  if (nscx) {
1229  QoreClass* qc = nscx->parseFindLocalClass(cname);
1230  if (qc)
1231  return qc;
1232  }
1233  }
1234 
1235  clmap_t::iterator i = clmap.find(cname);
1236 
1237  if (i != clmap.end()) {
1238  return i->second.obj;
1239  }
1240 
1241  // now check all namespaces with class handlers
1242  NamespaceDepthListIterator nhi(nshlist);
1243  while (nhi.next()) {
1244  QoreClass* qc = nhi.get()->findLoadClass(cname);
1245  if (qc)
1246  return qc;
1247  }
1248 
1249  //printd(5, "qore_root_ns_private::parseFindClassIntern() this: %p '%s' not found\n", this, cname);
1250  return nullptr;
1251  }
1252 
1253  DLLLOCAL const QoreClass* runtimeFindClass(const char* name) const {
1254  clmap_t::const_iterator i = clmap.find(name);
1255  return i != clmap.end() ? i->second.obj : nullptr;
1256  }
1257 
1258  DLLLOCAL QoreNamespace* runtimeFindNamespaceForAddFunction(const NamedScope& name, ExceptionSink* xsink) {
1259  //printd(5, "QoreNamespaceIntern::runtimeFindNamespaceForAddFunction() this: %p name: %s (%s)\n", this, name.ostr, name[0]);
1260  bool fnd = false;
1261 
1262  // iterate all namespaces with the initial name and look for the match
1263  NamespaceMapIterator nmi(nsmap, name[0]);
1264  while (nmi.next()) {
1265  const qore_ns_private* rv = nmi.get()->runtimeMatchAddFunction(name, fnd);
1266  //printd(5, "QoreNamespaceIntern::runtimeFindNamespaceForAddFunction() this: %p name: %s ns: %p '%s' rv: %p fnd: %d\n", this, name.ostr, nmi.get(), nmi.get()->name.c_str(), rv, fnd);
1267  if (rv)
1268  return const_cast<QoreNamespace*>(rv->ns);
1269  }
1270 
1271  if (fnd)
1272  xsink->raiseException("FUNCTION-IMPORT-ERROR", "target function '%s' already exists in the given namespace", name.ostr);
1273  else
1274  xsink->raiseException("FUNCTION-IMPORT-ERROR", "target namespace in '%s' does not exist", name.ostr);
1275  return 0;
1276  }
1277 
1278  DLLLOCAL QoreNamespace* runtimeFindNamespaceForAddClass(const NamedScope& name, ExceptionSink* xsink) {
1279  bool fnd = false;
1280 
1281  // iterate all namespaces with the initial name and look for the match
1282  NamespaceMapIterator nmi(nsmap, name.get(0));
1283  while (nmi.next()) {
1284  const qore_ns_private* rv = nmi.get()->runtimeMatchAddClass(name, fnd);
1285  if (rv)
1286  return const_cast<QoreNamespace*>(rv->ns);
1287  }
1288 
1289  if (fnd)
1290  xsink->raiseException("CLASS-IMPORT-ERROR", "target class '%s' already exists in the given namespace", name.ostr);
1291  else
1292  xsink->raiseException("CLASS-IMPORT-ERROR", "target namespace in '%s' does not exist", name.ostr);
1293  return 0;
1294  }
1295 
1296  DLLLOCAL void addConstant(qore_ns_private& ns, const char* cname, QoreValue value, const QoreTypeInfo* typeInfo);
1297 
1298  DLLLOCAL QoreValue parseFindReferencedConstantValueIntern(const QoreProgramLocation* loc, const NamedScope& name, const QoreTypeInfo*& typeInfo, bool& found, bool error);
1299 
1300  DLLLOCAL QoreValue parseResolveBarewordIntern(const QoreProgramLocation* loc, const char* bword, const QoreTypeInfo*& typeInfo, bool& found);
1301 
1302  DLLLOCAL QoreValue parseResolveReferencedScopedReferenceIntern(const QoreProgramLocation* loc, const NamedScope& name, const QoreTypeInfo*& typeInfo, bool& found);
1303 
1304  DLLLOCAL void parseAddConstantIntern(const QoreProgramLocation* loc, QoreNamespace& ns, const NamedScope& name, QoreValue value, bool pub);
1305 
1306  DLLLOCAL void parseAddClassIntern(const QoreProgramLocation* loc, const NamedScope& name, QoreClass* oc);
1307 
1308  DLLLOCAL void parseAddHashDeclIntern(const QoreProgramLocation* loc, const NamedScope& name, TypedHashDecl* hd);
1309 
1310  DLLLOCAL qore_ns_private* parseResolveNamespaceIntern(const QoreProgramLocation* loc, const NamedScope& nscope, qore_ns_private* sns);
1311  DLLLOCAL qore_ns_private* parseResolveNamespace(const QoreProgramLocation* loc, const NamedScope& nscope, qore_ns_private* sns);
1312  DLLLOCAL qore_ns_private* parseResolveNamespace(const QoreProgramLocation* loc, const NamedScope& nscope);
1313 
1314  DLLLOCAL const FunctionEntry* parseResolveFunctionEntryIntern(const NamedScope& nscope);
1315 
1316  DLLLOCAL Var* parseAddResolvedGlobalVarDefIntern(const QoreProgramLocation* loc, const NamedScope& name, const QoreTypeInfo* typeInfo);
1317  DLLLOCAL Var* parseAddGlobalVarDefIntern(const QoreProgramLocation* loc, const NamedScope& name, QoreParseTypeInfo* typeInfo);
1318 
1319  DLLLOCAL Var* parseCheckImplicitGlobalVarIntern(const QoreProgramLocation* loc, const NamedScope& name, const QoreTypeInfo* typeInfo);
1320 
1321  DLLLOCAL Var* parseFindGlobalVarIntern(const NamedScope& vname) {
1322  assert(vname.size() > 1);
1323 
1324  Var* rv = 0;
1325  unsigned match = 0;
1326 
1327  {
1328  // try to check in current namespace first
1329  qore_ns_private* nscx = parse_get_ns();
1330  if (nscx && nscx->name == vname[0]) {
1331  QoreNamespace* vns = nscx->parseMatchNamespace(vname, match);
1332  if (vns && (rv = vns->priv->var_list.parseFindVar(vname.getIdentifier())))
1333  return rv;
1334  }
1335  }
1336 
1337  // iterate all namespaces with the initial name and look for the match
1338  {
1339  NamespaceMapIterator nmi(nsmap, vname[0]);
1340  while (nmi.next()) {
1341  QoreNamespace* vns = nmi.get()->parseMatchNamespace(vname, match);
1342  if (vns && (rv = vns->priv->var_list.parseFindVar(vname.getIdentifier())))
1343  return rv;
1344  }
1345  }
1346 
1347  return rv;
1348  }
1349 
1350  DLLLOCAL Var* parseFindGlobalVarIntern(const char* vname) {
1351  {
1352  // try to check in current namespace first
1353  qore_ns_private* nscx = parse_get_ns();
1354  if (nscx) {
1355  Var* v = nscx->var_list.parseFindVar(vname);
1356  if (v)
1357  return v;
1358  }
1359 
1360  //printd(5, "qore_root_ns_private::parseFindGlobalVarIntern() this: %p '%s' nscx: %p ('%s') varmap: %d pend_varmap: %d\n", this, vname, nscx, nscx ? nscx->name.c_str() : "n/a", varmap.find(vname) != varmap.end(), pend_varmap.find(vname) != pend_varmap.end());
1361  }
1362 
1363  varmap_t::iterator i = varmap.find(vname);
1364 
1365  if (i != varmap.end()) {
1366  return i->second.obj;
1367  }
1368 
1369  return nullptr;
1370  }
1371 
1372  DLLLOCAL Var* runtimeFindGlobalVar(const NamedScope& nscope, const qore_ns_private*& vns) const;
1373 
1374  DLLLOCAL Var* runtimeFindGlobalVar(const char* vname, const qore_ns_private*& vns) const {
1375  if (strstr(vname, "::")) {
1376  NamedScope nscope(vname);
1377  return runtimeFindGlobalVar(nscope, vns);
1378  }
1379 
1380  varmap_t::const_iterator i = varmap.find(vname);
1381  if (i != varmap.end()) {
1382  assert(i->second.ns);
1383  vns = i->second.ns;
1384  return i->second.obj;
1385  }
1386  return nullptr;
1387  }
1388 
1389  DLLLOCAL const ConstantEntry* runtimeFindNamespaceConstant(const NamedScope& nscope, const qore_ns_private*& cns) const;
1390 
1391  DLLLOCAL const ConstantEntry* runtimeFindNamespaceConstant(const char* cname, const qore_ns_private*& cns) const {
1392  if (strstr(cname, "::")) {
1393  NamedScope nscope(cname);
1394  return runtimeFindNamespaceConstant(nscope, cns);
1395  }
1396 
1397  cnmap_t::const_iterator i = cnmap.find(cname);
1398  if (i != cnmap.end()) {
1399  assert(i->second.ns);
1400  cns = i->second.ns;
1401  return i->second.obj;
1402  }
1403  return nullptr;
1404  }
1405 
1406  DLLLOCAL void runtimeImportGlobalVariable(qore_ns_private& tns, Var* v, bool readonly, ExceptionSink* xsink) {
1407  Var* var = tns.var_list.import(v, xsink, readonly);
1408  if (!var)
1409  return;
1410 
1411  varmap.update(var->getName(), &tns, var);
1412  }
1413 
1414  DLLLOCAL Var* runtimeCreateVar(qore_ns_private& vns, const char* vname, const QoreTypeInfo* typeInfo, bool builtin) {
1415  Var* v = vns.var_list.runtimeCreateVar(vname, typeInfo, builtin);
1416 
1417  if (v)
1418  varmap.update(v->getName(), &vns, v);
1419  return v;
1420  }
1421 
1422  DLLLOCAL bool parseResolveGlobalVarsAndClassHierarchiesIntern();
1423 
1424  // returns 0 for success, non-zero for error
1425  DLLLOCAL int parseAddMethodToClassIntern(const QoreProgramLocation* loc, const NamedScope& name, MethodVariantBase* qcmethod, bool static_flag);
1426 
1427  DLLLOCAL static void rebuildConstantIndexes(cnmap_t& cnmap, ConstantList& cl, qore_ns_private* ns) {
1428  ConstantListIterator cli(cl);
1429  while (cli.next())
1430  cnmap.update(cli.getName().c_str(), ns, cli.getEntry());
1431  }
1432 
1433  DLLLOCAL static void rebuildClassIndexes(clmap_t& clmap, QoreClassList& cl, qore_ns_private* ns) {
1434  ClassListIterator cli(cl);
1435  while (cli.next())
1436  clmap.update(cli.getName(), ns, cli.get());
1437  }
1438 
1439  DLLLOCAL static void rebuildHashDeclIndexes(thdmap_t& thdmap, HashDeclList& hdl, qore_ns_private* ns) {
1440  HashDeclListIterator hdli(hdl);
1441  while (hdli.next())
1442  thdmap.update(hdli.getName(), ns, hdli.get());
1443  }
1444 
1445  DLLLOCAL static void rebuildFunctionIndexes(fmap_t& fmap, fl_map_t& flmap, qore_ns_private* ns) {
1446  for (fl_map_t::iterator i = flmap.begin(), e = flmap.end(); i != e; ++i) {
1447  assert(i->second->getNamespace() == ns);
1448  fmap.update(i->first, i->second);
1449  //printd(5, "qore_root_ns_private::rebuildFunctionIndexes() this: %p ns: %p func %s\n", this, ns, i->first);
1450  }
1451  }
1452 
1453  DLLLOCAL void rebuildIndexes(qore_ns_private* ns) {
1454  // process function indexes
1455  rebuildFunctionIndexes(fmap, ns->func_list, ns);
1456 
1457  // process variable indexes
1458  for (map_var_t::iterator i = ns->var_list.vmap.begin(), e = ns->var_list.vmap.end(); i != e; ++i)
1459  varmap.update(i->first, ns, i->second);
1460 
1461  // process constant indexes
1462  rebuildConstantIndexes(cnmap, ns->constant, ns);
1463 
1464  // process class indexes
1465  rebuildClassIndexes(clmap, ns->classList, ns);
1466 
1467  // process hashdecl indexes
1468  rebuildHashDeclIndexes(thdmap, ns->hashDeclList, ns);
1469 
1470  // reindex namespace
1471  nsmap.update(ns);
1472 
1473  // inserts into depth list
1474  nshlist.add(ns);
1475  }
1476 
1477  DLLLOCAL void parseRebuildIndexes(qore_ns_private* ns) {
1478  //printd(5, "qore_root_ns_private::parseRebuildIndexes() this: %p ns: %p (%s) depth %d\n", this, ns, ns->name.c_str(), ns->depth);
1479 
1480  // process function indexes
1481  for (fl_map_t::iterator i = ns->func_list.begin(), e = ns->func_list.end(); i != e; ++i) {
1482  assert(i->second->getNamespace() == ns);
1483  pend_fmap.update(i->first, i->second);
1484  }
1485 
1486  // process variable indexes
1487  for (map_var_t::iterator i = ns->var_list.vmap.begin(), e = ns->var_list.vmap.end(); i != e; ++i)
1488  varmap.update(i->first, ns, i->second);
1489 
1490  // process constant indexes
1491  rebuildConstantIndexes(cnmap, ns->constant, ns);
1492 
1493  // process class indexes
1494  rebuildClassIndexes(clmap, ns->classList, ns);
1495 
1496  // process hashdecl indexes
1497  rebuildHashDeclIndexes(thdmap, ns->hashDeclList, ns);
1498 
1499  // reindex namespace
1500  nsmap.update(ns);
1501  }
1502 
1503  DLLLOCAL void parseAddNamespaceIntern(QoreNamespace* nns);
1504 
1505 public:
1506  RootQoreNamespace* rns;
1507  QoreNamespace* qoreNS;
1509 
1511  QoreProgram* pgm = nullptr;
1512 
1513  fmap_t fmap, // root function map
1514  pend_fmap; // root pending function map (only used during parsing)
1515 
1516  cnmap_t cnmap; // root constant map
1517 
1518  clmap_t clmap; // root class map
1519 
1520  thdmap_t thdmap; // root hashdecl map
1521 
1522  varmap_t varmap; // root variable map
1523 
1524  NamespaceMap nsmap; // root namespace map
1525 
1526  NamespaceDepthList nshlist; // root namespace with handler map
1527 
1528  // unresolved pending global variable list - only used in the 1st stage of parsing (data read in to tree)
1529  gvlist_t pend_gvlist;
1530 
1531  DLLLOCAL qore_root_ns_private(RootQoreNamespace* n_rns) : qore_ns_private(n_rns), rns(n_rns), qoreNS(nullptr) {
1532  assert(root);
1533  assert(pub);
1534  // add initial namespace to committed map
1535  nsmap.update(this);
1536  }
1537 
1538  DLLLOCAL qore_root_ns_private(const qore_root_ns_private& old, int64 po, QoreProgram* pgm)
1539  : qore_ns_private(old, po), pgm(pgm) {
1540  assert(pgm);
1541  if ((po & PO_NO_API) == PO_NO_API) {
1542  // create empty Qore namespace
1543  qoreNS = new QoreNamespace("Qore");
1544  nsl.nsmap.insert(nsmap_t::value_type("Qore", qoreNS));
1545  qoreNS->priv->nsl.nsmap.insert(nsmap_t::value_type("Option", new QoreNamespace("Option")));
1546  } else
1547  qoreNS = nsl.find("Qore");
1548  assert(qoreNS);
1549 
1550  // always set the module public flag to true in the root namespace
1551  pub = true;
1552 
1553  // rebuild root indexes - only for committed objects
1554  rebuildAllIndexes();
1555  }
1556 
1557  DLLLOCAL ~qore_root_ns_private() {
1558  }
1559 
1560  DLLLOCAL RootQoreNamespace* copy(int64 po, QoreProgram* pgm) {
1561  qore_root_ns_private* p = new qore_root_ns_private(*this, po, pgm);
1562  RootQoreNamespace* rv = new RootQoreNamespace(p);
1563  return rv;
1564  }
1565 
1566  DLLLOCAL void rebuildAllIndexes() {
1567  // clear depth list
1568  nshlist.clear();
1569 
1570  // rebuild root indexes
1571  QorePrivateNamespaceIterator qpni(this);
1572  while (qpni.next())
1573  rebuildIndexes(qpni.get());
1574  }
1575 
1576  DLLLOCAL void deferParseCheckAbstractNew(const qore_class_private* qc, const QoreProgramLocation* loc) {
1577  deferred_new_check_vec.push_back(deferred_new_check_t(qc, loc));
1578  }
1579 
1580  DLLLOCAL QoreNamespace* runtimeFindNamespace(const NamedScope& name) {
1581  // iterate all namespaces with the initial name and look for the match
1582  NamespaceMapIterator nmi(nsmap, name[0]);
1583  while (nmi.next()) {
1584  const qore_ns_private* rv = nmi.get()->runtimeMatchNamespace(name);
1585  if (rv) {
1586  return const_cast<QoreNamespace*>(rv->ns);
1587  }
1588  }
1589 
1590  return nullptr;
1591  }
1592 
1593  DLLLOCAL QoreNamespace* runtimeFindNamespace(const QoreString& name) {
1594  if (name.bindex("::", 0) != -1) {
1595  NamedScope scope(name.c_str());
1596  return runtimeFindNamespace(scope);
1597  }
1598 
1599  return nsmap.findFirst(name.c_str());
1600  }
1601 
1602  DLLLOCAL const QoreClass* runtimeFindScopedClassWithMethod(const NamedScope& name) const;
1603  DLLLOCAL const QoreClass* runtimeFindScopedClassWithMethodIntern(const NamedScope& name) const;
1604 
1605  /*
1606  DLLLOCAL void deleteClearData(ExceptionSink* xsink) {
1607  }
1608  */
1609 
1610  DLLLOCAL qore_ns_private* getQore() {
1611  return qoreNS->priv;
1612  }
1613 
1614  DLLLOCAL const qore_ns_private* getQore() const {
1615  return qoreNS->priv;
1616  }
1617 
1618  DLLLOCAL QoreHashNode* getGlobalVars() const {
1619  QoreHashNode* rv = new QoreHashNode(autoTypeInfo);
1620  qore_ns_private::getGlobalVars(*rv);
1621  return rv;
1622  }
1623 
1624  DLLLOCAL void commitModule(QoreModuleContext& qmc) {
1625  for (unsigned j = 0; j < qmc.mcnl.size(); ++j) {
1626  ModuleContextNamespaceCommit& mc = qmc.mcnl[j];
1627  mc.parent->addCommitNamespaceIntern(mc.nns);
1628  }
1629 
1630  for (unsigned j = 0; j < qmc.mcfl.size(); ++j) {
1631  ModuleContextFunctionCommit& mc = qmc.mcfl[j];
1632  mc.parent->addBuiltinVariantIntern(mc.name, mc.v);
1633  }
1634 
1635  // issue #3461: must rebuild all indexes here or symbols will appear missing
1636  if (qmc.mcnl.size() || qmc.mcfl.size()) {
1637  rebuildAllIndexes();
1638  }
1639  }
1640 
1641  DLLLOCAL void parseRollback(ExceptionSink* xsink) {
1642  // roll back pending lookup entries
1643  pend_fmap.clear();
1644  cnmap.clear();
1645 
1646  varmap.clear();
1647  nsmap.clear();
1648 
1649  // roll back pending global variables
1650  pend_gvlist.clear();
1651 
1652  clmap.clear();
1653  thdmap.clear();
1654 
1655  // delete any deferred new object checks for classes with abstract members
1656  deferred_new_check_vec.clear();
1657 
1658  qore_ns_private::parseRollback(xsink);
1659  }
1660 
1661  DLLLOCAL TypedHashDecl* parseFindHashDecl(const QoreProgramLocation* loc, const NamedScope& name);
1662 
1663  DLLLOCAL const TypedHashDecl* runtimeFindHashDeclIntern(const NamedScope& name, const qore_ns_private*& ns);
1664 
1665  DLLLOCAL QoreNamespace* runtimeFindCreateNamespacePath(const NamedScope& nspath, bool pub, bool user) {
1666  assert(nspath.size());
1667  bool is_new = false;
1668  QoreNamespace* nns = findCreateNamespacePath(nspath, pub, user, is_new);
1669  if (is_new) // add namespace index
1670  nsmap.update(nns->priv);
1671  return nns;
1672  }
1673 
1674  DLLLOCAL QoreNamespace* runtimeFindCreateNamespacePath(const qore_ns_private& ns, bool user) {
1675  // get a list of namespaces from after the root (not including the root) to the current
1676  nslist_t nsl;
1677  ns.getNsList(nsl);
1678 
1679  printd(5, "qore_root_ns_private::runtimeFindCreateNamespacePath() this: %p ns: '%s'\n", this, ns.name.c_str());
1680 
1681  bool is_new = false;
1682  QoreNamespace* nns = findCreateNamespacePath(nsl, user, is_new);
1683  assert(ns.name == nns->getName());
1684  if (is_new) // add namespace index
1685  nsmap.update(nns->priv);
1686  return nns;
1687  }
1688 
1689  DLLLOCAL void runtimeRebuildConstantIndexes(qore_ns_private* ns) {
1690  rebuildConstantIndexes(cnmap, ns->constant, ns);
1691  }
1692 
1693  DLLLOCAL void runtimeRebuildClassIndexes(qore_ns_private* ns) {
1694  rebuildClassIndexes(clmap, ns->classList, ns);
1695  }
1696 
1697  DLLLOCAL void runtimeRebuildHashDeclIndexes(qore_ns_private* ns) {
1698  rebuildHashDeclIndexes(thdmap, ns->hashDeclList, ns);
1699  }
1700 
1701  DLLLOCAL void runtimeRebuildFunctionIndexes(qore_ns_private* ns) {
1702  rebuildFunctionIndexes(fmap, ns->func_list, ns);
1703  }
1704 
1705  DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindCall(const char* name, const QoreListNode* params, ExceptionSink* xsink);
1706 
1707  DLLLOCAL QoreListNode* runtimeFindCallVariants(const char* name, ExceptionSink* xsink);
1708 
1709  DLLLOCAL void parseInit();
1710 
1711  DLLLOCAL class_vec_t runtimeFindAllClassesRegex(const QoreString& pattern, int re_opts, ExceptionSink* xsink) const;
1712 
1713  DLLLOCAL hashdecl_vec_t runtimeFindAllHashDeclsRegex(const QoreString& pattern, int re_opts, ExceptionSink* xsink) const;
1714 
1715  DLLLOCAL func_vec_t runtimeFindAllFunctionsRegex(const QoreString& pattern, int re_opts, ExceptionSink* xsink) const;
1716 
1717  DLLLOCAL ns_vec_t runtimeFindAllNamespacesRegex(const QoreString& pattern, int re_opts, ExceptionSink* xsink) const;
1718 
1719  DLLLOCAL gvar_vec_t runtimeFindAllGlobalVarsRegex(const QoreString& pattern, int re_opts, ExceptionSink* xsink) const;
1720 
1721  DLLLOCAL const_vec_t runtimeFindAllNamespaceConstantsRegex(const QoreString& pattern, int re_opts, ExceptionSink* xsink) const;
1722 
1723  DLLLOCAL static QoreHashNode* getGlobalVars(RootQoreNamespace& rns) {
1724  return rns.rpriv->getGlobalVars();
1725  }
1726 
1727  DLLLOCAL static void runtimeImportSystemClasses(RootQoreNamespace& rns, const RootQoreNamespace& source, ExceptionSink* xsink) {
1728  rns.priv->runtimeImportSystemClasses(*source.priv, *rns.rpriv, xsink);
1729  }
1730 
1731  DLLLOCAL static void runtimeImportSystemHashDecls(RootQoreNamespace& rns, const RootQoreNamespace& source, ExceptionSink* xsink) {
1732  rns.priv->runtimeImportSystemHashDecls(*source.priv, *rns.rpriv, xsink);
1733  }
1734 
1735  DLLLOCAL static void runtimeImportSystemConstants(RootQoreNamespace& rns, const RootQoreNamespace& source, ExceptionSink* xsink) {
1736  rns.priv->runtimeImportSystemConstants(*source.priv, *rns.rpriv, xsink);
1737  }
1738 
1739  DLLLOCAL static void runtimeImportSystemFunctions(RootQoreNamespace& rns, const RootQoreNamespace& source, ExceptionSink* xsink) {
1740  rns.priv->runtimeImportSystemFunctions(*source.priv, *rns.rpriv, xsink);
1741  }
1742 
1743  DLLLOCAL static QoreNamespace* runtimeFindCreateNamespacePath(const RootQoreNamespace& rns, const qore_ns_private& ns, bool user) {
1744  return rns.rpriv->runtimeFindCreateNamespacePath(ns, user);
1745  }
1746 
1747  DLLLOCAL static QoreNamespace* runtimeFindCreateNamespacePath(const RootQoreNamespace& rns, const NamedScope& nspath, bool pub, bool user) {
1748  return rns.rpriv->runtimeFindCreateNamespacePath(nspath, pub, user);
1749  }
1750 
1751  DLLLOCAL static RootQoreNamespace* copy(const RootQoreNamespace& rns, int64 po, QoreProgram* pgm) {
1752  return rns.rpriv->copy(po, pgm);
1753  }
1754 
1755  DLLLOCAL static int addPendingVariant(qore_ns_private& nsp, const char* name, AbstractQoreFunctionVariant* v) {
1756  return getRootNS()->rpriv->addPendingVariantIntern(nsp, name, v);
1757  }
1758 
1759  DLLLOCAL static int addPendingVariant(qore_ns_private& nsp, const NamedScope& name, AbstractQoreFunctionVariant* v) {
1760  return getRootNS()->rpriv->addPendingVariantIntern(nsp, name, v);
1761  }
1762 
1763  DLLLOCAL static int runtimeImportFunction(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns, QoreFunction* u, const char* new_name = nullptr, bool inject = false) {
1764  return rns.rpriv->runtimeImportFunction(xsink, *ns.priv, u, new_name, inject);
1765  }
1766 
1767  DLLLOCAL static int runtimeImportClass(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns, const QoreClass* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = 0, bool inject = false, const qore_class_private* injectedClass = nullptr) {
1768  return rns.rpriv->runtimeImportClass(xsink, *ns.priv, c, spgm, set_pub, new_name, inject, injectedClass);
1769  }
1770 
1771  DLLLOCAL static int runtimeImportHashDecl(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns, const TypedHashDecl* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr) {
1772  return rns.rpriv->runtimeImportHashDecl(xsink, *ns.priv, c, spgm, set_pub, new_name);
1773  }
1774 
1775  DLLLOCAL static const QoreClass* runtimeFindClass(RootQoreNamespace& rns, const char* name, const qore_ns_private*& ns) {
1776  if (strstr(name, "::")) {
1777  NamedScope nscope(name);
1778  return rns.rpriv->runtimeFindClassIntern(nscope, ns);
1779  }
1780  return rns.rpriv->runtimeFindClassIntern(name, ns);
1781  }
1782 
1783  DLLLOCAL static const TypedHashDecl* runtimeFindHashDecl(RootQoreNamespace& rns, const char* name, const qore_ns_private*& ns) {
1784  if (strstr(name, "::")) {
1785  NamedScope nscope(name);
1786  return rns.rpriv->runtimeFindHashDeclIntern(nscope, ns);
1787  }
1788  return rns.rpriv->runtimeFindHashDeclIntern(name, ns);
1789  }
1790 
1791  DLLLOCAL static const QoreFunction* runtimeFindFunction(RootQoreNamespace& rns, const char* name, const qore_ns_private*& ns) {
1792  const FunctionEntry* fe = runtimeFindFunctionEntry(rns, name);
1793  if (fe) {
1794  ns = fe->getNamespace();
1795  return fe->getFunction();
1796  }
1797  return nullptr;
1798  }
1799 
1800  DLLLOCAL static const FunctionEntry* runtimeFindFunctionEntry(RootQoreNamespace& rns, const char* name) {
1801  if (strstr(name, "::")) {
1802  NamedScope nscope(name);
1803  return rns.rpriv->runtimeFindFunctionEntryIntern(nscope);
1804  }
1805  return rns.rpriv->runtimeFindFunctionEntryIntern(name);
1806  }
1807 
1808  DLLLOCAL static bool runtimeExistsFunction(RootQoreNamespace& rns, const char* name) {
1809  return rns.rpriv->runtimeExistsFunctionIntern(name);
1810  }
1811 
1812  DLLLOCAL static void addConstant(qore_root_ns_private& rns, qore_ns_private& ns, const char* cname, QoreValue value, const QoreTypeInfo* typeInfo) {
1813  rns.addConstant(ns, cname, value, typeInfo);
1814  }
1815 
1816  DLLLOCAL static const QoreFunction* parseResolveFunction(const QoreProgramLocation* loc, const char* fname) {
1817  const FunctionEntry* fe = getRootNS()->rpriv->parseResolveFunctionEntryIntern(loc, fname);
1818  return fe ? fe->getFunction() : nullptr;
1819  }
1820 
1821  DLLLOCAL static const FunctionEntry* parseResolveFunctionEntry(const QoreProgramLocation* loc, const char* fname) {
1822  return getRootNS()->rpriv->parseResolveFunctionEntryIntern(loc, fname);
1823  }
1824 
1825  // called during parsing (plock already grabbed)
1826  DLLLOCAL static AbstractCallReferenceNode* parseResolveCallReference(UnresolvedProgramCallReferenceNode* fr) {
1827  return getRootNS()->rpriv->parseResolveCallReferenceIntern(fr);
1828  }
1829 
1830  DLLLOCAL static bool parseResolveGlobalVarsAndClassHierarchies() {
1831  return getRootNS()->rpriv->parseResolveGlobalVarsAndClassHierarchiesIntern();
1832  }
1833 
1834  DLLLOCAL static void parseCommit(RootQoreNamespace& rns) {
1835  rns.rpriv->parseCommit();
1836  }
1837 
1838  DLLLOCAL static QoreValue parseFindConstantValue(const QoreProgramLocation* loc, const char* name, const QoreTypeInfo*& typeInfo, bool& found, bool error) {
1839  found = false;
1840  return getRootNS()->rpriv->parseFindConstantValueIntern(loc, name, typeInfo, found, error);
1841  }
1842 
1843  DLLLOCAL static QoreValue parseFindReferencedConstantValue(const QoreProgramLocation* loc, const NamedScope& name, const QoreTypeInfo*& typeInfo, bool& found, bool error) {
1844  found = false;
1845  return getRootNS()->rpriv->parseFindReferencedConstantValueIntern(loc, name, typeInfo, found, error);
1846  }
1847 
1848  DLLLOCAL static QoreValue parseResolveBareword(const QoreProgramLocation* loc, const char* bword, const QoreTypeInfo*& typeInfo, bool& found) {
1849  found = false;
1850  return getRootNS()->rpriv->parseResolveBarewordIntern(loc, bword, typeInfo, found);
1851  }
1852 
1853  DLLLOCAL static QoreValue parseResolveReferencedScopedReference(const QoreProgramLocation* loc, const NamedScope& name, const QoreTypeInfo*& typeInfo, bool& found) {
1854  found = false;
1855  return getRootNS()->rpriv->parseResolveReferencedScopedReferenceIntern(loc, name, typeInfo, found);
1856  }
1857 
1858  DLLLOCAL static QoreClass* parseFindClass(const QoreProgramLocation* loc, const char* name, bool raise_error = true) {
1859  QoreClass* qc = getRootNS()->rpriv->parseFindClassIntern(name);
1860  if (!qc && raise_error) {
1861  parse_error(*loc, "reference to undefined class '%s'", name);
1862  }
1863  return qc;
1864  }
1865 
1866  DLLLOCAL static QoreClass* parseFindScopedClass(const QoreProgramLocation* loc, const NamedScope& name, bool raise_error = true) {
1867  return getRootNS()->rpriv->parseFindScopedClassIntern(loc, name, raise_error);
1868  }
1869 
1870  DLLLOCAL static QoreClass* parseFindScopedClassWithMethod(const QoreProgramLocation* loc, const NamedScope& name, bool error) {
1871  return getRootNS()->rpriv->parseFindScopedClassWithMethodInternError(loc, name, error);
1872  }
1873 
1874  DLLLOCAL static void parseAddConstant(const QoreProgramLocation* loc, QoreNamespace& ns, const NamedScope& name, QoreValue value, bool pub) {
1875  getRootNS()->rpriv->parseAddConstantIntern(loc, ns, name, value, pub);
1876  }
1877 
1878  // returns 0 for success, non-zero for error
1879  DLLLOCAL static int parseAddMethodToClass(const QoreProgramLocation* loc, const NamedScope& name, MethodVariantBase* qcmethod, bool static_flag) {
1880  return getRootNS()->rpriv->parseAddMethodToClassIntern(loc, name, qcmethod, static_flag);
1881  }
1882 
1883  DLLLOCAL static void parseAddClass(const QoreProgramLocation* loc, const NamedScope& name, QoreClass* oc) {
1884  getRootNS()->rpriv->parseAddClassIntern(loc, name, oc);
1885  }
1886 
1887  DLLLOCAL static void parseAddHashDecl(const QoreProgramLocation* loc, const NamedScope& name, TypedHashDecl* hd) {
1888  getRootNS()->rpriv->parseAddHashDeclIntern(loc, name, hd);
1889  }
1890 
1891  DLLLOCAL static void parseAddNamespace(QoreNamespace* nns) {
1892  getRootNS()->rpriv->parseAddNamespaceIntern(nns);
1893  }
1894 
1895  DLLLOCAL static const QoreFunction* parseResolveFunction(const NamedScope& nscope) {
1896  const FunctionEntry* fe = getRootNS()->rpriv->parseResolveFunctionEntryIntern(nscope);
1897  return fe ? fe->getFunction() : nullptr;
1898  }
1899 
1900  DLLLOCAL static const FunctionEntry* parseResolveFunctionEntry(const NamedScope& nscope) {
1901  return getRootNS()->rpriv->parseResolveFunctionEntryIntern(nscope);
1902  }
1903 
1904  DLLLOCAL const QoreClass* runtimeFindScopedClass(const NamedScope& name) const;
1905 
1906  DLLLOCAL static ResolvedCallReferenceNode* runtimeGetCallReference(RootQoreNamespace& rns, const char* name, ExceptionSink* xsink) {
1907  return rns.rpriv->runtimeGetCallReference(name, xsink);
1908  }
1909 
1910  DLLLOCAL static Var* parseAddResolvedGlobalVarDef(const QoreProgramLocation* loc, const NamedScope& vname, const QoreTypeInfo* typeInfo) {
1911  return getRootNS()->rpriv->parseAddResolvedGlobalVarDefIntern(loc, vname, typeInfo);
1912  }
1913 
1914  DLLLOCAL static Var* parseAddGlobalVarDef(const QoreProgramLocation* loc, const NamedScope& vname, QoreParseTypeInfo* typeInfo) {
1915  return getRootNS()->rpriv->parseAddGlobalVarDefIntern(loc, vname, typeInfo);
1916  }
1917 
1918  DLLLOCAL static Var* parseCheckImplicitGlobalVar(const QoreProgramLocation* loc, const NamedScope& name, const QoreTypeInfo* typeInfo) {
1919  return getRootNS()->rpriv->parseCheckImplicitGlobalVarIntern(loc, name, typeInfo);
1920  }
1921 
1922  DLLLOCAL static Var* parseFindGlobalVar(const char* vname) {
1923  return getRootNS()->rpriv->parseFindGlobalVarIntern(vname);
1924  }
1925 
1926  DLLLOCAL static Var* parseFindGlobalVar(const NamedScope& nscope) {
1927  return getRootNS()->rpriv->parseFindGlobalVarIntern(nscope);
1928  }
1929 
1930  DLLLOCAL static void scanMergeCommittedNamespace(const RootQoreNamespace& ns, const RootQoreNamespace& mns, QoreModuleContext& qmc) {
1931  ns.priv->scanMergeCommittedNamespace(*(mns.priv), qmc);
1932  }
1933 
1934  DLLLOCAL static void copyMergeCommittedNamespace(RootQoreNamespace& ns, const RootQoreNamespace& mns) {
1935  ns.priv->copyMergeCommittedNamespace(*(mns.priv));
1936 
1937  // rebuild root indexes - only for committed objects
1938  ns.rpriv->rebuildAllIndexes();
1939  }
1940 
1941  DLLLOCAL static Var* runtimeFindGlobalVar(const RootQoreNamespace& rns, const char* vname, const qore_ns_private*& vns) {
1942  return rns.rpriv->runtimeFindGlobalVar(vname, vns);
1943  }
1944 
1945  DLLLOCAL static Var* runtimeCreateVar(RootQoreNamespace& rns, QoreNamespace& vns, const char* vname, const QoreTypeInfo* typeInfo, bool builtin = false) {
1946  return rns.rpriv->runtimeCreateVar(*vns.priv, vname, typeInfo, builtin);
1947  }
1948 
1949  DLLLOCAL static void runtimeImportGlobalVariable(RootQoreNamespace& rns, QoreNamespace& tns, Var* v, bool readonly, ExceptionSink* xsink) {
1950  return rns.rpriv->runtimeImportGlobalVariable(*tns.priv, v, readonly, xsink);
1951  }
1952 
1953  /*
1954  DLLLOCAL static void runtimeModuleRebuildIndexes(RootQoreNamespace& rns) {
1955  // rebuild root indexes
1956  QorePrivateNamespaceIterator qpni(rns.priv, true);
1957  while (qpni.next())
1958  rns.rpriv->rebuildIndexes(qpni.get());
1959  }
1960  */
1961 
1962  DLLLOCAL static const QoreClass* runtimeFindClass(RootQoreNamespace& rns, const char* name) {
1963  return rns.rpriv->runtimeFindClass(name);
1964  }
1965 
1966  DLLLOCAL static const ConstantEntry* runtimeFindNamespaceConstant(const RootQoreNamespace& rns, const char* cname, const qore_ns_private*& cns) {
1967  return rns.rpriv->runtimeFindNamespaceConstant(cname, cns);
1968  }
1969 
1970  DLLLOCAL static QoreNamespace* runtimeFindNamespaceForAddFunction(RootQoreNamespace& rns, const NamedScope& name, ExceptionSink* xsink) {
1971  return rns.rpriv->runtimeFindNamespaceForAddFunction(name, xsink);
1972  }
1973 
1974  DLLLOCAL static QoreNamespace* runtimeFindNamespaceForAddClass(RootQoreNamespace& rns, const NamedScope& name, ExceptionSink* xsink) {
1975  return rns.rpriv->runtimeFindNamespaceForAddClass(name, xsink);
1976  }
1977 
1978  DLLLOCAL static qore_root_ns_private* get(RootQoreNamespace& rns) {
1979  return rns.rpriv;
1980  }
1981 
1982  DLLLOCAL static const qore_root_ns_private* get(const RootQoreNamespace& rns) {
1983  return rns.rpriv;
1984  }
1985 
1986  DLLLOCAL static qore_ns_private* getQore(RootQoreNamespace& rns) {
1987  return rns.rpriv->qoreNS->priv;
1988  }
1989 
1990  DLLLOCAL static const qore_ns_private* getQore(const RootQoreNamespace& rns) {
1991  return rns.rpriv->qoreNS->priv;
1992  }
1993 
1994  DLLLOCAL static void clearConstants(RootQoreNamespace& ns, QoreListNode& l) {
1995  ns.priv->clearConstants(l);
1996  ns.rpriv->cnmap.clear();
1997  }
1998 
1999  DLLLOCAL static void clearData(RootQoreNamespace& ns, ExceptionSink* xsink) {
2000  ns.priv->clearData(xsink);
2001  }
2002 };
2003 
2004 #endif
SimpleRefHolder
manages a reference count of a pointer to a class that takes a simple "deref()" call with no argument...
Definition: ReferenceHolder.h:118
PO_NO_API
#define PO_NO_API
an alias of PO_INHERITANCE_OPTIONS
Definition: Restrictions.h:154
TypedHashDecl::getName
const DLLEXPORT char * getName() const
returns the name of the typed hash
QoreProgram
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:126
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
QoreClass
defines a Qore-language class
Definition: QoreClass.h:239
QoreNamespace::addConstant
DLLEXPORT void addConstant(const char *name, QoreValue value)
adds a constant definition to the namespace
QoreClass::getName
const DLLEXPORT char * getName() const
returns the class name
QoreListNode
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
QoreNamespace::copy
DLLEXPORT QoreNamespace * copy(int po) const
returns a deep copy of the namespace; DEPRECATED: use copy(int64) instead
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
arg_vec_t
std::vector< QoreValue > arg_vec_t
vector of value information for default argument lists
Definition: common.h:254
QoreNamespace
contains constants, classes, and subnamespaces in QoreProgram objects
Definition: QoreNamespace.h:65
QoreString
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
QoreString::c_str
const DLLEXPORT char * c_str() const
returns the string's buffer; this data should not be changed
QoreNamespace::getName
const DLLEXPORT char * getName() const
returns the name of the namespace
ExceptionSink::raiseException
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
TypedHashDecl
typed hash declaration
Definition: TypedHashDecl.h:44
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
UnresolvedProgramCallReferenceNode
an unresolved call reference, only present temporarily in the parse tree
Definition: CallReferenceNode.h:68
num_params
static unsigned num_params(const QoreListNode *n)
returns the number of arguments passed to the function
Definition: params.h:54
type_vec_t
std::vector< const QoreTypeInfo * > type_vec_t
vector of type information for parameter lists
Definition: common.h:251
QoreString::bindex
DLLEXPORT qore_offset_t bindex(const QoreString &needle, qore_offset_t pos) const
returns the byte position of a substring within the string or -1 if not found
getProgram
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
ResolvedCallReferenceNode
base class for resolved call references
Definition: CallReferenceNode.h:105
QoreNamespace::findCreateNamespacePath
DLLEXPORT QoreNamespace * findCreateNamespacePath(const char *nspath)
finds a Namespace based on the argument; creates it (or the whole path) if necessary
name_vec_t
std::vector< std::string > name_vec_t
vector of parameter names for parameter lists
Definition: common.h:257
RootQoreNamespace
the root namespace of a QoreProgram object
Definition: QoreNamespace.h:335
QoreNamespace::QoreNamespace
DLLEXPORT QoreNamespace(const char *n)
creates a namespace with the given name
AbstractCallReferenceNode
base class for call references, reference-counted, dynamically allocated only
Definition: CallReferenceNode.h:39