File tree 3 files changed +53
-0
lines changed
3 files changed +53
-0
lines changed Original file line number Diff line number Diff line change
1
+ 2
2
+ List(3, 2, 4)
Original file line number Diff line number Diff line change
1
+ import scala .quoted .*
2
+
3
+ object Places :
4
+ def withPlace [T : Type , R : Type ](x : Expr [T ])(body : Quotes ?=> Place [T ] => Expr [R ])(using Quotes ): Expr [R ] = {
5
+ x match
6
+ case ' { ($arr : Array [T ]).apply($index) } => // TODO use more general version using reflection (apply/update methods)
7
+ ' {
8
+ val idx = $index
9
+ $ {
10
+ body(
11
+ new Place [T ]:
12
+ def set (x : Expr [T ]): Expr [Unit ] = ' { $arr(idx) = $x }
13
+ def get : Expr [T ] = ' { $arr(idx) }
14
+ )
15
+ }
16
+ }
17
+ case ' { $x : T } =>
18
+ import quotes .reflect .*
19
+ x.asTerm match
20
+ case ident : Ident if ident.symbol.flags.is(Flags .Mutable ) =>
21
+ body(
22
+ new Place [T ]:
23
+ def set (x : Expr [T ]): Expr [Unit ] = Assign (ident, x.asTerm).asExprOf[Unit ]
24
+ def get : Expr [T ] = x
25
+ )
26
+ case Apply (Select (place, " apply" ), List (idx)) => // TODO check that place has an update method
27
+ ' {??? } // TODO
28
+ case tree =>
29
+ throw new MatchError (tree.show(using Printer .TreeStructure ))
30
+ }
31
+
32
+ trait Place [T ]:
33
+ def set (x : Expr [T ]): Expr [Unit ]
34
+ def get : Expr [T ]
35
+
36
+
37
+ inline def increment (inline x : Int ): Unit = $ { incrementExpr(' x ) } // TODO generalize to Numeric types
38
+
39
+ private def incrementExpr (x : Expr [Int ])(using Quotes ): Expr [Unit ] =
40
+ Places .withPlace(x) { place => place.set(' { $ {place.get} + 1 }) }
Original file line number Diff line number Diff line change
1
+
2
+ @ main def Test : Unit =
3
+ var x = 1
4
+ increment(x)
5
+ println(x)
6
+
7
+ val arr = Array (1 , 2 , 3 )
8
+ increment(arr(0 ))
9
+ increment(arr(0 ))
10
+ increment(arr(2 ))
11
+ println(arr.toList)
You can’t perform that action at this time.
0 commit comments