instruction.hpp 2.36 KB
Newer Older
Paul's avatar
Paul committed
1
#ifndef RTG_GUARD_RTGLIB_INSTRUCTION_HPP
Paul's avatar
Paul committed
2
#define RTG_GUARD_RTGLIB_INSTRUCTION_HPP
Paul's avatar
Paul committed
3

Paul's avatar
Paul committed
4
#include <rtg/literal.hpp>
Paul's avatar
Paul committed
5
#include <rtg/shape.hpp>
Paul's avatar
Paul committed
6
#include <rtg/builtin.hpp>
Paul's avatar
Paul committed
7
#include <rtg/instruction_ref.hpp>
Paul's avatar
Paul committed
8
#include <rtg/erase.hpp>
Paul's avatar
Paul committed
9
#include <string>
Paul's avatar
Paul committed
10
11
12

namespace rtg {

Paul's avatar
Paul committed
13
14
shape compute_shape(operation op, std::vector<instruction_ref> args);

Paul's avatar
Paul committed
15
16
struct instruction
{
Paul's avatar
Paul committed
17
18
    instruction() {}

Paul's avatar
Paul committed
19
    instruction(operation o, shape r, std::vector<instruction_ref> args)
Paul's avatar
Paul committed
20
        : op(std::move(o)), result(std::move(r)), arguments(std::move(args))
Paul's avatar
Paul committed
21
22
    {
    }
Paul's avatar
Paul committed
23

Paul's avatar
Paul committed
24
    instruction(literal l) : op(builtin::literal{}), result(l.get_shape()), lit(std::move(l)) {}
Paul's avatar
Paul committed
25

Paul's avatar
Paul committed
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
    void replace(operation o, shape r, std::vector<instruction_ref> args)
    {
        op = o;
        replace(std::move(r));
        replace(std::move(args));
    }

    void replace(shape r)
    {
        if(r != result)
        {
            result = r;
            for(auto&& ins:output)
            {
                ins->replace(compute_shape(ins->op, ins->arguments));
            }
        }
    }


    void replace(std::vector<instruction_ref> args)
    {
        clear_arguments();
        arguments = std::move(args);
    }

    void clear_arguments()
    {
        for(auto&& arg:arguments)
        {
            rtg::erase(arg->output, *this);
        }
    }

    friend bool operator==(const instruction& i, instruction_ref ref)
    {
        return std::addressof(i) == std::addressof(*ref);
    }

    friend bool operator==(instruction_ref ref, const instruction& i)
    {
        return i == ref;
    }

    friend bool operator!=(const instruction& i, instruction_ref ref)
    {
        return !(i == ref);
    }

    friend bool operator!=(instruction_ref ref, const instruction& i)
    {
        return !(i == ref);
    }

Paul's avatar
Paul committed
80
    operation op;
Paul's avatar
Paul committed
81
    shape result;
Paul's avatar
Paul committed
82
    std::vector<instruction_ref> output;
Paul's avatar
Paul committed
83
    std::vector<instruction_ref> arguments;
Paul's avatar
Paul committed
84
    literal lit;
Paul's avatar
Paul committed
85
86
};

Paul's avatar
Paul committed
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
inline void backreference(instruction_ref ref)
{
    for(auto&& arg : ref->arguments)
        arg->output.push_back(ref);
}

// TODO: Move to a cpp file
// TODO: Use const ref for vector
inline shape compute_shape(operation op, std::vector<instruction_ref> args)
{
    std::vector<shape> shapes(args.size());
    std::transform(
        args.begin(), args.end(), shapes.begin(), [](instruction_ref i) { return i->result; });
    return op.compute_shape(shapes);
}

Paul's avatar
Paul committed
103
} // namespace rtg
Paul's avatar
Paul committed
104
105

#endif