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