loom

Форк
0
/
ScriptSemantics_abstract.cpp 
369 строк · 18.8 Кб
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/interpret/StackOfNames.h"
12
#include "simodo/variable/FunctionWrapper.h"
13
#include "simodo/bormental/DrBormental.h"
14
#include "simodo/inout/convert/functions.h"
15
#include "simodo/inout/format/fmt.h"
16

17
#include <functional>
18
#include <iterator>
19
#include <cassert>
20

21
#ifndef NDEBUG
22
#define DEBUG
23
#endif
24

25
#ifdef DEBUG
26
    #include "simodo/interpret/Interpret.h"
27
#endif
28

29
#if __cplusplus >= __cpp_2017
30
#include <filesystem>
31
namespace fs = std::filesystem;
32
#else
33
#include <experimental/filesystem>
34
namespace fs = std::filesystem::experimental;
35
#endif
36

37
namespace simodo::interpret
38
{
39
    namespace 
40
    {
41
        void initializeOperationSwitchboard(std::vector<OperationParser_t> & switchboard)
42
        {
43
            switchboard.resize(static_cast<size_t>(ScriptOperationCode::LastOperation), nullptr);
44

45
            switchboard[static_cast<size_t>(ScriptOperationCode::None)]           = OperationParser::parseNone;
46
            switchboard[static_cast<size_t>(ScriptOperationCode::PushConstant)]   = OperationParser::parsePushConstant;
47
            switchboard[static_cast<size_t>(ScriptOperationCode::PushVariable)]   = OperationParser::parsePushVariable;
48
            switchboard[static_cast<size_t>(ScriptOperationCode::ObjectElement)]  = OperationParser::parseObjectElement;
49
            switchboard[static_cast<size_t>(ScriptOperationCode::FunctionCall)]   = OperationParser::parseFunctionCall;
50
            switchboard[static_cast<size_t>(ScriptOperationCode::ProcedureCheck)] = OperationParser::parseProcedureCheck;
51
            switchboard[static_cast<size_t>(ScriptOperationCode::Print)]          = OperationParser::parsePrint;
52
            switchboard[static_cast<size_t>(ScriptOperationCode::Block)]          = OperationParser::parseBlock;
53
            switchboard[static_cast<size_t>(ScriptOperationCode::Pop)]            = OperationParser::parsePop;
54

55
            switchboard[static_cast<size_t>(ScriptOperationCode::Reference)]      = OperationParser::parseReference;
56
            switchboard[static_cast<size_t>(ScriptOperationCode::ArrayElement)]   = OperationParser::parseArrayElement;
57

58
            switchboard[static_cast<size_t>(ScriptOperationCode::ObjectStructure)]  = OperationParser::parseRecordStructure;
59
            switchboard[static_cast<size_t>(ScriptOperationCode::ArrayStructure)]   = OperationParser::parseArrayStructure;
60
            switchboard[static_cast<size_t>(ScriptOperationCode::Import)]           = OperationParser::parseImport;
61
            switchboard[static_cast<size_t>(ScriptOperationCode::Contract)]         = OperationParser::parseContractDefinition;
62
            switchboard[static_cast<size_t>(ScriptOperationCode::Type)]             = OperationParser::parseContractDefinition;
63
            switchboard[static_cast<size_t>(ScriptOperationCode::Announcement)]     = OperationParser::parseAnnouncement;
64
            switchboard[static_cast<size_t>(ScriptOperationCode::Declaration)]      = OperationParser::parseDeclaration;
65
            switchboard[static_cast<size_t>(ScriptOperationCode::DeclarationOnce)]  = OperationParser::parseDeclarationOnce;
66
            switchboard[static_cast<size_t>(ScriptOperationCode::Announcements_Completed)]= OperationParser::parseDeclarationCompletion;
67
            switchboard[static_cast<size_t>(ScriptOperationCode::PostInitialize)]   = OperationParser::parsePostAssignment;
68
            
69
            switchboard[static_cast<size_t>(ScriptOperationCode::Initialize)]         = OperationParser::parseAssignment;
70
            switchboard[static_cast<size_t>(ScriptOperationCode::Assignment)]         = OperationParser::parseAssignment;
71

72
            switchboard[static_cast<size_t>(ScriptOperationCode::AssignmentAddition)] = OperationParser::parseAssignment;
73
            switchboard[static_cast<size_t>(ScriptOperationCode::AssignmentSubtraction)]= OperationParser::parseAssignment;
74
            switchboard[static_cast<size_t>(ScriptOperationCode::AssignmentMultiplication)]= OperationParser::parseAssignment;
75
            switchboard[static_cast<size_t>(ScriptOperationCode::AssignmentDivision)] = OperationParser::parseAssignment;
76
            switchboard[static_cast<size_t>(ScriptOperationCode::AssignmentModulo)]   = OperationParser::parseAssignment;
77

78
            switchboard[static_cast<size_t>(ScriptOperationCode::Plus)]           = OperationParser::parseUnary;
79
            switchboard[static_cast<size_t>(ScriptOperationCode::Minus)]          = OperationParser::parseUnary;
80
            switchboard[static_cast<size_t>(ScriptOperationCode::Not)]            = OperationParser::parseUnary;
81

82
            switchboard[static_cast<size_t>(ScriptOperationCode::Or)]             = OperationParser::parseLogical;
83
            switchboard[static_cast<size_t>(ScriptOperationCode::And)]            = OperationParser::parseLogical;
84

85
            switchboard[static_cast<size_t>(ScriptOperationCode::Equal)]          = OperationParser::parseCompare;
86
            switchboard[static_cast<size_t>(ScriptOperationCode::NotEqual)]       = OperationParser::parseCompare;
87
            switchboard[static_cast<size_t>(ScriptOperationCode::Less)]           = OperationParser::parseCompare;
88
            switchboard[static_cast<size_t>(ScriptOperationCode::LessOrEqual)]    = OperationParser::parseCompare;
89
            switchboard[static_cast<size_t>(ScriptOperationCode::More)]           = OperationParser::parseCompare;
90
            switchboard[static_cast<size_t>(ScriptOperationCode::MoreOrEqual)]    = OperationParser::parseCompare;
91

92
            switchboard[static_cast<size_t>(ScriptOperationCode::Addition)]       = OperationParser::parseArithmetic;
93
            switchboard[static_cast<size_t>(ScriptOperationCode::Subtraction)]    = OperationParser::parseArithmetic;
94
            switchboard[static_cast<size_t>(ScriptOperationCode::Multiplication)] = OperationParser::parseArithmetic;
95
            switchboard[static_cast<size_t>(ScriptOperationCode::Division)]       = OperationParser::parseArithmetic;
96
            switchboard[static_cast<size_t>(ScriptOperationCode::Modulo)]         = OperationParser::parseArithmetic;
97
            switchboard[static_cast<size_t>(ScriptOperationCode::Power)]          = OperationParser::parseArithmetic;
98

99
            switchboard[static_cast<size_t>(ScriptOperationCode::Ternary)]        = OperationParser::parseConditional;
100
            switchboard[static_cast<size_t>(ScriptOperationCode::If)]             = OperationParser::parseConditional;
101

102
            switchboard[static_cast<size_t>(ScriptOperationCode::FunctionDefinition)]= OperationParser::parseFunctionDefinition;
103
            switchboard[static_cast<size_t>(ScriptOperationCode::FunctionDefinitionEnd)]= OperationParser::parseFunctionDefinitionEnd;
104
            switchboard[static_cast<size_t>(ScriptOperationCode::FunctionTethered)]= OperationParser::parseFunctionTethered;
105

106
            switchboard[static_cast<size_t>(ScriptOperationCode::Return)]         = OperationParser::parseReturn;
107
            switchboard[static_cast<size_t>(ScriptOperationCode::ReturnExpression)]= OperationParser::parseReturn;
108

109
            switchboard[static_cast<size_t>(ScriptOperationCode::For)]            = OperationParser::parseFor;
110
            switchboard[static_cast<size_t>(ScriptOperationCode::While)]          = OperationParser::parseWhile;
111
            switchboard[static_cast<size_t>(ScriptOperationCode::DoWhile)]        = OperationParser::parseDoWhile;
112
            switchboard[static_cast<size_t>(ScriptOperationCode::Break)]          = OperationParser::parseBreak;
113
            switchboard[static_cast<size_t>(ScriptOperationCode::Continue)]       = OperationParser::parseContinue;
114

115
            switchboard[static_cast<size_t>(ScriptOperationCode::Apply)]        = OperationParser::parseCommon;
116
            switchboard[static_cast<size_t>(ScriptOperationCode::Using)]        = OperationParser::parseUsing;
117
            switchboard[static_cast<size_t>(ScriptOperationCode::AutoDeclaration)]= OperationParser::parseDeclaration;
118
            switchboard[static_cast<size_t>(ScriptOperationCode::CheckState)]   = OperationParser::parseCheckState;
119
            switchboard[static_cast<size_t>(ScriptOperationCode::ArrayPush)]    = OperationParser::parseArrayPush;
120
            switchboard[static_cast<size_t>(ScriptOperationCode::ArrayPop)]     = OperationParser::parseArrayPop;
121

122
            switchboard[static_cast<size_t>(ScriptOperationCode::FiberMake)]    = OperationParser::parseFiberOperations;
123
            switchboard[static_cast<size_t>(ScriptOperationCode::FiberFlow)]    = OperationParser::parseFiberOperations;
124
            switchboard[static_cast<size_t>(ScriptOperationCode::FiberWait)]    = OperationParser::parseFiberOperations;
125
            switchboard[static_cast<size_t>(ScriptOperationCode::FiberPush)]    = OperationParser::parseFiberOperations;
126
            switchboard[static_cast<size_t>(ScriptOperationCode::FiberPull)]    = OperationParser::parseFiberOperations;
127
            // switchboard[static_cast<size_t>(ScriptOperationCode::FiberCut)]     = OperationParser::parseFiberOperations;
128
        }
129

130
    }
131

132
    ScriptSemantics_abstract::ScriptSemantics_abstract(ModuleManagement_interface & module_management)
133
        : _module_management(module_management)
134
    {
135
        initializeOperationSwitchboard(_operation_switchboard);
136
        initiateCallbacks();
137
    }
138

139
    ScriptSemantics_abstract::~ScriptSemantics_abstract()
140
    {
141
    }
142

143
    void ScriptSemantics_abstract::reset()
144
    {
145
    }
146

147
    InterpretState ScriptSemantics_abstract::before_start() 
148
    { 
149
        return InterpretState::Flow; 
150
    }
151

152
    InterpretState ScriptSemantics_abstract::before_finish(InterpretState state) 
153
    { 
154
        return state; 
155
    }
156

157
    bool ScriptSemantics_abstract::isOperationExists(ast::OperationCode operation_code) const
158
    {
159
        size_t operation_index = static_cast<size_t>(operation_code);
160

161
        return operation_index < _operation_switchboard.size() 
162
            && _operation_switchboard[operation_index] != nullptr;
163
    }
164

165
    InterpretState ScriptSemantics_abstract::performOperation(const ast::Node & op) 
166
    {
167
        if (!isOperationExists(op.operation()))
168
            throw bormental::DrBormental("ScriptSemantics_abstract::performOperation", 
169
                                inout::fmt("Invalid operation index %1")
170
                                    .arg(op.operation()));
171

172
        return _operation_switchboard[static_cast<size_t>(op.operation())](*this,op);
173
    }
174

175
    std::string ScriptSemantics_abstract::makeModulePath(const inout::Token & path, const std::string & parent_path)
176
    {
177
        if (path.type() != inout::LexemeType::Annotation)
178
            return inout::toU8(path.lexeme());
179

180
        if (path.lexeme().substr(0,2) == u"//") {
181
            // Модули из установки SIMODO
182
            std::string path_string = _module_management.simodo_root_path()
183
                                    + "/data/modules/" + inout::toU8(path.lexeme().substr(2));
184
            return fs::path(path_string).lexically_normal().string();
185
        }
186

187
        if (path.lexeme()[0] == u'/')
188
            // Модули из рабочего каталога
189
            return fs::current_path().concat(path.lexeme()).lexically_normal().string();
190

191
        // Модули по относительному к текущему модулю пути
192
        return fs::path(parent_path).parent_path().append(path.lexeme()).lexically_normal().string();
193
    }
194

195
    bool ScriptSemantics_abstract::prepareForVariableByCounter()
196
    {
197
        ExecuteCycle_data & data = _cycle_data_stack.back();
198

199
        assert(data.variable_index == stack().top() - 1);
200
        assert(data.source.value().isArray() || data.source.value().isObject());
201

202
        variable::index_t counter = data.source_counter;
203

204
        if ((data.source.value().isArray() && counter  >= data.source.value().getArray()->values().size())
205
         || (data.source.value().isObject() && counter >= data.source.value().getObject()->variables().size()))
206
        {
207
            if (!checkInterpretType(InterpretType::Preview))
208
                return true;
209

210
            stack().clearBoundary(data.boundary_index);
211
            _cycle_data_stack.pop_back();
212
            return false;
213
        }
214

215
        variable::Variable & for_variable = stack().variable(data.variable_index);
216

217
        if (data.source.value().isArray())
218
            for_variable.setValue(data.source.value().getArray()->getRefByIndex({counter}));
219
        else if (data.source.value().isObject()) {
220
            std::shared_ptr<variable::Object> object = data.source.value().getObject();
221
            variable::Variable &              source = object->getVariableByIndex_mutable(counter);
222
            
223
            for_variable.setValue(source.makeReference());
224
        }
225
        else
226
            assert(false);
227

228
        try
229
        {
230
            if (!data.typed_variable.value().isNull()
231
             && for_variable.type() != data.typed_variable.type()) {
232
                variable::Variable source = inter().expr().convertVariable(for_variable, data.typed_variable.type());
233

234
                for_variable.setValue(source.value());
235
            }
236
        }
237
        catch(...)
238
        {
239
            stack().clearBoundary(data.boundary_index);
240
            _cycle_data_stack.pop_back();
241
            throw;
242
        }
243
        
244
        return true;
245
    }
246

247
    bool ScriptSemantics_abstract::hidden(const variable::Variable & var)
248
    {
249
        const variable::Value & hidden_value = var.spec().object()->find(variable::SPEC_HIDDEN);
250

251
        return hidden_value.isBool() && hidden_value.getBool();
252
    }
253

254
    bool ScriptSemantics_abstract::tethered(const variable::Variable & var)
255
    {
256
        const variable::Value & tethered_value = var.spec().object()->find(variable::SPEC_TETHERED);
257

258
        return tethered_value.isBool() && tethered_value.getBool();
259
    }
260

261
    variable::Variable & ScriptSemantics_abstract::prepareFiberVariableOrigin()
262
    {
263
        variable::Variable & fiber_variable_ref     = stack().variable(stack().top());
264
        variable::Variable & fiber_variable_origin  = fiber_variable_ref.origin();
265
        std::string          object_name_text       = fiber_variable_ref.name().empty()
266
                                                    ? inout::toU8(fiber_variable_origin.name()) 
267
                                                    : inout::toU8(fiber_variable_ref.name());
268

269
        if (!object_name_text.empty())
270
            object_name_text = " '" + object_name_text + "'";
271

272
        if (!fiber_variable_origin.value().isObject())
273
            throw AnalyzeException( "ScriptSemantics_abstract::executeFiberWait", 
274
                                    fiber_variable_ref.location().makeLocation(inter().files()), 
275
                                    inout::fmt("Only a variable with an object type can act as a fiber"));
276

277
        std::shared_ptr<variable::Object> object = fiber_variable_origin.value().getObject();
278

279
        const ChildFlowInfo * p_info = inter().parallelize().findChildFlowInfo(fiber_variable_origin);
280
        if (checkInterpretType(InterpretType::Preview) && !p_info)
281
            throw AnalyzeException( "ScriptSemantics_abstract::executeFiberWait", 
282
                                    fiber_variable_ref.location().makeLocation(inter().files()), 
283
                                    inout::fmt("Object %1 have not fiber")
284
                                        .arg(object_name_text));
285

286
        return fiber_variable_origin;
287
    }    
288

289
    variable::Variable ScriptSemantics_abstract::prepareVariableByToken(const inout::Token & token)
290
    {
291
#ifdef DEBUG
292
        [[maybe_unused]] const Interpret * p_inter = static_cast<const Interpret *>(&inter());
293
#endif
294
        const variable::Variable & var = stack().findVariable(token.lexeme());
295

296
        if (!var.name().empty()) {
297
            if (var.type() == variable::ValueType::Ref)
298
                return {var.name(), var.value().getRef(), token.location()};
299
            else
300
                return {{}, var.makeReference(), token.location()};
301
        }
302

303
        const variable::Variable &        function       = inter().expr().getContextFunction();
304
        std::shared_ptr<variable::Object> self_object    = function.value().getInternalParent();
305
        const variable::Value &           tethered_value = function.spec().object()->find(variable::SPEC_TETHERED);
306
        bool                              tethered       = tethered_value.isBool() && tethered_value.getBool();
307
        
308
        if (self_object && tethered) {
309
            const variable::Variable & var = self_object->getVariableByName(token.lexeme());
310

311
            if (!var.name().empty())
312
                return {{}, var.makeReference(), token.location()};
313
        }
314

315
        if (token.lexeme() == SELF_VARIABLE_NAME) {
316
            variable::Variable self;
317

318
            if (self_object)
319
                self = {SELF_VARIABLE_NAME, self_object, token.location(), 
320
                        variable::VariableSet_t {{{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_MODULE}}}};
321
            else
322
                self = {SELF_VARIABLE_NAME, inter().expr().makeSelf(), token.location(), 
323
                        variable::VariableSet_t {{{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_MODULE}}}};
324

325
            return self;
326
        }
327

328
        static variable::Variable null;
329
        return null;
330
    }
331

332
    variable::Variable ScriptSemantics_abstract::makeSuperElement(const variable::Variable & var, const inout::Token & token) const
333
    {
334
        if (token.lexeme() == u"spec") {
335
            std::shared_ptr<variable::Object> object  = var.spec().object();
336
            return {token.lexeme(), object, token.location()};
337
        }
338
        else if (token.lexeme() == u"origin_name") {
339
            return {token.lexeme(), var.name(), token.location()};
340
        }
341
        else if (token.lexeme() == u"size") {
342
            switch(var.type()) {
343
            case variable::ValueType::String:
344
                return {token.lexeme(), int64_t(var.value().getString().size()), token.location()};
345
            case variable::ValueType::Object:
346
                return {token.lexeme(), int64_t(var.value().getObject()->variables().size()), token.location()};
347
            case variable::ValueType::Array:
348
                return {token.lexeme(), int64_t(var.value().getArray()->values().size()), token.location()};
349
            default:
350
                break;
351
            }
352
        }
353
        else if (token.lexeme() == u"dimension" && var.type() == variable::ValueType::Array) {
354
            return {token.lexeme(), int64_t(var.value().getArray()->dimensions().size()), token.location()};
355
        }
356
        else if (token.lexeme() == u"spaces" && var.type() == variable::ValueType::Array) {
357
            const std::shared_ptr<variable::Array> array = var.value().getArray();
358
            std::vector<variable::Value>           values;
359

360
            for(variable::index_t s : array->dimensions())
361
                values.push_back(int64_t(s));
362

363
            return {token.lexeme(), values, token.location()};
364
        }
365

366
        return {};
367
    }
368

369
}
370

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

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

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

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