4
Copyright (c) 2022 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
6
https://bmstu.codes/lsx/simodo/loom
9
#include "ScriptSemantics_abstract.h"
10
#include "simodo/interpret/AnalyzeException.h"
11
#include "simodo/inout/format/fmt.h"
15
namespace simodo::interpret
17
void ScriptSemantics_abstract::initiateCallbacks()
19
_cycle_condition_callback =
20
[this](const FlowLayerInfo & flow)
22
if (flow.error_sign) {
23
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
24
_cycle_data_stack.pop_back();
28
name_index_t condition_variable_index = stack().top();
29
variable::Variable condition_variable = stack().variable(condition_variable_index).origin();
30
bool condition = false;
34
if (!condition_variable.value().isNull() && !condition_variable.value().isBool())
35
condition_variable = inter().expr().convertVariable(condition_variable, variable::ValueType::Bool);
39
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
40
_cycle_data_stack.pop_back();
44
if (condition_variable.value().isNull())
46
else if (condition_variable.value().isBool())
47
condition = condition_variable.value().getBool();
53
if (condition || !checkInterpretType(InterpretType::Preview))
54
inter().addFlowLayer(*_cycle_data_stack.back().pop_body, _cycle_body_callback);
56
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
57
_cycle_data_stack.pop_back();
61
_cycle_body_callback =
62
[this](const FlowLayerInfo & flow)
64
if (flow.error_sign || !checkInterpretType(InterpretType::Preview)) {
65
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
66
_cycle_data_stack.pop_back();
70
inter().addFlowLayer(*_cycle_data_stack.back().pop_expression, _cycle_condition_callback);
73
_for_source_callback =
74
[this](const FlowLayerInfo & flow)
76
if (flow.error_sign) {
77
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
78
_cycle_data_stack.pop_back();
82
name_index_t source_index = stack().top();
84
_cycle_data_stack.back().source = stack().variable(source_index).origin();
86
if (!_cycle_data_stack.back().source.value().isArray() && !_cycle_data_stack.back().source.value().isObject())
87
_cycle_data_stack.back().source = inter().expr().convertVariable(_cycle_data_stack.back().source, variable::ValueType::Array);
89
if (_cycle_data_stack.back().source.type() == variable::ValueType::Object) {
90
std::shared_ptr<variable::Object> object = _cycle_data_stack.back().source.value().getObject();
91
const variable::Variable iterator = object->getVariableByName(u"__iterator__");
93
if (!iterator.name().empty() && iterator.type() == variable::ValueType::Function) {
94
_cycle_data_stack.back().iterator = iterator;
95
stack().push(_cycle_data_stack.back().iterator);
97
boundary_index_t boundary_index = stack().startBoundary(BoundScope::Local, BOUNDARY_MARK_FUNCTION_FRAME);
99
stack().push(_cycle_data_stack.back().source);
100
inter().expr().callPreparedFunction(
104
_for_iterator_callback);
109
if (prepareForVariableByCounter())
110
inter().addFlowLayer(*_cycle_data_stack.back().pop_body, _for_body_callback);
114
[this](const FlowLayerInfo & flow)
116
if (flow.error_sign || !checkInterpretType(InterpretType::Preview)) {
117
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
118
_cycle_data_stack.pop_back();
122
assert(_cycle_data_stack.back().source.value().isArray() || _cycle_data_stack.back().source.value().isObject());
123
assert(_cycle_data_stack.back().iterator.value().isNull());
125
_cycle_data_stack.back().source_counter += 1;
127
if (prepareForVariableByCounter())
128
inter().addFlowLayer(*_cycle_data_stack.back().pop_body, _for_body_callback);
131
_for_iterator_callback =
132
[this](const FlowLayerInfo & flow)
134
// Завершаем обработку функции итератора после оператора return
135
boundary_index_t function_boundary = stack().findNearestMarkedBoundary(BOUNDARY_MARK_FUNCTION_FRAME,BoundScope::Global);
136
assert(function_boundary != UNDEFINED_BOUNDARY_INDEX);
137
stack().clearBoundary(function_boundary);
138
stack().pop(); // функция итератора
140
if (flow.error_sign) {
141
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
142
_cycle_data_stack.pop_back();
146
// Обработка возврата итератора
147
if (inter().expr().return_value().isArray()) {
148
std::shared_ptr<variable::Array> iterator_pair = inter().expr().return_value().getArray();
149
if (iterator_pair->values().size() >= 2) {
150
const variable::Value & condition_value = iterator_pair->values()[1];
151
if (condition_value.isBool()) {
152
if (condition_value.getBool() == true) {
153
variable::Variable & variable = stack().variable(_cycle_data_stack.back().variable_index);
155
variable.setValue(iterator_pair->values()[0]);
156
if (!_cycle_data_stack.back().typed_variable.value().isNull()
157
&& _cycle_data_stack.back().typed_variable.type() != variable.value().type())
158
variable.value() = inter().expr().convertVariable(variable, _cycle_data_stack.back().typed_variable.type()).value();
160
inter().addFlowLayer(*_cycle_data_stack.back().pop_body, _iterator_body_callback);
163
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
164
_cycle_data_stack.pop_back();
170
assert(_cycle_data_stack.back().pop_source && !_cycle_data_stack.back().pop_source->branches().empty());
171
inout::TokenLocation loc = _cycle_data_stack.back().pop_source->branches().front().token().location();
173
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
174
_cycle_data_stack.pop_back();
176
throw AnalyzeException("ScriptSemantics_abstract::_for_iterator_callback",
177
loc.makeLocation(inter().files()),
178
inout::fmt("The iterator of the iteration should return values in the form of "
179
"a vector in the format: [value, bool : condition]"));
182
_iterator_body_callback =
183
[this](const FlowLayerInfo & flow)
185
if (flow.error_sign || !checkInterpretType(InterpretType::Preview)) {
186
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
187
_cycle_data_stack.pop_back();
191
assert(_cycle_data_stack.back().source.value().isArray() || _cycle_data_stack.back().source.value().isObject());
192
assert(!_cycle_data_stack.back().iterator.value().isNull());
194
stack().push(_cycle_data_stack.back().iterator);
196
boundary_index_t boundary_index = stack().startBoundary(BoundScope::Local, BOUNDARY_MARK_FUNCTION_FRAME);
198
stack().push(_cycle_data_stack.back().source);
199
inter().expr().callPreparedFunction(
202
checkInterpretType(InterpretType::Preview)
203
|| _cycle_data_stack.back().iterator.origin().name().substr(0,2) == u"__",
204
_for_iterator_callback);