From f9340a7c068db439d14c5039355f9f3f60ccd49d Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 21 May 2008 12:33:42 +0000 Subject: Inner classes are now kept as such when compili... Inner classes are now kept as such when compiling to .NET. --- src/build/msil.xml | 3 +- src/compiler/scala/tools/nsc/Global.scala | 10 +++--- .../scala/tools/nsc/backend/icode/GenICode.scala | 5 +-- .../scala/tools/nsc/backend/msil/GenMSIL.scala | 36 +++++++++++++++------- src/compiler/scala/tools/nsc/transform/Mixin.scala | 11 +++++-- src/dotnet-library/README | 8 ++--- 6 files changed, 48 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/build/msil.xml b/src/build/msil.xml index 28adb5a4f4..3040870ad5 100644 --- a/src/build/msil.xml +++ b/src/build/msil.xml @@ -134,7 +134,8 @@ MSIL BUILD srcdir="${build-msil-src.dir}" destdir="${build-msil.dir}/library" target="msil" - assemname="predef.msil" assemrefs="${lib.dir}"> + assemname="predef.msil" + assemrefs="${lib.dir}"> diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 454be7a667..4d00907934 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -397,9 +397,9 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable analyzer.typerFactory: SubComponent, // consistency check after refchecks would fail. superAccessors, // add super accessors pickler, // serialize symbol tables - refchecks // perform reference and override checking, translate nested objects + refchecks // perform reference and override checking, translate nested objects ) ::: ( - if (forJVM) List(liftcode) else List() // generate reified trees + if (forJVM) List(liftcode) else List() // generate reified trees ) ::: List( uncurry, // uncurry, translate function values to anonymous classes tailCalls, // replace tail calls by jumps @@ -409,8 +409,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable lazyVals, lambdaLift, // move nested functions to top level // detach, - constructors, // move field definitions into constructors - flatten, // get rid of inner classes + constructors // move field definitions into constructors + ) ::: ( + if (forMSIL) List() else List(flatten) // get rid of inner classes + ) ::: List( mixer, // do mixin composition cleanup, // some platform-specific cleanups diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index d975432bd2..7ae791566b 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -82,12 +82,13 @@ abstract class GenICode extends SubComponent { case ClassDef(mods, name, _, impl) => log("Generating class: " + tree.symbol.fullNameString) + val outerClass = ctx.clazz ctx setClass (new IClass(tree.symbol) setCompilationUnit unit) addClassFields(ctx, tree.symbol); classes += (tree.symbol -> ctx.clazz) unit.icode += ctx.clazz - gen(impl, ctx) - ctx setClass null + gen(impl, ctx) + ctx setClass outerClass // !! modules should be eliminated by refcheck... or not? case ModuleDef(mods, name, impl) => diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala index a4b5a84d5d..8ed5871a95 100644 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala @@ -1999,9 +1999,8 @@ abstract class GenMSIL extends SubComponent { } def createTypeBuilder(iclass: IClass) { - def getMsilType(tpe: Type): MsilType = { - val sym = tpe.typeSymbol - types.get(sym.asInstanceOf[clrTypes.global.Symbol]) match { + def msilTypeFromSym(sym: Symbol): MsilType = { + types.get(sym.asInstanceOf[clrTypes.global.Symbol]) match { case Some(mtype) => mtype case None => createTypeBuilder(classes(sym)); types(sym.asInstanceOf[clrTypes.global.Symbol]) } @@ -2015,11 +2014,12 @@ abstract class GenMSIL extends SubComponent { if (sym.info.parents.isEmpty) List(definitions.ObjectClass.tpe) else sym.info.parents.removeDuplicates - val superType = if (isInterface(sym)) null else getMsilType(parents.head) + val superType = if (isInterface(sym)) null else msilTypeFromSym(parents.head.typeSymbol) if (settings.debug.value) log("super type: " + parents(0).typeSymbol + ", msil type: " + superType) - val interfaces: Array[MsilType] = parents.tail.map(getMsilType).toArray + val interfaces: Array[MsilType] = + parents.tail.map(p => msilTypeFromSym(p.typeSymbol)).toArray if (parents.length > 1) { if (settings.debug.value){ log("interfaces:") @@ -2029,10 +2029,16 @@ abstract class GenMSIL extends SubComponent { } } - //TODO here: if the class is not top-level, use DefineNestedType? - val tBuilder = - mmodule.DefineType(msilName(sym), msilTypeFlags(sym), superType, interfaces) - mapType(sym, tBuilder) + if (sym.isNestedClass) { + val ownerT = msilTypeFromSym(sym.owner).asInstanceOf[TypeBuilder] + val tBuilder = + ownerT.DefineNestedType(msilName(sym), msilTypeFlags(sym), superType, interfaces) + mapType(sym, tBuilder) + } else { + val tBuilder = + mmodule.DefineType(msilName(sym), msilTypeFlags(sym), superType, interfaces) + mapType(sym, tBuilder) + } } // createTypeBuilder def createClassMembers(iclass: IClass) { @@ -2095,7 +2101,7 @@ abstract class GenMSIL extends SubComponent { } } - if (isStaticModule(iclass.symbol)){ + if (isStaticModule(iclass.symbol)) { addModuleInstanceField(iclass.symbol) notInitializedModules += iclass.symbol addStaticInit(iclass.symbol) @@ -2108,8 +2114,13 @@ abstract class GenMSIL extends SubComponent { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass } + // if the module is lifted it does not need to be initialized in + // its static constructor, and the MODULE$ field is not required. + // the outer class will care about it. private def isStaticModule(sym: Symbol): Boolean = { - sym.isModuleClass && !sym.isImplClass && !sym.hasFlag(Flags.LIFTED) + // .net inner classes: removed '!sym.hasFlag(Flags.LIFTED)', added + // 'sym.isStatic'. -> no longer compatible without skipping flatten! + sym.isModuleClass && sym.isStatic && !sym.isImplClass } private def isCloneable(sym: Symbol): Boolean = { @@ -2169,6 +2180,9 @@ abstract class GenMSIL extends SubComponent { val instanceConstructor = constructors(sym.primaryConstructor.asInstanceOf[clrTypes.global.Symbol]) + // there are no constructor parameters. assuming the constructor takes no parameter + // is fine: we call (in the static constructor) the constructor of the module class, + // which takes no arguments - an object definition cannot take constructor arguments. sicode.Emit(OpCodes.Newobj, instanceConstructor) // the stsfld is done in the instance constructor, just after the super call. sicode.Emit(OpCodes.Pop) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index a0b66a6644..21b12f7e9d 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -359,7 +359,7 @@ abstract class Mixin extends InfoTransform { private var enclInterface: Symbol = _ /** The first transform; called in a pre-order traversal at phase mixin - * (that is, every node is processed before its children. + * (that is, every node is processed before its children). * What transform does: * - For every non-trait class, add all mixed in members to the class info. * - For every trait, add all late interface members to the class info @@ -635,7 +635,7 @@ abstract class Mixin extends InfoTransform { mkLazyDef(clazz, Apply(staticRef(initializer(sym)), List(gen.mkAttributedThis(clazz))), Literal(()), offset) else { val assign = atPos(sym.pos) { - Assign(Select(This(sym.accessed.owner), sym.accessed) /*gen.mkAttributedRef(sym.accessed)*/, + Assign(Select(This(sym.accessed.owner), sym.accessed) /*gen.mkAttributedRef(sym.accessed)*/ , Apply(staticRef(initializer(sym)), gen.mkAttributedThis(clazz) :: Nil)) } mkLazyDef(clazz, assign, Select(This(clazz), sym.accessed), offset) @@ -805,8 +805,13 @@ abstract class Mixin extends InfoTransform { */ override def transform(tree: Tree): Tree = { try { //debug + val outerTyper = localTyper val tree1 = super.transform(preTransform(tree)) - atPhase(phase.next)(postTransform(tree1)) + val res = atPhase(phase.next)(postTransform(tree1)) + // needed when not flattening inner classes. parts after an + // inner class will otherwise be typechecked with a wrong scope + localTyper = outerTyper + res } catch { case ex: Throwable => if (settings.debug.value) Console.println("exception when traversing " + tree) diff --git a/src/dotnet-library/README b/src/dotnet-library/README index 7514508453..4461aa141d 100644 --- a/src/dotnet-library/README +++ b/src/dotnet-library/README @@ -1,5 +1,5 @@ INFO: The dotnet-library tree has been synchronized with -revision 12880 of src/library on $Date$. +revision 15115 of src/library on $Date$. IMPORTANT: Never, never, never, ever add/remove/edit files in the dotnet-library @@ -13,11 +13,11 @@ of the tree. Or from the second line of this document. But you should always check to see if it is consistent with svn log messages. -koko:~/scala/src/dotnet-library>svn log -r 12367 +lamppc26:trunk luc$ svn log -r 15115 ------------------------------------------------------------------------ -r12367 | mihaylov | 2007-07-19 23:11:21 +0200 (Thu, 19 Jul 2007) | 1 line +r15115 | rytz | 2008-05-20 16:57:39 +0200 (Tue, 20 May 2008) | 1 line -Synced dotnet-library/ with rev 12365 +Synced src/dotnet-library with rev 15086 of src/library ------------------------------------------------------------------------ -- cgit v1.2.3