1
1
import scala .quoted ._
2
+ import scala .quoted .util ._
2
3
import given scala .quoted .autolift ._
3
4
4
5
/**
5
6
* Port of the strymonas library as described in O. Kiselyov et al., Stream fusion, to completeness (POPL 2017)
6
7
*/
7
-
8
8
object Test {
9
9
10
- // TODO: remove as it exists in Quoted Lib
11
- sealed trait Var [T ] {
12
- def get given QuoteContext : Expr [T ]
13
- def update (x : Expr [T ]) given QuoteContext : Expr [Unit ]
14
- }
15
-
16
- object Var {
17
- def apply [T : Type , U : Type ](init : Expr [T ])(body : Var [T ] => Expr [U ]) given QuoteContext : Expr [U ] = ' {
18
- var x = $init
19
- $ {
20
- body(
21
- new Var [T ] {
22
- def get given QuoteContext : Expr [T ] = ' x
23
- def update (e : Expr [T ]) given QuoteContext : Expr [Unit ] = ' { x = $e }
24
- }
25
- )
26
- }
27
- }
28
- }
10
+ type E [T ] = given QuoteContext => Expr [T ]
29
11
30
12
/** * Producer represents a linear production of values with a loop structure.
31
13
*
@@ -61,27 +43,29 @@ object Test {
61
43
* @param k the continuation that is invoked after the new state is defined in the body of `init`
62
44
* @return expr value of unit per the CPS-encoding
63
45
*/
64
- def init (k : St => Expr [Unit ]) given QuoteContext : Expr [Unit ]
46
+ def init (k : St => Expr [Unit ]): E [Unit ]
65
47
66
48
/** Step method that defines the transformation of data.
67
49
*
68
50
* @param st the state needed for this iteration step
69
51
* @param k the continuation that accepts each element and proceeds with the step-wise processing
70
52
* @return expr value of unit per the CPS-encoding
71
53
*/
72
- def step (st : St , k : (A => Expr [Unit ])) given QuoteContext : Expr [Unit ]
54
+ def step (st : St , k : (A => Expr [Unit ])): E [Unit ]
73
55
74
56
/** The condition that checks for termination
75
57
*
76
58
* @param st the state needed for this iteration check
77
59
* @return the expression for a boolean
78
60
*/
79
- def hasNext (st : St ) given QuoteContext : Expr [Boolean ]
61
+ def hasNext (st : St ): E [Boolean ]
80
62
}
81
63
82
- trait Cardinality
83
- case object AtMost1 extends Cardinality
84
- case object Many extends Cardinality
64
+ enum Cardinality {
65
+ case AtMost1
66
+ case Many
67
+ }
68
+ import Cardinality ._
85
69
86
70
trait StagedStream [A ]
87
71
case class Linear [A ](producer : Producer [A ]) extends StagedStream [A ]
@@ -98,19 +82,17 @@ object Test {
98
82
* @tparam W the type of the accumulator
99
83
* @return
100
84
*/
101
- def fold [W : Type ](z : Expr [W ], f : ((Expr [W ], Expr [A ]) => Expr [W ])) given QuoteContext : Expr [W ] = {
102
- Var (z) { s : Var [W ] => ' {
103
- $ {
104
- foldRaw[Expr [A ]]((a : Expr [A ]) => ' {
105
- $ { s.update(f(s.get, a)) }
106
- }, stream)
107
- }
85
+ def fold [W : Type ](z : Expr [W ], f : ((Expr [W ], Expr [A ]) => Expr [W ])): E [W ] = {
86
+ Var (z) { s =>
87
+ ' {
88
+ $ { foldRaw[Expr [A ]]((a : Expr [A ]) => s.update(f(s.get, a)), stream) }
89
+
108
90
$ { s.get }
109
91
}
110
92
}
111
93
}
112
94
113
- private def foldRaw [A ](consumer : A => Expr [Unit ], stream : StagedStream [A ]) given QuoteContext : Expr [Unit ] = {
95
+ private def foldRaw [A ](consumer : A => Expr [Unit ], stream : StagedStream [A ]): E [Unit ] = {
114
96
stream match {
115
97
case Linear (producer) => {
116
98
producer.card match {
@@ -166,15 +148,15 @@ object Test {
166
148
type St = producer.St
167
149
val card = producer.card
168
150
169
- def init (k : St => Expr [Unit ]) given QuoteContext : Expr [Unit ] = {
151
+ def init (k : St => Expr [Unit ]): E [Unit ] = {
170
152
producer.init(k)
171
153
}
172
154
173
- def step (st : St , k : (B => Expr [Unit ])) given QuoteContext : Expr [Unit ] = {
155
+ def step (st : St , k : (B => Expr [Unit ])): E [Unit ] = {
174
156
producer.step(st, el => f(el)(k))
175
157
}
176
158
177
- def hasNext (st : St ) given QuoteContext : Expr [Boolean ] = {
159
+ def hasNext (st : St ): E [Boolean ] = {
178
160
producer.hasNext(st)
179
161
}
180
162
}
@@ -229,13 +211,13 @@ object Test {
229
211
type St = Expr [A ]
230
212
val card = AtMost1
231
213
232
- def init (k : St => Expr [Unit ]) given QuoteContext : Expr [Unit ] =
214
+ def init (k : St => Expr [Unit ]): E [Unit ] =
233
215
k(a)
234
216
235
- def step (st : St , k : (Expr [A ] => Expr [Unit ])) given QuoteContext : Expr [Unit ] =
217
+ def step (st : St , k : (Expr [A ] => Expr [Unit ])): E [Unit ] =
236
218
k(st)
237
219
238
- def hasNext (st : St ) given QuoteContext : Expr [Boolean ] =
220
+ def hasNext (st : St ): E [Boolean ] =
239
221
pred(st)
240
222
}
241
223
@@ -259,13 +241,13 @@ object Test {
259
241
type St = producer.St
260
242
val card = producer.card
261
243
262
- def init (k : St => Expr [Unit ]) given QuoteContext : Expr [Unit ] =
244
+ def init (k : St => Expr [Unit ]): E [Unit ] =
263
245
producer.init(k)
264
246
265
- def step (st : St , k : (A => Expr [Unit ])) given QuoteContext : Expr [Unit ] =
247
+ def step (st : St , k : (A => Expr [Unit ])): E [Unit ] =
266
248
producer.step(st, el => k(el))
267
249
268
- def hasNext (st : St ) given QuoteContext : Expr [Boolean ] =
250
+ def hasNext (st : St ): E [Boolean ] =
269
251
f(producer.hasNext(st))
270
252
}
271
253
case AtMost1 => producer
@@ -292,22 +274,20 @@ object Test {
292
274
type St = (Var [Int ], producer.St )
293
275
val card = producer.card
294
276
295
- def init (k : St => Expr [Unit ]) given QuoteContext : Expr [Unit ] = {
277
+ def init (k : St => Expr [Unit ]): E [Unit ] = {
296
278
producer.init(st => {
297
279
Var (n) { counter =>
298
280
k(counter, st)
299
281
}
300
282
})
301
283
}
302
284
303
- def step (st : St , k : (((Var [Int ], A )) => Expr [Unit ])) given QuoteContext : Expr [Unit ] = {
285
+ def step (st : St , k : (((Var [Int ], A )) => Expr [Unit ])): E [Unit ] = {
304
286
val (counter, currentState) = st
305
- producer.step(currentState, el => ' {
306
- $ {k((counter, el))}
307
- })
287
+ producer.step(currentState, el => k((counter, el)))
308
288
}
309
289
310
- def hasNext (st : St ) given QuoteContext : Expr [Boolean ] = {
290
+ def hasNext (st : St ): E [Boolean ] = {
311
291
val (counter, currentState) = st
312
292
producer.card match {
313
293
case Many => ' { $ {counter.get} > 0 && $ {producer.hasNext(currentState)} }
@@ -365,7 +345,7 @@ object Test {
365
345
pushLinear[A = Expr [A ], C = B ](producer1, producer2, nestf2)
366
346
367
347
case (Nested (producer1, nestf1), Linear (producer2)) =>
368
- mapRaw[(B , Expr [A ]), (Expr [A ], B )]((t => k => ' { $ { k((t._2, t._1))} } ), pushLinear[A = B , C = Expr [A ]](producer2, producer1, nestf1))
348
+ mapRaw[(B , Expr [A ]), (Expr [A ], B )]((t => k => k((t._2, t._1))), pushLinear[A = B , C = Expr [A ]](producer2, producer1, nestf1))
369
349
370
350
case (Nested (producer1, nestf1), Nested (producer2, nestf2)) =>
371
351
zipRaw[A , B ](Linear (makeLinear(stream1)), stream2)
@@ -441,7 +421,7 @@ object Test {
441
421
* @param k the continuation that consumes a variable.
442
422
* @return the quote of the orchestrated code that will be executed as
443
423
*/
444
- def makeAdvanceFunction [A ](nadv : Var [Unit => Unit ], k : A => Expr [Unit ], stream : StagedStream [A ]) given QuoteContext : Expr [Unit ] = {
424
+ def makeAdvanceFunction [A ](nadv : Var [Unit => Unit ], k : A => Expr [Unit ], stream : StagedStream [A ]): E [Unit ] = {
445
425
stream match {
446
426
case Linear (producer) =>
447
427
producer.card match {
@@ -482,7 +462,7 @@ object Test {
482
462
type St = (Var [Boolean ], Var [A ], Var [Unit => Unit ])
483
463
val card : Cardinality = Many
484
464
485
- def init (k : St => Expr [Unit ]) given QuoteContext : Expr [Unit ] = {
465
+ def init (k : St => Expr [Unit ]): E [Unit ] = {
486
466
producer.init(st =>
487
467
Var (' { (_ : Unit ) => ()}){ nadv => {
488
468
Var (' { true }) { hasNext => {
@@ -506,7 +486,7 @@ object Test {
506
486
}})
507
487
}
508
488
509
- def step (st : St , k : Expr [A ] => Expr [Unit ]) given QuoteContext : Expr [Unit ] = {
489
+ def step (st : St , k : Expr [A ] => Expr [Unit ]): E [Unit ] = {
510
490
val (flag, current, nadv) = st
511
491
' {
512
492
var el = $ {current.get}
@@ -517,7 +497,7 @@ object Test {
517
497
518
498
}
519
499
520
- def hasNext (st : St ) given QuoteContext : Expr [Boolean ] = {
500
+ def hasNext (st : St ): E [Boolean ] = {
521
501
val (flag, _, _) = st
522
502
flag.get
523
503
}
@@ -532,19 +512,19 @@ object Test {
532
512
type St = (Var [Boolean ], producer.St , nestedProducer.St )
533
513
val card : Cardinality = Many
534
514
535
- def init (k : St => Expr [Unit ]) given QuoteContext : Expr [Unit ] = {
536
- producer.init(s1 => ' { $ { nestedProducer.init(s2 =>
515
+ def init (k : St => Expr [Unit ]): E [Unit ] = {
516
+ producer.init(s1 => nestedProducer.init(s2 =>
537
517
Var (producer.hasNext(s1)) { flag =>
538
518
k((flag, s1, s2))
539
- })}} )
519
+ }))
540
520
}
541
521
542
- def step (st : St , k : ((Var [Boolean ], producer.St , B )) => Expr [Unit ]) given QuoteContext : Expr [Unit ] = {
522
+ def step (st : St , k : ((Var [Boolean ], producer.St , B )) => Expr [Unit ]): E [Unit ] = {
543
523
val (flag, s1, s2) = st
544
- nestedProducer.step(s2, b => ' { $ { k((flag, s1, b))} } )
524
+ nestedProducer.step(s2, b => k((flag, s1, b)))
545
525
}
546
526
547
- def hasNext (st : St ) given QuoteContext : Expr [Boolean ] = {
527
+ def hasNext (st : St ): E [Boolean ] = {
548
528
val (flag, s1, s2) = st
549
529
' { $ {flag.get} && $ {nestedProducer.hasNext(s2)} }
550
530
}
@@ -554,7 +534,7 @@ object Test {
554
534
val (flag, s1, b) = t
555
535
556
536
mapRaw[C , (A , C )]((c => k => ' {
557
- $ {producer.step(s1, a => ' { $ { k((a, c))} } )}
537
+ $ {producer.step(s1, a => k((a, c)))}
558
538
$ {flag.update(producer.hasNext(s1))}
559
539
}), addTerminationCondition((b_flag : Expr [Boolean ]) => ' { $ {flag.get} && $b_flag }, nestedf(b)))
560
540
})
@@ -567,16 +547,16 @@ object Test {
567
547
type St = (producer1.St , producer2.St )
568
548
val card : Cardinality = Many
569
549
570
- def init (k : St => Expr [Unit ]) given QuoteContext : Expr [Unit ] = {
550
+ def init (k : St => Expr [Unit ]): E [Unit ] = {
571
551
producer1.init(s1 => producer2.init(s2 => k((s1, s2)) ))
572
552
}
573
553
574
- def step (st : St , k : ((A , B )) => Expr [Unit ]) given QuoteContext : Expr [Unit ] = {
554
+ def step (st : St , k : ((A , B )) => Expr [Unit ]): E [Unit ] = {
575
555
val (s1, s2) = st
576
556
producer1.step(s1, el1 => producer2.step(s2, el2 => k((el1, el2)) ))
577
557
}
578
558
579
- def hasNext (st : St ) given QuoteContext : Expr [Boolean ] = {
559
+ def hasNext (st : St ): E [Boolean ] = {
580
560
val (s1, s2) = st
581
561
' { $ {producer1.hasNext(s1)} && $ {producer2.hasNext(s2)} }
582
562
}
@@ -597,15 +577,15 @@ object Test {
597
577
598
578
val card = Many
599
579
600
- def init (k : St => Expr [Unit ]) given QuoteContext : Expr [Unit ] = {
580
+ def init (k : St => Expr [Unit ]): E [Unit ] = {
601
581
Var (' {($arr).length}) { n =>
602
582
Var (0 ){ i =>
603
583
k((i, n, arr))
604
584
}
605
585
}
606
586
}
607
587
608
- def step (st : St , k : (Expr [A ] => Expr [Unit ])) given QuoteContext : Expr [Unit ] = {
588
+ def step (st : St , k : (Expr [A ] => Expr [Unit ])): E [Unit ] = {
609
589
val (i, _, arr) = st
610
590
' {
611
591
val el = ($arr).apply($ {i.get})
@@ -614,7 +594,7 @@ object Test {
614
594
}
615
595
}
616
596
617
- def hasNext (st : St ) given QuoteContext : Expr [Boolean ] = {
597
+ def hasNext (st : St ): E [Boolean ] = {
618
598
val (i, n, _) = st
619
599
' {
620
600
($ {i.get} < $ {n.get})
0 commit comments