From 23fdf0b4e28ca528513a00c2a6675e824face34a Mon Sep 17 00:00:00 2001 From: David MacIver Date: Sun, 9 Nov 2008 18:52:19 +0000 Subject: Separating out a single Binding from a collecti... Separating out a single Binding from a collection of Bindings. --- .../scala/tools/nsc/matching/CodeFactory.scala | 19 ----------- .../tools/nsc/matching/ParallelMatching.scala | 20 +++++------ .../scala/tools/nsc/matching/PatternNodes.scala | 39 +++++++++++----------- 3 files changed, 29 insertions(+), 49 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala index 6e33be24d1..24b4a908c8 100644 --- a/src/compiler/scala/tools/nsc/matching/CodeFactory.scala +++ b/src/compiler/scala/tools/nsc/matching/CodeFactory.scala @@ -37,17 +37,6 @@ trait CodeFactory { val FALSE = Const(false) val NULL = Const(null) - // I am guessing implicits and object creation are prohibitively expensive in the - // compiler to achieve syntax improvement, but if someone wanted to add methods such - // as these to Tree directly, it would enable much more readable code generation. - // Combinators would be even better, but also too expensive (?) - // - // class RichTree(t: Tree) { - // def ===(rhs: Tree) = Equals(t, rhs) - // def GTE(rhs: Tree) = GreaterThanOrEquals(t, rhs) - // } - // implicit def enrichTree(t: Tree) = new RichTree(t) - object Const { def apply(x: Any) = Literal(Constant(x)) def unapply(x: Any) = x match { @@ -69,14 +58,6 @@ trait CodeFactory { final def mkIdent(sym: Symbol) = Ident(sym) setType sym.tpe final def mk_(tpe: Type) = Ident(nme.WILDCARD) setType tpe - /** - * Convert a pattern binding into a list of value definitions. - */ - final def targetParams(subst:Binding)(implicit typer : Typer):List[ValDef] = subst match { - case NoBinding => Nil; - case Binding(v,t,n) => ValDef(v, typer.typed(mkIdent(t)))::targetParams(n) - } - /** returns A for T <: Sequence[ A ] */ final def getElemType_Sequence(tpe: Type): Type = { diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala index 263e1b6ba4..40bc0c6203 100644 --- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala +++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala @@ -122,13 +122,13 @@ trait ParallelMatching { } /** {case ... if guard => bx} else {guardedRest} */ - case class VariableRule(subst:Binding, guard: Tree, guardedRest:Rep, bx: Int)(implicit rep:RepFactory) extends RuleApplication(rep) { + case class VariableRule(subst: Bindings, guard: Tree, guardedRest: Rep, bx: Int)(implicit rep:RepFactory) extends RuleApplication(rep) { def scrutinee: Symbol = impossible final def tree(implicit theOwner: Symbol, failTree: Tree): Tree = { val body = typer.typed { rep.requestBody(bx, subst) } if (guard eq EmptyTree) return body - val vdefs = targetParams(subst) + val vdefs = subst.targetParams val typedElse = repToTree(guardedRest) val typedIf = typer.typed { If(guard.duplicate, body, typedElse) } @@ -192,8 +192,8 @@ trait ParallelMatching { } //lazy - private def bindVars(Tag:Int, orig: Binding): Binding = { - def myBindVars(rest:List[(Int,List[Symbol])], bnd: Binding): Binding = rest match { + private def bindVars(Tag: Int, orig: Bindings): Bindings = { + def myBindVars(rest:List[(Int,List[Symbol])], bnd: Bindings): Bindings = rest match { case Nil => bnd case (Tag,vs)::xs => myBindVars(xs, bnd.add(vs, scrutinee)) case (_, vs)::xs => myBindVars(xs, bnd) @@ -587,10 +587,10 @@ trait ParallelMatching { final def repToTree(r: Rep)(implicit theOwner: Symbol, failTree: Tree, rep: RepFactory): Tree = r.applyRule.tree - case class Row(pat:List[Tree], subst: Binding, guard: Tree, bx: Int) { + case class Row(pat: List[Tree], subst: Bindings, guard: Tree, bx: Int) { def insert(h: Tree) = Row(h :: pat, subst, guard, bx) // prepends supplied tree def insert(hs: List[Tree]) = Row(hs ::: pat, subst, guard, bx) - def insert2(hs: List[Tree], b: Binding) = Row(hs ::: pat, b, guard, bx) // prepends and substitutes + def insert2(hs: List[Tree], b: Bindings) = Row(hs ::: pat, b, guard, bx) // prepends and substitutes def replace(hs: List[Tree]) = Row(hs, subst, guard, bx) // replaces pattern list } @@ -654,7 +654,7 @@ trait ParallelMatching { /** first time bx is requested, a LabelDef is returned. next time, a jump. * the function takes care of binding */ - final def requestBody(bx:Int, subst:Binding)(implicit theOwner: Symbol): Tree = { + final def requestBody(bx: Int, subst: Bindings)(implicit theOwner: Symbol): Tree = { if (bx < 0) { // is shortcut val jlabel = shortCuts(-bx-1) return Apply(mkIdent(jlabel), Nil) @@ -662,7 +662,7 @@ trait ParallelMatching { if (!isReached(bx)) { // first time this bx is requested // might be bound elsewhere ( see `x @ unapply' ) <-- this comment refers to null check val (vsyms, argts, vdefs) : (List[Symbol], List[Type], List[Tree]) = unzip3( - for (v <- vss(bx) ; val substv = subst(v) ; if substv ne null) yield + for (v <- vss(bx) ; substv <- subst(v)) yield (v, v.tpe, typedValDef(v, substv)) ) @@ -680,7 +680,7 @@ trait ParallelMatching { // if some bx is not reached twice, its LabelDef is replaced with body itself markReachedTwice(bx) - val args: List[Ident] = vss(bx).map(subst) + val args: List[Ident] = vss(bx).flatMap(subst(_)) val label = labels(bx) val body = targets(bx) val MethodType(fmls, _) = label.tpe @@ -698,7 +698,7 @@ trait ParallelMatching { body match { case _: Throw | _: Literal => // might be bound elsewhere (see `x @ unapply') - val vdefs = for (v <- vss(bx) ; val substv = subst(v) ; if substv ne null) yield typedValDef(v, substv) + val vdefs = for (v <- vss(bx) ; substv <- subst(v)) yield typedValDef(v, substv) squeezedBlock(vdefs, body.duplicate setType resultType) case _ => Apply(mkIdent(label),args) diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala index 6b78770af0..57ff8faeaf 100644 --- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala +++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala @@ -12,8 +12,10 @@ import scala.tools.nsc.util.{Position, NoPosition} * @author Burak Emir */ trait PatternNodes { self: transform.ExplicitOuter => - import global._ + import global.{typer => _, _} + import analyzer.Typer; import symtab.Flags + final def DBG(x: => String) = if (settings.debug.value) Console.println(x) final def getDummies(i: Int): List[Tree] = List.make(i, EmptyTree) @@ -115,27 +117,24 @@ trait PatternNodes { self: transform.ExplicitOuter => /** pvar: the symbol of the pattern variable * temp: the temp variable that holds the actual value - * next: next binding */ - case class Binding(pvar:Symbol, temp:Symbol, private val next: Binding) extends Function1[Symbol, Ident]{ - def add(vs : Iterable[Symbol], temp : Symbol): Binding = - vs.foldLeft(this)((x, y) => Binding(y, temp, x)) - - /** this is just to produce debug output, ListBuffer needs an equals method?! */ - override def equals(x:Any) = { - x match { - case NoBinding => false - case Binding(pv2,tmp2,next2) => (pvar eq pv2) && (temp eq tmp2) && (next==next2) - } - } - def apply(v:Symbol): Ident = { - if (v eq pvar) Ident(temp).setType(v.tpe) else next(v) + case class Binding(pvar: Symbol, temp: Symbol) + + case class Bindings(bindings: Binding*) extends Function1[Symbol, Option[Ident]] { + def add(vs: Iterable[Symbol], temp: Symbol): Bindings = + Bindings(vs.toList.map(Binding(_, temp)) ++ bindings : _*) + + def apply(v: Symbol): Option[Ident] = bindings.find(_.pvar eq v) match { + case Some(b) => Some(Ident(b.temp) setType v.tpe) + case None => None // abort("Symbol " + v + " has no binding in " + bindings) } - } - object NoBinding extends Binding(null, null, null) { - override def apply(v:Symbol) = null // not found, means bound elsewhere (x @ unapply-call) - override def toString = "." - override def equals(x:Any) = x.isInstanceOf[Binding] && (x.asInstanceOf[Binding] eq this) + /** + * The corresponding list of value definitions. + */ + final def targetParams(implicit typer: Typer): List[ValDef] = + bindings.toList.map{ case Binding(v, t) => ValDef(v, typer.typed(mkIdent(t))) } } + + val NoBinding: Bindings = Bindings() } -- cgit v1.2.3