4
Copyright (c) 2022 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
6
https://bmstu.codes/lsx/simodo/loom
9
#include "simodo/interpret/builtins/hosts/base/BaseAnalyzer.h"
10
#include "simodo/interpret/AnalyzeException.h"
11
#include "simodo/variable/FunctionWrapper.h"
12
#include "simodo/inout/convert/functions.h"
16
inline const std::string EXCEEDED = "The number of errors has exceeded the allowable limit";
20
simodo::interpret::SemanticDataCollector_null null_collector;
23
namespace simodo::interpret::builtins
26
BaseAnalyzer::BaseAnalyzer(Interpret_interface * inter)
27
: BaseInterpret_abstract(inter)
28
, _collector(null_collector)
32
BaseAnalyzer::BaseAnalyzer(Interpret_interface * inter, SemanticDataCollector_interface & collector)
33
: BaseInterpret_abstract(inter)
34
, _collector(collector)
38
void BaseAnalyzer::importNamespace(const std::u16string & name, const variable::Value & ns, const inout::TokenLocation & location)
40
BaseInterpret_abstract::importNamespace(name, ns, location);
42
// machine().stack().top().origin().spec().set(u"module", true);
44
_collector.collectNameDeclared(machine().stack().top());
47
InterpretState BaseAnalyzer::before_start()
49
return BaseInterpret_abstract::before_start();
52
InterpretState BaseAnalyzer::before_finish(InterpretState state)
54
return BaseInterpret_abstract::before_finish(state);
57
InterpretState BaseAnalyzer::performOperation(const ast::Node & op)
59
inout::Location location {inout::null_location};
63
return BaseInterpret_abstract::performOperation(op);
65
catch(const AnalyzeException & e)
67
location = e.location();
68
inter().reporter().reportError(location, e.what());
69
inter().setErrorSign();
70
_number_of_mistakes ++;
73
if (_number_of_mistakes >= MAX_NUMBER_OF_MISTAKES)
74
throw AnalyzeException("ScriptAnalyzer::performOperation",
75
op.token().makeLocation(inter().files()),
78
return InterpretState::Flow;
81
InterpretState BaseAnalyzer::executePushValue(const inout::Token & variable_name)
83
/// \note Перехватывать исключение AnalyzeException не нужно, т.к. оно обрабатывается в BaseAnalyzer::performOperation
84
InterpretState state = BaseInterpret_abstract::executePushValue(variable_name);
86
const variable::Variable & ref = machine().stack().top();
88
if (ref.type() != variable::ValueType::Ref)
89
return state; // Что-то пошло не так...
91
const variable::Variable & var = ref.origin();
93
_collector.collectNameUsed(var, variable_name.location());
98
InterpretState BaseAnalyzer::executeObjectElement(const inout::Token & dot, const inout::Token & variable_name)
100
/// \note Перехватывать исключение AnalyzeException не нужно, т.к. оно обрабатывается в BaseAnalyzer::performOperation
101
InterpretState state = BaseInterpret_abstract::executeObjectElement(dot, variable_name);
103
const variable::Variable & ref = machine().stack().top();
105
if (ref.type() != variable::ValueType::Ref)
106
return state; // Что-то пошло не так...
108
const variable::Variable & var = ref.origin();
110
_collector.collectNameUsed(var, variable_name.location());
115
InterpretState BaseAnalyzer::executeFunctionCall(const ast::Node & op)
117
size_t args_stack_position = machine().stack().size();
119
inter().addFlowLayer(
121
[this, args_stack_position](FlowLayerInfo flow) {
124
if (!flow.error_sign) {
126
const variable::Variable & function_variable = machine().stack().at(args_stack_position-1);
127
variable::FunctionWrapper wrapper(function_variable);
128
variable::VariableSetWrapper params = wrapper.getArgumentDeclarationVariables();
129
if (machine().stack().size() - args_stack_position != params.size())
130
throw AnalyzeException(
131
"BaseAnalyzer::executeFunctionCall",
132
function_variable.location().makeLocation(inter().files()),
133
"The number of given parameters does not match the number of declared arguments for function '"
134
+ inout::toU8(function_variable.name()) + "'");
135
for(size_t i=0; i < params.size(); ++i) {
136
if (machine().stack().at(args_stack_position+i).origin().type() != params[i].type()
137
&& params[i].type() != variable::ValueType::Null)
138
throw AnalyzeException(
139
"BaseAnalyzer::executeFunctionCall",
140
machine().stack().at(args_stack_position+i).location().makeLocation(inter().files()),
141
"Wrong parameter type");
145
// Перед выходом восстанавливаем ожидаемое состояние выполнения команды
146
machine().popAmount(machine().stack().size() - args_stack_position);
148
machine().push(variable::null_variable());
152
machine().popAmount(machine().stack().size() - args_stack_position);
154
machine().push(variable::null_variable());
157
return InterpretState::Flow;
160
InterpretState BaseAnalyzer::executeBlock(const ast::Node & op)
162
if (op.token().lexeme() == u"{") {
163
_open_scope.push_back(op.token().location());
166
assert(!_open_scope.empty());
167
_collector.collectScoped(_open_scope.back(), op.token().location());
168
_open_scope.pop_back();
171
return BaseInterpret_abstract::executeBlock(op);