@@ -13,18 +13,31 @@ import config.Config
1313import collection .mutable
1414import java .lang .ref .WeakReference
1515
16- class TyperState (r : Reporter ) extends DotClass with Showable {
16+ class TyperState (previous : TyperState /* | Null */ ) extends DotClass with Showable {
1717
18- /** The current reporter */
19- def reporter = r
18+ private var myReporter =
19+ if (previous == null ) new ConsoleReporter () else previous.reporter
2020
21- /** The current constraint set */
22- def constraint : Constraint =
23- new OrderingConstraint (SimpleMap .Empty , SimpleMap .Empty , SimpleMap .Empty )
24- def constraint_= (c : Constraint )(implicit ctx : Context ): Unit = {}
21+ def reporter : Reporter = myReporter
2522
26- /** The uninstantiated variables */
27- def uninstVars = constraint.uninstVars
23+ /** A fresh type state with the same constraint as this one and the given reporter */
24+ def setReporter (reporter : Reporter ): this .type = { myReporter = reporter; this }
25+
26+ private var myConstraint : Constraint =
27+ if (previous == null ) new OrderingConstraint (SimpleMap .Empty , SimpleMap .Empty , SimpleMap .Empty )
28+ else previous.constraint
29+
30+ def constraint = myConstraint
31+ def constraint_= (c : Constraint )(implicit ctx : Context ) = {
32+ if (Config .debugCheckConstraintsClosed && isGlobalCommittable) c.checkClosed()
33+ myConstraint = c
34+ }
35+
36+ private val previousConstraint =
37+ if (previous == null ) constraint else previous.constraint
38+
39+ private var myEphemeral : Boolean =
40+ if (previous == null ) false else previous.ephemeral
2841
2942 /** The ephemeral flag is set as a side effect if an operation accesses
3043 * the underlying type of a type variable. The reason we need this flag is
@@ -33,8 +46,26 @@ class TyperState(r: Reporter) extends DotClass with Showable {
3346 * check the ephemeral flag; If the flag is set during an operation, the result
3447 * of that operation should not be cached.
3548 */
36- def ephemeral : Boolean = false
37- def ephemeral_= (x : Boolean ): Unit = ()
49+ def ephemeral = myEphemeral
50+ def ephemeral_= (x : Boolean ): Unit = { myEphemeral = x }
51+
52+ private var myIsCommittable = true
53+
54+ def isCommittable = myIsCommittable
55+
56+ def setCommittable (committable : Boolean ): this .type = { this .myIsCommittable = committable; this }
57+
58+ def isGlobalCommittable : Boolean =
59+ isCommittable && (previous == null || previous.isGlobalCommittable)
60+
61+ private var isCommitted = false
62+
63+ /** A fresh typer state with the same constraint as this one. */
64+ def fresh (): TyperState =
65+ new TyperState (this ).setReporter(new StoreReporter (reporter)).setCommittable(isCommittable)
66+
67+ /** The uninstantiated variables */
68+ def uninstVars = constraint.uninstVars
3869
3970 /** Gives for each instantiated type var that does not yet have its `inst` field
4071 * set, the instance value stored in the constraint. Storing instances in constraints
@@ -49,92 +80,33 @@ class TyperState(r: Reporter) extends DotClass with Showable {
4980 case tp => tp
5081 }
5182
52- /** A fresh typer state with the same constraint as this one.
53- * @param isCommittable The constraint can be committed to an enclosing context.
54- */
55- def fresh (isCommittable : Boolean ): TyperState = this
56-
57- /** A fresh type state with the same constraint as this one and the given reporter */
58- def withReporter (reporter : Reporter ) = new TyperState (reporter)
59-
60- /** Commit state so that it gets propagated to enclosing context */
61- def commit ()(implicit ctx : Context ): Unit = unsupported(" commit" )
62-
6383 /** The closest ancestor of this typer state (including possibly this typer state itself)
6484 * which is not yet committed, or which does not have a parent.
6585 */
66- def uncommittedAncestor : TyperState = this
67-
68- /** Make type variable instances permanent by assigning to `inst` field if
69- * type variable instantiation cannot be retracted anymore. Then, remove
70- * no-longer needed constraint entries.
71- */
72- def gc ()(implicit ctx : Context ): Unit = ()
73-
74- /** Is it allowed to commit this state? */
75- def isCommittable : Boolean = false
76- def isCommittable_= (b : Boolean ) = ()
86+ def uncommittedAncestor : TyperState =
87+ if (isCommitted) previous.uncommittedAncestor else this
7788
78- /** Can this state be transitively committed until the top-level? */
79- def isGlobalCommittable : Boolean = false
89+ private var testReporter : StoreReporter = null
8090
8191 /** Test using `op`, restoring typerState to previous state afterwards */
82- def test (op : => Boolean ): Boolean = op
83-
84- override def toText (printer : Printer ): Text = " ImmutableTyperState"
85-
86- /** A string showing the hashes of all nested mutable typerstates */
87- def hashesStr : String = " "
88- }
89-
90- class MutableTyperState (previous : TyperState , r : Reporter , override var isCommittable : Boolean )
91- extends TyperState (r) {
92-
93- private var myReporter = r
94-
95- override def reporter = myReporter
96-
97- private val previousConstraint = previous.constraint
98- private var myConstraint : Constraint = previousConstraint
99-
100- override def constraint = myConstraint
101- override def constraint_= (c : Constraint )(implicit ctx : Context ) = {
102- if (Config .debugCheckConstraintsClosed && isGlobalCommittable) c.checkClosed()
103- myConstraint = c
104- }
105-
106- private var myEphemeral : Boolean = previous.ephemeral
107-
108- override def ephemeral = myEphemeral
109- override def ephemeral_= (x : Boolean ): Unit = { myEphemeral = x }
110-
111- override def fresh (isCommittable : Boolean ): TyperState =
112- new MutableTyperState (this , new StoreReporter (reporter), isCommittable)
113-
114- override def withReporter (reporter : Reporter ) =
115- new MutableTyperState (this , reporter, isCommittable)
116-
117- override val isGlobalCommittable =
118- isCommittable &&
119- (! previous.isInstanceOf [MutableTyperState ] || previous.isGlobalCommittable)
120-
121- private var isCommitted = false
122-
123- override def uncommittedAncestor : TyperState =
124- if (isCommitted) previous.uncommittedAncestor else this
125-
126- override def test (op : => Boolean ): Boolean = {
92+ def test (op : => Boolean ): Boolean = {
12793 val savedReporter = myReporter
12894 val savedConstraint = myConstraint
95+ val savedCommittable = myIsCommittable
12996 val savedCommitted = isCommitted
130- val savedCommittable = isCommittable
131- isCommittable = false
97+ myIsCommittable = false
98+ myReporter =
99+ if (testReporter == null ) new StoreReporter (reporter)
100+ else {
101+ testReporter.reset()
102+ testReporter
103+ }
132104 try op
133105 finally {
134106 myReporter = savedReporter
135107 myConstraint = savedConstraint
108+ myIsCommittable = savedCommittable
136109 isCommitted = savedCommitted
137- isCommittable = savedCommittable
138110 }
139111 }
140112
@@ -156,7 +128,7 @@ extends TyperState(r) {
156128 * isApplicableSafe but also for (e.g. erased-lubs.scala) as well as
157129 * many parts of dotty itself.
158130 */
159- override def commit ()(implicit ctx : Context ) = {
131+ def commit ()(implicit ctx : Context ) = {
160132 val targetState = ctx.typerState
161133 assert(isCommittable)
162134 targetState.constraint =
@@ -171,7 +143,11 @@ extends TyperState(r) {
171143 isCommitted = true
172144 }
173145
174- override def gc ()(implicit ctx : Context ): Unit = {
146+ /** Make type variable instances permanent by assigning to `inst` field if
147+ * type variable instantiation cannot be retracted anymore. Then, remove
148+ * no-longer needed constraint entries.
149+ */
150+ def gc ()(implicit ctx : Context ): Unit = {
175151 val toCollect = new mutable.ListBuffer [TypeLambda ]
176152 constraint foreachTypeVar { tvar =>
177153 if (! tvar.inst.exists) {
@@ -189,6 +165,5 @@ extends TyperState(r) {
189165
190166 override def toText (printer : Printer ): Text = constraint.toText(printer)
191167
192- override def hashesStr : String = hashCode.toString + " -> " + previous.hashesStr
193-
168+ def hashesStr : String = hashCode.toString + " -> " + previous.hashesStr
194169}
0 commit comments