summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-08-24 17:16:48 +0000
committerMartin Odersky <odersky@gmail.com>2006-08-24 17:16:48 +0000
commitb5f66bdd72531b82a30a98872338f682d553f642 (patch)
tree62ce5f575b75c34b49f5fe88e11fb7793768cafd /src
parent296bcdfcb2c467943dfdab8e290fb69cb971db55 (diff)
downloadscala-b5f66bdd72531b82a30a98872338f682d553f642.tar.gz
scala-b5f66bdd72531b82a30a98872338f682d553f642.tar.bz2
scala-b5f66bdd72531b82a30a98872338f682d553f642.zip
fixed bug 710.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala43
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala10
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Tokens.scala3
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala4
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala20
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala34
10 files changed, 79 insertions, 43 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index 20c5b1ec56..62bddd488a 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -105,7 +105,7 @@ abstract class TreeInfo {
/** Is tree a variable pattern */
def isVarPattern(pat: Tree): boolean = pat match {
- case Ident(name) => isVariableName(name)
+ case Ident(name) => isVariableName(name) && !pat.isInstanceOf[BackQuotedIdent]
case _ => false
}
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 3c94b9334a..c385c78012 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -515,6 +515,8 @@ trait Trees requires Global {
override def isType = name.isTypeName
}
+ class BackQuotedIdent(name: Name) extends Ident(name)
+
def Ident(sym: Symbol): Ident =
Ident(sym.name) setSymbol sym
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 282d2b5ce3..47f8c7bc64 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -170,9 +170,11 @@ trait Parsers requires SyntaxAnalyzer {
case _ => false
}
+ def isIdent = in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT
+
def isExprIntroToken(token: int): boolean = token match {
case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
- STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL | IDENTIFIER |
+ STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL | IDENTIFIER | BACKQUOTED_IDENT |
THIS | SUPER | IF | FOR | NEW | USCORE | TRY | WHILE |
DO | RETURN | THROW | LPAREN | LBRACE | XMLSTART => true
case _ => false
@@ -316,7 +318,7 @@ trait Parsers requires SyntaxAnalyzer {
final val LT : Name = "<"
def ident(): Name =
- if (in.token == IDENTIFIER) {
+ if (in.token == IDENTIFIER || in.token == BACKQUOTED_IDENT) {
val name = in.name.encode
in.nextToken()
name
@@ -351,7 +353,10 @@ trait Parsers requires SyntaxAnalyzer {
if (in.token == DOT)
t = selectors(t, typeOK, in.skipToken())
} else {
- val i = atPos(in.currentPos) { Ident(ident()) }
+ val i = atPos(in.currentPos) {
+ if (in.token == BACKQUOTED_IDENT) new BackQuotedIdent(ident())
+ else Ident(ident())
+ }
t = i;
if (in.token == DOT) {
val pos = in.skipToken();
@@ -703,7 +708,7 @@ trait Parsers requires SyntaxAnalyzer {
}
case DOT =>
atPos(in.skipToken()) {
- if (in.token == IDENTIFIER) makeClosure(simpleExpr())
+ if (isIdent) makeClosure(simpleExpr())
else { syntaxError("identifier expected", true); errorTermTree }
}
case _ =>
@@ -718,7 +723,7 @@ trait Parsers requires SyntaxAnalyzer {
val pos = in.skipToken();
if (isArgument && in.token == USCORE) {
val pos1 = in.skipToken();
- if (in.token == IDENTIFIER && in.name == nme.STAR) {
+ if (isIdent && in.name == nme.STAR) {
in.nextToken();
t = atPos(pos) {
Typed(t, atPos(pos1) { Ident(nme.WILDCARD_STAR.toTypeName) })
@@ -764,7 +769,7 @@ trait Parsers requires SyntaxAnalyzer {
def postfixExpr(): Tree = {
val base = opstack
var top = prefixExpr()
- while (in.token == IDENTIFIER) {
+ while (isIdent) {
top = reduceStack(
true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name));
opstack = OpInfo(top, in.name, in.currentPos) :: opstack;
@@ -786,17 +791,17 @@ trait Parsers requires SyntaxAnalyzer {
/** PrefixExpr ::= [`-' | `+' | `~' | `!' | `&'] SimpleExpr
*/
def prefixExpr(): Tree =
- if (in.token == IDENTIFIER && in.name == MINUS) {
+ if (isIdent && in.name == MINUS) {
val name = ident();
in.token match {
case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => literal(false, true)
case _ => atPos(in.currentPos) { Select(simpleExpr(), name) }
}
- } else if (in.token == IDENTIFIER && (in.name == PLUS || in.name == TILDE || in.name == BANG)) {
+ } else if (isIdent && (in.name == PLUS || in.name == TILDE || in.name == BANG)) {
val pos = in.currentPos;
val name = ident();
atPos(pos) { Select(simpleExpr(), name) }
- } else if (in.token == IDENTIFIER && in.name == AMP) {
+ } else if (isIdent && in.name == AMP) {
val pos = in.currentPos;
val name = ident();
atPos(pos) { Typed(simpleExpr(), Function(List(), EmptyTree)) }
@@ -826,7 +831,7 @@ trait Parsers requires SyntaxAnalyzer {
case XMLSTART =>
t = xmlp.xLiteral
//Console.println("successfully parsed XML at "+t); // DEBUG
- case IDENTIFIER | THIS | SUPER =>
+ case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>
t = path(true, false)
case LPAREN =>
val pos = in.skipToken()
@@ -990,9 +995,9 @@ trait Parsers requires SyntaxAnalyzer {
def pattern(seqOK: boolean): Tree = {
val pos = in.currentPos
val t = pattern1(seqOK)
- if (in.token == IDENTIFIER && in.name == BAR) {
+ if (isIdent && in.name == BAR) {
val ts = new ListBuffer[Tree] + t;
- while (in.token == IDENTIFIER && in.name == BAR) {
+ while (isIdent && in.name == BAR) {
in.nextToken(); ts += pattern1(seqOK);
}
atPos(pos) { makeAlternative(ts.toList) }
@@ -1014,7 +1019,7 @@ trait Parsers requires SyntaxAnalyzer {
//} else {
val p = pattern2(seqOK);
p match {
- case Ident(name) if (treeInfo.isVariableName(name) && in.token == COLON) =>
+ case Ident(name) if (treeInfo.isVarPattern(p) && in.token == COLON) =>
atPos(in.skipToken()) { Typed(p, type1()) }
case _ =>
p
@@ -1034,7 +1039,7 @@ trait Parsers requires SyntaxAnalyzer {
case Ident(name) =>
if (name == nme.WILDCARD) {
in.nextToken(); pattern3(seqOK)
- } else if (treeInfo.isVariableName(name)) {
+ } else if (treeInfo.isVarPattern(p)) {
atPos(in.skipToken()) { Bind(name, pattern3(seqOK)) }
} else {
p
@@ -1053,7 +1058,7 @@ trait Parsers requires SyntaxAnalyzer {
def pattern3(seqOK: boolean): Tree = {
val base = opstack
var top = simplePattern(seqOK)
- if (seqOK && in.token == IDENTIFIER) {
+ if (seqOK && isIdent) {
if (in.name == STAR)
return atPos(in.skipToken())(Star(top))
else if (in.name == PLUS)
@@ -1061,7 +1066,7 @@ trait Parsers requires SyntaxAnalyzer {
else if (in.name == OPT)
return atPos(in.skipToken())(makeOpt(top))
}
- while (in.token == IDENTIFIER && in.name != BAR) {
+ while (isIdent && in.name != BAR) {
top = reduceStack(
false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name));
opstack = OpInfo(top, in.name, in.currentPos) :: opstack;
@@ -1085,7 +1090,7 @@ trait Parsers requires SyntaxAnalyzer {
* | `(' Patterns `)'
*/
def simplePattern(seqOK: boolean): Tree = in.token match {
- case IDENTIFIER | THIS =>
+ case IDENTIFIER | BACKQUOTED_IDENT | THIS =>
var t = stableId();
in.token match {
case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT =>
@@ -1290,7 +1295,7 @@ trait Parsers requires SyntaxAnalyzer {
}
else {
val t = typ()
- if (in.token == IDENTIFIER && in.name == STAR) {
+ if (isIdent && in.name == STAR) {
in.nextToken();
atPos(t.pos) {
AppliedTypeTree(
@@ -1307,7 +1312,7 @@ trait Parsers requires SyntaxAnalyzer {
def typeParamClauseOpt(owner: Name, implicitViews: ListBuffer[Tree]): List[AbsTypeDef] = {
def typeParam(): AbsTypeDef = {
var mods = Modifiers(Flags.PARAM);
- if (owner.isTypeName && in.token == IDENTIFIER) {
+ if (owner.isTypeName && isIdent) {
if (in.name == PLUS) {
in.nextToken();
mods = mods | Flags.COVARIANT;
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 5c37359adc..4811cd6ace 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -280,7 +280,7 @@ trait Scanners requires SyntaxAnalyzer {
case '`' =>
in.next
getStringLit('`')
- token = IDENTIFIER
+ token = IDENTIFIER /*BACKQUOTED_IDENT*/
return
case '\"' =>
in.next
@@ -456,8 +456,8 @@ trait Scanners requires SyntaxAnalyzer {
def inLastOfStat(token: int) = token match {
case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | SYMBOLLIT |
- IDENTIFIER | THIS | NULL | TRUE | FALSE | RETURN | USCORE | TYPE | XMLSTART |
- RPAREN | RBRACKET | RBRACE =>
+ IDENTIFIER | BACKQUOTED_IDENT | THIS | NULL | TRUE | FALSE | RETURN | USCORE |
+ TYPE | XMLSTART | RPAREN | RBRACKET | RBRACE =>
true
case _ =>
false
@@ -895,7 +895,7 @@ trait Scanners requires SyntaxAnalyzer {
/** Returns the string representation of given token. */
def token2string(token: int): String = token match {
- case IDENTIFIER =>
+ case IDENTIFIER | BACKQUOTED_IDENT =>
"identifier"/* + \""+name+"\""*/
case CHARLIT =>
"character literal"
@@ -951,7 +951,7 @@ trait Scanners requires SyntaxAnalyzer {
}
override def toString() = token match {
- case IDENTIFIER =>
+ case IDENTIFIER | BACKQUOTED_IDENT =>
"id(" + name + ")"
case CHARLIT =>
"char(" + intVal + ")"
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
index b99ee08811..620c04dc45 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
@@ -22,8 +22,9 @@ object Tokens {
final val STRINGLIT = 6;
final val SYMBOLLIT = 7;
- /** identifier */
+ /** identifiers */
final val IDENTIFIER = 10;
+ final val BACKQUOTED_IDENT = 11;
/** keywords */
final val IF = 20;
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 53936ed9aa..055f5325b0 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -34,9 +34,9 @@ abstract class TreeBuilder {
*/
private object patvarTransformer extends Transformer {
override def transform(tree: Tree): Tree = tree match {
- case Ident(name) if (treeInfo.isVariableName(name) && name != nme.WILDCARD) =>
+ case Ident(name) if (treeInfo.isVarPattern(tree) && name != nme.WILDCARD) =>
atPos(tree.pos)(Bind(name, Ident(nme.WILDCARD)))
- case Typed(id @ Ident(name), tpt) if (treeInfo.isVariableName(name) && name != nme.WILDCARD) =>
+ case Typed(id @ Ident(name), tpt) if (treeInfo.isVarPattern(id) && name != nme.WILDCARD) =>
Bind(name, atPos(tree.pos)(Typed(Ident(nme.WILDCARD), tpt))) setPos id.pos
case Apply(fn @ Apply(_, _), args) =>
copy.Apply(tree, transform(fn), transformTrees(args))
diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
index 3b63f04fdc..62b96782f0 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
@@ -299,8 +299,6 @@ trait PatternMatchers requires (TransMatcher with PatternNodes) extends AnyRef w
case Ident(name) => // pattern without args or named constant
if (tree.symbol.isPrimaryConstructor)
scala.Predef.error("error may not happen: ident is primary constructor"+tree.symbol); // Burak
- else if (treeInfo.isVariableName(name))
- scala.Predef.error("this may not happen"); // because id => id @ _
else
pVariablePat(tree.pos, tree); // named constant (capitalized variable Foo)
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index f1540ff52f..80760e7de8 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -160,25 +160,25 @@ trait Types requires SymbolTable {
* Members appear in linearization order of their owners.
* Members with the same owner appear in reverse order of their declarations.
*/
- def members: List[Symbol] = findMember(nme.ANYNAME, 0, 0).alternatives
+ def members: List[Symbol] = findMember(nme.ANYNAME, 0, 0, false).alternatives
/** A list of all non-private members of this type (defined or inherited) */
- def nonPrivateMembers: List[Symbol] = findMember(nme.ANYNAME, PRIVATE | BRIDGE, 0).alternatives;
+ def nonPrivateMembers: List[Symbol] = findMember(nme.ANYNAME, PRIVATE | BRIDGE, 0, false).alternatives;
/** A list of all implicit symbols of this type (defined or inherited) */
- def implicitMembers: List[Symbol] = findMember(nme.ANYNAME, BRIDGE, IMPLICIT).alternatives;
+ def implicitMembers: List[Symbol] = findMember(nme.ANYNAME, BRIDGE, IMPLICIT, false).alternatives;
/** The member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist */
- def member(name: Name): Symbol = findMember(name, BRIDGE, 0)
+ def member(name: Name): Symbol = findMember(name, BRIDGE, 0, false)
/** The non-private member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist */
- def nonPrivateMember(name: Name): Symbol = findMember(name, PRIVATE | BRIDGE, 0)
+ def nonPrivateMember(name: Name): Symbol = findMember(name, PRIVATE | BRIDGE, 0, false)
/** The non-local member with given name,
* an OverloadedSymbol if several exist, NoSymbol if none exist */
- def nonLocalMember(name: Name): Symbol = findMember(name, LOCAL | BRIDGE, 0)
+ def nonLocalMember(name: Name): Symbol = findMember(name, LOCAL | BRIDGE, 0, false)
/** The least type instance of given class which is a supertype
* of this type */
@@ -377,7 +377,7 @@ trait Types requires SymbolTable {
}
//todo: use narrow only for modules? (correct? efficiency gain?)
- def findMember(name: Name, excludedFlags: int, requiredFlags: long): Symbol = {
+ def findMember(name: Name, excludedFlags: int, requiredFlags: long, stableOnly: boolean): Symbol = {
if (util.Statistics.enabled) findMemberCount = findMemberCount + 1;
val startTime = if (util.Statistics.enabled) System.currentTimeMillis() else 0l;
@@ -405,6 +405,8 @@ trait Types requires SymbolTable {
checkMalformedSwitch = savedCheckMalformedSwitch;
if (util.Statistics.enabled) findMemberMillis = findMemberMillis + System.currentTimeMillis() - startTime;
return sym
+ } else if (stableOnly) {
+ if (sym.isStable) return sym
} else if (member == NoSymbol) {
member = sym
} else if (members == null) {
@@ -492,7 +494,7 @@ trait Types requires SymbolTable {
// todo see whether we can do without
override def isError: boolean = true;
override def decls: Scope = new ErrorScope(NoSymbol);
- override def findMember(name: Name, excludedFlags: int, requiredFlags: long): Symbol = {
+ override def findMember(name: Name, excludedFlags: int, requiredFlags: long, stableOnly: boolean): Symbol = {
var sym = decls lookup name;
if (sym == NoSymbol) {
sym = NoSymbol.newErrorSymbol(name);
@@ -1493,7 +1495,7 @@ trait Types requires SymbolTable {
if (sym.isModuleClass && !phase.flatClasses) adaptToNewRun(pre, sym.sourceModule).moduleClass;
else if ((pre eq NoPrefix) || (pre eq NoType) || sym.owner.isPackageClass) sym
else {
- var rebind0 = pre.member(sym.name)
+ var rebind0 = pre.findMember(sym.name, BRIDGE, 0, true)
/** The two symbols have the same fully qualified name */
def corresponds(sym1: Symbol, sym2: Symbol): boolean =
sym1.name == sym2.name && (sym1.isPackageClass || corresponds(sym1.owner, sym2.owner))
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index 8e1a9cc7a4..4fb0dbba37 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -113,7 +113,7 @@ abstract class Mixin extends InfoTransform {
val imember = member.overriddenSymbol(mixinClass.toInterface)
if (imember.overridingSymbol(clazz) == NoSymbol &&
atPhase(phase.next)(clazz.info)
- .findMember(member.name, 0, lateDEFERRED).alternatives.contains(imember)) {
+ .findMember(member.name, 0, lateDEFERRED, false).alternatives.contains(imember)) {
val member1 = addMember(
clazz,
member.cloneSymbol(clazz) setPos clazz.pos resetFlag (DEFERRED | lateDEFERRED))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index ead21e71e5..29a83910f1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1334,7 +1334,27 @@ trait Typers requires Analyzer {
}
}
- /** Attribute an identifier consisting of a simple name o ran outer reference.
+ /** does given name name an identifier visible at this point? */
+ def namesSomeIdent(name: Name): boolean = {
+ var cx = context
+ while (cx != NoContext) {
+ val pre = cx.enclClass.prefix
+ val defEntry = cx.scope.lookupEntry(name)
+ if (defEntry != null && defEntry.sym.exists) return true
+ cx = cx.enclClass
+ if ((pre.member(name) filter (
+ sym => sym.exists && context.isAccessible(sym, pre, false))) != NoSymbol) return true
+ cx = cx.outer
+ }
+ var imports = context.imports; // impSym != NoSymbol => it is imported from imports.head
+ while (!imports.isEmpty) {
+ if (imports.head.importedSymbol(name) != NoSymbol) return true
+ imports = imports.tail
+ }
+ false
+ }
+
+ /** Attribute an identifier consisting of a simple name or an outer reference.
* @param tree The tree representing the identifier.
* @param name The name of the identifier.
* Transformations: (1) Prefix class members with this.
@@ -1353,7 +1373,6 @@ trait Typers requires Analyzer {
var cx = context
while (defSym == NoSymbol && cx != NoContext) {
- //if (phase.name == "uncurry") System.out.println("typing " + name + " " + cx.owner + " " + (if (cx.enclClass == null) "null" else cx.enclClass.owner));//DEBUG
pre = cx.enclClass.prefix
defEntry = cx.scope.lookupEntry(name)
if (defEntry != null && defEntry.sym.exists) {
@@ -1500,7 +1519,16 @@ trait Typers requires Analyzer {
case Bind(name, body) =>
var vble = tree.symbol
if (vble == NoSymbol) vble = context.owner.newValue(tree.pos, name)
- if (vble.name != nme.WILDCARD) namer.enterInScope(vble)
+ if (vble.name != nme.WILDCARD) {
+/*
+ if (namesSomeIdent(vble.name))
+ context.unit.warning(tree.pos,
+ "pattern variable "+vble.name+" shadows a value visible in the environment;\n"+
+ "use backquotes `"+vble.name+"` if you mean to match against that value;\n" +
+ "or rename the variable or use an explicit bind "+vble.name+"@_ to avoid this warning.")
+*/
+ namer.enterInScope(vble)
+ }
val body1 = typed(body, mode, pt)
vble.setInfo(if (treeInfo.isSequenceValued(body)) seqType(body1.tpe) else body1.tpe)
copy.Bind(tree, name, body1) setSymbol vble setType body1.tpe; // buraq, was: pt