#ifndef wasm_analysis_lattices_shared_h
#define wasm_analysis_lattices_shared_h
#include <cstdint>
#include <utility>
#include "../lattice.h"
#include "bool.h"
namespace wasm::analysis {
template<Lattice L> struct Shared {
using Seq = uint32_t;
class Element {
const typename L::Element* val;
Seq seq = 0;
Element(const typename L::Element* val) : val(val) {}
public:
Element() = default;
Element(const Element&) = default;
Element(Element&&) = default;
Element& operator=(const Element&) = default;
Element& operator=(Element&&) = default;
const typename L::Element& operator*() const noexcept { return *val; }
const typename L::Element* operator->() const noexcept { return val; }
bool operator==(const Element& other) const noexcept {
assert(val == other.val);
return seq == other.seq;
}
bool operator!=(const Element& other) const noexcept {
return !(*this == other);
}
friend Shared;
};
L lattice;
mutable typename L::Element val;
mutable Seq seq = 0;
Shared(L&& l) : lattice(std::move(l)), val(lattice.getBottom()) {}
Element getBottom() const noexcept { return Element{&val}; }
LatticeComparison compare(const Element& a, const Element& b) const noexcept {
assert(a.val == b.val);
return a.seq < b.seq ? LESS : a.seq == b.seq ? EQUAL : GREATER;
}
bool join(Element& joinee, const Element& joiner) const noexcept {
assert(joinee.val == joiner.val);
if (joinee.seq < joiner.seq) {
joinee.seq = joiner.seq;
return true;
}
return false;
}
template<typename Elem>
bool join(Element& joinee, const Elem& joiner) const noexcept {
if (lattice.join(val, joiner)) {
joinee.seq = ++seq;
return true;
}
return false;
}
};
template<typename L> Shared(L&&) -> Shared<L>;
#if __cplusplus >= 202002L
static_assert(Lattice<Shared<Bool>>);
#endif
}
#endif