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/variable/Module_interface.h"
12
#include "simodo/inout/convert/functions.h"
13
#include "simodo/inout/format/fmt.h"
14
#include "simodo/bormental/DrBormental.h"
21
#include "simodo/interpret/Interpret.h"
28
#if __cplusplus >= __cpp_2017
30
namespace fs = std::filesystem;
32
#include <experimental/filesystem>
33
namespace fs = std::filesystem::experimental;
36
namespace simodo::interpret
38
InterpretState ScriptSemantics_abstract::executeNone()
40
return InterpretState::Flow;
43
InterpretState ScriptSemantics_abstract::executePushConstant(const ast::Node & op)
45
variable::Variable constant_variable;
46
[[maybe_unused]] size_t index = 0;
48
switch(op.token().type())
50
case inout::LexemeType::Id:
51
case inout::LexemeType::Annotation:
52
constant_variable = { u"", op.token().lexeme(), op.token().location() };
54
case inout::LexemeType::Number:
55
if (op.token().lexeme().substr(0,2) == u"0b")
56
constant_variable = { u"",
57
static_cast<int64_t>(std::stoll(inout::toU8(op.token().lexeme().substr(2)),nullptr,2)),
58
op.token().location() };
59
else if (op.token().lexeme().substr(0,2) == u"0o")
60
constant_variable = { u"",
61
static_cast<int64_t>(std::stoll(inout::toU8(op.token().lexeme().substr(2)),nullptr,8)),
62
op.token().location() };
63
else if (op.token().lexeme().substr(0,2) == u"0x")
64
constant_variable = { u"",
65
static_cast<int64_t>(std::stoll(inout::toU8(op.token().lexeme().substr(2)),nullptr,16)),
66
op.token().location() };
67
else if (op.token().qualification() == inout::TokenQualification::Integer)
68
constant_variable = { u"", static_cast<int64_t>(std::stoll(inout::toU8(op.token().lexeme()))), op.token().location() };
70
constant_variable = { u"", std::stod(inout::toU8(op.token().lexeme())), op.token().location() };
72
case inout::LexemeType::Punctuation:
73
if (op.token().lexeme() == u"true" || op.token().lexeme() == u"false")
74
constant_variable = { u"", op.token().lexeme() == u"true", op.token().location() };
75
else if (op.token().lexeme() == u"null") {
76
constant_variable = variable::null_variable(op.token().location());
77
index = constant_variable.value().variant().index();
81
throw bormental::DrBormental("ScriptSemantics_abstract::executePushConstant",
82
inout::fmt("Invalid internal type of constant to convert (%1)")
83
.arg(getLexemeTypeName(op.token().type())));
86
if (!op.branches().empty()) {
87
std::vector<variable::Value> unit_parts;
89
for(const ast::Node & n : op.branches())
90
unit_parts.push_back(n.token().lexeme());
92
constant_variable.spec().set(u"unit", unit_parts);
95
stack().push(constant_variable);
97
return InterpretState::Flow;
100
InterpretState ScriptSemantics_abstract::executePushVariable(const inout::Token & token)
103
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
105
variable::Variable var = prepareVariableByToken(token);
107
if (var.name().empty() && var.origin().name().empty()) {
108
stack().push({token.lexeme(), {}, token.location(), {}});
109
throw AnalyzeException("ScriptSemantics_abstract::executePushVariable",
110
token.location().makeLocation(inter().files()),
111
inout::fmt("Variable '%1' not found")
112
.arg(token.lexeme()));
115
if (token.lexeme() == SELF_VARIABLE_NAME) {
120
notifyNameUsed(var.origin(), token.location());
124
return InterpretState::Flow;
127
InterpretState ScriptSemantics_abstract::executeObjectElement(const ast::Node & op)
131
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
133
variable::Variable & candid = stack().variable(stack().top());
134
variable::Variable & origin = candid.origin();
136
variable::Variable super_element = makeSuperElement(origin, op.token());
138
if (!super_element.name().empty()) {
140
stack().push(super_element);
141
notifyDeclared(super_element);
142
return InterpretState::Flow;
145
if (origin.value().isNull()) {
147
stack().push(variable::error_variable(op.token().location(),op.token().lexeme()));
148
return InterpretState::Flow;
151
variable::Variable obj_variable = origin;
153
if (!obj_variable.value().isObject())
154
obj_variable = inter().expr().convertVariable(candid, variable::ValueType::Object);
156
assert(obj_variable.value().isObject());
158
std::shared_ptr<variable::Object> object = obj_variable.value().getObject();
159
variable::Variable & element = object->getVariableByName_mutable(op.token().lexeme());
161
if (!element.name().empty() && !hidden(element)) {
162
variable::VariableSet_t ref_spec;
163
if (element.type() == variable::ValueType::Function) {
164
if (object->flags().isSet(variable::ObjectFlag::Fiber)
165
&& _fiber_flow_mode == FiberFlowMode::InDemand) {
166
ref_spec.push_back({variable::SPEC_FLOW, object});
167
_fiber_flow_mode = FiberFlowMode::Prepared;
172
stack().pushRef(element, op.token().location(), ref_spec);
173
notifyNameUsed(element, op.token().location());
175
return InterpretState::Flow;
178
const ast::Node * p_next_node = inter().lookupOperationNode(+1);
181
&& checkSemanticName(p_next_node->host())
182
&& ScriptOperationCode(p_next_node->operation()) == ScriptOperationCode::Assignment) {
183
variable::Variable & setter = object->getVariableByName_mutable(u"set_" + op.token().lexeme());
185
if (!setter.name().empty() && !hidden(setter) && setter.type() == variable::ValueType::Function) {
187
stack().pushRef(setter, op.token().location());
188
notifyNameUsed(setter, op.token().location());
189
_setter_in_stack = true;
190
return InterpretState::Flow;
194
variable::Variable & getter = object->getVariableByName_mutable(u"get_" + op.token().lexeme());
196
if (!getter.name().empty() && !hidden(getter) && getter.type() == variable::ValueType::Function) {
198
stack().pushRef(getter, op.token().location());
199
notifyNameUsed(getter, op.token().location());
200
return executeFunctionCall({});
205
throw AnalyzeException("ScriptSemantics_abstract::executeObjectElement",
206
op.token().location().makeLocation(inter().files()),
207
inout::fmt("Property '%1' is hidden in '%2' and have not getter 'get_%3'")
208
.arg(op.token().lexeme())
209
.arg(obj_variable.name())
210
.arg(op.token().lexeme()));
212
throw AnalyzeException("ScriptSemantics_abstract::executeObjectElement",
213
op.token().location().makeLocation(inter().files()),
214
inout::fmt("Property '%1' not found in '%2'")
215
.arg(op.token().lexeme())
216
.arg(obj_variable.name()));
222
stack().push(variable::error_variable());
226
InterpretState ScriptSemantics_abstract::executeFunctionCall(const ast::Node & op)
229
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
231
name_index_t function_index { stack().top() };
232
variable::Variable function { stack().variable(function_index) };
234
if (function.origin().type() != variable::ValueType::Function) {
235
if (function.origin().type() == variable::ValueType::Object) {
236
std::shared_ptr<variable::Object> object = function.origin().value().getObject();
237
const variable::Variable init_func = object->getVariableByName(u"__init__");
239
if (!init_func.name().empty())
240
function = init_func;
243
if (function.origin().type() != variable::ValueType::Function) {
244
if (function.origin().type() == variable::ValueType::Null
245
&& checkInterpretType(InterpretType::Analyzer))
248
function = inter().expr().convertVariable(function, variable::ValueType::Function);
252
stack().push(function);
255
boundary_index_t boundary_index { stack().startBoundary(BoundScope::Local, BOUNDARY_MARK_FUNCTION_FRAME) };
257
// Вычисляем аргументы функции, а потом вызываем функцию
258
inter().addFlowLayer(
260
[this, boundary_index, function](const FlowLayerInfo & flow)
262
if (flow.error_sign) {
263
stack().clearBoundary(boundary_index);
265
stack().push(variable::error_variable());
269
if (!function.origin().value().isFunction()
270
&& checkInterpretType(InterpretType::Analyzer)) {
271
stack().clearBoundary(boundary_index);
273
stack().push(variable::error_variable());
278
Interpret_interface * p_interpret = nullptr;
280
if (_fiber_flow_mode == FiberFlowMode::Prepared) {
281
if (checkInterpretType(InterpretType::Preview)) {
282
const variable::Variable & flow_variable = function.spec().object()->getVariableByName(variable::SPEC_FLOW);
283
assert(!flow_variable.name().empty());
284
const ChildFlowInfo * info = inter().parallelize().findChildFlowInfo(flow_variable);
286
if (info->child->ready()) {
287
stack().clearBoundary(boundary_index);
289
stack().push(variable::error_variable());
291
throw bormental::DrBormental("ScriptSemantics_abstract::executeFunctionCall",
292
inout::fmt("Unacceptable use of an already working fiber"));
294
p_interpret = info->child;
297
p_interpret = _interpret;
301
_fiber_flow_mode = FiberFlowMode::Launched;
302
notifyRemoteFunctionLaunch(function.location());
305
p_interpret = _interpret;
307
if (invoke && checkInterpretType(InterpretType::Analyzer)) {
308
std::shared_ptr<variable::Object> our_function_object = function.origin().value().getFunction();
309
auto it = std::find_if( _functions_for_analyze.begin(), _functions_for_analyze.end(),
310
[our_function_object] (const variable::Variable & f) {
311
std::shared_ptr<variable::Object> f_object = f.origin().value().getFunction();
312
return f_object.get() == our_function_object.get();
315
if (it != _functions_for_analyze.end())
316
_functions_for_analyze.erase(it);
317
else if (stack().isRecursiveCalls()) {
318
const auto [begin,end] = stack().boundaryLowAndTop(boundary_index);
319
variable::Variable & function_origin = stack().variable(begin-1).origin();
320
assert(function_origin.value().isFunction());
321
function_origin.origin().spec().set(variable::SPEC_RECURSIVE, true);
326
// Очистка границы вызова (stack().clearBoundary(boundary_index))
327
// выполняется внутри callPreparedFunction
328
inter().expr().callPreparedFunction(
335
return InterpretState::Flow;
338
InterpretState ScriptSemantics_abstract::executeProcedureCheck()
340
/// \todo Проверять, что была вызвана не функция, а процедура? Или как в C/C++?
343
return InterpretState::Flow;
346
InterpretState ScriptSemantics_abstract::executePrint(bool need_detailed_report)
348
inter().expr().print(need_detailed_report);
351
return InterpretState::Flow;
354
InterpretState ScriptSemantics_abstract::executeBlock(bool is_beginning_of_block, const ast::Node & op)
356
if (is_beginning_of_block) {
357
boundary_index_t boundary_index = stack().startBoundary(BoundScope::Local);
359
inter().addFlowLayer(
361
[this, boundary_index](const FlowLayerInfo & )
363
stack().clearBoundary(boundary_index);
367
return InterpretState::Flow;
370
InterpretState ScriptSemantics_abstract::executePop()
374
return InterpretState::Flow;
377
InterpretState ScriptSemantics_abstract::executeFunctionDefinition(
378
const ast::Node * pop_closure,
379
const ast::Node * pop_params,
380
const ast::Node * pop_return_type,
381
const ast::Node & op_body)
383
boundary_index_t boundary_index = stack().startBoundary();
385
std::function<void(const FlowLayerInfo &)> call_back =
386
[this, boundary_index](const FlowLayerInfo & flow)
388
if (flow.error_sign) {
389
_function_definition_data.setReturnType({});
390
stack().clearBoundary(boundary_index);
391
_function_definition_mode = false;
392
stack().push(variable::error_variable());
396
if (_function_definition_data.state() == FunctionDefinition_data::State::Params) {
397
auto [begin_index,end_index] = stack().boundaryLowAndTop(boundary_index);
398
assert(end_index-begin_index > 0);
400
variable::Object params;
402
for(name_index_t i=begin_index; i < end_index; ++i) {
403
const variable::Variable & param = stack().variable(i);
404
const variable::Variable & closure = _function_definition_data.closures().getVariableByName(param.name());
405
if (!closure.name().empty()) {
406
inout::TokenLocation location = param.location();
408
_function_definition_data.setReturnType({});
409
stack().clearBoundary(boundary_index);
410
_function_definition_mode = false;
411
stack().push(variable::error_variable());
413
throw AnalyzeException("ScriptSemantics_abstract::executeFunctionDefinition",
414
location.makeLocation(inter().files()),
415
inout::fmt("The argument and closure have the same names"));
420
stack().pop(end_index - begin_index);
422
_function_definition_data.setParams(params);
424
if (_function_definition_data.pop_return_type()) {
425
inter().addFlowLayer(*_function_definition_data.pop_return_type(), flow.on_layer_end);
429
_function_definition_data.setReturnType({});
430
stack().clearBoundary(boundary_index);
431
_function_definition_mode = false;
432
stack().push(_function_definition_data.createFunction());
436
assert(_function_definition_data.state() == FunctionDefinition_data::State::Return_Type);
438
_function_definition_data.setReturnType(
439
createVariable(stack().accumulator(), flow.code_flow.token(), variable::SPEC_ORIGIN_TYPE));
440
stack().clearBoundary(boundary_index);
441
_function_definition_mode = false;
442
stack().push(_function_definition_data.createFunction());
446
variable::Object closures;
449
for(const ast::Node & n : pop_closure->branches())
452
variable::Variable v;
454
if (n.token().lexeme() == u"*")
455
v = {u"*", {}, n.token().location()};
456
else if (n.token().lexeme() == SELF_VARIABLE_NAME)
457
v = {n.token().lexeme(), {}, n.token().location()};
459
v = prepareVariableByToken(n.token());
461
if (v.name().empty() && v.origin().name().empty())
462
throw AnalyzeException("ScriptSemantics_abstract::executeFunctionDefinition",
463
n.token().location().makeLocation(inter().files()),
464
inout::fmt("Variable '%1' not found")
465
.arg(n.token().lexeme()));
467
notifyNameUsed(v.origin(), n.token().location());
469
closures.add(v.origin());
473
stack().clearBoundary(boundary_index);
474
_function_definition_mode = false;
475
stack().push(variable::error_variable());
479
_function_definition_data.initiate(closures, pop_return_type, &op_body);
480
_function_definition_mode = true;
483
inter().addFlowLayer(*pop_params, call_back);
484
return InterpretState::Flow;
487
variable::Object params;
488
_function_definition_data.setParams(params);
490
if (pop_return_type) {
491
inter().addFlowLayer(*pop_return_type, call_back);
492
return InterpretState::Flow;
495
_function_definition_data.setReturnType({});
496
stack().clearBoundary(boundary_index);
497
_function_definition_mode = false;
498
stack().push(_function_definition_data.createFunction());
500
return InterpretState::Flow;
503
InterpretState ScriptSemantics_abstract::executeFunctionDefinitionEnd(const ast::Node & )
505
name_index_t func_index = stack().top();
506
variable::Variable & func_variable = stack().variable(func_index).origin();
508
assert(func_variable.value().isFunction());
510
func_variable.value().setInternalParent(inter().expr().makeSelf());
512
_functions_for_closures.push_back(func_variable.value().getFunction());
514
return InterpretState::Flow;
517
InterpretState ScriptSemantics_abstract::executePostAssignment(const ast::Node & )
519
while(!_functions_for_closures.empty()) {
520
std::shared_ptr<variable::Object> function_object = _functions_for_closures.back();
521
_functions_for_closures.pop_back();
523
assert(!function_object->variables().empty());
525
variable::Variable & function_core = function_object->getVariableByIndex_mutable(0);
526
variable::Object & closures = function_core.value().getIntFunctionClosures();
527
variable::Object tmp_closures;
529
for(const variable::Variable & closure : closures.variables())
530
if (closure.name() == u"*") {
531
boundary_index_t module_bound = stack().findNearestMarkedBoundary(BOUNDARY_MARK_MODULE_FRAME, BoundScope::Global);
532
if (module_bound != UNDEFINED_BOUNDARY_INDEX) {
533
auto [begin_index, end_index] = stack().boundaryLowAndTop(module_bound);
534
for(name_index_t i = begin_index; i < end_index; ++i) {
535
variable::Variable & v = stack().variable(i);
536
tmp_closures.add(v.origin());
541
variable::Variable v = prepareVariableByToken({closure.name(), closure.location()});
542
if (v.name().empty() && v.origin().name().empty())
543
tmp_closures.add(closure);
545
tmp_closures.add(v.origin());
547
if (closure.name() == SELF_VARIABLE_NAME)
550
notifyNameUsed(v.origin(), closure.location());
554
closures.swap(tmp_closures);
557
return InterpretState::Flow;
560
InterpretState ScriptSemantics_abstract::executeFunctionTethered(const ast::Node & )
562
name_index_t func_index = stack().top();
563
variable::Variable & func_variable = stack().variable(func_index).origin();
564
assert(func_variable.value().isFunction());
566
func_variable.spec().set(variable::SPEC_TETHERED, true);
568
return InterpretState::Flow;
571
InterpretState ScriptSemantics_abstract::executeReturn(const ast::Node & op)
573
ScriptOperationCode operation_code = static_cast<ScriptOperationCode>(op.operation());
574
boundary_index_t function_boundary = stack().findNearestMarkedBoundary(BOUNDARY_MARK_FUNCTION_FRAME,BoundScope::Global);
576
if (operation_code == ScriptOperationCode::ReturnExpression) {
577
variable::Variable & top = stack().variable(stack().top());
578
inter().expr().setReturnValue(top.origin().value());
582
if (function_boundary == UNDEFINED_BOUNDARY_INDEX)
583
throw AnalyzeException( "ScriptSemantics_abstract::executeReturn",
584
op.token().makeLocation(inter().files()),
585
inout::fmt("Inappropriate use of the return statement"));
587
const auto [begin,end] = stack().boundaryLowAndTop(function_boundary);
589
name_index_t function_index { begin-1 };
590
variable::Variable & function { stack().variable(function_index).origin() };
591
variable::FunctionWrapper func { function };
592
variable::ValueType return_declared_type { func.getReturnDeclarationVariable().type() };
594
if (return_declared_type != variable::ValueType::Null && inter().expr().return_value().type() != variable::ValueType::Null
595
&& return_declared_type != inter().expr().return_value().type())
596
inter().expr().setReturnValue(inter().expr().convertVariable({u"", inter().expr().return_value(), op.token().location()},return_declared_type).value());
598
if (return_declared_type != variable::ValueType::Null && operation_code == ScriptOperationCode::Return)
599
throw AnalyzeException( "ScriptSemantics_abstract::executeReturn",
600
op.token().makeLocation(inter().files()),
601
inout::fmt("The function must return a value"));
603
if (checkInterpretType(InterpretType::Preview)
604
|| function.name().substr(0,2) == u"__"
606
while(!_cycle_data_stack.empty() && _cycle_data_stack.back().boundary_index > function_boundary)
607
_cycle_data_stack.pop_back();
609
const ast::Node * code = std::get<variable::InternalFunction>(func.getCallingAddressVariable().variant()).code;
610
bool returned = inter().flushLayers(*code, true);
614
return InterpretState::Flow;
617
InterpretState ScriptSemantics_abstract::executeFor(const inout::Token & ,
618
const ast::Node * pop_variable,
619
const ast::Node * pop_source,
620
const ast::Node * pop_body)
622
assert(pop_variable);
626
boundary_index_t boundary_index = stack().startBoundary(BoundScope::Local, BOUNDARY_MARK_CYCLE_FRAME);
628
_cycle_data_stack.push_back({boundary_index, pop_variable, pop_source, pop_body});
630
inter().addFlowLayer(
631
*_cycle_data_stack.back().pop_variable,
632
[this, boundary_index](const FlowLayerInfo & flow)
634
if (flow.error_sign) {
635
stack().clearBoundary(boundary_index);
636
_cycle_data_stack.pop_back();
640
_cycle_data_stack.back().variable_index = stack().top();
641
_cycle_data_stack.back().typed_variable = stack().variable(_cycle_data_stack.back().variable_index).origin();
643
inter().addFlowLayer(*_cycle_data_stack.back().pop_source, _for_source_callback);
646
return InterpretState::Flow;
649
InterpretState ScriptSemantics_abstract::executeWhile(const inout::Token & ,
650
const ast::Node * pop_expression,
651
const ast::Node * pop_body)
653
assert(pop_expression);
656
boundary_index_t boundary_index = stack().startBoundary(BoundScope::Local, BOUNDARY_MARK_CYCLE_FRAME);
658
_cycle_data_stack.push_back({boundary_index, pop_expression, pop_body});
660
inter().addFlowLayer(*_cycle_data_stack.back().pop_expression, _cycle_condition_callback);
662
return InterpretState::Flow;
665
InterpretState ScriptSemantics_abstract::executeDoWhile(const inout::Token & ,
666
const ast::Node * pop_body,
667
const ast::Node * pop_expression)
670
assert(pop_expression);
672
boundary_index_t boundary_index = stack().startBoundary(BoundScope::Local, BOUNDARY_MARK_CYCLE_FRAME);
674
_cycle_data_stack.push_back({boundary_index, pop_expression, pop_body});
676
inter().addFlowLayer(*_cycle_data_stack.back().pop_body, _cycle_body_callback);
678
return InterpretState::Flow;
681
InterpretState ScriptSemantics_abstract::executeBreak(const ast::Node & op)
683
if (_cycle_data_stack.empty()
684
|| UNDEFINED_BOUNDARY_INDEX == stack().findNearestMarkedBoundary(BOUNDARY_MARK_CYCLE_FRAME))
685
throw AnalyzeException( "ScriptSemantics_abstract::executeBreak",
686
op.token().makeLocation(inter().files()),
687
inout::fmt("Inappropriate use of the 'break' statement"));
689
if (checkInterpretType(InterpretType::Preview)) {
690
inter().flushLayers(*_cycle_data_stack.back().pop_body,false);
691
stack().clearBoundary(_cycle_data_stack.back().boundary_index);
692
_cycle_data_stack.pop_back();
695
return InterpretState::Flow;
698
InterpretState ScriptSemantics_abstract::executeContinue(const ast::Node & op)
700
if (_cycle_data_stack.empty()
701
|| UNDEFINED_BOUNDARY_INDEX == stack().findNearestMarkedBoundary(BOUNDARY_MARK_CYCLE_FRAME))
702
throw AnalyzeException( "ScriptSemantics_abstract::executeContinue",
703
op.token().makeLocation(inter().files()),
704
inout::fmt("Inappropriate use of the 'continue' statement"));
706
if (checkInterpretType(InterpretType::Preview))
707
inter().flushLayers(*_cycle_data_stack.back().pop_body,true);
709
return InterpretState::Flow;
712
InterpretState ScriptSemantics_abstract::executeReference(const ast::Node & )
714
name_index_t var_index = stack().top();
715
variable::Variable & var = stack().variable(var_index);
717
if (!var.value().isRef())
718
throw AnalyzeException("ScriptSemantics_abstract::executeReference",
719
var.location().makeLocation(inter().files()),
720
inout::fmt("It is unacceptable to take a reference for a temporary value"));
722
var.spec().set(variable::SPEC_REFERENCE, true);
724
return InterpretState::Flow;
727
InterpretState ScriptSemantics_abstract::executeArrayElement(const ast::Node & op)
729
name_index_t array_index = stack().top();
730
boundary_index_t boundary_index = stack().startBoundary();
732
inter().addFlowLayer(
734
[this, array_index, boundary_index](const FlowLayerInfo & flow)
737
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
739
if (flow.error_sign) {
740
stack().clearBoundary(boundary_index);
742
stack().push(variable::error_variable(flow.code_flow.bound().location()));
746
const variable::Variable & array_variable = stack().variable(array_index);
747
const variable::Variable & array_origin = array_variable.origin();
748
variable::VariableRef ref;
752
auto [begin_index, end_index] = stack().boundaryLowAndTop(boundary_index);
754
if (array_origin.type() == variable::ValueType::Object) {
755
if (end_index-begin_index != 1)
756
throw AnalyzeException("ScriptSemantics_abstract::executeArrayElement",
757
array_variable.location().makeLocation(inter().files()),
758
inout::fmt("Unable to multi-index variable '%1'")
759
.arg(array_origin.name()));
761
std::shared_ptr<variable::Object> object = array_origin.value().getObject();
762
const variable::Variable & index_variable = stack().variable(begin_index);
764
if (index_variable.origin().type() == variable::ValueType::Int) {
765
ref = object->getVariableByIndex(index_variable.origin().value().getInt()).makeReference();
767
else if (index_variable.origin().type() == variable::ValueType::String) {
768
std::u16string name = index_variable.origin().value().getString();
769
variable::Variable & var = object->getVariableByName_mutable(name);
771
if (var.name().empty()) {
772
const ast::Node * p_next_node = inter().lookupOperationNode(+1);
775
&& checkSemanticName(p_next_node->host())
776
&& ScriptOperationCode(p_next_node->operation()) == ScriptOperationCode::Assignment) {
777
object->add({name, {}, index_variable.location()});
778
variable::Variable & v = object->getVariableByName_mutable(name);
779
assert(!v.name().empty());
780
ref = v.makeReference();
783
// Оставляем ref пустым, а далее для этого случая кладём на стек null
787
ref = var.makeReference();
790
throw AnalyzeException("ScriptSemantics_abstract::executeArrayElement",
791
index_variable.location().makeLocation(inter().files()),
792
inout::fmt("Incorrect index type '%1'")
793
.arg(variable::getValueTypeName(index_variable.origin().type())));
795
else if (array_origin.type() == variable::ValueType::Array) {
796
std::vector<variable::index_t> indexes;
798
for(name_index_t i = begin_index; i < end_index; ++i) {
799
const variable::Variable & index_variable = stack().variable(i);
800
if (index_variable.origin().type() == variable::ValueType::Int) {
801
int64_t index = index_variable.origin().value().getInt();
803
if (index >= 0 && index < std::numeric_limits<variable::index_t>::max()) {
804
indexes.push_back(variable::index_t(index));
809
throw AnalyzeException("ScriptSemantics_abstract::executeArrayElement",
810
stack().variable(i).location().makeLocation(inter().files()),
811
inout::fmt("The index must be a positive integer number and not exceed %1")
812
.arg(std::numeric_limits<variable::index_t>::max()));
815
ref = array_origin.value().getArray()->getRefByIndex(indexes);
818
throw AnalyzeException("ScriptSemantics_abstract::executeArrayElement",
819
array_variable.location().makeLocation(inter().files()),
820
inout::fmt("Invalid type %1 for indexing. The indexing operation is only available for arrays and objects")
821
.arg(variable::getValueTypeName(array_origin.type())));
825
stack().clearBoundary(boundary_index);
827
stack().push(variable::error_variable(flow.code_flow.bound().location()));
831
stack().clearBoundary(boundary_index);
835
stack().push({{}, {}, flow.code_flow.bound().location()});
837
stack().push({{}, ref, flow.code_flow.bound().location()});
840
return InterpretState::Flow;
843
InterpretState ScriptSemantics_abstract::executeObjectStructure(const ast::Node & op)
845
if (op.branches().empty()) {
846
stack().push({ {}, variable::VariableSet_t {}, op.token().location(),
847
variable::VariableSet_t { {{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_STRUCTURE}, }} });
848
return InterpretState::Flow;
851
_executeRecordStructure_stack.push_back({stack().startBoundary(), op});
853
inter().addFlowLayer(
854
op.branches().front(),
855
[this](const FlowLayerInfo & flow)
857
boundary_index_t boundary_index = _executeRecordStructure_stack.back().boundary_index;
858
const ast::Node & op = _executeRecordStructure_stack.back().op;
859
size_t & op_branches_index = _executeRecordStructure_stack.back().op_branches_index;
863
// Проверяем уникальность имени
864
auto [begin_index, end_index] = stack().boundaryLowAndTop(boundary_index);
865
for(name_index_t i=begin_index; i < end_index; ++i)
866
if (stack().variable(i).name() == flow.code_flow.token().lexeme())
867
throw AnalyzeException("ScriptSemantics_abstract::executeObjectStructure",
868
flow.code_flow.token().makeLocation(inter().files()),
869
inout::fmt("Duplicate object element name '%1'")
870
.arg(flow.code_flow.token().lexeme()));
872
variable::Variable param = { flow.code_flow.token().lexeme(), {}, flow.code_flow.token().location() };
873
name_index_t param_value_index = stack().top();
874
const variable::Variable & param_value = stack().variable(param_value_index);
876
param.setValue(param_value.value());
877
param.spec().clone(param_value.spec());
882
notifyDeclared(param);
884
// Переключаемся на следующий элемент объекта
885
op_branches_index += 1;
887
if (op_branches_index >= op.branches().size()) {
888
// Элементы закончились
889
std::shared_ptr<variable::Object> obj = stack().convertToObject(boundary_index);
890
stack().clearBoundary(boundary_index);
891
stack().push({ {}, obj, op.token().location(),
892
variable::VariableSet_t { {{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_STRUCTURE}, }} });
893
_executeRecordStructure_stack.pop_back();
896
// Ставим на обработку выражение справа от очередной переменной объекта
897
inter().addFlowLayer(op.branches()[op_branches_index], flow.on_layer_end);
901
if (stack().clearBoundary(boundary_index))
902
stack().push(variable::error_variable());
903
_executeRecordStructure_stack.pop_back();
908
return InterpretState::Flow;
911
InterpretState ScriptSemantics_abstract::executeArrayStructure(const ast::Node & op)
913
boundary_index_t boundary_index = stack().startBoundary();
915
inter().addFlowLayer(
917
[this, boundary_index](const FlowLayerInfo & flow)
919
std::vector<variable::Value> values;
923
auto [begin_index,end_index] = stack().boundaryLowAndTop(boundary_index);
924
for(name_index_t i=begin_index; i < end_index; ++i)
925
values.push_back(stack().variable(i).origin().value());
929
stack().clearBoundary(boundary_index);
930
stack().push(variable::error_variable());
934
stack().clearBoundary(boundary_index);
935
std::shared_ptr<variable::Array> array = std::make_shared<variable::Array>(
936
variable::ValueType::Null,
937
std::vector<variable::index_t> {static_cast<variable::index_t>(values.size())},
940
stack().push({{}, array, flow.code_flow.token().location(), {}});
943
return InterpretState::Flow;
946
InterpretState ScriptSemantics_abstract::executeImport(const inout::Token & path)
950
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
952
std::string module_path = makeModulePath(path, inter().files().at(path.location().uri_index()));
954
if (path.type() == inout::LexemeType::Annotation && !_module_management.isTheModuleLoaded(module_path)) {
955
if (!fs::exists(module_path))
956
throw AnalyzeException("ScriptSemantics_abstract::executeImport",
957
path.makeLocation(inter().files()),
958
inout::fmt("File '%1' was not found")
961
notifyRef(path, inout::toU16(module_path));
962
inter().addFile(module_path);
964
const ast::Node * node = _module_management.getCode(module_path,inter().files());
966
throw interpret::AnalyzeException("ScriptSemantics_abstract::executeImport",
967
path.makeLocation(inter().files()),
968
inout::fmt("Unable to load module '%1'")
971
boundary_index_t boundary_index = stack().startBoundary(BoundScope::Global, BOUNDARY_MARK_MODULE_FRAME);
973
inter().addFlowLayer(
975
[this,boundary_index,path,module_path](const FlowLayerInfo &)
978
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
980
std::shared_ptr<variable::Object> record;
984
std::shared_ptr<variable::Object> module_object = stack().convertToObject(boundary_index);
986
std::shared_ptr<variable::Module_interface> module
987
= _module_management.registerSoftModule(module_path,module_object);
989
/// \todo Пересмотреть странную передачу самого себя в свой же метод.
990
/// PVS Studio: warn V678 An object is used as an argument to its own method.
991
/// Consider checking the first actual argument of the 'instantiate' function.
992
record = module->instantiate(module).getObject();
996
throw AnalyzeException("ScriptSemantics_abstract::executeImport",
997
path.makeLocation(inter().files()),
998
inout::fmt("Unable to load module '%1'")
1003
stack().clearBoundary(boundary_index);
1004
stack().push({ {}, {}, path.location(),
1005
variable::VariableSet_t {{{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_MODULE}, }} });
1009
stack().clearBoundary(boundary_index);
1010
stack().push({ {}, record, path.location(),
1011
variable::VariableSet_t {{{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_MODULE}, }} });
1015
// =====================================================================================================
1016
// =====================================================================================================
1017
// =====================================================================================================
1018
// =====================================================================================================
1019
// =====================================================================================================
1020
// =====================================================================================================
1021
// =====================================================================================================
1022
// =====================================================================================================
1023
// =====================================================================================================
1024
// =====================================================================================================
1025
// =====================================================================================================
1026
// =====================================================================================================
1027
// =====================================================================================================
1028
// =====================================================================================================
1029
// =====================================================================================================
1030
// =====================================================================================================
1031
// =====================================================================================================
1032
// =====================================================================================================
1033
// =====================================================================================================
1034
// =====================================================================================================
1035
std::shared_ptr<variable::Object> object = _module_management.produceObject(module_path,&inter());
1037
throw interpret::AnalyzeException("ScriptSemantics_abstract::executeImport",
1038
path.makeLocation(inter().files()),
1039
inout::fmt("Unable to load module '%1'")
1042
stack().push({ {}, object, path.location(),
1043
variable::VariableSet_t {{{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_MODULE}, }} });
1046
return InterpretState::Flow;
1050
stack().push({ {}, variable::VariableSet_t {}, path.location(),
1051
variable::VariableSet_t {{{variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_MODULE}, }} });
1055
InterpretState ScriptSemantics_abstract::executeAnnouncement()
1057
name_index_t top = stack().top();
1058
const variable::Variable & contract = stack().variable(top);
1060
appendContractProperties(contract, stack().accumulator());
1063
return InterpretState::Flow;
1066
InterpretState ScriptSemantics_abstract::executeContract(const ast::Node & op)
1068
if (stack().find(op.token().lexeme(),interpret::BoundScope::Local) != UNDEFINED_NAME_INDEX) {
1069
stack().push(variable::error_variable());
1070
throw AnalyzeException( "ScriptSemantics_abstract::executeContract",
1071
op.token().location().makeLocation(inter().files()),
1072
inout::fmt("The name '%1' has already been declared in the local scope")
1073
.arg(op.token().lexeme()));
1076
variable::Variable new_contract {op.token().lexeme(), {}, op.token().location()};
1078
appendContractProperties(stack().accumulator(), new_contract);
1080
if (new_contract.type() == variable::ValueType::Null
1081
&& new_contract.spec().object()->getVariableByName(variable::SPEC_NAME_INITIAL_VALUE).name().empty()
1082
&& new_contract.spec().object()->getVariableByName(variable::SPEC_NAME_BUILT_IN_TYPE).name().empty()) {
1083
if (ScriptOperationCode(op.operation()) == ScriptOperationCode::Type)
1084
throw AnalyzeException( "ScriptSemantics_abstract::executeContract",
1085
op.token().location().makeLocation(inter().files()),
1086
inout::fmt("Type '%1' is not typed")
1087
.arg(op.token().lexeme()));
1088
new_contract.spec().set(variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_CONTRACT);
1091
new_contract.spec().set(variable::SPEC_ORIGIN, variable::SPEC_ORIGIN_TYPE);
1093
stack().push(new_contract);
1094
notifyDeclared(new_contract);
1096
return InterpretState::Flow;
1099
InterpretState ScriptSemantics_abstract::executeDeclaration(const ast::Node & op)
1102
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
1104
if (stack().find(op.token().lexeme(),interpret::BoundScope::Local) != UNDEFINED_NAME_INDEX) {
1105
stack().push(variable::error_variable());
1106
throw AnalyzeException( "ScriptSemantics_abstract::executeDeclaration",
1107
op.token().location().makeLocation(inter().files()),
1108
inout::fmt("The name '%1' has already been declared in the local scope")
1109
.arg(op.token().lexeme()));
1112
if (ScriptOperationCode(op.operation()) == ScriptOperationCode::AutoDeclaration) {
1113
stack().accumulator() = {u"", {variable::ValueType::Null}, op.token().location()};
1114
stack().accumulator().spec().set(variable::SPEC_NAME_INITIAL_VALUE, variable::ValueType::Null);
1117
variable::Variable var = createVariable(stack().accumulator(), op.token(), variable::SPEC_ORIGIN_VARIABLE);
1119
if (_function_definition_mode)
1120
var.spec().set(variable::SPEC_PARAMETER, true);
1121
else if (stack().getTopBoundaryMarkAndScope().first == BOUNDARY_MARK_MODULE_FRAME)
1122
var.spec().set(variable::SPEC_PROPERTY, true);
1125
notifyDeclared(stack().variable(stack().top()));
1127
return InterpretState::Flow;
1130
InterpretState ScriptSemantics_abstract::executeDeclarationOnce(const ast::Node & op)
1133
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
1135
const variable::Variable & var = stack().findVariable(op.token().lexeme());
1137
if (var.name().empty())
1138
return executeDeclaration(op);
1140
return InterpretState::Flow;
1143
InterpretState ScriptSemantics_abstract::executeDeclarationCompletion()
1145
stack().accumulator() = {};
1146
return InterpretState::Flow;
1149
InterpretState ScriptSemantics_abstract::executeAssignment(const ast::Node & op)
1152
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
1154
bool iteration = false;
1155
switch (ScriptOperationCode(op.operation()))
1157
case ScriptOperationCode::AssignmentAddition:
1158
case ScriptOperationCode::AssignmentSubtraction:
1159
case ScriptOperationCode::AssignmentMultiplication:
1160
case ScriptOperationCode::AssignmentDivision:
1161
case ScriptOperationCode::AssignmentModulo:
1162
stack().pushRef(stack().variable(stack().top()), op.token().location());
1169
if (_setter_in_stack) {
1170
_setter_in_stack = false;
1173
stack().push(variable::error_variable(op.token().location()));
1174
throw AnalyzeException( "ScriptSemantics_abstract::executeAssignment",
1175
op.token().location().makeLocation(inter().files()),
1176
inout::fmt("Assignment-iteration is not allowed for the setter"));
1178
return executeFunctionCall(op);
1181
inter().addFlowLayer(
1183
[this, iteration](const FlowLayerInfo & flow)
1186
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
1188
if (flow.error_sign) {
1196
arithmetic(ScriptOperationCode(flow.code_flow.operation()), flow.code_flow.token().location());
1204
name_index_t source_index = stack().top(0);
1205
variable::Variable & source_variable = stack().variable(source_index);
1206
name_index_t target_index = stack().top(1);
1207
variable::Variable & target_variable = stack().variable(target_index);
1208
ScriptOperationCode operation_code = ScriptOperationCode(flow.code_flow.operation());
1210
/// \todo Нужно переделать ВСЕ методы присваивания и копирования
1211
/// с учётом нового self!!!
1213
inter().expr().assignVariable(target_variable, source_variable);
1214
stack().pop(); // правая часть присваивания
1216
if (operation_code == ScriptOperationCode::Initialize)
1217
notifyInitiated(target_variable.origin());
1219
stack().pop(); // ссылка на переменную
1221
name_index_t var_index = stack().top(0);
1222
const variable::Variable & var = stack().variable(var_index);
1224
notifyNameUsed(var.origin(), var.location());
1227
return InterpretState::Flow;
1230
InterpretState ScriptSemantics_abstract::executeUnary(const ast::Node & op)
1232
unary(static_cast<ScriptOperationCode>(op.operation()), op.bound().location());
1233
return InterpretState::Flow;
1236
InterpretState ScriptSemantics_abstract::executeLogical(const ast::Node & op)
1238
name_index_t top_name_index = stack().top();
1242
logical(static_cast<ScriptOperationCode>(op.operation()), op.bound().location());
1246
stack().pop(stack().top()+1-top_name_index);
1247
stack().variable(stack().top()) = variable::error_variable().copyVariable();
1251
return InterpretState::Flow;
1254
InterpretState ScriptSemantics_abstract::executeCompare(const ast::Node & op)
1256
name_index_t top_name_index = stack().top();
1260
compare(static_cast<ScriptOperationCode>(op.operation()), op.bound().location());
1264
stack().pop(stack().top()+1-top_name_index);
1265
stack().variable(stack().top()) = variable::error_variable().copyVariable();
1269
return InterpretState::Flow;
1272
InterpretState ScriptSemantics_abstract::executeArithmetic(const ast::Node & op)
1274
name_index_t top_name_index = stack().top();
1278
arithmetic(static_cast<ScriptOperationCode>(op.operation()), op.bound().location());
1282
name_index_t current_top_name_index = stack().top();
1283
size_t pop_count = current_top_name_index - top_name_index + 1;
1285
stack().pop(pop_count);
1286
stack().variable(stack().top()) = variable::error_variable().copyVariable();
1290
return InterpretState::Flow;
1293
InterpretState ScriptSemantics_abstract::executeConditional(ScriptOperationCode code, const ast::Node & op_true, const ast::Node * op_false)
1295
name_index_t condition_index = stack().top();
1296
variable::Variable condition_variable = stack().variable(condition_index).origin();
1302
if (condition_variable.type() == variable::ValueType::Bool) {
1303
condition = condition_variable.value().getBool();
1306
condition_variable = inter().expr().convertVariable(condition_variable, variable::ValueType::Bool);
1307
condition = condition_variable.value().getBool();
1313
inter().addFlowLayer(op_true);
1314
else if (op_false != nullptr)
1315
inter().addFlowLayer(*op_false);
1317
return InterpretState::Flow;
1321
if (code == ScriptOperationCode::Ternary)
1322
stack().pop(stack().top() - condition_index);
1327
return InterpretState::Flow;
1330
InterpretState ScriptSemantics_abstract::executeCommon(const ast::Node & , const std::vector<inout::Token> & names)
1332
for(const inout::Token & t : names) {
1333
name_index_t name_index = stack().find(t.lexeme());
1334
if (name_index == UNDEFINED_NAME_INDEX)
1335
throw AnalyzeException( "ScriptSemantics_abstract::executeCommon",
1336
t.location().makeLocation(inter().files()),
1337
inout::fmt("The name '%1' not found")
1340
if (stack().addGlobal(name_index))
1341
notifyNameUsed(stack().variable(name_index), t.location());
1343
throw AnalyzeException( "ScriptSemantics_abstract::executeCommon",
1344
t.location().makeLocation(inter().files()),
1345
inout::fmt("Unable to make the name '%1' global")
1349
return InterpretState::Flow;
1352
InterpretState ScriptSemantics_abstract::executeUsing(const ast::Node & , const ast::Node & body)
1354
name_index_t using_index = stack().top();
1355
const variable::Variable & using_variable = stack().variable(using_index);
1356
const variable::Variable & using_origin = stack().variable(using_index).origin();
1358
if (using_origin.type() != variable::ValueType::Object)
1359
throw AnalyzeException( "ScriptSemantics_abstract::executeUsing",
1360
using_variable.location().makeLocation(inter().files()),
1361
inout::fmt("Unable to use not object '%1'")
1362
.arg(using_origin.name()));
1364
boundary_index_t using_bound = stack().startBoundary();
1366
stack().addUsing(using_origin.value().getObject(), using_bound);
1368
inter().addFlowLayer(
1370
[this, using_bound](const FlowLayerInfo & )
1372
stack().clearBoundary(using_bound);
1376
return InterpretState::Flow;
1379
InterpretState ScriptSemantics_abstract::executeFiberMake(const ast::Node & op)
1381
inter().addFlowLayer(
1383
[this](const FlowLayerInfo & flow)
1385
if (flow.error_sign) {
1391
variable::Variable & fiber_variable_ref = stack().variable(stack().top());
1392
variable::Variable & fiber_variable_origin = fiber_variable_ref.origin();
1394
if (!fiber_variable_origin.value().isObject())
1395
throw AnalyzeException( "ScriptSemantics_abstract::executeFiberOperation",
1396
fiber_variable_ref.location().makeLocation(inter().files()),
1397
inout::fmt("Only a variable with an object type can act as a fiber"));
1399
std::shared_ptr<variable::Object> object = fiber_variable_origin.value().getObject();
1401
if (object->flags().isSet(variable::ObjectFlag::Fiber)) {
1402
std::string object_name_text = fiber_variable_ref.name().empty()
1403
? inout::toU8(fiber_variable_origin.name())
1404
: inout::toU8(fiber_variable_ref.name());
1406
if (!object_name_text.empty())
1407
object_name_text = " '" + object_name_text + "'";
1409
throw AnalyzeException( "ScriptSemantics_abstract::executeFiberOperation",
1410
fiber_variable_ref.location().makeLocation(inter().files()),
1411
inout::fmt("Object %1 has already been declared as a fiber")
1412
.arg(object_name_text));
1415
if (!inter().parallelize().addChildFiber(fiber_variable_origin))
1416
throw bormental::DrBormental("ScriptSemantics_abstract::executeFiberOperation",
1417
inout::fmt("Unable to create fiber"));
1419
object->setFlag(variable::ObjectFlag::Fiber);
1429
return InterpretState::Flow;
1432
InterpretState ScriptSemantics_abstract::executeFiberWait(const ast::Node & op)
1434
inter().addFlowLayer(
1436
[this](const FlowLayerInfo & flow)
1438
if (flow.error_sign) {
1444
if (checkInterpretType(InterpretType::Preview))
1445
if (!inter().parallelize().wait(prepareFiberVariableOrigin()))
1446
throw bormental::DrBormental("ScriptSemantics_abstract::executeFiberWait",
1447
inout::fmt("Unable to wait fiber"));
1457
return InterpretState::Flow;
1460
InterpretState ScriptSemantics_abstract::executeFiberPushPull(const ast::Node & op)
1462
inter().addFlowLayer(
1464
[this](const FlowLayerInfo & flow)
1466
if (flow.error_sign) {
1472
switch(ScriptOperationCode(flow.code_flow.operation()))
1474
case ScriptOperationCode::FiberPush:
1475
if (checkInterpretType(InterpretType::Preview))
1476
if (!inter().parallelize().push(prepareFiberVariableOrigin()))
1477
throw bormental::DrBormental("ScriptSemantics_abstract::executeFiberPushPull",
1478
inout::fmt("Unable to push fiber"));
1480
case ScriptOperationCode::FiberPull:
1481
if (checkInterpretType(InterpretType::Preview))
1482
if (!inter().parallelize().pull(prepareFiberVariableOrigin()))
1483
throw bormental::DrBormental("ScriptSemantics_abstract::executeFiberPushPull",
1484
inout::fmt("Unable to pull fiber"));
1487
throw bormental::DrBormental("ScriptSemantics_abstract::executeFiberPushPull",
1488
inout::fmt("Unexpected operation"));
1499
return InterpretState::Flow;
1502
InterpretState ScriptSemantics_abstract::executeFiberFlow(const ast::Node & op)
1504
_fiber_flow_mode = FiberFlowMode::InDemand;
1506
inter().addFlowLayer(
1508
[this](const FlowLayerInfo & flow)
1510
if (_fiber_flow_mode != FiberFlowMode::Launched)
1511
throw AnalyzeException( "ScriptSemantics_abstract::executeFiberOperation",
1512
flow.code_flow.token().location().makeLocation(inter().files()),
1513
inout::fmt("Unable to launch remote procedure"));
1515
_fiber_flow_mode = FiberFlowMode::None;
1518
return InterpretState::Flow;
1521
InterpretState ScriptSemantics_abstract::executeCheckState(const ast::Node & )
1523
return InterpretState::Flow;
1526
InterpretState ScriptSemantics_abstract::executeArrayPush(const ast::Node & )
1529
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
1533
name_index_t source_index = stack().top(0);
1534
variable::Variable & source_variable = stack().variable(source_index);
1535
name_index_t target_index = stack().top(1);
1536
variable::Variable & target_variable = stack().variable(target_index);
1538
if (!target_variable.origin().value().isArray())
1539
throw AnalyzeException("ScriptSemantics_abstract::executeArrayPush",
1540
target_variable.location().makeLocation(inter().files()),
1541
inout::fmt("For working with slices, the variable %1 is not an array")
1542
.arg(target_variable.origin().name()));
1544
std::shared_ptr<variable::Array> array = target_variable.origin().value().getArray();
1546
if (array->dimensions().size() > 1)
1547
throw AnalyzeException("ScriptSemantics_abstract::executeArrayPush",
1548
target_variable.location().makeLocation(inter().files()),
1549
inout::fmt("Slice operations are implemented only for vectors"));
1551
array->add(source_variable.origin().value());
1552
notifyNameUsed(target_variable.origin(), target_variable.location());
1561
return InterpretState::Flow;
1564
InterpretState ScriptSemantics_abstract::executeArrayPop(const ast::Node & )
1567
[[maybe_unused]] Interpret * p_inter = static_cast<Interpret *>(&inter());
1571
name_index_t target_index = stack().top(0);
1572
variable::Variable & target_variable = stack().variable(target_index);
1574
if (!target_variable.origin().value().isArray())
1575
throw AnalyzeException("ScriptSemantics_abstract::executeArrayPop",
1576
target_variable.location().makeLocation(inter().files()),
1577
inout::fmt("For working with slices, the variable %1 is not an array")
1578
.arg(target_variable.origin().name()));
1580
std::shared_ptr<variable::Array> array = target_variable.origin().value().getArray();
1582
if (array->dimensions().size() > 1)
1583
throw AnalyzeException("ScriptSemantics_abstract::executeArrayPop",
1584
target_variable.location().makeLocation(inter().files()),
1585
inout::fmt("Slice operations are implemented only for vectors"));
1587
if (array->values().empty())
1588
throw bormental::DrBormental("ScriptSemantics_abstract::executeArrayPop",
1589
inout::fmt("Attempt to take a slice of an empty array"));
1592
notifyNameUsed(target_variable.origin(), target_variable.location());
1601
return InterpretState::Flow;