-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make HOAS Quote pattern match with def method capture
closes #17105
- Loading branch information
1 parent
a68568c
commit 3af515d
Showing
8 changed files
with
191 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
case erased: [erased case] | ||
case erased nested: c | ||
case erased nested 2: d |
25 changes: 25 additions & 0 deletions
25
tests/run-custom-args/run-macros-erased/i17105/Macro_1.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import scala.quoted.* | ||
|
||
inline def testExpr(inline body: Any) = ${ testExprImpl('body) } | ||
def testExprImpl(body: Expr[Any])(using Quotes): Expr[String] = | ||
body match | ||
// Erased Types | ||
case '{ def erasedfn(y: String) = "placeholder"; $a(erasedfn): String } => | ||
Expr("This case should not match") | ||
case '{ def erasedfn(erased y: String) = "placeholder"; $a(erasedfn): String } => | ||
'{ $a((erased z: String) => "[erased case]") } | ||
case '{ | ||
def erasedfn(a: String, b: String)(c: String, d: String): String = a | ||
$y(erasedfn): String | ||
} => Expr("This should not match") | ||
case '{ | ||
def erasedfn(a: String, erased b: String)(erased c: String, d: String): String = a | ||
$y(erasedfn): String | ||
} => | ||
'{ $y((a: String, erased b: String) => (erased c: String, d: String) => d) } | ||
case '{ | ||
def erasedfn(a: String, erased b: String)(c: String, erased d: String): String = a | ||
$y(erasedfn): String | ||
} => | ||
'{ $y((a: String, erased b: String) => (c: String, erased d: String) => c) } | ||
case _ => Expr("not matched") |
10 changes: 10 additions & 0 deletions
10
tests/run-custom-args/run-macros-erased/i17105/Test_2.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
@main def Test: Unit = | ||
println("case erased: " + testExpr { def erasedfn1(erased x: String) = "placeholder"; erasedfn1("arg1")}) | ||
println("case erased nested: " + testExpr { | ||
def erasedfn2(p: String, erased q: String)(r: String, erased s: String) = p | ||
erasedfn2("a", "b")("c", "d") | ||
}) | ||
println("case erased nested 2: " + testExpr { | ||
def erasedfn2(p: String, erased q: String)(erased r: String, s: String) = p | ||
erasedfn2("a", "b")("c", "d") | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
case single: [1st case] arg1 outside | ||
case no-param-method (will be eta-expanded): [1st case] placeholder 2 | ||
case curried: [2nd case] arg1, arg2 outside | ||
case methods from outer scope: [1st case] arg1 outer-method | ||
case refinement: Hoe got 1 | ||
case dependent: 1 | ||
case dependent2: 1 | ||
case dependent3: 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
|
||
// Test case for dependent types | ||
trait DSL { | ||
type N | ||
def toString(n: N): String | ||
val zero: N | ||
def next(n: N): N | ||
} | ||
|
||
object IntDSL extends DSL { | ||
type N = Int | ||
def toString(n: N): String = n.toString() | ||
val zero = 0 | ||
def next(n: N): N = n + 1 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import scala.quoted.* | ||
import language.experimental.erasedDefinitions | ||
|
||
inline def testExpr(inline body: Any) = ${ testExprImpl('body) } | ||
def testExprImpl(body: Expr[Any])(using Quotes): Expr[String] = | ||
body match | ||
case '{ def g(y: String) = "placeholder" + y; $a(g): String } => | ||
'{ $a((z: String) => s"[1st case] ${z}") } | ||
case '{ def g(y: String)(z: String) = "placeholder" + y; $a(g): String } => | ||
'{ $a((z1: String) => (z2: String) => s"[2nd case] ${z1}, ${z2}") } | ||
// Refined Types | ||
case '{ | ||
type t | ||
def refined(a: `t`): String = $x(a): String | ||
$y(refined): String | ||
} => | ||
'{ $y($x) } | ||
// Dependent Types | ||
case '{ | ||
def p(dsl: DSL): dsl.N = dsl.zero | ||
$y(p): String | ||
} => | ||
'{ $y((dsl1: DSL) => dsl1.next(dsl1.zero)) } | ||
case '{ | ||
def p(dsl: DSL)(a: dsl.N): dsl.N = a | ||
$y(p): String | ||
} => | ||
'{ $y((dsl: DSL) => (b2: dsl.N) => dsl.next(b2)) } | ||
case '{ | ||
def p(dsl1: DSL)(dsl2: DSL): dsl2.N = dsl2.zero | ||
$y(p): String | ||
} => | ||
'{ $y((dsl1: DSL) => (dsl2: DSL) => dsl2.next(dsl2.zero)) } | ||
case _ => Expr("not matched") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import reflect.Selectable.reflectiveSelectable | ||
|
||
class Hoe { def f(x: Int): String = s"Hoe got ${x}" } | ||
|
||
@main def Test: Unit = | ||
println("case single: " + testExpr { def f(x: String) = "placeholder" + x; f("arg1") + " outside" }) | ||
println("case no-param-method (will be eta-expanded): " + testExpr { def f(x: String) = "placeholder" + x; (() => f)()("placeholder 2") }) | ||
println("case curried: " + testExpr { def f(x: String)(y: String) = "placeholder" + x; f("arg1")("arg2") + " outside" }) | ||
def outer() = " outer-method" | ||
println("case methods from outer scope: " + testExpr { def f(x: String) = "placeholder" + x; f("arg1") + outer() }) | ||
println("case refinement: " + testExpr { def refined(a: { def f(x: Int): String }): String = a.f(1); refined(Hoe()) }) | ||
println("case dependent: " + testExpr { | ||
def p(a: DSL): a.N = a.zero | ||
IntDSL.toString(p(IntDSL)) | ||
}) | ||
println("case dependent2: " + testExpr { | ||
def p(dsl1: DSL)(c: dsl1.N): dsl1.N = c | ||
IntDSL.toString(p(IntDSL)(IntDSL.zero)) | ||
}) | ||
println("case dependent3: " + testExpr { | ||
def p(dsl1: DSL)(dsl2: DSL): dsl2.N = dsl2.zero | ||
IntDSL.toString(p(IntDSL)(IntDSL)) | ||
}) |