Lean2Js.Exhaustive
A match the compiler accepted has an arm for every value of its scrutinee #
Maranget's usefulness test, read back as a statement about values: a match the compiler accepted as
exhaustive has an arm for every value of the scrutinee's type.
The generated code takes its last arm without a test, so this is what says the reference semantics never
reaches the end of the chain either — evalExpr returns noMatchingAlternative for no scrutinee the
entry check let through.
Lean2Js.Exhaustive.Covers
sourceSome row of the matrix accepts the value vector.
Equations
- Lean2Js.Exhaustive.Covers rows vs = ∃ (row : List Lean2Js.Core.Pat), row ∈ rows ∧ (Lean2Js.matchPats row vs).isSome = true
Instances For
Used by
Lean2Js.Exhaustive.ValuesTyped
sourceThe columns type the values, pairwise.
Equations
- Lean2Js.Exhaustive.ValuesTyped p [] [] = True
- Lean2Js.Exhaustive.ValuesTyped p (v :: vs) (ty :: tys) = (Lean2Js.Value.hasTy p v ty = true ∧ Lean2Js.Exhaustive.ValuesTyped p vs tys)
- Lean2Js.Exhaustive.ValuesTyped p x✝¹ x✝ = False
Instances For
Used by
Reading matchPats apart #
Lean2Js.Exhaustive.matchPats_nil_inv
sourceUsed by
Lean2Js.Exhaustive.matchPats_nil
sourceUsed by
Lean2Js.Exhaustive.matchPats_cons_inv
sourceUsed by
Lean2Js.Exhaustive.matchPats_cons
sourceUsed by
Lean2Js.Exhaustive.matchPats_length
sourceUsed by
Lean2Js.Exhaustive.matchPats_append
sourceUsed by
Lean2Js.Exhaustive.matchPats_append_inv
sourceUsed by
The head a value takes #
The matrix splits a column by the head of its values. A value of a type the signature enumerates carries exactly one of the heads, with the fields that head lists.
Lean2Js.Exhaustive.HeadOf
sourceThe value a head stands for, and the fields it carries.
Equations
- Lean2Js.Exhaustive.HeadOf (Lean2Js.Compile.Head.lit l) v fieldVs = ((Lean2Js.litValue l == v) = true ∧ fieldVs = [])
- Lean2Js.Exhaustive.HeadOf (Lean2Js.Compile.Head.ctor name) (Lean2Js.Value.obj ctor fields) fieldVs = (name = ctor ∧ fieldVs = List.map (fun (x : String × Lean2Js.Value) => x.snd) fields)
- Lean2Js.Exhaustive.HeadOf (Lean2Js.Compile.Head.ctor name) v fieldVs = False
Instances For
Used by
Lean2Js.Exhaustive.lit_beq_eq
sourceUsed by
Lean2Js.Exhaustive.head_beq_eq
sourceUsed by
Lean2Js.Exhaustive.litValue_beq_self
sourceA literal's value equals itself. The matcher compares by Value.beq, and a literal pattern only ever
faces the value the same literal builds.
Used by
Reading the matrix apart #
specialize and defaultRows are how the test splits a column. Both directions of the split have to be
read back as statements about the values a row accepts.
Lean2Js.Exhaustive.covers_of_specialize
sourceA row of the specialized matrix that accepts the head's fields, followed by the rest of the vector, comes from a row of the original that accepts the value itself.
Used by
Lean2Js.Exhaustive.covers_of_defaultRows
sourceA row of the default matrix that accepts the rest of the vector comes from a row of the original whose head is a wildcard, which accepts any value in front of it.
Used by
The head a typed value takes #
Lean2Js.Exhaustive.valuesTyped_of_hasFieldTys
sourceUsed by
Lean2Js.Exhaustive.head_of_hasTy
sourceA value of a type the signature enumerates carries one of the heads it lists, with fields of the types that head names. This is what says a wildcard column with every head seen leaves nothing out.
Used by
Widths #
The matrix's rows are as wide as the query. Splitting a column keeps them lined up.
Lean2Js.Exhaustive.SameWidth
sourceEquations
- Lean2Js.Exhaustive.SameWidth rows n = ∀ (row : List Lean2Js.Core.Pat), row ∈ rows → row.length = n
Instances For
Used by
Lean2Js.Exhaustive.sameWidth_specialize
sourceUsed by
Lean2Js.Exhaustive.sameWidth_defaultRows
sourceUsed by
Lean2Js.Exhaustive.valuesTyped_length
sourceUsed by
Lean2Js.Exhaustive.valuesTyped_append
sourceUsed by
Lean2Js.Exhaustive.matchPats_replicate_wild
sourceUsed by
What the test settles #
Lean2Js.Exhaustive.headOf_obj_inv
sourceA literal never stands for a constructor value.
Used by
Lean2Js.Exhaustive.head_fieldTys
sourceThe field types the signature gives a value's head, in the shape fieldTysOf reads them.
Used by
Lean2Js.Exhaustive.signature_isSome_of_obj
sourceOnly a named type, an option or a result has a constructor value, and each of those has a signature. So a value the matcher took apart is one the matrix can split on.
Used by
Lean2Js.Exhaustive.covered_wildcard
sourceThe column a wildcard leaves open. Either the matrix has every head the type can take, and the value carries one of them, or it does not, and the rows that fall through cover the value. Both branches hand the rest of the vector to the induction hypothesis.
Used by
Lean2Js.Exhaustive.covered_of_useful_false
sourceIf the usefulness test finds no value vector that q accepts and every row misses, then a vector
the columns type and q accepts is accepted by some row.
match asks this of an all-wildcard q: the answer is that every value of the scrutinee's type is
matched by an arm.
Used by
What a compiled match settles #
The generated arm chain takes its last arm without a test. That is sound because the compiler refused a
match the usefulness test called useful — and by the theorem above, a match it accepted has an arm
for every value the scrutinee's type can take. So the reference semantics never reaches the end of the
chain either.
Lean2Js.Exhaustive.useful_false_of_compile
sourceThe exhaustiveness check a compiled match passed.
Used by
Lean2Js.Exhaustive.firstMatch_isSome_of_mem
sourceAn arm whose pattern matches is reached, or an earlier one is.
Used by
Lean2Js.Exhaustive.firstMatch_isSome
sourceAn arm matches. The chain the generated code walks ends in an arm it takes without a test, and this is what says the reference semantics takes an arm too.
Used by
What a compiled fold settles #
A fold's alternatives are not matched against the value the fold was handed but against the rebuilt
node, whose fields that came round carry the fold's answers. That node is a value of no type the
language writes, so firstMatch_isSome does not reach it and the compiler does not check its
alternatives with useful: it checks them with usefulFold, at foldHeads, which is the same test
with the one column's signature handed over rather than read off the declared type.
Checking it at the declared type instead would not be conservative. Two types may declare constructors of the same name, so an alternative may name every constructor the declared type has, pass the test at that type, and still leave a rebuilt node no alternative matches.
Lean2Js.Exhaustive.covered_of_usefulFold_false
sourceThe rebuilt node a fold's alternatives are matched against is covered by one of them.
covered_of_useful_false's twin at one column. A twin rather than an instance: what types the node's
fields is the head list, and no Ty names it.
Used by
Lean2Js.Exhaustive.usefulFold_false_of_compile
sourceThe exhaustiveness check a compiled fold passed.
Used by
Lean2Js.Exhaustive.foldFirstMatch_isSome
sourceAn alternative of a fold matches the rebuilt node. The chain the generated code walks ends in an arm it takes without a test, and this is what says the reference semantics takes an arm too.