Qore Programming Language 1.19.1
Loading...
Searching...
No Matches
StatementBlock.h
1/* -*- mode: c++; indent-tabs-mode: nil -*- */
2/*
3 StatementBlock.h
4
5 Qore Programming Language
6
7 Copyright (C) 2003 - 2023 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
44class BCAList;
45class BCList;
46
47class LVList {
48public:
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 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
84class LVListInstantiator {
85 const LVList* l;
86 ExceptionSink* xsink;
87
88public:
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],
94 // l->lv[i]->getName());
95 l->lv[i]->instantiate();
96 }
97 }
98
99 DLLLOCAL ~LVListInstantiator() {
100 if (!l) return;
101 for (int i = (int)l->size() - 1; i >= 0; --i) {
102 //printd(5, "LVListInstantiator::~LVListInstantiator() this: %p v: %p %s\n", this, l->lv[i],
103 // l->lv[i]->getName());
104 l->lv[i]->uninstantiate(xsink);
105 }
106 }
107};
108
109// forward declaration
110class qore_program_private_base;
111
112class StatementBlock : public AbstractStatement {
113public:
114 DLLLOCAL StatementBlock(int sline, int eline);
115
116 // line numbers on statement blocks are set later
117 DLLLOCAL StatementBlock(int sline, int eline, AbstractStatement* s);
118
119 DLLLOCAL virtual ~StatementBlock() {
120 del();
121 }
122
123 DLLLOCAL virtual int execImpl(QoreValue& return_value, ExceptionSink* xsink);
124 DLLLOCAL virtual int parseInitImpl(QoreParseContext& parse_context);
125
126 DLLLOCAL void del();
127
128 DLLLOCAL void addStatement(AbstractStatement* s);
129
130 using AbstractStatement::exec;
131 DLLLOCAL QoreValue exec(ExceptionSink* xsink);
132
133 using AbstractStatement::parseInit;
134 DLLLOCAL int parseInit(UserVariantBase* uvb);
135
136 // initialize methods
137 DLLLOCAL int parseInitMethod(const QoreTypeInfo* typeInfo, UserVariantBase* uvb);
138 DLLLOCAL int parseInitConstructor(const QoreTypeInfo* typeInfo, UserVariantBase* uvb, BCAList* bcal,
139 const QoreClass& cls);
140
141 // initialize closure blocks
142 DLLLOCAL int parseInitClosure(UserVariantBase* uvb, UserClosureFunction* cf);
143
144 DLLLOCAL virtual void parseCommit(QoreProgram* pgm);
145
146 DLLLOCAL void exec();
147
148 DLLLOCAL const LVList* getLVList() const {
149 return lvars;
150 }
151
152 DLLLOCAL virtual bool hasFinalReturn() const {
153 if (statement_list.empty())
154 return false;
155
156 return (*statement_list.last())->hasFinalReturn();
157 }
158
159 DLLLOCAL void setupLVList(QoreParseContext& parse_context) {
160 assert(!lvars);
161 if (!parse_context.lvids) {
162 return;
163 }
164
165 lvars = new LVList(parse_context.lvids);
166 parse_context.lvids = 0;
167 }
168
169protected:
170 typedef safe_dslist<AbstractStatement*> statement_list_t;
171 statement_list_t statement_list;
172 block_list_t on_block_exit_list;
173 LVList* lvars = nullptr;
174
175 // start must be the element before the start position
176 DLLLOCAL int parseInitIntern(QoreParseContext& parse_context, statement_list_t::iterator start);
177 DLLLOCAL void parseCommitIntern(statement_list_t::iterator start);
178 DLLLOCAL bool hasLastReturn(AbstractStatement* as);
179 DLLLOCAL int parseCheckReturn();
180
181 DLLLOCAL int execIntern(QoreValue& return_value, ExceptionSink* xsink);
182
183 DLLLOCAL StatementBlock(qore_program_private_base* p);
184};
185
186class TopLevelStatementBlock : public StatementBlock {
187public:
188 DLLLOCAL TopLevelStatementBlock(qore_program_private_base* p) : StatementBlock(p), hwm(statement_list.end()),
189 first(true) {
190 }
191
192 DLLLOCAL virtual ~TopLevelStatementBlock() {
193 }
194
195 using StatementBlock::parseInit;
196 DLLLOCAL int 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(QoreParseContext& parse_context) {
224 if (!parse_context.lvids) {
225 return;
226 }
227
228 if (lvars) {
229 lvars->add(parse_context.lvids);
230 } else {
231 lvars = new LVList(parse_context.lvids);
232 }
233 parse_context.lvids = 0;
234 }
235
236protected:
237 // iterator to last commit element in statement list
238 statement_list_t::iterator hwm;
239 // true only the first time parseInit() is called
240 bool first;
241};
242
243// parse variable stack
244class VNode {
245public:
246 LocalVar* lvar;
247 VNode* next;
248
249 DLLLOCAL VNode(LocalVar* lv, const QoreProgramLocation* n_loc = nullptr, int n_refs = 0,
250 bool n_top_level = false);
251
252 DLLLOCAL ~VNode();
253
254 DLLLOCAL void appendLocation(QoreString& str);
255
256 DLLLOCAL void setRef() {
257 ++refs;
258 }
259
260 DLLLOCAL bool setBlockStart(bool bs = true) {
261 bool rc = block_start;
262 block_start = bs;
263 return rc;
264 }
265
266 DLLLOCAL bool isBlockStart() const {
267 return block_start;
268 }
269
270 DLLLOCAL bool isReferenced() const {
271 return refs;
272 }
273
274 DLLLOCAL int refCount() const {
275 return refs;
276 }
277
278 DLLLOCAL bool isTopLevel() const {
279 return top_level;
280 }
281
282 DLLLOCAL const char* getName() const;
283
284 // searches to marker and then jumps to global thread-local variables
285 DLLLOCAL VNode* nextSearch() const;
286
287protected:
288 // # of times this variable is referenced in code
289 int refs;
290
291 // to store parse location in case of errors
292 const QoreProgramLocation* loc;
293 bool block_start;
294 bool top_level;
295};
296
297class CatchExceptionHelper {
298private:
299 QoreException* e;
300
301public:
302 DLLLOCAL CatchExceptionHelper(QoreException* n_e) : e(catch_swap_exception(n_e)) {
303 }
304
305 DLLLOCAL ~CatchExceptionHelper() {
306 catch_swap_exception(e);
307 }
308};
309
310#endif // _QORE_STATEMENT_BLOCK_H
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:253
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:128
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:276