4
Copyright (c) 2022 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
6
https://bmstu.codes/lsx/simodo/loom
9
#include "simodo/interpret/builtins/hosts/base/BaseMachine.h"
10
#include "simodo/interpret/builtins/hosts/base/BaseInterpret_abstract.h"
11
#include "simodo/interpret/AnalyzeException.h"
12
#include "simodo/variable/FunctionWrapper.h"
13
#include "simodo/inout/convert/functions.h"
14
#include "simodo/inout/format/fmt.h"
15
#include "simodo/inout/token/LexemeType.h"
21
static const simodo::variable::Variable error = simodo::variable::error_variable();
24
namespace simodo::interpret::builtins
27
BaseMachine::BaseMachine(const inout::uri_set_t & files)
30
, _return_variable(variable::null_variable())
34
void BaseMachine::reset()
36
/// \todo BaseMachine::reset()
39
void BaseMachine::push(variable::Variable v)
44
void BaseMachine::pushRef(const variable::Variable & v, const inout::TokenLocation & location)
46
const variable::Variable & o = v.origin();
48
// _stack.push({ o.name(), variable::VariableRef {o}, location(), {} });
49
_stack.push( variable::Variable { variable::VariableRef(o), location } );
52
void BaseMachine::pushRef(variable::VariableRef ref)
54
// _stack.push({ ref.origin().name(), ref, ref.origin().location()(), {} });
55
_stack.push( { ref, ref.origin().location() } );
58
variable::Variable BaseMachine::pop()
63
void BaseMachine::popAmount(size_t n)
68
variable::VariableRef BaseMachine::findVariable(const inout::Token & variable_name) const
70
/// \todo Не забыть переделать под ограничения фреймов вызовов и другие механизмы
72
variable::VariableSetWrapper search_area(_stack.stack(), 0, _stack.size());
74
variable::VariableRef ref = find(search_area, variable_name.lexeme());
76
if (ref.origin().name().empty())
77
throw AnalyzeException("BaseMachine::findVariable",
78
variable_name.makeLocation(_files),
79
"Переменная '" + inout::toU8(variable_name.lexeme()) + "' не найдена");
84
variable::VariableRef BaseMachine::find(variable::VariableSetWrapper & search_area, const std::u16string & variable_name) const
86
// Поиск ведётся с конца, чтобы корректно работал поиск переменных по истории их объявления с учётом блоков кода
88
for(size_t i=search_area.size()-1; i < search_area.size(); --i)
89
if (search_area[i].name() == variable_name)
90
return search_area[i].makeReference();
92
return error.makeReference();
95
void BaseMachine::checkProcedureCalled()
97
/// \todo BaseMachine::checkProcedureCalled()
100
variable::Variable BaseMachine::createVariable_implicit(const inout::Token & constant_value) const
102
switch(constant_value.type())
104
case inout::LexemeType::Annotation:
105
return { u"", constant_value.lexeme(), constant_value.location(), {} };
106
case inout::LexemeType::Number:
107
if (constant_value.qualification() == inout::TokenQualification::Integer)
108
return { u"", static_cast<int64_t>(stoll(inout::toU8(constant_value.lexeme()))), constant_value.location(), {} };
109
return { u"", stod(inout::toU8(constant_value.lexeme())), constant_value.location(), {} };
110
case inout::LexemeType::Punctuation:
111
if (constant_value.lexeme() == u"true" || constant_value.lexeme() == u"false")
112
return { u"", constant_value.lexeme() == u"true", constant_value.location(), {} };
113
if (constant_value.lexeme() == u"undef")
114
return { u"", variable::ValueType::Null, constant_value.location(), {} };
115
if (constant_value.lexeme() == u"null")
116
return { u"", variable::ValueType::Null, constant_value.location(), {} };
121
throw bormental::DrBormental("BaseMachine::createVariable_implicit",
122
inout::fmt("Invalid internal constant type to convert (%1)")
123
.arg(getLexemeTypeName(constant_value.type())));
126
variable::Value BaseMachine::callFunction_implicit(const inout::Token & , size_t args_stack_position)
128
const variable::Variable & function_origin = _stack.at(args_stack_position-1).origin();
130
if (function_origin.type() == variable::ValueType::Null)
133
if (function_origin.type() != variable::ValueType::Function) {
134
// Variable function = convertVariable_overridable(_stack.at(args_stack_position-1), ValueType::Function);
135
// FunctionWrapper wrapper(*this, dot, function);
136
// VariableSetWrapper_mutable arguments(_stack.stack(), args_stack_position, _stack.size());
138
// return wrapper.invoke(arguments, host().getSemanticType());
142
variable::FunctionWrapper wrapper(function_origin);
143
variable::VariableSetWrapper_mutable arguments(_stack.stack(), args_stack_position, _stack.size());
145
return wrapper.invoke(arguments);
148
variable::Variable BaseMachine::getElement_implicit(const inout::Token & , const inout::Token & variable_name)
150
// Источник элемента: top(0)
152
if (_stack.back().origin().type() == variable::ValueType::Null)
153
return variable::error_variable(variable_name.location());
155
std::shared_ptr<variable::Object> record = _stack.back().origin().value().getObject();
157
const variable::Variable & element = record->getVariableByName(variable_name.lexeme());
159
if (element.type() != variable::ValueType::Null)
160
// Создаём ссылку на элемент (VariableRef).
161
// Возвращая имя, разрешается использовать элемент в левой части инициализации/присваивания
162
return { element.makeReference(), variable_name.location() };
164
throw AnalyzeException("BaseMachine::getElement_implicit",
165
variable_name.makeLocation(_files),
166
"Member '" + inout::toU8(variable_name.lexeme()) + "' not found");