Skip to content

Instantly share code, notes, and snippets.

@prolativ
Created June 19, 2023 17:08
Show Gist options
  • Save prolativ/0fca0f4c1a36abca291837007ff80dd0 to your computer and use it in GitHub Desktop.
Save prolativ/0fca0f4c1a36abca291837007ff80dd0 to your computer and use it in GitHub Desktop.
Constructing structural type in macro
//> using scala 3.3.0
trait Sel extends Selectable:
def selectDynamic(name: String) = s"name: $name"
def applyDynamic(name: String)(args: Any*) = s"name: $name, args: $args"
object Sel:
type Subtype[T <: Sel] = T
import scala.quoted.*
transparent inline def makeSel: Sel = ${ makeSelImpl }
def makeSelImpl(using Quotes): Expr[Sel] =
import quotes.reflect.*
val tpe0 = TypeRepr.of[Sel]
val tpe1 = Refinement(tpe0, "field", TypeRepr.of[String])
val tpe2 = Refinement(tpe1, "parameterless", ByNameType(TypeRepr.of[String]))
val tpe3 = Refinement(tpe2, "emptyParamList", MethodType(List())(_ => List(), _ => TypeRepr.of[String]))
val tpe4 = Refinement(tpe3, "singleParam", MethodType(List("arg1"))(_ => List(TypeRepr.of[Int]), _ => TypeRepr.of[String]))
val tpe5 = Refinement(tpe4, "curried", MethodType(List("arg1"))(_ => List(TypeRepr.of[Int]), _ => MethodType(List("arg2"))(_ => List(TypeRepr.of[Boolean]), _ => TypeRepr.of[String])))
tpe5.asType match
case '[Sel.Subtype[t]] => '{ (new Sel {}).asInstanceOf[t] }
@main def run() =
val sel = Sel.makeSel
println(sel.field)
println(sel.parameterless)
println(sel.emptyParamList())
println(sel.singleParam(1))
println(sel.curried(1)(true))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment