|
| 1 | +package i11401 |
| 2 | + |
| 3 | +import scala.quoted._ |
| 4 | + |
| 5 | +import scala.concurrent.Future |
| 6 | + |
| 7 | +def await[T](x:Future[T]):T = ??? |
| 8 | + |
| 9 | +class CIFReader[A](a:A) |
| 10 | + |
| 11 | + |
| 12 | +class SLSelect[S]: |
| 13 | + |
| 14 | + def onRead[A](ch: CIFReader[A])(f: A=> S): this.type = |
| 15 | + ??? |
| 16 | + |
| 17 | + def fold[S](s0:S)(step: (S,SLSelect[S])=> S): S = { |
| 18 | + ??? |
| 19 | + } |
| 20 | + |
| 21 | + def fold_async[S](s0:S)(step: (S,SLSelect[S])=> Future[S]): Future[S] = { |
| 22 | + ??? |
| 23 | + } |
| 24 | + |
| 25 | + inline def apply1[A](inline ch: CIFReader[A], f: A=>S): S = |
| 26 | + val s0 = new SLSelect[S] |
| 27 | + await(s0.onRead(ch)(f).runAsync()) |
| 28 | + |
| 29 | + def runAsync(): Future[S] = ??? |
| 30 | + |
| 31 | + |
| 32 | + |
| 33 | +object X: |
| 34 | + |
| 35 | + inline def process[T](inline f:T) = ${ |
| 36 | + processImpl[T]('f) |
| 37 | + } |
| 38 | + |
| 39 | + def processImpl[T:Type](t:Expr[T])(using Quotes):Expr[Future[T]] = |
| 40 | + import quotes.reflect._ |
| 41 | + val r = processTree[T](t.asTerm) |
| 42 | + r.asExprOf[Future[T]] |
| 43 | + |
| 44 | + |
| 45 | + def processTree[T:Type](using Quotes)(t: quotes.reflect.Term):quotes.reflect.Term = |
| 46 | + import quotes.reflect._ |
| 47 | + val r: Term = t match |
| 48 | + case Inlined(_,List(),body) => processTree(body) |
| 49 | + case Inlined(d,bindings,body) => |
| 50 | + Inlined(d,bindings,processTree[T](body)) |
| 51 | + case Block(stats,expr) => Block(stats,processTree(expr)) |
| 52 | + case Apply(Apply(TypeApply(Select(x,"fold"),targs),List(state)),List(fun)) => |
| 53 | + val nFun = processLambda[T](fun) |
| 54 | + Apply(Apply(TypeApply(Select.unique(x,"fold_async"),targs),List(state)),List(nFun)) |
| 55 | + case Apply(TypeApply(Ident("await"),targs),List(body)) => body |
| 56 | + case Typed(x,tp) => Typed(processTree(x), Inferred(TypeRepr.of[Future].appliedTo(tp.tpe)) ) |
| 57 | + case _ => throw new RuntimeException(s"tree not recoginized: $t") |
| 58 | + val checker = new TreeMap() {} |
| 59 | + checker.transformTerm(r)(Symbol.spliceOwner) |
| 60 | + r |
| 61 | + |
| 62 | + def processLambda[T:Type](using Quotes)(fun: quotes.reflect.Term):quotes.reflect.Term = |
| 63 | + import quotes.reflect._ |
| 64 | + |
| 65 | + def changeArgs(oldArgs:List[Tree], newArgs:List[Tree], body:Term, owner: Symbol):Term = |
| 66 | + val association: Map[Symbol, Term] = (oldArgs zip newArgs).foldLeft(Map.empty){ |
| 67 | + case (m, (oldParam, newParam: Term)) => m.updated(oldParam.symbol, newParam) |
| 68 | + case (m, (oldParam, newParam: Tree)) => throw RuntimeException("Term expected") |
| 69 | + } |
| 70 | + val changes = new TreeMap() { |
| 71 | + override def transformTerm(tree:Term)(owner: Symbol): Term = |
| 72 | + tree match |
| 73 | + case ident@Ident(name) => association.getOrElse(ident.symbol, super.transformTerm(tree)(owner)) |
| 74 | + case _ => super.transformTerm(tree)(owner) |
| 75 | + } |
| 76 | + changes.transformTerm(body)(owner) |
| 77 | + |
| 78 | + val r = fun match |
| 79 | + case Lambda(params, body) => |
| 80 | + val nBody = processTree[T](body) |
| 81 | + val paramTypes = params.map(_.tpt.tpe) |
| 82 | + val paramNames = params.map(_.name) |
| 83 | + val mt = MethodType(paramNames)(_ => paramTypes, _ => TypeRepr.of[Future].appliedTo(body.tpe.widen) ) |
| 84 | + val r = Lambda(Symbol.spliceOwner, mt, (owner,args) => changeArgs(params,args,nBody,owner).changeOwner(owner) ) |
| 85 | + r |
| 86 | + case Block(List(),expr) => processLambda(expr) |
| 87 | + case _ => |
| 88 | + throw new RuntimeException(s"Lambda expected") |
| 89 | + r |
0 commit comments