diff options
author | Martin Odersky <odersky@gmail.com> | 2013-08-23 16:15:46 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-08-23 16:16:14 +0200 |
commit | 7b8000914abe73883052b1d8af356f91cc133806 (patch) | |
tree | eca9fd3178e13c65c61dd9ff19f7953c11814a21 /src/dotty/tools | |
parent | 66a176bea94205469851fdb4fab46c2589fba407 (diff) | |
download | dotty-7b8000914abe73883052b1d8af356f91cc133806.tar.gz dotty-7b8000914abe73883052b1d8af356f91cc133806.tar.bz2 dotty-7b8000914abe73883052b1d8af356f91cc133806.zip |
Fixes expansion and general handling of pattern defs.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r-- | src/dotty/tools/dotc/ast/Desugar.scala | 103 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/UntypedTrees.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 12 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 4 |
5 files changed, 66 insertions, 59 deletions
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index 047a60814..ccb99290a 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -232,11 +232,53 @@ object desugar { Thicket(modul, cls) } - def memberDef(tree: Tree)(implicit ctx: Context): Tree = tree match { + def patDef(pdef: PatDef)(implicit ctx: Context): Tree = { + val PatDef(mods, pats, tpt, rhs) = pdef + val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt)) + flatTree(pats1 map (makePatDef(mods, _, rhs))) + } + + def defTree(tree: Tree)(implicit ctx: Context): Tree = tree match { case tree: ValDef => valDef(tree) case tree: TypeDef => if (tree.isClassDef) classDef(tree) else typeDef(tree) case tree: DefDef => defDef(tree) case tree: ModuleDef => moduleDef(tree) + case tree: PatDef => patDef(tree) + } + + /** In case there is exactly one variable x_1 in pattern + * val/var p = e ==> val/var x_1 = (e: @unchecked) match (case p => (x_1)) + * + * in case there are zero or more than one variables in pattern + * val/var p = e ==> private synthetic val t$ = (e: @unchecked) match (case p => (x_1, ..., x_N)) + * val/var x_1 = t$._1 + * ... + * val/var x_N = t$._N + * If the original pattern variable carries a type annotation, so does the corresponding + * ValDef. + */ + def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree)(implicit ctx: Context): Tree = pat match { + case VarPattern(named, tpt) => + derivedValDef(mods, named, tpt, rhs) + case _ => + val rhsUnchecked = makeAnnotated(defn.UncheckedAnnot, rhs) + val vars = getVariables(pat) + val ids = for ((named, _) <- vars) yield Ident(named.name) + val caseDef = CaseDef(pat, EmptyTree, makeTuple(ids)) + val matchExpr = Match(rhsUnchecked, caseDef :: Nil) + vars match { + case (named, tpt) :: Nil => + derivedValDef(mods, named, tpt, matchExpr) + case _ => + val tmpName = ctx.freshName().toTermName + val patMods = Modifiers(PrivateLocal | Synthetic | (mods.flags & Lazy)) + val firstDef = ValDef(patMods, tmpName, TypeTree(), matchExpr) + def selector(n: Int) = Select(Ident(tmpName), ("_" + n).toTermName) + val restDefs = + for (((named, tpt), n) <- vars.zipWithIndex) + yield derivedValDef(mods, named, tpt, selector(n)) + flatTree(firstDef :: restDefs) + } } /** Make closure corresponding to function params => body */ @@ -251,6 +293,12 @@ object desugar { Function(param :: Nil, Match(Ident(param.name), cases)) } + def makeAnnotated(cls: Symbol, tree: Tree)(implicit ctx: Context) = + Annotated(TypedSplice(tpd.New(cls.typeConstructor)), tree) + + private def derivedValDef(mods: Modifiers, named: NameTree, tpt: Tree, rhs: Tree) = + ValDef(mods, named.name.asTermName, tpt, rhs).withPos(named.pos) + def apply(tree: Tree)(implicit ctx: Context): Tree = { def labelDefAndCall(lname: TermName, rhs: Tree, call: Tree) = { @@ -258,9 +306,6 @@ object desugar { Block(ldef, call) } - def derivedValDef(mods: Modifiers, named: NameTree, tpt: Tree, rhs: Tree) = - ValDef(mods, named.name.asTermName, tpt, rhs).withPos(named.pos) - /** Translate infix operation expression left op right */ def makeBinop(left: Tree, op: Name, right: Tree): Tree = { @@ -418,50 +463,6 @@ object desugar { } } - def makeAnnotated(cls: Symbol, tree: Tree) = - Annotated(TypedSplice(tpd.New(cls.typeConstructor)), tree) - - /** Returns list of all pattern variables, possibly with their types, - * without duplicates - */ - def getVariables(tree: Tree): List[VarInfo] = - getVars(new ListBuffer[VarInfo], tree).toList - - /** In case there is exactly one variable x_1 in pattern - * val/var p = e ==> val/var x_1 = (e: @unchecked) match (case p => (x_1)) - * - * in case there are zero or more than one variables in pattern - * val/var p = e ==> private synthetic val t$ = (e: @unchecked) match (case p => (x_1, ..., x_N)) - * val/var x_1 = t$._1 - * ... - * val/var x_N = t$._N - * If the original pattern variable carries a type annotation, so does the corresponding - * ValDef. - */ - def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree): Tree = pat match { - case VarPattern(named, tpt) => - derivedValDef(mods, named, tpt, rhs) - case _ => - val rhsUnchecked = makeAnnotated(defn.UncheckedAnnot, rhs) - val vars = getVariables(pat) - val ids = for ((named, _) <- vars) yield Ident(named.name) - val caseDef = CaseDef(pat, EmptyTree, makeTuple(ids)) - val matchExpr = Match(rhsUnchecked, caseDef :: Nil) - vars match { - case (named, tpt) :: Nil => - derivedValDef(mods, named, tpt, matchExpr) - case _ => - val tmpName = ctx.freshName().toTermName - val patMods = Modifiers(PrivateLocal | Synthetic | (mods.flags & Lazy)) - val firstDef = ValDef(patMods, tmpName, TypeTree(), matchExpr) - def selector(n: Int) = Select(Ident(tmpName), ("_" + n).toTermName) - val restDefs = - for (((named, tpt), n) <- vars.zipWithIndex) - yield derivedValDef(mods, named, tpt, selector(n)) - flatTree(firstDef :: restDefs) - } - } - // begin desugar tree match { case SymbolLit(str) => @@ -555,4 +556,10 @@ object desugar { } } } + + /** Returns list of all pattern variables, possibly with their types, + * without duplicates + */ + private def getVariables(tree: Tree): List[VarInfo] = + getVars(new ListBuffer[VarInfo], tree).toList } diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala index d7e0a7b3d..6ad547dc9 100644 --- a/src/dotty/tools/dotc/ast/UntypedTrees.scala +++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala @@ -38,7 +38,7 @@ object untpd extends Trees.Instance[Untyped] with TreeInfo[Untyped] { case class GenFrom(pat: Tree, expr: Tree) extends Tree case class GenAlias(pat: Tree, expr: Tree) extends Tree case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree - case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends Tree + case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends DefTree class PolyTypeDef(mods: Modifiers, name: TypeName, override val tparams: List[TypeDef], rhs: Tree) extends TypeDef(mods, name, rhs) { diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index b9d079a20..8f10816e9 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -2105,8 +2105,8 @@ object Types { def apply(tp: Type) = tp } - /** Approximate occurrences of paremter types and uninstantiated typevars - * by wildcard types + /** Approximate occurrences of parameter types and uninstantiated typevars + * by wildcard types. */ class WildApprox(implicit ctx: Context) extends TypeMap { override def apply(tp: Type) = tp match { diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 3b1fb4810..5f6a6528f 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -59,12 +59,12 @@ class Namer { typer: Typer => import untpd._ - /** A partial map from unexpanded member defs to their expansions. + /** A partial map from unexpanded member and pattern defs and to their expansions. * Populated during enterSyms, emptied during typer. */ - lazy val expandedTree = new mutable.HashMap[MemberDef, Tree] + lazy val expandedTree = new mutable.HashMap[DefTree, Tree] - /** A map from expanded MemberDef or Import trees to their symbols. + /** A map from expanded MemberDef, PatDef or Import trees to their symbols. * Populated during enterSyms, emptied at the point a typed tree * with the same symbol is created (this can be when the symbol is completed * or at the latest when the tree is typechecked. @@ -187,8 +187,8 @@ class Namer { typer: Typer => } /** The expansion of a member def */ - def expansion(mdef: MemberDef)(implicit ctx: Context): Tree = { - val expanded = desugar.memberDef(mdef) + def expansion(mdef: DefTree)(implicit ctx: Context): Tree = { + val expanded = desugar.defTree(mdef) if (expanded ne mdef) expandedTree(mdef) = expanded expanded } @@ -215,7 +215,7 @@ class Namer { typer: Typer => ctx case imp: Import => importContext(createSymbol(imp), imp.selectors) - case mdef: MemberDef => + case mdef: DefTree => expansion(mdef).toList foreach (tree => enterSymbol(createSymbol(tree))) ctx case _ => diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index c693209f4..8bd5c6975 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -754,7 +754,7 @@ class Typer extends Namer with Applications with Implicits { cpy.Typed(tree, arg1, TypeTree(ownType)) withType ownType } - def typedPackageDef(tree: untpd.PackageDef)(implicit ctx: Context): Tree = { + def typedPackageDef(tree: untpd.PackageDef)(implicit ctx: Context): Tree = { val pid1 = typedExpr(tree.pid, AnySelectionProto) val pkg = pid1.symbol val packageContext = @@ -845,7 +845,7 @@ class Typer extends Namer with Applications with Implicits { val imp1 = typed(imp) buf += imp1 traverse(rest)(importContext(imp1.symbol, imp.selectors)) - case (mdef: untpd.MemberDef) :: rest => + case (mdef: untpd.DefTree) :: rest => expandedTree remove mdef match { case Some(xtree) => traverse(xtree :: rest) |