1+ import language .experimental .captureChecking
2+ import language .experimental .separationChecking
3+ import caps .*
4+
5+ class Ref (x : Int ) extends Mutable :
6+ private var value : Int = x
7+ def get (): Int = value
8+ update def set (newValue : Int ): Unit = value = newValue
9+
10+ // For testing types other than functions
11+ class Wrapper (val ref : Ref ^ ) extends Mutable :
12+ def compute (): Int = ref.get()
13+ update def mutate (x : Int ): Unit = ref.set(x)
14+
15+ class WrapperRd (val ref : Ref ^ {cap.rd}):
16+ def compute (): Int = ref.get()
17+
18+ @ main def run =
19+ val r : Ref ^ = Ref (0 )
20+ val r2 : Ref ^ = Ref (42 )
21+
22+ // Test case 1: Read-only access in initializer - should be OK
23+ lazy val lazyVal : () -> {r.rd} Int =
24+ val current = r2.get()
25+ () => r.get() + current
26+
27+ // Test case 2: Exclusive access in initializer - should error
28+ lazy val lazyVal2 : () -> {r.rd} Int =
29+ val current = r2.get()
30+ r.set(current * 100 ) // error - exclusive access in initializer
31+ () => r.get()
32+
33+ // Test case 3: Exclusive access in returned closure - should be OK
34+ lazy val lazyVal3 : () -> {r} Int =
35+ val current = r2.get()
36+ () => r.set(current); r.get() // exclusive access in closure, not initializer
37+
38+ // Test case 4: Multiple nested blocks with exclusive access - should error
39+ lazy val lazyVal4 : () -> {r.rd} Int =
40+ val x = {
41+ val y = {
42+ r.set(100 ) // error
43+ r.get()
44+ }
45+ y + 1
46+ }
47+ () => r.get() + x
48+
49+ // Test case 5: Multiple nested blocks with only read access - should be OK
50+ lazy val lazyVal5 : () -> {r.rd} Int =
51+ val x = {
52+ val y = {
53+ r.get() // only read access in nested blocks
54+ }
55+ y + 1
56+ }
57+ () => r.get() + x
58+
59+ // Test case 6: WrapperRd type - exclusive access in initializer - should error
60+ lazy val lazyVal6 : WrapperRd ^ {r} =
61+ r.set(200 ) // error
62+ WrapperRd (r)
63+
64+ // Test case 7: WrapperRd type - non-exclusive access in initializer - should be ok
65+ lazy val lazyVal7 : WrapperRd ^ {r} =
66+ r.get()
67+ WrapperRd (r)
68+
69+ // Test case 8: Wrapper type - exclusive access in initializer - should error
70+ lazy val lazyVal8 : Wrapper ^ {cap, r} =
71+ r.set(200 ) // error
72+ Wrapper (r)
73+
74+ // Test case 9: Wrapper type - non-exclusive access in initializer - should be ok
75+ lazy val lazyVal9 : Wrapper ^ {cap, r} =
76+ r.get()
77+ Wrapper (r)
78+
79+ // Test case 10: Conditional with exclusive access - should error
80+ lazy val lazyVal10 : WrapperRd ^ {r} =
81+ val x = if r.get() > 0 then
82+ r.set(0 ) // error exclusive access in conditional
83+ 1
84+ else 2
85+ WrapperRd (r)
86+
87+ // Test case 11: Try-catch with exclusive access - should error
88+ lazy val lazyVal11 : () -> {r.rd} Int =
89+ val x = try
90+ r.set(42 ) // error
91+ r.get()
92+ catch
93+ case _ : Exception => 0
94+ () => r.get() + x
95+
96+ // // Test case 12: Local exclusive access - should be OK
97+ // lazy val lazyVal12: () => Int =
98+ // val r3: Ref^ = Ref(10)
99+ // r3.set(100) FIXME should work
100+ // () => r3.get()
0 commit comments