scala.tools.nsc.transform.patmat.PatternMatching
Conjunctive normal form (of a Boolean formula).
Conjunctive normal form (of a Boolean formula). A formula in this form is amenable to a SAT solver (i.e., solver that decides satisfiability of a formula).
Make a TreeMaker that will result in an extractor call specified by extractor
the next TreeMaker (here, we don't know which it'll be) is chained after this one by flatMap'ing
a function with binder nextBinder
over our extractor's result
the function's body is determined by the next TreeMaker
(furthermore, the interpretation of flatMap
depends on the codegen instance we're using).
Make a TreeMaker that will result in an extractor call specified by extractor
the next TreeMaker (here, we don't know which it'll be) is chained after this one by flatMap'ing
a function with binder nextBinder
over our extractor's result
the function's body is determined by the next TreeMaker
(furthermore, the interpretation of flatMap
depends on the codegen instance we're using).
The values for the subpatterns, as computed by the extractor call in extractor
,
are stored in local variables that re-use the symbols in subPatBinders
.
This makes extractor patterns more debuggable (SI-5739).
An optimized version of ExtractorTreeMaker for Products.
An optimized version of ExtractorTreeMaker for Products. For now, this is hard-coded to case classes, and we simply extract the case class fields.
The values for the subpatterns, as specified by the case class fields at the time of extraction,
are stored in local variables that re-use the symbols in subPatBinders
.
This makes extractor patterns more debuggable (SI-5739) as well as
avoiding mutation after the pattern has been matched (SI-5158, SI-6070)
TODO: make this user-definable as follows
When a companion object defines a method def unapply_1(x: T): U_1
, but no def unapply
or def unapplySeq
,
the extractor is considered to match any non-null value of type T
the pattern is expected to have as many sub-patterns as there are def unapply_I(x: T): U_I
methods,
and the type of the I'th sub-pattern is U_I
.
The same exception for Seq patterns applies: if the last extractor is of type Seq[U_N]
,
the pattern must have at least N arguments (exactly N if the last argument is annotated with : _*
).
The arguments starting at N (and beyond) are taken from the sequence returned by apply_N,
and it is checked that that sequence has enough elements to provide values for all expected sub-patterns.
For a case class C, the implementation is assumed to be def unapply_I(x: C) = x._I
,
and the extractor call is inlined under that assumption.
Plaisted transformation: used for conversion of a propositional formula into conjunctive normal form (CNF) (input format for SAT solver).
Plaisted transformation: used for conversion of a propositional formula into conjunctive normal form (CNF) (input format for SAT solver). A simple conversion into CNF via Shannon expansion would also be possible but it's worst-case complexity is exponential (in the number of variables) and thus even simple problems could become untractable. The Plaisted transformation results in an _equisatisfiable_ CNF-formula (it generates auxiliary variables) but runs with linear complexity. The common known Tseitin transformation uses bi-implication, whereas the Plaisted transformation uses implication only, thus the resulting CNF formula has (on average) only half of the clauses of a Tseitin transformation. The Plaisted transformation uses the polarities of sub-expressions to figure out which part of the bi-implication can be omitted. However, if all sub-expressions have positive polarity (e.g., after transformation into negation normal form) then the conversion is rather simple and the pseudo-normalization via NNF increases chances only one side of the bi-implication is needed.
implements the run-time aspects of (§8.2) (typedPattern has already done the necessary type transformations)
implements the run-time aspects of (§8.2) (typedPattern has already done the necessary type transformations)
Type patterns consist of types, type variables, and wildcards. A type pattern T is of one of the following forms:
Test two objects for inequality.
Test two objects for inequality.
true
if !(this == that), false otherwise.
Equivalent to x.hashCode
except for boxed numeric types and null
.
Equivalent to x.hashCode
except for boxed numeric types and null
.
For numerics, it returns a hash value which is consistent
with value equality: if two value type instances compare
as true, then ## will produce the same hash value for each
of them.
For null
returns a hashcode where null.hashCode
throws a
NullPointerException
.
a hash value consistent with ==
The expression x == that
is equivalent to if (x eq null) that eq null else x.equals(that)
.
The expression x == that
is equivalent to if (x eq null) that eq null else x.equals(that)
.
true
if the receiver object is equivalent to the argument; false
otherwise.
A conservative approximation of which patterns do not discern anything.
A conservative approximation of which patterns do not discern anything. They are discarded during the translation.
Cast the receiver object to be of type T0
.
Cast the receiver object to be of type T0
.
Note that the success of a cast at runtime is modulo Scala's erasure semantics.
Therefore the expression 1.asInstanceOf[String]
will throw a ClassCastException
at
runtime, while the expression List(1).asInstanceOf[List[String]]
will not.
In the latter example, because the type argument is erased as part of compilation it is
not possible to check whether the contents of the list are of the requested type.
the receiver object.
ClassCastException
if the receiver object is not an instance of the erasure of type T0
.
Create a copy of the receiver object.
Create a copy of the receiver object.
The default implementation of the clone
method is platform dependent.
a copy of the receiver object.
not specified by SLS as a member of AnyRef
a flow-sensitive, generalised, common sub-expression elimination reuse knowledge from performed tests the only sub-expressions we consider are the conditions and results of the three tests (type, type&equality, equality) when a sub-expression is shared, it is stored in a mutable variable the variable is floated up so that its scope includes all of the program that shares it we generalize sharing to implication, where b reuses a if a => b and priors(a) => priors(b) (the priors of a sub expression form the path through the decision tree)
a flow-sensitive, generalised, common sub-expression elimination reuse knowledge from performed tests the only sub-expressions we consider are the conditions and results of the three tests (type, type&equality, equality) when a sub-expression is shared, it is stored in a mutable variable the variable is floated up so that its scope includes all of the program that shares it we generalize sharing to implication, where b reuses a if a => b and priors(a) => priors(b) (the priors of a sub expression form the path through the decision tree)
Tests whether the argument (that
) is a reference to the receiver object (this
).
Tests whether the argument (that
) is a reference to the receiver object (this
).
The eq
method implements an equivalence relation on
non-null instances of AnyRef
, and has three additional properties:
x
and y
of type AnyRef
, multiple invocations of
x.eq(y)
consistently returns true
or consistently returns false
.x
of type AnyRef
, x.eq(null)
and null.eq(x)
returns false
.null.eq(null)
returns true
. When overriding the equals
or hashCode
methods, it is important to ensure that their behavior is
consistent with reference equality. Therefore, if two objects are references to each other (o1 eq o2
), they
should be equal to each other (o1 == o2
) and they should hash to the same value (o1.hashCode == o2.hashCode
).
true
if the argument is a reference to the receiver object; false
otherwise.
The equality method for reference types.
The models we get from the DPLL solver need to be mapped back to counter examples.
The models we get from the DPLL solver need to be mapped back to counter examples. However there's no precalculated mapping model -> counter example. Even worse, not every valid model corresponds to a valid counter example. The reason is that restricting the valid models further would for example require a quadratic number of additional clauses. So to keep the optimistic case fast (i.e., all cases are covered in a pattern match), the infeasible counter examples are filtered later.
The DPLL procedure keeps the literals that do not contribute to the solution
unassigned, e.g., for (a \/ b)
only {a = true} or {b = true} is required and the other variable can have any value.
This function does a smart expansion of the model and avoids models that have conflicting mappings.
For example for in case of the given set of symbols (taken from t7020.scala
):
"V2=2#16"
"V2=6#19"
"V2=5#18"
"V2=4#17"
"V2=7#20"
One possibility would be to group the symbols by domain but
this would only work for equality tests and would not be compatible
with type tests.
Another observation leads to a much simpler algorithm:
Only one of these symbols can be set to true,
since V2
can at most be equal to one of {2,6,5,4,7}.
Called by the garbage collector on the receiver object when there are no more references to the object.
Called by the garbage collector on the receiver object when there are no more references to the object.
The details of when and if the finalize
method is invoked, as
well as the interaction between finalize
and non-local returns
and exceptions, are all platform dependent.
not specified by SLS as a member of AnyRef
A representation that corresponds to the dynamic class of the receiver object.
A representation that corresponds to the dynamic class of the receiver object.
The nature of the representation is platform dependent.
a representation that corresponds to the dynamic class of the receiver object.
not specified by SLS as a member of AnyRef
The hashCode method for reference types.
Test whether the dynamic type of the receiver object is T0
.
Test whether the dynamic type of the receiver object is T0
.
Note that the result of the test is modulo Scala's erasure semantics.
Therefore the expression 1.isInstanceOf[String]
will return false
, while the
expression List(1).isInstanceOf[List[String]]
will return true
.
In the latter example, because the type argument is erased as part of compilation it is
not possible to check whether the contents of the list are of the specified type.
true
if the receiver object is an instance of erasure of type T0
; false
otherwise.
Equivalent to !(this eq that)
.
Equivalent to !(this eq that)
.
true
if the argument is not a reference to the receiver object; false
otherwise.
Wakes up a single thread that is waiting on the receiver object's monitor.
Wakes up a single thread that is waiting on the receiver object's monitor.
not specified by SLS as a member of AnyRef
Wakes up all threads that are waiting on the receiver object's monitor.
Wakes up all threads that are waiting on the receiver object's monitor.
not specified by SLS as a member of AnyRef
Simplifies propositional formula according to the following rules: - eliminate double negation (avoids unnecessary Tseitin variables) - flatten trees of same connectives (avoids unnecessary Tseitin variables) - removes constants and connectives that are in fact constant because of their operands - eliminates duplicate operands - convert formula into NNF: all sub-expressions have a positive polarity which makes them amenable for the subsequent Plaisted transformation and increases chances to figure out that the formula is already in CNF
Simplifies propositional formula according to the following rules: - eliminate double negation (avoids unnecessary Tseitin variables) - flatten trees of same connectives (avoids unnecessary Tseitin variables) - removes constants and connectives that are in fact constant because of their operands - eliminates duplicate operands - convert formula into NNF: all sub-expressions have a positive polarity which makes them amenable for the subsequent Plaisted transformation and increases chances to figure out that the formula is already in CNF
Complexity: DFS over formula tree
See http://www.decision-procedures.org/slides/propositional_logic-2x3.pdf
Creates a String representation of this object.
Creates a String representation of this object. The default representation is platform dependent. On the java platform it is the concatenation of the class name, "@", and the object's hashcode in hexadecimal.
a String representation of the object.
The translation of pat if guard => body
has two aspects:
1) the substitution due to the variables bound by patterns
2) the combination of the extractor calls using flatMap
.
The translation of pat if guard => body
has two aspects:
1) the substitution due to the variables bound by patterns
2) the combination of the extractor calls using flatMap
.
2) is easy -- it looks like: translatePattern_1.flatMap(translatePattern_2....flatMap(translatePattern_N.flatMap(translateGuard.flatMap((x_i) => success(Xbody(x_i)))))...)
this must be right-leaning tree, as can be seen intuitively by considering the scope of bound variables:
variables bound by pat_1 must be visible from the function inside the left-most flatMap right up to Xbody all the way on the right
1) is tricky because translatePattern_i determines the shape of translatePattern_i+1:
zoom in on translatePattern_1.flatMap(translatePattern_2)
for example -- it actually looks more like:
translatePattern_1(x_scrut).flatMap((x_1) => {y_i -> x_1._i}translatePattern_2)
x_1
references the result (inside the monad) of the extractor corresponding to pat_1
,
this result holds the values for the constructor arguments, which translatePattern_1 has extracted
from the object pointed to by x_scrut
. The y_i
are the symbols bound by pat_1
(in order)
in the scope of the remainder of the pattern, and they must thus be replaced by:
x_1
in the treemakers,
Thus, the result type of translatePattern_i
's extractor must conform to M[(T_1,..., T_n)]
.
Operationally, phase 1) is a foldLeft, since we must consider the depth-first-flattening of the transformed patterns from left to right. For every pattern ast node, it produces a transformed ast and a function that will take care of binding and substitution of the next ast (to the right).
Implement a pattern match by turning its cases (including the implicit failure case)
into the corresponding (monadic) extractors, and combining them with the orElse
combinator.
Implement a pattern match by turning its cases (including the implicit failure case)
into the corresponding (monadic) extractors, and combining them with the orElse
combinator.
For scrutinee match { case1 ... caseN }
, the resulting tree has the shape
runOrElse(scrutinee)(x => translateCase1(x).orElse(translateCase2(x)).....orElse(zero))
NOTE: the resulting tree is not type checked, nor are nested pattern matches transformed thus, you must typecheck the result (and that will in turn translate nested matches) this could probably optimized... (but note that the matchStrategy must be solved for each nested patternmatch)