24 auto& world = type->world();
32 return world.call(
quant::star, optional_app->arg());
37 if (
auto quant_app =
Axm::isa<quant>(arg))
return world.app(callee, quant_app->arg());
49template<
class ConjOrDisj>
51 assert(!args.empty());
52 auto& world = args.front()->world();
53 return std::accumulate(args.begin() + 1, args.end(), args.front(), [&world](
const Def* lhs,
const Def* rhs) {
54 return world.call<ConjOrDisj, false>(Defs{lhs, rhs});
59 auto& world = type->world();
60 world.log().d(
"conj {}: {} ({})", callee, type, arg);
64 case 0:
return world.annex<
empty>();
67 if (
auto args = detail::flatten_in_arg<conj>(arg); !args.empty())
70 return world.annex<
empty>();
78 if (
auto r =
Axm::isa<range>(
d); r && r->arg(2, 0)->isa<Lit>() && r->arg(2, 1)->isa<
Lit>())
return r;
86 if (lhs_range && rhs_range)
return Lit::as(lhs_range->arg(2, 0)) <
Lit::as(rhs_range->arg(2, 0));
88 if (lhs_range)
return false;
89 if (rhs_range)
return true;
91 return lhs->
gid() < rhs->
gid();
95 std::stable_sort(args.begin(), args.end(), &
compare_re);
97 auto new_end = std::unique(args.begin(), args.end());
98 args.erase(new_end, args.end());
113 auto ranges_begin = args.begin();
114 while (ranges_begin != args.end() && !
lit_range(*ranges_begin))
116 if (ranges_begin == args.end())
return;
119 auto& world = (*ranges_begin)->world();
121 std::transform(ranges_begin, args.end(), std::back_inserter(old_ranges),
get_range);
123 auto new_ranges =
automaton::merge_ranges(old_ranges, [&world](std::string_view msg) { world.log().d(
"{}", msg); });
126 args.erase(ranges_begin, args.end());
127 std::transform(new_ranges.begin(), new_ranges.end(), std::back_inserter(args),
app_range{world});
133 auto check_arg_equiv = [](
const Def* lhs,
const Def* rhs) {
136 if (
auto rng_rhs =
Axm::isa<range>(not_rhs->arg()))
return rng_lhs == rng_rhs;
141 return check_arg_equiv(lhs, rhs) || check_arg_equiv(rhs, lhs);
146 auto rhs_view = negated_rhs | to_range;
148 if (std::ranges::distance(rhs_view) != std::ranges::distance(negated_rhs))
return false;
150 return std::ranges::includes(lhs | to_range, rhs_view);
154 auto& world = type->world();
160 auto new_args = detail::flatten_in_arg<disj>(arg);
163 auto make_any = [&world](
DefVec args) {
166 args.emplace_back(world.annex<
any>());
167 if (args.size() == 1)
return args.front();
173 return make_any(new_args);
177 for (
const auto* cls0 : new_args) {
178 for (
const auto* cls1 : new_args)
179 if (
equals_any(cls0, cls1))
return make_any(new_args);
183 auto rngs = detail::flatten_in_arg<disj>(disj_rhs->arg());
185 if (
equals_any(new_args, rngs))
return make_any(new_args);
190 world.log().d(
"final ranges: {}", fe::Join(new_args));
193 return new_args.back();
200 auto& world = type->world();
201 auto [lhs, rhs] = arg->
projs<2>();
203 if (
auto l =
Lit::isa(lhs), r =
Lit::isa(rhs); l && r && *l > *r)
return world.raw_app(type, callee, {rhs, lhs});
211 for (
const auto* disj_arg :
disj->args())
220 arg->
blame(
"regex.not must only be used with regex.disj, regex.range, regex.any and regex.not: {} {}", callee,
222 .n(
"found unwanted: {}", unwanted)
static auto isa(const Def *def)
auto projs(Projector auto f) const
Splits this Def via Def::projections into an Array (if A == std::dynamic_extent) or std::array (other...
fe::Error & blame(fe::cite_string< Args... > s, Args &&... args) const
Reports an error that blames this; chain Error::n for Notes and Error::bail to throw.
constexpr u32 gid() const noexcept
Global id - unique number for this Def.
const Def * arity() const
Number of elements available to Extract / Insert (may be dynamic).
static std::optional< T > isa(const Def *def)
static T as(const Def *def)
The World represents the whole program and manages creation of MimIR nodes (Defs).
fe::Vector< Range > Ranges
std::pair< std::uint64_t, std::uint64_t > Range
std::optional< Range > merge_ranges(Range a, Range b) noexcept
void merge_ranges(DefVec &args)
void make_vector_unique(DefVec &args)
auto get_range(const Def *rng) -> Range
const App * lit_range(const Def *d)
const Def * normalize_conj(const Def *type, const Def *callee, const Def *arg)
const Def * normalize_range(const Def *type, const Def *callee, const Def *arg)
bool equals_any(const Def *lhs, const Def *rhs)
const Def * normalize_disj(const Def *type, const Def *, const Def *arg)
const Def * normalize_quant(const Def *type, const Def *callee, const Def *arg)
const Def * normalize_not(const Def *, const Def *callee, const Def *arg)
bool compare_re(const Def *lhs, const Def *rhs)
const Def * make_binary_tree(Defs args)
const Def * any_unwanted_for_not(const Def *arg)
fe::View< const Def * > Defs
fe::Vector< const Def * > DefVec
#define MIM_regex_NORMALIZER_IMPL
const Def * operator()(Range rng)