/*++ Copyright (c) 2026 Microsoft Corporation Module Name: range_predicate_translator.cpp Abstract: Implementation of seq::range_predicate_translator. See header for the algebraic specification of the translatable fragment. Authors: Margus Veanes (veanes) 2026 --*/ #include "ast/rewriter/range_predicate_translator.h" namespace seq { bool range_predicate_translator::translate(expr* ele, expr* cond, range_predicate& out) const { unsigned const max_char = m_u.max_char(); if (m.is_true(cond)) { out = range_predicate::top(max_char); return true; } if (m.is_false(cond)) { out = range_predicate::empty(max_char); return true; } expr* a = nullptr; expr* b = nullptr; unsigned c = 0; if (m.is_eq(cond, a, b)) { if (a == ele && m_u.is_const_char(b, c)) { out = range_predicate::singleton(c, max_char); return true; } if (b == ele && m_u.is_const_char(a, c)) { out = range_predicate::singleton(c, max_char); return true; } return false; } if (m_u.is_char_le(cond, a, b)) { // ele <= c --> [0, c] if (a == ele && m_u.is_const_char(b, c)) { out = range_predicate::range(0, c, max_char); return true; } // c <= ele --> [c, max_char] if (b == ele && m_u.is_const_char(a, c)) { out = range_predicate::range(c, max_char, max_char); return true; } return false; } expr* arg = nullptr; if (m.is_not(cond, arg)) { range_predicate tmp(max_char); if (!translate(ele, arg, tmp)) return false; out = ~tmp; return true; } if (m.is_and(cond)) { range_predicate acc = range_predicate::top(max_char); for (expr* sub : *to_app(cond)) { range_predicate p(max_char); if (!translate(ele, sub, p)) return false; acc = acc & p; } out = acc; return true; } if (m.is_or(cond)) { range_predicate acc = range_predicate::empty(max_char); for (expr* sub : *to_app(cond)) { range_predicate p(max_char); if (!translate(ele, sub, p)) return false; acc = acc | p; } out = acc; return true; } return false; } }