Qore Programming Language  1.7.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  return f;
1239  }
1240 
1241  // called during parsing (plock already grabbed)
1242  DLLLOCAL AbstractCallReferenceNode* parseResolveCallReferenceIntern(UnresolvedProgramCallReferenceNode* fr);
1243 
1244  DLLLOCAL void parseCommit() {
1245  // commit pending function lookup entries
1246  for (fmap_t::iterator i = pend_fmap.begin(), e = pend_fmap.end(); i != e; ++i)
1247  fmap.update(i);
1248  pend_fmap.clear();
1249 
1250  qore_ns_private::parseCommit();
1251  // exceptions can be through thrown when performing runtime initialization
1252  qore_ns_private::parseCommitRuntimeInit(getProgram()->getParseExceptionSink());
1253  }
1254 
1255  DLLLOCAL ConstantEntry* parseFindOnlyConstantEntryIntern(const char* cname, qore_ns_private*& ns) {
1256  {
1257  // first try to look in current namespace context
1258  qore_ns_private* nscx = parse_get_ns();
1259  if (nscx) {
1260  ConstantEntry* ce = nscx->constant.findEntry(cname);
1261  if (ce) {
1262  ns = nscx;
1263  return ce;
1264  }
1265  }
1266  }
1267 
1268  // look up in global constant map
1269  cnmap_t::iterator i = cnmap.find(cname);
1270 
1271  if (i != cnmap.end()) {
1272  ns = i->second.ns;
1273  return i->second.obj;;
1274  }
1275 
1276  return 0;
1277  }
1278 
1279  DLLLOCAL QoreValue parseFindOnlyConstantValueIntern(const QoreProgramLocation* loc, const char* cname,
1280  const QoreTypeInfo*& typeInfo, bool& found) {
1281  assert(!found);
1282  qore_ns_private* ns;
1283  ConstantEntry* ce = parseFindOnlyConstantEntryIntern(cname, ns);
1284  if (!ce)
1285  return QoreValue();
1286 
1287  //printd(5, "qore_root_ns_private::parseFindOnlyConstantValueIntern() const: %s ns: %p %s\n", cname, ns,
1288  // ns->name.c_str());
1289 
1290  found = true;
1291  NamespaceParseContextHelper nspch(ns);
1292  return ce->get(loc, typeInfo, ns);
1293  }
1294 
1295  DLLLOCAL QoreValue parseFindConstantValueIntern(const QoreProgramLocation* loc, const char* cname,
1296  const QoreTypeInfo*& typeInfo, bool& found, bool error) {
1297  assert(!found);
1298  // look up class constants first
1299  QoreClass* pc = parse_get_class();
1300  if (pc) {
1301  QoreValue rv = qore_class_private::parseFindConstantValue(pc, cname, typeInfo, found,
1302  pc ? qore_class_private::get(*pc) : nullptr);
1303  if (found) {
1304  return rv;
1305  }
1306  }
1307 
1308  QoreValue rv = parseFindOnlyConstantValueIntern(loc, cname, typeInfo, found);
1309  if (found) {
1310  return rv;
1311  }
1312 
1313  if (error) {
1314  parse_error(*loc, "constant '%s' cannot be resolved in any namespace", cname);
1315  }
1316 
1317  return QoreValue();
1318  }
1319 
1320  DLLLOCAL ResolvedCallReferenceNode* runtimeGetCallReference(const char* fname, ExceptionSink* xsink) {
1321  fmap_t::iterator i = fmap.find(fname);
1322  if (i == fmap.end()) {
1323  xsink->raiseException("NO-SUCH-FUNCTION", "callback function '%s()' does not exist", fname);
1324  return 0;
1325  }
1326 
1327  return i->second.obj->makeCallReference(get_runtime_location());
1328  }
1329 
1330  DLLLOCAL TypedHashDecl* parseFindScopedHashDeclIntern(const NamedScope& nscope, unsigned& matched);
1331 
1332  DLLLOCAL TypedHashDecl* parseFindHashDeclIntern(const char* hdname) {
1333  {
1334  // try to check in current namespace first
1335  qore_ns_private* nscx = parse_get_ns();
1336  if (nscx) {
1337  TypedHashDecl* hd = nscx->parseFindLocalHashDecl(hdname);
1338  if (hd)
1339  return hd;
1340  }
1341  }
1342 
1343  thdmap_t::iterator i = thdmap.find(hdname);
1344 
1345  if (i != thdmap.end()) {
1346  return i->second.obj;
1347  }
1348 
1349  //printd(5, "qore_root_ns_private::parseFindHashDeclIntern() this: %p '%s' not found\n", this, cname);
1350  return nullptr;
1351  }
1352 
1353  DLLLOCAL QoreClass* parseFindScopedClassIntern(const QoreProgramLocation* loc, const NamedScope& name,
1354  bool raise_error);
1355  DLLLOCAL QoreClass* parseFindScopedClassIntern(const NamedScope& name, unsigned& matched);
1356  DLLLOCAL QoreClass* parseFindScopedClassWithMethodInternError(const QoreProgramLocation* loc,
1357  const NamedScope& name, bool error);
1358  DLLLOCAL QoreClass* parseFindScopedClassWithMethodIntern(const NamedScope& name, unsigned& matched);
1359 
1360  DLLLOCAL QoreClass* parseFindClassIntern(const char* cname) {
1361  assert(cname);
1362  {
1363  // try to check in current namespace first
1364  qore_ns_private* nscx = parse_get_ns();
1365  if (nscx) {
1366  QoreClass* qc = nscx->parseFindLocalClass(cname);
1367  if (qc)
1368  return qc;
1369  }
1370  }
1371 
1372  clmap_t::iterator i = clmap.find(cname);
1373 
1374  if (i != clmap.end()) {
1375  return i->second.obj;
1376  }
1377 
1378  // now check all namespaces with class handlers
1379  NamespaceDepthListIterator nhi(nshlist);
1380  while (nhi.next()) {
1381  QoreClass* qc = nhi.get()->findLoadClass(cname);
1382  if (qc)
1383  return qc;
1384  }
1385 
1386  //printd(5, "qore_root_ns_private::parseFindClassIntern() this: %p '%s' not found\n", this, cname);
1387  return nullptr;
1388  }
1389 
1390  DLLLOCAL const QoreClass* runtimeFindClass(const char* name) const {
1391  clmap_t::const_iterator i = clmap.find(name);
1392  return i != clmap.end() ? i->second.obj : nullptr;
1393  }
1394 
1395  DLLLOCAL QoreNamespace* runtimeFindNamespaceForAddFunction(const NamedScope& name, ExceptionSink* xsink) {
1396  //printd(5, "QoreNamespaceIntern::runtimeFindNamespaceForAddFunction() this: %p name: %s (%s)\n", this,
1397  // name.ostr, name[0]);
1398  bool fnd = false;
1399 
1400  // iterate all namespaces with the initial name and look for the match
1401  NamespaceMapIterator nmi(nsmap, name[0]);
1402  while (nmi.next()) {
1403  const qore_ns_private* rv = nmi.get()->runtimeMatchAddFunction(name, fnd);
1404  //printd(5, "QoreNamespaceIntern::runtimeFindNamespaceForAddFunction() this: %p name: %s ns: %p '%s' "
1405  // "rv: %p fnd: %d\n", this, name.ostr, nmi.get(), nmi.get()->name.c_str(), rv, fnd);
1406  if (rv)
1407  return const_cast<QoreNamespace*>(rv->ns);
1408  }
1409 
1410  if (fnd) {
1411  xsink->raiseException("FUNCTION-IMPORT-ERROR", "target function '%s' already exists in the given "
1412  "namespace", name.ostr);
1413  } else {
1414  xsink->raiseException("FUNCTION-IMPORT-ERROR", "target namespace in '%s' does not exist", name.ostr);
1415  }
1416  return nullptr;
1417  }
1418 
1419  DLLLOCAL QoreNamespace* runtimeFindNamespaceForAddClass(const NamedScope& name, ExceptionSink* xsink) {
1420  bool fnd = false;
1421 
1422  // iterate all namespaces with the initial name and look for the match
1423  NamespaceMapIterator nmi(nsmap, name.get(0));
1424  while (nmi.next()) {
1425  const qore_ns_private* rv = nmi.get()->runtimeMatchAddClass(name, fnd);
1426  if (rv)
1427  return const_cast<QoreNamespace*>(rv->ns);
1428  }
1429 
1430  if (fnd) {
1431  xsink->raiseException("CLASS-IMPORT-ERROR", "target class '%s' already exists in the given namespace",
1432  name.ostr);
1433  } else {
1434  xsink->raiseException("CLASS-IMPORT-ERROR", "target namespace in '%s' does not exist", name.ostr);
1435  }
1436  return 0;
1437  }
1438 
1439  DLLLOCAL void addConstant(qore_ns_private& ns, const char* cname, QoreValue value, const QoreTypeInfo* typeInfo);
1440 
1441  DLLLOCAL QoreValue parseFindReferencedConstantValueIntern(const QoreProgramLocation* loc, const NamedScope& name,
1442  const QoreTypeInfo*& typeInfo, bool& found, bool error);
1443 
1444  DLLLOCAL QoreValue parseResolveBarewordIntern(const QoreProgramLocation* loc, const char* bword,
1445  const QoreTypeInfo*& typeInfo, bool& found);
1446 
1447  DLLLOCAL QoreValue parseResolveReferencedScopedReferenceIntern(const QoreProgramLocation* loc,
1448  const NamedScope& name, const QoreTypeInfo*& typeInfo, bool& found);
1449 
1450  DLLLOCAL void parseAddConstantIntern(const QoreProgramLocation* loc, QoreNamespace& ns, const NamedScope& name,
1451  QoreValue value, bool pub);
1452 
1453  DLLLOCAL void parseAddClassIntern(const QoreProgramLocation* loc, const NamedScope& name, QoreClass* oc);
1454 
1455  DLLLOCAL void parseAddHashDeclIntern(const QoreProgramLocation* loc, const NamedScope& name, TypedHashDecl* hd);
1456 
1457  DLLLOCAL qore_ns_private* parseResolveNamespaceIntern(const QoreProgramLocation* loc, const NamedScope& nscope,
1458  qore_ns_private* sns);
1459  DLLLOCAL qore_ns_private* parseResolveNamespace(const QoreProgramLocation* loc, const NamedScope& nscope,
1460  qore_ns_private* sns);
1461  DLLLOCAL qore_ns_private* parseResolveNamespace(const QoreProgramLocation* loc, const NamedScope& nscope);
1462 
1463  DLLLOCAL const FunctionEntry* parseResolveFunctionEntryIntern(const NamedScope& nscope);
1464 
1465  DLLLOCAL Var* parseAddResolvedGlobalVarDefIntern(const QoreProgramLocation* loc, const NamedScope& name,
1466  const QoreTypeInfo* typeInfo, qore_var_t type = VT_GLOBAL);
1467  DLLLOCAL Var* parseAddGlobalVarDefIntern(const QoreProgramLocation* loc, const NamedScope& name,
1468  QoreParseTypeInfo* typeInfo, qore_var_t type = VT_GLOBAL);
1469 
1470  DLLLOCAL Var* parseCheckImplicitGlobalVarIntern(const QoreProgramLocation* loc, const NamedScope& name,
1471  const QoreTypeInfo* typeInfo);
1472 
1473  DLLLOCAL Var* parseFindGlobalVarIntern(const NamedScope& vname) {
1474  assert(vname.size() > 1);
1475 
1476  Var* rv = 0;
1477  unsigned match = 0;
1478 
1479  {
1480  // try to check in current namespace first
1481  qore_ns_private* nscx = parse_get_ns();
1482  if (nscx && nscx->name == vname[0]) {
1483  QoreNamespace* vns = nscx->parseMatchNamespace(vname, match);
1484  if (vns && (rv = vns->priv->var_list.parseFindVar(vname.getIdentifier())))
1485  return rv;
1486  }
1487  }
1488 
1489  // iterate all namespaces with the initial name and look for the match
1490  {
1491  NamespaceMapIterator nmi(nsmap, vname[0]);
1492  while (nmi.next()) {
1493  QoreNamespace* vns = nmi.get()->parseMatchNamespace(vname, match);
1494  if (vns && (rv = vns->priv->var_list.parseFindVar(vname.getIdentifier())))
1495  return rv;
1496  }
1497  }
1498 
1499  return rv;
1500  }
1501 
1502  DLLLOCAL Var* parseFindGlobalVarIntern(const char* vname) {
1503  {
1504  // try to check in current namespace first
1505  qore_ns_private* nscx = parse_get_ns();
1506  if (nscx) {
1507  Var* v = nscx->var_list.parseFindVar(vname);
1508  if (v)
1509  return v;
1510  }
1511 
1512  //printd(5, "qore_root_ns_private::parseFindGlobalVarIntern() this: %p '%s' nscx: %p ('%s') varmap: %d "
1513  // "pend_varmap: %d\n", this, vname, nscx, nscx ? nscx->name.c_str() : "n/a",
1514  // varmap.find(vname) != varmap.end(), pend_varmap.find(vname) != pend_varmap.end());
1515  }
1516 
1517  varmap_t::iterator i = varmap.find(vname);
1518 
1519  if (i != varmap.end()) {
1520  return i->second.obj;
1521  }
1522 
1523  return nullptr;
1524  }
1525 
1526  DLLLOCAL Var* runtimeFindGlobalVar(const NamedScope& nscope, const qore_ns_private*& vns) const;
1527 
1528  DLLLOCAL Var* runtimeFindGlobalVar(const char* vname, const qore_ns_private*& vns) const {
1529  if (strstr(vname, "::")) {
1530  NamedScope nscope(vname);
1531  return runtimeFindGlobalVar(nscope, vns);
1532  }
1533 
1534  varmap_t::const_iterator i = varmap.find(vname);
1535  if (i != varmap.end()) {
1536  assert(i->second.ns);
1537  vns = i->second.ns;
1538  return i->second.obj;
1539  }
1540  return nullptr;
1541  }
1542 
1543  DLLLOCAL const ConstantEntry* runtimeFindNamespaceConstant(const NamedScope& nscope,
1544  const qore_ns_private*& cns) const;
1545 
1546  DLLLOCAL const ConstantEntry* runtimeFindNamespaceConstant(const char* cname, const qore_ns_private*& cns) const {
1547  if (strstr(cname, "::")) {
1548  NamedScope nscope(cname);
1549  return runtimeFindNamespaceConstant(nscope, cns);
1550  }
1551 
1552  cnmap_t::const_iterator i = cnmap.find(cname);
1553  if (i != cnmap.end()) {
1554  assert(i->second.ns);
1555  cns = i->second.ns;
1556  return i->second.obj;
1557  }
1558  return nullptr;
1559  }
1560 
1561  DLLLOCAL void runtimeImportGlobalVariable(qore_ns_private& tns, Var* v, bool readonly, ExceptionSink* xsink) {
1562  Var* var = tns.var_list.import(v, xsink, readonly);
1563  if (!var)
1564  return;
1565 
1566  varmap.update(var->getName(), &tns, var);
1567  }
1568 
1569  DLLLOCAL Var* runtimeCreateVar(qore_ns_private& vns, const char* vname, const QoreTypeInfo* typeInfo,
1570  bool builtin) {
1571  Var* v = vns.var_list.runtimeCreateVar(vname, typeInfo, builtin);
1572 
1573  if (v)
1574  varmap.update(v->getName(), &vns, v);
1575  return v;
1576  }
1577 
1578  DLLLOCAL bool parseResolveGlobalVarsAndClassHierarchiesIntern();
1579 
1580  // returns 0 for success, non-zero for error
1581  DLLLOCAL int parseAddMethodToClassIntern(const QoreProgramLocation* loc, const NamedScope& name,
1582  MethodVariantBase* qcmethod, bool static_flag);
1583 
1584  DLLLOCAL static void rebuildConstantIndexes(cnmap_t& cnmap, ConstantList& cl, qore_ns_private* ns) {
1585  ConstantListIterator cli(cl);
1586  while (cli.next())
1587  cnmap.update(cli.getName().c_str(), ns, cli.getEntry());
1588  }
1589 
1590  DLLLOCAL static void rebuildClassIndexes(clmap_t& clmap, QoreClassList& cl, qore_ns_private* ns) {
1591  ClassListIterator cli(cl);
1592  while (cli.next())
1593  clmap.update(cli.getName(), ns, cli.get());
1594  }
1595 
1596  DLLLOCAL static void rebuildHashDeclIndexes(thdmap_t& thdmap, HashDeclList& hdl, qore_ns_private* ns) {
1597  HashDeclListIterator hdli(hdl);
1598  while (hdli.next())
1599  thdmap.update(hdli.getName(), ns, hdli.get());
1600  }
1601 
1602  DLLLOCAL static void rebuildFunctionIndexes(fmap_t& fmap, fl_map_t& flmap, qore_ns_private* ns) {
1603  for (fl_map_t::iterator i = flmap.begin(), e = flmap.end(); i != e; ++i) {
1604  assert(i->second->getNamespace() == ns);
1605  fmap.update(i->first, i->second);
1606  //printd(5, "qore_root_ns_private::rebuildFunctionIndexes() this: %p ns: %p func %s\n", this, ns,
1607  // i->first);
1608  }
1609  }
1610 
1611  DLLLOCAL void rebuildIndexes(qore_ns_private* ns) {
1612  // process function indexes
1613  rebuildFunctionIndexes(fmap, ns->func_list, ns);
1614 
1615  // process variable indexes
1616  for (map_var_t::iterator i = ns->var_list.vmap.begin(), e = ns->var_list.vmap.end(); i != e; ++i)
1617  varmap.update(i->first, ns, i->second);
1618 
1619  // process constant indexes
1620  rebuildConstantIndexes(cnmap, ns->constant, ns);
1621 
1622  // process class indexes
1623  rebuildClassIndexes(clmap, ns->classList, ns);
1624 
1625  // process hashdecl indexes
1626  rebuildHashDeclIndexes(thdmap, ns->hashDeclList, ns);
1627 
1628  // reindex namespace
1629  nsmap.update(ns);
1630 
1631  // inserts into depth list
1632  nshlist.add(ns);
1633  }
1634 
1635  DLLLOCAL void parseRebuildIndexes(qore_ns_private* ns) {
1636  //printd(5, "qore_root_ns_private::parseRebuildIndexes() this: %p ns: %p (%s) depth %d\n", this, ns,
1637  // ns->name.c_str(), ns->depth);
1638 
1639  // process function indexes
1640  for (fl_map_t::iterator i = ns->func_list.begin(), e = ns->func_list.end(); i != e; ++i) {
1641  assert(i->second->getNamespace() == ns);
1642  pend_fmap.update(i->first, i->second);
1643  }
1644 
1645  // process variable indexes
1646  for (map_var_t::iterator i = ns->var_list.vmap.begin(), e = ns->var_list.vmap.end(); i != e; ++i)
1647  varmap.update(i->first, ns, i->second);
1648 
1649  // process constant indexes
1650  rebuildConstantIndexes(cnmap, ns->constant, ns);
1651 
1652  // process class indexes
1653  rebuildClassIndexes(clmap, ns->classList, ns);
1654 
1655  // process hashdecl indexes
1656  rebuildHashDeclIndexes(thdmap, ns->hashDeclList, ns);
1657 
1658  // reindex namespace
1659  nsmap.update(ns);
1660  }
1661 
1662  DLLLOCAL void parseAddNamespaceIntern(QoreNamespace* nns);
1663 
1664 public:
1665  RootQoreNamespace* rns;
1666  QoreNamespace* qoreNS;
1668 
1670  QoreProgram* pgm = nullptr;
1671 
1672  fmap_t fmap, // root function map
1673  pend_fmap; // root pending function map (only used during parsing)
1674 
1675  cnmap_t cnmap; // root constant map
1676 
1677  clmap_t clmap; // root class map
1678 
1679  thdmap_t thdmap; // root hashdecl map
1680 
1681  varmap_t varmap; // root variable map
1682 
1683  NamespaceMap nsmap; // root namespace map
1684 
1685  NamespaceDepthList nshlist; // root namespace with handler map
1686 
1687  // unresolved pending global variable list - only used in the 1st stage of parsing (data read in to tree)
1688  gvlist_t pend_gvlist;
1689 
1690  DLLLOCAL qore_root_ns_private(RootQoreNamespace* n_rns) : qore_ns_private(n_rns), rns(n_rns), qoreNS(nullptr) {
1691  assert(root);
1692  assert(pub);
1693  // add initial namespace to committed map
1694  nsmap.update(this);
1695  }
1696 
1697  DLLLOCAL qore_root_ns_private(const qore_root_ns_private& old, int64 po, QoreProgram* pgm, RootQoreNamespace* ns)
1698  : qore_ns_private(old, po, ns), pgm(pgm) {
1699  assert(pgm);
1700  if ((po & PO_NO_API) == PO_NO_API) {
1701  // create empty Qore namespace
1702  qoreNS = new QoreNamespace("Qore");
1703  nsl.nsmap.insert(nsmap_t::value_type("Qore", qoreNS));
1704  qoreNS->priv->nsl.nsmap.insert(nsmap_t::value_type("Option", new QoreNamespace("Option")));
1705  } else
1706  qoreNS = nsl.find("Qore");
1707  assert(qoreNS);
1708 
1709  // always set the module public flag to true in the root namespace
1710  pub = true;
1711 
1712  // rebuild root indexes - only for committed objects
1713  rebuildAllIndexes();
1714  }
1715 
1716  DLLLOCAL ~qore_root_ns_private() {
1717  }
1718 
1719  DLLLOCAL RootQoreNamespace* copy(int64 po, QoreProgram* pgm) {
1720  RootQoreNamespace* rv = new RootQoreNamespace(nullptr);
1721  qore_root_ns_private* rpriv = new qore_root_ns_private(*this, po, pgm, rv);
1722  rv->priv = rv->rpriv = rpriv;
1723  rpriv->rns = rv;
1724  return rv;
1725  }
1726 
1727  DLLLOCAL void rebuildAllIndexes() {
1728  // clear depth list
1729  nshlist.clear();
1730 
1731  // rebuild root indexes
1732  QorePrivateNamespaceIterator qpni(this);
1733  while (qpni.next())
1734  rebuildIndexes(qpni.get());
1735  }
1736 
1737  DLLLOCAL void deferParseCheckAbstractNew(const qore_class_private* qc, const QoreProgramLocation* loc) {
1738  deferred_new_check_vec.push_back(deferred_new_check_t(qc, loc));
1739  }
1740 
1741  DLLLOCAL QoreNamespace* runtimeFindNamespace(const NamedScope& name) {
1742  // iterate all namespaces with the initial name and look for the match
1743  NamespaceMapIterator nmi(nsmap, name[0]);
1744  while (nmi.next()) {
1745  const qore_ns_private* rv = nmi.get()->runtimeMatchNamespace(name);
1746  if (rv) {
1747  return const_cast<QoreNamespace*>(rv->ns);
1748  }
1749  }
1750 
1751  return nullptr;
1752  }
1753 
1754  DLLLOCAL QoreNamespace* runtimeFindNamespace(const QoreString& name) {
1755  if (name.bindex("::", 0) != -1) {
1756  NamedScope scope(name.c_str());
1757  return runtimeFindNamespace(scope);
1758  }
1759 
1760  return nsmap.findFirst(name.c_str());
1761  }
1762 
1763  DLLLOCAL const QoreClass* runtimeFindScopedClassWithMethod(const NamedScope& name) const;
1764  DLLLOCAL const QoreClass* runtimeFindScopedClassWithMethodIntern(const NamedScope& name) const;
1765 
1766  /*
1767  DLLLOCAL void deleteClearData(ExceptionSink* xsink) {
1768  }
1769  */
1770 
1771  DLLLOCAL qore_ns_private* getQore() {
1772  return qoreNS->priv;
1773  }
1774 
1775  DLLLOCAL const qore_ns_private* getQore() const {
1776  return qoreNS->priv;
1777  }
1778 
1779  DLLLOCAL QoreHashNode* getGlobalVars() const {
1780  QoreHashNode* rv = new QoreHashNode(autoTypeInfo);
1781  qore_ns_private::getGlobalVars(*rv);
1782  return rv;
1783  }
1784 
1785  DLLLOCAL void commitModule(QoreModuleContext& qmc) {
1786  for (unsigned j = 0; j < qmc.mcnl.size(); ++j) {
1787  ModuleContextNamespaceCommit& mc = qmc.mcnl[j];
1788  mc.parent->addCommitNamespaceIntern(mc.nns);
1789  }
1790 
1791  for (unsigned j = 0; j < qmc.mcfl.size(); ++j) {
1792  ModuleContextFunctionCommit& mc = qmc.mcfl[j];
1793  mc.parent->addBuiltinVariantIntern(mc.name, mc.v);
1794  }
1795 
1796  // issue #3461: must rebuild all indexes here or symbols will appear missing
1797  if (qmc.mcnl.size() || qmc.mcfl.size()) {
1798  rebuildAllIndexes();
1799  }
1800  }
1801 
1802  DLLLOCAL void parseRollback(ExceptionSink* xsink) {
1803  // roll back pending lookup entries
1804  pend_fmap.clear();
1805  cnmap.clear();
1806 
1807  varmap.clear();
1808  nsmap.clear();
1809 
1810  // roll back pending global variables
1811  pend_gvlist.clear();
1812 
1813  clmap.clear();
1814  thdmap.clear();
1815 
1816  // delete any deferred new object checks for classes with abstract members
1817  deferred_new_check_vec.clear();
1818 
1819  qore_ns_private::parseRollback(xsink);
1820  }
1821 
1822  DLLLOCAL TypedHashDecl* parseFindHashDecl(const QoreProgramLocation* loc, const NamedScope& name);
1823 
1824  DLLLOCAL const TypedHashDecl* runtimeFindHashDeclIntern(const NamedScope& name, const qore_ns_private*& ns);
1825 
1826  DLLLOCAL QoreNamespace* runtimeFindCreateNamespacePath(const NamedScope& nspath, bool pub, bool user) {
1827  assert(nspath.size());
1828  bool is_new = false;
1829  QoreNamespace* nns = findCreateNamespacePath(nspath, pub, user, is_new);
1830  if (is_new) // add namespace index
1831  nsmap.update(nns->priv);
1832  return nns;
1833  }
1834 
1835  DLLLOCAL QoreNamespace* runtimeFindCreateNamespacePath(const qore_ns_private& ns, bool user) {
1836  // get a list of namespaces from after the root (not including the root) to the current
1837  nslist_t nsl;
1838  ns.getNsList(nsl);
1839 
1840  printd(5, "qore_root_ns_private::runtimeFindCreateNamespacePath() this: %p ns: '%s'\n", this,
1841  ns.name.c_str());
1842 
1843  bool is_new = false;
1844  QoreNamespace* nns = findCreateNamespacePath(nsl, user, is_new);
1845  assert(ns.name == nns->getName());
1846  if (is_new) // add namespace index
1847  nsmap.update(nns->priv);
1848  return nns;
1849  }
1850 
1851  DLLLOCAL void runtimeRebuildConstantIndexes(qore_ns_private* ns) {
1852  rebuildConstantIndexes(cnmap, ns->constant, ns);
1853  }
1854 
1855  DLLLOCAL void runtimeRebuildClassIndexes(qore_ns_private* ns) {
1856  rebuildClassIndexes(clmap, ns->classList, ns);
1857  }
1858 
1859  DLLLOCAL void runtimeRebuildHashDeclIndexes(qore_ns_private* ns) {
1860  rebuildHashDeclIndexes(thdmap, ns->hashDeclList, ns);
1861  }
1862 
1863  DLLLOCAL void runtimeRebuildFunctionIndexes(qore_ns_private* ns) {
1864  rebuildFunctionIndexes(fmap, ns->func_list, ns);
1865  }
1866 
1867  DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindCall(const char* name, const QoreListNode* params,
1868  ExceptionSink* xsink);
1869 
1870  DLLLOCAL QoreListNode* runtimeFindCallVariants(const char* name, ExceptionSink* xsink);
1871 
1872  DLLLOCAL int parseInit();
1873 
1874  DLLLOCAL class_vec_t runtimeFindAllClassesRegex(const QoreString& pattern, int re_opts,
1875  ExceptionSink* xsink) const;
1876 
1877  DLLLOCAL hashdecl_vec_t runtimeFindAllHashDeclsRegex(const QoreString& pattern, int re_opts,
1878  ExceptionSink* xsink) const;
1879 
1880  DLLLOCAL func_vec_t runtimeFindAllFunctionsRegex(const QoreString& pattern, int re_opts,
1881  ExceptionSink* xsink) const;
1882 
1883  DLLLOCAL ns_vec_t runtimeFindAllNamespacesRegex(const QoreString& pattern, int re_opts,
1884  ExceptionSink* xsink) const;
1885 
1886  DLLLOCAL gvar_vec_t runtimeFindAllGlobalVarsRegex(const QoreString& pattern, int re_opts,
1887  ExceptionSink* xsink) const;
1888 
1889  DLLLOCAL const_vec_t runtimeFindAllNamespaceConstantsRegex(const QoreString& pattern, int re_opts,
1890  ExceptionSink* xsink) const;
1891 
1892  DLLLOCAL static QoreHashNode* getGlobalVars(RootQoreNamespace& rns) {
1893  return rns.rpriv->getGlobalVars();
1894  }
1895 
1896  DLLLOCAL static void runtimeImportSystemClasses(RootQoreNamespace& rns, const RootQoreNamespace& source,
1897  ExceptionSink* xsink) {
1898  rns.priv->runtimeImportSystemClasses(*source.priv, *rns.rpriv, xsink);
1899  }
1900 
1901  DLLLOCAL static void runtimeImportSystemHashDecls(RootQoreNamespace& rns, const RootQoreNamespace& source,
1902  ExceptionSink* xsink) {
1903  rns.priv->runtimeImportSystemHashDecls(*source.priv, *rns.rpriv, xsink);
1904  }
1905 
1906  DLLLOCAL static void runtimeImportSystemConstants(RootQoreNamespace& rns, const RootQoreNamespace& source,
1907  ExceptionSink* xsink) {
1908  rns.priv->runtimeImportSystemConstants(*source.priv, *rns.rpriv, xsink);
1909  }
1910 
1911  DLLLOCAL static void runtimeImportSystemFunctions(RootQoreNamespace& rns, const RootQoreNamespace& source,
1912  ExceptionSink* xsink) {
1913  rns.priv->runtimeImportSystemFunctions(*source.priv, *rns.rpriv, xsink);
1914  }
1915 
1916  DLLLOCAL static QoreNamespace* runtimeFindCreateNamespacePath(const RootQoreNamespace& rns,
1917  const qore_ns_private& ns, bool user) {
1918  return rns.rpriv->runtimeFindCreateNamespacePath(ns, user);
1919  }
1920 
1921  DLLLOCAL static QoreNamespace* runtimeFindCreateNamespacePath(const RootQoreNamespace& rns,
1922  const NamedScope& nspath, bool pub, bool user) {
1923  return rns.rpriv->runtimeFindCreateNamespacePath(nspath, pub, user);
1924  }
1925 
1926  DLLLOCAL static RootQoreNamespace* copy(const RootQoreNamespace& rns, int64 po, QoreProgram* pgm) {
1927  return rns.rpriv->copy(po, pgm);
1928  }
1929 
1930  DLLLOCAL static int addPendingVariant(qore_ns_private& nsp, const char* name, AbstractQoreFunctionVariant* v) {
1931  return getRootNS()->rpriv->addPendingVariantIntern(nsp, name, v);
1932  }
1933 
1934  DLLLOCAL static int addPendingVariant(qore_ns_private& nsp, const NamedScope& name,
1935  AbstractQoreFunctionVariant* v) {
1936  return getRootNS()->rpriv->addPendingVariantIntern(nsp, name, v);
1937  }
1938 
1939  DLLLOCAL static int runtimeImportFunction(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns,
1940  QoreFunction* u, const char* new_name = nullptr, bool inject = false) {
1941  return rns.rpriv->runtimeImportFunction(xsink, *ns.priv, u, new_name, inject);
1942  }
1943 
1944  DLLLOCAL static int runtimeImportClass(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns,
1945  const QoreClass* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = 0, bool inject = false,
1946  const qore_class_private* injectedClass = nullptr) {
1947  return rns.rpriv->runtimeImportClass(xsink, *ns.priv, c, spgm, set_pub, new_name, inject, injectedClass);
1948  }
1949 
1950  DLLLOCAL static int runtimeImportHashDecl(RootQoreNamespace& rns, ExceptionSink* xsink, QoreNamespace& ns,
1951  const TypedHashDecl* c, QoreProgram* spgm, q_setpub_t set_pub, const char* new_name = nullptr) {
1952  return rns.rpriv->runtimeImportHashDecl(xsink, *ns.priv, c, spgm, set_pub, new_name);
1953  }
1954 
1955  DLLLOCAL static const QoreClass* runtimeFindClass(RootQoreNamespace& rns, const char* name,
1956  const qore_ns_private*& ns) {
1957  if (strstr(name, "::")) {
1958  NamedScope nscope(name);
1959  return rns.rpriv->runtimeFindClassIntern(nscope, ns);
1960  }
1961  return rns.rpriv->runtimeFindClassIntern(name, ns);
1962  }
1963 
1964  DLLLOCAL static const TypedHashDecl* runtimeFindHashDecl(RootQoreNamespace& rns, const char* name,
1965  const qore_ns_private*& ns) {
1966  if (strstr(name, "::")) {
1967  NamedScope nscope(name);
1968  return rns.rpriv->runtimeFindHashDeclIntern(nscope, ns);
1969  }
1970  return rns.rpriv->runtimeFindHashDeclIntern(name, ns);
1971  }
1972 
1973  DLLLOCAL static const QoreFunction* runtimeFindFunction(RootQoreNamespace& rns, const char* name,
1974  const qore_ns_private*& ns) {
1975  const FunctionEntry* fe = runtimeFindFunctionEntry(rns, name);
1976  if (fe) {
1977  ns = fe->getNamespace();
1978  return fe->getFunction();
1979  }
1980  return nullptr;
1981  }
1982 
1983  DLLLOCAL static const FunctionEntry* runtimeFindFunctionEntry(RootQoreNamespace& rns, const char* name) {
1984  if (strstr(name, "::")) {
1985  NamedScope nscope(name);
1986  return rns.rpriv->runtimeFindFunctionEntryIntern(nscope);
1987  }
1988  return rns.rpriv->runtimeFindFunctionEntryIntern(name);
1989  }
1990 
1991  DLLLOCAL static bool runtimeExistsFunction(RootQoreNamespace& rns, const char* name) {
1992  return rns.rpriv->runtimeExistsFunctionIntern(name);
1993  }
1994 
1995  DLLLOCAL static void addConstant(qore_root_ns_private& rns, qore_ns_private& ns, const char* cname,
1996  QoreValue value, const QoreTypeInfo* typeInfo) {
1997  rns.addConstant(ns, cname, value, typeInfo);
1998  }
1999 
2000  DLLLOCAL static const QoreFunction* parseResolveFunction(const QoreProgramLocation* loc, const char* fname) {
2001  const FunctionEntry* fe = getRootNS()->rpriv->parseResolveFunctionEntryIntern(loc, fname);
2002  return fe ? fe->getFunction() : nullptr;
2003  }
2004 
2005  DLLLOCAL static const FunctionEntry* parseResolveFunctionEntry(const QoreProgramLocation* loc, const char* fname) {
2006  return getRootNS()->rpriv->parseResolveFunctionEntryIntern(loc, fname);
2007  }
2008 
2009  // called during parsing (plock already grabbed)
2010  DLLLOCAL static AbstractCallReferenceNode* parseResolveCallReference(UnresolvedProgramCallReferenceNode* fr) {
2011  return getRootNS()->rpriv->parseResolveCallReferenceIntern(fr);
2012  }
2013 
2014  DLLLOCAL static bool parseResolveGlobalVarsAndClassHierarchies() {
2015  return getRootNS()->rpriv->parseResolveGlobalVarsAndClassHierarchiesIntern();
2016  }
2017 
2018  DLLLOCAL static void parseCommit(RootQoreNamespace& rns) {
2019  rns.rpriv->parseCommit();
2020  }
2021 
2022  DLLLOCAL static QoreValue parseFindConstantValue(const QoreProgramLocation* loc, const char* name,
2023  const QoreTypeInfo*& typeInfo, bool& found, bool error) {
2024  found = false;
2025  return getRootNS()->rpriv->parseFindConstantValueIntern(loc, name, typeInfo, found, error);
2026  }
2027 
2028  DLLLOCAL static QoreValue parseFindReferencedConstantValue(const QoreProgramLocation* loc, const NamedScope& name,
2029  const QoreTypeInfo*& typeInfo, bool& found, bool error) {
2030  found = false;
2031  return getRootNS()->rpriv->parseFindReferencedConstantValueIntern(loc, name, typeInfo, found, error);
2032  }
2033 
2034  DLLLOCAL static QoreValue parseResolveBareword(const QoreProgramLocation* loc, const char* bword,
2035  const QoreTypeInfo*& typeInfo, bool& found) {
2036  found = false;
2037  return getRootNS()->rpriv->parseResolveBarewordIntern(loc, bword, typeInfo, found);
2038  }
2039 
2040  DLLLOCAL static QoreValue parseResolveReferencedScopedReference(const QoreProgramLocation* loc,
2041  const NamedScope& name, const QoreTypeInfo*& typeInfo, bool& found) {
2042  found = false;
2043  return getRootNS()->rpriv->parseResolveReferencedScopedReferenceIntern(loc, name, typeInfo, found);
2044  }
2045 
2046  DLLLOCAL static QoreClass* parseFindClass(const QoreProgramLocation* loc, const char* name,
2047  bool raise_error = true) {
2048  QoreClass* qc = getRootNS()->rpriv->parseFindClassIntern(name);
2049  if (!qc && raise_error) {
2050  parse_error(*loc, "reference to undefined class '%s'", name);
2051  }
2052  return qc;
2053  }
2054 
2055  DLLLOCAL static QoreClass* parseFindScopedClass(const QoreProgramLocation* loc, const NamedScope& name,
2056  bool raise_error = true) {
2057  return getRootNS()->rpriv->parseFindScopedClassIntern(loc, name, raise_error);
2058  }
2059 
2060  DLLLOCAL static QoreClass* parseFindScopedClassWithMethod(const QoreProgramLocation* loc, const NamedScope& name,
2061  bool error) {
2062  return getRootNS()->rpriv->parseFindScopedClassWithMethodInternError(loc, name, error);
2063  }
2064 
2065  DLLLOCAL static void parseAddConstant(const QoreProgramLocation* loc, QoreNamespace& ns, const NamedScope& name,
2066  QoreValue value, bool pub) {
2067  getRootNS()->rpriv->parseAddConstantIntern(loc, ns, name, value, pub);
2068  }
2069 
2070  // returns 0 for success, non-zero for error
2071  DLLLOCAL static int parseAddMethodToClass(const QoreProgramLocation* loc, const NamedScope& name,
2072  MethodVariantBase* qcmethod, bool static_flag) {
2073  return getRootNS()->rpriv->parseAddMethodToClassIntern(loc, name, qcmethod, static_flag);
2074  }
2075 
2076  DLLLOCAL static void parseAddClass(const QoreProgramLocation* loc, const NamedScope& name, QoreClass* oc) {
2077  getRootNS()->rpriv->parseAddClassIntern(loc, name, oc);
2078  }
2079 
2080  DLLLOCAL static void parseAddHashDecl(const QoreProgramLocation* loc, const NamedScope& name, TypedHashDecl* hd) {
2081  getRootNS()->rpriv->parseAddHashDeclIntern(loc, name, hd);
2082  }
2083 
2084  DLLLOCAL static void parseAddNamespace(QoreNamespace* nns) {
2085  getRootNS()->rpriv->parseAddNamespaceIntern(nns);
2086  }
2087 
2088  DLLLOCAL static const QoreFunction* parseResolveFunction(const NamedScope& nscope) {
2089  const FunctionEntry* fe = getRootNS()->rpriv->parseResolveFunctionEntryIntern(nscope);
2090  return fe ? fe->getFunction() : nullptr;
2091  }
2092 
2093  DLLLOCAL static const FunctionEntry* parseResolveFunctionEntry(const NamedScope& nscope) {
2094  return getRootNS()->rpriv->parseResolveFunctionEntryIntern(nscope);
2095  }
2096 
2097  DLLLOCAL const QoreClass* runtimeFindScopedClass(const NamedScope& name) const;
2098 
2099  DLLLOCAL static ResolvedCallReferenceNode* runtimeGetCallReference(RootQoreNamespace& rns, const char* name,
2100  ExceptionSink* xsink) {
2101  return rns.rpriv->runtimeGetCallReference(name, xsink);
2102  }
2103 
2104  DLLLOCAL static Var* parseAddResolvedGlobalVarDef(const QoreProgramLocation* loc, const NamedScope& vname,
2105  const QoreTypeInfo* typeInfo, qore_var_t type = VT_GLOBAL) {
2106  return getRootNS()->rpriv->parseAddResolvedGlobalVarDefIntern(loc, vname, typeInfo, type);
2107  }
2108 
2109  DLLLOCAL static Var* parseAddGlobalVarDef(const QoreProgramLocation* loc, const NamedScope& vname,
2110  QoreParseTypeInfo* typeInfo, qore_var_t type = VT_GLOBAL) {
2111  return getRootNS()->rpriv->parseAddGlobalVarDefIntern(loc, vname, typeInfo, type);
2112  }
2113 
2114  DLLLOCAL static Var* parseCheckImplicitGlobalVar(const QoreProgramLocation* loc, const NamedScope& name,
2115  const QoreTypeInfo* typeInfo) {
2116  return getRootNS()->rpriv->parseCheckImplicitGlobalVarIntern(loc, name, typeInfo);
2117  }
2118 
2119  DLLLOCAL static Var* parseFindGlobalVar(const char* vname) {
2120  return getRootNS()->rpriv->parseFindGlobalVarIntern(vname);
2121  }
2122 
2123  DLLLOCAL static Var* parseFindGlobalVar(const NamedScope& nscope) {
2124  return getRootNS()->rpriv->parseFindGlobalVarIntern(nscope);
2125  }
2126 
2127  DLLLOCAL static void scanMergeCommittedNamespace(const RootQoreNamespace& ns, const RootQoreNamespace& mns, QoreModuleContext& qmc) {
2128  ns.priv->scanMergeCommittedNamespace(*(mns.priv), qmc);
2129  }
2130 
2131  DLLLOCAL static void copyMergeCommittedNamespace(RootQoreNamespace& ns, const RootQoreNamespace& mns) {
2132  ns.priv->copyMergeCommittedNamespace(*(mns.priv));
2133 
2134  // rebuild root indexes - only for committed objects
2135  ns.rpriv->rebuildAllIndexes();
2136  }
2137 
2138  DLLLOCAL static Var* runtimeFindGlobalVar(const RootQoreNamespace& rns, const char* vname, const qore_ns_private*& vns) {
2139  return rns.rpriv->runtimeFindGlobalVar(vname, vns);
2140  }
2141 
2142  DLLLOCAL static Var* runtimeCreateVar(RootQoreNamespace& rns, QoreNamespace& vns, const char* vname, const QoreTypeInfo* typeInfo, bool builtin = false) {
2143  return rns.rpriv->runtimeCreateVar(*vns.priv, vname, typeInfo, builtin);
2144  }
2145 
2146  DLLLOCAL static void runtimeImportGlobalVariable(RootQoreNamespace& rns, QoreNamespace& tns, Var* v, bool readonly, ExceptionSink* xsink) {
2147  return rns.rpriv->runtimeImportGlobalVariable(*tns.priv, v, readonly, xsink);
2148  }
2149 
2150  /*
2151  DLLLOCAL static void runtimeModuleRebuildIndexes(RootQoreNamespace& rns) {
2152  // rebuild root indexes
2153  QorePrivateNamespaceIterator qpni(rns.priv, true);
2154  while (qpni.next())
2155  rns.rpriv->rebuildIndexes(qpni.get());
2156  }
2157  */
2158 
2159  DLLLOCAL static const QoreClass* runtimeFindClass(RootQoreNamespace& rns, const char* name) {
2160  return rns.rpriv->runtimeFindClass(name);
2161  }
2162 
2163  DLLLOCAL static const ConstantEntry* runtimeFindNamespaceConstant(const RootQoreNamespace& rns, const char* cname, const qore_ns_private*& cns) {
2164  return rns.rpriv->runtimeFindNamespaceConstant(cname, cns);
2165  }
2166 
2167  DLLLOCAL static QoreNamespace* runtimeFindNamespaceForAddFunction(RootQoreNamespace& rns, const NamedScope& name, ExceptionSink* xsink) {
2168  return rns.rpriv->runtimeFindNamespaceForAddFunction(name, xsink);
2169  }
2170 
2171  DLLLOCAL static QoreNamespace* runtimeFindNamespaceForAddClass(RootQoreNamespace& rns, const NamedScope& name, ExceptionSink* xsink) {
2172  return rns.rpriv->runtimeFindNamespaceForAddClass(name, xsink);
2173  }
2174 
2175  DLLLOCAL static qore_root_ns_private* get(RootQoreNamespace& rns) {
2176  return rns.rpriv;
2177  }
2178 
2179  DLLLOCAL static const qore_root_ns_private* get(const RootQoreNamespace& rns) {
2180  return rns.rpriv;
2181  }
2182 
2183  DLLLOCAL static qore_ns_private* getQore(RootQoreNamespace& rns) {
2184  return rns.rpriv->qoreNS->priv;
2185  }
2186 
2187  DLLLOCAL static const qore_ns_private* getQore(const RootQoreNamespace& rns) {
2188  return rns.rpriv->qoreNS->priv;
2189  }
2190 
2191  DLLLOCAL static void clearConstants(RootQoreNamespace& ns, QoreListNode& l) {
2192  ns.priv->clearConstants(l);
2193  ns.rpriv->cnmap.clear();
2194  }
2195 
2196  DLLLOCAL static void clearData(RootQoreNamespace& ns, ExceptionSink* xsink) {
2197  ns.priv->clearData(xsink);
2198  }
2199 };
2200 
2201 #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:239
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