From 112f39aa1c3a9e36848b30d7d2709fb1b2ef7949 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 16 Jun 2015 16:27:10 +0200 Subject: Use FlagSet directly instead of defKind Instead of classifying class members with a TreeInfo.DefKind, we use directly the flags into which kinds were previously translated. --- src/dotty/tools/dotc/ast/TreeInfo.scala | 26 +++++++------------ src/dotty/tools/dotc/core/Flags.scala | 2 ++ src/dotty/tools/dotc/core/SymDenotations.scala | 10 ++++---- .../tools/dotc/core/tasty/TreeUnpickler.scala | 29 +++++++++++----------- src/dotty/tools/dotc/typer/Namer.scala | 4 +-- 5 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index b20b7c9f2..c9a22f09e 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -25,14 +25,16 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => case _ => false } - /** Does tree contain an initialization part when seen as a member of a class or trait? + /** The largest subset of {NoInits, PureInterface} that a + * trait enclosing this statement can have as flags. + * Does tree contain an initialization part when seen as a member of a class or trait? */ - def defKind(tree: Tree): DefKind = unsplice(tree) match { - case EmptyTree | _: Import => InterfaceDef - case tree: TypeDef => if (tree.isClassDef) NoInitDef else InterfaceDef - case tree: DefDef => if (tree.unforcedRhs == EmptyTree) InterfaceDef else NoInitDef - case tree: ValDef => if (tree.unforcedRhs == EmptyTree) InterfaceDef else GeneralDef - case _ => GeneralDef + def defKind(tree: Tree): FlagSet = unsplice(tree) match { + case EmptyTree | _: Import => NoInitsInterface + case tree: TypeDef => if (tree.isClassDef) NoInits else NoInitsInterface + case tree: DefDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else NoInits + case tree: ValDef => if (tree.unforcedRhs == EmptyTree) NoInitsInterface else EmptyFlags + case _ => EmptyFlags } def isOpAssign(tree: Tree) = unsplice(tree) match { @@ -517,7 +519,6 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => } object TreeInfo { - class PurityLevel(val x: Int) extends AnyVal { def >= (that: PurityLevel) = x >= that.x def min(that: PurityLevel) = new PurityLevel(x min that.x) @@ -526,15 +527,6 @@ object TreeInfo { val Pure = new PurityLevel(2) val Idempotent = new PurityLevel(1) val Impure = new PurityLevel(0) - - case class DefKind(val x: Int) extends AnyVal { - def >= (that: DefKind) = x >= that.x - def min(that: DefKind) = new DefKind(x min that.x) - } - - val InterfaceDef = new DefKind(2) - val NoInitDef = new DefKind(1) - val GeneralDef = new DefKind(0) } /** a Match(Typed(_, tpt), _) must be translated into a switch if isSwitchAnnotation(tpt.tpe) diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 3efadcb00..759dff0d4 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -467,6 +467,8 @@ object Flags { /** Pure interfaces always have these flags */ final val PureInterfaceCreationFlags = Trait | NoInits | PureInterface + final val NoInitsInterface = NoInits | PureInterface + /** The flags of the self symbol */ final val SelfSymFlags = Private | Local | Deferred diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index f4fde3e81..6d8d6a8f0 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -115,11 +115,11 @@ object SymDenotations { /** Unset given flags(s) of this denotation */ final def resetFlag(flags: FlagSet): Unit = { myFlags &~= flags } - final def setFlagsFromDefKind(kind: TreeInfo.DefKind): Unit = - if (kind >= TreeInfo.NoInitDef) { - setFlag(NoInits) - if (kind == TreeInfo.InterfaceDef && myFlags.is(Trait)) setFlag(PureInterface) - } + /** Set applicable flags from `flags` which is a subset of {NoInits, PureInterface} */ + final def setApplicableFlags(flags: FlagSet): Unit = { + val mask = if (myFlags.is(Trait)) NoInitsInterface else NoInits + setFlag(flags & mask) + } /** Has this denotation one of the flags in `fs` set? */ final def is(fs: FlagSet)(implicit ctx: Context) = { diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 0dfef0c51..44abef435 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -7,7 +7,6 @@ import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, Name import StdNames._, Denotations._, Flags._, Constants._, Annotations._ import util.Positions._ import ast.{tpd, Trees, untpd} -import ast.TreeInfo._ import Trees._ import Decorators._ import TastyUnpickler._, TastyBuffer._, PositionPickler._ @@ -351,9 +350,10 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { } /** Create symbol of definition node and enter in symAtAddr map - * @return true iff the definition does not contain initialization code + * @return the largest subset of {NoInits, PureInterface} that a + * trait owning this symbol can have as flags. */ - def createSymbol()(implicit ctx: Context): DefKind = { + def createSymbol()(implicit ctx: Context): FlagSet = { val start = currentAddr val tag = readByte() val end = readEnd() @@ -409,10 +409,10 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { sym.completer.withDecls(newScope) forkAt(templateStart).indexTemplateParams()(localContext(sym)) } - if (isClass) NoInitDef - else if (sym.isType || sym.isConstructor || flags.is(Deferred)) InterfaceDef - else if (tag == VALDEF) GeneralDef - else NoInitDef + if (isClass) NoInits + else if (sym.isType || sym.isConstructor || flags.is(Deferred)) NoInitsInterface + else if (tag == VALDEF) EmptyFlags + else NoInits } /** Read modifier list into triplet of flags, annotations and a privateWithin @@ -476,25 +476,26 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { /** Create symbols for a definitions in statement sequence between * current address and `end`. - * @return true iff none of the statements contains initialization code + * @return the largest subset of {NoInits, PureInterface} that a + * trait owning the indexed statements can have as flags. */ - def indexStats(end: Addr)(implicit ctx: Context): DefKind = { - val defKinds = + def indexStats(end: Addr)(implicit ctx: Context): FlagSet = { + val flagss = until(end) { nextByte match { case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM => createSymbol() case IMPORT => skipTree() - InterfaceDef + NoInitsInterface case PACKAGE => processPackage { (pid, end) => implicit ctx => indexStats(end) } case _ => skipTree() - GeneralDef + EmptyFlags } } - (InterfaceDef /: defKinds)(_ min _) + (NoInitsInterface /: flagss)(_ & _) } /** Process package with given operation `op`. The operation takes as arguments @@ -635,7 +636,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { } else EmptyValDef setClsInfo(parentRefs, if (self.isEmpty) NoType else self.tpt.tpe) - cls.setFlagsFromDefKind(fork.indexStats(end)) + cls.setApplicableFlags(fork.indexStats(end)) val constr = readIndexedDef().asInstanceOf[DefDef] def mergeTypeParamsAndAliases(tparams: List[TypeDef], stats: List[Tree]): (List[Tree], List[Tree]) = diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index e8a0294f8..879c0d0a8 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -563,8 +563,8 @@ class Namer { typer: Typer => index(rest)(inClassContext(selfInfo)) denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo) - cls.setFlagsFromDefKind( - (TreeInfo.InterfaceDef /: impl.body)((kind, stat) => kind min defKind(stat))) + cls.setApplicableFlags( + (NoInitsInterface /: impl.body)((fs, stat) => fs & defKind(stat))) } } -- cgit v1.2.3