Skip to content

Commit e71fe80

Browse files
authoredJun 6, 2022
Merge pull request #15339 from dotty-staging/add-place-regression-test
Add regression tests
2 parents ec74aa4 + a4bab18 commit e71fe80

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed
 

‎tests/run-macros/places-proto.check

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2
2+
List(3, 2, 4)
3+
A(3, 2, 4)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import scala.quoted.*
2+
3+
object Places:
4+
def withPlace[T: Type, R: Type](expr: Expr[T])(body: Quotes ?=> Place[T] => Expr[R])(using Quotes): Expr[R] = {
5+
// TODO: support applyDynamic/updateDynamic?
6+
import quotes.reflect.*
7+
expr match
8+
case '{ $expr: T } =>
9+
expr.asTerm match
10+
case placeVar: Ident if placeVar.symbol.flags.is(Flags.Mutable) =>
11+
body(
12+
new Place[T]:
13+
def set(x: Expr[T]): Expr[Unit] = Assign(placeVar, x.asTerm).asExprOf[Unit]
14+
def get: Expr[T] = expr
15+
)
16+
case Apply(placeApply @ Select(placeTerm, "apply"), List(indexTerm)) =>
17+
def updateWithCorrectSignature(sym: Symbol): Boolean =
18+
true // TODO check signature
19+
val updateSym = placeTerm.symbol.methodMember("update")
20+
.find(updateWithCorrectSignature)
21+
.getOrElse(report.errorAndAbort("Cannot assign to " + expr, expr))
22+
val placeUpdate = placeTerm.select(updateSym)
23+
indexTerm.asExpr match
24+
case '{ $indexExpr: idx } =>
25+
'{
26+
val index: idx = $indexExpr
27+
${
28+
val boundIndex = '{index}.asTerm
29+
val place = new Place[T]:
30+
def set(x: Expr[T]): Expr[Unit] = placeUpdate.appliedTo(boundIndex, x.asTerm).asExprOf[Unit]
31+
def get: Expr[T] = placeApply.appliedTo(boundIndex).asExprOf[T]
32+
body(place)
33+
}
34+
}
35+
case tree =>
36+
throw new MatchError(tree.show(using Printer.TreeStructure))
37+
}
38+
39+
40+
trait Place[T]:
41+
def set(x: Expr[T]): Expr[Unit]
42+
def get: Expr[T]
43+
44+
end Places
45+
46+
inline def increment(inline x: Int): Unit = ${ incrementExpr('x) } // TODO generalize to Numeric types
47+
48+
private def incrementExpr(x: Expr[Int])(using Quotes): Expr[Unit] =
49+
Places.withPlace(x) { place => place.set('{ ${place.get} + 1 }) }
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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)
12+
13+
val a = new A
14+
increment(a(0))
15+
increment(a(0))
16+
increment(a(2))
17+
println(a)
18+
19+
20+
class A:
21+
private var x = Array(1, 2, 3)
22+
def apply(i: Int): Int = x(i)
23+
def update(i: Int, value: Int): Unit = { x(i) = value }
24+
override def toString(): String = s"A(${x.mkString(", ")})"

0 commit comments

Comments
 (0)