summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-06-29 04:27:36 +0000
committerPaul Phillips <paulp@improving.org>2009-06-29 04:27:36 +0000
commita868cd75895e239e20280e37c1d5e8dc81e5045a (patch)
tree2922ec6d1cffb6114eaf687a8666a0698d4d9971 /src
parent31baa0e552e0df0592ece4c181231887cd8709b5 (diff)
downloadscala-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.scala8
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala139
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala20
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 &lt;lhs = rhs&gt; */
@@ -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 &lt;case pat if guard => rhs&gt; */
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 &lt;val pat0 = rhs&gt; */
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 =>