Skip to content

Commit

Permalink
select optimization: avoid backtracking on mutually exclusive branches
Browse files Browse the repository at this point in the history
When we match against characters that belong to no other select branch we can avoid backtracking by a significant amount.
Note: HeadOptions could be a fairly large sequence, we could use calculate_first() to evaluate the initial condition and backtrack by at worst one character*
  • Loading branch information
Andersama committed Jan 2, 2021
1 parent 9a37e55 commit 3bbd78a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
19 changes: 16 additions & 3 deletions include/ctre/evaluation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,24 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
// matching select in patterns
template <typename R, typename Iterator, typename EndIterator, typename HeadOptions, typename... TailOptions, typename... Tail>
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, const flags & f, R captures, ctll::list<select<HeadOptions, TailOptions...>, Tail...>) noexcept {
if (auto r = evaluate(begin, current, end, f, captures, ctll::list<HeadOptions, Tail...>())) {
return r;
#ifndef CTRE_DISABLE_GREEDY_OPT
if constexpr (sizeof...(TailOptions) > 0 && !collides(calculate_first(sequence<HeadOptions, Tail...>{}), calculate_first(sequence<select<TailOptions...>, Tail...>{}))) {
auto r = evaluate(begin, current, end, f, captures, ctll::list<decltype(transform_into_set(calculate_first(sequence<HeadOptions, Tail...>{}))), end_cycle_mark>{});
if (r) {
return evaluate(begin, current, end, f, captures, ctll::list<HeadOptions, Tail...>{});
} else {
return evaluate(begin, current, end, f, captures, ctll::list<select<TailOptions...>, Tail...>());
}
} else {
return evaluate(begin, current, end, f, captures, ctll::list<select<TailOptions...>, Tail...>());
#endif
if (auto r = evaluate(begin, current, end, f, captures, ctll::list<HeadOptions, Tail...>())) {
return r;
} else {
return evaluate(begin, current, end, f, captures, ctll::list<select<TailOptions...>, Tail...>());
}
#ifndef CTRE_DISABLE_GREEDY_OPT
}
#endif
}

template <typename R, typename Iterator, typename EndIterator, typename... Tail>
Expand Down
21 changes: 21 additions & 0 deletions include/ctre/first.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,21 @@ template <typename CB> constexpr void negative_helper(ctre::negative_set<>, CB &
}
}

template <typename... Content>
constexpr auto transform_into_set(ctll::list<Content...>) {
return ctre::set<decltype(transform_into_set(Content{}))...>{};
}

template <typename T>
constexpr auto transform_into_set(T) {
return T{};
}

template<>
constexpr auto transform_into_set(can_be_anything) {
return ctre::char_range<std::numeric_limits<int64_t>::min(), std::numeric_limits<int64_t>::max()>{};
}

// simple fixed set
// TODO: this needs some optimizations
template <size_t Capacity> class point_set {
Expand Down Expand Up @@ -469,6 +484,9 @@ template <size_t Capacity> class point_set {
constexpr bool check(can_be_anything) {
return used > 0;
}
constexpr bool check(empty) {
return used == 0;
}
template <typename... Content> constexpr bool check(ctre::negative_set<Content...> nset) {
bool collision = false;
negative_helper(nset, [&](int64_t low, int64_t high){
Expand Down Expand Up @@ -497,6 +515,9 @@ template <size_t Capacity> class point_set {
constexpr void populate(can_be_anything) {
insert(std::numeric_limits<int64_t>::min(), std::numeric_limits<int64_t>::max());
}
constexpr void populate(empty) {
//do nothing
}
template <typename... Content> constexpr void populate(ctre::negative_set<Content...> nset) {
negative_helper(nset, [&](int64_t low, int64_t high){
this->insert(low, high);
Expand Down

0 comments on commit 3bbd78a

Please sign in to comment.