Enforce exhaustiveness of make.

This commit is contained in:
Alexander McCord 2024-06-01 18:03:14 -07:00
parent 26f1d18c81
commit 2ef0ccd5e8
2 changed files with 57 additions and 33 deletions

View file

@ -3,6 +3,7 @@
#include "Luau/Common.h" #include "Luau/Common.h"
#include "Luau/Id.h" #include "Luau/Id.h"
#include "Luau/Language.h"
#include "Luau/UnionFind.h" #include "Luau/UnionFind.h"
#include "Luau/VecDeque.h" #include "Luau/VecDeque.h"
@ -23,9 +24,19 @@ struct Analysis final
using D = typename N::Data; using D = typename N::Data;
D make(const EGraph<L, N>& egraph, const L& enode) const template<typename T>
static D fnMake(const N& analysis, const EGraph<L, N>& egraph, const L& enode)
{ {
return analysis.make(egraph, enode); return analysis.make(egraph, *enode.template get<T>());
}
template<typename... Ts>
D make(const EGraph<L, N>& egraph, const Language<Ts...>& enode) const
{
using FnMake = D (*)(const N&, const EGraph<L, N>&, const L&);
static constexpr FnMake tableMake[sizeof...(Ts)] = {&fnMake<Ts>...};
return tableMake[enode.index()](analysis, egraph, enode);
} }
void join(D& a, const D& b) void join(D& a, const D& b)

View file

@ -32,38 +32,51 @@ struct ConstantFold
{ {
using Data = std::optional<bool>; using Data = std::optional<bool>;
Data make(const EGraph& egraph, const PropositionalLogic& enode) const Data make(const EGraph& egraph, const Var& var) const
{ {
if (enode.get<Var>()) return std::nullopt;
return std::nullopt; }
else if (auto b = enode.get<Bool>())
return b->value; Data make(const EGraph& egraph, const Bool& b) const
else if (auto n = enode.get<Not>()) {
{ return b.value;
if (auto data = egraph[n->field<Negated>()].data) }
return !*data;
} Data make(const EGraph& egraph, const Not& n) const
else if (auto a = enode.get<And>()) {
{ Data data = egraph[n.field<Negated>()].data;
Data left = egraph[a->field<Left>()].data; if (data)
Data right = egraph[a->field<Right>()].data; return !*data;
if (left && right)
return *left && *right; return std::nullopt;
} }
else if (auto o = enode.get<Or>())
{ Data make(const EGraph& egraph, const And& a) const
Data left = egraph[o->field<Left>()].data; {
Data right = egraph[o->field<Right>()].data; Data left = egraph[a.field<Left>()].data;
if (left && right) Data right = egraph[a.field<Right>()].data;
return *left && *right; if (left && right)
} return *left && *right;
else if (auto i = enode.get<Implies>())
{ return std::nullopt;
Data antecedent = egraph[i->field<Antecedent>()].data; }
Data consequent = egraph[i->field<Consequent>()].data;
if (antecedent && consequent) Data make(const EGraph& egraph, const Or& o) const
return !*antecedent || *consequent; {
} Data left = egraph[o.field<Left>()].data;
Data right = egraph[o.field<Right>()].data;
if (left && right)
return *left || *right;
return std::nullopt;
}
Data make(const EGraph& egraph, const Implies& i) const
{
Data antecedent = egraph[i.field<Antecedent>()].data;
Data consequent = egraph[i.field<Consequent>()].data;
if (antecedent && consequent)
return !*antecedent || *consequent;
return std::nullopt; return std::nullopt;
} }