Qore Programming Language  0.9.4.6
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 protected:
689  std::string name;
690 
691  // list of function variants
692  VList vlist;
693 
694  // list of inherited methods for variant matching; the first pointer is always a pointer to "this"
695  IList ilist;
696 
697  // if true means all variants have the same return value
698  int64 unique_functionality = QDOM_DEFAULT;
699  int64 unique_flags = QCF_NO_FLAGS;
700 
701  // same as above but for variants without QCF_RUNTIME_NOOP
702  int64 nn_unique_functionality = QDOM_DEFAULT;
703  int64 nn_unique_flags = QCF_NO_FLAGS;
704  int nn_count = 0;
705 
706  bool same_return_type : 1;
707  bool nn_same_return_type : 1;
708  bool parse_rt_done : 1;
709  bool parse_init_done : 1;
710  bool parse_init_in_progress : 1;
711  bool has_user : 1; // has at least 1 committed user variant
712  bool has_builtin : 1; // has at least 1 committed builtin variant
713  bool has_pub : 1; // has at least 1 committed user variant with public visibility
714  bool inject : 1;
715  bool check_parse : 1;
716  bool has_priv : 1; // has at least 1 private variant
717  bool all_priv : 1; // all variants are private
718 
719  const QoreTypeInfo* nn_uniqueReturnType = nullptr;
720 
721  DLLLOCAL void parseCheckReturnType() {
722  if (parse_rt_done)
723  return;
724 
725  parse_rt_done = true;
726 
727  if (!same_return_type)
728  return;
729 
730  for (vlist_t::iterator i = vlist.begin(), e = vlist.end(); i != e; ++i) {
731  reinterpret_cast<UserSignature*>((*i)->getUserVariantBase()->getUserSignature())->resolve();
732  const QoreTypeInfo* rti = (*i)->getReturnTypeInfo();
733 
734  if (i == vlist.begin()) {
735  continue;
736  }
737 
738  if (!QoreTypeInfo::isOutputIdentical(rti, first()->getReturnTypeInfo())) {
739  same_return_type = false;
740  break;
741  }
742  }
743  //printd(5, "QoreFunction::parseCheckReturnType() '%s' srt: %d\n", name.c_str(), same_return_type);
744  }
745 
746  // returns QTI_NOT_EQUAL, QTI_AMBIGUOUS, or QTI_IDENT
747  DLLLOCAL static int parseCompareResolvedSignature(const VList& vlist, const AbstractFunctionSignature* sig, const AbstractFunctionSignature*& vs);
748 
749  // returns 0 for OK (not a duplicate), -1 for error (duplicate) - parse exceptions are raised if a duplicate is found
750  DLLLOCAL int parseCheckDuplicateSignature(AbstractQoreFunctionVariant* variant);
751 
752  // FIXME: does not check unparsed types properly
753  DLLLOCAL void addVariant(AbstractQoreFunctionVariant* variant) {
754  const QoreTypeInfo* rti = variant->getReturnTypeInfo();
755  if (same_return_type && !vlist.empty() && !QoreTypeInfo::isOutputIdentical(rti, first()->getReturnTypeInfo()))
756  same_return_type = false;
757 
758  int64 vf = variant->getFunctionality();
759  int64 vflags = variant->getFlags();
760 
761  bool rtn = (bool)(vflags & QCF_RUNTIME_NOOP);
762 
763  if (vlist.empty()) {
764  unique_functionality = vf;
765  unique_flags = vflags;
766  }
767  else {
768  unique_functionality &= vf;
769  unique_flags &= vflags;
770  }
771 
772  if (!rtn) {
773  if (!nn_count) {
774  nn_unique_functionality = vf;
775  nn_unique_flags = vflags;
776  nn_uniqueReturnType = rti;
777  ++nn_count;
778  }
779  else {
780  nn_unique_functionality &= vf;
781  nn_unique_flags &= vflags;
782  if (nn_uniqueReturnType && !QoreTypeInfo::isOutputIdentical(rti, nn_uniqueReturnType))
783  nn_uniqueReturnType = 0;
784  ++nn_count;
785  }
786  }
787 
788  vlist.push_back(variant);
789  }
790 
791  DLLLOCAL virtual ~QoreFunction() {
792  //printd(5, "QoreFunction::~QoreFunction() this: %p %s\n", this, name.c_str());
793  }
794 
795  DLLLOCAL const AbstractQoreFunctionVariant* checkVariant(ExceptionSink* xsink, const type_vec_t& args,
796  const qore_class_private* class_ctx, const QoreFunction* aqf, const qore_class_private* last_class,
797  bool internal_access, int64 ppo, const AbstractQoreFunctionVariant* variant) const;
798 
799 public:
800  DLLLOCAL QoreFunction(const char* n_name) : name(n_name),
801  same_return_type(true),
802  nn_same_return_type(true),
803  parse_rt_done(true),
804  parse_init_done(true),
805  parse_init_in_progress(false),
806  has_user(false),
807  has_builtin(false),
808  has_pub(false),
809  inject(false),
810  check_parse(false),
811  has_priv(false),
812  all_priv(true) {
813  ilist.push_back(INode(this, Public));
814  //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
815  }
816 
817  // copy constructor (used by method functions when copied)
818  DLLLOCAL QoreFunction(const QoreFunction& old, int64 po = 0, bool copy_all = false, bool n_inject = false)
819  : name(old.name),
820  unique_functionality(old.unique_functionality),
821  unique_flags(old.unique_flags),
822  nn_unique_functionality(old.nn_unique_functionality),
823  nn_unique_flags(old.nn_unique_flags),
824  nn_count(old.nn_count),
825  same_return_type(old.same_return_type),
826  nn_same_return_type(old.nn_same_return_type),
827  parse_rt_done(true),
828  parse_init_done(true),
829  parse_init_in_progress(false),
830  has_user(old.has_user),
831  has_builtin(old.has_builtin),
832  has_pub(false),
833  inject(n_inject),
834  check_parse(false),
835  has_priv(old.has_priv),
836  all_priv(old.all_priv),
837  nn_uniqueReturnType(old.nn_uniqueReturnType) {
838  bool no_user = po & PO_NO_INHERIT_USER_FUNC_VARIANTS;
839  bool no_builtin = po & PO_NO_SYSTEM_FUNC_VARIANTS;
840 
841  // copy variants by reference
842  for (vlist_t::const_iterator i = old.vlist.begin(), e = old.vlist.end(); i != e; ++i) {
843  if (!copy_all) {
844  if ((*i)->isUser()) {
845  if (no_user || !(*i)->isModulePublic())
846  continue;
847  }
848  else
849  if (no_builtin)
850  continue;
851  }
852 
853  vlist.push_back((*i)->ref());
854  }
855 
856  if (no_user && has_user)
857  has_user = false;
858  if (no_builtin && has_builtin)
859  has_builtin = false;
860 
861  // make sure the new variant list is not empty if the parent also wasn't
862  assert(old.vlist.empty() || !vlist.empty());
863 
864  assert(!old.ilist.empty());
865  assert(old.ilist.front().func == &old);
866 
867  // resolve initial ilist entry to this function
868  ilist.push_back(INode(this, Public));
869 
870  // the rest of ilist is copied in method base class
871  // do not copy pending variants
872  //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
873  }
874 
875 #if 0
876  // copy constructor when importing public user variants from user modules into Program objects
877  DLLLOCAL QoreFunction(bool ignore, const QoreFunction& old, qore_ns_private* nns)
878  : name(old.name), ns(nns), same_return_type(old.same_return_type),
879  unique_functionality(old.unique_functionality),
880  unique_flags(old.unique_flags),
881  nn_same_return_type(old.nn_same_return_type),
882  nn_unique_functionality(old.nn_unique_functionality),
883  nn_unique_flags(old.nn_unique_flags),
884  nn_count(old.nn_count),
885  parse_rt_done(true), parse_init_done(true),
886  has_user(true), has_builtin(false), has_mod_pub(false /*old.has_mod_pub*/), inject(false),
887  nn_uniqueReturnType(old.nn_uniqueReturnType) {
888  assert(!ignore);
889  assert(old.has_mod_pub);
890 
891  // copy variants by reference
892  for (vlist_t::const_iterator i = old.vlist.begin(), e = old.vlist.end(); i != e; ++i) {
893  if (!(*i)->isModulePublic())
894  continue;
895  vlist.push_back((*i)->ref());
896  }
897 
898  // make sure the new variant list is not empty if the parent also wasn't
899  assert(old.vlist.empty() || !vlist.empty());
900 
901  assert(!old.ilist.empty());
902  assert(old.ilist.front().func == &old);
903 
904  // resolve initial ilist entry to this function
905  ilist.push_back(INode(this, Public));
906 
907  // the rest of ilist is copied in method base class
908  // do not copy pending variants
909  //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
910  }
911 #endif
912 
913  // convenience function for returning the first variant in the list
914  DLLLOCAL const AbstractQoreFunctionVariant* first() const {
915  assert(!vlist.empty());
916  return *(vlist.begin());
917  }
918 
919  // convenience function for returning the first variant in the list
920  DLLLOCAL AbstractQoreFunctionVariant* first() {
921  assert(!vlist.empty());
922  return *(vlist.begin());
923  }
924 
925  DLLLOCAL unsigned numVariants() const {
926  return vlist.size();
927  }
928 
929  DLLLOCAL QoreListNode* runtimeGetCallVariants() const;
930 
931  // returns 0 for OK, -1 for error
932  DLLLOCAL int parseCheckDuplicateSignatureCommitted(UserSignature* sig);
933 
934  DLLLOCAL const char* getName() const {
935  return name.c_str();
936  }
937 
938  DLLLOCAL virtual const QoreClass* getClass() const {
939  return nullptr;
940  }
941 
942  DLLLOCAL void ref() {
943  ROreference();
944  }
945 
946  DLLLOCAL void deref() {
947  if (ROdereference())
948  delete this;
949  }
950 
951  DLLLOCAL const char* className() const {
952  const QoreClass* qc = getClass();
953  return qc ? qc->getName() : nullptr;
954  }
955 
956  DLLLOCAL void addAncestor(QoreFunction* ancestor, ClassAccess access) {
957  ilist.push_back(INode(ancestor, access));
958  }
959 
960  DLLLOCAL void addNewAncestor(QoreFunction* ancestor, ClassAccess access) {
961  for (ilist_t::iterator i = ilist.begin(), e = ilist.end(); i != e; ++i)
962  if ((*i).func == ancestor)
963  return;
964  ilist.push_back(INode(ancestor, access));
965  }
966 
967  // resolves all types in signatures and return types in pending variants; called during the "parseInit" phase
968  DLLLOCAL void resolvePendingSignatures();
969 
970  DLLLOCAL AbstractFunctionSignature* getUniqueSignature() const {
971  return vlist.singular() ? first()->getSignature() : 0;
972  }
973 
974  DLLLOCAL AbstractFunctionSignature* parseGetUniqueSignature() const;
975 
976  DLLLOCAL int64 parseGetUniqueFunctionality() const {
977  if (parse_get_parse_options() & PO_REQUIRE_TYPES)
978  return nn_unique_functionality;
979  return unique_functionality;
980  }
981 
982  DLLLOCAL int64 parseGetUniqueFlags() const {
983  if (parse_get_parse_options() & PO_REQUIRE_TYPES)
984  return nn_unique_flags;
985  return unique_flags;
986  }
987 
988  // object takes ownership of variant or deletes it if it can't be added
989  DLLLOCAL int addPendingVariant(AbstractQoreFunctionVariant* variant);
990 
991  DLLLOCAL void addBuiltinVariant(AbstractQoreFunctionVariant* variant);
992 
993  DLLLOCAL void parseInit(qore_ns_private* ns);
994  DLLLOCAL void parseCommit();
995  DLLLOCAL void parseRollback();
996 
997  DLLLOCAL const QoreTypeInfo* getUniqueReturnTypeInfo() const {
998  if (runtime_get_parse_options() & PO_REQUIRE_TYPES)
999  return nn_uniqueReturnType;
1000 
1001  return same_return_type && !vlist.empty() ? first()->getReturnTypeInfo() : 0;
1002  }
1003 
1004  DLLLOCAL const QoreTypeInfo* parseGetUniqueReturnTypeInfo() {
1005  parseCheckReturnType();
1006 
1007  //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());
1008 
1009  if (!same_return_type)
1010  return nullptr;
1011 
1012  if (parse_get_parse_options() & PO_REQUIRE_TYPES) {
1013  if (!nn_same_return_type)
1014  return nullptr;
1015 
1016  return nn_count ? nn_uniqueReturnType : (!vlist.empty() ? first()->getReturnTypeInfo() : nullptr);
1017  }
1018 
1019  if (!vlist.empty())
1020  return first()->getReturnTypeInfo();
1021 
1022  return nullptr;
1023  }
1024 
1025  // if the variant was identified at parse time, then variant will not be NULL, otherwise if NULL then it is identified at run time
1026  DLLLOCAL virtual QoreValue evalFunction(const AbstractQoreFunctionVariant* variant, const QoreListNode* args, QoreProgram* pgm, ExceptionSink* xsink) const;
1027 
1028  // if the variant was identified at parse time, then variant will not be NULL, otherwise if NULL then it is identified at run time
1029  // this function will use destructive evaluation of "args"
1030  DLLLOCAL virtual QoreValue evalFunctionTmpArgs(const AbstractQoreFunctionVariant* variant, QoreListNode* args, QoreProgram* pgm, ExceptionSink* xsink) const;
1031 
1032  // finds a variant and checks variant capabilities against current program parse options and executes the variant
1033  DLLLOCAL QoreValue evalDynamic(const QoreListNode* args, ExceptionSink* xsink) const;
1034 
1035  // find variant at parse time, throw parse exception if no variant can be matched
1036  // 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
1037  DLLLOCAL const AbstractQoreFunctionVariant* parseFindVariant(const QoreProgramLocation* loc, const type_vec_t& argTypeInfo, const qore_class_private* class_ctx) const;
1038 
1039  // returns true if there are no uncommitted parse variants in the function
1040  DLLLOCAL bool pendingEmpty() const {
1041  return vlist.empty() || !check_parse;
1042  }
1043 
1044  // returns true if there are no committed parse variants in the function
1045  DLLLOCAL bool committedEmpty() const {
1046  return vlist.empty() || check_parse;
1047  }
1048 
1049  DLLLOCAL bool existsVariant(const type_vec_t& paramTypeInfo) const;
1050 
1051  // find variant at runtime
1052  // 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
1053  DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindVariant(ExceptionSink* xsink, const QoreListNode* args, bool only_user, const qore_class_private* class_ctx) const;
1054 
1055  // finds the best match with the given arg types
1056  DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindVariant(ExceptionSink* xsink, const type_vec_t& args, const qore_class_private* class_ctx) const;
1057  // finds only an exact match with the given arg types
1058  DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindExactVariant(ExceptionSink* xsink, const type_vec_t& args, const qore_class_private* class_ctx) const;
1059 
1060  DLLLOCAL void parseAssimilate(QoreFunction& other) {
1061  while (!other.vlist.empty()) {
1062  addPendingVariant(*(other.vlist.begin()));
1063  other.vlist.pop_front();
1064  }
1065  }
1066 
1067  DLLLOCAL bool hasUser() const {
1068  return has_user;
1069  }
1070 
1071  DLLLOCAL bool hasBuiltin() const {
1072  return has_builtin;
1073  }
1074 
1075  DLLLOCAL bool hasPublic() const {
1076  return has_pub;
1077  }
1078 
1079  DLLLOCAL bool hasUserPublic() const {
1080  return has_pub && has_user;
1081  }
1082 
1083  DLLLOCAL bool injected() const {
1084  return inject;
1085  }
1086 
1087  DLLLOCAL bool hasPrivate() const {
1088  return has_priv;
1089  }
1090 
1091  DLLLOCAL bool allPrivate() const {
1092  return all_priv;
1093  }
1094 
1095  DLLLOCAL const std::string& getNameStr() const {
1096  return name;
1097  }
1098 };
1099 
1100 class QoreFunctionIterator {
1101 public:
1102  DLLLOCAL QoreFunctionIterator(const QoreFunction& f) : f(f) {
1103  i = f.vlist.end();
1104  }
1105 
1106  DLLLOCAL bool next() {
1107  if (i == f.vlist.end()) {
1108  i = f.vlist.begin();
1109  }
1110  else {
1111  ++i;
1112  }
1113 
1114  return i != f.vlist.end();
1115  }
1116 
1117  DLLLOCAL const AbstractQoreFunctionVariant* getVariant() const {
1118  return *i;
1119  }
1120 
1121 private:
1122  const QoreFunction& f;
1123  VList::const_iterator i;
1124 };
1125 
1126 class MethodVariantBase;
1127 class MethodFunctionBase;
1128 #define METHFB(f) (reinterpret_cast<MethodFunctionBase*>(f))
1129 #define METHFB_const(f) (reinterpret_cast<const MethodFunctionBase*>(f))
1130 
1131 class MethodFunctionBase : public QoreFunction {
1132 friend hashdecl AbstractMethod;
1133 protected:
1134  const QoreClass* qc;
1135 
1136  // for concrete variants for local abstract variants inherited from base classes
1137  VList pending_save;
1138 
1139  // pointer to copy, only valid during copy
1140  mutable MethodFunctionBase* new_copy = nullptr;
1141 
1142  bool is_static,
1143  has_final = false,
1144  is_abstract = true,
1145  has_private_internal_variants = false;
1146 
1147  ClassAccess access;
1148 
1149  DLLLOCAL int checkFinalVariant(const MethodFunctionBase* m, const MethodVariantBase* v) const;
1150 
1151  DLLLOCAL void replaceAbstractVariantIntern(MethodVariantBase* variant);
1152 
1153 public:
1154  DLLLOCAL MethodFunctionBase(const char* nme, const QoreClass* n_qc, bool n_is_static) : QoreFunction(nme),
1155  qc(n_qc), is_static(n_is_static), has_final(false), access(Internal) {
1156  }
1157 
1158  // copy constructor, only copies committed variants
1159  DLLLOCAL MethodFunctionBase(const MethodFunctionBase& old, const QoreClass* n_qc)
1160  : QoreFunction(old, 0, true),
1161  qc(n_qc),
1162  is_static(old.is_static),
1163  has_final(old.has_final),
1164  is_abstract(old.is_abstract),
1165  has_private_internal_variants(old.has_private_internal_variants),
1166  access(old.access) {
1167  //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());
1168 
1169  // set a pointer to the new function
1170  old.new_copy = this;
1171 
1172  // copy ilist, will be adjusted for new class pointers after all classes have been copied
1173  ilist.reserve(old.ilist.size());
1174  ilist_t::const_iterator i = old.ilist.begin(), e = old.ilist.end();
1175  ++i;
1176  for (; i != e; ++i) {
1177  ilist.push_back(*i);
1178  }
1179  }
1180 
1181  DLLLOCAL void resolveCopy() {
1182  ilist_t::iterator i = ilist.begin(), e = ilist.end();
1183  ++i;
1184  for (; i != e; ++i) {
1185  MethodFunctionBase* mfb = METHFB((*i).func);
1186 #ifdef DEBUG
1187  if (!mfb->new_copy)
1188  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());
1189  assert(mfb->new_copy);
1190  //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);
1191 #endif
1192  (*i).func = mfb->new_copy;
1193  }
1194  }
1195 
1196  DLLLOCAL void parseInit();
1197  DLLLOCAL void parseCommit();
1198  DLLLOCAL void parseRollback();
1199 
1200  // returns -1 for error, 0 = OK
1201  DLLLOCAL int parseAddUserMethodVariant(MethodVariantBase* variant);
1202 
1203  // maintains access flag and commits the builtin variant
1204  DLLLOCAL void addBuiltinMethodVariant(MethodVariantBase* variant);
1205 
1206  // maintains access flag and commits user variants
1207  DLLLOCAL void parseCommitMethod(QoreString& csig, const char* mod);
1208 
1209  DLLLOCAL void parseCommitMethod();
1210  // processes method signatures
1211  DLLLOCAL void parseSignatures(QoreString& csig, const char* mod) const;
1212 
1213  // if an identical signature is found to the passed variant, then it is removed from the abstract list
1214  DLLLOCAL MethodVariantBase* parseHasVariantWithSignature(MethodVariantBase* v) const;
1215 
1216  DLLLOCAL void replaceAbstractVariant(MethodVariantBase* variant);
1217 
1218  DLLLOCAL void parseRollbackMethod();
1219 
1220  DLLLOCAL bool isUniquelyPrivate() const {
1221  return access > Public;
1222  }
1223 
1224  DLLLOCAL bool isAbstract() const {
1225  return is_abstract;
1226  }
1227 
1228  DLLLOCAL ClassAccess getAccess() const {
1229  return access;
1230  }
1231 
1232  DLLLOCAL virtual const QoreClass* getClass() const {
1233  return qc;
1234  }
1235 
1236  DLLLOCAL const char* getClassName() const {
1237  return qc->getName();
1238  }
1239 
1240  DLLLOCAL bool isStatic() const {
1241  return is_static;
1242  }
1243 
1244  DLLLOCAL bool hasPrivateInternalVariants() const {
1245  return has_private_internal_variants;
1246  }
1247 
1248  DLLLOCAL void checkFinal() const;
1249 
1250  // virtual copy constructor
1251  DLLLOCAL virtual MethodFunctionBase* copy(const QoreClass* n_qc) const = 0;
1252 };
1253 
1254 class UserParamListLocalVarHelper {
1255 protected:
1256  UserVariantBase* uvb;
1257 
1258 public:
1259  DLLLOCAL UserParamListLocalVarHelper(UserVariantBase* n_uvb, const QoreTypeInfo* classTypeInfo = 0) : uvb(n_uvb) {
1260  uvb->parseInitPushLocalVars(classTypeInfo);
1261  }
1262 
1263  DLLLOCAL ~UserParamListLocalVarHelper() {
1264  uvb->parseInitPopLocalVars();
1265  }
1266 };
1267 
1268 class UserClosureVariant : public UserFunctionVariant {
1269 protected:
1270 public:
1271  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) {
1272  }
1273 
1274  DLLLOCAL virtual void parseInit(QoreFunction* f);
1275 
1276  DLLLOCAL QoreValue evalClosure(CodeEvaluationHelper& ceh, QoreObject* self, ExceptionSink* xsink) const {
1277  return eval("<anonymous closure>", &ceh, self, xsink);
1278  }
1279 };
1280 
1281 #define UCLOV(f) (reinterpret_cast<UserClosureVariant*>(f))
1282 #define UCLOV_const(f) (reinterpret_cast<const UserClosureVariant*>(f))
1283 
1284 class UserClosureFunction : public QoreFunction {
1285 protected:
1286  LVarSet varlist; // closure local variable environment
1287  const QoreTypeInfo* classTypeInfo;
1288 
1289 public:
1290  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) {
1291  addPendingVariant(new UserClosureVariant(b, n_sig_first_line, n_sig_last_line, params, rv, synced, n_flags));
1292  }
1293 
1294  DLLLOCAL QoreValue evalClosure(const QoreClosureBase& closure_base, QoreProgram* pgm, const QoreListNode* args, QoreObject* self, const qore_class_private* class_ctx, ExceptionSink* xsink) const;
1295 
1296  DLLLOCAL void setClassType(const QoreTypeInfo* cti) {
1297  classTypeInfo = cti;
1298  }
1299 
1300  DLLLOCAL const QoreTypeInfo* getClassType() const {
1301  return classTypeInfo;
1302  }
1303 
1304  DLLLOCAL LVarSet* getVList() {
1305  return &varlist;
1306  }
1307 
1308  // 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)
1309  DLLLOCAL bool needsScan() const {
1310  return varlist.needsScan();
1311  }
1312 };
1313 
1314 #endif // _QORE_FUNCTION_H
Stack location element abstract class.
Definition: ExceptionSink.h:396
#define PO_NO_INHERIT_USER_FUNC_VARIANTS
do not inherit public user function variants from the parent into the new program&#39;s space ...
Definition: Restrictions.h:70
uint64_t q_rt_flags_t
runtime code execution flags
Definition: common.h:263
Qore&#39;s string type supported by the QoreEncoding class.
Definition: QoreString.h:81
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
provides atomic reference counting to Qore objects
Definition: QoreReferenceCounter.h:44
defines a Qore-language class
Definition: QoreClass.h:239
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only ...
Definition: QoreProgram.h:126
the implementation of Qore&#39;s object data type, reference counted, dynamically-allocated only ...
Definition: QoreObject.h:61
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:46
std::vector< std::string > name_vec_t
vector of parameter names for parameter lists
Definition: common.h:257
#define PO_REQUIRE_TYPES
require type information for all declarations
Definition: Restrictions.h:61
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
DLLEXPORT QoreValue eval(ExceptionSink *xsink) const
evaluates the node and returns the result
std::vector< const QoreTypeInfo * > type_vec_t
vector of type information for parameter lists
Definition: common.h:251
DLLEXPORT const char * getName() const
returns the class name
For use on the stack only: manages result of the optional evaluation of a QoreListNode.
Definition: QoreListNodeEvalOptionalRefHolder.h:37
#define QDOM_DEFAULT
the default domain (no domain)
Definition: Restrictions.h:155