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

Last change on this file since 4599 was 4443, checked in by nmedfort, 5 years ago

Temporary check in.

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