From c53ac49cbe7c98c05a99fea3c8e1dcad75275a82 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 28 May 2013 14:56:22 +0200 Subject: wip namer. --- src/dotty/tools/dotc/ast/Trees.scala | 19 +-- src/dotty/tools/dotc/ast/UntypedTrees.scala | 26 ++++- src/dotty/tools/dotc/core/Contexts.scala | 3 +- src/dotty/tools/dotc/core/Decorators.scala | 4 + src/dotty/tools/dotc/core/StdNames.scala | 1 + src/dotty/tools/dotc/core/SymDenotations.scala | 5 + src/dotty/tools/dotc/core/Types.scala | 2 +- src/dotty/tools/dotc/typer/Namer.scala | 143 +++++++++++++++++++++++ src/dotty/tools/dotc/util/FreshNameCreator.scala | 10 +- 9 files changed, 191 insertions(+), 22 deletions(-) create mode 100644 src/dotty/tools/dotc/typer/Namer.scala (limited to 'src/dotty/tools/dotc') diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 15aa3585b..3b38fed7d 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -302,7 +302,7 @@ object Trees { * The envelope of a ModDefTree contains the whole definition and his its point * on the opening keyword (or the next token after that if keyword is missing). */ - trait ModDefTree[T >: Untyped] extends DefTree[T] { + trait ModDefTree[T >: Untyped] extends NameTree[T] with DefTree[T] { type ThisTree[T >: Untyped] <: ModDefTree[T] def mods: Modifiers[T] override def envelope: Position = mods.pos union pos union initialPos @@ -465,12 +465,16 @@ object Trees { /** A type tree that represents an existing or inferred type */ case class TypeTree[T >: Untyped](original: Tree[T] = emptyTree[T]) - extends DenotingTree[T] with TypTree[T] { + extends DenotingTree[T] with TypTree[T] type ThisTree[T >: Untyped] = TypeTree[T] override def initialPos = NoPosition override def isEmpty = !hasType && original.isEmpty } + object TypeTree { + def apply(tpe: Type): TypeTree[Type] = TypeTree().withType(tpe) + } + /** ref.type */ case class SingletonTypeTree[T >: Untyped](ref: Tree[T]) extends DenotingTree[T] with TypTree[T] { @@ -541,14 +545,14 @@ object Trees { /** mods val name: tpt = rhs */ case class ValDef[T >: Untyped](mods: Modifiers[T], name: TermName, tpt: Tree[T], rhs: Tree[T]) - extends NameTree[T] with ModDefTree[T] { + extends ModDefTree[T] { type ThisTree[T >: Untyped] = ValDef[T] def withName(name: Name) = this.derivedValDef(mods, name.toTermName, tpt, rhs) } /** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */ case class DefDef[T >: Untyped](mods: Modifiers[T], name: TermName, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T]) - extends NameTree[T] with ModDefTree[T] { + extends ModDefTree[T] { type ThisTree[T >: Untyped] = DefDef[T] def withName(name: Name) = this.derivedDefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs) } @@ -557,7 +561,7 @@ object Trees { * mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) */ case class TypeDef[T >: Untyped](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], rhs: Tree[T]) - extends NameTree[T] with ModDefTree[T] { + extends ModDefTree[T] { type ThisTree[T >: Untyped] = TypeDef[T] def withName(name: Name) = this.derivedTypeDef(mods, name.toTypeName, tparams, rhs) } @@ -570,7 +574,7 @@ object Trees { /** mods class name[tparams] impl */ case class ClassDef[T >: Untyped](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], impl: Template[T]) - extends NameTree[T] with ModDefTree[T] { + extends ModDefTree[T] { type ThisTree[T >: Untyped] = ClassDef[T] def withName(name: Name) = this.derivedClassDef(mods, name.toTypeName, tparams, impl) } @@ -716,9 +720,6 @@ object Trees { protected implicit def pos(implicit ctx: Context): Position = ctx.position def defPos(sym: Symbol)(implicit ctx: Context) = ctx.position union sym.coord.toPosition - - def Parameter(pname: TermName, tpe: Tree, mods: Modifiers = Modifiers()): ValDef = - ValDef(mods | Param, pname, tpe, emptyTree()) } // ----- Helper functions and classes --------------------------------------- diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala index 3087772a8..bc64bc465 100644 --- a/src/dotty/tools/dotc/ast/UntypedTrees.scala +++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala @@ -70,13 +70,18 @@ object untpd extends Trees.Instance[Untyped] { case _ => Tuple(ts) } + def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers = Modifiers()): ValDef = + ValDef(mods | Param, pname, tpe, emptyTree()) + + def makeSyntheticParameter(n: Int = 1, tpt: Tree = EmptyTree)(implicit ctx: Context): ValDef = + ValDef(Modifiers(SyntheticTermParam), nme.syntheticParamName(n), TypeTree(), EmptyTree) + + def refOfDef(tree: NameTree) = Ident(tree.name) + // ------ Untyped tree desugaring ------------------------------------------ def desugar(tree: Tree, mode: Mode.Value)(implicit ctx: Context): Tree = { - def makeSyntheticParameter(): ValDef = - ValDef(Modifiers(SyntheticTermParam), ctx.freshName().toTermName, TypeTree(), EmptyTree) - def labelDefAndCall(lname: TermName, rhs: Tree, call: Tree) = { val ldef = DefDef(Modifiers(Label), lname, Nil, ListOfNil, TypeTree(), rhs) Block(ldef, call) @@ -439,6 +444,21 @@ object untpd extends Trees.Instance[Untyped] { case _ => tree } + /** Expand to: + * val name: name$ = New(name$) + * final class name$ extends parents { self: name.type => body } + */ + def desugarModuleDef(mdef: ModuleDef): Tree = { + val ModuleDef(mods, name, tmpl @ Template(constr, parents, self, body)) = mdef + val clsName = name.moduleClassName + val clsRef = Ident(clsName) + val modul = ValDef(mods | ModuleCreationFlags, name, clsRef, New(clsRef, Nil)) + val clsSelf = self.derivedValDef(self.mods, self.name, SingletonTypeTree(Ident(name)), self.rhs) + val clsTmpl = tmpl.derivedTemplate(constr, parents, clsSelf, body) + val cls = ClassDef(mods.toTypeFlags & AccessFlags | ModuleClassCreationFlags, clsName, Nil, clsTmpl) + Thicket(modul, cls) + } + def desugarAnonClass(templ: Template): Tree = { val x = tpnme.ANON_CLASS val clsDef = ClassDef(Modifiers(Final), x, Nil, templ) diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index af8bd6e91..6ff6e148d 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -293,8 +293,7 @@ object Contexts { /** The standard fresh name creator */ val freshNames = new FreshNameCreator.Default - def freshName(): String = freshNames.newName() - def freshName(prefix: String): String = freshNames.newName(prefix) + def freshName(prefix: String = ""): String = freshNames.newName(prefix) def freshName(prefix: Name): String = freshName(prefix.toString) /** The loader that loads the members of _root_ */ diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala index 031974dfd..094aa7b4a 100644 --- a/src/dotty/tools/dotc/core/Decorators.scala +++ b/src/dotty/tools/dotc/core/Decorators.scala @@ -70,6 +70,10 @@ object Decorators { } } + implicit class ListOfListDecorator[T](val xss: List[List[T]]) extends AnyVal { + def nestedMap[U](f: T => U): List[List[U]] = xss map (_ map f) + } + implicit class TextToString(val text: Text) extends AnyVal { def show(implicit ctx: Context) = text.mkString(ctx.settings.pageWidth.value) } diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index ada74c69d..9ae4729f4 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -380,6 +380,7 @@ object StdNames { val info: N = "info" val inlinedEquals: N = "inlinedEquals" val isArray: N = "isArray" + val isDefined: N = "isDefined" val isDefinedAt: N = "isDefinedAt" val isEmpty: N = "isEmpty" val isInstanceOf_ : N = "isInstanceOf" diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index bec55720f..51e03aee7 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -470,6 +470,11 @@ object SymDenotations { final def enclosingClass(implicit ctx: Context): Symbol = if (isClass) symbol else owner.enclosingClass + final def enclosingClassNamed(name: Name)(implicit ctx: Context): Symbol = { + val cls = enclosingClass + if (cls.name == name) cls else cls.owner.enclosingClassNamed(name) + } + /** The top-level class containing this denotation, * except for a toplevel module, where its module class is returned. */ diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 1b21567a0..880cb7174 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1556,7 +1556,7 @@ object Types { /** The type of an import clause tree */ - case class ImportType(expr: SharedTree) extends UncachedGroundType + case class ImportType(expr: Tree) extends UncachedGroundType /** Sentinal for "missing type" */ case object NoType extends CachedGroundType { diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala new file mode 100644 index 000000000..a024ba953 --- /dev/null +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -0,0 +1,143 @@ +package dotty.tools +package dotc +package typer + +import core._ +import ast._ +import Trees._, Constants._, StdNames._ +import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._ +import util.Positions._ +import util.SourcePosition +import language.implicitConversions + +class Namer { + + import untpd._ + + implicit def sourcePos(pos: Position)(implicit ctx: Context): SourcePosition = + ctx.source.atPos(pos) + + implicit def posToCoord(pos: Position): Coord = positionCoord(pos) + + def privateWithinClass(mods: Modifiers)(implicit ctx: Context): Symbol = { + val pw = mods.privateWithin + if (pw.isEmpty) NoSymbol + else { + val cls = ctx.owner.enclosingClassNamed(pw) + if (!cls.exists) ctx.error(s"no enclosing class or object is named $pw", mods.pos) + cls + } + } + + def createSymbol(tree: Tree)(implicit ctx: Context): Symbol = tree match { + case tree: ModDefTree => + val sym = ctx.newSymbol( + ctx.owner, tree.name, tree.mods.flags, new Completer(tree), + privateWithinClass(tree.mods), tree.pos) + ctx.scope.enter(sym) + sym + } + + + def expansion(tree: Tree)(implicit ctx: Context): Tree = { + + def expandCaseClass(tree: Tree, companion: Tree): Tree = { + val ClassDef(mods, cname, tparams, impl @ Template(constr, parents, self, stats)) = tree + val constr1 = + if (constr.vparamss.nonEmpty) constr + else { + ctx.error("case classes need to have at least one parameter list") + constr.derivedDefDef(constr.mods, constr.name, constr.tparams, ListOfNil, constr.tpt, constr.rhs) + } + val caseParams = constr1.vparamss.head + val caseParamsArray = caseParams.toArray + val isDefinedMeth = syntheticProperty(nme.isDefined, Literal(Constant(true))) + val productArityMeth = syntheticProperty(nme.productArity, Literal(Constant(caseParamsArray.length))) + val productElemMeths = for (i <- 0 until caseParamsArray.length) yield + syntheticProperty(("_" + (i + 1)).toTermName, Select(This(EmptyTypeName), caseParamsArray(i).name)) + val clsTypeRef = AppliedTypeTree(Ident(cname), tparams map refOfDef) + val methTparams = for (tparam <- tparams) yield + tparam.derivedTypeDef(Modifiers(TypeParam), tparam.name, tparam.tparams, tparam.rhs) + val (copyMeths, applyMeths) = + if (mods is Abstract) (Nil, Nil) + else { + val creator = New(clsTypeRef, constr1.vparamss map (_ map refOfDef)) + val copyFirstParams = caseParams.map(vparam => + vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, refOfDef(vparam))) + val copyRestParamss = constr1.vparamss.tail.nestedMap(vparam => + vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, EmptyTree)) + val applyParamss = constr1.vparamss.nestedMap(vparam => + vparam.derivedValDef(Modifiers(TermParam), vparam.name, vparam.tpt, vparam.rhs)) + val copyMeth = + DefDef(Modifiers(Synthetic), nme.copy, methTparams, copyFirstParams :: copyRestParamss, EmptyTree, creator) + val applyMeth = + DefDef(Modifiers(Synthetoc), nme.apply, methTparams, applyParamss, EmptyTree, creator) + (copyMeth :: Nil, applyMeth :: Nil) + } + val unapplyMeth = { + val unapplyParam = makeSyntheticParameter(tpt = clsTypeRef) + DefDef(Modifiers(Synthetic), nme.unapply, methTparams, (unapplyParam :: Nil) :: Nil, clsTypeRef, This(EmptyTypeName)) + } + val newClassDefs = copyMeths ++ isDefinedMeth :: productArityMeth :: productElemMeths.toList + val newModuleDefs = applyMeths ++ unapplyMeth :: Nil + val cls1 = tree.derivedClassDef(mods, cname, tparams, + impl.derivedTemplate(constr, parents, self, stats ++ newClassDefs)) + val companion1 = companion match { + case ModuleDef(mods, name, impl @ Template(constr, parents, self, stats)) => + companion.derivedModuleDef(mods, name, + impl.derivedTemplate(constr, parents, self, stats ++ newModuleDefs)) + case _ => + + } + if (companion.isEmpty) + else { + + } + + val applyMeth = { + val applyVparamss = + DefDef(Modifiers(Synthetic), nme.apply, methTparams, applyVparamss, EmptyTree, ) + } + + } + + } + + + tree match { + case ValDef(mods, name, tpt, rhs) => + if (!ctx.owner.isClass || (mods is Private)) tree + else { + val lname = name.toLocalName + val field = tree.derivedValDef(mods, lname, tpt, rhs) + val getter = tree.derivedDefDef(mods, name, Nil, Nil, tpt, Ident(lname)) + if (!(mods is Mutable)) Thicket(field, getter) + else { + val setterParam = makeSyntheticParameter(tpt = TypeTree(field)) + val setter = tree.derivedDefDef( + mods, name.getterToSetter, Nil, (setterParam :: Nil) :: Nil, EmptyTree, refOfDef(setterParam)) + Thicket(field, getter, setter) + } + } + case tree: ModuleDef => + desugarModuleDef(tree) + case tree: ClassDef if tree.mods is Case => + expandCaseClass(tree) + } + + def syntheticProperty(name: TermName, rhs: Tree) = DefDef(Modifiers(Synthetic), name, Nil, Nil, EmptyTree, rhs) + + class Completer(tree: Tree) extends LazyType { + def complete(sym: Symbol) => + ??? + } + + def enter(tree: Tree)(implicit ctx: Context) = tree match { + case Import(expr, selectors) => + ??? + case DefDef + + + } + +} \ No newline at end of file diff --git a/src/dotty/tools/dotc/util/FreshNameCreator.scala b/src/dotty/tools/dotc/util/FreshNameCreator.scala index d0c007d94..cc39008ed 100644 --- a/src/dotty/tools/dotc/util/FreshNameCreator.scala +++ b/src/dotty/tools/dotc/util/FreshNameCreator.scala @@ -24,15 +24,11 @@ object FreshNameCreator { * that the returned name has never been returned by a previous * call to this function (provided the prefix does not end in a digit). */ - def newName(prefix: String): String = { + def newName(prefix: String = ""): String = { val safePrefix = prefix.replaceAll("""[<>]""", """\$""") counters(safePrefix) += 1 - - safePrefix + counters(safePrefix) - } - def newName(): String = { - counter += 1 - "$" + counter + "$" + val counter = counters(safePrefix) + if (prefix.isEmpty) "$" + counter + "$" else safePrefix + counter } } } -- cgit v1.2.3