aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-11-02 11:08:28 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-11-22 01:35:07 +0100
commit8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch)
treea8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused
parent6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff)
downloaddotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.gz
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.bz2
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.zip
Move compiler and compiler tests to compiler dir
Diffstat (limited to 'compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused')
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused535
1 files changed, 535 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused b/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused
new file mode 100644
index 000000000..672c85179
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused
@@ -0,0 +1,535 @@
+package dotty.tools
+package dotc
+package parsing
+
+import core._
+import Flags._, Trees._, TypedTrees._, UntypedTrees._, Names._, StdNames._, NameOps._, Contexts._
+import scala.collection.mutable.ListBuffer
+import util.Positions._, Symbols._, Decorators._, Flags._, Constants._
+import TreeInfo._
+
+/** Methods for building trees, used in the parser. All the trees
+ * returned by this class must be untyped.
+ * Note: currently unused
+ */
+class TreeBuilder(implicit ctx: Context) {
+
+ import untpd._
+
+ def scalaDot(name: Name): Select =
+ Select(new TypedSplice(tpd.Ident(defn.ScalaPackageVal.termRef)), name)
+
+ def scalaAnyRefConstr = scalaDot(tpnme.AnyRef)
+ def scalaAnyValConstr = scalaDot(tpnme.AnyVal)
+ def scalaAnyConstr = scalaDot(tpnme.Any)
+ def scalaUnitConstr = scalaDot(tpnme.Unit)
+ def productConstr = scalaDot(tpnme.Product)
+ def productConstrN(n: Int) = scalaDot(("Product" + n).toTypeName)
+ def serializableConstr = scalaDot(tpnme.Serializable)
+
+ def convertToTypeName(t: Tree): Tree = ???
+
+ private implicit val cpos = NoPosition
+
+ /** Convert all occurrences of (lower-case) variables in a pattern as follows:
+ * x becomes x @ _
+ * x: T becomes x @ (_: T)
+ * Also covert all toplevel lower-case type arguments as follows:
+ * t becomes t @ _
+ */
+ private object patvarTransformer extends TreeTransformer {
+ override def transform(tree: Tree): Tree = tree match {
+ case Ident(name) if isVarPattern(tree) && name != nme.WILDCARD =>
+ Bind(
+ name, Ident(nme.WILDCARD).withPos(tree.pos.focus)
+ ).withPos(tree.pos)
+ case Typed(id @ Ident(name), tpt) if isVarPattern(id) && name != nme.WILDCARD =>
+ Bind(
+ name,
+ Typed(
+ Ident(nme.WILDCARD).withPos(tree.pos.focus),
+ transform(tpt)
+ ).withPos(tree.pos.withStart(tree.pos.point))
+ ).withPos(tree.pos.withPoint(id.pos.point))
+ case Apply(fn @ Apply(_, _), args) =>
+ tree.derivedApply(transform(fn), transform(args))
+ case Apply(fn, args) =>
+ tree.derivedApply(fn, transform(args))
+ case Typed(expr, tpt) =>
+ tree.derivedTyped(transform(expr), transform(tpt))
+ case Bind(name, body) =>
+ tree.derivedBind(name, transform(body))
+ case AppliedTypeTree(tycon, args) =>
+ tree.derivedAppliedTypeTree(tycon, args map transform)
+ case Alternative(_) | Typed(_, _) | AndTypeTree(_, _) | Annotated(_, _) =>
+ super.transform(tree)
+ case Parens(_) =>
+ stripParens(tree)
+ case _ =>
+ tree
+ }
+ }
+
+ case class VariableInfo(name: Name, tree: Tree, pos: Position)
+
+ /** Traverse pattern and collect all variable names with their types in buffer
+ * The variables keep their positions; whereas the pattern is converted to be
+ * synthetic for all nodes that contain a variable position.
+ */
+ object getVars extends TreeAccumulator[ListBuffer[VariableInfo]] {
+
+ def namePos(tree: Tree, name: Name): Position =
+ if (name contains '$') tree.pos.focus
+ else {
+ val start = tree.pos.start
+ val end = start + name.decode.length
+ Position(start, end)
+ }
+
+ override def apply(buf: ListBuffer[VariableInfo], tree: Tree): ListBuffer[VariableInfo] = {
+ def seenName(name: Name) = buf exists (_.name == name)
+ def add(name: Name, t: Tree): ListBuffer[VariableInfo] =
+ if (seenName(name)) buf else buf += VariableInfo(name, t, namePos(tree, name))
+
+ tree match {
+ case Bind(nme.WILDCARD, _) =>
+ foldOver(buf, tree)
+ case Bind(name, Typed(tree1, tpt)) if !mayBeTypePat(tpt) =>
+ apply(add(name, tpt), tree1)
+ case Bind(name, tree1) =>
+ apply(add(name, TypeTree()), tree1)
+ case _ =>
+ foldOver(buf, tree)
+ }
+ }
+ }
+
+ /** Returns list of all pattern variables, possibly with their types,
+ * without duplicates
+ */
+ private def getVariables(tree: Tree): List[VariableInfo] =
+ getVars(new ListBuffer[VariableInfo], tree).toList
+
+ def byNameApplication(tpe: Tree): Tree =
+ AppliedTypeTree(scalaDot(tpnme.BYNAME_PARAM_CLASS), List(tpe))
+ def repeatedApplication(tpe: Tree): Tree =
+ AppliedTypeTree(scalaDot(tpnme.REPEATED_PARAM_CLASS), List(tpe))
+
+ def makeTuple(trees: List[Tree])(implicit cpos: Position): Tree = {
+ def mkPair(t1: Tree, t2: Tree) = {
+ if (t1.isType) AppliedTypeTree(scalaDot(tpnme.Pair), List(t1, t2))
+ else Pair(t1, t2)
+ }
+ trees reduce mkPair
+ }
+
+ def stripParens(t: Tree) = t match {
+ case Parens(t) => t
+ case _ => t
+ }
+
+ def makeSelfDef(name: TermName, tpt: Tree): ValDef =
+ ValDef(Modifiers(Private), name, tpt, EmptyTree())
+
+ /** If tree is a variable pattern, return its variable info.
+ * Otherwise return none.
+ */
+ private def matchVarPattern(tree: Tree): Option[VariableInfo] = {
+ def wildType(t: Tree): Option[Tree] = t match {
+ case Ident(x) if x.toTermName == nme.WILDCARD => Some(TypeTree())
+ case Typed(Ident(x), tpt) if x.toTermName == nme.WILDCARD => Some(tpt)
+ case _ => None
+ }
+ tree match {
+ case Ident(name) => Some(VariableInfo(name, TypeTree(), tree.pos))
+ case Bind(name, body) => wildType(body) map (x => VariableInfo(name, x, tree.pos))
+ case Typed(id @ Ident(name), tpt) => Some(VariableInfo(name, tpt, id.pos))
+ case _ => None
+ }
+ }
+
+ /** Create tree representing (unencoded) binary operation expression or pattern. */
+ def makeBinop(isExpr: Boolean, left: Tree, op: TermName, right: Tree, opPos: Position): Tree = {
+ def mkNamed(args: List[Tree]) =
+ if (isExpr) args map {
+ case arg @ Assign(Ident(name), rhs) => NamedArg(name, rhs).withPos(arg.pos)
+ case arg => arg
+ } else args
+ val arguments = right match {
+ case Parens(arg) => mkNamed(arg :: Nil)
+ case _ => right :: Nil
+ }
+ if (isExpr) {
+ if (isLeftAssoc(op)) {
+ Apply(Select(stripParens(left), op.encode).withPos(opPos), arguments)
+ } else {
+ val x = ctx.freshName().toTermName
+ Block(
+ List(ValDef(Modifiers(Synthetic), x, TypeTree(), stripParens(left))),
+ Apply(Select(stripParens(right), op.encode).withPos(opPos), List(Ident(x).withPos(left.pos))))
+ }
+ } else {
+ Apply(Ident(op.encode).withPos(opPos), stripParens(left) :: arguments)
+ }
+ }
+
+ /** tpt.<init> */
+ def SelectConstructor(tpt: Tree): Tree =
+ Select(tpt, nme.CONSTRUCTOR)
+
+ private def splitArgss(constr: Tree, outerArgss: List[List[Tree]]): (Tree, List[List[Tree]]) = constr match {
+ case Apply(tree, args) => splitArgss(tree, args :: outerArgss)
+ case _ => (constr, if (outerArgss.isEmpty) ListOfNil else outerArgss)
+ }
+
+ /** new tpt(argss_1)...(argss_n)
+ * @param npos the position spanning <new tpt>, without any arguments
+ */
+ def makeNew(parentConstr: Tree) = {
+ val (tpt, argss) = splitArgss(parentConstr, Nil)
+ New(tpt, argss)
+ }
+
+ /** Create positioned tree representing an object creation <new parents { self => stats }
+ */
+ def makeNew(templ: Template): Tree = {
+ val x = tpnme.ANON_CLASS
+ val nu = makeNew(Ident(x))
+ val clsDef = {
+ implicit val cpos = NoPosition
+ ClassDef(Modifiers(Final), x, Nil, templ)
+ }
+ Block(clsDef, nu)
+ }
+
+ /** Create positioned tree representing an object creation <new parents { self => stats }
+ * @param cpos the position of the new, focus should be the first parent's start.
+ */
+ def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree]): Tree = {
+ val newPos = Position(cpos.start, cpos.point)
+ val clsPos = Position(cpos.point, cpos.end)
+ if (parents.isEmpty)
+ makeNew(List(scalaAnyRefConstr.withPos(newPos.endPos)), self, stats)
+ else if (parents.tail.isEmpty && stats.isEmpty)
+ makeNew(parents.head)
+ else {
+ val x = tpnme.ANON_CLASS
+ val nu = makeNew(Ident(x).withPos(newPos)).withPos(newPos)
+ val clsDef = {
+ implicit val cpos = clsPos
+ ClassDef(Modifiers(Final), x, Nil, Template(???, parents, self, stats))
+ }
+ Block(clsDef, nu)
+ }
+ }
+
+ /** Create a tree representing an assignment <lhs = rhs> */
+ def makeAssign(lhs: Tree, rhs: Tree): Tree = lhs match {
+ case Apply(fn, args) =>
+ Apply(Select(fn, nme.update), args :+ rhs)
+ case _ =>
+ Assign(lhs, rhs)
+ }
+
+ /** A type tree corresponding to (possibly unary) intersection type
+ def makeIntersectionTypeTree(tps: List[Tree]): Tree =
+ if (tps.tail.isEmpty) tps.head
+ else CompoundTypeTree(Template(tps, emptyValDef, Nil))*/
+
+ private def labelDefAndCall(lname: TermName, rhs: Tree, call: Tree) = {
+ val ldef = DefDef(Modifiers(Label).withPos(cpos.startPos), lname, Nil, ListOfNil, TypeTree(), rhs)
+ Block(ldef, call)
+ }
+
+ private def labelCall(lname: TermName): Apply =
+ Apply(Ident(lname), Nil)
+
+ /** Create tree representing a while loop */
+ def makeWhile(lname: TermName, cond: Tree, body: Tree): Tree = {
+ val continu = labelCall(lname).withPos((cond.pos union body.pos).endPos)
+ val rhs = {
+ implicit val cpos = NoPosition
+ If(cond, Block(body, continu), Literal(Constant()).withPos(continu.pos))
+ }
+ labelDefAndCall(lname, rhs, continu)
+ }
+
+ /** Create tree representing a do-while loop */
+ def makeDoWhile(lname: TermName, body: Tree, cond: Tree): Tree = {
+ val continu = labelCall(lname).withPos((cond.pos union body.pos).endPos)
+ val rhs = Block(body, If(cond, continu, Literal(Constant()).withPos(continu.pos)))
+ labelDefAndCall(lname, rhs, continu)
+ }
+
+ /** Create block of statements `stats` */
+ def makeBlock(stats: List[Tree]): Tree =
+ if (stats.isEmpty) Literal(Constant())
+ else if (!stats.last.isTerm) Block(stats, Literal(Constant()).withPos(cpos.endPos))
+ else if (stats.length == 1) stats.head
+ else Block(stats.init, stats.last)
+
+ def makePatFilter(tree: Tree, condition: Tree, canDrop: Boolean): Tree = {
+ val cases = List(
+ CaseDef(condition, EmptyTree(), Literal(Constant(true))),
+ CaseDef(Ident(nme.WILDCARD), EmptyTree(), Literal(Constant(false)))
+ )
+ val matchTree = makeVisitor(cases, checkExhaustive = false, canDrop)
+ locally {
+ implicit val cpos = tree.pos
+ Apply(Select(tree, nme.withFilter), matchTree :: Nil)
+ }
+ }
+
+ /** Create tree for for-comprehension generator <pat <- rhs> or <pat = rhs> */
+ def makeGenerator(pat: Tree, valeq: Boolean, rhs: Tree): Enumerator = {
+ val pat1 = patvarTransformer.transform(pat)
+ if (valeq) ValEq(pat1, rhs)
+ else ValFrom(pat1, makePatFilter(rhs, pat1, canDrop = true))
+ }
+
+/*
+ def makeSyntheticTypeParam(pname: TypeName, bounds: Tree) =
+ TypeDef(Modifiers(DEFERRED | SYNTHETIC), pname, Nil, bounds)
+*/
+ abstract class Enumerator { def pos: Position }
+ case class ValFrom(pat: Tree, rhs: Tree) extends Enumerator {
+ val pos = cpos union pat.pos union rhs.pos
+ }
+ case class ValEq(pat: Tree, rhs: Tree) extends Enumerator {
+ val pos = cpos union pat.pos union rhs.pos
+ }
+ case class Filter(test: Tree) extends Enumerator {
+ val pos = cpos union test.pos
+ }
+
+ /** Create tree for for-comprehension <for (enums) do body> or
+ * <for (enums) yield body> where mapName and flatMapName are chosen
+ * corresponding to whether this is a for-do or a for-yield.
+ * The creation performs the following rewrite rules:
+ *
+ * 1.
+ *
+ * for (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 variable pattern and as the partial function { case P => E } otherwise.
+ *
+ * 2.
+ *
+ * for (P <- G) yield E ==> G.map (P => E)
+ *
+ * 3.
+ *
+ * for (P_1 <- G_1; P_2 <- G_2; ...) ...
+ * ==>
+ * G_1.flatMap (P_1 => for (P_2 <- G_2; ...) ...)
+ *
+ * 4.
+ *
+ * for (P <- G; E; ...) ...
+ * =>
+ * for (P <- G.filter (P => E); ...) ...
+ *
+ * 5. For any N:
+ *
+ * for (P_1 <- G; P_2 = E_2; val P_N = E_N; ...)
+ * ==>
+ * for (TupleN(P_1, P_2, ... P_N) <-
+ * for (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
+ *
+ * @param mapName The name to be used for maps (either map or foreach)
+ * @param flatMapName The name to be used for flatMaps (either flatMap or foreach)
+ * @param enums The enumerators in the for expression
+ * @param body The body of the for expression
+ */
+ private def makeFor(mapName: TermName, flatMapName: TermName, enums: List[Enumerator], body: Tree): Tree = {
+
+ /** make a closure pat => body.
+ * The closure is assigned a transparent position with the point at pos.point and
+ * the limits given by pat and body.
+ */
+ def makeClosure(pat: Tree, body: Tree): Tree =
+ matchVarPattern(pat) match {
+ case Some(VariableInfo(name, tpt, pos)) =>
+ Function(ValDef(Modifiers(Param).withPos(cpos.startPos), name.toTermName, tpt, EmptyTree()).withPos(pos) :: Nil, body)
+ case None =>
+ makeVisitor(List(CaseDef(pat, EmptyTree(), body)), checkExhaustive = false)
+ }
+
+ /** Make an application qual.meth(pat => body) positioned at `pos`.
+ */
+ def makeCombination(meth: TermName, qual: Tree, pat: Tree, body: Tree): Tree =
+ Apply(Select(qual, meth).withPos(NoPosition), makeClosure(pat, body))
+
+ /** Optionally, if pattern is a `Bind`, the bound name, otherwise None.
+ */
+ def patternVar(pat: Tree): Option[Name] = pat match {
+ case Bind(name, _) => Some(name)
+ case _ => None
+ }
+
+ /** If `pat` is not yet a `Bind` wrap it in one with a fresh name
+ */
+ def makeBind(pat: Tree): Tree = pat match {
+ case Bind(_, _) => pat
+ case _ => Bind(ctx.freshName().toTermName, pat)
+ }
+
+ /** A reference to the name bound in Bind `pat`.
+ */
+ def makeValue(pat: Tree): Tree = pat match {
+ case Bind(name, _) => Ident(name).withPos(pat.pos.focus)
+ }
+
+ enums match {
+ case (enum @ ValFrom(pat, rhs)) :: Nil =>
+ makeCombination(mapName, rhs, pat, body).withPos(enum.pos)
+ case ValFrom(pat, rhs) :: (rest @ (ValFrom( _, _) :: _)) =>
+ makeCombination(flatMapName, rhs, pat,
+ makeFor(mapName, flatMapName, rest, body))
+ case (enum @ ValFrom(pat, rhs)) :: Filter(test) :: rest =>
+ makeFor(mapName, flatMapName,
+ ValFrom(pat, makeCombination(nme.withFilter, rhs, pat, test)) :: rest,
+ body)
+ case (enum @ ValFrom(pat, rhs)) :: rest =>
+ val (valeqs, rest1) = rest.span(_.isInstanceOf[ValEq])
+ assert(!valeqs.isEmpty)
+ val pats = valeqs map { case ValEq(pat, _) => pat }
+ val rhss = valeqs map { case ValEq(_, rhs) => rhs }
+ val defpat1 = makeBind(pat)
+ val defpats = pats map makeBind
+ val pdefs = (defpats, rhss).zipped flatMap (makePatDef)
+ val ids = (defpat1 :: defpats) map makeValue
+ val rhs1 = makeForYield(ValFrom(defpat1, rhs) :: Nil, Block(pdefs, makeTuple(ids)))
+ val allpats = pat :: pats
+ val vfrom1 = ValFrom(makeTuple(allpats), rhs1)
+ makeFor(mapName, flatMapName, vfrom1 :: 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 pattern alternative */
+ def makeAlternative(ts: List[Tree]): Tree = Alternative(ts flatMap alternatives)
+
+ def alternatives(t: Tree): List[Tree] = t match {
+ case Alternative(ts) => ts
+ case _ => List(t)
+ }
+
+ def mkAnnotated(cls: Symbol, tree: Tree) =
+ Annotated(TypedSplice(tpd.New(cls.typeRef)), tree)
+
+ /** Create visitor <x => x match cases> */
+ def makeVisitor(cases: List[CaseDef], checkExhaustive: Boolean, canDrop: Boolean = false): Tree = {
+ val x = ctx.freshName().toTermName
+ val id = Ident(x)
+ val sel =
+ if (canDrop) mkAnnotated(???, id)
+ else if (!checkExhaustive) mkAnnotated(defn.UncheckedAnnot, id)
+ else id
+ Function(List(ugen.syntheticParameter(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(), pat, rhs)
+
+ /** Create tree for pattern definition <mods val pat0 = rhs> */
+ def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree, varsArePatterns: Boolean = false): List[Tree] = matchVarPattern(pat) match {
+ case Some(VariableInfo(name, tpt, pos)) if varsArePatterns =>
+ ValDef(mods, name.toTermName, tpt, rhs).withPos(pos) :: Nil // point comes from pat.pos
+
+ case _ =>
+ // 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 rhsUnchecked = mkAnnotated(defn.UncheckedAnnot, rhs)
+
+ // TODO: clean this up -- there is too much information packed into makePatDef's `pat` argument
+ // when it's a simple identifier (case Some((name, tpt)) -- above),
+ // pat should have the type ascription that was specified by the user
+ // however, in `case None` (here), we must be careful not to generate illegal pattern trees (such as `(a, b): Tuple2[Int, String]`)
+ // i.e., this must hold: pat1 match { case Typed(expr, tp) => assert(expr.isInstanceOf[Ident]) case _ => }
+ // if we encounter such an erroneous pattern, we strip off the type ascription from pat and propagate the type information to rhs
+ val (pat1, rhs1) = patvarTransformer.transform(pat) match {
+ // move the Typed ascription to the rhs
+ case Typed(expr, tpt) if !expr.isInstanceOf[Ident] =>
+ val rhsTypedUnchecked =
+ if (tpt.isEmpty) rhsUnchecked else Typed(rhsUnchecked, tpt)
+ (expr, rhsTypedUnchecked)
+ case ok =>
+ (ok, rhsUnchecked)
+ }
+ val vars = getVariables(pat1)
+ val ids = vars map (v => Ident(v.name).withPos(v.pos))
+ val caseDef = CaseDef(pat1, EmptyTree(), makeTuple(ids))
+ val matchExpr = Match(rhs1, caseDef :: Nil)
+ vars match {
+ case List(VariableInfo(vname, tpt, pos)) =>
+ ValDef(mods, vname.toTermName, tpt, matchExpr) :: Nil
+ case _ =>
+ val tmpName = ctx.freshName().toTermName
+ val patMods = Modifiers(PrivateLocal | Synthetic | (mods.flags & Lazy))
+ val firstDef = ValDef(patMods, tmpName, TypeTree(), matchExpr)
+ val restDefs = for {
+ (VariableInfo(vname, tpt, pos), n) <- vars.zipWithIndex
+ } yield {
+ val rhs = {
+ implicit val cpos = pos.focus
+ Select(Ident(tmpName), ("_" + n).toTermName)
+ }
+ ValDef(mods, vname.toTermName, tpt, rhs).withPos(pos)
+ }
+ firstDef :: restDefs
+ }
+ }
+
+ /** Create a tree representing the function type (argtpes) => restpe */
+ def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree =
+ AppliedTypeTree(scalaDot(("Function" + argtpes.length).toTypeName), argtpes ::: List(restpe))
+
+ /** Append implicit parameter section if `contextBounds` nonempty */
+ def addEvidenceParams(owner: Name, vparamss: List[List[ValDef]], contextBounds: List[Tree]): List[List[ValDef]] = {
+ if (contextBounds.isEmpty) vparamss
+ else {
+ val mods = Modifiers(if (owner.isTypeName) PrivateLocal | ParamAccessor else Param)
+ val evidenceParams = for (tpt <- contextBounds) yield {
+ val pname = ctx.freshName(nme.EVIDENCE_PARAM_PREFIX).toTermName
+ ValDef(mods | Implicit | Synthetic, pname, tpt, EmptyTree())
+ }
+ vparamss.reverse match {
+ case (vparams @ (vparam :: _)) :: _ if vparam.mods is Implicit =>
+ vparamss.init :+ (evidenceParams ++ vparams)
+ case _ =>
+ vparamss :+ evidenceParams
+ }
+ }
+ }
+}