source: icGREP/icgrep-devel/icgrep/pablo/expression_map.hpp @ 4667

Last change on this file since 4667 was 4646, checked in by nmedfort, 4 years ago

Fixed Multiplexing for new While structure/logic + Potential bug fix for PabloBuilder::Create.

File size: 6.1 KB
Line 
1#ifndef EXPRESSION_MAP_HPP
2#define EXPRESSION_MAP_HPP
3
4#include <map>
5#include <tuple>
6#include <pablo/pabloAST.h>
7
8namespace pablo {
9
10template<typename... Args>
11struct ExpressionMap {
12    enum {N = sizeof...(Args)};
13    typedef ExpressionMap<Args...> Type;
14    typedef std::tuple<PabloAST::ClassTypeId, Args...> Key;
15    friend struct ExpressionTable;
16
17    explicit ExpressionMap(Type * predecessor = nullptr) : mPredecessor(predecessor) { }
18
19    explicit ExpressionMap(Type && other) noexcept
20    : mPredecessor(other.mPredecessor)
21    , mMap(std::move(other.mMap)) {
22
23    }
24
25    ExpressionMap & operator=(Type && other) {
26        mPredecessor = other.mPredecessor;
27        mMap = std::move(other.mMap);
28        return *this;
29    }
30
31    template <class Functor, typename... Params>
32    inline PabloAST * findOrCall(Functor && functor, const PabloAST::ClassTypeId type, Args... args, Params... params) {
33        Key key = std::make_tuple(type, args...);
34        PabloAST * const f = find(key);
35        if (f) {
36            return f;
37        }
38        PabloAST * const object = functor(std::forward<Args>(args)..., std::forward<Params>(params)...);
39        mMap.insert(std::make_pair(std::move(key), object));
40        return object;
41    }
42
43    inline std::pair<PabloAST *, bool> findOrAdd(PabloAST * object, const PabloAST::ClassTypeId type, Args... args) {
44        Key key = std::make_tuple(type, args...);
45        PabloAST * const entry = find(key);
46        if (entry) {
47            return std::make_pair(entry, false);
48        }
49        mMap.insert(std::make_pair(std::move(key), object));
50        return std::make_pair(object, true);
51    }
52
53    inline bool erase(const PabloAST::ClassTypeId type, Args... args) {
54        Key key = std::make_tuple(type, args...);
55        auto itr = mMap.find(key);
56        if (itr == mMap.end()) {
57            return mPredecessor ? mPredecessor->erase(type, args...) : false;
58        }
59        mMap.erase(itr);
60        return true;
61    }
62
63    inline PabloAST * find(const PabloAST::ClassTypeId type, Args... args) const {
64        Key key = std::make_tuple(type, args...);
65        return find(key);
66    }
67
68private:
69
70    inline PabloAST * find(const Key & key) const {
71        // check this map to see if we have it
72        auto itr = mMap.find(key);
73        if (itr != mMap.end()) {
74            return itr->second;
75        }
76        // check any previous maps to see if it exists
77        auto * pred = mPredecessor;
78        while (pred) {
79            itr = pred->mMap.find(key);
80            if (itr == pred->mMap.end()) {
81                pred = pred->mPredecessor;
82                continue;
83            }
84            return itr->second;
85        }
86        return nullptr;
87    }
88
89private:
90    const Type *                mPredecessor;
91    std::map<Key, PabloAST *>   mMap;
92};
93
94
95struct ExpressionTable {
96
97    explicit ExpressionTable(const ExpressionTable * predecessor = nullptr) noexcept {
98        if (predecessor) {
99            mUnary.mPredecessor = &(predecessor->mUnary);
100            mBinary.mPredecessor = &(predecessor->mBinary);
101            mTernary.mPredecessor = &(predecessor->mTernary);
102        }
103    }
104
105    explicit ExpressionTable(ExpressionTable & other) = delete;
106
107    explicit ExpressionTable(ExpressionTable && other) noexcept
108    : mUnary(std::move(other.mUnary))
109    , mBinary(std::move(other.mBinary))
110    , mTernary(std::move(other.mTernary)) {
111
112    }
113
114    ExpressionTable & operator=(ExpressionTable && other) {
115        mUnary = std::move(other.mUnary);
116        mBinary = std::move(other.mBinary);
117        mTernary = std::move(other.mTernary);
118        return *this;
119    }
120
121
122    template <class Functor, typename... Params>
123    inline PabloAST * findUnaryOrCall(Functor && functor, const PabloAST::ClassTypeId type, PabloAST * expr, Params... params) {
124        return mUnary.findOrCall(std::move(functor), type, expr, std::forward<Params>(params)...);
125    }
126
127    template <class Functor, typename... Params>
128    inline PabloAST * findBinaryOrCall(Functor && functor, const PabloAST::ClassTypeId type, PabloAST * expr1, PabloAST * expr2, Params... params) {
129        return mBinary.findOrCall(std::move(functor), type, expr1, expr2, std::forward<Params>(params)...);
130    }
131
132    template <class Functor, typename... Params>
133    inline PabloAST * findTernaryOrCall(Functor && functor, const PabloAST::ClassTypeId type, PabloAST * expr1, PabloAST * expr2, PabloAST * expr3, Params... params) {
134        return mTernary.findOrCall(std::move(functor), type, expr1, expr2, expr3, std::forward<Params>(params)...);
135    }
136
137    std::pair<PabloAST *, bool> findOrAdd(Statement * stmt) {
138        switch (stmt->getClassTypeId()) {           
139            case PabloAST::ClassTypeId::Assign:
140            case PabloAST::ClassTypeId::Call:
141            case PabloAST::ClassTypeId::Var:
142            case PabloAST::ClassTypeId::Not:
143                return mUnary.findOrAdd(stmt, stmt->getClassTypeId(), stmt->getOperand(0));
144            case PabloAST::ClassTypeId::And:
145            case PabloAST::ClassTypeId::Or:
146            case PabloAST::ClassTypeId::Xor:
147                // test whether the communative version of this statement exists
148                if (PabloAST * commExpr = mBinary.find(stmt->getClassTypeId(), stmt->getOperand(1), stmt->getOperand(0))) {
149                    return std::make_pair(commExpr, false);
150                }
151            case PabloAST::ClassTypeId::Advance:
152            case PabloAST::ClassTypeId::ScanThru:
153            case PabloAST::ClassTypeId::MatchStar:
154            case PabloAST::ClassTypeId::Next:
155                return mBinary.findOrAdd(stmt, stmt->getClassTypeId(), stmt->getOperand(0), stmt->getOperand(1));
156            case PabloAST::ClassTypeId::Sel:
157                return mTernary.findOrAdd(stmt, stmt->getClassTypeId(), stmt->getOperand(0), stmt->getOperand(1), stmt->getOperand(2));
158            default:
159                return std::make_pair(stmt, true);
160        }
161    }
162
163
164private:
165    ExpressionMap<PabloAST *>                           mUnary;
166    ExpressionMap<PabloAST *, PabloAST *>               mBinary;
167    ExpressionMap<PabloAST *, PabloAST *, PabloAST *>   mTernary;
168};
169
170}
171
172#endif // EXPRESSION_MAP_HPP
Note: See TracBrowser for help on using the repository browser.