program.hpp 2.1 KB
Newer Older
Paul's avatar
Paul committed
1
2
3
#ifndef GUARD_RTGLIB_PROGRAM_HPP
#define GUARD_RTGLIB_PROGRAM_HPP

Paul's avatar
Paul committed
4
#include <list>
Paul's avatar
Paul committed
5
6
#include <unordered_map>
#include <rtg/instruction.hpp>
Paul's avatar
Paul committed
7
#include <rtg/operand.hpp>
Paul's avatar
Paul committed
8
#include <rtg/builtin.hpp>
Paul's avatar
Paul committed
9
#include <algorithm>
Paul's avatar
Paul committed
10
11
12
13
14

namespace rtg {

struct program
{
Paul's avatar
Paul committed
15
16
17
18
19
    // TODO: A program should be copyable
    program() = default;
    program(const program&) = delete;
    program& operator=(const program&) = delete;

Paul's avatar
Paul committed
20
    template<class... Ts>
Paul's avatar
Paul committed
21
    instruction * add_instruction(operand op, Ts*... args)
Paul's avatar
Paul committed
22
23
    {
        shape r = op.compute_shape({args->result...});
Paul's avatar
Paul committed
24
        instructions.push_back({op, r, {args...}});
Paul's avatar
Paul committed
25
26
        return std::addressof(instructions.back());
    }
Paul's avatar
Paul committed
27
28
29
30
31
32
33
34
35
36
    instruction * add_instruction(operand op, std::vector<instruction*> args)
    {
        assert(std::all_of(args.begin(), args.end(), [&](instruction* x) { return has_instruction(x); }) && "Argument is not an exisiting instruction");
        std::vector<shape> shapes(args.size());
        std::transform(args.begin(), args.end(), shapes.begin(), [](instruction* ins) { return ins->result; });
        shape r = op.compute_shape(shapes);
        instructions.push_back({op, r, args});
        assert(instructions.back().arguments == args);
        return std::addressof(instructions.back());
    }
Paul's avatar
Paul committed
37
38
39
40
41
42
43
    template<class... Ts>
    instruction * add_literal(Ts&&... xs)
    {
        instructions.emplace_back(literal{std::forward<Ts>(xs)...});
        return std::addressof(instructions.back());
    }

Paul's avatar
Paul committed
44
45
    instruction * add_parameter(std::string name, shape s)
    {
Paul's avatar
Paul committed
46
        instructions.push_back({builtin::param{std::move(name)}, s, {}});
Paul's avatar
Paul committed
47
48
49
50
        return std::addressof(instructions.back());
    }

    literal eval(std::unordered_map<std::string, argument> params) const;
Paul's avatar
Paul committed
51

Paul's avatar
Paul committed
52
53
54
    // TODO: Change to stream operator
    void print() const;

Paul's avatar
Paul committed
55
56
57
58
59
    bool has_instruction(const instruction * ins) const
    {
        return std::find_if(instructions.begin(), instructions.end(), [&](const instruction& x) {return ins == std::addressof(x); }) != instructions.end();
    }

Paul's avatar
Paul committed
60
61
62
private:
    // A list is used to keep references to an instruction stable
    std::list<instruction> instructions;
Paul's avatar
Paul committed
63
64
65
66
67
};

}

#endif