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