#ifndef wasm_analysis_lattices_lift_h
#define wasm_analysis_lattices_lift_h
#include <optional>
#include <utility>
#include "../lattice.h"
#include "bool.h"
namespace wasm::analysis {
template<Lattice L> struct Lift {
struct Element : std::optional<typename L::Element> {
bool isBottom() const noexcept { return !this->has_value(); }
bool operator==(const Element& other) const noexcept {
return (isBottom() && other.isBottom()) ||
(!isBottom() && !other.isBottom() && **this == *other);
}
};
L lattice;
Lift(L&& lattice) : lattice(std::move(lattice)) {}
Element getBottom() const noexcept { return {std::nullopt}; }
Element get(typename L::Element&& val) const noexcept {
return Element{std::move(val)};
}
LatticeComparison compare(const Element& a, const Element& b) const noexcept {
if (a.isBottom() && b.isBottom()) {
return EQUAL;
} else if (a.isBottom()) {
return LESS;
} else if (b.isBottom()) {
return GREATER;
} else {
return lattice.compare(*a, *b);
}
}
bool join(Element& joinee, const Element& joiner) const noexcept {
if (joinee.isBottom() && joiner.isBottom()) {
return false;
} else if (joinee.isBottom()) {
joinee = joiner;
return true;
} else if (joiner.isBottom()) {
return false;
} else {
return lattice.join(*joinee, *joiner);
}
}
};
template<typename L> Lift(L&&) -> Lift<L>;
#if __cplusplus >= 202002L
static_assert(Lattice<Lift<Bool>>);
#endif
}
#endif