mixin.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 818 行 · 第 1/3 页
SCALA
818 行
/* NSC -- new Scala compiler * Copyright 2005-2007 LAMP/EPFL * @author Martin Odersky */// $Id: Mixin.scala 14106 2008-02-22 13:24:21Z odersky $package scala.tools.nsc.transformimport symtab._import Flags._import scala.collection.mutable.ListBufferimport scala.tools.nsc.util.{Position,NoPosition}import scala.collection.mutable.HashMapabstract class Mixin extends InfoTransform { import global._ import definitions._ import posAssigner.atPos /** The name of the phase: */ val phaseName: String = "mixin" /** The phase might set the fiollowing new flags: */ override def phaseNewFlags: Long = lateMODULE | notABSTRACT /** This map contains a binding (class -> info) if * the class with this info at phase mixinPhase has been treated for mixin composition */ private val treatedClassInfos = collection.mutable.Map[Symbol, Type]()// --------- helper functions ----------------------------------------------- /** A member of a trait is implemented statically if its implementation after the * mixin transform is in the static implementation module. To be statically * implemented, a member must be a method that belonged to the trait's implementation class * before (e.g. it is not abstract). Not statically implemented are * - non-private modules: these are implemented directly in the mixin composition class * (private modules, on the other hand, are implemented statically, but their * module variable is not. all such private modules are lifted, because * non-lifted private modules have been eliminated in ExplicitOuter) * - field accessors and superaccessors, except for lazy value accessors which become initializer * methods in the impl class (because they can have arbitrary initializers) */ private def isImplementedStatically(sym: Symbol) = sym.owner.isImplClass && sym.isMethod && (!sym.isModule || sym.hasFlag(PRIVATE | LIFTED)) && (!(sym hasFlag (ACCESSOR | SUPERACCESSOR)) || sym.hasFlag(LAZY)) /** A member of a trait is static only if it belongs only to the * implementation class, not the interface, and it is implemented * statically. */ private def isStaticOnly(sym: Symbol) = isImplementedStatically(sym) && sym.isImplOnly /** A member of a trait is forwarded if it is implemented statically and it * is also visible in the trait's interface. In that case, a forwarder to * the member's static implementation will be added to the class that * inherits the trait. */ private def isForwarded(sym: Symbol) = isImplementedStatically(sym) && !sym.isImplOnly /** Maps the type of an implementation class to its interface; * maps all other types to themselves. */ private def toInterface(tp: Type): Type = atPhase(currentRun.mixinPhase)(tp.typeSymbol.toInterface).tpe /** Maps all parts of this type that refer to implementation classes to * their corresponding interfaces. */ private val toInterfaceMap = new TypeMap { def apply(tp: Type): Type = mapOver( tp match { case TypeRef(pre, sym, args) if (sym.isImplClass) => typeRef(pre, atPhase(currentRun.mixinPhase)(sym.toInterface), args) case _ => tp }) } /** The implementation class corresponding to a currently compiled interface. * todo: try to use Symbol.implClass instead? */ private def implClass(iface: Symbol): Symbol = { val impl = iface.implClass if (impl != NoSymbol) impl else erasure.implClass(iface) } /** Returns the symbol that is accessed by a super-accessor in a mixin composition. * * @param base The class in mwhich everything is mixed together * @param member The symbol statically referred to by the superaccessor in the trait * @param mixinClass The mixin class that produced the superaccessor */ private def rebindSuper(base: Symbol, member: Symbol, mixinClass: Symbol): Symbol = atPhase(currentRun.refchecksPhase) { var bcs = base.info.baseClasses.dropWhile(mixinClass !=).tail var sym: Symbol = NoSymbol if (settings.debug.value) log("starting rebindsuper " + base + " " + member + ":" + member.tpe + " " + mixinClass + " " + base.info.baseClasses) while (!bcs.isEmpty && sym == NoSymbol) { if (settings.debug.value) { val other = bcs.head.info.nonPrivateDecl(member.name); log("rebindsuper " + bcs.head + " " + other + " " + other.tpe + " " + other.isDeferred) } sym = member.overridingSymbol(bcs.head).suchThat(sym => !sym.hasFlag(DEFERRED | BRIDGE)) bcs = bcs.tail } assert(sym != NoSymbol, member) sym }// --------- type transformation ----------------------------------------------- /** Add given member to given class, and mark member as mixed-in. */ def addMember(clazz: Symbol, member: Symbol): Symbol = { if (settings.debug.value) log("new member of " + clazz + ":" + member.defString) clazz.info.decls enter member member setFlag MIXEDIN } /** Add getters and setters for all non-module fields of an implementation * class to its interface unless they are already present. This is done * only once per class. The mixedin flag is used to remember whether late * members have been added to an interface. * - lazy fields don't get a setter. * * @param clazz ... */ def addLateInterfaceMembers(clazz: Symbol) { if ((treatedClassInfos get clazz) != Some(clazz.info)) { treatedClassInfos(clazz) = clazz.info assert(phase == currentRun.mixinPhase) /** Create a new getter. Getters are never private or local. They are * always accessors and deferred. */ def newGetter(field: Symbol): Symbol = clazz.newMethod(field.pos, nme.getterName(field.name)) .setFlag(field.flags & ~(PRIVATE | LOCAL) | ACCESSOR | lateDEFERRED) .setInfo(MethodType(List(), field.info)) /** Create a new setter. Setters are never private or local. They are * always accessors and deferred. */ def newSetter(field: Symbol): Symbol = clazz.newMethod(field.pos, nme.getterToSetter(nme.getterName(field.name))) .setFlag(field.flags & ~(PRIVATE | LOCAL) | ACCESSOR | lateDEFERRED) .setInfo(MethodType(List(field.info), UnitClass.tpe)) clazz.info // make sure info is up to date, so that implClass is set. val impl = implClass(clazz) assert(impl != NoSymbol) for (val member <- impl.info.decls.toList) { if (!member.isMethod && !member.isModule && !member.isModuleVar) { assert(member.isTerm && !member.isDeferred, member) if (member.getter(impl) hasFlag PRIVATE) { member.makeNotPrivate(clazz) // this will also make getter&setter not private } val getter = member.getter(clazz) if (getter == NoSymbol) addMember(clazz, newGetter(member)) if (!member.tpe.isInstanceOf[ConstantType] && !member.hasFlag(LAZY)) { val setter = member.setter(clazz) if (setter == NoSymbol) addMember(clazz, newSetter(member)) } } } if (settings.debug.value) log("new defs of " + clazz + " = " + clazz.info.decls); } } /** Map a lazy, mixedin field accessor to it's trait member accessor */ val initializer = new HashMap[Symbol, Symbol] /** Add all members to be mixed in into a (non-trait-) class * These are: * for every mixin trait T that is not also inherited by the superclass: * add late interface members to T and then: * - if a member M of T is forwarded to the implementation class, add * a forwarder for M unless one exists already. * The alias of the forwarder is the static member it forwards to. * - for every abstract accessor in T, add a field and an implementation for that acessor * - for every super accessor in T, add an implementation of that accessor * - for every module in T, add a module */ def addMixedinMembers(clazz: Symbol) { if (!(clazz hasFlag JAVA) && (treatedClassInfos get clazz) != Some(clazz.info)) { treatedClassInfos(clazz) = clazz.info assert(!clazz.isTrait, clazz) assert(!clazz.info.parents.isEmpty, clazz) // first complete the superclass with mixed in members addMixedinMembers(clazz.superClass) //Console.println("adding members of " + clazz.info.baseClasses.tail.takeWhile(superclazz !=) + " to " + clazz);//DEBUG /** Mix in members of implementation class mixinClass into class clazz */ def mixinImplClassMembers(impl: Symbol, iface: Symbol) { assert (impl.isImplClass) for (val member <- impl.info.decls.toList) { if (isForwarded(member)) { val imember = member.overriddenSymbol(iface) //Console.println("mixin member "+member+":"+member.tpe+member.locationString+" "+imember+" "+imember.overridingSymbol(clazz)+" to "+clazz+" with scope "+clazz.info.decls)//DEBUG if (imember.overridingSymbol(clazz) == NoSymbol && clazz.info.findMember(member.name, 0, lateDEFERRED, false).alternatives.contains(imember)) { val member1 = addMember( clazz, member.cloneSymbol(clazz) setPos clazz.pos resetFlag (DEFERRED | lateDEFERRED)) member1.asInstanceOf[TermSymbol] setAlias member; } } } } /** Mix in members of trait mixinClass into class clazz. Also, * for each lazy field in mixinClass, add a link from its mixed in member to it's * initializer method inside the implclass. */ def mixinTraitMembers(mixinClass: Symbol) { // For all members of a trait's interface do: def isConcreteAccessor(member: Symbol) = (member hasFlag ACCESSOR) && (!(member hasFlag DEFERRED) || (member hasFlag lateDEFERRED)) def isOverridden(member: Symbol) = isConcreteAccessor(member.overridingSymbol(clazz)) for (val member <- mixinClass.info.decls.toList) { if (isConcreteAccessor(member)) { if (isOverridden(member)) { if (settings.debug.value) println("!!! is overridden val: "+member) } else { // mixin field accessors val member1 = addMember( clazz, member.cloneSymbol(clazz) setPos clazz.pos setFlag FINAL resetFlag (DEFERRED | lateDEFERRED)) if (member.hasFlag(LAZY)) { var init = implClass(mixinClass).info.decl(member.name) assert(init != NoSymbol, "Could not find initializer for " + member.name) initializer(member1) = init } if (!member.isSetter) member.tpe match { case MethodType(List(), ConstantType(_)) => // member is a constant; only getter is needed ; case MethodType(List(), TypeRef(_, tpeSym, _)) if member.hasFlag(LAZY) && tpeSym == definitions.UnitClass => // member is a lazy value of type unit. No field needed ; case _ => // otherwise mixin a field as well addMember(clazz, clazz.newValue(member.pos, nme.getterToLocal(member.name)) setFlag (LOCAL | PRIVATE | member.getFlag(MUTABLE | LAZY)) setFlag (if (!member.hasFlag(STABLE)) MUTABLE else 0) setInfo member.tpe.resultType setAttributes member.attributes) } } } else if (member hasFlag SUPERACCESSOR) { // mixin super accessors val member1 = addMember(clazz, member.cloneSymbol(clazz)) setPos clazz.pos assert(member1.alias != NoSymbol, member1) val alias1 = rebindSuper(clazz, member.alias, mixinClass) member1.asInstanceOf[TermSymbol] setAlias alias1 } else if (member.isMethod && member.isModule && !(member hasFlag (LIFTED | BRIDGE))) { // mixin objects: todo what happens with abstract objects? addMember(clazz, member.cloneSymbol(clazz)) .setPos(clazz.pos)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?