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/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"
26
#include "simodo/interpret/Interpret.h"
29
#if __cplusplus >= __cpp_2017
31
namespace fs = std::filesystem;
33
#include <experimental/filesystem>
34
namespace fs = std::filesystem::experimental;
37
namespace simodo::interpret
41
void initializeOperationSwitchboard(std::vector<OperationParser_t> & switchboard)
43
switchboard.resize(static_cast<size_t>(ScriptOperationCode::LastOperation), nullptr);
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;
55
switchboard[static_cast<size_t>(ScriptOperationCode::Reference)] = OperationParser::parseReference;
56
switchboard[static_cast<size_t>(ScriptOperationCode::ArrayElement)] = OperationParser::parseArrayElement;
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;
69
switchboard[static_cast<size_t>(ScriptOperationCode::Initialize)] = OperationParser::parseAssignment;
70
switchboard[static_cast<size_t>(ScriptOperationCode::Assignment)] = OperationParser::parseAssignment;
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;
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;
82
switchboard[static_cast<size_t>(ScriptOperationCode::Or)] = OperationParser::parseLogical;
83
switchboard[static_cast<size_t>(ScriptOperationCode::And)] = OperationParser::parseLogical;
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;
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;
99
switchboard[static_cast<size_t>(ScriptOperationCode::Ternary)] = OperationParser::parseConditional;
100
switchboard[static_cast<size_t>(ScriptOperationCode::If)] = OperationParser::parseConditional;
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;
106
switchboard[static_cast<size_t>(ScriptOperationCode::Return)] = OperationParser::parseReturn;
107
switchboard[static_cast<size_t>(ScriptOperationCode::ReturnExpression)]= OperationParser::parseReturn;
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;
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;
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;
132
ScriptSemantics_abstract::ScriptSemantics_abstract(ModuleManagement_interface & module_management)
133
: _module_management(module_management)
135
initializeOperationSwitchboard(_operation_switchboard);
139
ScriptSemantics_abstract::~ScriptSemantics_abstract()
143
void ScriptSemantics_abstract::reset()
147
InterpretState ScriptSemantics_abstract::before_start()
149
return InterpretState::Flow;
152
InterpretState ScriptSemantics_abstract::before_finish(InterpretState state)
157
bool ScriptSemantics_abstract::isOperationExists(ast::OperationCode operation_code) const
159
size_t operation_index = static_cast<size_t>(operation_code);
161
return operation_index < _operation_switchboard.size()
162
&& _operation_switchboard[operation_index] != nullptr;
165
InterpretState ScriptSemantics_abstract::performOperation(const ast::Node & op)
167
if (!isOperationExists(op.operation()))
168
throw bormental::DrBormental("ScriptSemantics_abstract::performOperation",
169
inout::fmt("Invalid operation index %1")
170
.arg(op.operation()));
172
return _operation_switchboard[static_cast<size_t>(op.operation())](*this,op);
175
std::string ScriptSemantics_abstract::makeModulePath(const inout::Token & path, const std::string & parent_path)
177
if (path.type() != inout::LexemeType::Annotation)
178
return inout::toU8(path.lexeme());
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();
187
if (path.lexeme()[0] == u'/')
188
// Модули из рабочего каталога
189
return fs::current_path().concat(path.lexeme()).lexically_normal().string();
191
// Модули по относительному к текущему модулю пути
192
return fs::path(parent_path).parent_path().append(path.lexeme()).lexically_normal().string();
195
bool ScriptSemantics_abstract::prepareForVariableByCounter()
197
ExecuteCycle_data & data = _cycle_data_stack.back();
199
assert(data.variable_index == stack().top() - 1);
200
assert(data.source.value().isArray() || data.source.value().isObject());
202
variable::index_t counter = data.source_counter;
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()))
207
if (!checkInterpretType(InterpretType::Preview))
210
stack().clearBoundary(data.boundary_index);
211
_cycle_data_stack.pop_back();
215
variable::Variable & for_variable = stack().variable(data.variable_index);
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);
223
for_variable.setValue(source.makeReference());
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());
234
for_variable.setValue(source.value());
239
stack().clearBoundary(data.boundary_index);
240
_cycle_data_stack.pop_back();
247
bool ScriptSemantics_abstract::hidden(const variable::Variable & var)
249
const variable::Value & hidden_value = var.spec().object()->find(variable::SPEC_HIDDEN);
251
return hidden_value.isBool() && hidden_value.getBool();
254
bool ScriptSemantics_abstract::tethered(const variable::Variable & var)
256
const variable::Value & tethered_value = var.spec().object()->find(variable::SPEC_TETHERED);
258
return tethered_value.isBool() && tethered_value.getBool();
261
variable::Variable & ScriptSemantics_abstract::prepareFiberVariableOrigin()
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());
269
if (!object_name_text.empty())
270
object_name_text = " '" + object_name_text + "'";
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"));
277
std::shared_ptr<variable::Object> object = fiber_variable_origin.value().getObject();
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));
286
return fiber_variable_origin;
289
variable::Variable ScriptSemantics_abstract::prepareVariableByToken(const inout::Token & token)
292
[[maybe_unused]] const Interpret * p_inter = static_cast<const Interpret *>(&inter());
294
const variable::Variable & var = stack().findVariable(token.lexeme());
296
if (!var.name().empty()) {
297
if (var.type() == variable::ValueType::Ref)
298
return {var.name(), var.value().getRef(), token.location()};
300
return {{}, var.makeReference(), token.location()};
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();
308
if (self_object && tethered) {
309
const variable::Variable & var = self_object->getVariableByName(token.lexeme());
311
if (!var.name().empty())
312
return {{}, var.makeReference(), token.location()};
315
if (token.lexeme() == SELF_VARIABLE_NAME) {
316
variable::Variable self;
319
self = {SELF_VARIABLE_NAME, self_object, token.location(),
320
variable::VariableSet_t {{{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_MODULE}}}};
322
self = {SELF_VARIABLE_NAME, inter().expr().makeSelf(), token.location(),
323
variable::VariableSet_t {{{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_MODULE}}}};
328
static variable::Variable null;
332
variable::Variable ScriptSemantics_abstract::makeSuperElement(const variable::Variable & var, const inout::Token & token) const
334
if (token.lexeme() == u"spec") {
335
std::shared_ptr<variable::Object> object = var.spec().object();
336
return {token.lexeme(), object, token.location()};
338
else if (token.lexeme() == u"origin_name") {
339
return {token.lexeme(), var.name(), token.location()};
341
else if (token.lexeme() == u"size") {
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()};
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()};
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;
360
for(variable::index_t s : array->dimensions())
361
values.push_back(int64_t(s));
363
return {token.lexeme(), values, token.location()};