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