aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Constraint.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-09-05 14:56:18 +0200
committerMartin Odersky <odersky@gmail.com>2013-09-05 14:56:18 +0200
commit5bd9945e41f65b93f03543dbff3a4d7f531d6c3e (patch)
tree96f06e1dfd65780894e191927f91324521fdc1e1 /src/dotty/tools/dotc/core/Constraint.scala
parentae8cc6ff0b3c57877ae60b0b1fd30d1bcefa0518 (diff)
downloaddotty-5bd9945e41f65b93f03543dbff3a4d7f531d6c3e.tar.gz
dotty-5bd9945e41f65b93f03543dbff3a4d7f531d6c3e.tar.bz2
dotty-5bd9945e41f65b93f03543dbff3a4d7f531d6c3e.zip
File rename
Diffstat (limited to 'src/dotty/tools/dotc/core/Constraint.scala')
-rw-r--r--src/dotty/tools/dotc/core/Constraint.scala117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala
new file mode 100644
index 000000000..26ab00340
--- /dev/null
+++ b/src/dotty/tools/dotc/core/Constraint.scala
@@ -0,0 +1,117 @@
+package dotty.tools
+package dotc
+package core
+
+import Types._, Contexts._
+import util.SimpleMap
+import collection.mutable.ListBuffer
+import printing.{Printer, Showable}
+import printing.Texts._
+
+/** Constraint over undetermined type parameters
+ * @param map a map from PolyType to the type bounds that constrain the
+ * polytype's type parameters. A type parameter that does not
+ * have a constraint is represented by a `NoType` in the corresponding
+ * array entry.
+ */
+class Constraint(val map: SimpleMap[PolyType, Array[Type]]) extends AnyVal with Showable {
+
+ /** Does the constraint's domain contain the type parameters of `pt`? */
+ def contains(pt: PolyType): Boolean = map(pt) != null
+
+ /** The constraint for given type parameter `param`, or NoType if `param` is not part of
+ * the constraint domain.
+ */
+ def apply(param: PolyParam): Type = {
+ val entries = map(param.binder)
+ if (entries == null) NoType else entries(param.paramNum)
+ }
+
+ /** The constraint for the type parameters of `pt`.
+ * @pre The polytype's type parameters are contained in the constraint's domain.
+ */
+ def apply(pt: PolyType): Array[Type] = map(pt)
+
+ /** A new constraint which is derived from this constraint by adding or replacing
+ * the entries corresponding to `pt` with `entries`.
+ */
+ def updated(pt: PolyType, entries: Array[Type]) = {
+ assert(map(pt) != null)
+ new Constraint(map.updated(pt, entries))
+ }
+
+ /** A new constraint which is derived from this constraint by removing
+ * the type parameter `param` from the domain.
+ */
+ def - (param: PolyParam) = {
+ val pt = param.binder
+ val pnum = param.paramNum
+ val entries = map(pt)
+ var noneLeft = true
+ var i = 0
+ while (noneLeft && (i < entries.length)) {
+ noneLeft = (entries(i) eq NoType) || i == pnum
+ i += 1
+ }
+ new Constraint(
+ if (noneLeft) map remove pt
+ else {
+ val newEntries = entries.clone
+ newEntries(pnum) = NoType
+ map.updated(pt, newEntries)
+ })
+ }
+
+ def +(pt: PolyType) = {
+/*
+ pt.resultType match {
+ case MethodType(pname :: rest, _) =>
+ assert(pname.toString != "__thingToAdd")
+ case _ =>
+ }
+*/
+ new Constraint(map.updated(pt, pt.paramBounds.toArray))
+ }
+ /** A new constraint which is derived from this constraint by removing
+ * the type parameter `param` from the domain and replacing all occurrences
+ * of the parameter elsewhere in the constraint by type `tp`.
+ */
+ def replace(param: PolyParam, tp: Type)(implicit ctx: Context) = {
+ def subst(entries: Array[Type]) = {
+ var result = entries
+ var i = 0
+ while (i < entries.length) {
+ entries(i) match {
+ case oldBounds: TypeBounds =>
+ val newBounds = oldBounds.substParam(param, tp)
+ if (oldBounds ne newBounds) {
+ if (result eq entries) result = entries.clone
+ result(i) = newBounds
+ }
+ case _ =>
+ }
+ i += 1
+ }
+ result
+ }
+
+ new Constraint((this - param).map mapValues subst)
+ }
+
+ def domainPolys: List[PolyType] = map.map2((k, v) => k)
+
+ def domainParams: List[PolyParam] =
+ for {
+ (poly, entries) <- map.map2((k, v) => (k, v))
+ n <- 0 until entries.length
+ if entries(n).exists
+ } yield PolyParam(poly, n)
+
+ override def toText(printer: Printer): Text = {
+ val dom = domainPolys map (_.toText(printer))
+ val assocs =
+ for (param <- domainParams)
+ yield " " ~ param.toText(printer) ~ this(param).toText(printer)
+ "Constraint(" ~ Text(dom, ", ") ~ ") {" ~ Text(assocs, "\n") ~ "}"
+ }
+}