marianoguerra/wax/cond does not have a README file

    Atom

    An atom: one variable against one constant.

    The order theory is normalized the way a total-order theory has to be, and the way the reference's Leq does: an atom is always an upper bound, and the lower bounds are its negations. vid > v is not (vid <= v), and vid = v is vid <= v and not (vid < v). That is what keeps the atom set small enough for the search to be trivial.

    Env

    pub struct Env {
    bool_vars : Map[String, Int]
    version_vars : Map[String, Int]
    string_vars : Map[String, Int]
    names : Map[Int, String]
    next_var : Int
    var_kind : Map[String, String]
    reported : Map[(Int, Int), Unit]
    }

    Per-module solver state: variable interning, the kind each name is used at, and deduplication of ill-formed-condition diagnostics.

    One Env per module, so nothing leaks between modules processed in the same run.

    Env::explain

    fn Env::explain(self : Env, f : T, style? : Style) -> String?

    A minimal assumption under which the formula holds -- e.g. $oxcaml and not $debug.

    None when the formula is a tautology (always reachable, so there is nothing to assume) or unsatisfiable (no assumption would do).

    The reference asks its BDD for a shortest satisfying cube. Here a satisfying assignment is found first and then minimized greedily: a literal whose removal still leaves the remaining conjunction entailing the formula was not carrying its weight. Greedy gives a minimal cube, not necessarily the globally shortest one -- for a handful of atoms the two coincide, and this is diagnostic text rather than a decision.

    Env::new

    fn Env::new() -> Env

    Env::of_cond

    Translate a condition, interning its variables.

    A condition that cannot be modelled is reported (once per source location) and becomes a fresh unconstrained variable, so that exploration proceeds rather than stopping at the first unmodelable branch. location is the enclosing conditional, used when a sub-condition carries no span of its own.

    Node

    A boolean formula over atoms.

    Style

    pub(all) enum Style {
    Wat
    Wax
    } derive(Eq,
    Debug
    )

    Which surface syntax to render in.

    The two spell conditions differently: WAT uses $-prefixed variables, dotted versions and <>; Wax uses bare names, version tuples and !=.
    pub struct T {
    node : Node
    }

    A formula over condition variables.

    Version

    pub(all) struct Version {
    major : Int
    minor : Int
    patch : Int
    } derive(Eq, Hash,
    Debug
    )

    A version triple, ordered lexicographically.
    impl Show for Version

    Version::compare_to

    fn Version::compare_to(self : Version, other : Version) -> Int

    and_

    fn and_(a : T, b : T) -> T

    Conjunction, with the constant folding that keeps formulas small.

    canonical_key

    fn canonical_key(f : T) -> String

    A canonical STRUCTURAL key, for deduplicating formulas in a table.

    equal is semantic and hash is therefore a constant, which is correct but useless as a hash key. The exploration driver needs to ask "have I seen this assumption before?" thousands of times, and answering it semantically would be a satisfiability query per comparison.

    So this is the weaker question, asked cheaply: two formulas share a key when they are the same up to the commutativity, associativity and idempotence of and and or, which is what actually varies between assumptions built in different branch orders. Equal keys imply equivalence; different keys do not imply inequivalence.

    That asymmetry is safe for a dedup set and only there: missing a duplicate costs one more configuration explored, never a wrong answer. It would not be safe for anything that treats "not seen" as "not implied".

    equal

    fn equal(a : T, b : T) -> Bool

    Are the two formulas equivalent?

    Semantic, matching the reference, where equality is BDD identity and BDDs are canonical. Here it is two satisfiability queries instead.

    false_

    let false_ : T

    hash

    fn hash(_ : T) -> Int

    A hash consistent with equal.

    Semantically equal formulas must hash alike, and without a canonical form there is nothing cheap to hash that respects that -- so this is a constant. Correct, and degenerate: a hash table keyed on formulas degrades to a list.

    The exploration driver does need to dedup assumptions, and asks the weaker structural question instead -- see canonical_key, which is cheap and whose asymmetry is safe for exactly that use.

    is_satisfiable

    fn is_satisfiable(f : T) -> Bool

    Does the formula have a satisfying assignment?

    Theory-aware, so contradictory version bounds are unsatisfiable rather than merely unlikely.

    logical_implies

    fn logical_implies(a : T, b : T) -> Bool

    Does a entail b?

    not_

    fn not_(f : T) -> T

    or_

    fn or_(a : T, b : T) -> T

    true_

    let true_ : T

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io