Overhaul of mixin.
If extempore is going to fix the hard bugs then first he is going to make them less hard to fix. The major work of interest in here is the decomplification of the bitmap logic. Hopefully this will come in handy for anyone wishing to try out other encodings. git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@25853 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
7278b610e4
commit
1ae87317ab
|
|
@ -267,6 +267,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
|
|||
def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass
|
||||
def isJavaRepeatedParamType(tp: Type) = tp.typeSymbol == JavaRepeatedParamClass
|
||||
def isRepeatedParamType(tp: Type) = isScalaRepeatedParamType(tp) || isJavaRepeatedParamType(tp)
|
||||
def isCastSymbol(sym: Symbol) = sym == Any_asInstanceOf || sym == Object_asInstanceOf
|
||||
|
||||
def isJavaVarArgs(params: List[Symbol]) = params.nonEmpty && isJavaRepeatedParamType(params.last.tpe)
|
||||
def isScalaVarArgs(params: List[Symbol]) = params.nonEmpty && isScalaRepeatedParamType(params.last.tpe)
|
||||
|
|
|
|||
|
|
@ -80,8 +80,7 @@ trait NameManglers {
|
|||
|
||||
def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR
|
||||
def isExceptionResultName(name: Name) = name startsWith EXCEPTION_RESULT_PREFIX
|
||||
/** !!! Foo$class$1 is an implClassName, I think. */
|
||||
def isImplClassName(name: Name) = name endsWith IMPL_CLASS_SUFFIX
|
||||
def isImplClassName(name: Name) = stripAnonNumberSuffix(name) endsWith IMPL_CLASS_SUFFIX
|
||||
def isLocalDummyName(name: Name) = name startsWith LOCALDUMMY_PREFIX
|
||||
def isLocalName(name: Name) = name endsWith LOCAL_SUFFIX_STRING
|
||||
def isLoopHeaderLabel(name: Name) = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX)
|
||||
|
|
@ -159,6 +158,26 @@ trait NameManglers {
|
|||
else name
|
||||
}
|
||||
|
||||
/** !!! I'm putting this logic in place because I can witness
|
||||
* trait impls get lifted and acquiring names like 'Foo$class$1'
|
||||
* while clearly still being what they were. It's only being used on
|
||||
* isImplClassName. However, it's anyone's guess how much more
|
||||
* widely this logic actually ought to be applied. Anything which
|
||||
* tests for how a name ends is a candidate for breaking down once
|
||||
* something is lifted from a method.
|
||||
*
|
||||
* TODO: resolve this significant problem.
|
||||
*/
|
||||
def stripAnonNumberSuffix(name: Name): Name = {
|
||||
val str = "" + name
|
||||
if (str == "" || !str.endChar.isDigit) name
|
||||
else {
|
||||
val idx = name.lastPos('$')
|
||||
if (idx < 0 || str.substring(idx + 1).exists(c => !c.isDigit)) name
|
||||
else name.subName(0, idx)
|
||||
}
|
||||
}
|
||||
|
||||
def stripModuleSuffix(name: Name): Name = (
|
||||
if (isModuleName(name)) name stripEnd MODULE_SUFFIX_STRING else name
|
||||
)
|
||||
|
|
|
|||
|
|
@ -361,23 +361,15 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy
|
|||
mkName(simple, div == '.') :: segments(rest, assumeTerm)
|
||||
}
|
||||
}
|
||||
private def bitmapName(n: Int, suffix: String): TermName =
|
||||
newTermName(BITMAP_PREFIX + suffix + n)
|
||||
|
||||
/** The name of bitmaps for initialized (public or protected) lazy vals. */
|
||||
def bitmapName(n: Int): TermName = bitmapName(n, "")
|
||||
def newBitmapName(bitmapPrefix: Name, n: Int) = bitmapPrefix append ("" + n)
|
||||
|
||||
/** The name of bitmaps for initialized transient lazy vals. */
|
||||
def bitmapNameForTransient(n: Int): TermName = bitmapName(n, "trans$")
|
||||
|
||||
/** The name of bitmaps for initialized private lazy vals. */
|
||||
def bitmapNameForPrivate(n: Int): TermName = bitmapName(n, "priv$")
|
||||
|
||||
/** The name of bitmaps for checkinit values */
|
||||
def bitmapNameForCheckinit(n: Int): TermName = bitmapName(n, "init$")
|
||||
|
||||
/** The name of bitmaps for checkinit values that have transient flag*/
|
||||
def bitmapNameForCheckinitTransient(n: Int): TermName = bitmapName(n, "inittrans$")
|
||||
val BITMAP_PREFIX: String = "bitmap$"
|
||||
val BITMAP_NORMAL: NameType = BITMAP_PREFIX + "" // initialization bitmap for public/protected lazy vals
|
||||
val BITMAP_TRANSIENT: NameType = BITMAP_PREFIX + "trans$" // initialization bitmap for transient lazy vals
|
||||
val BITMAP_PRIVATE: NameType = BITMAP_PREFIX + "priv$" // initialization bitmap for private lazy vals
|
||||
val BITMAP_CHECKINIT: NameType = BITMAP_PREFIX + "init$" // initialization bitmap for checkinit values
|
||||
val BITMAP_CHECKINIT_TRANSIENT: NameType = BITMAP_PREFIX + "inittrans$" // initialization bitmap for transient checkinit values
|
||||
|
||||
/** The expanded name of `name` relative to this class `base` with given `separator`
|
||||
*/
|
||||
|
|
@ -391,7 +383,6 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy
|
|||
val ROOTPKG: TermName = "_root_"
|
||||
|
||||
/** Base strings from which synthetic names are derived. */
|
||||
val BITMAP_PREFIX = "bitmap$"
|
||||
val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$"
|
||||
val DEFAULT_GETTER_STRING = "$default$"
|
||||
val DO_WHILE_PREFIX = "doWhile$"
|
||||
|
|
|
|||
|
|
@ -1317,8 +1317,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|
|||
|
||||
/** The symbol accessed by this accessor function, but with given owner type. */
|
||||
final def accessed(ownerTp: Type): Symbol = {
|
||||
assert(hasAccessorFlag)
|
||||
ownerTp.decl(nme.getterToLocal(if (isSetter) nme.setterToGetter(name) else name))
|
||||
assert(hasAccessorFlag, this)
|
||||
ownerTp decl nme.getterToLocal(getterName)
|
||||
}
|
||||
|
||||
/** The module corresponding to this module class (note that this
|
||||
|
|
@ -1349,6 +1349,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|
|||
/** If this is a lazy value, the lazy accessor; otherwise this symbol. */
|
||||
def lazyAccessorOrSelf: Symbol = if (isLazy) lazyAccessor else this
|
||||
|
||||
/** If this is an accessor, the accessed symbol. Otherwise, this symbol. */
|
||||
def accessedOrSelf: Symbol = if (hasAccessorFlag) accessed else this
|
||||
|
||||
/** For an outer accessor: The class from which the outer originates.
|
||||
* For all other symbols: NoSymbol
|
||||
*/
|
||||
|
|
@ -1646,10 +1649,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|
|||
/** The getter of this value or setter definition in class `base`, or NoSymbol if
|
||||
* none exists.
|
||||
*/
|
||||
final def getter(base: Symbol): Symbol = {
|
||||
val getterName = if (isSetter) nme.setterToGetter(name) else nme.getterName(name)
|
||||
base.info.decl(getterName) filter (_.hasAccessorFlag)
|
||||
}
|
||||
final def getter(base: Symbol): Symbol = base.info.decl(getterName) filter (_.hasAccessorFlag)
|
||||
|
||||
def getterName = if (isSetter) nme.setterToGetter(name) else nme.getterName(name)
|
||||
|
||||
/** The setter of this value or getter definition, or NoSymbol if none exists */
|
||||
final def setter(base: Symbol): Symbol = setter(base, false)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ abstract class TreeInfo {
|
|||
val global: SymbolTable
|
||||
|
||||
import global._
|
||||
import definitions.{ isVarArgsList, ThrowableClass }
|
||||
import definitions.{ isVarArgsList, isCastSymbol, ThrowableClass }
|
||||
|
||||
/* Does not seem to be used. Not sure what it does anyway.
|
||||
def isOwnerDefinition(tree: Tree): Boolean = tree match {
|
||||
|
|
@ -303,6 +303,15 @@ abstract class TreeInfo {
|
|||
case _ => false
|
||||
}
|
||||
|
||||
/** If this tree represents a type application (after unwrapping
|
||||
* any applies) the first type argument. Otherwise, EmptyTree.
|
||||
*/
|
||||
def firstTypeArg(tree: Tree): Tree = tree match {
|
||||
case Apply(fn, _) => firstTypeArg(fn)
|
||||
case TypeApply(_, targ :: _) => targ
|
||||
case _ => EmptyTree
|
||||
}
|
||||
|
||||
/** Does this argument list end with an argument of the form <expr> : _* ? */
|
||||
def isWildcardStarArgList(trees: List[Tree]) =
|
||||
trees.nonEmpty && isWildcardStarArg(trees.last)
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
|
|||
if (bmps.length > n)
|
||||
bmps(n)
|
||||
else {
|
||||
val sym = meth.newVariable(meth.pos, nme.bitmapName(n)).setInfo(IntClass.tpe)
|
||||
val sym = meth.newVariable(meth.pos, nme.newBitmapName(nme.BITMAP_NORMAL, n)).setInfo(IntClass.tpe)
|
||||
atPhase(currentRun.typerPhase) {
|
||||
sym addAnnotation VolatileAttr
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -933,26 +933,26 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
|
|||
*/
|
||||
private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean): TypeEnv = (tp1, tp2) match {
|
||||
case (TypeRef(_, sym1, _), _) if isSpecialized(sym1) =>
|
||||
log("Unify - basic case: " + tp1 + ", " + tp2)
|
||||
debuglog("Unify - basic case: " + tp1 + ", " + tp2)
|
||||
if (isValueClass(tp2.typeSymbol) || isSpecializedAnyRefSubtype(tp2, sym1))
|
||||
env + ((sym1, tp2))
|
||||
else
|
||||
if (strict) throw UnifyError else env
|
||||
case (TypeRef(_, sym1, args1), TypeRef(_, sym2, args2)) =>
|
||||
log("Unify TypeRefs: " + tp1 + " and " + tp2 + " with args " + (args1, args2) + " - ")
|
||||
debuglog("Unify TypeRefs: " + tp1 + " and " + tp2 + " with args " + (args1, args2) + " - ")
|
||||
if (strict && args1.length != args2.length) throw UnifyError
|
||||
val e = unify(args1, args2, env, strict)
|
||||
log("unified to: " + e)
|
||||
debuglog("unified to: " + e)
|
||||
e
|
||||
case (TypeRef(_, sym1, _), _) if sym1.isTypeParameterOrSkolem =>
|
||||
env
|
||||
case (MethodType(params1, res1), MethodType(params2, res2)) =>
|
||||
if (strict && params1.length != params2.length) throw UnifyError
|
||||
log("Unify MethodTypes: " + tp1 + " and " + tp2)
|
||||
debuglog("Unify MethodTypes: " + tp1 + " and " + tp2)
|
||||
unify(res1 :: (params1 map (_.tpe)), res2 :: (params2 map (_.tpe)), env, strict)
|
||||
case (PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
|
||||
if (strict && tparams1.length != tparams2.length) throw UnifyError
|
||||
log("Unify PolyTypes: " + tp1 + " and " + tp2)
|
||||
debuglog("Unify PolyTypes: " + tp1 + " and " + tp2)
|
||||
unify(res1, res2, env, strict)
|
||||
case (PolyType(_, res), other) =>
|
||||
unify(res, other, env, strict)
|
||||
|
|
@ -965,7 +965,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
|
|||
case (AnnotatedType(_, tp1, _), tp2) => unify(tp2, tp1, env, strict)
|
||||
case (ExistentialType(_, res1), _) => unify(tp2, res1, env, strict)
|
||||
case _ =>
|
||||
log("don't know how to unify %s [%s] with %s [%s]".format(tp1, tp1.getClass, tp2, tp2.getClass))
|
||||
debuglog("don't know how to unify %s [%s] with %s [%s]".format(tp1, tp1.getClass, tp2, tp2.getClass))
|
||||
env
|
||||
}
|
||||
|
||||
|
|
@ -977,7 +977,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
|
|||
val nenv = unify(args._1, args._2, emptyEnv, strict)
|
||||
if (env.keySet intersect nenv.keySet isEmpty) env ++ nenv
|
||||
else {
|
||||
log("could not unify: u(" + args._1 + ", " + args._2 + ") yields " + nenv + ", env: " + env)
|
||||
debuglog("could not unify: u(" + args._1 + ", " + args._2 + ") yields " + nenv + ", env: " + env)
|
||||
throw UnifyError
|
||||
}
|
||||
}
|
||||
|
|
@ -1216,14 +1216,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
|
|||
(treeType =:= memberType) || { // anyref specialization
|
||||
memberType match {
|
||||
case PolyType(_, resTpe) =>
|
||||
log("Conformance for anyref - polytype with result type: " + resTpe + " and " + treeType + "\nOrig. sym.: " + origSymbol)
|
||||
debuglog("Conformance for anyref - polytype with result type: " + resTpe + " and " + treeType + "\nOrig. sym.: " + origSymbol)
|
||||
try {
|
||||
val e = unify(origSymbol.tpe, memberType, emptyEnv, true)
|
||||
log("obtained env: " + e)
|
||||
debuglog("obtained env: " + e)
|
||||
e.keySet == env.keySet
|
||||
} catch {
|
||||
case _ =>
|
||||
log("Could not unify.")
|
||||
debuglog("Could not unify.")
|
||||
false
|
||||
}
|
||||
case _ => false
|
||||
|
|
|
|||
|
|
@ -206,8 +206,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
|
|||
|
||||
case Select(Super(_, mix), name) =>
|
||||
if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) {
|
||||
unit.error(tree.pos, "super may be not be used on "+
|
||||
(if (sym.hasAccessorFlag) sym.accessed else sym))
|
||||
unit.error(tree.pos, "super may be not be used on "+ sym.accessedOrSelf)
|
||||
}
|
||||
else if (isDisallowed(sym)) {
|
||||
unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead")
|
||||
|
|
|
|||
|
|
@ -2185,7 +2185,8 @@ trait Typers extends Modes with Adaptations {
|
|||
* follow the logic, so I renamed one to something distinct.
|
||||
*/
|
||||
def accesses(looker: Symbol, accessed: Symbol) = accessed.hasLocalFlag && (
|
||||
accessed.isParamAccessor || (looker.hasAccessorFlag && !accessed.hasAccessorFlag && accessed.isPrivate)
|
||||
(accessed.isParamAccessor)
|
||||
|| (looker.hasAccessorFlag && !accessed.hasAccessorFlag && accessed.isPrivate)
|
||||
)
|
||||
|
||||
def checkNoDoubleDefsAndAddSynthetics(stats: List[Tree]): List[Tree] = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
class A {
|
||||
def f1(t: String) = {
|
||||
trait T {
|
||||
def xs = Nil map (_ => t)
|
||||
}
|
||||
}
|
||||
def f2(t: String) = {
|
||||
def xs = Nil map (_ => t)
|
||||
}
|
||||
def f3(t: String) = {
|
||||
var t1 = 5
|
||||
trait T {
|
||||
def xs = { t1 = 10 ; t }
|
||||
}
|
||||
}
|
||||
def f4() = {
|
||||
var u = 5
|
||||
trait T {
|
||||
def xs = Nil map (_ => u = 10)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue