diff options
author | Martin Odersky <odersky@gmail.com> | 2007-04-23 15:00:18 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2007-04-23 15:00:18 +0000 |
commit | dd225e9a2580d1824be7016cc9428d5aeb7122fa (patch) | |
tree | 94244cc79acf0e37f26309cbf7685fdfeb89596f | |
parent | a9cc141f197da8741b395c4e2321c4f8b15e3c0c (diff) | |
download | scala-dd225e9a2580d1824be7016cc9428d5aeb7122fa.tar.gz scala-dd225e9a2580d1824be7016cc9428d5aeb7122fa.tar.bz2 scala-dd225e9a2580d1824be7016cc9428d5aeb7122fa.zip |
some optimizations. new closure syntax.
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) |