diff options
author | Martin Odersky <odersky@gmail.com> | 2008-09-28 07:56:50 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2008-09-28 07:56:50 +0000 |
commit | 184383a519ab637530899ffd446a30c919e4a991 (patch) | |
tree | 9ca2646d5bb8404b17273ec2a55e1ed3ce87663a | |
parent | e20362771cc395d6894658de101881b7ae6295b4 (diff) | |
download | scala-184383a519ab637530899ffd446a30c919e4a991.tar.gz scala-184383a519ab637530899ffd446a30c919e4a991.tar.bz2 scala-184383a519ab637530899ffd446a30c919e4a991.zip |
Fixed #1263, and some cosmetic changes
7 files changed, 103 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 734921eac6..cc9c748d88 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -301,6 +301,8 @@ abstract class TreeGen { def mkForwarder(target: Tree, vparamss: List[List[Symbol]]) = (target /: vparamss)((fn, vparams) => Apply(fn, vparams map paramToArg)) + /** Used in situations where you need to access value of an expression several times + */ def evalOnce(expr: Tree, owner: Symbol, unit: CompilationUnit)(within: (() => Tree) => Tree): Tree = if (treeInfo.isPureExpr(expr)) { within(() => expr); diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index f6c2bfd40f..929f623c2d 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -45,9 +45,14 @@ trait Trees { // modifiers -------------------------------------------------------- + /** @param privateWithin the qualifier for a private (a type name) + * or nme.EMPTY.toTypeName, if none is given. + * @param annotations the annotations for the definition + * (i.e things starting with @) + */ case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Annotation]) { - def isCovariant = hasFlag(COVARIANT ) - def isContravariant = hasFlag(CONTRAVARIANT) + def isCovariant = hasFlag(COVARIANT ) // marked with `+' + def isContravariant = hasFlag(CONTRAVARIANT) // marked with `-' def isPrivate = hasFlag(PRIVATE ) def isProtected = hasFlag(PROTECTED) def isVariable = hasFlag(MUTABLE ) @@ -101,7 +106,10 @@ trait Trees { def pos = rawpos - var tpe: Type = _ + private[this] var rawtpe: Type = _ + + def tpe = rawtpe + def tpe_=(t: Type) = rawtpe = t def setPos(pos: Position): this.type = { rawpos = pos; this } def setType(tp: Type): this.type = { @@ -285,7 +293,9 @@ trait Trees { /** The empty tree */ case object EmptyTree extends TermTree { - tpe = NoType + super.tpe_=(NoType) + override def tpe_=(t: Type) = + if (t != NoType) throw new Error("tpe_=("+t+") inapplicable for <empty>") override def isEmpty = true } @@ -327,7 +337,6 @@ trait Trees { */ def ClassDef(sym: Symbol, impl: Template): ClassDef = posAssigner.atPos(sym.pos) { - var flags = sym.flags ClassDef(Modifiers(sym.flags), sym.name, sym.typeParams map TypeDef, @@ -500,7 +509,7 @@ trait Trees { case class Import(expr: Tree, selectors: List[(Name, Name)]) extends SymTree // The symbol of an Import is an import symbol @see Symbol.newImport - // It's used primarily as a marker to check thta the import has been typechecked. + // It's used primarily as a marker to check that the import has been typechecked. /** Annotation application (constructor arguments + name-value pairs) */ case class Annotation(constr: Tree, elements: List[Tree]) @@ -537,19 +546,32 @@ trait Trees { // System.err.println("TEMPLATE: " + parents) } - /** - * @param parents ... - * @param vparamss ... - * @param argss ... - * @param body ... - * @return ... + /** Generates a template with constructor corresponding to + * + * constrmods (vparams1_) ... (vparams_n) preSuper { presupers } + * extends superclass(args_1) ... (args_n) with mixins { self => body } + * + * This gets translated to + * + * extends superclass with mixins { self => + * presupers' // presupers without rhs + * vparamss // abstract fields corresponding to value parameters + * def <init>(vparamss) { + * presupers + * super.<init>(args) + * } + * body + * } */ def Template(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree]): Template = { - /** Add constructor to template */ + /* Add constructor to template */ + + // create parameters for <init> var vparamss1 = vparamss map (vps => vps.map { vd => - val ret = ValDef(Modifiers(vd.mods.flags & IMPLICIT | PARAM) withAnnotations vd.mods.annotations, - vd.name, vd.tpt.duplicate, EmptyTree).setPos(vd.pos) + val ret = ValDef( + Modifiers(vd.mods.flags & IMPLICIT | PARAM) withAnnotations vd.mods.annotations, + vd.name, vd.tpt.duplicate, EmptyTree).setPos(vd.pos) if (inIDE && vd.symbol != NoSymbol) ret.symbol = vd.symbol ret @@ -568,6 +590,7 @@ trait Trees { else List( DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(lvdefs, Literal(())))) } else { + // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section if (vparamss1.isEmpty || !vparamss1.head.isEmpty && (vparamss1.head.head.mods.flags & IMPLICIT) != 0) vparamss1 = List() :: vparamss1; @@ -843,25 +866,39 @@ trait Trees { case PackageDef(name, stats) => // package name { stats } case ClassDef(mods, name, tparams, impl) => - // mods class name[tparams] impl + // mods class name [tparams] impl where impl = extends parents { defs } case ModuleDef(mods, name, impl) => (eliminated by refcheck) // mods object name impl where impl = extends parents { defs } case ValDef(mods, name, tpt, rhs) => // mods val name: tpt = rhs + // note missing type information is expressed by tpt = TypeTree() case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - // mods def name[tparams](vparams): tpt = rhs + // mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs + // note missing type information is expressed by tpt = TypeTree() case TypeDef(mods, name, tparams, rhs) => (eliminated by erasure) // mods type name[tparams] = rhs + // mods type name[tparams] >: lo <: hi, where lo, hi are in a TypeBoundsTree, + and DEFERRED is set in mods case LabelDef(name, params, rhs) => // used for tailcalls and like + // while/do are desugared to label defs as follows: + // while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ()) + // do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ()) case Import(expr, selectors) => (eliminated by typecheck) // import expr.{selectors} + // Selectors are a list of pairs of names (from, to). + // The last (and maybe only name) may be a nme.WILDCARD + // for instance + // import qual.{x, y => z, _} would be represented as + // Import(qual, List(("x", "x"), ("y", "z"), (WILDCARD, null))) case Annotation(constr, elements) => - // @constr(elements) where constr = tp(args), elements = { val x1 = c1, ..., val xn = cn } + // @constr(elements) where constr = tp(args), (an instance of Apply) + // elements = { val x1 = c1, ..., val xn = cn } case DocDef(comment, definition) => (eliminated by typecheck) // /** comment */ definition case Template(parents, self, body) => // extends parents { self => body } + // if self is missing it is represented as emptyValDef case Block(stats, expr) => // { stats; expr } case CaseDef(pat, guard, body) => (eliminated by transmatch/explicitouter) @@ -878,6 +915,11 @@ trait Trees { // used for unapply's case ArrayValue(elemtpt, trees) => (introduced by uncurry) // used to pass arguments to vararg arguments + // for instance, printf("%s%d", foo, 42) is translated to after uncurry to: + // Apply( + // Ident("printf"), + // Literal("%s%d"), + // ArrayValue(<Any>, List(Ident("foo"), Literal(42)))) case Function(vparams, body) => (eliminated by lambdaLift) // vparams => body where vparams:List[ValDef] case Assign(lhs, rhs) => @@ -893,27 +935,30 @@ trait Trees { case Throw(expr) => // throw expr case New(tpt) => - // new tpt always in the context: new tpt.<init>[targs](args) + // new tpt always in the context: (new tpt).<init>[targs](args) case Typed(expr, tpt) => (eliminated by erasure) // expr: tpt case TypeApply(fun, args) => // fun[args] case Apply(fun, args) => // fun(args) + // for instance fun[targs](args) is expressed as Apply(TypeApply(fun, targs), args) case ApplyDynamic(qual, args) (introduced by erasure, eliminated by cleanup) // fun(args) case Super(qual, mix) => - // qual.super[mix] + // qual.super[mix] if qual and/or mix is empty, ther are nme.EMPTY.toTypeName case This(qual) => // qual.this case Select(qualifier, selector) => // qualifier.selector case Ident(name) => // name + // note: type checker converts idents that refer to enclosing fields or methods + // to selects; name ==> this.name case Literal(value) => // value case TypeTree() => (introduced by refcheck) - // a type that's not written out, but given in the attribute + // a type that's not written out, but given in the tpe attribute case Annotated(annot, arg) => (eliminated by typer) // arg @annot for types, arg: @annot for exprs case SingletonTypeTree(ref) => (eliminated by uncurry) @@ -924,9 +969,10 @@ trait Trees { // parent1 with ... with parentN { refinement } case AppliedTypeTree(tpt, args) => (eliminated by uncurry) // tpt[args] - case TypeBoundsTree(lo, hi) => (eliminated by uncurry) + case TypeBoundsTree(lo, hi) => (eliminated by uncurry) // >: lo <: hi - case ExistentialTypeTree(tpt, whereClauses) => + case ExistentialTypeTree(tpt, whereClauses) => (eliminated by uncurry) + // tpt forSome { whereClauses } */ diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 99b8089b8b..1cd4ee8820 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -3414,6 +3414,17 @@ A type's typeSymbol should never be inspected directly. case _ => tp.normalize } + /* + todo: change to: + def normalizePlus(tp: Type) = tp match { + case TypeRef(pre, sym, List()) => + if (!sym.isInitialized) sym.rawInfo.load(sym) + if (sym.hasFlag(JAVA) && !sym.typeParams.isEmpty) rawToExistential(tp) + else tp.normalize + case _ => tp.normalize + } + */ + private def isSameType0(tp1: Type, tp2: Type): Boolean = ((tp1, tp2) match { case (ErrorType, _) => true diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index c52eda360a..5a74c9087c 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -764,8 +764,7 @@ abstract class ClassfileParser { val t = pool.getType(index) val n = pool.getName(in.nextChar) val s = t.typeSymbol.linkedModuleOfClass.info.decls.lookup(n) - //assert (s != NoSymbol, "while processing " + in.file + ": " + t + "." + n + ": " + t.decls) - assert(s != NoSymbol, t) // avoid string concatenation! + assert(s != NoSymbol, t) Constant(s) case ARRAY_TAG => val arr = new ArrayBuffer[Constant]() diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 23203bd848..48a096a78b 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -177,7 +177,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { def classSig: String = "L"+atPhase(currentRun.icodePhase)(sym.fullNameString).replace('.', '/') def classSigSuffix: String = - "."+atPhase(currentRun.icodePhase)(sym.name) + "."+sym.name if (sym == ArrayClass) ARRAY_TAG.toString+(args map jsig).mkString else if (sym.isTypeParameterOrSkolem) @@ -228,7 +228,10 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { jsig(erasure(tp)) } } - if (needsJavaSig(sym.info)) Some(jsig2(true, List(), sym.info)) + if (needsJavaSig(sym.info)) { + //println("Java sig of "+sym+" is "+jsig2(true, List(), sym.info))//DEBUG + Some(jsig2(true, List(), sym.info)) + } else None } diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 582baba778..bb552de8b9 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -256,7 +256,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { // ------ Transforming anonymous functions and by-name-arguments ---------------- - /** Undo eta expansion for parameterless and nullaray methods */ + /** Undo eta expansion for parameterless and nullary methods */ def deEta(fun: Function): Tree = fun match { case Function(List(), Apply(expr, List())) if treeInfo.isPureExpr(expr) => if (expr.hasSymbol && expr.symbol.hasFlag(LAZY)) @@ -316,6 +316,16 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { def applyMethodDef(body: Tree) = DefDef(Modifiers(FINAL), nme.apply, List(), List(fun.vparams), TypeTree(restpe), body) .setSymbol(applyMethod) +/* + def toStringMethodDefs = fun match { + case etaExpansion(_, fn, _) if (fn.hasSymbol) => + List( + DefDef(Modifiers(FINAL | OVERRIDE), nme.toString_, List(), List(List()), TypeTree(StringClass.tpe), + Literal(fn.symbol.name))) + case _ => + List() + } +*/ def mkUnchecked(tree: Tree) = tree match { case Match(selector, cases) => atPos(tree.pos) { @@ -326,7 +336,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { case _ => tree } - val members = + val members = { if (fun.tpe.typeSymbol == PartialFunctionClass) { val isDefinedAtMethod = anonClass.newMethod(fun.pos, nme.isDefinedAt) .setFlag(FINAL).setInfo(MethodType(formals, BooleanClass.tpe)) @@ -350,6 +360,7 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { } else { List(applyMethodDef(fun.body)) } + } /* ::: toStringMethodDefs */ localTyper.typed { atPos(fun.pos) { Block( diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 860e83666e..7172a0a2d0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -372,6 +372,8 @@ abstract class RefChecks extends InfoTransform { unit.error(clazz.pos, "illegal inheritance;\n " + clazz + " inherits different type instances of " + baseClass + ":\n" + tp1 + " and " + tp2); + explainTypes(tp1, tp2) + explainTypes(tp2, tp1) } } } |