Qore Programming Language 2.0.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 { return QDOM_DEFAULT; } \
656 using AbstractQoreFunctionVariant::getUserVariantBase; \
657 DLLLOCAL virtual UserVariantBase* getUserVariantBase() { return static_cast<UserVariantBase*>(this); } \
658 DLLLOCAL virtual AbstractFunctionSignature* getSignature() const { return const_cast<UserSignature*>(&signature); } \
659 DLLLOCAL virtual const QoreTypeInfo* parseGetReturnTypeInfo(int& err) const { return signature.parseGetReturnTypeInfo(err); } \
660 DLLLOCAL virtual void setRecheck() { recheck = true; } \
661 DLLLOCAL virtual void parseCommit() { UserVariantBase::parseCommit(); } \
662 DLLLOCAL virtual bool hasVarargs() const { if (signature.hasVarargs()) return true; return AbstractQoreFunctionVariant::hasVarargs(); }
663
664
665// this class ensures that instantiated variables in user code are uninstantiated, even if an exception occurs
666class UserVariantExecHelper : ProgramThreadCountContextHelper, ThreadFrameBoundaryHelper {
667protected:
668 const UserVariantBase* uvb;
670 ExceptionSink* xsink;
671
672public:
673 DLLLOCAL UserVariantExecHelper(const UserVariantBase* n_uvb, CodeEvaluationHelper* ceh, ExceptionSink* n_xsink) :
674 ProgramThreadCountContextHelper(n_xsink, n_uvb->pgm, true),
675 ThreadFrameBoundaryHelper(!*n_xsink),
676 uvb(n_uvb), argv(n_xsink), xsink(n_xsink) {
677 assert(xsink);
678 if (*xsink || uvb->setupCall(ceh, argv, xsink))
679 uvb = nullptr;
680 }
681
682 DLLLOCAL ~UserVariantExecHelper();
683
684 DLLLOCAL operator bool() const {
685 return uvb;
686 }
687
688 DLLLOCAL ReferenceHolder<QoreListNode>& getArgv() {
689 return argv;
690 }
691};
692
693class UserFunctionVariant : public AbstractQoreFunctionVariant, public UserVariantBase {
694protected:
695 bool mod_pub; // is public in module
696
697 DLLLOCAL virtual ~UserFunctionVariant() {
698 }
699
700public:
701 DLLLOCAL UserFunctionVariant(StatementBlock* b, int n_sig_first_line, int n_sig_last_line, QoreValue params,
702 RetTypeInfo* rv, bool synced, int64 n_flags = QCF_NO_FLAGS) :
703 AbstractQoreFunctionVariant(n_flags, true),
704 UserVariantBase(b, n_sig_first_line, n_sig_last_line, params, rv, synced), mod_pub(false) {
705 if (signature.hasVarargs()) {
706 flags |= QCF_USES_EXTRA_ARGS;
707 }
708 }
709
710 // the following defines the virtual functions that are common to all user variants
711 COMMON_USER_VARIANT_FUNCTIONS
712
713 DLLLOCAL virtual QoreValue evalFunction(ExceptionSink* xsink, CodeEvaluationHelper& ceh) const {
714 return eval(ceh.getName(), &ceh, nullptr, xsink);
715 }
716
717 DLLLOCAL virtual int parseInit(QoreFunction* f);
718
719 DLLLOCAL virtual bool isModulePublic() const {
720 return mod_pub;
721 }
722
723 DLLLOCAL void setModulePublic() {
724 assert(!mod_pub);
725 mod_pub = true;
726 }
727};
728
729#define UFV(f) (reinterpret_cast<UserFunctionVariant*>(f))
730#define UFV_const(f) (reinterpret_cast<const UserFunctionVariant*>(f))
731
732// type for lists of function variants
733// this type will be read at runtime and could be appended to simultaneously at parse time (under a lock)
734typedef safe_dslist<AbstractQoreFunctionVariant*> vlist_t;
735
736class VList : public vlist_t {
737public:
738 DLLLOCAL ~VList() {
739 del();
740 }
741 DLLLOCAL void del() {
742 // dereference all variants
743 for (vlist_t::iterator i = begin(), e = end(); i != e; ++i)
744 (*i)->deref();
745 clear();
746 }
747};
748
749// inheritance noce
750hashdecl INode {
751 QoreFunction* func;
752 ClassAccess access;
753
754 DLLLOCAL INode(QoreFunction* f, ClassAccess a) : func(f), access(a) {
755 }
756};
757
758// inheritance list type
759typedef std::vector<INode> ilist_t;
760
761hashdecl IList : public ilist_t {
762 DLLLOCAL QoreFunction* getFunction(const qore_class_private* class_ctx, const qore_class_private*& last_class,
763 const_iterator aqfi, bool& internal_access, bool& stop) const;
764};
765
766class QoreFunction : protected QoreReferenceCounter {
767friend class QoreFunctionIterator;
768friend class qore_external_function_iterator_private;
769public:
770 DLLLOCAL QoreFunction(const char* n_name) : name(n_name),
771 same_return_type(true),
772 nn_same_return_type(true),
773 parse_rt_done(true),
774 parse_init_done(true),
775 parse_init_in_progress(false),
776 has_user(false),
777 has_builtin(false),
778 has_pub(false),
779 inject(false),
780 check_parse(false),
781 has_priv(false),
782 all_priv(true) {
783 ilist.push_back(INode(this, Public));
784 //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
785 const char* mod_name = get_module_context_name();
786 if (mod_name) {
787 from_module = mod_name;
788 }
789 }
790
791 // copy constructor (used by method functions when copied)
792 DLLLOCAL QoreFunction(const QoreFunction& old, int64 po = 0, bool copy_all = false, bool n_inject = false)
793 : name(old.name),
794 unique_functionality(old.unique_functionality),
795 unique_flags(old.unique_flags),
796 nn_unique_functionality(old.nn_unique_functionality),
797 nn_unique_flags(old.nn_unique_flags),
798 nn_count(old.nn_count),
799 same_return_type(old.same_return_type),
800 nn_same_return_type(old.nn_same_return_type),
801 parse_rt_done(true),
802 parse_init_done(true),
803 parse_init_in_progress(false),
804 has_user(old.has_user),
805 has_builtin(old.has_builtin),
806 has_pub(false),
807 inject(n_inject),
808 check_parse(false),
809 has_priv(old.has_priv),
810 all_priv(old.all_priv),
811 nn_uniqueReturnType(old.nn_uniqueReturnType),
812 from_module(old.from_module) {
813 bool no_user = po & PO_NO_INHERIT_USER_FUNC_VARIANTS;
814 bool no_builtin = po & PO_NO_SYSTEM_FUNC_VARIANTS;
815
816 // copy variants by reference
817 for (vlist_t::const_iterator i = old.vlist.begin(), e = old.vlist.end(); i != e; ++i) {
818 if (!copy_all) {
819 if ((*i)->isUser()) {
820 if (no_user || !(*i)->isModulePublic())
821 continue;
822 }
823 else
824 if (no_builtin)
825 continue;
826 }
827
828 vlist.push_back((*i)->ref());
829 }
830
831 if (no_user && has_user)
832 has_user = false;
833 if (no_builtin && has_builtin)
834 has_builtin = false;
835
836 // make sure the new variant list is not empty if the parent also wasn't
837 assert(old.vlist.empty() || !vlist.empty());
838
839 assert(!old.ilist.empty());
840 assert(old.ilist.front().func == &old);
841
842 // resolve initial ilist entry to this function
843 ilist.push_back(INode(this, Public));
844
845 // the rest of ilist is copied in method base class
846 // do not copy pending variants
847 //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
848 }
849
850#if 0
851 // copy constructor when importing public user variants from user modules into Program objects
852 DLLLOCAL QoreFunction(bool ignore, const QoreFunction& old, qore_ns_private* nns)
853 : name(old.name), ns(nns), same_return_type(old.same_return_type),
854 unique_functionality(old.unique_functionality),
855 unique_flags(old.unique_flags),
856 nn_same_return_type(old.nn_same_return_type),
857 nn_unique_functionality(old.nn_unique_functionality),
858 nn_unique_flags(old.nn_unique_flags),
859 nn_count(old.nn_count),
860 parse_rt_done(true), parse_init_done(true),
861 has_user(true), has_builtin(false), has_mod_pub(false /*old.has_mod_pub*/), inject(false),
862 nn_uniqueReturnType(old.nn_uniqueReturnType) {
863 assert(!ignore);
864 assert(old.has_mod_pub);
865
866 // copy variants by reference
867 for (vlist_t::const_iterator i = old.vlist.begin(), e = old.vlist.end(); i != e; ++i) {
868 if (!(*i)->isModulePublic())
869 continue;
870 vlist.push_back((*i)->ref());
871 }
872
873 // make sure the new variant list is not empty if the parent also wasn't
874 assert(old.vlist.empty() || !vlist.empty());
875
876 assert(!old.ilist.empty());
877 assert(old.ilist.front().func == &old);
878
879 // resolve initial ilist entry to this function
880 ilist.push_back(INode(this, Public));
881
882 // the rest of ilist is copied in method base class
883 // do not copy pending variants
884 //printd(5, "QoreFunction::QoreFunction() this: %p %s\n", this, name.c_str());
885 }
886#endif
887
888 // convenience function for returning the first variant in the list
889 DLLLOCAL const AbstractQoreFunctionVariant* first() const {
890 assert(!vlist.empty());
891 return *(vlist.begin());
892 }
893
894 // convenience function for returning the first variant in the list
895 DLLLOCAL AbstractQoreFunctionVariant* first() {
896 assert(!vlist.empty());
897 return *(vlist.begin());
898 }
899
900 DLLLOCAL unsigned numVariants() const {
901 return vlist.size();
902 }
903
904 DLLLOCAL QoreListNode* runtimeGetCallVariants() const;
905
906 // returns 0 for OK, -1 for error
907 DLLLOCAL int parseCheckDuplicateSignatureCommitted(UserSignature* sig);
908
909 DLLLOCAL const char* getName() const {
910 return name.c_str();
911 }
912
913 DLLLOCAL virtual const QoreClass* getClass() const {
914 return nullptr;
915 }
916
917 DLLLOCAL void ref() {
918 ROreference();
919 }
920
921 DLLLOCAL void deref() {
922 if (ROdereference())
923 delete this;
924 }
925
926 DLLLOCAL const char* className() const {
927 const QoreClass* qc = getClass();
928 return qc ? qc->getName() : nullptr;
929 }
930
931 DLLLOCAL std::string classPath() const {
932 const QoreClass* qc = getClass();
933 if (!qc) {
934 return std::string();
935 }
936 return qc->getNamespacePath(true);
937 }
938
939 DLLLOCAL void addAncestor(QoreFunction* ancestor, ClassAccess access) {
940 ilist.push_back(INode(ancestor, access));
941 }
942
943 DLLLOCAL void addNewAncestor(QoreFunction* ancestor, ClassAccess access) {
944 for (ilist_t::iterator i = ilist.begin(), e = ilist.end(); i != e; ++i)
945 if ((*i).func == ancestor)
946 return;
947 ilist.push_back(INode(ancestor, access));
948 }
949
950 // resolves all types in signatures and return types in pending variants; called during the "parseInit" phase
951 DLLLOCAL void resolvePendingSignatures();
952
953 DLLLOCAL AbstractFunctionSignature* getUniqueSignature() const {
954 return vlist.singular() ? first()->getSignature() : 0;
955 }
956
957 DLLLOCAL AbstractFunctionSignature* parseGetUniqueSignature() const;
958
959 DLLLOCAL int64 parseGetUniqueFunctionality() const {
960 if (parse_get_parse_options() & PO_REQUIRE_TYPES)
961 return nn_unique_functionality;
962 return unique_functionality;
963 }
964
965 DLLLOCAL int64 parseGetUniqueFlags() const {
966 if (parse_get_parse_options() & PO_REQUIRE_TYPES)
967 return nn_unique_flags;
968 return unique_flags;
969 }
970
971 // object takes ownership of variant or deletes it if it can't be added
972 DLLLOCAL int addPendingVariant(AbstractQoreFunctionVariant* variant);
973
974 DLLLOCAL void addBuiltinVariant(AbstractQoreFunctionVariant* variant);
975
976 DLLLOCAL int parseInit(qore_ns_private* ns);
977 DLLLOCAL void parseCommit();
978 DLLLOCAL void parseRollback();
979
980 DLLLOCAL const QoreTypeInfo* getUniqueReturnTypeInfo() const {
981 if (runtime_get_parse_options() & PO_REQUIRE_TYPES)
982 return nn_uniqueReturnType;
983
984 return same_return_type && !vlist.empty() ? first()->getReturnTypeInfo() : 0;
985 }
986
987 DLLLOCAL const QoreTypeInfo* parseGetUniqueReturnTypeInfo() {
988 parseCheckReturnType();
989
990 //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());
991
992 if (!same_return_type)
993 return nullptr;
994
995 if (parse_get_parse_options() & PO_REQUIRE_TYPES) {
996 if (!nn_same_return_type)
997 return nullptr;
998
999 return nn_count ? nn_uniqueReturnType : (!vlist.empty() ? first()->getReturnTypeInfo() : nullptr);
1000 }
1001
1002 if (!vlist.empty())
1003 return first()->getReturnTypeInfo();
1004
1005 return nullptr;
1006 }
1007
1008 // if the variant was identified at parse time, then variant will not be NULL, otherwise if NULL then it is identified at run time
1009 DLLLOCAL virtual QoreValue evalFunction(const AbstractQoreFunctionVariant* variant, const QoreListNode* args,
1010 QoreProgram* pgm, ExceptionSink* xsink) const;
1011
1012 // if the variant was identified at parse time, then variant will not be NULL, otherwise if NULL then it is identified at run time
1013 // this function will use destructive evaluation of "args"
1014 DLLLOCAL virtual QoreValue evalFunctionTmpArgs(const AbstractQoreFunctionVariant* variant, QoreListNode* args,
1015 QoreProgram* pgm, ExceptionSink* xsink) const;
1016
1017 // finds a variant and checks variant capabilities against current program parse options and executes the variant
1018 DLLLOCAL QoreValue evalDynamic(const QoreListNode* args, ExceptionSink* xsink) const;
1019
1020 // find variant at parse time, throw parse exception if no variant can be matched
1021 // class_ctx is only for use in a class hierarchy and is only set if there is a current class context and it's
1022 // reachable
1023 DLLLOCAL const AbstractQoreFunctionVariant* parseFindVariant(const QoreProgramLocation* loc,
1024 const type_vec_t& argTypeInfo, const qore_class_private* class_ctx, int& err) const;
1025
1026 // returns true if there are no uncommitted parse variants in the function
1027 DLLLOCAL bool pendingEmpty() const {
1028 return vlist.empty() || !check_parse;
1029 }
1030
1031 // returns true if there are no committed parse variants in the function
1032 DLLLOCAL bool committedEmpty() const {
1033 return vlist.empty() || check_parse;
1034 }
1035
1036 DLLLOCAL bool existsVariant(const type_vec_t& paramTypeInfo) const;
1037
1038 // find variant at runtime
1039 // 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
1040 DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindVariant(ExceptionSink* xsink, const QoreListNode* args, bool only_user, const qore_class_private* class_ctx) const;
1041
1042 // finds the best match with the given arg types
1043 DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindVariant(ExceptionSink* xsink, const type_vec_t& args, const qore_class_private* class_ctx) const;
1044 // finds only an exact match with the given arg types
1045 DLLLOCAL const AbstractQoreFunctionVariant* runtimeFindExactVariant(ExceptionSink* xsink, const type_vec_t& args, const qore_class_private* class_ctx) const;
1046
1047 DLLLOCAL void parseAssimilate(QoreFunction& other) {
1048 while (!other.vlist.empty()) {
1049 addPendingVariant(*(other.vlist.begin()));
1050 other.vlist.pop_front();
1051 }
1052 }
1053
1054 DLLLOCAL bool hasUser() const {
1055 return has_user;
1056 }
1057
1058 DLLLOCAL bool hasBuiltin() const {
1059 return has_builtin;
1060 }
1061
1062 DLLLOCAL bool hasPublic() const {
1063 return has_pub;
1064 }
1065
1066 DLLLOCAL bool hasUserPublic() const {
1067 return has_pub && has_user;
1068 }
1069
1070 DLLLOCAL bool injected() const {
1071 return inject;
1072 }
1073
1074 DLLLOCAL bool hasPrivate() const {
1075 return has_priv;
1076 }
1077
1078 DLLLOCAL bool allPrivate() const {
1079 return all_priv;
1080 }
1081
1082 DLLLOCAL const std::string& getNameStr() const {
1083 return name;
1084 }
1085
1086 DLLLOCAL const char* getModuleName() const {
1087 return from_module.empty() ? nullptr : from_module.c_str();
1088 }
1089
1090protected:
1091 std::string name;
1092
1093 // list of function variants
1094 VList vlist;
1095
1096 // list of inherited methods for variant matching; the first pointer is always a pointer to "this"
1097 IList ilist;
1098
1099 int64 unique_functionality = QDOM_DEFAULT;
1100 int64 unique_flags = QCF_NO_FLAGS;
1101
1102 // same as above but for variants without QCF_RUNTIME_NOOP
1103 int64 nn_unique_functionality = QDOM_DEFAULT;
1104 int64 nn_unique_flags = QCF_NO_FLAGS;
1105 int nn_count = 0;
1106
1107 // if true means all variants have the same return value
1108 bool same_return_type : 1;
1109 bool nn_same_return_type : 1;
1110 bool parse_rt_done : 1;
1111 bool parse_init_done : 1;
1112 bool parse_init_in_progress : 1;
1113 bool has_user : 1; // has at least 1 committed user variant
1114 bool has_builtin : 1; // has at least 1 committed builtin variant
1115 bool has_pub : 1; // has at least 1 committed user variant with public visibility
1116 bool inject : 1;
1117 bool check_parse : 1;
1118 bool has_priv : 1; // has at least 1 private variant
1119 bool all_priv : 1; // all variants are private
1120
1121 const QoreTypeInfo* nn_uniqueReturnType = nullptr;
1122
1123 std::string from_module;
1124
1125 DLLLOCAL int parseCheckReturnType() {
1126 if (parse_rt_done)
1127 return 0;
1128
1129 parse_rt_done = true;
1130
1131 if (!same_return_type)
1132 return 0;
1133
1134
1135 int err = 0;
1136 for (vlist_t::iterator i = vlist.begin(), e = vlist.end(); i != e; ++i) {
1137 if (reinterpret_cast<UserSignature*>((*i)->getUserVariantBase()->getUserSignature())->resolve() && !err) {
1138 err = -1;
1139 }
1140 const QoreTypeInfo* rti = (*i)->getReturnTypeInfo();
1141
1142 if (i == vlist.begin()) {
1143 continue;
1144 }
1145
1146 if (!QoreTypeInfo::isOutputIdentical(rti, first()->getReturnTypeInfo())) {
1147 same_return_type = false;
1148 break;
1149 }
1150 }
1151 //printd(5, "QoreFunction::parseCheckReturnType() '%s' srt: %d\n", name.c_str(), same_return_type);
1152 return err;
1153 }
1154
1155 // returns QTI_NOT_EQUAL, QTI_AMBIGUOUS, or QTI_IDENT
1156 DLLLOCAL static int parseCompareResolvedSignature(const VList& vlist, const AbstractFunctionSignature* sig,
1157 const AbstractFunctionSignature*& vs);
1158
1159 // returns 0 for OK (not a duplicate), -1 for error (duplicate) - parse exceptions are raised if a duplicate is found
1160 DLLLOCAL int parseCheckDuplicateSignature(AbstractQoreFunctionVariant* variant);
1161
1162 // FIXME: does not check unparsed types properly
1163 DLLLOCAL void addVariant(AbstractQoreFunctionVariant* variant) {
1164 const QoreTypeInfo* rti = variant->getReturnTypeInfo();
1165 if (same_return_type && !vlist.empty() && !QoreTypeInfo::isOutputIdentical(rti, first()->getReturnTypeInfo()))
1166 same_return_type = false;
1167
1168 int64 vf = variant->getFunctionality();
1169 int64 vflags = variant->getFlags();
1170
1171 bool rtn = (bool)(vflags & QCF_RUNTIME_NOOP);
1172
1173 if (vlist.empty()) {
1174 unique_functionality = vf;
1175 unique_flags = vflags;
1176 } else {
1177 unique_functionality &= vf;
1178 unique_flags &= vflags;
1179 }
1180
1181 if (!rtn) {
1182 if (!nn_count) {
1183 nn_unique_functionality = vf;
1184 nn_unique_flags = vflags;
1185 nn_uniqueReturnType = rti;
1186 ++nn_count;
1187 } else {
1188 nn_unique_functionality &= vf;
1189 nn_unique_flags &= vflags;
1190 if (nn_uniqueReturnType && !QoreTypeInfo::isOutputIdentical(rti, nn_uniqueReturnType))
1191 nn_uniqueReturnType = 0;
1192 ++nn_count;
1193 }
1194 }
1195
1196 vlist.push_back(variant);
1197 }
1198
1199 DLLLOCAL virtual ~QoreFunction() {
1200 //printd(5, "QoreFunction::~QoreFunction() this: %p %s\n", this, name.c_str());
1201 }
1202
1203 DLLLOCAL const AbstractQoreFunctionVariant* checkVariant(ExceptionSink* xsink, const type_vec_t& args,
1204 const qore_class_private* class_ctx, const QoreFunction* aqf, const qore_class_private* last_class,
1205 bool internal_access, int64 ppo, const AbstractQoreFunctionVariant* variant) const;
1206};
1207
1208class QoreFunctionIterator {
1209public:
1210 DLLLOCAL QoreFunctionIterator(const QoreFunction& f) : f(f) {
1211 i = f.vlist.end();
1212 }
1213
1214 DLLLOCAL bool next() {
1215 if (i == f.vlist.end()) {
1216 i = f.vlist.begin();
1217 }
1218 else {
1219 ++i;
1220 }
1221
1222 return i != f.vlist.end();
1223 }
1224
1225 DLLLOCAL const AbstractQoreFunctionVariant* getVariant() const {
1226 return *i;
1227 }
1228
1229private:
1230 const QoreFunction& f;
1231 VList::const_iterator i;
1232};
1233
1234class MethodVariantBase;
1235class MethodFunctionBase;
1236#define METHFB(f) (reinterpret_cast<MethodFunctionBase*>(f))
1237#define METHFB_const(f) (reinterpret_cast<const MethodFunctionBase*>(f))
1238
1239class MethodFunctionBase : public QoreFunction {
1240friend hashdecl AbstractMethod;
1241protected:
1242 const QoreClass* qc;
1243
1244 // for concrete variants for local abstract variants inherited from base classes
1245 VList pending_save;
1246
1247 // pointer to copy, only valid during copy
1248 mutable MethodFunctionBase* new_copy = nullptr;
1249
1250 bool is_static,
1251 has_final = false,
1252 is_abstract = true,
1253 has_private_internal_variants = false;
1254
1255 ClassAccess access;
1256
1257 DLLLOCAL int checkFinalVariant(const MethodFunctionBase* m, const MethodVariantBase* v) const;
1258
1259 DLLLOCAL void replaceAbstractVariantIntern(MethodVariantBase* variant);
1260
1261public:
1262 DLLLOCAL MethodFunctionBase(const char* nme, const QoreClass* n_qc, bool n_is_static) : QoreFunction(nme),
1263 qc(n_qc), is_static(n_is_static), has_final(false), access(Internal) {
1264 }
1265
1266 // copy constructor, only copies committed variants
1267 DLLLOCAL MethodFunctionBase(const MethodFunctionBase& old, const QoreClass* n_qc)
1268 : QoreFunction(old, 0, true),
1269 qc(n_qc),
1270 is_static(old.is_static),
1271 has_final(old.has_final),
1272 is_abstract(old.is_abstract),
1273 has_private_internal_variants(old.has_private_internal_variants),
1274 access(old.access) {
1275 //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());
1276
1277 // set a pointer to the new function
1278 old.new_copy = this;
1279
1280 // copy ilist, will be adjusted for new class pointers after all classes have been copied
1281 ilist.reserve(old.ilist.size());
1282 ilist_t::const_iterator i = old.ilist.begin(), e = old.ilist.end();
1283 ++i;
1284 for (; i != e; ++i) {
1285 ilist.push_back(*i);
1286 }
1287 }
1288
1289 DLLLOCAL void resolveCopy() {
1290 ilist_t::iterator i = ilist.begin(), e = ilist.end();
1291 ++i;
1292 for (; i != e; ++i) {
1293 MethodFunctionBase* mfb = METHFB((*i).func);
1294#ifdef DEBUG
1295 if (!mfb->new_copy)
1296 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());
1297 assert(mfb->new_copy);
1298 //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);
1299#endif
1300 (*i).func = mfb->new_copy;
1301 }
1302 }
1303
1304 DLLLOCAL int parseInit();
1305 DLLLOCAL void parseCommit();
1306 DLLLOCAL void parseRollback();
1307
1308 // returns -1 for error, 0 = OK
1309 DLLLOCAL int parseAddUserMethodVariant(MethodVariantBase* variant);
1310
1311 // maintains access flag and commits the builtin variant
1312 DLLLOCAL void addBuiltinMethodVariant(MethodVariantBase* variant);
1313
1314 // maintains access flag and commits user variants
1315 DLLLOCAL void parseCommitMethod(QoreString& csig, const char* mod);
1316
1317 DLLLOCAL void parseCommitMethod();
1318 // processes method signatures
1319 DLLLOCAL void parseSignatures(QoreString& csig, const char* mod) const;
1320
1321 // if an identical signature is found to the passed variant, then it is removed from the abstract list
1322 DLLLOCAL MethodVariantBase* parseHasVariantWithSignature(MethodVariantBase* v, bool relaxed_match = false) const;
1323
1324 DLLLOCAL void replaceAbstractVariant(MethodVariantBase* variant);
1325
1326 DLLLOCAL void parseRollbackMethod();
1327
1328 DLLLOCAL bool isUniquelyPrivate() const {
1329 return access > Public;
1330 }
1331
1332 DLLLOCAL bool isAbstract() const {
1333 return is_abstract;
1334 }
1335
1336 DLLLOCAL ClassAccess getAccess() const {
1337 return access;
1338 }
1339
1340 DLLLOCAL virtual const QoreClass* getClass() const {
1341 return qc;
1342 }
1343
1344 DLLLOCAL const char* getClassName() const {
1345 return qc->getName();
1346 }
1347
1348 DLLLOCAL std::string classPath() const {
1349 if (!qc) {
1350 return std::string();
1351 }
1352 return qc->getNamespacePath(true);
1353 }
1354
1355 DLLLOCAL bool isStatic() const {
1356 return is_static;
1357 }
1358
1359 DLLLOCAL bool hasPrivateInternalVariants() const {
1360 return has_private_internal_variants;
1361 }
1362
1363 DLLLOCAL int checkFinal() const;
1364
1365 // virtual copy constructor
1366 DLLLOCAL virtual MethodFunctionBase* copy(const QoreClass* n_qc) const = 0;
1367};
1368
1369class UserParamListLocalVarHelper {
1370protected:
1371 UserVariantBase* uvb;
1372
1373public:
1374 DLLLOCAL UserParamListLocalVarHelper(UserVariantBase* n_uvb, const QoreTypeInfo* classTypeInfo = nullptr)
1375 : uvb(n_uvb) {
1376 uvb->parseInitPushLocalVars(classTypeInfo);
1377 }
1378
1379 DLLLOCAL ~UserParamListLocalVarHelper() {
1380 uvb->parseInitPopLocalVars();
1381 }
1382};
1383
1384class UserClosureVariant : public UserFunctionVariant {
1385protected:
1386public:
1387 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) {
1388 }
1389
1390 DLLLOCAL virtual int parseInit(QoreFunction* f);
1391
1392 DLLLOCAL QoreValue evalClosure(CodeEvaluationHelper& ceh, QoreObject* self, ExceptionSink* xsink) const {
1393 return eval("<anonymous closure>", &ceh, self, xsink);
1394 }
1395};
1396
1397#define UCLOV(f) (reinterpret_cast<UserClosureVariant*>(f))
1398#define UCLOV_const(f) (reinterpret_cast<const UserClosureVariant*>(f))
1399
1400class UserClosureFunction : public QoreFunction {
1401protected:
1402 LVarSet varlist; // closure local variable environment
1403 const QoreTypeInfo* classTypeInfo;
1404
1405public:
1406 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) {
1407 addPendingVariant(new UserClosureVariant(b, n_sig_first_line, n_sig_last_line, params, rv, synced, n_flags));
1408 }
1409
1410 DLLLOCAL QoreValue evalClosure(const QoreClosureBase& closure_base, QoreProgram* pgm, const QoreListNode* args, QoreObject* self, const qore_class_private* class_ctx, ExceptionSink* xsink) const;
1411
1412 DLLLOCAL void setClassType(const QoreTypeInfo* cti) {
1413 classTypeInfo = cti;
1414 }
1415
1416 DLLLOCAL const QoreTypeInfo* getClassType() const {
1417 return classTypeInfo;
1418 }
1419
1420 DLLLOCAL LVarSet* getVList() {
1421 return &varlist;
1422 }
1423
1424 // 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)
1425 DLLLOCAL bool needsScan() const {
1426 return varlist.needsScan();
1427 }
1428};
1429
1430#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