Qore Programming Language  0.9.16
StatementBlock.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  StatementBlock.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2019 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_STATEMENT_BLOCK_H
33 
34 #define _QORE_STATEMENT_BLOCK_H
35 
36 #include "qore/intern/AbstractStatement.h"
37 #include <qore/safe_dslist>
38 
39 #include <set>
40 #include <vector>
41 #include <typeinfo>
42 
43 // all definitions in this file are private to the library and subject to change
44 class BCAList;
45 class BCList;
46 
47 class LVList {
48 public:
49  typedef std::vector<LocalVar*> lv_vec_t;
50  lv_vec_t lv;
51 
52  DLLLOCAL LVList(int num) {
53  add(num);
54  }
55 
56  DLLLOCAL LVList(const LVList& old) {
57  lv.resize(old.size());
58  for (unsigned i = 0; i < old.size(); ++i)
59  lv[i] = old.lv[i];
60 
61  //printd(5, "LVList::LVList() populated with %d vars\n", lv.size());
62  }
63 
64  DLLLOCAL ~LVList() {
65  }
66 
67  DLLLOCAL qore_size_t size() const {
68  return lv.size();
69  }
70 
71  DLLLOCAL void add(int num) {
72  assert(num > 0);
73  unsigned start = lv.size();
74  //printd(5, "LVList::add(num: %d) this: %p start: %d\n", num, this, start);
75  lv.resize(start + num);
76  // pop variables off stack and save in reverse order
77  for (int i = (int)(start + num - 1); i >= (int)start; --i) {
78  lv[i] = pop_local_var();
79  //printd(5, "LVList::add() %d = %p: %s\n", i, lv[i], lv[i]->getName());
80  }
81  }
82 };
83 
84 class LVListInstantiator {
85  const LVList* l;
86  ExceptionSink* xsink;
87 
88 public:
89  DLLLOCAL LVListInstantiator(const LVList* l, ExceptionSink* xs) : l(l) {
90  if (!l) return;
91  xsink = xs;
92  for (unsigned i = 0; i < l->size(); ++i) {
93  //printd(5, "LVListInstantiator::LVListInstantiator() this: %p v: %p %s\n", this, l->lv[i], l->lv[i]->getName());
94  l->lv[i]->instantiate();
95  }
96  }
97 
98  DLLLOCAL ~LVListInstantiator() {
99  if (!l) return;
100  for (int i = (int)l->size() - 1; i >= 0; --i) {
101  //printd(5, "LVListInstantiator::~LVListInstantiator() this: %p v: %p %s\n", this, l->lv[i], l->lv[i]->getName());
102  l->lv[i]->uninstantiate(xsink);
103  }
104  }
105 };
106 
107 // forward declaration
108 class qore_program_private_base;
109 
110 class StatementBlock : public AbstractStatement {
111 protected:
112  typedef safe_dslist<AbstractStatement*> statement_list_t;
113  statement_list_t statement_list;
114  block_list_t on_block_exit_list;
115  LVList* lvars = nullptr;
116 
117  // start must be the element before the start position
118  DLLLOCAL int parseInitIntern(LocalVar* oflag, int pflag, statement_list_t::iterator start);
119  DLLLOCAL void parseCommitIntern(statement_list_t::iterator start);
120  DLLLOCAL bool hasLastReturn(AbstractStatement* as);
121  DLLLOCAL void parseCheckReturn();
122 
123  DLLLOCAL int execIntern(QoreValue& return_value, ExceptionSink* xsink);
124 
125  DLLLOCAL StatementBlock(qore_program_private_base* p);
126 
127 public:
128  DLLLOCAL StatementBlock(int sline, int eline);
129 
130  // line numbers on statement blocks are set later
131  DLLLOCAL StatementBlock(int sline, int eline, AbstractStatement* s);
132 
133  DLLLOCAL virtual ~StatementBlock() {
134  del();
135  }
136 
137  DLLLOCAL virtual int execImpl(QoreValue& return_value, ExceptionSink* xsink);
138  DLLLOCAL virtual int parseInitImpl(LocalVar* oflag, int pflag = 0);
139 
140  DLLLOCAL void del();
141 
142  DLLLOCAL void addStatement(AbstractStatement* s);
143 
144  using AbstractStatement::exec;
145  DLLLOCAL QoreValue exec(ExceptionSink* xsink);
146 
147  using AbstractStatement::parseInit;
148  DLLLOCAL void parseInit(UserVariantBase* uvb);
149 
150  // initialize methods
151  DLLLOCAL void parseInitMethod(const QoreTypeInfo* typeInfo, UserVariantBase* uvb);
152  DLLLOCAL void parseInitConstructor(const QoreTypeInfo* typeInfo, UserVariantBase* uvb, BCAList* bcal, const QoreClass& cls);
153 
154  // initialize closure blocks
155  DLLLOCAL void parseInitClosure(UserVariantBase* uvb, UserClosureFunction* cf);
156 
157  DLLLOCAL virtual void parseCommit(QoreProgram* pgm);
158 
159  DLLLOCAL void exec();
160 
161  DLLLOCAL const LVList* getLVList() const {
162  return lvars;
163  }
164 
165  DLLLOCAL virtual bool hasFinalReturn() const {
166  if (statement_list.empty())
167  return false;
168 
169  return (*statement_list.last())->hasFinalReturn();
170  }
171 
172  DLLLOCAL void setupLVList(int lvids) {
173  assert(!lvars);
174  if (!lvids)
175  return;
176 
177  lvars = new LVList(lvids);
178  }
179 };
180 
181 class TopLevelStatementBlock : public StatementBlock {
182 protected:
183  // iterator to last commit element in statement list
184  statement_list_t::iterator hwm;
185  // true only the first time parseInit() is called
186  bool first;
187 
188 public:
189  DLLLOCAL TopLevelStatementBlock(qore_program_private_base* p) : StatementBlock(p), hwm(statement_list.end()), first(true) {
190  }
191 
192  DLLLOCAL virtual ~TopLevelStatementBlock() {
193  }
194 
195  using StatementBlock::parseInit;
196  DLLLOCAL void parseInit();
197 
198  DLLLOCAL virtual void parseCommit(QoreProgram* pgm);
199 
200  DLLLOCAL void parseRollback() {
201  // delete all statements after the high water mark (hwm) to the end of the list
202  statement_list_t::iterator start = hwm;
203  if (start != statement_list.end())
204  ++start;
205  else
206  start = statement_list.begin();
207 
208  for (statement_list_t::iterator i = start, e = statement_list.end(); i != e; ++i)
209  delete *i;
210 
211  statement_list.erase_to_end(hwm);
212  }
213 
214  // local vars are not instantiated here because they are instantiated by the QoreProgram object
215  DLLLOCAL virtual int execImpl(QoreValue& return_value, ExceptionSink* xsink);
216 
217  // assign inherited local var list from parent program
218  DLLLOCAL void assignLocalVars(const LVList* lvl) {
219  assert(!lvars);
220  lvars = new LVList(*lvl);
221  }
222 
223  DLLLOCAL void setupLVList(int lvids) {
224  if (!lvids)
225  return;
226 
227  if (lvars)
228  lvars->add(lvids);
229  else
230  lvars = new LVList(lvids);
231  }
232 };
233 
234 // parse variable stack
235 class VNode {
236 public:
237  LocalVar* lvar;
238  VNode* next;
239 
240  DLLLOCAL VNode(LocalVar* lv, const QoreProgramLocation* n_loc = nullptr, int n_refs = 0,
241  bool n_top_level = false);
242 
243  DLLLOCAL ~VNode();
244 
245  DLLLOCAL void appendLocation(QoreString& str);
246 
247  DLLLOCAL void setRef() {
248  ++refs;
249  }
250 
251  DLLLOCAL bool setBlockStart(bool bs = true) {
252  bool rc = block_start;
253  block_start = bs;
254  return rc;
255  }
256 
257  DLLLOCAL bool isBlockStart() const {
258  return block_start;
259  }
260 
261  DLLLOCAL bool isReferenced() const {
262  return refs;
263  }
264 
265  DLLLOCAL int refCount() const {
266  return refs;
267  }
268 
269  DLLLOCAL bool isTopLevel() const {
270  return top_level;
271  }
272 
273  DLLLOCAL const char* getName() const;
274 
275  // searches to marker and then jumps to global thread-local variables
276  DLLLOCAL VNode* nextSearch() const;
277 
278 protected:
279  // # of times this variable is referenced in code
280  int refs;
281 
282  // to store parse location in case of errors
283  const QoreProgramLocation* loc;
284  bool block_start;
285  bool top_level;
286 };
287 
288 #endif // _QORE_STATEMENT_BLOCK_H
QoreProgram
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:126
QoreValue
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
QoreClass
defines a Qore-language class
Definition: QoreClass.h:239
qore_size_t
size_t qore_size_t
used for sizes (same range as a pointer)
Definition: common.h:73
QoreString
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48