• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ArkScript-lang / Ark / 11629611787

01 Nov 2024 12:48PM UTC coverage: 77.319% (+0.3%) from 77.042%
11629611787

push

github

SuperFola
feat(tests): adding first test for IR generation and optimization

5209 of 6737 relevant lines covered (77.32%)

9473.78 hits per line

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

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

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

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

14
    IROptimizer::IROptimizer(const unsigned debug) :
200✔
15
        m_logger("IROptimizer", debug)
100✔
16
    {}
200✔
17

18
    void IROptimizer::process(const std::vector<IR::Block>& pages, const std::vector<std::string>& symbols, const std::vector<ValTableElem>& values)
27✔
19
    {
27✔
20
        m_logger.traceStart("process");
27✔
21
        m_symbols = symbols;
27✔
22
        m_values = values;
27✔
23

24
        auto map = []<typename T>(const std::optional<T>& opt, auto&& lambda) -> decltype(std::optional(lambda(opt.value()))) {
14,863✔
25
            if (opt.has_value())
14,836✔
26
                return lambda(opt.value());
1,002✔
27
            return std::nullopt;
13,834✔
28
        };
14,836✔
29

30
        auto or_else = []<typename T>(const std::optional<T>& opt, auto&& lambda) -> std::optional<T> {
7,860✔
31
            if (!opt.has_value())
7,833✔
32
                return lambda();
6,882✔
33
            return opt;
951✔
34
        };
7,833✔
35

36
        for (const auto& block : pages)
160✔
37
        {
38
            m_ir.emplace_back();
133✔
39
            IR::Block& current_block = m_ir.back();
133✔
40

41
            std::size_t i = 0;
133✔
42
            const std::size_t end = block.size();
133✔
43

44
            while (i < end)
8,207✔
45
            {
46
                std::optional<EntityWithOffset> maybe_compacted = std::nullopt;
8,074✔
47

48
                if (i + 1 < end)
8,074✔
49
                    maybe_compacted = map(
15,908✔
50
                        compactEntities(block[i], block[i + 1]),
7,954✔
51
                        [](const auto& entity) {
8,918✔
52
                            return std::make_optional<EntityWithOffset>(entity, 2);
964✔
53
                        });
54
                if (i + 2 < end)
8,074✔
55
                    maybe_compacted = or_else(
7,833✔
56
                        maybe_compacted,
57
                        [&, this]() {
14,715✔
58
                            return map(
13,764✔
59
                                compactEntities(block[i], block[i + 1], block[i + 2]),
6,882✔
60
                                [](const auto& entity) {
6,920✔
61
                                    return std::make_optional<EntityWithOffset>(entity, 3);
38✔
62
                                });
63
                        });
64

65
                if (maybe_compacted.has_value())
8,074✔
66
                {
67
                    auto [entity, offset] = maybe_compacted.value();
1,002✔
68
                    current_block.emplace_back(entity);
1,002✔
69
                    i += offset;
1,002✔
70
                }
1,002✔
71
                else
72
                {
73
                    current_block.emplace_back(block[i]);
7,072✔
74
                    ++i;
7,072✔
75
                }
76
            }
8,074✔
77
        }
133✔
78

79
        m_logger.traceEnd();
27✔
80
    }
27✔
81

82
    const std::vector<IR::Block>& IROptimizer::intermediateRepresentation() const noexcept
27✔
83
    {
27✔
84
        return m_ir;
27✔
85
    }
86

87
    std::optional<IR::Entity> IROptimizer::compactEntities(const IR::Entity& first, const IR::Entity& second)
7,954✔
88
    {
7,954✔
89
        if (first.primaryArg() > IR::MaxValueForDualArg || second.primaryArg() > IR::MaxValueForDualArg)
7,954✔
90
            return std::nullopt;
×
91

92
        // LOAD_CONST x
93
        // LOAD_CONST y
94
        // ---> LOAD_CONST_LOAD_CONST x y
95
        if (first.inst() == LOAD_CONST && second.inst() == LOAD_CONST)
7,954✔
96
            return IR::Entity(LOAD_CONST_LOAD_CONST, first.primaryArg(), second.primaryArg());
633✔
97
        // LOAD_CONST x
98
        // STORE / SET_VAL a
99
        // ---> LOAD_CONST_STORE x a ; LOAD_CONST_SET_VAL x a
100
        if (first.inst() == LOAD_CONST && second.inst() == STORE)
7,321✔
101
            return IR::Entity(LOAD_CONST_STORE, first.primaryArg(), second.primaryArg());
143✔
102
        if (first.inst() == LOAD_CONST && second.inst() == SET_VAL)
7,178✔
103
            return IR::Entity(LOAD_CONST_SET_VAL, first.primaryArg(), second.primaryArg());
4✔
104
        // LOAD_SYMBOL a
105
        // STORE / SET_VAL b
106
        // ---> STORE_FROM a b ; SET_VAL_FROM a b
107
        if (first.inst() == LOAD_SYMBOL && second.inst() == STORE)
7,174✔
108
            return IR::Entity(STORE_FROM, first.primaryArg(), second.primaryArg());
7✔
109
        if (first.inst() == LOAD_SYMBOL && second.inst() == SET_VAL)
7,167✔
110
            return IR::Entity(SET_VAL_FROM, first.primaryArg(), second.primaryArg());
4✔
111
        // BUILTIN i
112
        // CALL n
113
        // ---> CALL_BUILTIN i n
114
        if (first.inst() == BUILTIN && second.inst() == CALL && Builtins::builtins[first.primaryArg()].second.isFunction())
7,163✔
115
            return IR::Entity(CALL_BUILTIN, first.primaryArg(), second.primaryArg());
173✔
116

117
        return std::nullopt;
6,990✔
118
    }
7,954✔
119

120
    std::optional<IR::Entity> IROptimizer::compactEntities(const IR::Entity& first, const IR::Entity& second, const IR::Entity& third)
6,882✔
121
    {
6,882✔
122
        if (first.primaryArg() > IR::MaxValueForDualArg || second.primaryArg() > IR::MaxValueForDualArg || third.primaryArg() > IR::MaxValueForDualArg)
6,882✔
123
            return std::nullopt;
×
124

125
        // LOAD_SYMBOL a
126
        // LOAD_CONST n (1)
127
        // ADD / SUB
128
        // ---> INCREMENT / DECREMENT a
129
        if (third.inst() == ADD && first.inst() == LOAD_CONST && second.inst() == LOAD_SYMBOL && isNumber(first.primaryArg(), 1))
6,882✔
130
            return IR::Entity(INCREMENT, second.primaryArg());
27✔
131
        if (third.inst() == ADD && first.inst() == LOAD_SYMBOL && second.inst() == LOAD_CONST && isNumber(second.primaryArg(), 1))
6,855✔
132
            return IR::Entity(INCREMENT, first.primaryArg());
5✔
133
        if (third.inst() == SUB && first.inst() == LOAD_SYMBOL && second.inst() == LOAD_CONST && isNumber(second.primaryArg(), 1))
6,850✔
134
            return IR::Entity(DECREMENT, first.primaryArg());
6✔
135
        // LOAD_SYMBOL list
136
        // TAIL / HEAD
137
        // STORE / SET_VAL a
138
        // ---> STORE_TAIL list a ; STORE_HEAD ; SET_VAL_TAIL ; SET_VAL_HEAD
139
        if (first.inst() == LOAD_SYMBOL && second.inst() == TAIL && third.inst() == STORE)
6,844✔
140
            return IR::Entity(STORE_TAIL, first.primaryArg(), third.primaryArg());
×
141
        if (first.inst() == LOAD_SYMBOL && second.inst() == TAIL && third.inst() == SET_VAL)
6,844✔
142
            return IR::Entity(SET_VAL_TAIL, first.primaryArg(), third.primaryArg());
×
143
        if (first.inst() == LOAD_SYMBOL && second.inst() == HEAD && third.inst() == STORE)
6,844✔
144
            return IR::Entity(STORE_HEAD, first.primaryArg(), third.primaryArg());
×
145
        if (first.inst() == LOAD_SYMBOL && second.inst() == HEAD && third.inst() == SET_VAL)
6,844✔
146
            return IR::Entity(SET_VAL_HEAD, first.primaryArg(), third.primaryArg());
×
147

148
        return std::nullopt;
6,844✔
149
    }
6,882✔
150

151
    bool IROptimizer::isNumber(const uint16_t id, const double expected_number) const
38✔
152
    {
38✔
153
        return std::cmp_less(id, m_values.size()) && m_values[id].type == ValTableElemType::Number && std::get<double>(m_values[id].value) == expected_number;
38✔
154
    }
155
}
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