Qore Programming Language  0.9.4.6
QoreClosureNode.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  QoreClosureNode.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2016 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_QORECLOSURENODE_H
33 
34 #define _QORE_QORECLOSURENODE_H
35 
36 #include "qore/intern/QoreObjectIntern.h"
37 
38 #include <map>
39 
40 class CVecInstantiator {
41 protected:
42  cvv_vec_t* cvec;
43  ExceptionSink* xsink;
44 
45 public:
46  DLLLOCAL CVecInstantiator(cvv_vec_t* cv, ExceptionSink* xs) : cvec(cv), xsink(xs) {
47  if (!cvec)
48  return;
49  for (cvv_vec_t::iterator i = cvec->begin(), e = cvec->end(); i != e; ++i)
50  thread_instantiate_closure_var((*i)->refSelf());
51  }
52 
53  DLLLOCAL ~CVecInstantiator() {
54  if (!cvec)
55  return;
56  // elements are dereferenced when uninstantiated
57  for (cvv_vec_t::iterator i = cvec->begin(), e = cvec->end(); i != e; ++i)
58  thread_uninstantiate_closure_var(xsink);
59  }
60 };
61 
62 class QoreClosureBase : public ResolvedCallReferenceNode {
63 protected:
64  const QoreClosureParseNode* closure;
65  mutable ThreadSafeLocalVarRuntimeEnvironment closure_env;
66  cvv_vec_t* cvec;
67 
68  DLLLOCAL void del(ExceptionSink* xsink) {
69  closure_env.del(xsink);
70  if (cvec) {
71  for (cvv_vec_t::iterator i = cvec->begin(), e = cvec->end(); i != e; ++i)
72  (*i)->deref(xsink);
73  delete cvec;
74 #ifdef DEBUG
75  cvec = 0;
76 #endif
77  }
78  }
79 
80 public:
82  DLLLOCAL QoreClosureBase(const QoreClosureParseNode* n_closure, cvv_vec_t* cv) : ResolvedCallReferenceNode(false, NT_RUNTIME_CLOSURE), closure(n_closure), closure_env(n_closure->getVList()), cvec(cv) {
83  //printd(5, "QoreClosureBase::QoreClosureBase() this: %p closure: %p\n", this, closure);
84  closure->ref();
85  }
86 
87  DLLLOCAL ~QoreClosureBase() {
88  //printd(5, "QoreClosureBase::~QoreClosureBase() this: %p closure: %p\n", this, closure);
89  const_cast<QoreClosureParseNode*>(closure)->deref();
90  assert(!cvec);
91  }
92 
93  DLLLOCAL ClosureVarValue* find(const LocalVar* id) const {
94  return closure_env.find(id);
95  }
96 
97  DLLLOCAL bool hasVar(ClosureVarValue* cvv) const {
98  return closure_env.hasVar(cvv);
99  }
100 
101  DLLLOCAL const cvar_map_t& getMap() const {
102  return closure_env.getMap();
103  }
104 
105  // 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)
106  DLLLOCAL bool needsScan() const {
107  return closure->needsScan();
108  }
109 
110  DLLLOCAL static const char* getStaticTypeName() {
111  return "closure";
112  }
113 
114  DLLLOCAL virtual QoreFunction* getFunction() {
115  return closure->getFunction();
116  }
117 
118  DLLLOCAL virtual QoreObject* getObject() const {
119  return 0;
120  }
121 };
122 
123 class QoreClosureNode : public QoreClosureBase {
124 private:
125  QoreProgram* pgm;
126 
127  DLLLOCAL QoreClosureNode(const QoreClosureNode&); // not implemented
128  DLLLOCAL QoreClosureNode& operator=(const QoreClosureNode&); // not implemented
129 
130 protected:
131  DLLLOCAL virtual bool derefImpl(ExceptionSink* xsink);
132 
133 public:
134  DLLLOCAL QoreClosureNode(const QoreClosureParseNode* n_closure, cvv_vec_t* cv = 0) : QoreClosureBase(n_closure, cv), pgm(::getProgram()) {
135  pgm->depRef();
136  }
137 
138  DLLLOCAL virtual ~QoreClosureNode() {
139  }
140 
141  DLLLOCAL virtual QoreValue execValue(const QoreListNode* args, ExceptionSink* xsink) const;
142 
143  DLLLOCAL virtual QoreProgram* getProgram() const {
144  return pgm;
145  }
146 
148 
150  DLLEXPORT virtual bool getAsBoolImpl() const;
151 
152  DLLLOCAL virtual int getAsString(QoreString& str, int foff, ExceptionSink* xsink) const {
153  str.sprintf("function closure (%slambda, %p)", closure->isLambda() ? "" : "non-", this);
154  return 0;
155  }
156 
157  DLLLOCAL virtual QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const {
158  del = true;
159  QoreString* rv = new QoreString;
160  getAsString(*rv, foff, xsink);
161  return rv;
162  }
163 
164  DLLLOCAL virtual const char* getTypeName() const {
165  return getStaticTypeName();
166  }
167 
168  DLLLOCAL bool isLambda() const { return closure->isLambda(); }
169 
170  DLLLOCAL virtual bool is_equal_soft(const AbstractQoreNode* v, ExceptionSink* xsink) const {
171  return QoreClosureNode::is_equal_hard(v, xsink);
172  }
173 
174  DLLLOCAL virtual bool is_equal_hard(const AbstractQoreNode* v, ExceptionSink* xsink) const {
175  return v == this;
176  }
177 };
178 
179 class QoreObjectClosureNode : public QoreClosureBase {
180 private:
181  QoreObject* obj;
182  const qore_class_private* class_ctx;
183 
184  DLLLOCAL QoreObjectClosureNode(const QoreObjectClosureNode&); // not implemented
185  DLLLOCAL QoreObjectClosureNode& operator=(const QoreObjectClosureNode&); // not implemented
186 
187 protected:
188  DLLLOCAL virtual bool derefImpl(ExceptionSink* xsink);
189 
190 public:
191  DLLLOCAL QoreObjectClosureNode(QoreObject* n_obj, const qore_class_private* c_ctx, const QoreClosureParseNode* n_closure, cvv_vec_t* cv = 0) : QoreClosureBase(n_closure, cv), obj(n_obj), class_ctx(c_ctx) {
192  obj->tRef();
193  }
194 
195  DLLLOCAL ~QoreObjectClosureNode() {
196  assert(!obj);
197  }
198 
199  DLLLOCAL virtual QoreValue execValue(const QoreListNode* args, ExceptionSink* xsink) const;
200 
201  DLLLOCAL virtual QoreProgram* getProgram() const {
202  return obj->getProgram();
203  }
204 
205  DLLLOCAL virtual int getAsString(QoreString& str, int foff, ExceptionSink* xsink) const {
206  str.sprintf("function closure (%slambda, in object of class '%s', %p)", closure->isLambda() ? "" : "non-", obj->getClassName(), this);
207  return 0;
208  }
209 
210  DLLLOCAL virtual QoreString* getAsString(bool& del, int foff, ExceptionSink* xsink) const {
211  del = true;
212  QoreString* rv = new QoreString;
213  getAsString(*rv, foff, xsink);
214  return rv;
215  }
216 
217  DLLLOCAL virtual const char* getTypeName() const {
218  return getStaticTypeName();
219  }
220 
221  DLLLOCAL bool isLambda() const { return closure->isLambda(); }
222 
223  DLLLOCAL virtual bool is_equal_soft(const AbstractQoreNode* v, ExceptionSink* xsink) const {
224  return QoreObjectClosureNode::is_equal_hard(v, xsink);
225  }
226 
227  DLLLOCAL virtual bool is_equal_hard(const AbstractQoreNode* v, ExceptionSink* xsink) const {
228  return v == this;
229  }
230 
231  DLLLOCAL virtual QoreObject* getObject() const {
232  return obj;
233  }
234 };
235 
236 #endif
DLLEXPORT void depRef()
incremements the weak reference count for the program object
DLLEXPORT int sprintf(const char *fmt,...)
this will concatentate a formatted string to the existing string according to the format string and t...
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:54
DLLEXPORT void tRef() const
increments the existence reference count
Qore&#39;s string type supported by the QoreEncoding class.
Definition: QoreString.h:81
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
const qore_type_t NT_RUNTIME_CLOSURE
type value for ResolvedCallReferenceNode (QoreClosureNode, QoreObjectClosureNode) ...
Definition: node_types.h:71
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only ...
Definition: QoreProgram.h:126
the implementation of Qore&#39;s object data type, reference counted, dynamically-allocated only ...
Definition: QoreObject.h:61
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:46
DLLEXPORT void ref() const
increments the reference count
base class for resolved call references
Definition: CallReferenceNode.h:105
DLLEXPORT QoreProgram * getProgram() const
returns the QoreProgram object associated with this object
DLLEXPORT const char * getClassName() const
returns the name of the class