treebuilder.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 458 行 · 第 1/2 页
SCALA
458 行
* for (val P <- G) E ==> G.foreach (P => E) * * Here and in the following (P => E) is interpreted as the function (P => E) * if P is a a variable pattern and as the partial function { case P => E } otherwise. * * 2. * * for (val P <- G) yield E ==> G.map (P => E) * * 3. * * for (val P_1 <- G_1; val P_2 <- G_2; ...) ... * ==> * G_1.flatMap (P_1 => for (val P_2 <- G_2; ...) ...) * * 4. * * for (val P <- G; E; ...) ... * => * for (val P <- G.filter (P => E); ...) ... * * 5. For N < MaxTupleArity: * * for (val P_1 <- G; val P_2 = E_2; val P_N = E_N; ...) * ==> * for (val TupleN(P_1, P_2, ... P_N) <- * for (val x_1 @ P_1 <- G) yield { * val x_2 @ P_2 = E_2 * ... * val x_N & P_N = E_N * TupleN(x_1, ..., x_N) * } ...) * * If any of the P_i are variable patterns, the corresponding `x_i @ P_i' is not generated * and the variable constituting P_i is used instead of x_i * */ private def makeFor(mapName: Name, flatMapName: Name, enums: List[Enumerator], body: Tree): Tree = { def makeClosure(pat: Tree, body: Tree): Tree = matchVarPattern(pat) match { case Some((name, tpt)) => Function(List(ValDef(Modifiers(PARAM), name, tpt, EmptyTree)), body) case None => makeVisitor(List(CaseDef(pat, EmptyTree, body)), false) } def makeCombination(meth: Name, qual: Tree, pat: Tree, body: Tree): Tree = Apply(Select(qual, meth), List(makeClosure(pat, body))); def patternVar(pat: Tree): Option[Name] = pat match { case Bind(name, _) => Some(name) case _ => None } def makeBind(pat: Tree): Tree = pat match { case Bind(_, _) => pat case _ => Bind(freshName(pat.pos), pat) } def makeValue(pat: Tree): Tree = pat match { case Bind(name, _) => Ident(name) } enums match { case ValFrom(pos, pat, rhs) :: Nil => atPos(pos) { makeCombination(mapName, rhs, pat, body) } case ValFrom(pos, pat, rhs) :: (rest @ (ValFrom(_, _, _) :: _)) => atPos(pos) { makeCombination(flatMapName, rhs, pat, makeFor(mapName, flatMapName, rest, body)) } case ValFrom(pos, pat, rhs) :: Filter(test) :: rest => makeFor(mapName, flatMapName, ValFrom(pos, pat, makeCombination(nme.filter, rhs, pat.duplicate, test)) :: rest, body) case ValFrom(pos, pat, rhs) :: rest => val valeqs = rest.take(definitions.MaxTupleArity - 1).takeWhile(_.isInstanceOf[ValEq]); assert(!valeqs.isEmpty) val rest1 = rest.drop(valeqs.length) val pats = valeqs map { case ValEq(_, pat, _) => pat } val rhss = valeqs map { case ValEq(_, _, rhs) => rhs } val defpats = pats map (x => makeBind(x.duplicate)) val pdefs = List.flatten(List.map2(defpats, rhss)(makePatDef)) val patX1 = makeBind(pat.duplicate); val ids = (patX1 :: defpats) map makeValue val rhs1 = makeForYield( List(ValFrom(pos, patX1, rhs)), Block(pdefs, makeTupleTerm(ids, true))) makeFor(mapName, flatMapName, ValFrom(pos, makeTuple(pat :: pats, false), rhs1) :: rest1, body) case _ => EmptyTree //may happen for erroneous input } } /** Create tree for for-do comprehension <for (enums) body> */ def makeFor(enums: List[Enumerator], body: Tree): Tree = makeFor(nme.foreach, nme.foreach, enums, body) /** Create tree for for-yield comprehension <for (enums) yield body> */ def makeForYield(enums: List[Enumerator], body: Tree): Tree = makeFor(nme.map, nme.flatMap, enums, body) /** Create tree for a lifted expression XX-LIFTING */ def makeLifted(gs: List[ValFrom], body: Tree): Tree = { def combine(gs: List[ValFrom]): ValFrom = (gs: @unchecked) match { case g :: Nil => g case ValFrom(pos1, pat1, rhs1) :: gs2 => val ValFrom(pos2, pat2, rhs2) = combine(gs2) ValFrom(pos1, makeTuple(List(pat1, pat2), false), Apply(Select(rhs1, nme.zip), List(rhs2))) } makeForYield(List(combine(gs)), body) } /** Create tree for a pattern alternative */ def makeAlternative(ts: List[Tree]): Tree = { def alternatives(t: Tree): List[Tree] = t match { case Alternative(ts) => ts case _ => List(t) } Alternative(for (val t <- ts; val a <- alternatives(t)) yield a) } /** Create tree for a pattern sequence */ def makeSequence(ts: List[Tree]): Tree = { def elements(t: Tree): List[Tree] = t match { case Sequence(ts) => ts case _ => List(t) } Sequence(for (val t <- ts; val e <- elements(t)) yield e) } /** Create tree for the p+ regex pattern, becomes p p* */ def makePlus(p: Tree): Tree = makeSequence(List(p, Star(p.duplicate))) /** Create tree for the p? regex pattern, becomes (p| ) */ def makeOpt(p: Tree): Tree = makeAlternative(List(p, Sequence(List()))) /** Create visitor <x => x match cases> */ def makeVisitor(cases: List[CaseDef], checkExhaustive: Boolean): Tree = makeVisitor(cases, checkExhaustive, "x$") private def makeUnchecked(expr: Tree): Tree = Annotated(Annotation(New(scalaDot(definitions.UncheckedClass.name), List(List())), List()), expr) /** Create visitor <x => x match cases> */ def makeVisitor(cases: List[CaseDef], checkExhaustive: Boolean, prefix: String): Tree = { val x = freshName(posAssigner.pos, prefix) val sel = if (checkExhaustive) Ident(x) else makeUnchecked(Ident(x)) Function(List(makeSyntheticParam(x)), Match(sel, cases)) } /** Create tree for case definition <case pat if guard => rhs> */ def makeCaseDef(pat: Tree, guard: Tree, rhs: Tree): CaseDef = CaseDef(patvarTransformer.transform(pat), guard, rhs) /** Create tree for pattern definition <val pat0 = rhs> */ def makePatDef(pat: Tree, rhs: Tree): List[Tree] = makePatDef(Modifiers(0), pat, rhs) /** Create tree for pattern definition <mods val pat0 = rhs> */ def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree): List[Tree] = matchVarPattern(pat) match { case Some((name, tpt)) => List(ValDef(mods, name, tpt, rhs).setPos(pat.pos)) case None => // in case there is exactly one variable x_1 in pattern // val/var p = e ==> val/var x_1 = e.match (case p => (x_1)) // // in case there are zero or more than one variables in pattern // val/var p = e ==> private synthetic val t$ = e.match (case p => (x_1, ..., x_N)) // val/var x_1 = t$._1 // ... // val/var x_N = t$._N val pat1 = patvarTransformer.transform(pat) val vars = getVariables(pat1) val matchExpr = atPos(pat1.pos){ Match( makeUnchecked(rhs), List(CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map Ident, true)))) } vars match { case List((vname, tpt, pos)) => List(ValDef(mods, vname, tpt, matchExpr).setPos(pos)) case _ => val tmp = freshName(pat1.pos) val firstDef = ValDef(Modifiers(PRIVATE | LOCAL | SYNTHETIC | (mods.flags & LAZY)), tmp, TypeTree(), matchExpr) var cnt = 0 val restDefs = for (val (vname, tpt, pos) <- vars) yield atPos(pos) { cnt = cnt + 1 ValDef(mods, vname, tpt, Select(Ident(tmp), newTermName("_" + cnt))) } firstDef :: restDefs } } /** Create a tree representing the function type (argtpes) => restpe */ def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree = AppliedTypeTree(scalaDot(newTypeName("Function" + argtpes.length)), argtpes ::: List(restpe)) /** Create a tree representing a the name function type (=> argtpe) => restpe */ /* def makeByNameFunctionTypeTree(argtpe: Tree, restpe: Tree): Tree = AppliedTypeTree(scalaDot(newTypeName("ByNameFunction")), List(argtpe, restpe)) */ /** Append implicit view section if for `implicitViews' if nonempty */ def addImplicitViews(owner: Name, vparamss: List[List[ValDef]], implicitViews: List[Tree]): List[List[ValDef]] = { val mods = Modifiers(if (owner.isTypeName) PARAMACCESSOR | LOCAL | PRIVATE else PARAM) def makeViewParam(tpt: Tree) = ValDef(mods | IMPLICIT, freshName(tpt.pos, "view$"), tpt, EmptyTree) if (implicitViews.isEmpty) vparamss else vparamss ::: List(implicitViews map makeViewParam) } /** Create a tree representing a packaging */ def makePackaging(pkg: Tree, stats: List[Tree]): PackageDef = pkg match { case Ident(name) => PackageDef(name, stats).setPos(pkg.pos) case Select(qual, name) => makePackaging(qual, List(PackageDef(name, stats).setPos(pkg.pos))) } case class Parens(args: List[Tree]) extends Tree}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?