loom

Форк
0
/
ScriptSemantics_callback.cpp 
208 строк · 10.1 Кб
1
/*
2
MIT License
3

4
Copyright (c) 2022 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
5

6
https://bmstu.codes/lsx/simodo/loom
7
*/
8

9
#include "ScriptSemantics_abstract.h"
10
#include "simodo/interpret/AnalyzeException.h"
11
#include "simodo/inout/format/fmt.h"
12

13
#include <cassert>
14

15
namespace simodo::interpret
16
{
17
    void ScriptSemantics_abstract::initiateCallbacks()
18
    {
19
        _cycle_condition_callback = 
20
                [this](const FlowLayerInfo & flow)
21
                {
22
                    if (flow.error_sign) {
23
                        stack().clearBoundary(_cycle_data_stack.back().boundary_index);
24
                        _cycle_data_stack.pop_back();
25
                        return;
26
                    }
27

28
                    name_index_t        condition_variable_index = stack().top();
29
                    variable::Variable  condition_variable       = stack().variable(condition_variable_index).origin();
30
                    bool                condition = false; 
31
                    
32
                    try
33
                    {
34
                        if (!condition_variable.value().isNull() && !condition_variable.value().isBool())
35
                            condition_variable = inter().expr().convertVariable(condition_variable, variable::ValueType::Bool);
36
                    }
37
                    catch(...)
38
                    {
39
                        stack().clearBoundary(_cycle_data_stack.back().boundary_index);
40
                        _cycle_data_stack.pop_back();
41
                        throw;
42
                    }
43
                    
44
                    if (condition_variable.value().isNull())
45
                        condition = false;
46
                    else if (condition_variable.value().isBool())
47
                        condition = condition_variable.value().getBool();
48
                    else
49
                        assert(false);
50

51
                    stack().pop();
52

53
                    if (condition || !checkInterpretType(InterpretType::Preview))
54
                        inter().addFlowLayer(*_cycle_data_stack.back().pop_body, _cycle_body_callback);
55
                    else {
56
                        stack().clearBoundary(_cycle_data_stack.back().boundary_index);
57
                        _cycle_data_stack.pop_back();
58
                    }
59
                };
60

61
        _cycle_body_callback =
62
                [this](const FlowLayerInfo & flow)
63
                {
64
                    if (flow.error_sign || !checkInterpretType(InterpretType::Preview)) {
65
                        stack().clearBoundary(_cycle_data_stack.back().boundary_index);
66
                        _cycle_data_stack.pop_back();
67
                        return;
68
                    }
69

70
                    inter().addFlowLayer(*_cycle_data_stack.back().pop_expression, _cycle_condition_callback);
71
                };
72

73
        _for_source_callback =
74
                [this](const FlowLayerInfo & flow)
75
                {
76
                    if (flow.error_sign) {
77
                        stack().clearBoundary(_cycle_data_stack.back().boundary_index);
78
                        _cycle_data_stack.pop_back();
79
                        return;
80
                    }
81

82
                    name_index_t source_index = stack().top();
83

84
                    _cycle_data_stack.back().source = stack().variable(source_index).origin();
85

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);
88

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__");
92

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);
96

97
                            boundary_index_t   boundary_index  = stack().startBoundary(BoundScope::Local, BOUNDARY_MARK_FUNCTION_FRAME);
98

99
                            stack().push(_cycle_data_stack.back().source);
100
                            inter().expr().callPreparedFunction(
101
                                    boundary_index, 
102
                                    notification(),
103
                                    true,
104
                                    _for_iterator_callback);
105
                            return;
106
                        }
107
                    }
108

109
                    if (prepareForVariableByCounter())
110
                        inter().addFlowLayer(*_cycle_data_stack.back().pop_body, _for_body_callback);
111
                };
112

113
        _for_body_callback =
114
                [this](const FlowLayerInfo & flow)
115
                {
116
                    if (flow.error_sign || !checkInterpretType(InterpretType::Preview)) {
117
                        stack().clearBoundary(_cycle_data_stack.back().boundary_index);
118
                        _cycle_data_stack.pop_back();
119
                        return;
120
                    }
121

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());
124

125
                    _cycle_data_stack.back().source_counter += 1;
126

127
                    if (prepareForVariableByCounter()) 
128
                        inter().addFlowLayer(*_cycle_data_stack.back().pop_body, _for_body_callback);
129
                };
130

131
        _for_iterator_callback =
132
                [this](const FlowLayerInfo & flow)
133
                {
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(); // функция итератора
139

140
                    if (flow.error_sign) {
141
                        stack().clearBoundary(_cycle_data_stack.back().boundary_index);
142
                        _cycle_data_stack.pop_back();
143
                        return;
144
                    }
145

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);
154

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();
159

160
                                    inter().addFlowLayer(*_cycle_data_stack.back().pop_body, _iterator_body_callback);
161
                                    return;
162
                                }
163
                                stack().clearBoundary(_cycle_data_stack.back().boundary_index);
164
                                _cycle_data_stack.pop_back();
165
                                return;
166
                            }
167
                        }
168
                    }
169

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();
172

173
                    stack().clearBoundary(_cycle_data_stack.back().boundary_index);
174
                    _cycle_data_stack.pop_back();
175

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]"));
180
                };
181

182
        _iterator_body_callback =
183
                [this](const FlowLayerInfo & flow)
184
                {
185
                    if (flow.error_sign || !checkInterpretType(InterpretType::Preview)) {
186
                        stack().clearBoundary(_cycle_data_stack.back().boundary_index);
187
                        _cycle_data_stack.pop_back();
188
                        return;
189
                    }
190

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());
193

194
                    stack().push(_cycle_data_stack.back().iterator);
195

196
                    boundary_index_t   boundary_index  = stack().startBoundary(BoundScope::Local, BOUNDARY_MARK_FUNCTION_FRAME);
197

198
                    stack().push(_cycle_data_stack.back().source);
199
                    inter().expr().callPreparedFunction(
200
                            boundary_index, 
201
                            notification(),
202
                            checkInterpretType(InterpretType::Preview) 
203
                            || _cycle_data_stack.back().iterator.origin().name().substr(0,2) == u"__",
204
                            _for_iterator_callback);
205
                };
206
    }
207

208
}
209

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.