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