@@ -19,8 +19,7 @@ import Errors._
19
19
import scala .collection .mutable
20
20
import scala .annotation .tailrec
21
21
22
- class Semantic {
23
- import Semantic ._
22
+ object Semantic {
24
23
25
24
// ----- Domain definitions --------------------------------
26
25
@@ -93,10 +92,10 @@ class Semantic {
93
92
*
94
93
* We need to restrict nesting levels of `outer` to finitize the domain.
95
94
*/
96
- case class Warm (klass : ClassSymbol , outer : Value , args : List [Value ]) extends Ref {
95
+ case class Warm (klass : ClassSymbol , outer : Value , args : List [Value ])( using Heap ) extends Ref {
97
96
val objekt = getCachedObject()
98
97
99
- private def getCachedObject () =
98
+ private def getCachedObject ()( using Heap ) =
100
99
if heap.contains(this ) then heap(this )
101
100
else {
102
101
val obj = Objekt (this .klass, fields = mutable.Map .empty, outers = mutable.Map (this .klass -> this .outer))
@@ -149,7 +148,7 @@ class Semantic {
149
148
opaque type Heap = mutable.Map [Warm , Objekt ]
150
149
151
150
/** Note: don't use `val` to avoid incorrect sharing */
152
- def empty : Heap = mutable.Map .empty
151
+ private [ Semantic ] def empty : Heap = mutable.Map .empty
153
152
154
153
extension (heap : Heap )
155
154
def contains (ref : Warm ): Boolean = heap.contains(ref)
@@ -160,8 +159,9 @@ class Semantic {
160
159
}
161
160
type Heap = Heap .Heap
162
161
162
+ inline def heap (using h : Heap ): Heap = h
163
+
163
164
import Heap ._
164
- private val heap : Heap = Heap .empty
165
165
166
166
/** The environment for method parameters
167
167
*
@@ -205,7 +205,7 @@ class Semantic {
205
205
}
206
206
207
207
type Env = Env .Env
208
- def env (using env : Env ) = env
208
+ inline def env (using env : Env ) = env
209
209
inline def withEnv [T ](env : Env )(op : Env ?=> T ): T = op(using env)
210
210
211
211
import Env ._
@@ -233,7 +233,7 @@ class Semantic {
233
233
type Promoted = Promoted .Promoted
234
234
235
235
import Promoted ._
236
- def promoted (using p : Promoted ): Promoted = p
236
+ inline def promoted (using p : Promoted ): Promoted = p
237
237
238
238
/** Interpreter configuration
239
239
*
@@ -290,8 +290,15 @@ class Semantic {
290
290
value.instantiate(klass, ctor, args, source) ++ errors
291
291
}
292
292
293
+ // ----- State --------------------------------------------
294
+ /** Global state of the checker */
295
+ class State (val heap : Heap , val workList : WorkList )
296
+
297
+ given (using s : State ): Heap = s.heap
298
+ given (using s : State ): WorkList = s.workList
299
+
293
300
/** The state that threads through the interpreter */
294
- type Contextual [T ] = (Env , Context , Trace , Promoted ) ?=> T
301
+ type Contextual [T ] = (Env , Context , Trace , Promoted , State ) ?=> T
295
302
296
303
// ----- Error Handling -----------------------------------
297
304
@@ -704,7 +711,7 @@ class Semantic {
704
711
// ----- Work list ---------------------------------------------------
705
712
case class Task (value : ThisRef )(val trace : Trace )
706
713
707
- private class WorkList {
714
+ class WorkList private [ Semantic ]() {
708
715
private var checkedTasks : Set [Task ] = Set .empty
709
716
private var pendingTasks : List [Task ] = Nil
710
717
@@ -713,7 +720,7 @@ class Semantic {
713
720
714
721
/** Process the worklist until done */
715
722
@ tailrec
716
- final def work ()(using Context ): Unit =
723
+ final def work ()(using State , Context ): Unit =
717
724
pendingTasks match
718
725
case task :: rest =>
719
726
pendingTasks = rest
@@ -726,7 +733,7 @@ class Semantic {
726
733
*
727
734
* This method should only be called from the work list scheduler.
728
735
*/
729
- private def doTask (task : Task )(using Context ): Unit = {
736
+ private def doTask (task : Task )(using State , Context ): Unit = {
730
737
val thisRef = task.value
731
738
val tpl = thisRef.klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
732
739
@@ -738,14 +745,31 @@ class Semantic {
738
745
res.errors.foreach(_.issue)
739
746
}
740
747
}
748
+ inline def workList (using wl : WorkList ): WorkList = wl
741
749
742
- private val workList = new WorkList
750
+ // ----- API --------------------------------
743
751
744
752
/** Add a checking task to the work list */
745
- def addTask (task : ThisRef )(using Trace ) = workList.addTask(Task (task)(trace))
753
+ def addTask (task : ThisRef )(using WorkList , Trace ) = workList.addTask(Task (task)(trace))
754
+
755
+ /** Perform check on the work list until it becomes empty
756
+ *
757
+ * Should only be called once from the checker.
758
+ */
759
+ def check ()(using State , Context ) = workList.work()
746
760
747
- /** Perform check on the work list until it becomes empty */
748
- def check ()(using Context ) = workList.work()
761
+ /** Perform actions with initial checking state.
762
+ *
763
+ * Semantic.withInitialState {
764
+ * Semantic.addTask(...)
765
+ * ...
766
+ * Semantic.check()
767
+ * }
768
+ */
769
+ def withInitialState [T ](work : State ?=> T ): T = {
770
+ val initialState = State (Heap .empty, new WorkList )
771
+ work(using initialState)
772
+ }
749
773
750
774
// ----- Semantic definition --------------------------------
751
775
@@ -1210,10 +1234,6 @@ class Semantic {
1210
1234
traverser.traverse(tpt.tpe)
1211
1235
buf.toList
1212
1236
1213
- }
1214
-
1215
- object Semantic {
1216
-
1217
1237
// ----- Utility methods and extractors --------------------------------
1218
1238
1219
1239
def typeRefOf (tp : Type )(using Context ): TypeRef = tp.dealias.typeConstructor match {
0 commit comments