Qore Programming Language  1.12.0
Function.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  Function.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_FUNCTION_H
33 
34 #define _QORE_FUNCTION_H
35 
36 #include <cstdio>
37 #include <cstdlib>
38 #include <cstring>
39 #include <string>
40 #include <vector>
41 
42 #include "qore/intern/QoreListNodeEvalOptionalRefHolder.h"
43 
44 class qore_class_private;
45 
46 // these data structures are all private to the library
47 
48 class LocalVar;
49 class VarRefNode;
50 class BCAList;
51 class QoreOperatorNode;
52 class BarewordNode;
53 class QoreFunction;
54 class qore_class_private;
55 class qore_ns_private;
56 
57 typedef std::vector<QoreParseTypeInfo*> ptype_vec_t;
58 typedef std::vector<LocalVar*> lvar_vec_t;
59 
60 class AbstractFunctionSignature {
61 protected:
62  unsigned short num_param_types = 0, // number of parameters that have type information
63  min_param_types = 0; // minimum number of parameters with type info (without default args)
64 
65  const QoreTypeInfo* returnTypeInfo;
66  type_vec_t typeList;
67  arg_vec_t defaultArgList;
68  name_vec_t names;
69 
70  // parameter signature string
71  std::string str;
72 
73 public:
74  DLLLOCAL AbstractFunctionSignature(const QoreTypeInfo* n_returnTypeInfo = nullptr)
75  : returnTypeInfo(n_returnTypeInfo) {
76  }
77 
78  DLLLOCAL AbstractFunctionSignature(const QoreTypeInfo* n_returnTypeInfo, const type_vec_t& n_typeList,
79  const arg_vec_t& n_defaultArgList, const name_vec_t& n_names)
80  : returnTypeInfo(n_returnTypeInfo), typeList(n_typeList), defaultArgList(n_defaultArgList),
81  names(n_names) {
82  }
83 
84  DLLLOCAL virtual ~AbstractFunctionSignature() {
85  // delete all default argument expressions
86  for (arg_vec_t::iterator i = defaultArgList.begin(), e = defaultArgList.end(); i != e; ++i) {
87  (*i).discard(nullptr);
88  }
89  }
90 
91  // called at parse time to include optional type resolution
92  DLLLOCAL const QoreTypeInfo* parseGetReturnTypeInfo() const {
93  int err = 0;
94  return parseGetReturnTypeInfo(err);
95  }
96 
97  // called at parse time to include optional type resolution
98  DLLLOCAL virtual const QoreTypeInfo* parseGetReturnTypeInfo(int& err) const = 0;
99 
100  DLLLOCAL virtual const QoreParseTypeInfo* getParseParamTypeInfo(unsigned num) const = 0;
101 
102  DLLLOCAL const QoreTypeInfo* getReturnTypeInfo() const {
103  return returnTypeInfo;
104  }
105 
106  DLLLOCAL const arg_vec_t& getDefaultArgList() const {
107  return defaultArgList;
108  }
109 
110  DLLLOCAL const type_vec_t& getTypeList() const {
111  return typeList;
112  }
113 
114  DLLLOCAL const name_vec_t& getParamNames() const {
115  return names;
116  }
117 
118  DLLLOCAL QoreValue evalDefaultArg(unsigned i, ExceptionSink* xsink) const {
119  assert(i < defaultArgList.size());
120  return defaultArgList[i].eval(xsink);
121  }
122 
123  DLLLOCAL const char* getSignatureText() const {
124  return str.c_str();
125  }
126 
127  DLLLOCAL virtual void addAbstractParameterSignature(std::string& str) const {
128  for (unsigned i = 0; i < typeList.size(); ++i) {
129  str.append(QoreTypeInfo::getPath(typeList[i]));
130  const char* vname = getName(i);
131  if (vname) {
132  str.append(" ");
133  str.append(vname);
134  }
135  if (hasDefaultArg(i)) {
136  addDefaultArgument(str, defaultArgList[i]);
137  }
138  if (i != typeList.size() - 1) {
139  str.append(", ");
140  }
141  }
142  }
143 
144  DLLLOCAL unsigned numParams() const {
145  return (unsigned)typeList.size();
146  }
147 
148  // number of params with type information
149  DLLLOCAL unsigned getParamTypes() const {
150  return num_param_types;
151  }
152 
153  DLLLOCAL unsigned getMinParamTypes() const {
154  return min_param_types;
155  }
156 
157  DLLLOCAL const QoreTypeInfo* getParamTypeInfo(unsigned num) const {
158  return num >= typeList.size() ? 0 : typeList[num];
159  }
160 
161  DLLLOCAL bool hasDefaultArg(unsigned i) const {
162  return i >= defaultArgList.size() || !defaultArgList[i] ? false : true;
163  }
164 
165  // adds a description of the given default argument to the signature string
166  DLLLOCAL static void addDefaultArgument(std::string& str, QoreValue arg);
167 
168  DLLLOCAL const char* getName(unsigned i) const {
169  return i < names.size() ? names[i].c_str() : 0;
170  }
171 
172  DLLLOCAL bool compare(const AbstractFunctionSignature& sig, bool relaxed_match = false) const;
173 };
174 
175 // used to store return type info during parsing for user code
176 class RetTypeInfo {
177  QoreParseTypeInfo* parseTypeInfo;
178  const QoreTypeInfo* typeInfo;
179 
180 public:
181  DLLLOCAL RetTypeInfo(QoreParseTypeInfo* n_parseTypeInfo, const QoreTypeInfo* n_typeInfo) : parseTypeInfo(n_parseTypeInfo), typeInfo(n_typeInfo) {
182  }
183  DLLLOCAL ~RetTypeInfo() {
184  delete parseTypeInfo;
185  }
186  DLLLOCAL const QoreTypeInfo* getTypeInfo() const {
187  return typeInfo;
188  }
189  DLLLOCAL QoreParseTypeInfo* takeParseTypeInfo() {
190  QoreParseTypeInfo* rv = parseTypeInfo;
191  parseTypeInfo = 0;
192  return rv;
193  }
194 };
195 
196 class UserSignature : public AbstractFunctionSignature {
197 protected:
198  ptype_vec_t parseTypeList;
199  QoreParseTypeInfo* parseReturnTypeInfo;
200 
201  const QoreProgramLocation* loc;
202 
203  DLLLOCAL int pushParam(BarewordNode* b, bool needs_types, bool bare_refs);
204  DLLLOCAL int pushParam(QoreOperatorNode* t, bool needs_types);
205  DLLLOCAL int pushParam(VarRefNode* v, QoreValue defArg, bool needs_types);
206 
207  DLLLOCAL void param_error() {
208  parse_error(*loc, "parameter list contains non-variable reference expressions");
209  }
210 
211 public:
212  lvar_vec_t lv;
213  LocalVar* argvid;
214  LocalVar* selfid;
215  bool resolved;
216  int err = 0;
217 
218  DLLLOCAL UserSignature(int n_first_line, int n_last_line, QoreValue params, RetTypeInfo* retTypeInfo, int64 po);
219 
220  DLLLOCAL virtual ~UserSignature() {
221  for (ptype_vec_t::iterator i = parseTypeList.begin(), e = parseTypeList.end(); i != e; ++i)
222  delete* i;
223  delete parseReturnTypeInfo;
224  }
225 
226  DLLLOCAL void setFirstParamType(const QoreTypeInfo* typeInfo) {
227  assert(!typeList.empty());
228  typeList[0] = typeInfo;
229  }
230 
231  DLLLOCAL void setSelfId(LocalVar* n_selfid) {
232  assert(!selfid);
233  selfid = n_selfid;
234  }
235 
236  DLLLOCAL LocalVar* getSelfId() const {
237  return selfid;
238  }
239 
240  DLLLOCAL virtual const QoreParseTypeInfo* getParseParamTypeInfo(unsigned num) const {
241  return num < parseTypeList.size() ? parseTypeList[num] : nullptr;
242  }
243 
244  // resolves all parse types to the final types
245  DLLLOCAL virtual int resolve();
246 
247  DLLLOCAL virtual void addAbstractParameterSignature(std::string& str) const {
248  if (resolved) {
249  AbstractFunctionSignature::addAbstractParameterSignature(str);
250  return;
251  }
252 
253  for (unsigned i = 0; i < parseTypeList.size(); ++i) {
254  if (!parseTypeList[i] && typeList.size() > i && typeList[i])
255  str.append(QoreTypeInfo::getPath(typeList[i]));
256  else
257  str.append(QoreParseTypeInfo::getName(parseTypeList[i]));
258  if (i != parseTypeList.size() - 1)
259  str.append(",");
260  }
261  }
262 
263  // called at parse time to ensure types are resolved
264  DLLLOCAL virtual const QoreTypeInfo* parseGetReturnTypeInfo(int& err) const {
265  if (const_cast<UserSignature*>(this)->resolve() && !err) {
266  err = -1;
267  }
268  return returnTypeInfo;
269  }
270 
271  DLLLOCAL const QoreProgramLocation* getParseLocation() const {
272  return loc;
273  }
274 
275  DLLLOCAL bool hasReturnTypeInfo() const {
276  return parseReturnTypeInfo || returnTypeInfo;
277  }
278 
279  DLLLOCAL void parseInitPushLocalVars(const QoreTypeInfo* classTypeInfo);
280 
281  // returns the $argv reference count
282  DLLLOCAL void parseInitPopLocalVars();
283 };
284 
285 class AbstractQoreFunctionVariant;
286 
287 class CodeEvaluationHelper : public QoreStackLocation {
288 public:
290 
302  DLLLOCAL CodeEvaluationHelper(ExceptionSink* n_xsink, const QoreFunction* func,
303  const AbstractQoreFunctionVariant*& variant, const char* n_name, const QoreListNode* args = nullptr,
304  QoreObject* self = nullptr, const qore_class_private* n_qc = nullptr, qore_call_t n_ct = CT_UNUSED,
305  bool is_copy = false, const qore_class_private* cctx = nullptr);
306 
308 
321  DLLLOCAL CodeEvaluationHelper(ExceptionSink* n_xsink, const QoreFunction* func,
322  const AbstractQoreFunctionVariant*& variant, const char* n_name, QoreListNode* args,
323  QoreObject* self = nullptr, const qore_class_private* n_qc = nullptr, qore_call_t n_ct = CT_UNUSED,
324  bool is_copy = false, const qore_class_private* cctx = nullptr);
325 
326  DLLLOCAL ~CodeEvaluationHelper();
327 
328  DLLLOCAL void setReturnTypeInfo(const QoreTypeInfo* n_returnTypeInfo) {
329  returnTypeInfo = saveReturnTypeInfo(n_returnTypeInfo);
330  }
331 
332  // once this is set, exception information will be raised in the destructor if an exception has been raised
333  DLLLOCAL void setCallType(qore_call_t n_ct) {
334  ct = n_ct;
335  }
336 
338 
349  DLLLOCAL int processDefaultArgs(const QoreFunction* func, const AbstractQoreFunctionVariant* variant,
350  bool check_args, bool is_copy, QoreObject* self);
351 
352  DLLLOCAL void setArgs(QoreListNode* n_args) {
353  assert(!*tmp);
354  tmp.assign(true, n_args);
355  }
356 
357  DLLLOCAL QoreListNodeEvalOptionalRefHolder& getArgHolder() {
358  return tmp;
359  }
360 
361  DLLLOCAL const QoreListNode* getArgs() const {
362  return *tmp;
363  }
364 
365  // returns the QoreProgram object where the call originated
366  DLLLOCAL QoreProgram* getSourceProgram() const {
367  return pgm;
368  }
369 
370  DLLLOCAL q_rt_flags_t getRuntimeFlags() const {
371  return rtflags;
372  }
373 
374  DLLLOCAL const qore_class_private* getClass() const {
375  return qc;
376  }
377 
379  DLLLOCAL virtual const QoreProgramLocation& getLocation() const {
380  // return loc_builtin for Qore builtin calls
381  return *loc;
382  }
383 
385  DLLLOCAL virtual const std::string& getCallName() const {
386  return callName;
387  }
388 
389  DLLLOCAL virtual qore_call_t getCallType() const {
390  return ct;
391  }
392 
394  DLLLOCAL virtual QoreProgram* getProgram() const {
395  return pgm;
396  }
397 
398  DLLLOCAL virtual const AbstractStatement* getStatement() const {
399  return stmt;
400  }
401 
402 protected:
403  qore_call_t ct;
404  const char* name;
405  ExceptionSink* xsink;
406  // method class
407  const qore_class_private* qc;
408  const QoreProgramLocation* loc;
410  const QoreTypeInfo* returnTypeInfo; // saved return type info
411  QoreProgram* pgm = nullptr; // program used when evaluated (to find stacks for references)
412  const AbstractStatement* stmt = nullptr; // the current statement for the call stack entry
413  q_rt_flags_t rtflags = 0; // runtime flags
414  std::string callName;
415  const QoreStackLocation* stack_loc = nullptr;
416  const QoreProgramLocation* old_runtime_loc = nullptr;
417  bool restore_stack = false;
418 
419  DLLLOCAL void init(const QoreFunction* func, const AbstractQoreFunctionVariant*& variant, bool is_copy,
420  const qore_class_private* cctx, QoreObject* self);
421 
422  DLLLOCAL void setCallName(const QoreFunction* func);
423 };
424 
425 class UserVariantBase;
426 
427 // describes the details of the function variant
428 class AbstractQoreFunctionVariant : protected QoreReferenceCounter {
429 private:
430  // not implemented
431  DLLLOCAL AbstractQoreFunctionVariant(const AbstractQoreFunctionVariant& old) = delete;
432  DLLLOCAL AbstractQoreFunctionVariant& operator=(AbstractQoreFunctionVariant& orig) = delete;
433 
434 protected:
435  // code flags
436  int64 flags;
437  bool is_user;
438 
439  DLLLOCAL virtual ~AbstractQoreFunctionVariant() {}
440 
441 public:
442  DLLLOCAL AbstractQoreFunctionVariant(int64 n_flags, bool n_is_user = false) : flags(n_flags), is_user(n_is_user) {
443  }
444 
445  DLLLOCAL const QoreTypeInfo* parseGetReturnTypeInfo() const {
446  int err = 0;
447  return parseGetReturnTypeInfo(err);
448  }
449 
450  DLLLOCAL virtual AbstractFunctionSignature* getSignature() const = 0;
451  DLLLOCAL virtual const QoreTypeInfo* parseGetReturnTypeInfo(int& err) const = 0;
452 
453  DLLLOCAL const QoreTypeInfo* getReturnTypeInfo() const {
454  return getSignature()->getReturnTypeInfo();
455  }
456 
457  DLLLOCAL unsigned numParams() const {
458  AbstractFunctionSignature* sig = getSignature();
459  return sig ? sig->numParams() : 0;
460  }
461 
462  DLLLOCAL qore_call_t getCallType() const {
463  return is_user ? CT_USER : CT_BUILTIN;
464  }
465 
466  DLLLOCAL int64 getParseOptions(int64 po) const;
467 
468  DLLLOCAL int64 getFlags() const {
469  return flags;
470  }
471 
472  DLLLOCAL virtual int64 getFunctionality() const = 0;
473 
474  // set flag to recheck params against committed variants in stage 2 parsing after type resolution (only for user
475  // variants); should never be called with builtin variants
476  DLLLOCAL virtual void setRecheck() {
477  assert(false);
478  }
479 
480  DLLLOCAL void parseResolveUserSignature();
481 
482  DLLLOCAL virtual UserVariantBase* getUserVariantBase() {
483  return nullptr;
484  }
485 
486  DLLLOCAL const UserVariantBase* getUserVariantBase() const {
487  // avoid the virtual function call if possible
488  return is_user ? const_cast<AbstractQoreFunctionVariant*>(this)->getUserVariantBase() : nullptr;
489  }
490 
491  DLLLOCAL virtual QoreValue evalFunction(const char* name, CodeEvaluationHelper& ceh, ExceptionSink* xsink) const {
492  assert(false);
493  return QoreValue();
494  }
495 
496  DLLLOCAL virtual const QoreClass* getClass() const {
497  return nullptr;
498  }
499 
500  DLLLOCAL const char* className() const {
501  const QoreClass* qc = getClass();
502  return qc ? qc->getName() : nullptr;
503  }
504 
505  DLLLOCAL std::string classPath() const {
506  const QoreClass* qc = getClass();
507  if (!qc) {
508  return std::string();
509  }
510  return qc->getNamespacePath(true);
511  }
512 
513  DLLLOCAL bool isSignatureIdentical(const AbstractFunctionSignature& sig, bool relaxed_match = false) const {
514  //printd(5, "AbstractQoreFunctionVariant::isSignatureIdentical() this: %p '%s' == '%s': %d\n", this,
515  // getSignature()->getSignatureText(), sig.getSignatureText(), *(getSignature()) == sig);
516  return getSignature()->compare(sig, relaxed_match);
517  }
518 
519  // only returns a non-nullptr value for normal user method variants
520  DLLLOCAL LocalVar* getSelfId() const;
521 
522  DLLLOCAL AbstractQoreFunctionVariant* ref() {
523  ROreference();
524  return this;
525  }
526 
527  DLLLOCAL void deref() {
528  if (ROdereference()) {
529  delete this;
530  }
531  }
532 
533  DLLLOCAL bool isUser() const {
534  return is_user;
535  }
536 
537  DLLLOCAL bool hasBody() const;
538 
539  DLLLOCAL virtual bool isModulePublic() const {
540  return false;
541  }
542 
543  // the default implementation of this function does nothing
544  DLLLOCAL virtual int parseInit(QoreFunction* f) {
545  return 0;
546  }
547 
548  // the default implementation of this function does nothing
549  DLLLOCAL virtual void parseCommit() {
550  }
551 };
552 
553 class VRMutex;
554 class UserVariantExecHelper;
555 
556 // base implementation shared between all user variants
557 class UserVariantBase {
558  friend class UserVariantExecHelper;
559 
560 protected:
561  UserSignature signature;
562  StatementBlock* statements;
563  // for "synchronized" functions
564  VRMutex* gate;
565 
566 public:
567  QoreProgram* pgm;
568 
569 protected:
570  // flag to recheck params against committed after type resolution
571  bool recheck;
572  // flag to tell if variant has been initialized or not (still in pending list)
573  bool init;
574 
575  DLLLOCAL QoreValue evalIntern(ReferenceHolder<QoreListNode>& argv, QoreObject* self, ExceptionSink* xsink) const;
576  DLLLOCAL QoreValue eval(const char* name, CodeEvaluationHelper* ceh, QoreObject* self, ExceptionSink* xsink,
577  const qore_class_private* qc = nullptr) const;
578  DLLLOCAL int setupCall(CodeEvaluationHelper* ceh, ReferenceHolder<QoreListNode>& argv, ExceptionSink* xsink) const;
579 
580 public:
581  DLLLOCAL UserVariantBase(StatementBlock* b, int n_sig_first_line, int n_sig_last_line, QoreValue params,
582  RetTypeInfo* rv, bool synced);
583  DLLLOCAL virtual ~UserVariantBase();
584  DLLLOCAL UserSignature* getUserSignature() const {
585  return const_cast<UserSignature*>(&signature);
586  }
587 
588  DLLLOCAL bool isSynchronized() const {
589  return (bool)gate;
590  }
591 
592  DLLLOCAL void setInit() {
593  init = true;
594  }
595 
596  DLLLOCAL bool getInit() const {
597  return init;
598  }
599 
600  DLLLOCAL bool hasBody() const {
601  return (bool)statements;
602  }
603  DLLLOCAL StatementBlock* getStatementBlock() const {
604  return statements;
605  }
606 
607  DLLLOCAL int64 getParseOptions(int64 po) const;
608 
609  DLLLOCAL void parseInitPushLocalVars(const QoreTypeInfo* classTypeInfo);
610 
611  DLLLOCAL void parseInitPopLocalVars();
612 
613  DLLLOCAL void setSelfId(LocalVar* selfid) {
614  signature.setSelfId(selfid);
615  }
616 
617  DLLLOCAL void parseCommit();
618 };
619 
620 // the following defines the pure virtual functions that are common to all user variants
621 #define COMMON_USER_VARIANT_FUNCTIONS DLLLOCAL virtual int64 getFunctionality() const { return QDOM_DEFAULT; } \
622  using AbstractQoreFunctionVariant::getUserVariantBase; \
623  DLLLOCAL virtual UserVariantBase* getUserVariantBase() { return static_cast<UserVariantBase*>(this); } \
624  DLLLOCAL virtual AbstractFunctionSignature* getSignature() const { return const_cast<UserSignature*>(&signature); } \
625  DLLLOCAL virtual const QoreTypeInfo* parseGetReturnTypeInfo(int& err) const { return signature.parseGetReturnTypeInfo(err); } \
626  DLLLOCAL virtual void setRecheck() { recheck = true; } \
627  DLLLOCAL virtual void parseCommit() { UserVariantBase::parseCommit(); }
628 
629 // this class ensures that instantiated variables in user code are uninstantiated, even if an exception occurs
630 class UserVariantExecHelper : ProgramThreadCountContextHelper, ThreadFrameBoundaryHelper {
631 protected:
632  const UserVariantBase* uvb;
634  ExceptionSink* xsink;
635 
636 public:
637  DLLLOCAL UserVariantExecHelper(const UserVariantBase* n_uvb, CodeEvaluationHelper* ceh, ExceptionSink* n_xsink) :
638  ProgramThreadCountContextHelper(n_xsink, n_uvb->pgm, true),
639  ThreadFrameBoundaryHelper(!*n_xsink),
640  uvb(n_uvb), argv(n_xsink), xsink(n_xsink) {
641  assert(xsink);
642  if (*xsink || uvb->setupCall(ceh, argv, xsink))
643  uvb = nullptr;
644  }
645 
646  DLLLOCAL ~UserVariantExecHelper();
647 
648  DLLLOCAL operator bool() const {
649  return uvb;
650  }
651 
652  DLLLOCAL ReferenceHolder<QoreListNode>& getArgv() {
653  return argv;
654  }
655 };
656 
657 class UserFunctionVariant : public AbstractQoreFunctionVariant, public UserVariantBase {
658 protected:
659  bool mod_pub; // is public in module
660 
661  DLLLOCAL virtual ~UserFunctionVariant() {
662  }
663 
664 public:
665  DLLLOCAL UserFunctionVariant(StatementBlock* b, int n_sig_first_line, int n_sig_last_line, QoreValue params, RetTypeInfo* rv, bool synced, int64 n_flags = QCF_NO_FLAGS) :
666  AbstractQoreFunctionVariant(n_flags, true), UserVariantBase(b, n_sig_first_line, n_sig_last_line, params, rv, synced), mod_pub(false) {
667  }
668 
669  // the following defines the virtual functions that are common to all user variants
670  COMMON_USER_VARIANT_FUNCTIONS
671 
672  DLLLOCAL virtual QoreValue evalFunction(const char* name, CodeEvaluationHelper& ceh, ExceptionSink* xsink) const {
673  return eval(name, &ceh, 0, xsink);
674  }
675 
676  DLLLOCAL virtual int parseInit(QoreFunction* f);
677 
678  DLLLOCAL virtual bool isModulePublic() const {
679  return mod_pub;
680  }
681 
682  DLLLOCAL void setModulePublic() {
683  assert(!mod_pub);
684  mod_pub = true;
685  }
686 };
687 
688 #define UFV(f) (reinterpret_cast<UserFunctionVariant*>(f))
689 #define UFV_const(f) (reinterpret_cast<const UserFunctionVariant*>(f))
690 
691 // type for lists of function variants
692 // this type will be read at runtime and could be appended to simultaneously at parse time (under a lock)
693 typedef safe_dslist<AbstractQoreFunctionVariant*> vlist_t;
694 
695 class VList : public vlist_t {
696 public:
697  DLLLOCAL ~VList() {
698  del();
699  }
700  DLLLOCAL void del() {
701  // dereference all variants
702  for (vlist_t::iterator i = begin(), e = end(); i != e; ++i)
703  (*i)->deref();
704  clear();
705  }
706 };
707 
708 // inheritance noce
709 hashdecl INode {
710  QoreFunction* func;
711  ClassAccess access;
712 
713  DLLLOCAL INode(QoreFunction* f, ClassAccess a) : func(f), access(a) {
714  }
715 };
716 
717 // inheritance list type
718 typedef std::vector<INode> ilist_t;
719 
720 hashdecl IList : public ilist_t {
721  DLLLOCAL QoreFunction* getFunction(const qore_class_private* class_ctx, const qore_class_private*& last_class,
722  const_iterator aqfi, bool& internal_access, bool& stop) const;
723 };
724 
725 class QoreFunction : protected QoreReferenceCounter {
726 friend class QoreFunctionIterator;
727 friend class qore_external_function_iterator_private;
728 public:
729  DLLLOCAL QoreFunction(const char* n_name) : name(n_name),
730  same_return_type(true),
731  nn_same_return_type(true),
732  parse_rt_done(true),
733  parse_init_done(true),
734  parse_init_in_progress(false),
735  has_user(false),
736  has_builtin(false),
737  has_pub(false),
738  inject(false),
739  check_parse(false),
740  has_priv(false),
741  all_priv(true) {
742  ilist.push_back(INode(this, Public));
743  //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
744  const char* mod_name = get_module_context_name();
745  if (mod_name) {
746  from_module = mod_name;
747  }
748  }
749 
750  // copy constructor (used by method functions when copied)
751  DLLLOCAL QoreFunction(const QoreFunction& old, int64 po = 0, bool copy_all = false, bool n_inject = false)
752  : name(old.name),
753  unique_functionality(old.unique_functionality),
754  unique_flags(old.unique_flags),
755  nn_unique_functionality(old.nn_unique_functionality),
756  nn_unique_flags(old.nn_unique_flags),
757  nn_count(old.nn_count),
758  same_return_type(old.same_return_type),
759  nn_same_return_type(old.nn_same_return_type),
760  parse_rt_done(true),
761  parse_init_done(true),
762  parse_init_in_progress(false),
763  has_user(old.has_user),
764  has_builtin(old.has_builtin),
765  has_pub(false),
766  inject(n_inject),
767  check_parse(false),
768  has_priv(old.has_priv),
769  all_priv(old.all_priv),
770  nn_uniqueReturnType(old.nn_uniqueReturnType),
771  from_module(old.from_module) {
772  bool no_user = po & PO_NO_INHERIT_USER_FUNC_VARIANTS;
773  bool no_builtin = po & PO_NO_SYSTEM_FUNC_VARIANTS;
774 
775  // copy variants by reference
776  for (vlist_t::const_iterator i = old.vlist.begin(), e = old.vlist.end(); i != e; ++i) {
777  if (!copy_all) {
778  if ((*i)->isUser()) {
779  if (no_user || !(*i)->isModulePublic())
780  continue;
781  }
782  else
783  if (no_builtin)
784  continue;
785  }
786 
787  vlist.push_back((*i)->ref());
788  }
789 
790  if (no_user && has_user)
791  has_user = false;
792  if (no_builtin && has_builtin)
793  has_builtin = false;
794 
795  // make sure the new variant list is not empty if the parent also wasn't
796  assert(old.vlist.empty() || !vlist.empty());
797 
798  assert(!old.ilist.empty());
799  assert(old.ilist.front().func == &old);
800 
801  // resolve initial ilist entry to this function
802  ilist.push_back(INode(this, Public));
803 
804  // the rest of ilist is copied in method base class
805  // do not copy pending variants
806  //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
807  }
808 
809 #if 0
810  // copy constructor when importing public user variants from user modules into Program objects
811  DLLLOCAL QoreFunction(bool ignore, const QoreFunction& old, qore_ns_private* nns)
812  : name(old.name), ns(nns), same_return_type(old.same_return_type),
813  unique_functionality(old.unique_functionality),
814  unique_flags(old.unique_flags),
815  nn_same_return_type(old.nn_same_return_type),
816  nn_unique_functionality(old.nn_unique_functionality),
817  nn_unique_flags(old.nn_unique_flags),
818  nn_count(old.nn_count),
819  parse_rt_done(true), parse_init_done(true),
820  has_user(true), has_builtin(false), has_mod_pub(false /*old.has_mod_pub*/), inject(false),
821  nn_uniqueReturnType(old.nn_uniqueReturnType) {
822  assert(!ignore);
823  assert(old.has_mod_pub);
824 
825  // copy variants by reference
826  for (vlist_t::const_iterator i = old.vlist.begin(), e = old.vlist.end(); i != e; ++i) {
827  if (!(*i)->isModulePublic())
828  continue;
829  vlist.push_back((*i)->ref());
830  }
831 
832  // make sure the new variant list is not empty if the parent also wasn't
833  assert(old.vlist.empty() || !vlist.empty());
834 
835  assert(!old.ilist.empty());
836  assert(old.ilist.front().func == &old);
837 
838  // resolve initial ilist entry to this function
839  ilist.push_back(INode(this, Public));
840 
841  // the rest of ilist is copied in method base class
842  // do not copy pending variants
843  //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
844  }
845 #endif
846 
847  // convenience function for returning the first variant in the list
848  DLLLOCAL const AbstractQoreFunctionVariant* first() const {
849  assert(!vlist.empty());
850  return *(vlist.begin());
851  }
852 
853  // convenience function for returning the first variant in the list
854  DLLLOCAL AbstractQoreFunctionVariant* first() {
855  assert(!vlist.empty());
856  return *(vlist.begin());
857  }
858 
859  DLLLOCAL unsigned numVariants() const {
860  return vlist.size();
861  }
862 
863  DLLLOCAL QoreListNode* runtimeGetCallVariants() const;
864 
865  // returns 0 for OK, -1 for error
866  DLLLOCAL int parseCheckDuplicateSignatureCommitted(UserSignature* sig);
867 
868  DLLLOCAL const char* getName() const {
869  return name.c_str();
870  }
871 
872  DLLLOCAL virtual const QoreClass* getClass() const {
873  return nullptr;
874  }
875 
876  DLLLOCAL void ref() {
877  ROreference();
878  }
879 
880  DLLLOCAL void deref() {
881  if (ROdereference())
882  delete this;
883  }
884 
885  DLLLOCAL const char* className() const {
886  const QoreClass* qc = getClass();
887  return qc ? qc->getName() : nullptr;
888  }
889 
890  DLLLOCAL std::string classPath() const {
891  const QoreClass* qc = getClass();
892  if (!qc) {
893  return std::string();
894  }
895  return qc->getNamespacePath(true);
896  }
897 
898  DLLLOCAL void addAncestor(QoreFunction* ancestor, ClassAccess access) {
899  ilist.push_back(INode(ancestor, access));
900  }
901 
902  DLLLOCAL void addNewAncestor(QoreFunction* ancestor, ClassAccess access) {
903  for (ilist_t::iterator i = ilist.begin(), e = ilist.end(); i != e; ++i)
904  if ((*i).func == ancestor)
905  return;
906  ilist.push_back(INode(ancestor, access));
907  }
908 
909  // resolves all types in signatures and return types in pending variants; called during the "parseInit" phase
910  DLLLOCAL void resolvePendingSignatures();
911 
912  DLLLOCAL AbstractFunctionSignature* getUniqueSignature() const {
913  return vlist.singular() ? first()->getSignature() : 0;
914  }
915 
916  DLLLOCAL AbstractFunctionSignature* parseGetUniqueSignature() const;
917 
918  DLLLOCAL int64 parseGetUniqueFunctionality() const {
919  if (parse_get_parse_options() & PO_REQUIRE_TYPES)
920  return nn_unique_functionality;
921  return unique_functionality;
922  }
923 
924  DLLLOCAL int64 parseGetUniqueFlags() const {
925  if (parse_get_parse_options() & PO_REQUIRE_TYPES)
926  return nn_unique_flags;
927  return unique_flags;
928  }
929 
930  // object takes ownership of variant or deletes it if it can't be added
931  DLLLOCAL int addPendingVariant(AbstractQoreFunctionVariant* variant);
932 
933  DLLLOCAL void addBuiltinVariant(AbstractQoreFunctionVariant* variant);
934 
935  DLLLOCAL int parseInit(qore_ns_private* ns);
936  DLLLOCAL void parseCommit();
937  DLLLOCAL void parseRollback();
938 
939  DLLLOCAL const QoreTypeInfo* getUniqueReturnTypeInfo() const {
940  if (runtime_get_parse_options() & PO_REQUIRE_TYPES)
941  return nn_uniqueReturnType;
942 
943  return same_return_type && !vlist.empty() ? first()->getReturnTypeInfo() : 0;
944  }
945 
946  DLLLOCAL const QoreTypeInfo* parseGetUniqueReturnTypeInfo() {
947  parseCheckReturnType();
948 
949  //printd(5, "QoreFunction::parseGetUniqueReturnTypeInfo() this: %p '%s' rt: %d srt: %d vs: %d\n", this, name.c_str(), parse_get_parse_options() & PO_REQUIRE_TYPES, same_return_type, vlist.size());
950 
951  if (!same_return_type)
952  return nullptr;
953 
954  if (parse_get_parse_options() & PO_REQUIRE_TYPES) {
955  if (!nn_same_return_type)
956  return nullptr;
957 
958  return nn_count ? nn_uniqueReturnType : (!vlist.empty() ? first()->getReturnTypeInfo() : nullptr);
959  }
960 
961  if (!vlist.empty())
962  return first()->getReturnTypeInfo();
963 
964  return nullptr;
965  }
966 
967  // if the variant was identified at parse time, then variant will not be NULL, otherwise if NULL then it is identified at run time
968  DLLLOCAL virtual QoreValue evalFunction(const AbstractQoreFunctionVariant* variant, const QoreListNode* args, QoreProgram* pgm, ExceptionSink* xsink) const;
969 
970  // if the variant was identified at parse time, then variant will not be NULL, otherwise if NULL then it is identified at run time
971  // this function will use destructive evaluation of "args"
972  DLLLOCAL virtual QoreValue evalFunctionTmpArgs(const AbstractQoreFunctionVariant* variant, QoreListNode* args, QoreProgram* pgm, ExceptionSink* xsink) const;
973 
974  // finds a variant and checks variant capabilities against current program parse options and executes the variant
975  DLLLOCAL QoreValue evalDynamic(const QoreListNode* args, ExceptionSink* xsink) const;
976 
977  // find variant at parse time, throw parse exception if no variant can be matched
978  // class_ctx is only for use in a class hierarchy and is only set if there is a current class context and it's
979  // reachable
980  DLLLOCAL const AbstractQoreFunctionVariant* parseFindVariant(const QoreProgramLocation* loc,
981  const type_vec_t& argTypeInfo, const qore_class_private* class_ctx, int& err) const;
982 
983  // returns true if there are no uncommitted parse variants in the function
984  DLLLOCAL bool pendingEmpty() const {
985  return vlist.empty() || !check_parse;
986  }
987 
988  // returns true if there are no committed parse variants in the function
989  DLLLOCAL bool committedEmpty() const {
990  return vlist.empty() || check_parse;
991  }
992 
993  DLLLOCAL bool existsVariant(const type_vec_t& paramTypeInfo) const;
994 
995  // find variant at runtime
996  // class_ctx is only for use in a class hierarchy and is only set if there is a current class context and it's reachable from the object being executed
997  DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindVariant(ExceptionSink* xsink, const QoreListNode* args, bool only_user, const qore_class_private* class_ctx) const;
998 
999  // finds the best match with the given arg types
1000  DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindVariant(ExceptionSink* xsink, const type_vec_t& args, const qore_class_private* class_ctx) const;
1001  // finds only an exact match with the given arg types
1002  DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindExactVariant(ExceptionSink* xsink, const type_vec_t& args, const qore_class_private* class_ctx) const;
1003 
1004  DLLLOCAL void parseAssimilate(QoreFunction& other) {
1005  while (!other.vlist.empty()) {
1006  addPendingVariant(*(other.vlist.begin()));
1007  other.vlist.pop_front();
1008  }
1009  }
1010 
1011  DLLLOCAL bool hasUser() const {
1012  return has_user;
1013  }
1014 
1015  DLLLOCAL bool hasBuiltin() const {
1016  return has_builtin;
1017  }
1018 
1019  DLLLOCAL bool hasPublic() const {
1020  return has_pub;
1021  }
1022 
1023  DLLLOCAL bool hasUserPublic() const {
1024  return has_pub && has_user;
1025  }
1026 
1027  DLLLOCAL bool injected() const {
1028  return inject;
1029  }
1030 
1031  DLLLOCAL bool hasPrivate() const {
1032  return has_priv;
1033  }
1034 
1035  DLLLOCAL bool allPrivate() const {
1036  return all_priv;
1037  }
1038 
1039  DLLLOCAL const std::string& getNameStr() const {
1040  return name;
1041  }
1042 
1043  DLLLOCAL const char* getModuleName() const {
1044  return from_module.empty() ? nullptr : from_module.c_str();
1045  }
1046 
1047 protected:
1048  std::string name;
1049 
1050  // list of function variants
1051  VList vlist;
1052 
1053  // list of inherited methods for variant matching; the first pointer is always a pointer to "this"
1054  IList ilist;
1055 
1056  int64 unique_functionality = QDOM_DEFAULT;
1057  int64 unique_flags = QCF_NO_FLAGS;
1058 
1059  // same as above but for variants without QCF_RUNTIME_NOOP
1060  int64 nn_unique_functionality = QDOM_DEFAULT;
1061  int64 nn_unique_flags = QCF_NO_FLAGS;
1062  int nn_count = 0;
1063 
1064  // if true means all variants have the same return value
1065  bool same_return_type : 1;
1066  bool nn_same_return_type : 1;
1067  bool parse_rt_done : 1;
1068  bool parse_init_done : 1;
1069  bool parse_init_in_progress : 1;
1070  bool has_user : 1; // has at least 1 committed user variant
1071  bool has_builtin : 1; // has at least 1 committed builtin variant
1072  bool has_pub : 1; // has at least 1 committed user variant with public visibility
1073  bool inject : 1;
1074  bool check_parse : 1;
1075  bool has_priv : 1; // has at least 1 private variant
1076  bool all_priv : 1; // all variants are private
1077 
1078  const QoreTypeInfo* nn_uniqueReturnType = nullptr;
1079 
1080  std::string from_module;
1081 
1082  DLLLOCAL int parseCheckReturnType() {
1083  if (parse_rt_done)
1084  return 0;
1085 
1086  parse_rt_done = true;
1087 
1088  if (!same_return_type)
1089  return 0;
1090 
1091 
1092  int err = 0;
1093  for (vlist_t::iterator i = vlist.begin(), e = vlist.end(); i != e; ++i) {
1094  if (reinterpret_cast<UserSignature*>((*i)->getUserVariantBase()->getUserSignature())->resolve() && !err) {
1095  err = -1;
1096  }
1097  const QoreTypeInfo* rti = (*i)->getReturnTypeInfo();
1098 
1099  if (i == vlist.begin()) {
1100  continue;
1101  }
1102 
1103  if (!QoreTypeInfo::isOutputIdentical(rti, first()->getReturnTypeInfo())) {
1104  same_return_type = false;
1105  break;
1106  }
1107  }
1108  //printd(5, "QoreFunction::parseCheckReturnType() '%s' srt: %d\n", name.c_str(), same_return_type);
1109  return err;
1110  }
1111 
1112  // returns QTI_NOT_EQUAL, QTI_AMBIGUOUS, or QTI_IDENT
1113  DLLLOCAL static int parseCompareResolvedSignature(const VList& vlist, const AbstractFunctionSignature* sig,
1114  const AbstractFunctionSignature*& vs);
1115 
1116  // returns 0 for OK (not a duplicate), -1 for error (duplicate) - parse exceptions are raised if a duplicate is found
1117  DLLLOCAL int parseCheckDuplicateSignature(AbstractQoreFunctionVariant* variant);
1118 
1119  // FIXME: does not check unparsed types properly
1120  DLLLOCAL void addVariant(AbstractQoreFunctionVariant* variant) {
1121  const QoreTypeInfo* rti = variant->getReturnTypeInfo();
1122  if (same_return_type && !vlist.empty() && !QoreTypeInfo::isOutputIdentical(rti, first()->getReturnTypeInfo()))
1123  same_return_type = false;
1124 
1125  int64 vf = variant->getFunctionality();
1126  int64 vflags = variant->getFlags();
1127 
1128  bool rtn = (bool)(vflags & QCF_RUNTIME_NOOP);
1129 
1130  if (vlist.empty()) {
1131  unique_functionality = vf;
1132  unique_flags = vflags;
1133  } else {
1134  unique_functionality &= vf;
1135  unique_flags &= vflags;
1136  }
1137 
1138  if (!rtn) {
1139  if (!nn_count) {
1140  nn_unique_functionality = vf;
1141  nn_unique_flags = vflags;
1142  nn_uniqueReturnType = rti;
1143  ++nn_count;
1144  } else {
1145  nn_unique_functionality &= vf;
1146  nn_unique_flags &= vflags;
1147  if (nn_uniqueReturnType && !QoreTypeInfo::isOutputIdentical(rti, nn_uniqueReturnType))
1148  nn_uniqueReturnType = 0;
1149  ++nn_count;
1150  }
1151  }
1152 
1153  vlist.push_back(variant);
1154  }
1155 
1156  DLLLOCAL virtual ~QoreFunction() {
1157  //printd(5, "QoreFunction::~QoreFunction() this: %p %s\n", this, name.c_str());
1158  }
1159 
1160  DLLLOCAL const AbstractQoreFunctionVariant* checkVariant(ExceptionSink* xsink, const type_vec_t& args,
1161  const qore_class_private* class_ctx, const QoreFunction* aqf, const qore_class_private* last_class,
1162  bool internal_access, int64 ppo, const AbstractQoreFunctionVariant* variant) const;
1163 };
1164 
1165 class QoreFunctionIterator {
1166 public:
1167  DLLLOCAL QoreFunctionIterator(const QoreFunction& f) : f(f) {
1168  i = f.vlist.end();
1169  }
1170 
1171  DLLLOCAL bool next() {
1172  if (i == f.vlist.end()) {
1173  i = f.vlist.begin();
1174  }
1175  else {
1176  ++i;
1177  }
1178 
1179  return i != f.vlist.end();
1180  }
1181 
1182  DLLLOCAL const AbstractQoreFunctionVariant* getVariant() const {
1183  return *i;
1184  }
1185 
1186 private:
1187  const QoreFunction& f;
1188  VList::const_iterator i;
1189 };
1190 
1191 class MethodVariantBase;
1192 class MethodFunctionBase;
1193 #define METHFB(f) (reinterpret_cast<MethodFunctionBase*>(f))
1194 #define METHFB_const(f) (reinterpret_cast<const MethodFunctionBase*>(f))
1195 
1196 class MethodFunctionBase : public QoreFunction {
1197 friend hashdecl AbstractMethod;
1198 protected:
1199  const QoreClass* qc;
1200 
1201  // for concrete variants for local abstract variants inherited from base classes
1202  VList pending_save;
1203 
1204  // pointer to copy, only valid during copy
1205  mutable MethodFunctionBase* new_copy = nullptr;
1206 
1207  bool is_static,
1208  has_final = false,
1209  is_abstract = true,
1210  has_private_internal_variants = false;
1211 
1212  ClassAccess access;
1213 
1214  DLLLOCAL int checkFinalVariant(const MethodFunctionBase* m, const MethodVariantBase* v) const;
1215 
1216  DLLLOCAL void replaceAbstractVariantIntern(MethodVariantBase* variant);
1217 
1218 public:
1219  DLLLOCAL MethodFunctionBase(const char* nme, const QoreClass* n_qc, bool n_is_static) : QoreFunction(nme),
1220  qc(n_qc), is_static(n_is_static), has_final(false), access(Internal) {
1221  }
1222 
1223  // copy constructor, only copies committed variants
1224  DLLLOCAL MethodFunctionBase(const MethodFunctionBase& old, const QoreClass* n_qc)
1225  : QoreFunction(old, 0, true),
1226  qc(n_qc),
1227  is_static(old.is_static),
1228  has_final(old.has_final),
1229  is_abstract(old.is_abstract),
1230  has_private_internal_variants(old.has_private_internal_variants),
1231  access(old.access) {
1232  //printd(5, "MethodFunctionBase() copying old=%p -> new=%p %p %s::%s() %p %s::%s()\n",& old, this, old.qc, old.qc->getName(), old.getName(), qc, qc->getName(), old.getName());
1233 
1234  // set a pointer to the new function
1235  old.new_copy = this;
1236 
1237  // copy ilist, will be adjusted for new class pointers after all classes have been copied
1238  ilist.reserve(old.ilist.size());
1239  ilist_t::const_iterator i = old.ilist.begin(), e = old.ilist.end();
1240  ++i;
1241  for (; i != e; ++i) {
1242  ilist.push_back(*i);
1243  }
1244  }
1245 
1246  DLLLOCAL void resolveCopy() {
1247  ilist_t::iterator i = ilist.begin(), e = ilist.end();
1248  ++i;
1249  for (; i != e; ++i) {
1250  MethodFunctionBase* mfb = METHFB((*i).func);
1251 #ifdef DEBUG
1252  if (!mfb->new_copy)
1253  printd(0, "error resolving %p %s::%s() base method %p %s::%s() nas no new method pointer\n", qc, qc->getName(), getName(), mfb->qc, mfb->qc->getName(), getName());
1254  assert(mfb->new_copy);
1255  //printd(5, "resolving %p %s::%s() base method %p %s::%s() from %p -> %p\n", qc, qc->getName(), getName(), mfb->qc, mfb->qc->getName(), getName(), mfb, mfb->new_copy);
1256 #endif
1257  (*i).func = mfb->new_copy;
1258  }
1259  }
1260 
1261  DLLLOCAL int parseInit();
1262  DLLLOCAL void parseCommit();
1263  DLLLOCAL void parseRollback();
1264 
1265  // returns -1 for error, 0 = OK
1266  DLLLOCAL int parseAddUserMethodVariant(MethodVariantBase* variant);
1267 
1268  // maintains access flag and commits the builtin variant
1269  DLLLOCAL void addBuiltinMethodVariant(MethodVariantBase* variant);
1270 
1271  // maintains access flag and commits user variants
1272  DLLLOCAL void parseCommitMethod(QoreString& csig, const char* mod);
1273 
1274  DLLLOCAL void parseCommitMethod();
1275  // processes method signatures
1276  DLLLOCAL void parseSignatures(QoreString& csig, const char* mod) const;
1277 
1278  // if an identical signature is found to the passed variant, then it is removed from the abstract list
1279  DLLLOCAL MethodVariantBase* parseHasVariantWithSignature(MethodVariantBase* v, bool relaxed_match = false) const;
1280 
1281  DLLLOCAL void replaceAbstractVariant(MethodVariantBase* variant);
1282 
1283  DLLLOCAL void parseRollbackMethod();
1284 
1285  DLLLOCAL bool isUniquelyPrivate() const {
1286  return access > Public;
1287  }
1288 
1289  DLLLOCAL bool isAbstract() const {
1290  return is_abstract;
1291  }
1292 
1293  DLLLOCAL ClassAccess getAccess() const {
1294  return access;
1295  }
1296 
1297  DLLLOCAL virtual const QoreClass* getClass() const {
1298  return qc;
1299  }
1300 
1301  DLLLOCAL const char* getClassName() const {
1302  return qc->getName();
1303  }
1304 
1305  DLLLOCAL std::string classPath() const {
1306  if (!qc) {
1307  return std::string();
1308  }
1309  return qc->getNamespacePath(true);
1310  }
1311 
1312  DLLLOCAL bool isStatic() const {
1313  return is_static;
1314  }
1315 
1316  DLLLOCAL bool hasPrivateInternalVariants() const {
1317  return has_private_internal_variants;
1318  }
1319 
1320  DLLLOCAL int checkFinal() const;
1321 
1322  // virtual copy constructor
1323  DLLLOCAL virtual MethodFunctionBase* copy(const QoreClass* n_qc) const = 0;
1324 };
1325 
1326 class UserParamListLocalVarHelper {
1327 protected:
1328  UserVariantBase* uvb;
1329 
1330 public:
1331  DLLLOCAL UserParamListLocalVarHelper(UserVariantBase* n_uvb, const QoreTypeInfo* classTypeInfo = 0) : uvb(n_uvb) {
1332  uvb->parseInitPushLocalVars(classTypeInfo);
1333  }
1334 
1335  DLLLOCAL ~UserParamListLocalVarHelper() {
1336  uvb->parseInitPopLocalVars();
1337  }
1338 };
1339 
1340 class UserClosureVariant : public UserFunctionVariant {
1341 protected:
1342 public:
1343  DLLLOCAL UserClosureVariant(StatementBlock* b, int n_sig_first_line, int n_sig_last_line, QoreValue params, RetTypeInfo* rv, bool synced = false, int64 n_flags = QCF_NO_FLAGS) : UserFunctionVariant(b, n_sig_first_line, n_sig_last_line, params, rv, synced, n_flags) {
1344  }
1345 
1346  DLLLOCAL virtual int parseInit(QoreFunction* f);
1347 
1348  DLLLOCAL QoreValue evalClosure(CodeEvaluationHelper& ceh, QoreObject* self, ExceptionSink* xsink) const {
1349  return eval("<anonymous closure>", &ceh, self, xsink);
1350  }
1351 };
1352 
1353 #define UCLOV(f) (reinterpret_cast<UserClosureVariant*>(f))
1354 #define UCLOV_const(f) (reinterpret_cast<const UserClosureVariant*>(f))
1355 
1356 class UserClosureFunction : public QoreFunction {
1357 protected:
1358  LVarSet varlist; // closure local variable environment
1359  const QoreTypeInfo* classTypeInfo;
1360 
1361 public:
1362  DLLLOCAL UserClosureFunction(StatementBlock* b, int n_sig_first_line, int n_sig_last_line, QoreValue params, RetTypeInfo* rv, bool synced = false, int64 n_flags = QCF_NO_FLAGS) : QoreFunction("<anonymous closure>"), classTypeInfo(0) {
1363  addPendingVariant(new UserClosureVariant(b, n_sig_first_line, n_sig_last_line, params, rv, synced, n_flags));
1364  }
1365 
1366  DLLLOCAL QoreValue evalClosure(const QoreClosureBase& closure_base, QoreProgram* pgm, const QoreListNode* args, QoreObject* self, const qore_class_private* class_ctx, ExceptionSink* xsink) const;
1367 
1368  DLLLOCAL void setClassType(const QoreTypeInfo* cti) {
1369  classTypeInfo = cti;
1370  }
1371 
1372  DLLLOCAL const QoreTypeInfo* getClassType() const {
1373  return classTypeInfo;
1374  }
1375 
1376  DLLLOCAL LVarSet* getVList() {
1377  return &varlist;
1378  }
1379 
1380  // returns true if at least one variable in the set of closure-bound local variables could contain an object or a closure (also through a container)
1381  DLLLOCAL bool needsScan() const {
1382  return varlist.needsScan();
1383  }
1384 };
1385 
1386 #endif // _QORE_FUNCTION_H
#define QDOM_DEFAULT
the default domain (no domain)
Definition: Restrictions.h:159
#define PO_REQUIRE_TYPES
require type information for all declarations
Definition: Restrictions.h:61
#define PO_NO_INHERIT_USER_FUNC_VARIANTS
do not inherit public user function variants from the parent into the new program's space
Definition: Restrictions.h:70
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
defines a Qore-language class
Definition: QoreClass.h:249
DLLEXPORT const char * getName() const
returns the class name
DLLEXPORT std::string getNamespacePath(bool anchored=false) const
returns the full namespace path of the class
For use on the stack only: manages result of the optional evaluation of a QoreListNode.
Definition: QoreListNodeEvalOptionalRefHolder.h:37
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
the implementation of Qore's object data type, reference counted, dynamically-allocated only
Definition: QoreObject.h:60
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:127
provides atomic reference counting to Qore objects
Definition: QoreReferenceCounter.h:44
DLLEXPORT void ROreference() const
atomically increments the reference count
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
Stack location element abstract class.
Definition: ExceptionSink.h:409
virtual DLLLOCAL const QoreProgramLocation & getLocation() const =0
returns the source location of the element
virtual DLLLOCAL const AbstractStatement * getStatement() const =0
returns the statement for the call for internal Qore code
virtual DLLLOCAL const std::string & getCallName() const =0
returns the name of the function or method call
virtual DLLLOCAL QoreProgram * getProgram() const =0
returns the QoreProgram container
virtual DLLLOCAL qore_call_t getCallType() const =0
returns the call type
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
uint64_t q_rt_flags_t
runtime code execution flags
Definition: common.h:263
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
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:275