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