uncurry.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 600 行 · 第 1/2 页
SCALA
600 行
cases) } case _ => tree } val members = if (fun.tpe.typeSymbol == PartialFunctionClass) { val isDefinedAtMethod = anonClass.newMethod(fun.pos, nme.isDefinedAt) .setFlag(FINAL).setInfo(MethodType(formals, BooleanClass.tpe)) anonClass.info.decls enter isDefinedAtMethod def idbody(idparam: Symbol) = fun.body match { case Match(_, cases) => val substParam = new TreeSymSubstituter(List(fun.vparams.head.symbol), List(idparam)); def transformCase(cdef: CaseDef): CaseDef = substParam( resetAttrs( CaseDef(cdef.pat.duplicate, cdef.guard.duplicate, Literal(true)))) if (cases exists treeInfo.isDefaultCase) Literal(true) else Match( Ident(idparam), (cases map transformCase) ::: List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false)))) } List(applyMethodDef(mkUnchecked(fun.body)), DefDef(isDefinedAtMethod, vparamss => mkUnchecked(idbody(vparamss.head.head)))) } else { List(applyMethodDef(fun.body)) } localTyper.typed { atPos(fun.pos) { Block( List(ClassDef(anonClass, NoMods, List(List()), List(List()), members)), Typed( New(TypeTree(anonClass.tpe), List(List())), TypeTree(fun.tpe))) } } } } def transformArgs(pos: Position, args: List[Tree], formals: List[Type]) = { if (formals.isEmpty) { assert(args.isEmpty); List() } else { val args1 = formals.last match { case TypeRef(pre, sym, List(elempt)) if (sym == RepeatedParamClass) => def mkArrayValue(ts: List[Tree]) = atPos(pos)(ArrayValue(TypeTree(elempt), ts) setType formals.last); if (args.isEmpty) List(mkArrayValue(args)) else { val suffix: Tree = args.last match { case Typed(arg, Ident(name)) if name == nme.WILDCARD_STAR.toTypeName => arg /*setType seqType(arg.tpe)*/ case _ => mkArrayValue(args.drop(formals.length - 1)) } args.take(formals.length - 1) ::: List(suffix) } case _ => args } List.map2(formals, args1) { (formal, arg) => if (formal.typeSymbol != ByNameParamClass) { arg } else if (isByNameRef(arg)) { byNameArgs.addEntry(arg) arg setType functionType(List(), arg.tpe) } else { val fun = localTyper.typed( Function(List(), arg) setPos arg.pos).asInstanceOf[Function]; new ChangeOwnerTraverser(currentOwner, fun.symbol).traverse(arg); transformFunction(fun) } } } }// ------ The tree transformers -------------------------------------------------------- def mainTransform(tree: Tree): Tree = { def withNeedLift(needLift: Boolean)(f: => Tree): Tree = { val savedNeedTryLift = needTryLift needTryLift = needLift val t = f needTryLift = savedNeedTryLift t } /** A try or synchronized needs to be lifted anyway for MSIL if it contains * return statements. These are disallowed in the CLR. By lifting * such returns will be converted to throws. */ def shouldBeLiftedAnyway(tree: Tree) = forMSIL && lookForReturns.found(tree) /** Transform tree `t' to { def f = t; f } where `f' is a fresh name */ def liftTree(tree: Tree) = { if (settings.debug.value) log("lifting tree at: " + (tree.pos)) val sym = currentOwner.newMethod(tree.pos, unit.fresh.newName("liftedTree")) sym.setInfo(MethodType(List(), tree.tpe)) new ChangeOwnerTraverser(currentOwner, sym).traverse(tree) localTyper.typed { atPos(tree.pos) { Block(List(DefDef(sym, List(List()), tree)), Apply(Ident(sym), Nil)) } } } def withInConstructorFlag(inConstructorFlag: Long)(f: => Tree): Tree = { val savedInConstructorFlag = this.inConstructorFlag this.inConstructorFlag = inConstructorFlag val t = f this.inConstructorFlag = savedInConstructorFlag t } tree match { case DefDef(mods, name, tparams, vparamss, tpt, rhs) => withNeedLift(false) { if (tree.symbol.isClassConstructor) { atOwner(tree.symbol) { val rhs1 = (rhs: @unchecked) match { case Block(stat :: stats, expr) => copy.Block( rhs, withInConstructorFlag(INCONSTRUCTOR) { transform(stat) } :: transformTrees(stats), transform(expr)); } copy.DefDef( tree, mods, name, transformTypeDefs(tparams), transformValDefss(vparamss), transform(tpt), rhs1) } } else { super.transform(tree) } } case ValDef(_, _, _, rhs) if (!tree.symbol.owner.isSourceMethod) => withNeedLift(true) { super.transform(tree) }/* case Apply(Select(Block(List(), Function(vparams, body)), nme.apply), args) => // perform beta-reduction; this helps keep view applications small println("beta-reduce1: "+tree) withNeedLift(true) { mainTransform(new TreeSubstituter(vparams map (_.symbol), args).transform(body)) } case Apply(Select(Function(vparams, body), nme.apply), args) =>// if (List.forall2(vparams, args)((vparam, arg) => treeInfo.isAffineIn(body) || // treeInfo.isPureExpr(arg))) => // perform beta-reduction; this helps keep view applications small println("beta-reduce2: "+tree) withNeedLift(true) { mainTransform(new TreeSubstituter(vparams map (_.symbol), args).transform(body)) }*/ case UnApply(fn, args) => inPattern = false val fn1 = transform(fn) inPattern = true val args1 = transformTrees( if (fn.symbol.name == nme.unapply) args else if (fn.symbol.name == nme.unapplySeq) transformArgs(tree.pos, args, analyzer.unapplyTypeListFromReturnTypeSeq(fn.tpe)) else { assert(false,"internal error: UnApply node has wrong symbol"); null }) copy.UnApply(tree, fn1, args1) case Apply(fn, args) => if (settings.noassertions.value && (fn.symbol ne null) && (fn.symbol.name == nme.assert_ || fn.symbol.name == nme.assume_) && fn.symbol.owner == PredefModule.moduleClass) { Literal(()).setPos(tree.pos).setType(UnitClass.tpe) } else if (fn.symbol == Object_synchronized && shouldBeLiftedAnyway(args.head)) { transform(copy.Apply(tree, fn, List(liftTree(args.head)))) } else { withNeedLift(true) { val formals = fn.tpe.paramTypes; copy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, args, formals))) } } case Assign(Select(_, _), _) => withNeedLift(true) { super.transform(tree) } case Assign(lhs, _) if lhs.symbol.owner != currentMethod => withNeedLift(true) { super.transform(tree) } case Try(block, catches, finalizer) => if (needTryLift || shouldBeLiftedAnyway(tree)) transform(liftTree(tree)) else super.transform(tree) case CaseDef(pat, guard, body) => inPattern = true val pat1 = transform(pat) inPattern = false copy.CaseDef(tree, pat1, transform(guard), transform(body)) case fun @ Function(_, _) => mainTransform(transformFunction(fun)) case Template(_, _, _) => withInConstructorFlag(0) { super.transform(tree) } case _ => val tree1 = super.transform(tree) if (isByNameRef(tree1)) { val tree2 = tree1 setType functionType(List(), tree1.tpe) return { if (noApply contains tree2) tree2 else localTyper.typed { atPos(tree1.pos) { Apply(Select(tree2, nme.apply), List()) } } } } tree1 } } setType uncurryTreeType(tree.tpe) def postTransform(tree: Tree): Tree = atPhase(phase.next) { def applyUnary(tree: Tree): Tree = if (tree.symbol.isMethod && (!tree.tpe.isInstanceOf[PolyType] || tree.tpe.typeParams.isEmpty)) { if (!tree.tpe.isInstanceOf[MethodType]) tree.tpe = MethodType(List(), tree.tpe); atPos(tree.pos)(Apply(tree, List()) setType tree.tpe.resultType) } else if (tree.isType) { TypeTree(tree.tpe) setPos tree.pos } else { tree } tree match { case DefDef(mods, name, tparams, vparamss, tpt, rhs) => val rhs1 = nonLocalReturnKeys.get(tree.symbol) match { case None => rhs case Some(k) => atPos(rhs.pos)(nonLocalReturnTry(rhs, k, tree.symbol)) } copy.DefDef(tree, mods, name, tparams, List(List.flatten(vparamss)), tpt, rhs1) case Try(body, catches, finalizer) => if (catches forall treeInfo.isCatchCase) tree else { val exname = unit.fresh.newName("ex$") val cases = if ((catches exists treeInfo.isDefaultCase) || (catches.last match { // bq: handle try { } catch { ... case ex:Throwable => ...} case CaseDef(Typed(Ident(nme.WILDCARD), tpt), EmptyTree, _) if (tpt.tpe =:= ThrowableClass.tpe) => true case CaseDef(Bind(_, Typed(Ident(nme.WILDCARD), tpt)), EmptyTree, _) if (tpt.tpe =:= ThrowableClass.tpe) => true case _ => false })) catches else catches ::: List(CaseDef(Ident(nme.WILDCARD), EmptyTree, Throw(Ident(exname)))); val catchall = atPos(tree.pos) { CaseDef( Bind(exname, Ident(nme.WILDCARD)), EmptyTree, Match(Ident(exname), cases)) } if (settings.debug.value) log("rewrote try: " + catches + " ==> " + catchall); val catches1 = localTyper.typedCases( tree, List(catchall), ThrowableClass.tpe, WildcardType); copy.Try(tree, body, catches1, finalizer) } case Apply(Apply(fn, args), args1) => copy.Apply(tree, fn, args ::: args1) case Ident(name) => assert(name != nme.WILDCARD_STAR.toTypeName) applyUnary(tree); case Select(qual, name) => /* Function1.apply to ByNameFunction.apply if qualifier is a ByNameFunction */ /* if (qual.tpe.typeSymbol == ByNameFunctionClass) { assert(tree.symbol.name == nme.apply && tree.symbol.owner == FunctionClass(1), tree.symbol) tree.symbol = getMember(ByNameFunctionClass, nme.apply) } */ applyUnary(tree) case TypeApply(_, _) => applyUnary(tree) case Return(expr) if (tree.symbol != currentOwner.enclMethod) => if (settings.debug.value) log("non local return in "+tree.symbol+" from "+currentOwner.enclMethod) atPos(tree.pos)(nonLocalReturnThrow(expr, tree.symbol)) case TypeTree() => tree case _ => if (tree.isType) TypeTree(tree.tpe) setPos tree.pos else tree } } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?