loom

Форк
0
/
BaseAnalyzer.cpp 
174 строки · 6.3 Кб
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/BaseAnalyzer.h"
10
#include "simodo/interpret/AnalyzeException.h"
11
#include "simodo/variable/FunctionWrapper.h"
12
#include "simodo/inout/convert/functions.h"
13

14
#include <cassert>
15

16
inline const std::string EXCEEDED = "The number of errors has exceeded the allowable limit";
17

18
namespace 
19
{
20
    simodo::interpret::SemanticDataCollector_null null_collector;
21
}
22

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

26
BaseAnalyzer::BaseAnalyzer(Interpret * inter)
27
    : BaseInterpret_abstract(inter)
28
    , _collector(null_collector)
29
{
30
}
31

32
BaseAnalyzer::BaseAnalyzer(Interpret * inter, SemanticDataCollector_interface & collector)
33
    : BaseInterpret_abstract(inter)
34
    , _collector(collector)
35
{
36
}
37

38
void BaseAnalyzer::importNamespace(std::u16string name, variable::Object ns, inout::TokenLocation location) 
39
{
40
    BaseInterpret_abstract::importNamespace(name, ns, location);
41

42
    // machine().stack().top().origin().spec().set(u"module", true);
43

44
    _collector.collectNameDeclared(machine().stack().top());
45
}
46

47
InterpretState BaseAnalyzer::before_start()
48
{
49
    return BaseInterpret_abstract::before_start();
50
}
51

52
InterpretState BaseAnalyzer::before_finish(InterpretState state)
53
{
54
    return BaseInterpret_abstract::before_finish(state);
55
}
56

57
InterpretState BaseAnalyzer::performOperation(const ast::Node & op)
58
{
59
    inout::Location location {inout::null_location};
60

61
    try
62
    {
63
        return BaseInterpret_abstract::performOperation(op);
64
    }
65
    catch(const AnalyzeException & e)
66
    {
67
        location = e.location();
68
        inter().reporter().reportError(location, e.what());
69
        inter().setErrorSign();
70
        _number_of_mistakes ++;
71
    }
72

73
    if (_number_of_mistakes >= MAX_NUMBER_OF_MISTAKES) 
74
        throw AnalyzeException("ScriptAnalyzer::performOperation", 
75
                                op.token().makeLocation(inter().files()), 
76
                                EXCEEDED);
77
    
78
    return InterpretState::Flow;
79
}
80

81
InterpretState BaseAnalyzer::executePushValue(const inout::Token & variable_name)
82
{
83
    /// \note Перехватывать исключение AnalyzeException не нужно, т.к. оно обрабатывается в BaseAnalyzer::performOperation
84
    InterpretState state = BaseInterpret_abstract::executePushValue(variable_name);
85

86
    const variable::Variable & ref = machine().stack().top();
87

88
    if (ref.type() != variable::ValueType::Ref)
89
        return state; // Что-то пошло не так...
90

91
    const variable::Variable & var = ref.origin();
92

93
    _collector.collectNameUsed(var, variable_name.location());
94

95
    return state;
96
}
97

98
InterpretState BaseAnalyzer::executeObjectElement(const inout::Token & dot, const inout::Token & variable_name)
99
{
100
    /// \note Перехватывать исключение AnalyzeException не нужно, т.к. оно обрабатывается в BaseAnalyzer::performOperation
101
    InterpretState state = BaseInterpret_abstract::executeObjectElement(dot, variable_name);
102

103
    const variable::Variable & ref = machine().stack().top();
104

105
    if (ref.type() != variable::ValueType::Ref)
106
        return state; // Что-то пошло не так...
107

108
    const variable::Variable & var = ref.origin();
109

110
    _collector.collectNameUsed(var, variable_name.location());
111

112
    return state;
113
}
114

115
InterpretState BaseAnalyzer::executeFunctionCall(const ast::Node & op)
116
{
117
    size_t args_stack_position = machine().stack().size();
118

119
    inter().addFlowLayer(
120
                op, 
121
                [this, args_stack_position](FlowLayerInfo flow) {
122
                    variable::Value v;
123

124
                    if (!flow.error_sign) {
125
                        try {
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");
142
                            }
143
                        }
144
                        catch(...) {
145
                            // Перед выходом восстанавливаем ожидаемое состояние выполнения команды
146
                            machine().popAmount(machine().stack().size() - args_stack_position);
147
                            machine().pop();
148
                            machine().push(variable::null_variable()); 
149
                            throw;
150
                        }
151
                    }
152
                    machine().popAmount(machine().stack().size() - args_stack_position);
153
                    machine().pop();
154
                    machine().push(variable::null_variable()); 
155
                });
156
    
157
    return InterpretState::Flow;
158
}
159

160
InterpretState BaseAnalyzer::executeBlock(const ast::Node & op)
161
{
162
    if (op.token().lexeme() == u"{") {
163
        _open_scope.push_back(op.token().location());
164
    }
165
    else {
166
        assert(!_open_scope.empty());
167
        _collector.collectScoped(_open_scope.back(), op.token().location());
168
        _open_scope.pop_back();
169
    }
170

171
    return BaseInterpret_abstract::executeBlock(op);
172
}
173

174
}

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

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

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

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