diff options
author | Paul Phillips <paulp@improving.org> | 2010-12-04 18:33:23 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-12-04 18:33:23 +0000 |
commit | b1e969a11b2b24f5883198dc0b90d9ab5513498b (patch) | |
tree | 434257c2afc84c4d86e55cd2bf78d9e29ca66dc9 | |
parent | 3d97123034a9d82e6e6961d589ccd3a1afde4390 (diff) | |
download | scala-b1e969a11b2b24f5883198dc0b90d9ab5513498b.tar.gz scala-b1e969a11b2b24f5883198dc0b90d9ab5513498b.tar.bz2 scala-b1e969a11b2b24f5883198dc0b90d9ab5513498b.zip |
A foot in the door with Parsers/JavaParsers and...
A foot in the door with Parsers/JavaParsers and Scanners/JavaScanners.
Recently clued in as to how this situation came to be, I now know
there's no reason not to start containing the damage. Also more work
on names: made a general method for transforming Trees into type-named
Trees and put it to work. No review.
9 files changed, 125 insertions, 100 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala index dd775d1a23..aeab9f75d7 100644 --- a/src/compiler/scala/tools/nsc/Interpreter.scala +++ b/src/compiler/scala/tools/nsc/Interpreter.scala @@ -821,7 +821,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) { * we know how to enumerate the identifiers. */ val importedNames: List[Name] = - selectorRenames filterNot (_ == USCOREkw) flatMap (x => List(x.toTypeName, x.toTermName)) + selectorRenames filterNot (_ == USCOREkw) flatMap (_.bothNames) override def resultExtractionCode(req: Request, code: PrintWriter) = code println codegenln(imp.toString) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index d93496a7c4..e606b1c6af 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -361,15 +361,19 @@ abstract class TreeGen { else mkCast(tree, pt) + /** Translate names in Select/Ident nodes to type names. + */ + def convertToTypeName(tree: Tree): Option[RefTree] = tree match { + case Select(qual, name) => Some(Select(qual, name.toTypeName)) + case Ident(name) => Some(Ident(name.toTypeName)) + case _ => None + } + /** Try to convert Select(qual, name) to a SelectFromTypeTree. */ - def convertToSelectFromType(qual: Tree, origName: Name): Tree = { - def selFromType(qual1: Tree) = SelectFromTypeTree(qual1 setPos qual.pos, origName) - qual match { - case Select(qual1, name) => selFromType(Select(qual1, name.toTypeName)) - case Ident(name) => selFromType(Ident(name.toTypeName)) - case _ => EmptyTree - } + def convertToSelectFromType(qual: Tree, origName: Name) = convertToTypeName(qual) match { + case Some(qual1) => SelectFromTypeTree(qual1 setPos qual.pos, origName) + case _ => EmptyTree } /** Used in situations where you need to access value of an expression several times diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index cc3910fdf3..2eb6b8c5f4 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -13,6 +13,39 @@ import util.{ OffsetPosition } import scala.reflect.generic.{ ModifierFlags => Flags } import Tokens._ +/** Historical note: JavaParsers started life as a direct copy of Parsers + * but at a time when that Parsers had been replaced by a different one. + * Later it was dropped and the original Parsers reinstated, leaving us with + * massive duplication between Parsers and JavaParsers. + * + * This trait and the similar one for Scanners/JavaScanners represents + * the beginnings of a campaign against this latest incursion by Cutty + * McPastington and his army of very similar soldiers. + */ +trait ParsersCommon extends ScannersCommon { + val global : Global + import global._ + + trait ParserCommon { + val in: ScannerCommon + def freshName(prefix: String): Name + def freshTermName(prefix: String): TermName + def freshTypeName(prefix: String): TypeName + def deprecationWarning(off: Int, msg: String): Unit + + def accept(token: Int): Int + def surround[T](open: Int, close: Int)(f: => T, orElse: T): T = { + val wasOpened = in.token == open + accept(open) + if (wasOpened) { + val ret = f + accept(close) + ret + } else orElse + } + } +} + //todo verify when stableId's should be just plain qualified type ids /** <p>Performs the following context-free rewritings:</p> @@ -50,7 +83,7 @@ import Tokens._ * </li> * </ol> */ -trait Parsers extends Scanners with MarkupParsers { +trait Parsers extends Scanners with MarkupParsers with ParsersCommon { self => val global: Global import global._ @@ -81,8 +114,7 @@ self => def r2p(start: Int, mid: Int, end: Int): Position = rangePos(unit.source, start, mid, end) def warning(offset: Int, msg: String) { unit.warning(o2p(offset), msg) } - def deprecationWarning(offset: Int, - msg: String) { + def deprecationWarning(offset: Int, msg: String) { unit.deprecationWarning(o2p(offset), msg) } @@ -141,7 +173,7 @@ self => import nme.raw - abstract class Parser { + abstract class Parser extends ParserCommon { val in: Scanner def freshName(prefix: String): Name @@ -367,7 +399,6 @@ self => } def warning(offset: Int, msg: String): Unit def incompleteInputError(msg: String): Unit - def deprecationWarning(offset: Int, msg: String): Unit private def syntaxError(pos: Position, msg: String, skipIt: Boolean) { syntaxError(pos pointOrElse in.offset, msg, skipIt) } @@ -417,16 +448,6 @@ self => offset } - def surround[T](open: Int, close: Int)(f: => T, orElse: T): T = { - val wasOpened = in.token == open - accept(open) - if (wasOpened) { - val ret = f - accept(close) - ret - } else orElse - } - /** semi = nl {nl} | `;' * nl = `\n' // where allowed */ @@ -587,14 +608,9 @@ self => /** Convert (qual)ident to type identifier */ def convertToTypeId(tree: Tree): Tree = atPos(tree.pos) { - tree match { - case Ident(name) => - Ident(name.toTypeName) - case Select(qual, name) => - Select(qual, name.toTypeName) - case _ => - syntaxError(tree.pos, "identifier expected", false) - errorTypeTree + convertToTypeName(tree) getOrElse { + syntaxError(tree.pos, "identifier expected", false) + errorTypeTree } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 25b65f0791..0835a1b2d0 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -12,7 +12,26 @@ import scala.annotation.switch import scala.collection.mutable.{ListBuffer, ArrayBuffer} import scala.xml.Utility.{ isNameStart } -trait Scanners { +/** See Parsers.scala / ParsersCommon for some explanation of ScannersCommon. + */ +trait ScannersCommon { + val global : Global + import global._ + + trait CommonTokenData { + def token: Int + def name: TermName + } + + trait ScannerCommon extends CommonTokenData { + // things to fill in, in addition to buf, decodeUni + def warning(off: Int, msg: String): Unit + def error (off: Int, msg: String): Unit + def incompleteInputError(off: Int, msg: String): Unit + } +} + +trait Scanners extends ScannersCommon { val global : Global import global._ @@ -22,7 +41,7 @@ trait Scanners { /** An undefined offset */ val NoOffset: Offset = -1 - trait TokenData { + trait TokenData extends CommonTokenData { /** the next token */ var token: Int = EMPTY @@ -52,7 +71,7 @@ trait Scanners { } } - abstract class Scanner extends CharArrayReader with TokenData { + abstract class Scanner extends CharArrayReader with TokenData with ScannerCommon { def flush = { charOffset = offset; nextChar(); this } @@ -62,12 +81,6 @@ trait Scanners { nextToken() } - // things to fill in, in addition to buf, decodeUni - def warning(off: Offset, msg: String): Unit - def error (off: Offset, msg: String): Unit - def incompleteInputError(off: Offset, msg: String): Unit - def deprecationWarning(off: Offset, msg: String): Unit - /** the last error offset */ var errOffset: Offset = NoOffset @@ -1022,7 +1035,6 @@ trait Scanners { def warning(off: Offset, msg: String) = unit.warning(unit.position(off), msg) def error (off: Offset, msg: String) = unit.error(unit.position(off), msg) def incompleteInputError(off: Offset, msg: String) = unit.incompleteInputError(unit.position(off), msg) - def deprecationWarning(off: Offset, msg: String) = unit.deprecationWarning(unit.position(off), msg) private var bracePatches: List[BracePatch] = patches diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index afb9999db8..c75ca15959 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -33,6 +33,8 @@ abstract class TreeBuilder { def productConstr = gen.productConstr def serializableConstr = gen.serializableConstr + def convertToTypeName(t: Tree) = gen.convertToTypeName(t) + /** Convert all occurrences of (lower-case) variables in a pattern as follows: * x becomes x @ _ * x: T becomes x @ (_: T) diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index d6cfdd24b1..d4167998e5 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -8,12 +8,12 @@ package scala.tools.nsc package javac -import scala.tools.nsc.util.{OffsetPosition, BatchSourceFile} +import scala.tools.nsc.util.OffsetPosition import scala.collection.mutable.ListBuffer import symtab.Flags import JavaTokens._ -trait JavaParsers extends JavaScanners { +trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val global : Global import global._ import definitions._ @@ -22,22 +22,25 @@ trait JavaParsers extends JavaScanners { class JavaUnitParser(val unit: global.CompilationUnit) extends JavaParser { val in = new JavaUnitScanner(unit) - def freshName(prefix : String) = unit.freshTermName(prefix) + def freshName(prefix: String): Name = freshTermName(prefix) + def freshTermName(prefix: String): TermName = unit.freshTermName(prefix) + def freshTypeName(prefix: String): TypeName = unit.freshTypeName(prefix) + def deprecationWarning(off: Int, msg: String) = unit.deprecationWarning(off, msg) implicit def i2p(offset : Int) : Position = new OffsetPosition(unit.source, offset) def warning(pos : Int, msg : String) : Unit = unit.warning(pos, msg) def syntaxError(pos: Int, msg: String) : Unit = unit.error(pos, msg) } - abstract class JavaParser { - + abstract class JavaParser extends ParserCommon { val in: JavaScanner + protected def posToReport: Int = in.currentPos - protected def freshName(prefix : String): Name + def freshName(prefix : String): Name protected implicit def i2p(offset : Int) : Position private implicit def p2i(pos : Position): Int = if (pos.isDefined) pos.point else -1 /** The simple name of the package of the currently parsed file */ - private var thisPackageName: Name = nme.EMPTY + private var thisPackageName: TypeName = tpnme.EMPTY /** this is the general parse method */ @@ -92,9 +95,9 @@ trait JavaParsers extends JavaScanners { } def warning(msg: String) : Unit = warning(in.currentPos, msg) - def errorTypeTree = TypeTree().setType(ErrorType).setPos((in.currentPos)) - def errorTermTree = Literal(Constant(null)).setPos((in.currentPos)) - def errorPatternTree = blankExpr.setPos((in.currentPos)) + def errorTypeTree = TypeTree().setType(ErrorType) setPos in.currentPos + def errorTermTree = Literal(Constant(null)) setPos in.currentPos + def errorPatternTree = blankExpr setPos in.currentPos // --------- tree building ----------------------------- @@ -123,17 +126,11 @@ trait JavaParsers extends JavaScanners { if (treeInfo.firstConstructor(stats) == EmptyTree) makeConstructor(List()) :: stats else stats) - def makeParam(name: Name, tpt: Tree) = - ValDef(Modifiers(Flags.JAVA | Flags.PARAM), name, tpt, EmptyTree) + def makeParam(name: String, tpt: Tree) = + ValDef(Modifiers(Flags.JAVA | Flags.PARAM), newTermName(name), tpt, EmptyTree) def makeConstructor(formals: List[Tree]) = { - var count = 0 - val vparams = - for (formal <- formals) - yield { - count += 1 - makeParam(newTermName("x$"+count), formal) - } + val vparams = formals.zipWithIndex map { case (p, i) => makeParam("x$" + (i + 1), p) } DefDef(Modifiers(Flags.JAVA), nme.CONSTRUCTOR, List(), List(vparams), TypeTree(), blankExpr) } @@ -225,16 +222,15 @@ trait JavaParsers extends JavaScanners { /** Convert (qual)ident to type identifier */ - def convertToTypeId(tree: Tree): Tree = tree match { - case Ident(name) => - Ident(name.toTypeName).setPos(tree.pos) - case Select(qual, name) => - Select(qual, name.toTypeName).setPos(tree.pos) - case AppliedTypeTree(_, _) | ExistentialTypeTree(_, _) | SelectFromTypeTree(_, _) => - tree - case _ => - syntaxError(tree.pos, "identifier expected", false) - errorTypeTree + def convertToTypeId(tree: Tree): Tree = gen.convertToTypeName(tree) match { + case Some(t) => t setPos tree.pos + case _ => tree match { + case AppliedTypeTree(_, _) | ExistentialTypeTree(_, _) | SelectFromTypeTree(_, _) => + tree + case _ => + syntaxError(tree.pos, "identifier expected", false) + errorTypeTree + } } // -------------------- specific parsing routines ------------------ @@ -390,8 +386,7 @@ trait JavaParsers extends JavaScanners { def modifiers(inInterface: Boolean): Modifiers = { var flags: Long = Flags.JAVA - // assumed true unless we see public/private/protected - see bug #1240 - // Todo: look at pos/t1176, #1240, #1840, #1842, see what current access issues are. + // assumed true unless we see public/private/protected var isPackageAccess = true var annots: List[Tree] = Nil def addAnnot(sym: Symbol) = @@ -433,7 +428,7 @@ trait JavaParsers extends JavaScanners { case SYNCHRONIZED | STRICTFP => in.nextToken case _ => - val privateWithin: Name = + val privateWithin: TypeName = if (isPackageAccess && !inInterface) thisPackageName else tpnme.EMPTY @@ -698,12 +693,11 @@ trait JavaParsers extends JavaScanners { } else { val qual = ((Ident(names.head): Tree) /: names.tail.init) (Select(_, _)) val lastname = names.last - List { - atPos(pos) { - if (lastname == nme.WILDCARD) Import(qual, List(ImportSelector(lastname, lastnameOffset, null, -1))) - else Import(qual, List(ImportSelector(lastname, lastnameOffset, lastname, lastnameOffset))) - } + val selector = lastname match { + case nme.WILDCARD => ImportSelector(lastname, lastnameOffset, null, -1) + case _ => ImportSelector(lastname, lastnameOffset, lastname, lastnameOffset) } + List(atPos(pos)(Import(qual, List(selector)))) } } @@ -850,7 +844,7 @@ trait JavaParsers extends JavaScanners { blankExpr), DefDef( Modifiers(Flags.JAVA | Flags.STATIC), newTermName("valueOf"), List(), - List(List(makeParam(newTermName("x"), TypeTree(StringClass.tpe)))), + List(List(makeParam("x", TypeTree(StringClass.tpe)))), enumType, blankExpr)) accept(RBRACE) @@ -881,11 +875,11 @@ trait JavaParsers extends JavaScanners { } def typeDecl(mods: Modifiers): List[Tree] = in.token match { - case ENUM => enumDecl(mods) + case ENUM => enumDecl(mods) case INTERFACE => interfaceDecl(mods) - case AT => annotationDecl(mods) - case CLASS => classDecl(mods) - case _ => in.nextToken; syntaxError("illegal start of type declaration", true); List(errorTypeTree) + case AT => annotationDecl(mods) + case CLASS => classDecl(mods) + case _ => in.nextToken; syntaxError("illegal start of type declaration", true); List(errorTypeTree) } /** CompilationUnit ::= [package QualId semi] TopStatSeq @@ -903,9 +897,9 @@ trait JavaParsers extends JavaScanners { } else { Ident(nme.EMPTY_PACKAGE_NAME) } - thisPackageName = pkg match { - case Ident(name) => name.toTypeName - case Select(_, name) => name.toTypeName + thisPackageName = gen.convertToTypeName(pkg) match { + case Some(t) => t.name + case _ => tpnme.EMPTY } val buf = new ListBuffer[Tree] while (in.token == IMPORT) diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index fd69f15edc..76137ccdf4 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -12,9 +12,10 @@ import JavaTokens._ import scala.annotation.switch // Todo merge these better with Scanners -trait JavaScanners { +trait JavaScanners extends ast.parser.ScannersCommon { val global : Global import global._ + abstract class AbstractJavaTokenData { def token: Int type ScanPosition @@ -56,10 +57,7 @@ trait JavaScanners { abstract class AbstractJavaScanner extends AbstractJavaTokenData { implicit def p2g(pos: Position): ScanPosition implicit def g2p(pos: ScanPosition): Position - def warning(pos: ScanPosition, msg: String): Unit - def error (pos: ScanPosition, msg: String): Unit - def incompleteInputError(pos: ScanPosition, msg: String): Unit - def deprecationWarning(pos: ScanPosition, msg: String): Unit + /** the last error position */ var errpos: ScanPosition @@ -250,7 +248,7 @@ trait JavaScanners { * * @author Martin Odersky */ - abstract class JavaScanner extends AbstractJavaScanner with JavaTokenData with Cloneable { + abstract class JavaScanner extends AbstractJavaScanner with JavaTokenData with Cloneable with ScannerCommon { override def intVal = super.intVal// todo: needed? override def floatVal = super.floatVal override var errpos: Int = NoPos @@ -312,12 +310,9 @@ trait JavaScanners { def nextToken { if (next.token == EMPTY) { - //print("[") - val t = fetchToken() - //print(this) - //print("]") - t - } else { + fetchToken() + } + else { this copyFrom next next.token = EMPTY } @@ -950,7 +945,6 @@ trait JavaScanners { def warning(pos: Int, msg: String) = unit.warning(pos, msg) def error (pos: Int, msg: String) = unit. error(pos, msg) def incompleteInputError(pos: Int, msg: String) = unit.incompleteInputError(pos, msg) - def deprecationWarning(pos: Int, msg: String) = unit.deprecationWarning(pos, msg) implicit def p2g(pos: Position): Int = if (pos.isDefined) pos.point else -1 implicit def g2p(pos: Int): Position = new OffsetPosition(unit.source, pos) } diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index 87f88d1c5b..9cfa17996c 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -658,7 +658,7 @@ trait Definitions extends reflect.generic.StandardDefinitions { abbrvTag(clazz) = tag if (weight > 0) numericWeight(clazz) = weight - val module = ScalaPackageClass.newModule(NoPosition, name.toTermName) + val module = ScalaPackageClass.newModule(NoPosition, name) ScalaPackageClass.info.decls.enter(module) val mclass = module.moduleClass mclass.setInfo(ClassInfoType(List(AnyRefClass.tpe, AnyValCompanionClass.tpe), new Scope, mclass)) diff --git a/src/compiler/scala/tools/nsc/symtab/Names.scala b/src/compiler/scala/tools/nsc/symtab/Names.scala index 1e4ff419ea..c794aadd62 100644 --- a/src/compiler/scala/tools/nsc/symtab/Names.scala +++ b/src/compiler/scala/tools/nsc/symtab/Names.scala @@ -176,6 +176,7 @@ trait Names extends reflect.generic.Names { def isTypeName: Boolean def toTermName: TermName def toTypeName: TypeName + def companionName: Name def bothNames: List[Name] = List(toTermName, toTypeName) /** Copy bytes of this name to buffer cs, starting at position `offset`. @@ -429,6 +430,7 @@ trait Names extends reflect.generic.Names { n = new TypeName(index, len, h); n } + def companionName: TypeName = toTypeName def subName(from: Int, to: Int): TermName = newTermName(chrs, start + from, to - from) } @@ -448,6 +450,7 @@ trait Names extends reflect.generic.Names { n } def toTypeName: TypeName = this + def companionName: TermName = toTermName def subName(from: Int, to: Int): TypeName = newTypeName(chrs, start + from, to - from) } |