class ExhaustivenessChecker::Compiler
- ExhaustivenessChecker::Compiler
- Reference
- Object
Defined in:
exhaustiveness_checker.crConstructors
Instance Method Summary
-
#branch_mode(all_rows : Array(Row)) : BranchMode
Given a row, returns the kind of branch that is referred to the most across all rows.
- #compile(rows : Array(Row)) : Match
-
#compile_array_cases(rows : Array(Row), branch_var : Variable, type : Checkable) : Decision
Decises array matches from the given rows.
-
#compile_constructor_cases(rows : Array(Row), branch_var : Variable, cases : Array(Tuple(Constructor, Array(Variable), Array(Row)))) : Array(Case)
Compiles the cases and sub cases for the constructor located at the column of the branching variable.
-
#compile_infinite_cases(rows : Array(Row), branch_var : Variable) : Tuple(Array(Case), Decision)
Values have an infinite number of constructors, so we specialise the compilation of their patterns with this function.
- #compile_rows(rows : Array(Row)) : Decision
-
#constructor_index(item : Constructor) : Int32
Returns the index of the constructor.
-
#diagnostics : Diagnostics
The diagnostics.
-
#flatten_or(pattern : Pattern, row : Row) : Array(Tuple(Pattern, Row))
Flattens
POr
patterns (left, then right). -
#move_unconditional_patterns(row : Row) : Row
Moves variable-only patterns/tests into the right-hand side/body of a case.
-
#new_variable(type : Checkable) : Variable
Returns a new variable to use in the decision tree.
-
#new_variables(types : Array(Checkable)) : Array(Variable)
Returns a new variables to use in the decision tree.
-
#variable_id : Int32
The current counter for variables.
- #variant_lookup : Proc(Checkable, Array(Variant) | Nil)
- #variant_name_lookup : Proc(String, Int32, String | Nil)
Constructor Detail
Instance Method Detail
Given a row, returns the kind of branch that is referred to the most across all rows.
Decises array matches from the given rows.
Compiles the cases and sub cases for the constructor located at the column of the branching variable.
What exactly this method does may be a bit hard to understand from the code, as there's simply quite a bit going on. Roughly speaking, it does the following:
-
It takes the column we're branching on (based on the branching variable) and removes it from every row.
-
We add additional columns to this row, if the constructor takes any arguments (which we'll handle in a nested match).
-
We turn the resulting list of rows into a list of cases, then compile those into decision (sub) trees.
If a row didn't include the branching variable, we copy that row into the list of rows for every constructor to test.
For this to work, the cases
variable must be prepared such that it has
a triple for every constructor we need to handle. For an ADT with 10
constructors, that means 10 triples. This is needed so this method can
assign the correct sub matches to these constructors.
Types with infinite constructors (e.g. values) are handled separately; they don't need most of this work anyway.
Values have an infinite number of constructors, so we specialise the compilation of their patterns with this function.
What this does is basically marks branches the same values unreachable.
case "a" { "A" => "" "A" => "" // here...this is unreachable _ => "" }
Flattens POr
patterns (left, then right).
Moves variable-only patterns/tests into the right-hand side/body of a case.
This turns cases like this:
case one -> print(one)
case _ -> print("nothing")
Into this:
case -> {
let one = it
print(one)
}
case -> {
print("nothing")
}
Where it
is a variable holding the value case one
is compared
against, and the case/row has no patterns (i.e. always matches).
Returns a new variable to use in the decision tree.
Returns a new variables to use in the decision tree.