|
| 1 | +import scala.quoted._ |
| 2 | + |
| 3 | +object Macro { |
| 4 | + |
| 5 | + case class Record(elems: (String, Any)*) extends Selectable { |
| 6 | + def selectDynamic(name: String): Any = elems.find(_._1 == name).get._2 |
| 7 | + } |
| 8 | + |
| 9 | + inline def toHMap(s: Selectable) <: Tuple = ${ toHMapImpl('s)} |
| 10 | + |
| 11 | + def toHMapImpl(s: Expr[Selectable])(given qctx:QuoteContext): Expr[Tuple] = { |
| 12 | + import qctx.tasty.{given, _} |
| 13 | + |
| 14 | + val repr = s.unseal.tpe.widenTermRefExpr.dealias |
| 15 | + |
| 16 | + def rec(tpe: Type): List[(String, Type)] = { |
| 17 | + tpe match { |
| 18 | + case Refinement(parent, name, info: Type) => (name, info) :: rec(parent) |
| 19 | + case _ => Nil |
| 20 | + } |
| 21 | + } |
| 22 | + |
| 23 | + def tupleElem(name: String, info: Type): Expr[Any] = { |
| 24 | + val nameExpr = Expr(name) |
| 25 | + info.seal match { |
| 26 | + case '[$qType] => |
| 27 | + Expr.ofTuple(Seq(nameExpr, '{$s.selectDynamic($nameExpr).asInstanceOf[$qType]})) |
| 28 | + } |
| 29 | + } |
| 30 | + |
| 31 | + // val list = println(rec(repr)) |
| 32 | + |
| 33 | + val ret = rec(repr).reverse.map(e => tupleElem(e._1, e._2)) |
| 34 | + |
| 35 | + Expr.ofTuple(ret) |
| 36 | + } |
| 37 | + |
| 38 | + inline def toSelectable[T](s: Tuple)<: T = ${ toSelectableImpl('s, '[T])} |
| 39 | + |
| 40 | + def toSelectableImpl[T](s: Expr[Tuple], tpe: Type[T])(given qctx:QuoteContext): Expr[T] = { |
| 41 | + import qctx.tasty.{given, _} |
| 42 | + |
| 43 | + val repr = s.unseal.tpe.widenTermRefExpr.dealias |
| 44 | + |
| 45 | + println(repr.show) |
| 46 | + println(repr.showExtractors) |
| 47 | + |
| 48 | + // new Record((res2._1._1, res2._1._2), (res2._2._1, res2._2._2)).asInstanceOf[Record {val name: String; val age: Int} ] |
| 49 | + |
| 50 | + def rec(tpe: Type): List[(String, Type)] = { |
| 51 | + tpe match { |
| 52 | + // todo: check number based on prefix |
| 53 | + case AppliedType(_, args) => args.map{ |
| 54 | + case AppliedType(_, ConstantType(Constant(name: String)) :: (info: Type) :: Nil) => (name, info) |
| 55 | + } |
| 56 | + } |
| 57 | + } |
| 58 | + val r = rec(repr) |
| 59 | + println(r) |
| 60 | + |
| 61 | + println(tpe.unseal.symbol) |
| 62 | + println(TypeIdent(tpe.unseal.symbol)) |
| 63 | + |
| 64 | + println('{new Record()}.unseal.showExtractors) |
| 65 | + |
| 66 | + '{ ??? } |
| 67 | + } |
| 68 | +} |
0 commit comments