summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-04-23 15:00:18 +0000
committerMartin Odersky <odersky@gmail.com>2007-04-23 15:00:18 +0000
commitdd225e9a2580d1824be7016cc9428d5aeb7122fa (patch)
tree94244cc79acf0e37f26309cbf7685fdfeb89596f /src/compiler/scala/tools
parenta9cc141f197da8741b395c4e2321c4f8b15e3c0c (diff)
downloadscala-dd225e9a2580d1824be7016cc9428d5aeb7122fa.tar.gz
scala-dd225e9a2580d1824be7016cc9428d5aeb7122fa.tar.bz2
scala-dd225e9a2580d1824be7016cc9428d5aeb7122fa.zip
some optimizations. new closure syntax.
Diffstat (limited to 'src/compiler/scala/tools')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala49
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala15
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Flags.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Scopes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala37
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala55
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala6
10 files changed, 128 insertions, 47 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index a2707969a5..e9f388f1f3 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -391,6 +391,13 @@ trait Parsers {
syntaxError(
pos, "left- and right-associative operators with same precedence may not be mixed", false)
+ def checkNoImplicitParams() = implicitParams match {
+ case vd :: _ =>
+ syntaxError(vd.pos, "unbound wildcard parameter", false)
+ implicitParams = List()
+ case _ =>
+ }
+
def reduceStack(isExpr: boolean, base: List[OpInfo], top0: Tree, prec: int, leftAssoc: boolean): Tree = {
var top = top0
if (opstack != base && precedence(opstack.head.operator) == prec)
@@ -519,7 +526,7 @@ trait Parsers {
}
/** SimpleExpr ::= literal
- * | symbol [ArgumentExprs]
+ * | symbol
* | null
*/
def literal(isPattern: boolean, isNegated: boolean): Tree = {
@@ -556,7 +563,6 @@ trait Parsers {
if (isSymLit) {
atPos(pos) {
var symid = scalaDot(nme.Symbol)
- if (isPattern) { symid = /*convertToTypeId*/(symid) }
val symobj = Apply(symid, List(t))
if (isPattern) symobj else Select(symobj, nme.intern)
}
@@ -818,23 +824,12 @@ trait Parsers {
* (also eats trailing comma if it finds one)
*/
def exprs(): List[Tree] = {
- val savedImplicitParams = implicitParams
- implicitParams = List()
- var first = expr()
- if (!implicitParams.isEmpty) {
- first = Function(implicitParams.reverse, first)
- implicitParams = List()
- }
- val ts = new ListBuffer[Tree] + first
+ val ts = new ListBuffer[Tree] + expr()
while (in.token == COMMA) {
in.nextToken;
if (in.token == RPAREN) return List(makeTupleTerm(ts.toList, false))
ts += expr()
- if (!implicitParams.isEmpty) {
- syntaxError(implicitParams.head.pos, "section outside (...)", false)
- }
}
- implicitParams = savedImplicitParams
ts.toList
}
@@ -843,7 +838,6 @@ trait Parsers {
private final val InTemplate = 2
/** Expr ::= (Bindings | Id) `=>' Expr
- * | PostfixExpr `:' Type
* | Expr1
* ResultExpr ::= (Bindings | Id `:' CompoundType) `=>' Block
* | Expr1
@@ -938,6 +932,7 @@ trait Parsers {
Throw(expr())
}
case DOT =>
+ //todo: deprecate
atPos(in.skipToken) {
if (isIdent) {
makeDotClosure(stripParens(simpleExpr()))
@@ -999,6 +994,8 @@ trait Parsers {
* | InfixExpr Id [nl] InfixExpr
*/
def postfixExpr(): Tree = {
+ var savedImplicitParams = implicitParams
+ implicitParams = List()
val base = opstack
var top = prefixExpr()
while (isIdent) {
@@ -1018,7 +1015,18 @@ trait Parsers {
topinfo.operator.encode).setPos(topinfo.pos)
}
}
- reduceStack(true, base, top, 0, true)
+ var res = reduceStack(true, base, top, 0, true)
+ def isWildcard(t: Tree): boolean = t match {
+ case Ident(name1) if name1 == implicitParams.head.name => true
+ case Typed(t1, _) => isWildcard(t1)
+ case Annotated(t1, _) => isWildcard(t1)
+ case _ => false
+ }
+ if (!implicitParams.isEmpty)
+ if (isWildcard(res)) savedImplicitParams = savedImplicitParams ::: implicitParams
+ else res = Function(implicitParams.reverse, res)
+ implicitParams = savedImplicitParams
+ res
}
/** PrefixExpr ::= [`-' | `+' | `~' | `!' | `&'] SimpleExpr
@@ -1053,7 +1061,7 @@ trait Parsers {
/* SimpleExpr ::= new ClassTemplate
* | BlockExpr
- * | SimpleExpr1
+ * | SimpleExpr1 [`_']
* SimpleExpr1 ::= literal
* | xLiteral
* | Path
@@ -1120,6 +1128,8 @@ trait Parsers {
}
case LPAREN | LBRACE if (canApply) =>
simpleExprRest(atPos(in.currentPos) { Apply(stripParens(t), argumentExprs()) }, true)
+ case USCORE =>
+ atPos(in.skipToken) { Typed(stripParens(t), Function(List(), EmptyTree)) }
case _ =>
t
}
@@ -1399,7 +1409,7 @@ trait Parsers {
else
mods
- private def addMod(mods: Modifiers, mod: int): Modifiers = {
+ private def addMod(mods: Modifiers, mod: long): Modifiers = {
if (mods hasFlag mod) syntaxError(in.currentPos, "repeated modifier", false)
in.nextToken
mods | mod
@@ -2244,6 +2254,7 @@ trait Parsers {
}
if (in.token != RBRACE && in.token != EOF) acceptStatSep()
}
+ checkNoImplicitParams()
(self, stats.toList)
}
@@ -2301,6 +2312,7 @@ trait Parsers {
syntaxErrorOrIncomplete("illegal start of statement", true)
}
}
+ checkNoImplicitParams()
stats.toList
}
@@ -2329,6 +2341,7 @@ trait Parsers {
} else {
ts ++= topStatSeq()
}
+ assert(implicitParams.isEmpty)
val stats = ts.toList
stats match {
case List(stat @ PackageDef(_, _)) => stat
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index b0cae8edb7..ecca05b6c4 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -72,7 +72,20 @@ trait ParallelMatching requires (transform.ExplicitOuter with PatternMatchers wi
pat match {
case Literal(Constant(null)) if !(patternType =:= pat.tpe) => //special case for constant null pattern
(ms,ss,(j,pat)::rs)
- case _ if (pat.symbol ne null) && (patternType =:= singleType(pat.symbol.tpe.prefix, pat.symbol))=>
+ case _ if (pat.symbol ne null) && /*
+ Martin: the following causes a lot of Error's in rebind/singletonType
+ these errors are masked by including the two tests below.
+ However, if you uncomment them you will get a bug in genLoad:
+ ^
+ [locker] java.lang.AssertionError: assertion failed: Trying to access the this of another class: tree.symbol = class TreeBrowsers, ctx.clazz.symbol = object TreeBrowsers$TreeInfo compilation unit:TreeBrowsers.scala
+ [locker] at scala.Predef$.assert(Predef.scala:90)
+ [locker] at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$backend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:809)
+ [locker] at scala.tools.nsc.backend.icode.GenICode$ICodePhase.genLoadQualifier(GenICode.scala:996)
+ [locker] at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$backend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:785)
+
+ (pat.symbol != NoSymbol) && pat.symbol.tpe.prefix.isStable &&
+ */
+ (patternType =:= singleType(pat.symbol.tpe.prefix, pat.symbol)) =>
(EmptyTree::ms, (j,dummies)::ss, rs); // matching an object
case _ if (pat.tpe <:< patternType) =>
({if(pat.tpe =:= patternType) EmptyTree else pat}::ms, (j,subpatterns(pat))::ss, rs); // subsumed (same or more specific) pattern;
diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
index c160818c14..601262b217 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
@@ -200,7 +200,7 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes with P
case CantHandleGuard => // fall back (actually already fell back before)
case e =>
- if(settings.debug.value) {
+ if (settings.debug.value) {
e.printStackTrace()
Console.println("****")
Console.println("**** falling back, cause " + e.getMessage)
diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala
index ebe587acae..4c5f227a21 100644
--- a/src/compiler/scala/tools/nsc/symtab/Flags.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala
@@ -57,7 +57,8 @@ object Flags extends Enumeration {
final val PARAMACCESSOR = 0x20000000 // for value definitions: is an access method
// for a final val parameter
// for parameters: is a val parameter
- final val MODULEVAR = 0x40000000
+ final val MODULEVAR = 0x40000000 // for term symbols: is the variable caching a module value
+ final val MONOMORPHIC = 0x40000000 // for type symbols: does not have type parameters
final val IS_ERROR = 0x100000000L // symbol is an error symbol
final val OVERLOADED = 0x200000000L // symbol is overloaded
diff --git a/src/compiler/scala/tools/nsc/symtab/Scopes.scala b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
index 33d8407c16..dfc5f6dd54 100644
--- a/src/compiler/scala/tools/nsc/symtab/Scopes.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
@@ -220,7 +220,7 @@ trait Scopes {
*/
def lookupEntry(name: Name): ScopeEntry = {
var e: ScopeEntry = null
- if (false & (hashtable ne null)) {
+ if (hashtable ne null) {
e = hashtable(name.start & HASHMASK)
while ((e ne null) && e.sym.name != name) e = e.tail;
} else {
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index b613104ece..2e20ecc2e1 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -172,6 +172,9 @@ trait Symbols {
def isTerm = false //to be overridden
def isType = false //to be overridden
def isClass = false //to be overridden
+ def isTypeMember = false //to be overridden
+ def isAliasType = false //to be overridden
+ def isAbstractType = false //to be overridden
final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA))
final def isVariable = isTerm && hasFlag(MUTABLE) && !isMethod
@@ -194,12 +197,10 @@ trait Symbols {
final def isPackage = isModule && hasFlag(PACKAGE)
final def isThisSym = isTerm && owner.thisSym == this
final def isThisSkolem = isTerm && deSkolemize != this
+ final def isMonomorphicType = isType && hasFlag(MONOMORPHIC)
final def isError = hasFlag(IS_ERROR)
final def isErroneous = isError || isInitialized && tpe.isErroneous
final def isTrait = isClass & hasFlag(TRAIT)
- final def isTypeMember = isType && !isClass
- final def isAliasType = isType && !isClass && !hasFlag(DEFERRED)
- final def isAbstractType = isType && !isClass && hasFlag(DEFERRED)
final def isTypeParameterOrSkolem = isType && hasFlag(PARAM)
final def isTypeParameter = isTypeParameterOrSkolem && deSkolemize == this
final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
@@ -536,15 +537,15 @@ trait Symbols {
def tpeHK = if(isType) typeConstructor else tpe // @M! used in memberType
/** The type parameters of this symbol */
- def unsafeTypeParams: List[Symbol] = rawInfo.typeParams
+ def unsafeTypeParams: List[Symbol] =
+ if (isMonomorphicType) List() else rawInfo.typeParams
/*
val limit = phaseId(validTo)
(if (limit < phase.id) infos.info else rawInfo).typeParams
*/
- def typeParams: List[Symbol] = {
- rawInfo.load(this); rawInfo.typeParams
- }
+ def typeParams: List[Symbol] =
+ if (isMonomorphicType) List() else { rawInfo.load(this); rawInfo.typeParams }
def getAttributes(clazz: Symbol): List[AnnotationInfo[Constant]] =
attributes.filter(.atp.symbol.isNonBottomSubClass(clazz))
@@ -1128,12 +1129,17 @@ trait Symbols {
*/
class TypeSymbol(initOwner: Symbol, initPos: Position, initName: Name)
extends Symbol(initOwner, initPos, initName) {
- override def isType = true
privateWithin = NoSymbol
private var tyconCache: Type = null
private var tyconRunId = NoRunId
private var tpeCache: Type = _
private var tpePeriod = NoPeriod
+
+ override def isType = true
+ override def isTypeMember = true
+ override def isAbstractType = hasFlag(DEFERRED)
+ override def isAliasType = !hasFlag(DEFERRED)
+
override def tpe: Type = {
if (tpeCache eq NoType) throw CyclicReference(this, typeConstructor)
if (tpePeriod != currentPeriod) {
@@ -1165,13 +1171,9 @@ trait Symbols {
override def setInfo(tp: Type): this.type = {
tpePeriod = NoPeriod
tyconCache = null
- tp match { //debug
- case TypeRef(_, sym, _) =>
- assert(sym != this, this)
- case ClassInfoType(parents, _, _) =>
- for(p <- parents) assert(p.symbol != this, owner)
- case _ =>
- }
+ if (tp.isComplete)
+ if (tp.isInstanceOf[PolyType]) resetFlag(MONOMORPHIC)
+ else if (!tp.isInstanceOf[AnnotatedType]) setFlag(MONOMORPHIC)
super.setInfo(tp)
this
}
@@ -1222,7 +1224,12 @@ trait Symbols {
else super.isFromClassFile
}
private var thissym: Symbol = this
+
override def isClass: boolean = true
+ override def isTypeMember = false
+ override def isAbstractType = false
+ override def isAliasType = false
+
override def reset(completer: Type): unit = {
super.reset(completer)
thissym = this
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 47f0ed2293..c4cde60bb8 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -471,7 +471,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
var tree1 = try {
super.typed1(adaptMember(tree), mode, pt)
} catch {
- case ex: Throwable =>
+ case ex: Exception =>
//if (settings.debug.value)
Console.println("exception when typing " + tree);
throw ex
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index f015344395..b8abc66fa9 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -665,8 +665,8 @@ abstract class Mixin extends InfoTransform {
atPhase(phase.next)(postTransform(tree1))
} catch {
case ex: Throwable =>
- Console.println("exception when traversing " + tree)
- throw ex
+ if (settings.debug.value) Console.println("exception when traversing " + tree)
+ throw ex
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index af34a088df..4624782479 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -102,10 +102,25 @@ trait Infer requires Analyzer {
* @param tp ...
* @return ...
*/
- def isFullyDefined(tp: Type): boolean = try {
- instantiate(tp); true
- } catch {
- case ex: NoInstance => false
+ def isFullyDefined(tp: Type): boolean = tp match {
+ case WildcardType | NoType =>
+ false
+ case NoPrefix | ThisType(_) | ConstantType(_) =>
+ true
+ case TypeRef(pre, sym, args) =>
+ isFullyDefined(pre) && (args.isEmpty || (args forall isFullyDefined))
+ case SingleType(pre, sym) =>
+ isFullyDefined(pre)
+ case RefinedType(ts, decls) =>
+ ts forall isFullyDefined
+ case TypeVar(origin, constr) if (constr.inst == NoType) =>
+ false
+ case _ =>
+ try {
+ instantiate(tp); true
+ } catch {
+ case ex: NoInstance => false
+ }
}
/** Do type arguments <code>targs</code> conform to formal parameters
@@ -368,6 +383,38 @@ trait Infer requires Analyzer {
}
}
+ def isPlausiblyCompatible(tp: Type, pt: Type): boolean = tp match {
+ case PolyType(_, restp) =>
+ isPlausiblyCompatible(restp, pt)
+ case MethodType(formals, restp) =>
+ pt.normalize match {
+ case TypeRef(pre, sym, args) =>
+ !sym.isClass || {
+ val l = args.length - 1
+ l == formals.length &&
+ sym == FunctionClass(l) &&
+ List.forall2(args, formals) (isPlausiblySubType) &&
+ isPlausiblySubType(restp, args.last)
+ }
+ case _ =>
+ true
+ }
+ case _ =>
+ true
+ }
+
+ def isPlausiblySubType(tp1: Type, tp2: Type): boolean = tp1.normalize match {
+ case TypeRef(_, sym1, _) =>
+ !sym1.isClass || {
+ tp2.normalize match {
+ case TypeRef(_, sym2, _) => !sym2.isClass || (sym1 isSubClass sym2)
+ case _ => true
+ }
+ }
+ case _ =>
+ true
+ }
+
def isCompatible(tp: Type, pt: Type): boolean = {
val tp1 = normalize(tp)
(tp1 <:< pt) || isCoercible(tp, pt)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 8a03ae3a44..de86bc9948 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -642,7 +642,7 @@ trait Typers requires Analyzer {
inferConstructorInstance(tree1, clazz.typeParams, widen(pt))
} catch {
case tpe : TypeError => throw tpe
- case t : Throwable =>
+ case t : Exception
logError("CONTEXT: " + (tree.pos).dbgString, t)
throw t
}
@@ -2624,7 +2624,7 @@ trait Typers requires Analyzer {
//Console.println("caught "+ex+" in typed");//DEBUG
reportTypeError(tree.pos, ex)
setError(tree)
- case ex: Throwable =>
+ case ex: Exception
// if (settings.debug.value) // @M causes cyclic reference error
// Console.println("exception when typing "+tree+", pt = "+pt)
if ((context ne null) && (context.unit ne null) &&
@@ -2744,7 +2744,7 @@ trait Typers requires Analyzer {
case TypeRef(pre, sym, _) => sym.isPackageClass || sym.isModuleClass && isStable(pre)
case _ => tp.isStable
}
- if (isCompatible(depoly(info.tpe), pt) && isStable(info.pre)) {
+ if (isPlausiblyCompatible(info.tpe, pt) && isCompatible(depoly(info.tpe), pt) && isStable(info.pre)) {
val tree = atPos(pos) {
if (info.pre == NoPrefix/*isLocal*/) Ident(info.name)
else Select(gen.mkAttributedQualifier(info.pre), info.name)