Qore Programming Language 2.3.0
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 - 2024 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
301#define ARG_DEF (1 << 0)
302#define ARG_OTHER (1 << 1)
303
304class CodeEvaluationHelper : public QoreStackLocation, public ProgramThreadCountContextHelper {
305public:
307
319 DLLLOCAL CodeEvaluationHelper(ExceptionSink* n_xsink, const QoreFunction* func,
320 const AbstractQoreFunctionVariant*& variant, const char* n_name, const QoreListNode* args = nullptr,
321 QoreObject* self = nullptr, const qore_class_private* n_qc = nullptr, qore_call_t n_ct = CT_UNUSED,
322 bool is_copy = false, const qore_class_private* cctx = nullptr, QoreProgram* pgm_ctx = nullptr);
323
325
338 DLLLOCAL CodeEvaluationHelper(ExceptionSink* n_xsink, const QoreFunction* func,
339 const AbstractQoreFunctionVariant*& variant, const char* n_name, QoreListNode* args,
340 QoreObject* self = nullptr, const qore_class_private* n_qc = nullptr, qore_call_t n_ct = CT_UNUSED,
341 bool is_copy = false, const qore_class_private* cctx = nullptr, QoreProgram* pgm_ctx = nullptr);
342
343 DLLLOCAL ~CodeEvaluationHelper();
344
345 DLLLOCAL void setReturnTypeInfo(const QoreTypeInfo* n_returnTypeInfo) {
346 returnTypeInfo = saveReturnTypeInfo(n_returnTypeInfo);
347 }
348
349 // once this is set, exception information will be raised in the destructor if an exception has been raised
350 DLLLOCAL void setCallType(qore_call_t n_ct) {
351 ct = n_ct;
352 }
353
354 DLLLOCAL int prepareDefaultArgs(ExceptionSink* xsink, const AbstractQoreFunctionVariant* variant,
355 AbstractFunctionSignature* sig, bool is_copy, QoreObject* self, int arg_type);
356
358
369 DLLLOCAL int processDefaultArgs(ExceptionSink* xsink, const QoreFunction* func,
370 const AbstractQoreFunctionVariant* variant, AbstractFunctionSignature* sig, bool is_copy,
371 QoreObject* self);
372
373 DLLLOCAL void setArgs(QoreListNode* n_args) {
374 assert(!*tmp);
375 tmp.assign(true, n_args);
376 }
377
378 DLLLOCAL QoreListNodeEvalOptionalRefHolder& getArgHolder() {
379 return tmp;
380 }
381
382 DLLLOCAL const QoreListNode* getArgs() const {
383 return *tmp;
384 }
385
386 // returns the QoreProgram object where the call originated
387 DLLLOCAL QoreProgram* getSourceProgram() const {
388 return pgm;
389 }
390
391 DLLLOCAL q_rt_flags_t getRuntimeFlags() const {
392 return rtflags;
393 }
394
395 DLLLOCAL const qore_class_private* getClass() const {
396 return qc;
397 }
398
400 DLLLOCAL virtual const QoreProgramLocation& getLocation() const {
401 // return loc_builtin for Qore builtin calls
402 return *loc;
403 }
404
406 DLLLOCAL virtual const std::string& getCallName() const {
407 return callName;
408 }
409
410 DLLLOCAL virtual qore_call_t getCallType() const {
411 return ct;
412 }
413
415 DLLLOCAL virtual QoreProgram* getProgram() const {
416 return pgm;
417 }
418
419 DLLLOCAL virtual const AbstractStatement* getStatement() const {
420 return stmt;
421 }
422
424 DLLLOCAL const char* getName() const {
425 return name;
426 }
427
428protected:
429 qore_call_t ct;
430 const char* name;
431 ExceptionSink* xsink;
432 // method class
433 const qore_class_private* qc;
434 const QoreProgramLocation* loc;
436 const QoreTypeInfo* returnTypeInfo; // saved return type info
437 QoreProgram* pgm = nullptr; // program used when evaluated (to find stacks for references)
438 const AbstractStatement* stmt = nullptr; // the current statement for the call stack entry
439 q_rt_flags_t rtflags = 0; // runtime flags
440 std::string callName;
441 const QoreStackLocation* stack_loc = nullptr;
442 const QoreProgramLocation* old_runtime_loc = nullptr;
443 bool restore_stack = false;
444
445 DLLLOCAL void init(const QoreFunction* func, const AbstractQoreFunctionVariant*& variant, bool is_copy,
446 const qore_class_private* cctx, QoreObject* self, QoreProgram* pgm_ctx);
447
448 DLLLOCAL int findVariant(const QoreFunction* func, const AbstractQoreFunctionVariant*& variant,
449 const qore_class_private* cctx);
450
451 DLLLOCAL void setCallName(const QoreFunction* func);
452};
453
454class UserVariantBase;
455
456// describes the details of the function variant
457class AbstractQoreFunctionVariant : protected QoreReferenceCounter {
458public:
459 DLLLOCAL AbstractQoreFunctionVariant(int64 n_flags, bool n_is_user = false) : flags(n_flags), is_user(n_is_user) {
460 }
461
462 DLLLOCAL const QoreTypeInfo* parseGetReturnTypeInfo() const {
463 int err = 0;
464 return parseGetReturnTypeInfo(err);
465 }
466
467 DLLLOCAL virtual AbstractFunctionSignature* getSignature() const = 0;
468 DLLLOCAL virtual const QoreTypeInfo* parseGetReturnTypeInfo(int& err) const = 0;
469
470 DLLLOCAL const QoreTypeInfo* getReturnTypeInfo() const {
471 return getSignature()->getReturnTypeInfo();
472 }
473
474 DLLLOCAL unsigned numParams() const {
475 AbstractFunctionSignature* sig = getSignature();
476 return sig ? sig->numParams() : 0;
477 }
478
479 DLLLOCAL qore_call_t getCallType() const {
480 return is_user ? CT_USER : CT_BUILTIN;
481 }
482
483 DLLLOCAL int64 getParseOptions(int64 po) const;
484
485 DLLLOCAL int64 getFlags() const {
486 return flags;
487 }
488
489 DLLLOCAL virtual int64 getFunctionality() const = 0;
490
491 // set flag to recheck params against committed variants in stage 2 parsing after type resolution (only for user
492 // variants); should never be called with builtin variants
493 DLLLOCAL virtual void setRecheck() {
494 assert(false);
495 }
496
497 DLLLOCAL void parseResolveUserSignature();
498
499 DLLLOCAL virtual UserVariantBase* getUserVariantBase() {
500 return nullptr;
501 }
502
503 DLLLOCAL const UserVariantBase* getUserVariantBase() const {
504 // avoid the virtual function call if possible
505 return is_user ? const_cast<AbstractQoreFunctionVariant*>(this)->getUserVariantBase() : nullptr;
506 }
507
508 DLLLOCAL virtual QoreValue evalFunction(ExceptionSink* xsink, CodeEvaluationHelper& ceh) const {
509 assert(false);
510 return QoreValue();
511 }
512
513 DLLLOCAL virtual const QoreClass* getClass() const {
514 return nullptr;
515 }
516
517 DLLLOCAL const char* className() const {
518 const QoreClass* qc = getClass();
519 return qc ? qc->getName() : nullptr;
520 }
521
522 DLLLOCAL std::string classPath() const {
523 const QoreClass* qc = getClass();
524 if (!qc) {
525 return std::string();
526 }
527 return qc->getNamespacePath(true);
528 }
529
530 DLLLOCAL bool isSignatureIdentical(const AbstractFunctionSignature& sig, bool relaxed_match = false) const {
531 //printd(5, "AbstractQoreFunctionVariant::isSignatureIdentical() this: %p '%s' == '%s': %d\n", this,
532 // getSignature()->getSignatureText(), sig.getSignatureText(), *(getSignature()) == sig);
533 return getSignature()->compare(sig, relaxed_match);
534 }
535
536 // only returns a non-nullptr value for normal user method variants
537 DLLLOCAL LocalVar* getSelfId() const;
538
539 DLLLOCAL AbstractQoreFunctionVariant* ref() {
540 ROreference();
541 return this;
542 }
543
544 DLLLOCAL void deref() {
545 if (ROdereference()) {
546 delete this;
547 }
548 }
549
550 DLLLOCAL bool isUser() const {
551 return is_user;
552 }
553
554 DLLLOCAL bool hasBody() const;
555
556 DLLLOCAL virtual bool isModulePublic() const {
557 return false;
558 }
559
560 // the default implementation of this function does nothing
561 DLLLOCAL virtual int parseInit(QoreFunction* f) {
562 return 0;
563 }
564
565 // the default implementation of this function does nothing
566 DLLLOCAL virtual void parseCommit() {
567 }
568
569 DLLLOCAL virtual bool hasVarargs() const {
570 return flags & QCF_USES_EXTRA_ARGS;
571 }
572
573protected:
574 // code flags
575 int64 flags;
576 bool is_user;
577
578 DLLLOCAL virtual ~AbstractQoreFunctionVariant() {}
579
580private:
581 // not implemented
582 DLLLOCAL AbstractQoreFunctionVariant(const AbstractQoreFunctionVariant& old) = delete;
583 DLLLOCAL AbstractQoreFunctionVariant& operator=(AbstractQoreFunctionVariant& orig) = delete;
584};
585
586class VRMutex;
587class UserVariantExecHelper;
588
589// base implementation shared between all user variants
590class UserVariantBase {
591 friend class UserVariantExecHelper;
592
593protected:
594 UserSignature signature;
595 StatementBlock* statements;
596 // for "synchronized" functions
597 VRMutex* gate;
598
599public:
600 QoreProgram* pgm;
601
602protected:
603 // flag to recheck params against committed after type resolution
604 bool recheck;
605 // flag to tell if variant has been initialized or not (still in pending list)
606 bool init;
607
608 DLLLOCAL QoreValue evalIntern(ReferenceHolder<QoreListNode>& argv, QoreObject* self, ExceptionSink* xsink) const;
609 DLLLOCAL QoreValue eval(const char* name, CodeEvaluationHelper* ceh, QoreObject* self, ExceptionSink* xsink,
610 const qore_class_private* qc = nullptr) const;
611 DLLLOCAL int setupCall(CodeEvaluationHelper* ceh, ReferenceHolder<QoreListNode>& argv, ExceptionSink* xsink)
612 const;
613
614public:
615 DLLLOCAL UserVariantBase(StatementBlock* b, int n_sig_first_line, int n_sig_last_line, QoreValue params,
616 RetTypeInfo* rv, bool synced);
617 DLLLOCAL virtual ~UserVariantBase();
618 DLLLOCAL UserSignature* getUserSignature() const {
619 return const_cast<UserSignature*>(&signature);
620 }
621
622 DLLLOCAL bool isSynchronized() const {
623 return (bool)gate;
624 }
625
626 DLLLOCAL void setInit() {
627 init = true;
628 }
629
630 DLLLOCAL bool getInit() const {
631 return init;
632 }
633
634 DLLLOCAL bool hasBody() const {
635 return (bool)statements;
636 }
637 DLLLOCAL StatementBlock* getStatementBlock() const {
638 return statements;
639 }
640
641 DLLLOCAL int64 getParseOptions(int64 po) const;
642
643 DLLLOCAL void parseInitPushLocalVars(const QoreTypeInfo* classTypeInfo);
644
645 DLLLOCAL void parseInitPopLocalVars();
646
647 DLLLOCAL void setSelfId(LocalVar* selfid) {
648 signature.setSelfId(selfid);
649 }
650
651 DLLLOCAL void parseCommit();
652};
653
654// the following defines the pure virtual functions that are common to all user variants
655#define COMMON_USER_VARIANT_FUNCTIONS DLLLOCAL virtual int64 getFunctionality() const {\
656 const QoreClass* cls = getClass(); return QDOM_DEFAULT | (cls ? cls->getDomain() : 0);\
657 }\
658 using AbstractQoreFunctionVariant::getUserVariantBase; \
659 DLLLOCAL virtual UserVariantBase* getUserVariantBase() { return static_cast<UserVariantBase*>(this); } \
660 DLLLOCAL virtual AbstractFunctionSignature* getSignature() const { return const_cast<UserSignature*>(&signature); } \
661 DLLLOCAL virtual const QoreTypeInfo* parseGetReturnTypeInfo(int& err) const { return signature.parseGetReturnTypeInfo(err); } \
662 DLLLOCAL virtual void setRecheck() { recheck = true; } \
663 DLLLOCAL virtual void parseCommit() { UserVariantBase::parseCommit(); } \
664 DLLLOCAL virtual bool hasVarargs() const { if (signature.hasVarargs()) return true; return AbstractQoreFunctionVariant::hasVarargs(); }
665
666// this class ensures that instantiated variables in user code are uninstantiated, even if an exception occurs
667class UserVariantExecHelper : ProgramThreadCountContextHelper, ThreadFrameBoundaryHelper {
668protected:
669 const UserVariantBase* uvb;
671 ExceptionSink* xsink;
672
673public:
674 DLLLOCAL UserVariantExecHelper(const UserVariantBase* n_uvb, CodeEvaluationHelper* ceh, ExceptionSink* n_xsink) :
675 ProgramThreadCountContextHelper(n_xsink, n_uvb->pgm, true),
676 ThreadFrameBoundaryHelper(!*n_xsink),
677 uvb(n_uvb), argv(n_xsink), xsink(n_xsink) {
678 assert(xsink);
679 if (*xsink || uvb->setupCall(ceh, argv, xsink))
680 uvb = nullptr;
681 }
682
683 DLLLOCAL ~UserVariantExecHelper();
684
685 DLLLOCAL operator bool() const {
686 return uvb;
687 }
688
689 DLLLOCAL ReferenceHolder<QoreListNode>& getArgv() {
690 return argv;
691 }
692};
693
694class UserFunctionVariant : public AbstractQoreFunctionVariant, public UserVariantBase {
695protected:
696 bool mod_pub; // is public in module
697
698 DLLLOCAL virtual ~UserFunctionVariant() {
699 }
700
701public:
702 DLLLOCAL UserFunctionVariant(StatementBlock* b, int n_sig_first_line, int n_sig_last_line, QoreValue params,
703 RetTypeInfo* rv, bool synced, int64 n_flags = QCF_NO_FLAGS) :
704 AbstractQoreFunctionVariant(n_flags, true),
705 UserVariantBase(b, n_sig_first_line, n_sig_last_line, params, rv, synced), mod_pub(false) {
706 if (signature.hasVarargs()) {
707 flags |= QCF_USES_EXTRA_ARGS;
708 }
709 }
710
711 // the following defines the virtual functions that are common to all user variants
712 COMMON_USER_VARIANT_FUNCTIONS
713
714 DLLLOCAL virtual QoreValue evalFunction(ExceptionSink* xsink, CodeEvaluationHelper& ceh) const {
715 return eval(ceh.getName(), &ceh, nullptr, xsink);
716 }
717
718 DLLLOCAL virtual int parseInit(QoreFunction* f);
719
720 DLLLOCAL virtual bool isModulePublic() const {
721 return mod_pub;
722 }
723
724 DLLLOCAL void setModulePublic() {
725 assert(!mod_pub);
726 mod_pub = true;
727 }
728};
729
730#define UFV(f) (reinterpret_cast<UserFunctionVariant*>(f))
731#define UFV_const(f) (reinterpret_cast<const UserFunctionVariant*>(f))
732
733// type for lists of function variants
734// this type will be read at runtime and could be appended to simultaneously at parse time (under a lock)
735typedef safe_dslist<AbstractQoreFunctionVariant*> vlist_t;
736
737class VList : public vlist_t {
738public:
739 DLLLOCAL ~VList() {
740 del();
741 }
742 DLLLOCAL void del() {
743 // dereference all variants
744 for (vlist_t::iterator i = begin(), e = end(); i != e; ++i)
745 (*i)->deref();
746 clear();
747 }
748};
749
750// inheritance noce
751hashdecl INode {
752 QoreFunction* func;
753 ClassAccess access;
754
755 DLLLOCAL INode(QoreFunction* f, ClassAccess a) : func(f), access(a) {
756 }
757};
758
759// inheritance list type
760typedef std::vector<INode> ilist_t;
761
762hashdecl IList : public ilist_t {
763 DLLLOCAL QoreFunction* getFunction(const qore_class_private* class_ctx, const qore_class_private*& last_class,
764 const_iterator aqfi, bool& internal_access, bool& stop) const;
765};
766
767class QoreFunction : protected QoreReferenceCounter {
768friend class QoreFunctionIterator;
769friend class qore_external_function_iterator_private;
770public:
771 DLLLOCAL QoreFunction(const char* n_name) : name(n_name),
772 same_return_type(true),
773 nn_same_return_type(true),
774 parse_rt_done(true),
775 parse_init_done(true),
776 parse_init_in_progress(false),
777 has_user(false),
778 has_builtin(false),
779 has_pub(false),
780 inject(false),
781 check_parse(false),
782 has_priv(false),
783 all_priv(true) {
784 ilist.push_back(INode(this, Public));
785 //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
786 const char* mod_name = get_module_context_name();
787 if (mod_name) {
788 from_module = mod_name;
789 }
790 }
791
792 // copy constructor (used by method functions when copied)
793 DLLLOCAL QoreFunction(const QoreFunction& old, int64 po = 0, bool copy_all = false, bool n_inject = false)
794 : name(old.name),
795 unique_functionality(old.unique_functionality),
796 unique_flags(old.unique_flags),
797 nn_unique_functionality(old.nn_unique_functionality),
798 nn_unique_flags(old.nn_unique_flags),
799 nn_count(old.nn_count),
800 same_return_type(old.same_return_type),
801 nn_same_return_type(old.nn_same_return_type),
802 parse_rt_done(true),
803 parse_init_done(true),
804 parse_init_in_progress(false),
805 has_user(old.has_user),
806 has_builtin(old.has_builtin),
807 has_pub(false),
808 inject(n_inject),
809 check_parse(false),
810 has_priv(old.has_priv),
811 all_priv(old.all_priv),
812 nn_uniqueReturnType(old.nn_uniqueReturnType),
813 from_module(old.from_module) {
814 bool no_user = po & PO_NO_INHERIT_USER_FUNC_VARIANTS;
815 bool no_builtin = po & PO_NO_SYSTEM_FUNC_VARIANTS;
816
817 // copy variants by reference
818 for (vlist_t::const_iterator i = old.vlist.begin(), e = old.vlist.end(); i != e; ++i) {
819 if (!copy_all) {
820 if ((*i)->isUser()) {
821 if (no_user || !(*i)->isModulePublic()) {
822 continue;
823 }
824 } else {
825 if (no_builtin) {
826 continue;
827 }
828 }
829 }
830
831 vlist.push_back((*i)->ref());
832 }
833
834 if (no_user && has_user) {
835 has_user = false;
836 }
837 if (no_builtin && has_builtin) {
838 has_builtin = false;
839 }
840
841 // make sure the new variant list is not empty if the parent also wasn't
842 assert(old.vlist.empty() || !vlist.empty());
843
844 assert(!old.ilist.empty());
845 assert(old.ilist.front().func == &old);
846
847 // resolve initial ilist entry to this function
848 ilist.push_back(INode(this, Public));
849
850 // the rest of ilist is copied in method base class
851 // do not copy pending variants
852 //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
853 }
854
855#if 0
856 // copy constructor when importing public user variants from user modules into Program objects
857 DLLLOCAL QoreFunction(bool ignore, const QoreFunction& old, qore_ns_private* nns)
858 : name(old.name), ns(nns), same_return_type(old.same_return_type),
859 unique_functionality(old.unique_functionality),
860 unique_flags(old.unique_flags),
861 nn_same_return_type(old.nn_same_return_type),
862 nn_unique_functionality(old.nn_unique_functionality),
863 nn_unique_flags(old.nn_unique_flags),
864 nn_count(old.nn_count),
865 parse_rt_done(true), parse_init_done(true),
866 has_user(true), has_builtin(false), has_mod_pub(false /*old.has_mod_pub*/), inject(false),
867 nn_uniqueReturnType(old.nn_uniqueReturnType) {
868 assert(!ignore);
869 assert(old.has_mod_pub);
870
871 // copy variants by reference
872 for (vlist_t::const_iterator i = old.vlist.begin(), e = old.vlist.end(); i != e; ++i) {
873 if (!(*i)->isModulePublic())
874 continue;
875 vlist.push_back((*i)->ref());
876 }
877
878 // make sure the new variant list is not empty if the parent also wasn't
879 assert(old.vlist.empty() || !vlist.empty());
880
881 assert(!old.ilist.empty());
882 assert(old.ilist.front().func == &old);
883
884 // resolve initial ilist entry to this function
885 ilist.push_back(INode(this, Public));
886
887 // the rest of ilist is copied in method base class
888 // do not copy pending variants
889 //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
890 }
891#endif
892
893 // convenience function for returning the first variant in the list
894 DLLLOCAL const AbstractQoreFunctionVariant* first() const {
895 assert(!vlist.empty());
896 return *(vlist.begin());
897 }
898
899 // convenience function for returning the first variant in the list
900 DLLLOCAL AbstractQoreFunctionVariant* first() {
901 assert(!vlist.empty());
902 return *(vlist.begin());
903 }
904
905 DLLLOCAL unsigned numVariants() const {
906 return vlist.size();
907 }
908
909 DLLLOCAL QoreListNode* runtimeGetCallVariants() const;
910
911 // returns 0 for OK, -1 for error
912 DLLLOCAL int parseCheckDuplicateSignatureCommitted(UserSignature* sig);
913
914 DLLLOCAL const char* getName() const {
915 return name.c_str();
916 }
917
918 DLLLOCAL virtual const QoreClass* getClass() const {
919 return nullptr;
920 }
921
922 DLLLOCAL void ref() {
923 ROreference();
924 }
925
926 DLLLOCAL void deref() {
927 if (ROdereference())
928 delete this;
929 }
930
931 DLLLOCAL const char* className() const {
932 const QoreClass* qc = getClass();
933 return qc ? qc->getName() : nullptr;
934 }
935
936 DLLLOCAL std::string classPath() const {
937 const QoreClass* qc = getClass();
938 if (!qc) {
939 return std::string();
940 }
941 return qc->getNamespacePath(true);
942 }
943
944 DLLLOCAL void addAncestor(QoreFunction* ancestor, ClassAccess access) {
945 ilist.push_back(INode(ancestor, access));
946 }
947
948 DLLLOCAL void addNewAncestor(QoreFunction* ancestor, ClassAccess access) {
949 for (ilist_t::iterator i = ilist.begin(), e = ilist.end(); i != e; ++i)
950 if ((*i).func == ancestor)
951 return;
952 ilist.push_back(INode(ancestor, access));
953 }
954
955 // resolves all types in signatures and return types in pending variants; called during the "parseInit" phase
956 DLLLOCAL void resolvePendingSignatures();
957
958 DLLLOCAL AbstractFunctionSignature* getUniqueSignature() const {
959 return vlist.singular() ? first()->getSignature() : 0;
960 }
961
962 DLLLOCAL AbstractFunctionSignature* parseGetUniqueSignature() const;
963
964 DLLLOCAL int64 parseGetUniqueFunctionality() const {
965 if (parse_get_parse_options() & PO_REQUIRE_TYPES)
966 return nn_unique_functionality;
967 return unique_functionality;
968 }
969
970 DLLLOCAL int64 parseGetUniqueFlags() const {
971 if (parse_get_parse_options() & PO_REQUIRE_TYPES)
972 return nn_unique_flags;
973 return unique_flags;
974 }
975
976 // object takes ownership of variant or deletes it if it can't be added
977 DLLLOCAL int addPendingVariant(AbstractQoreFunctionVariant* variant);
978
979 DLLLOCAL void addBuiltinVariant(AbstractQoreFunctionVariant* variant);
980
981 DLLLOCAL int parseInit(qore_ns_private* ns);
982 DLLLOCAL void parseCommit();
983 DLLLOCAL void parseRollback();
984
985 DLLLOCAL const QoreTypeInfo* getUniqueReturnTypeInfo() const {
986 if (runtime_get_parse_options() & PO_REQUIRE_TYPES)
987 return nn_uniqueReturnType;
988
989 return same_return_type && !vlist.empty() ? first()->getReturnTypeInfo() : 0;
990 }
991
992 DLLLOCAL const QoreTypeInfo* parseGetUniqueReturnTypeInfo() {
993 parseCheckReturnType();
994
995 //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());
996
997 if (!same_return_type)
998 return nullptr;
999
1000 if (parse_get_parse_options() & PO_REQUIRE_TYPES) {
1001 if (!nn_same_return_type)
1002 return nullptr;
1003
1004 return nn_count ? nn_uniqueReturnType : (!vlist.empty() ? first()->getReturnTypeInfo() : nullptr);
1005 }
1006
1007 if (!vlist.empty())
1008 return first()->getReturnTypeInfo();
1009
1010 return nullptr;
1011 }
1012
1013 // if the variant was identified at parse time, then variant will not be NULL, otherwise if NULL then it is identified at run time
1014 DLLLOCAL virtual QoreValue evalFunction(const AbstractQoreFunctionVariant* variant, const QoreListNode* args,
1015 QoreProgram* pgm, ExceptionSink* xsink) const;
1016
1017 // if the variant was identified at parse time, then variant will not be NULL, otherwise if NULL then it is identified at run time
1018 // this function will use destructive evaluation of "args"
1019 DLLLOCAL virtual QoreValue evalFunctionTmpArgs(const AbstractQoreFunctionVariant* variant, QoreListNode* args,
1020 QoreProgram* pgm, ExceptionSink* xsink) const;
1021
1022 // finds a variant and checks variant capabilities against current program parse options and executes the variant
1023 DLLLOCAL QoreValue evalDynamic(const QoreListNode* args, ExceptionSink* xsink) const;
1024
1025 // find variant at parse time, throw parse exception if no variant can be matched
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
1027 // reachable
1028 DLLLOCAL const AbstractQoreFunctionVariant* parseFindVariant(const QoreProgramLocation* loc,
1029 const type_vec_t& argTypeInfo, const qore_class_private* class_ctx, int& err) const;
1030
1031 // returns true if there are no uncommitted parse variants in the function
1032 DLLLOCAL bool pendingEmpty() const {
1033 return vlist.empty() || !check_parse;
1034 }
1035
1036 // returns true if there are no committed parse variants in the function
1037 DLLLOCAL bool committedEmpty() const {
1038 return vlist.empty() || check_parse;
1039 }
1040
1041 DLLLOCAL bool existsVariant(const type_vec_t& paramTypeInfo) const;
1042
1043 // find variant at runtime
1044 // 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
1045 DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindVariant(ExceptionSink* xsink, const QoreListNode* args, bool only_user, const qore_class_private* class_ctx) const;
1046
1047 // finds the best match with the given arg types
1048 DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindVariant(ExceptionSink* xsink, const type_vec_t& args, const qore_class_private* class_ctx) const;
1049 // finds only an exact match with the given arg types
1050 DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindExactVariant(ExceptionSink* xsink, const type_vec_t& args, const qore_class_private* class_ctx) const;
1051
1052 DLLLOCAL void parseAssimilate(QoreFunction& other) {
1053 while (!other.vlist.empty()) {
1054 addPendingVariant(*(other.vlist.begin()));
1055 other.vlist.pop_front();
1056 }
1057 }
1058
1059 DLLLOCAL bool hasUser() const {
1060 return has_user;
1061 }
1062
1063 DLLLOCAL bool hasBuiltin() const {
1064 return has_builtin;
1065 }
1066
1067 DLLLOCAL bool hasPublic() const {
1068 return has_pub;
1069 }
1070
1071 DLLLOCAL bool hasUserPublic() const {
1072 return has_pub && has_user;
1073 }
1074
1075 DLLLOCAL bool injected() const {
1076 return inject;
1077 }
1078
1079 DLLLOCAL bool hasPrivate() const {
1080 return has_priv;
1081 }
1082
1083 DLLLOCAL bool allPrivate() const {
1084 return all_priv;
1085 }
1086
1087 DLLLOCAL const std::string& getNameStr() const {
1088 return name;
1089 }
1090
1091 DLLLOCAL const char* getModuleName() const {
1092 return from_module.empty() ? nullptr : from_module.c_str();
1093 }
1094
1095protected:
1096 std::string name;
1097
1098 // list of function variants
1099 VList vlist;
1100
1101 // list of inherited methods for variant matching; the first pointer is always a pointer to "this"
1102 IList ilist;
1103
1104 int64 unique_functionality = QDOM_DEFAULT;
1105 int64 unique_flags = QCF_NO_FLAGS;
1106
1107 // same as above but for variants without QCF_RUNTIME_NOOP
1108 int64 nn_unique_functionality = QDOM_DEFAULT;
1109 int64 nn_unique_flags = QCF_NO_FLAGS;
1110 int nn_count = 0;
1111
1112 // if true means all variants have the same return value
1113 bool same_return_type : 1;
1114 bool nn_same_return_type : 1;
1115 bool parse_rt_done : 1;
1116 bool parse_init_done : 1;
1117 bool parse_init_in_progress : 1;
1118 bool has_user : 1; // has at least 1 committed user variant
1119 bool has_builtin : 1; // has at least 1 committed builtin variant
1120 bool has_pub : 1; // has at least 1 committed user variant with public visibility
1121 bool inject : 1;
1122 bool check_parse : 1;
1123 bool has_priv : 1; // has at least 1 private variant
1124 bool all_priv : 1; // all variants are private
1125
1126 const QoreTypeInfo* nn_uniqueReturnType = nullptr;
1127
1128 std::string from_module;
1129
1130 DLLLOCAL int parseCheckReturnType() {
1131 if (parse_rt_done)
1132 return 0;
1133
1134 parse_rt_done = true;
1135
1136 if (!same_return_type)
1137 return 0;
1138
1139
1140 int err = 0;
1141 for (vlist_t::iterator i = vlist.begin(), e = vlist.end(); i != e; ++i) {
1142 if (reinterpret_cast<UserSignature*>((*i)->getUserVariantBase()->getUserSignature())->resolve() && !err) {
1143 err = -1;
1144 }
1145 const QoreTypeInfo* rti = (*i)->getReturnTypeInfo();
1146
1147 if (i == vlist.begin()) {
1148 continue;
1149 }
1150
1151 if (!QoreTypeInfo::isOutputIdentical(rti, first()->getReturnTypeInfo())) {
1152 same_return_type = false;
1153 break;
1154 }
1155 }
1156 //printd(5, "QoreFunction::parseCheckReturnType() '%s' srt: %d\n", name.c_str(), same_return_type);
1157 return err;
1158 }
1159
1160 // returns QTI_NOT_EQUAL, QTI_AMBIGUOUS, or QTI_IDENT
1161 DLLLOCAL static int parseCompareResolvedSignature(const VList& vlist, const AbstractFunctionSignature* sig,
1162 const AbstractFunctionSignature*& vs);
1163
1164 // returns 0 for OK (not a duplicate), -1 for error (duplicate) - parse exceptions are raised if a duplicate is found
1165 DLLLOCAL int parseCheckDuplicateSignature(AbstractQoreFunctionVariant* variant);
1166
1167 // FIXME: does not check unparsed types properly
1168 DLLLOCAL void addVariant(AbstractQoreFunctionVariant* variant) {
1169 const QoreTypeInfo* rti = variant->getReturnTypeInfo();
1170 if (same_return_type && !vlist.empty() && !QoreTypeInfo::isOutputIdentical(rti, first()->getReturnTypeInfo()))
1171 same_return_type = false;
1172
1173 int64 vf = variant->getFunctionality();
1174 int64 vflags = variant->getFlags();
1175
1176 bool rtn = (bool)(vflags & QCF_RUNTIME_NOOP);
1177
1178 if (vlist.empty()) {
1179 unique_functionality = vf;
1180 unique_flags = vflags;
1181 } else {
1182 unique_functionality &= vf;
1183 unique_flags &= vflags;
1184 }
1185
1186 if (!rtn) {
1187 if (!nn_count) {
1188 nn_unique_functionality = vf;
1189 nn_unique_flags = vflags;
1190 nn_uniqueReturnType = rti;
1191 ++nn_count;
1192 } else {
1193 nn_unique_functionality &= vf;
1194 nn_unique_flags &= vflags;
1195 if (nn_uniqueReturnType && !QoreTypeInfo::isOutputIdentical(rti, nn_uniqueReturnType))
1196 nn_uniqueReturnType = 0;
1197 ++nn_count;
1198 }
1199 }
1200
1201 vlist.push_back(variant);
1202 }
1203
1204 DLLLOCAL virtual ~QoreFunction() {
1205 //printd(5, "QoreFunction::~QoreFunction() this: %p %s\n", this, name.c_str());
1206 }
1207
1208 DLLLOCAL const AbstractQoreFunctionVariant* checkVariant(ExceptionSink* xsink, const type_vec_t& args,
1209 const qore_class_private* class_ctx, const QoreFunction* aqf, const qore_class_private* last_class,
1210 bool internal_access, int64 ppo, const AbstractQoreFunctionVariant* variant) const;
1211
1212 DLLLOCAL const AbstractQoreFunctionVariant* checkVariantDomain(ExceptionSink* xsink, int64 ppo,
1213 const AbstractQoreFunctionVariant* variant) const;
1214};
1215
1216class QoreFunctionIterator {
1217public:
1218 DLLLOCAL QoreFunctionIterator(const QoreFunction& f) : f(f) {
1219 i = f.vlist.end();
1220 }
1221
1222 DLLLOCAL bool next() {
1223 if (i == f.vlist.end()) {
1224 i = f.vlist.begin();
1225 }
1226 else {
1227 ++i;
1228 }
1229
1230 return i != f.vlist.end();
1231 }
1232
1233 DLLLOCAL const AbstractQoreFunctionVariant* getVariant() const {
1234 return *i;
1235 }
1236
1237private:
1238 const QoreFunction& f;
1239 VList::const_iterator i;
1240};
1241
1242class MethodVariantBase;
1243class MethodFunctionBase;
1244#define METHFB(f) (reinterpret_cast<MethodFunctionBase*>(f))
1245#define METHFB_const(f) (reinterpret_cast<const MethodFunctionBase*>(f))
1246
1247class MethodFunctionBase : public QoreFunction {
1248friend hashdecl AbstractMethod;
1249protected:
1250 const QoreClass* qc;
1251
1252 // for concrete variants for local abstract variants inherited from base classes
1253 VList pending_save;
1254
1255 // pointer to copy, only valid during copy
1256 mutable MethodFunctionBase* new_copy = nullptr;
1257
1258 bool is_static,
1259 has_final = false,
1260 is_abstract = true,
1261 has_private_internal_variants = false;
1262
1263 ClassAccess access;
1264
1265 DLLLOCAL int checkFinalVariant(const MethodFunctionBase* m, const MethodVariantBase* v) const;
1266
1267 DLLLOCAL void replaceAbstractVariantIntern(MethodVariantBase* variant);
1268
1269public:
1270 DLLLOCAL MethodFunctionBase(const char* nme, const QoreClass* n_qc, bool n_is_static) : QoreFunction(nme),
1271 qc(n_qc), is_static(n_is_static), has_final(false), access(Internal) {
1272 }
1273
1274 // copy constructor, only copies committed variants
1275 DLLLOCAL MethodFunctionBase(const MethodFunctionBase& old, const QoreClass* n_qc)
1276 : QoreFunction(old, 0, true),
1277 qc(n_qc),
1278 is_static(old.is_static),
1279 has_final(old.has_final),
1280 is_abstract(old.is_abstract),
1281 has_private_internal_variants(old.has_private_internal_variants),
1282 access(old.access) {
1283 //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());
1284
1285 // set a pointer to the new function
1286 old.new_copy = this;
1287
1288 // copy ilist, will be adjusted for new class pointers after all classes have been copied
1289 ilist.reserve(old.ilist.size());
1290 ilist_t::const_iterator i = old.ilist.begin(), e = old.ilist.end();
1291 ++i;
1292 for (; i != e; ++i) {
1293 ilist.push_back(*i);
1294 }
1295 }
1296
1297 DLLLOCAL void resolveCopy() {
1298 ilist_t::iterator i = ilist.begin(), e = ilist.end();
1299 ++i;
1300 for (; i != e; ++i) {
1301 MethodFunctionBase* mfb = METHFB((*i).func);
1302#ifdef DEBUG
1303 if (!mfb->new_copy)
1304 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());
1305 assert(mfb->new_copy);
1306 //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);
1307#endif
1308 (*i).func = mfb->new_copy;
1309 }
1310 }
1311
1312 DLLLOCAL int parseInit();
1313 DLLLOCAL void parseCommit();
1314 DLLLOCAL void parseRollback();
1315
1316 // returns -1 for error, 0 = OK
1317 DLLLOCAL int parseAddUserMethodVariant(MethodVariantBase* variant);
1318
1319 // maintains access flag and commits the builtin variant
1320 DLLLOCAL void addBuiltinMethodVariant(MethodVariantBase* variant);
1321
1322 // maintains access flag and commits user variants
1323 DLLLOCAL void parseCommitMethod(QoreString& csig, const char* mod);
1324
1325 DLLLOCAL void parseCommitMethod();
1326 // processes method signatures
1327 DLLLOCAL void parseSignatures(QoreString& csig, const char* mod) const;
1328
1329 // if an identical signature is found to the passed variant, then it is removed from the abstract list
1330 DLLLOCAL MethodVariantBase* parseHasVariantWithSignature(MethodVariantBase* v, bool relaxed_match = false) const;
1331
1332 DLLLOCAL void replaceAbstractVariant(MethodVariantBase* variant);
1333
1334 DLLLOCAL void parseRollbackMethod();
1335
1336 DLLLOCAL bool isUniquelyPrivate() const {
1337 return access > Public;
1338 }
1339
1340 DLLLOCAL bool isAbstract() const {
1341 return is_abstract;
1342 }
1343
1344 DLLLOCAL ClassAccess getAccess() const {
1345 return access;
1346 }
1347
1348 DLLLOCAL virtual const QoreClass* getClass() const {
1349 return qc;
1350 }
1351
1352 DLLLOCAL const char* getClassName() const {
1353 return qc->getName();
1354 }
1355
1356 DLLLOCAL std::string classPath() const {
1357 if (!qc) {
1358 return std::string();
1359 }
1360 return qc->getNamespacePath(true);
1361 }
1362
1363 DLLLOCAL bool isStatic() const {
1364 return is_static;
1365 }
1366
1367 DLLLOCAL bool hasPrivateInternalVariants() const {
1368 return has_private_internal_variants;
1369 }
1370
1371 DLLLOCAL int checkFinal() const;
1372
1373 // virtual copy constructor
1374 DLLLOCAL virtual MethodFunctionBase* copy(const QoreClass* n_qc) const = 0;
1375};
1376
1377class UserParamListLocalVarHelper {
1378protected:
1379 UserVariantBase* uvb;
1380
1381public:
1382 DLLLOCAL UserParamListLocalVarHelper(UserVariantBase* n_uvb, const QoreTypeInfo* classTypeInfo = nullptr)
1383 : uvb(n_uvb) {
1384 uvb->parseInitPushLocalVars(classTypeInfo);
1385 }
1386
1387 DLLLOCAL ~UserParamListLocalVarHelper() {
1388 uvb->parseInitPopLocalVars();
1389 }
1390};
1391
1392class UserClosureVariant : public UserFunctionVariant {
1393protected:
1394public:
1395 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) {
1396 }
1397
1398 DLLLOCAL virtual int parseInit(QoreFunction* f);
1399
1400 DLLLOCAL QoreValue evalClosure(CodeEvaluationHelper& ceh, QoreObject* self, ExceptionSink* xsink) const {
1401 return eval("<anonymous closure>", &ceh, self, xsink);
1402 }
1403};
1404
1405#define UCLOV(f) (reinterpret_cast<UserClosureVariant*>(f))
1406#define UCLOV_const(f) (reinterpret_cast<const UserClosureVariant*>(f))
1407
1408class UserClosureFunction : public QoreFunction {
1409protected:
1410 LVarSet varlist; // closure local variable environment
1411 const QoreTypeInfo* classTypeInfo;
1412
1413public:
1414 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) {
1415 addPendingVariant(new UserClosureVariant(b, n_sig_first_line, n_sig_last_line, params, rv, synced, n_flags));
1416 }
1417
1418 DLLLOCAL QoreValue evalClosure(const QoreClosureBase& closure_base, QoreProgram* pgm, const QoreListNode* args, QoreObject* self, const qore_class_private* class_ctx, ExceptionSink* xsink) const;
1419
1420 DLLLOCAL void setClassType(const QoreTypeInfo* cti) {
1421 classTypeInfo = cti;
1422 }
1423
1424 DLLLOCAL const QoreTypeInfo* getClassType() const {
1425 return classTypeInfo;
1426 }
1427
1428 DLLLOCAL LVarSet* getVList() {
1429 return &varlist;
1430 }
1431
1432 // 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)
1433 DLLLOCAL bool needsScan() const {
1434 return varlist.needsScan();
1435 }
1436};
1437
1438#endif // _QORE_FUNCTION_H
#define QDOM_DEFAULT
the default domain (no domain)
Definition Restrictions.h:172
#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:310
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:61
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:426
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:269
std::vector< const QoreTypeInfo * > type_vec_t
vector of type information for parameter lists
Definition common.h:257
std::vector< std::string > name_vec_t
vector of parameter names for parameter lists
Definition common.h:263
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:266
std::vector< QoreValue > arg_vec_t
vector of value information for default argument lists
Definition common.h:260
The main value class in Qore, designed to be passed by value.
Definition QoreValue.h:279