#include <unordered_map>
#include <vector>
#include "wasm.h"
#include "../lattice.h"
#ifndef wasm_analysis_lattices_powerset_h
#define wasm_analysis_lattices_powerset_h
namespace wasm::analysis {
class FiniteIntPowersetLattice {
size_t setSize;
public:
FiniteIntPowersetLattice(size_t setSize) : setSize(setSize) {}
size_t getSetSize() { return setSize; }
class Element {
std::vector<bool> bitvector;
Element(size_t latticeSetSize) : bitvector(latticeSetSize) {}
public:
Element(Element&& source) = default;
Element(const Element& source) = default;
Element& operator=(Element&& source) = default;
Element& operator=(const Element& source) = default;
size_t count() const;
bool get(size_t index) { return bitvector[index]; }
void set(size_t index, bool value) { bitvector[index] = value; }
bool isTop() const { return count() == bitvector.size(); }
bool isBottom() const { return count() == 0; }
void print(std::ostream& os);
friend FiniteIntPowersetLattice;
};
LatticeComparison compare(const Element& left,
const Element& right) const noexcept;
Element getBottom() const noexcept;
bool join(Element& joinee, const Element& joiner) const noexcept;
};
template<typename T> class FinitePowersetLattice {
FiniteIntPowersetLattice intLattice;
std::vector<T> members;
std::unordered_map<T, size_t> memberIndices;
public:
using Element = FiniteIntPowersetLattice::Element;
FinitePowersetLattice(std::vector<T>&& setMembers)
: intLattice(setMembers.size()), members(std::move(setMembers)) {
for (size_t i = 0; i < members.size(); ++i) {
memberIndices[members[i]] = i;
}
}
using membersIterator = typename std::vector<T>::const_iterator;
membersIterator membersBegin() { return members.cbegin(); }
membersIterator membersEnd() { return members.cend(); }
size_t getSetSize() { return intLattice.getSetSize(); }
T indexToMember(size_t index) { return members[index]; }
size_t memberToIndex(T member) { return memberIndices[member]; }
void add(Element* element, T member) {
element->set(memberIndices[member], true);
}
void remove(Element* element, T member) {
element->set(memberIndices[member], false);
}
bool exists(Element* element, T member) {
return element->get(memberIndices[member]);
}
LatticeComparison compare(const Element& left,
const Element& right) const noexcept {
return intLattice.compare(left, right);
}
Element getBottom() const noexcept { return intLattice.getBottom(); }
bool join(Element& joinee, const Element& joiner) const noexcept {
return intLattice.join(joinee, joiner);
}
};
}
#include "powerset-impl.h"
#endif