loom

Форк
0
/
BaseMachine.cpp 
169 строк · 6.2 Кб
1
/*
2
MIT License
3

4
Copyright (c) 2022 МГТУ им. Н.Э. Баумана, кафедра ИУ-6, Михаил Фетисов,
5

6
https://bmstu.codes/lsx/simodo/loom
7
*/
8

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"
16

17
#include <cassert>
18

19
namespace
20
{
21
    static const simodo::variable::Variable error = simodo::variable::error_variable();
22
}
23

24
namespace simodo::interpret::builtins
25
{
26

27
BaseMachine::BaseMachine(const inout::uri_set_t & files)
28
    : _files(files)
29
    , _stack()
30
    , _return_variable(variable::null_variable())
31
{
32
}
33

34
void BaseMachine::reset()
35
{
36
    /// \todo BaseMachine::reset()
37
}
38

39
void BaseMachine::push(variable::Variable v)
40
{
41
    _stack.push(v);
42
}
43

44
void BaseMachine::pushRef(const variable::Variable & v, const inout::TokenLocation & location)
45
{
46
    const variable::Variable & o = v.origin();
47

48
    // _stack.push({ o.name(), variable::VariableRef {o}, location(), {} });
49
    _stack.push( variable::Variable { variable::VariableRef(o), location } );
50
}
51

52
void BaseMachine::pushRef(variable::VariableRef ref)
53
{
54
    // _stack.push({ ref.origin().name(), ref, ref.origin().location()(), {} });
55
    _stack.push( { ref, ref.origin().location() } );
56
}
57

58
variable::Variable BaseMachine::pop()                           
59
{ 
60
    return _stack.pop(); 
61
} 
62

63
void BaseMachine::popAmount(size_t n)
64
{
65
    _stack.popAmount(n); 
66
}
67

68
variable::VariableRef BaseMachine::findVariable(const inout::Token & variable_name) const
69
{
70
    /// \todo Не забыть переделать под ограничения фреймов вызовов и другие механизмы
71

72
    variable::VariableSetWrapper search_area(_stack.stack(), 0, _stack.size());
73

74
    variable::VariableRef ref = find(search_area, variable_name.lexeme());
75

76
    if (ref.origin().name().empty())
77
        throw AnalyzeException("BaseMachine::findVariable", 
78
                                variable_name.makeLocation(_files),
79
                                "Переменная '" + inout::toU8(variable_name.lexeme()) + "' не найдена");
80

81
    return ref;
82
}
83

84
variable::VariableRef BaseMachine::find(variable::VariableSetWrapper & search_area, const std::u16string & variable_name) const
85
{
86
    // Поиск ведётся с конца, чтобы корректно работал поиск переменных по истории их объявления с учётом блоков кода
87

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();
91

92
    return error.makeReference();
93
}
94

95
void BaseMachine::checkProcedureCalled()
96
{
97
    /// \todo BaseMachine::checkProcedureCalled()
98
}
99

100
variable::Variable BaseMachine::createVariable_implicit(const inout::Token & constant_value) const
101
{
102
    switch(constant_value.type())
103
    {
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(), {} };
117
    default:
118
        break;
119
    }
120

121
    throw bormental::DrBormental("BaseMachine::createVariable_implicit", 
122
                    inout::fmt("Invalid internal constant type to convert (%1)")
123
                    .arg(getLexemeTypeName(constant_value.type())));
124
}
125

126
variable::Value BaseMachine::callFunction_implicit(const inout::Token & , size_t args_stack_position)
127
{
128
    const variable::Variable & function_origin = _stack.at(args_stack_position-1).origin();
129

130
    if (function_origin.type() == variable::ValueType::Null)
131
        return {};
132

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());
137

138
        // return wrapper.invoke(arguments, host().getSemanticType());
139
        return {};
140
    }
141

142
    variable::FunctionWrapper            wrapper(function_origin);
143
    variable::VariableSetWrapper_mutable arguments(_stack.stack(), args_stack_position, _stack.size());
144

145
    return wrapper.invoke(arguments);
146
}
147

148
variable::Variable BaseMachine::getElement_implicit(const inout::Token & , const inout::Token & variable_name) 
149
{
150
    // Источник элемента: top(0)
151

152
    if (_stack.back().origin().type() == variable::ValueType::Null)
153
        return variable::error_variable(variable_name.location());
154

155
    std::shared_ptr<variable::Object> record = _stack.back().origin().value().getObject();
156
    
157
    const variable::Variable & element = record->getVariableByName(variable_name.lexeme());
158

159
    if (element.type() != variable::ValueType::Null)
160
        // Создаём ссылку на элемент (VariableRef).
161
        // Возвращая имя, разрешается использовать элемент в левой части инициализации/присваивания 
162
        return { element.makeReference(), variable_name.location() };
163
    
164
    throw AnalyzeException("BaseMachine::getElement_implicit", 
165
                           variable_name.makeLocation(_files),
166
                           "Member '" + inout::toU8(variable_name.lexeme()) + "' not found");
167
}
168

169
}

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

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

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

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