diff options
author | Paul Phillips <paulp@improving.org> | 2009-06-29 04:27:36 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-06-29 04:27:36 +0000 |
commit | a868cd75895e239e20280e37c1d5e8dc81e5045a (patch) | |
tree | 2922ec6d1cffb6114eaf687a8666a0698d4d9971 /src | |
parent | 31baa0e552e0df0592ece4c181231887cd8709b5 (diff) | |
download | scala-a868cd75895e239e20280e37c1d5e8dc81e5045a.tar.gz scala-a868cd75895e239e20280e37c1d5e8dc81e5045a.tar.bz2 scala-a868cd75895e239e20280e37c1d5e8dc81e5045a.zip |
Misc fussing with DSL details.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeDSL.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala | 139 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Mixin.scala | 20 |
3 files changed, 83 insertions, 84 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala index 5f28b1753f..09fc7ff2a9 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala @@ -28,10 +28,14 @@ trait TreeDSL { def ID(sym: Symbol) = Ident(sym) setType sym.tpe + // You might think these could be vals, but empirically I have found that + // at least in the case of UNIT the compiler breaks if you re-use trees. + // However we need stable identifiers to have attractive pattern matching. + // So it's inconsistent until I devise a better way. val TRUE = LIT(true) val FALSE = LIT(false) - val NULL = LIT(null) - val UNIT = LIT(()) + def NULL = LIT(null) + def UNIT = LIT(()) val ZERO = LIT(0) def WILD(tpe: Type = null) = diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 96b052013a..37c90324da 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -10,10 +10,11 @@ import symtab.Flags._ import scala.collection.mutable.ListBuffer import scala.tools.nsc.util.Position -abstract class TreeBuilder { - +abstract class TreeBuilder extends TreeDSL +{ val global: Global import global._ + import CODE._ def freshName(prefix: String): Name def freshName(): Name = freshName("x$") @@ -43,6 +44,9 @@ abstract class TreeBuilder { case Typed(id @ Ident(name), tpt) if (treeInfo.isVarPattern(id) && name != nme.WILDCARD) => atPos(tree.pos.withPoint(id.pos.point)) { Bind(name, atPos(tree.pos.withStart(tree.pos.point)) { + // XXX question: how do these differ: + // Typed(Ident(nme.WILDCARD), tpt) // annotation (eliminated by explicitouter) + // Ident(nme.WILDCARD) setType tpt // Typed(Ident(nme.WILDCARD), tpt) }) } @@ -65,14 +69,18 @@ abstract class TreeBuilder { private object getvarTraverser extends Traverser { val buf = new ListBuffer[(Name, Tree, Position)] def init: Traverser = { buf.clear; this } + def isVar(name: Name) = (name != nme.WILDCARD) && (buf.iterator forall (name !=)) + override def traverse(tree: Tree): Unit = tree match { case Bind(name, Typed(tree1, tpt)) => - if ((name != nme.WILDCARD) && (buf.iterator forall (name !=))) + if (isVar(name)) buf += ((name, if (treeInfo.mayBeTypePat(tpt)) TypeTree() else tpt, tree.pos)) + traverse(tree1) case Bind(name, tree1) => - if ((name != nme.WILDCARD) && (buf.iterator forall (name !=))) + if (isVar(name)) buf += ((name, TypeTree(), tree.pos)) + traverse(tree1) case _ => super.traverse(tree) @@ -93,15 +101,14 @@ abstract class TreeBuilder { } def makeTupleTerm(trees: List[Tree], flattenUnary: Boolean): Tree = trees match { - case List() => Literal(()) + case Nil => UNIT case List(tree) if flattenUnary => tree - case _ => makeTuple(trees, false) + case _ => makeTuple(trees, false) } - def makeTupleType(trees: List[Tree], flattenUnary: Boolean): Tree = trees match { - case List() => scalaUnitConstr + case Nil => scalaUnitConstr case List(tree) if flattenUnary => tree - case _ => AppliedTypeTree(scalaDot(newTypeName("Tuple" + trees.length)), trees) + case _ => AppliedTypeTree(scalaDot(newTypeName("Tuple" + trees.length)), trees) } def stripParens(t: Tree) = t match { @@ -128,35 +135,32 @@ abstract class TreeBuilder { def makeBinop(isExpr: Boolean, left: Tree, op: Name, right: Tree): Tree = { val arguments = right match { case Parens(args) => args - case _ => List(right) + case _ => List(right) } - if (isExpr) { - if (treeInfo.isLeftAssoc(op)) { - Apply(Select(stripParens(left), op.encode), arguments) - } else { - val x = freshName() - Block( - List(ValDef(Modifiers(SYNTHETIC), x, TypeTree(), stripParens(left))), - Apply(Select(stripParens(right), op.encode), List(Ident(x)))) - } - } else { - Apply(Ident(op.encode), stripParens(left) :: arguments) + + if (!isExpr) Ident(op.encode) APPLY (stripParens(left) :: arguments) + else if (treeInfo isLeftAssoc op) (stripParens(left) DOT op.encode)(arguments: _*) + else { + val x = freshName() + BLOCK( + ValDef(Modifiers(SYNTHETIC), x, TypeTree(), stripParens(left)), + (stripParens(right) DOT op.encode)(Ident(x)) + ) } } /** Create tree representing an object creation <new parents { stats }> */ def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], argss: List[List[Tree]]): Tree = - if (parents.isEmpty) - makeNew(List(scalaAnyRefConstr), self, stats, argss) - else if (parents.tail.isEmpty && stats.isEmpty) - New(parents.head, argss) - else { - val x = nme.ANON_CLASS_NAME.toTypeName - Block( - List(ClassDef( - Modifiers(FINAL), x, List(), - Template(parents, self, NoMods, List(List()), argss, stats))), - New(Ident(x), List(List()))) + (parents, stats) match { + case (Nil, _) => makeNew(List(scalaAnyRefConstr), self, stats, argss) + case (x :: Nil, Nil) => New(x, argss) + case _ => + val x = nme.ANON_CLASS_NAME.toTypeName + BLOCK( + ClassDef(Modifiers(FINAL), x, Nil, + Template(parents, self, NoMods, List(Nil), argss, stats)), + New(Ident(x), List(Nil)) + ) } /** Create a tree represeting an assignment <lhs = rhs> */ @@ -174,8 +178,9 @@ abstract class TreeBuilder { /** Create tree representing a while loop */ def makeWhile(lname: Name, cond: Tree, body: Tree): Tree = { - val continu = Apply(Ident(lname), List()) - val rhs = If(cond, Block(List(body), continu), Literal(())) + val continu = Ident(lname) APPLY () + val rhs = IF (cond) THEN BLOCK(body, continu) ELSE UNIT + LabelDef(lname, Nil, rhs) } @@ -208,8 +213,8 @@ abstract class TreeBuilder { List( makeVisitor( List( - CaseDef(pat1.syntheticDuplicate, EmptyTree, Literal(true)), - CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(false))), + CaseDef(pat1.syntheticDuplicate, EmptyTree, TRUE), + CaseDef(Ident(nme.WILDCARD), EmptyTree, FALSE)), false, nme.CHECK_IF_REFUTABLE_STRING ))) @@ -283,16 +288,16 @@ abstract class TreeBuilder { } def makeCombination(meth: Name, qual: Tree, pat: Tree, body: Tree): Tree = - Apply(Select(qual, meth), List(makeClosure(pat, body))); + (qual DOT meth)(makeClosure(pat, body)) def patternVar(pat: Tree): Option[Name] = pat match { - case Bind(name, _) => Some(name) - case _ => None + case Bind(name, _) => Some(name) + case _ => None } def makeBind(pat: Tree): Tree = pat match { case Bind(_, _) => pat - case _ => Bind(freshName(), pat) + case _ => Bind(freshName(), pat) } def makeValue(pat: Tree): Tree = pat match { @@ -354,19 +359,19 @@ abstract class TreeBuilder { /** 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) + case Alternative(ts) => ts + case _ => List(t) } - Alternative(for (t <- ts; a <- alternatives(t)) yield a) + Alternative(ts flatMap alternatives) } /** 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) + case _ => List(t) } - Sequence(for (t <- ts; e <- elements(t)) yield e) + Sequence(ts flatMap elements) } /** Create visitor <x => x match cases> */ @@ -374,7 +379,7 @@ abstract class TreeBuilder { makeVisitor(cases, checkExhaustive, "x$") private def makeUnchecked(expr: Tree): Tree = atPos(expr.pos) { - Annotated(New(scalaDot(definitions.UncheckedClass.name), List(List())), expr) + Annotated(New(scalaDot(definitions.UncheckedClass.name), List(Nil)), expr) } /** Create visitor <x => x match cases> */ @@ -386,7 +391,7 @@ abstract class TreeBuilder { /** 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) + (CASE(patvarTransformer transform pat) IF guard) ==> rhs /** Create tree for pattern definition <val pat0 = rhs> */ def makePatDef(pat: Tree, rhs: Tree): List[Tree] = @@ -406,31 +411,25 @@ abstract class TreeBuilder { // val/var x_1 = t$._1 // ... // val/var x_N = t$._N - val pat1 = patvarTransformer.transform(pat) - val vars = getVariables(pat1) - val matchExpr = atPos(rhs.pos){ - Match( - makeUnchecked(rhs), - List( - makeSynthetic( - atPos(rhs.pos) { - CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map Ident, true)) - }))) - + val pat1 = patvarTransformer.transform(pat) + val vars = getVariables(pat1) + def flags = Modifiers(PRIVATE | LOCAL | SYNTHETIC | (mods.flags & LAZY)) + val matchExpr = atPos(rhs.pos) { + makeUnchecked(rhs) MATCH ( + makeSynthetic(atPos(rhs.pos) { CASE(pat1) ==> makeTupleTerm(vars map (v => Ident(v._1)), true) }) + ) } + vars match { - case List((vname, tpt, pos)) => - List(ValDef(mods, vname, tpt, matchExpr)) - case _ => - val tmp = freshName() - val firstDef = ValDef(Modifiers(PRIVATE | LOCAL | SYNTHETIC | (mods.flags & LAZY)), - tmp, TypeTree(), matchExpr) - var cnt = 0 - val restDefs = for ((vname, tpt, pos) <- vars) yield atPos(pos) { - cnt = cnt + 1 - ValDef(mods, vname, tpt, Select(Ident(tmp), newTermName("_" + cnt))) - } - firstDef :: restDefs + case List((vname, tpt, pos)) => List(ValDef(mods, vname, tpt, matchExpr)) + case _ => + val x = freshName() + def body(i: Int) = Select(Ident(x), newTermName("_" + i)) + + ValDef(flags, x, TypeTree(), matchExpr) :: ( + for (((vname, tpt, pos), cnt) <- vars.zipWithIndex) yield + atPos(pos)( ValDef(mods, vname, tpt, body(cnt + 1)) ) + ) } } diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 040edb9a60..29d182b61e 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -564,10 +564,10 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { .setInfo(IntClass.tpe) .setFlag(PROTECTED) atPhase(currentRun.typerPhase) { - sym.addAnnotation(AnnotationInfo(VolatileAttr.tpe, List(), List())) + sym addAnnotation AnnotationInfo(VolatileAttr.tpe, Nil, Nil) } clazz.info.decls.enter(sym) - addDef(clazz.pos, ValDef(sym, ZERO)) + addDef(clazz.pos, VAL(sym) === ZERO) } sym } @@ -643,11 +643,9 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * the class constructor is changed to set the initialized bits. */ def addCheckedGetters(clazz: Symbol, stats: List[Tree]): List[Tree] = { - def findLazyAssignment(stats: List[Tree]): Tree = - (stats find { - case Assign(lhs, _) if lhs.symbol.hasFlag(LAZY) => true - case _ => false - }).get // if there's no assignment then it's a bug and we crash + def findLazyAssignment(stats: List[Tree]): Tree = ( + for (s @ Assign(lhs, _) <- stats ; if lhs.symbol hasFlag LAZY) yield s + ) head // if there's no assignment then it's a bug and we crash val stats1 = for (stat <- stats; sym = stat.symbol) yield stat match { case DefDef(mods, name, tp, vp, tpt, rhs) @@ -665,11 +663,9 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { if needsInitFlag(sym) && rhs != EmptyTree && !clazz.isImplClass && !clazz.isTrait => assert(fieldOffset.isDefinedAt(sym)) - val rhs1 = if (sym.tpe.resultType.typeSymbol == UnitClass) - mkCheckedAccessor(clazz, UNIT, fieldOffset(sym), stat.pos) - else { - mkCheckedAccessor(clazz, rhs, fieldOffset(sym), stat.pos) - } + val rhs1 = (mkCheckedAccessor(clazz, _: Tree, fieldOffset(sym), stat.pos))( + if (sym.tpe.resultType.typeSymbol == UnitClass) UNIT else rhs + ) treeCopy.DefDef(stat, mods, name, tp, vp, tpt, rhs1) case DefDef(mods, name, tp, vp, tpt, rhs) if sym.isConstructor => |