Last active
September 17, 2020 17:02
-
-
Save mbloms/4e453025d12114e445638b0b1c36431f to your computer and use it in GitHub Desktop.
Improved version: Captured types are aggregated into a Union Type
This file contains hidden or 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
import scala.spores._ | |
object CapturedTest { | |
def main(args: Array[String]): Unit = { | |
val hejdu: String = "hejdu" | |
val s = | |
spore { | |
val str = hejdu; | |
val num = 2; | |
{() => | |
println(str) | |
println(num) | |
} | |
} | |
s.apply() | |
} | |
} |
This file contains hidden or 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
//result of CapturedTest.scala after typer: | |
package <empty> { | |
import scala.spores._ | |
final lazy module val CapturedTest: CapturedTest$ = new CapturedTest$() | |
final module class CapturedTest$() extends Object() { | |
this: CapturedTest.type => | |
def main(args: Array[String]): Unit = | |
{ | |
val hejdu: String = "hejdu" | |
val s: spores.NullarySpore[Unit]{Captured = String | Int} = | |
{ | |
{ | |
spores.typedSpore[Unit, String | Int]( | |
{ | |
{ | |
{ | |
val str: String = hejdu | |
val num: Int = 2 | |
{ | |
def $anonfun(): Unit = | |
{ | |
println(str) | |
println(num) | |
} | |
closure($anonfun) | |
} | |
} | |
} | |
} | |
) | |
} | |
} | |
s.apply() | |
} | |
} | |
} |
This file contains hidden or 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
package scala.spores | |
import scala.quoted._ | |
import scala.tasty.reflect._ | |
transparent inline def spore[R](inline body: () => R) = | |
${sporeImpl('body)} | |
private def typedSpore[R,C](body: () => R) = | |
new NullarySpore[R] { | |
override type Captured = C | |
//override val captured = null | |
override def apply() = body() | |
override def skipScalaSamConversion: Nothing = ??? | |
} | |
/** dummy function only for generating union types */ | |
private def union(a: Any, b: Any): a.type | b.type = ??? | |
private def sporeImpl[R: Type](expr: Expr[() => R])(using qctx: QuoteContext) = { | |
import qctx.tasty.{Block,ValDef,Statement} | |
/** Extract rhs term from val declaration */ | |
transparent inline def rhs(statement: Statement) = statement match | |
case ValDef(str, tpt, Some(term)) => term.seal | |
case _ => report.throwError("Only val declarations are allowed in the spore header.") | |
/** Generate a bogus expression with the type of all captured variables | |
* NOTE: Currently the declared type in val defs are ignored, only the inferred type is used | |
*/ | |
def capturedTypes(statements: List[Statement]): Expr[?] = statements match { | |
case List(statement) => rhs(statement) match | |
case '{$c: $ct} => c | |
case x::xs => rhs(x) match | |
case '{$c: $ct} => '{union($c,${capturedTypes(xs)})} | |
} | |
expr.unseal.underlyingArgument match | |
case block @ Block(statements,term) => capturedTypes(statements) match | |
case '{$c: $ct} => | |
'{typedSpore[${summon[Type[R]]},$ct]($expr)} | |
case _ => ??? | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output from running: