|
1 | 1 | import language.experimental.captureChecking
|
2 | 2 | import language.experimental.separationChecking
|
| 3 | +import language.experimental.erasedDefinitions |
| 4 | + |
3 | 5 | import caps.*
|
4 | 6 |
|
5 | 7 | // Test inspired by the "Gentrification Gone too Far?" paper
|
6 | 8 | object Levels:
|
7 | 9 |
|
| 10 | + /* User-defined capability classifiers */ |
8 | 11 | trait Read extends Classifier, SharedCapability
|
9 | 12 | trait ReadWrite extends Classifier, SharedCapability
|
10 | 13 |
|
11 | 14 | trait File(val name: String):
|
12 |
| - val r: Read^ |
13 |
| - val rw: ReadWrite^ |
14 |
| - // operations guarded by boxed capability members |
| 15 | + // file-specific capability members, these are ensured to be erased |
| 16 | + erased val r: Read^ |
| 17 | + erased val rw: ReadWrite^ |
| 18 | + // operations guarded by capability members |
15 | 19 | val read: () ->{r} Int
|
16 | 20 | val write: Int ->{rw} Unit
|
17 | 21 |
|
18 | 22 | object File:
|
19 | 23 | def apply(s: String): File^ = new File(s) {
|
20 |
| - val r = new Read {} |
21 |
| - val rw = new ReadWrite {} |
| 24 | + erased val r = new Read {} |
| 25 | + erased val rw = new ReadWrite {} |
22 | 26 | val read = () =>
|
23 | 27 | println(s"Reading from $name with capability $r")
|
24 | 28 | 42
|
25 | 29 | val write = (i: Int) =>
|
26 | 30 | println(s"Writing $i to $name with capability $rw")
|
27 | 31 | }
|
28 | 32 |
|
29 |
| - // Unfortunately, we do not have @use lambdas yet |
30 |
| - trait UseFunction[U]: |
31 |
| - def apply[C^](f: File^{C}): U |
32 |
| - |
33 |
| - def withFile[U](name: String)(block: UseFunction[U]): U = block(File(name)) // unrestricted use of files & other capabilities |
| 33 | + def withFile[U](name: String)(block: File^ => U): U = block(File(name)) // unrestricted use of files & other capabilities |
34 | 34 | def parReduce[U](xs: Seq[U])(op: (U, U) ->{cap.only[Read]} U): U = xs.reduce(op) // only Read-classified allowed
|
35 | 35 |
|
36 | 36 | @main def test =
|
37 |
| - withFile("foo.txt"): |
38 |
| - new UseFunction[Unit]: |
39 |
| - def apply[C^](f: File^{C}): Unit = |
40 |
| - f.read() // ok |
41 |
| - parReduce(1 to 1000): (a, b) => |
42 |
| - a * b * f.read() // ok |
43 |
| - parReduce(1 to 1000): (a, b) => // error |
44 |
| - f.write(42) // the error stems from here |
45 |
| - a + b + f.read() // ok |
46 |
| - f.write(42) // ok, unrestricted access to file |
| 37 | + withFile("foo.txt"): f => |
| 38 | + f.read() // ok |
| 39 | + parReduce(1 to 1000): (a, b) => |
| 40 | + a * b * f.read() // ok |
| 41 | + parReduce(1 to 1000): (a, b) => // error |
| 42 | + f.write(42) // the error stems from here |
| 43 | + a + b + f.read() // ok |
| 44 | + f.write(42) // ok, unrestricted access to file |
47 | 45 |
|
48 | 46 | def testMulti =
|
49 |
| - withFile("foo.txt"): |
50 |
| - new UseFunction[Unit]: |
51 |
| - def apply[C^](f: File^{C}): Unit = |
52 |
| - withFile("bar.txt"): |
53 |
| - new UseFunction[Unit]: |
54 |
| - def apply[C^](g: File^{C}): Unit = |
55 |
| - f.read() // ok |
56 |
| - g.read() // ok |
57 |
| - parReduce(1 to 1000): (a, b) => |
58 |
| - a * b * f.read() + g.read() // ok |
59 |
| - parReduce(1 to 1000): (a, b) => // error |
60 |
| - f.write(42) // the error stems from here |
61 |
| - a + b + f.read() + g.read() // ok |
62 |
| - parReduce(1 to 1000): (a, b) => // error |
63 |
| - g.write(42) // the error stems from here |
64 |
| - 0 |
65 |
| - f.write(42) // ok, unrestricted access to file |
66 |
| - g.write(42) // ok, unrestricted access to file |
| 47 | + withFile("foo.txt"): f => |
| 48 | + withFile("bar.txt"): g => |
| 49 | + f.read() // ok |
| 50 | + g.read() // ok |
| 51 | + parReduce(1 to 1000): (a, b) => |
| 52 | + a * b * f.read() + g.read() // ok |
| 53 | + parReduce(1 to 1000): (a, b) => // error |
| 54 | + f.write(42) // the error stems from here |
| 55 | + a + b + f.read() + g.read() // ok |
| 56 | + parReduce(1 to 1000): (a, b) => // error |
| 57 | + g.write(42) // the error stems from here |
| 58 | + 0 |
| 59 | + f.write(42) // ok, unrestricted access to file |
| 60 | + g.write(42) // ok, unrestricted access to file |
67 | 61 |
|
0 commit comments