• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

ArkScript-lang / Ark / 14012558627

22 Mar 2025 09:33PM UTC coverage: 79.378% (+0.5%) from 78.852%
14012558627

push

github

SuperFola
chore: cleaning up dead code and old todos

6 of 14 new or added lines in 5 files covered. (42.86%)

248 existing lines in 6 files now uncovered.

6047 of 7618 relevant lines covered (79.38%)

77956.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.67
/src/arkreactor/Compiler/IntermediateRepresentation/IROptimizer.cpp
1
#include <Ark/Compiler/IntermediateRepresentation/IROptimizer.hpp>
2

3
#include <cassert>
4
#include <utility>
5
#include <Ark/Builtins/Builtins.hpp>
6

7
namespace Ark::internal
8
{
9
    struct EntityWithOffset
10
    {
11
        IR::Entity entity;
12
        std::size_t offset;
13
    };
14

15
    IROptimizer::IROptimizer(const unsigned debug) :
396✔
16
        m_logger("IROptimizer", debug)
198✔
17
    {
198✔
18
        m_ruleset_two = {
1,782✔
19
            Rule {
198✔
20
                { LOAD_CONST, LOAD_CONST }, LOAD_CONST_LOAD_CONST },
198✔
21
            Rule {
396✔
22
                { LOAD_CONST, STORE }, LOAD_CONST_STORE },
198✔
23
            Rule {
396✔
24
                { LOAD_CONST, SET_VAL }, LOAD_CONST_SET_VAL },
198✔
25
            Rule {
396✔
26
                { LOAD_SYMBOL, STORE }, STORE_FROM },
198✔
27
            Rule {
396✔
28
                { LOAD_SYMBOL_BY_INDEX, STORE }, STORE_FROM_INDEX },
198✔
29
            Rule {
396✔
30
                { LOAD_SYMBOL, SET_VAL }, SET_VAL_FROM },
198✔
31
            Rule {
396✔
32
                { LOAD_SYMBOL_BY_INDEX, SET_VAL }, SET_VAL_FROM_INDEX },
198✔
33
            Rule {
396✔
34
                { BUILTIN, CALL }, CALL_BUILTIN, [](const Entities& entities) {
699✔
35
                    return Builtins::builtins[entities[0].primaryArg()].second.isFunction();
501✔
36
                } }
37
        };
38

39
        m_ruleset_three = {
2,970✔
40
            // LOAD_SYMBOL a / LOAD_SYMBOL_BY_INDEX index
41
            // LOAD_CONST n (1)
42
            // ADD / SUB
43
            // ---> INCREMENT / DECREMENT a value
44
            Rule {
198✔
45
                { LOAD_CONST, LOAD_SYMBOL, ADD }, INCREMENT, [this](const Entities& e) {
593✔
46
                    return isPositiveNumberInlinable(e[0].primaryArg());
395✔
47
                },
48
                [this](const Entities& e) {
593✔
49
                    return std::make_pair(e[1].primaryArg(), numberAsArg(e[0].primaryArg()));
395✔
50
                } },
51
            Rule { { LOAD_SYMBOL, LOAD_CONST, ADD }, INCREMENT, [this](const Entities& e) {
241✔
52
                      return isPositiveNumberInlinable(e[1].primaryArg());
43✔
53
                  },
54
                   [this](const Entities& e) {
241✔
55
                       return std::make_pair(e[0].primaryArg(), numberAsArg(e[1].primaryArg()));
43✔
56
                   } },
57
            Rule { { LOAD_SYMBOL, LOAD_CONST, SUB }, DECREMENT, [this](const Entities& e) {
213✔
58
                      return isPositiveNumberInlinable(e[1].primaryArg());
2,985✔
59
                  },
60
                   [this](const Entities& e) {
213✔
61
                       return std::make_pair(e[0].primaryArg(), numberAsArg(e[1].primaryArg()));
15✔
62
                   } },
1,584✔
63
            Rule { { LOAD_CONST, LOAD_SYMBOL_BY_INDEX, ADD }, INCREMENT_BY_INDEX, [this](const Entities& e) {
244✔
64
                      return isPositiveNumberInlinable(e[0].primaryArg());
46✔
65
                  },
66
                   [this](const Entities& e) {
244✔
67
                       return std::make_pair(e[1].primaryArg(), numberAsArg(e[0].primaryArg()));
46✔
68
                   } },
69
            Rule { { LOAD_SYMBOL_BY_INDEX, LOAD_CONST, ADD }, INCREMENT_BY_INDEX, [this](const Entities& e) {
216✔
70
                      return isPositiveNumberInlinable(e[1].primaryArg());
18✔
71
                  },
72
                   [this](const Entities& e) {
203✔
73
                       return std::make_pair(e[0].primaryArg(), numberAsArg(e[1].primaryArg()));
5✔
74
                   } },
75
            Rule { { LOAD_SYMBOL_BY_INDEX, LOAD_CONST, SUB }, DECREMENT_BY_INDEX, [this](const Entities& e) {
254✔
76
                      return isPositiveNumberInlinable(e[1].primaryArg());
56✔
77
                  },
78
                   [this](const Entities& e) {
253✔
79
                       return std::make_pair(e[0].primaryArg(), numberAsArg(e[1].primaryArg()));
55✔
80
                   } },
81
            // LOAD_SYMBOL list
82
            // TAIL / HEAD
83
            // STORE / SET_VAL a
84
            // ---> STORE_TAIL list a ; STORE_HEAD ; SET_VAL_TAIL ; SET_VAL_HEAD
85
            Rule { .expected = { LOAD_SYMBOL, TAIL, STORE }, .replacement = STORE_TAIL, .createReplacement = [](const Entities& e) {
199✔
86
                      return std::make_pair(e[0].primaryArg(), e[2].primaryArg());
1✔
87
                  } },
88
            Rule { .expected = { LOAD_SYMBOL, TAIL, SET_VAL }, .replacement = SET_VAL_TAIL, .createReplacement = [](const Entities& e) {
199✔
89
                      return std::make_pair(e[0].primaryArg(), e[2].primaryArg());
1✔
90
                  } },
91
            Rule { .expected = { LOAD_SYMBOL, HEAD, STORE }, .replacement = STORE_HEAD, .createReplacement = [](const Entities& e) {
199✔
92
                      return std::make_pair(e[0].primaryArg(), e[2].primaryArg());
1✔
93
                  } },
94
            Rule { .expected = { LOAD_SYMBOL, HEAD, SET_VAL }, .replacement = SET_VAL_HEAD, .createReplacement = [](const Entities& e) {
199✔
95
                      return std::make_pair(e[0].primaryArg(), e[2].primaryArg());
1✔
96
                  } },
97
            Rule { .expected = { LOAD_SYMBOL_BY_INDEX, TAIL, STORE }, .replacement = STORE_TAIL_BY_INDEX, .createReplacement = [](const Entities& e) {
200✔
98
                      return std::make_pair(e[0].primaryArg(), e[2].primaryArg());
2✔
99
                  } },
100
            Rule { .expected = { LOAD_SYMBOL_BY_INDEX, TAIL, SET_VAL }, .replacement = SET_VAL_TAIL_BY_INDEX, .createReplacement = [](const Entities& e) {
200✔
101
                      return std::make_pair(e[0].primaryArg(), e[2].primaryArg());
2✔
102
                  } },
103
            Rule { .expected = { LOAD_SYMBOL_BY_INDEX, HEAD, STORE }, .replacement = STORE_HEAD_BY_INDEX, .createReplacement = [](const Entities& e) {
201✔
104
                      return std::make_pair(e[0].primaryArg(), e[2].primaryArg());
3✔
105
                  } },
106
            Rule { .expected = { LOAD_SYMBOL_BY_INDEX, HEAD, SET_VAL }, .replacement = SET_VAL_HEAD_BY_INDEX, .createReplacement = [](const Entities& e) {
200✔
107
                      return std::make_pair(e[0].primaryArg(), e[2].primaryArg());
2✔
108
                  } }
109
        };
110
    }
198✔
111

112
    void IROptimizer::process(const std::vector<IR::Block>& pages, const std::vector<std::string>& symbols, const std::vector<ValTableElem>& values)
89✔
113
    {
89✔
114
        m_logger.traceStart("process");
89✔
115
        m_symbols = symbols;
89✔
116
        m_values = values;
89✔
117

118
        auto map = []<typename T>(const std::optional<T>& opt, auto&& lambda) -> decltype(std::optional(lambda(opt.value()))) {
69,476✔
119
            if (opt.has_value())
69,387✔
120
                return lambda(opt.value());
4,173✔
121
            return std::nullopt;
65,214✔
122
        };
69,387✔
123

124
        auto or_else = []<typename T>(const std::optional<T>& opt, auto&& lambda) -> std::optional<T> {
35,976✔
125
            if (!opt.has_value())
35,887✔
126
                return lambda();
32,313✔
127
            return opt;
3,574✔
128
        };
35,887✔
129

130
        for (const auto& block : pages)
1,397✔
131
        {
132
            m_ir.emplace_back();
1,308✔
133
            IR::Block& current_block = m_ir.back();
1,308✔
134

135
            std::size_t i = 0;
1,308✔
136
            const std::size_t end = block.size();
1,308✔
137

138
            while (i < end)
39,662✔
139
            {
140
                std::optional<EntityWithOffset> maybe_compacted = std::nullopt;
38,354✔
141

142
                if (i + 1 < end)
38,354✔
143
                    maybe_compacted = map(
74,148✔
144
                        replaceWithRules(m_ruleset_two, { block[i], block[i + 1] }),
37,074✔
145
                        [](const auto& entity) {
40,675✔
146
                            return std::make_optional<EntityWithOffset>(entity, 2);
3,601✔
147
                        });
148
                if (i + 2 < end)
38,354✔
149
                    maybe_compacted = or_else(
35,887✔
150
                        maybe_compacted,
151
                        [&, this]() {
68,200✔
152
                            return map(
64,626✔
153
                                replaceWithRules(m_ruleset_three, { block[i], block[i + 1], block[i + 2] }),
32,313✔
154
                                [](const auto& entity) {
32,885✔
155
                                    return std::make_optional<EntityWithOffset>(entity, 3);
572✔
156
                                });
UNCOV
157
                        });
×
158

159
                if (maybe_compacted.has_value())
38,354✔
160
                {
161
                    auto [entity, offset] = maybe_compacted.value();
4,173✔
162
                    current_block.emplace_back(entity);
4,173✔
163
                    i += offset;
4,173✔
164
                }
4,173✔
165
                else
166
                {
167
                    current_block.emplace_back(block[i]);
34,181✔
168
                    ++i;
34,181✔
169
                }
170
            }
38,354✔
171
        }
1,308✔
172

173
        m_logger.traceEnd();
89✔
174
    }
89✔
175

176
    const std::vector<IR::Block>& IROptimizer::intermediateRepresentation() const noexcept
89✔
177
    {
89✔
178
        return m_ir;
89✔
179
    }
180

181
    bool IROptimizer::match(const std::vector<Instruction>& expected_insts, const Entities& entities) const
722,402✔
182
    {
722,402✔
183
        assert(expected_insts.size() == entities.size() && "Mismatching size between expected instructions and given entities");
722,402✔
184

185
        for (std::size_t i = 0; i < expected_insts.size(); ++i)
1,534,363✔
186
        {
187
            if (expected_insts[i] != entities[i].inst())
811,961✔
188
                return false;
718,213✔
189
        }
93,748✔
190

191
        return true;
4,189✔
192
    }
722,402✔
193

194
    std::optional<IR::Entity> IROptimizer::replaceWithRules(const std::vector<Rule>& rules, const Entities& entities)
69,387✔
195
    {
69,387✔
196
        for (auto&& entity : entities)
240,474✔
197
        {
198
            if (entity.primaryArg() > IR::MaxValueForDualArg)
171,087✔
UNCOV
199
                return std::nullopt;
×
200
        }
171,087✔
201

202
        for (const auto& [expected, replacement, condition, createReplacement] : rules)
804,324✔
203
        {
204
            if (match(expected, entities) && condition(entities))
722,402✔
205
            {
206
                auto [first, second] = createReplacement(entities);
8,346✔
207
                return IR::Entity(replacement, first, second);
16,692✔
208
            }
4,173✔
209
        }
722,402✔
210

211
        return std::nullopt;
65,214✔
212
    }
69,387✔
213

214
    bool IROptimizer::isPositiveNumberInlinable(const uint16_t id) const
573✔
215
    {
573✔
216
        if (std::cmp_less(id, m_values.size()) && m_values[id].type == ValTableElemType::Number)
573✔
217
        {
218
            const double val = std::get<double>(m_values[id].value);
562✔
219
            return val >= 0.0 &&
1,124✔
220
                val < IR::MaxValueForDualArg &&
562✔
221
                static_cast<double>(static_cast<long>(val)) == val;
561✔
222
        }
562✔
223
        return false;
11✔
224
    }
573✔
225

226
    uint16_t IROptimizer::numberAsArg(const uint16_t id) const
559✔
227
    {
559✔
228
        return static_cast<uint16_t>(std::get<double>(m_values[id].value));
559✔
229
    }
230
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc