Skip to content

Commit 7cc1e37

Browse files
committed
Base augment syntax on type patterns
1 parent 1c13524 commit 7cc1e37

File tree

5 files changed

+54
-62
lines changed

5 files changed

+54
-62
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -750,9 +750,15 @@ object desugar {
750750
}
751751
}
752752

753+
/** Expand variable identifier x to x @ _ */
754+
def patternVar(tree: Tree)(implicit ctx: Context) = {
755+
val Ident(name) = tree
756+
Bind(name, Ident(nme.WILDCARD)).withPos(tree.pos)
757+
}
758+
753759
def decomposeTypePattern(tree: Tree)(implicit ctx: Context): (Tree, List[TypeDef]) = {
754760
val bindingsBuf = new ListBuffer[TypeDef]
755-
val elimTypeDefs = new untpd.TreeMap {
761+
val elimTypeDefs = new untpd.UntypedTreeMap {
756762
override def transform(tree: Tree)(implicit ctx: Context) = tree match {
757763
case tree: TypeDef =>
758764
bindingsBuf += tree
@@ -764,12 +770,6 @@ object desugar {
764770
(elimTypeDefs.transform(tree), bindingsBuf.toList)
765771
}
766772

767-
/** Expand variable identifier x to x @ _ */
768-
def patternVar(tree: Tree)(implicit ctx: Context) = {
769-
val Ident(name) = tree
770-
Bind(name, Ident(nme.WILDCARD)).withPos(tree.pos)
771-
}
772-
773773
/** augment <name> <type-params> <params> extends <parents> { <body>} }
774774
* ->
775775
* implicit class <deconame> <type-params> ($this: name <type-args>) <params>
@@ -789,33 +789,36 @@ object desugar {
789789
* <body1> = <body> with each occurrence of unqualified `this` substituted by `$this`.
790790
*/
791791
def augmentation(tree: Augment)(implicit ctx: Context): Tree = {
792-
val Augment(name, impl) = tree
793-
val constr @ DefDef(_, tparams, vparamss, _, _) = impl.constr
794-
var decorated: Tree = Ident(name)
795-
if (tparams.nonEmpty)
796-
decorated =
797-
if (name.isEmpty) refOfDef(tparams.head)
798-
else AppliedTypeTree(decorated, tparams.map(refOfDef))
792+
val Augment(augmented, impl) = tree
793+
val constr @ DefDef(_, Nil, vparamss, _, _) = impl.constr
794+
val (decorated, bindings) = decomposeTypePattern(augmented)
799795
val firstParam = ValDef(nme.SELF, decorated, EmptyTree).withFlags(Private | Local | ParamAccessor)
800-
val constr1 = cpy.DefDef(constr)(vparamss = (firstParam :: Nil) :: vparamss)
796+
val constr1 =
797+
cpy.DefDef(constr)(
798+
tparams = bindings.map(_.withFlags(Param | Private | Local)),
799+
vparamss = (firstParam :: Nil) :: vparamss)
801800
val substThis = new UntypedTreeMap {
802801
override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
803802
case This(Ident(tpnme.EMPTY)) => Ident(nme.SELF).withPos(tree.pos)
804803
case _ => super.transform(tree)
805804
}
806805
}
807-
def targetSuffix(tree: Tree): String = tree match {
808-
case Apply(tycon, args) => targetSuffix(tycon)
809-
case TypeApply(tycon, args) => targetSuffix(tycon)
810-
case Select(pre, nme.CONSTRUCTOR) => targetSuffix(pre)
811-
case New(tpt) => targetSuffix(tpt)
812-
case AppliedTypeTree(tycon, _) => targetSuffix(tycon)
813-
case tree: RefTree => "To" ++ tree.name.toString
814-
case _ => str.Augmentation
815-
}
816-
val decoName: TypeName = impl.parents match {
817-
case parent :: _ => name ++ targetSuffix(parent)
818-
case _ => name ++ str.Augmentation
806+
val decoName = {
807+
def clsName(tree: Tree): String = tree match {
808+
case Apply(tycon, args) => clsName(tycon)
809+
case TypeApply(tycon, args) => clsName(tycon)
810+
case Select(pre, nme.CONSTRUCTOR) => clsName(pre)
811+
case New(tpt) => clsName(tpt)
812+
case AppliedTypeTree(tycon, _) => clsName(tycon)
813+
case tree: RefTree if tree.name.isTypeName => tree.name.toString
814+
case _ => ""
815+
}
816+
val fromName = clsName(augmented)
817+
val toName = impl.parents match {
818+
case parent :: _ if !clsName(parent).isEmpty => clsName(parent)
819+
case _ => str.Augmentation
820+
}
821+
fromName ++ toName
819822
}
820823
val icls =
821824
TypeDef(UniqueName.fresh(decoName.toTermName).toTypeName,

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
4040
def withName(name: Name)(implicit ctx: Context) = cpy.ModuleDef(this)(name.toTermName, impl)
4141
}
4242

43-
/** augment name impl */
44-
case class Augment(name: TypeName, impl: Template) extends DefTree
43+
/** augment augmented impl */
44+
case class Augment(augmented: Tree, impl: Template) extends DefTree
4545

4646
case class ParsedTry(expr: Tree, handler: Tree, finalizer: Tree) extends TermTree
4747

@@ -414,9 +414,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
414414
case tree: ModuleDef if (name eq tree.name) && (impl eq tree.impl) => tree
415415
case _ => finalize(tree, untpd.ModuleDef(name, impl))
416416
}
417-
def Augment(tree: Tree)(name: TypeName, impl: Template) = tree match {
418-
case tree: Augment if (name eq tree.name) && (impl eq tree.impl) => tree
419-
case _ => finalize(tree, untpd.Augment(name, impl))
417+
def Augment(tree: Tree)(augmented: Tree, impl: Template) = tree match {
418+
case tree: Augment if (augmented eq tree.augmented) && (impl eq tree.impl) => tree
419+
case _ => finalize(tree, untpd.Augment(augmented, impl))
420420
}
421421
def ParsedTry(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree) = tree match {
422422
case tree: ParsedTry

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,17 +2303,16 @@ object Parsers {
23032303
Template(constr, parents, EmptyValDef, Nil)
23042304
}
23052305

2306-
/** Augmentation ::= ‘augment’ (id | [id] ClassTypeParamClause)
2307-
* [[nl] ImplicitParamClause] TemplateClause
2306+
/** Augmentation ::= ‘augment’ BindingTypePattern
2307+
* [[nl] ImplicitParamClause] TemplateClause
2308+
* BindingTypePattern ::= AnnotType
23082309
*/
23092310
def augmentation(): Augment = atPos(in.skipToken(), nameStart) {
2310-
val (name, tparams) =
2311-
if (isIdent) (ident().toTypeName, typeParamClauseOpt(ParamOwner.Class))
2312-
else (tpnme.EMPTY, typeParamClause(ParamOwner.Class))
2313-
val vparamss = paramClauses(name, ofAugmentation = true)
2314-
val constr = makeConstructor(tparams, vparamss)
2311+
val augmented = withinTypePattern(binding = true)(annotType())
2312+
val vparamss = paramClauses(tpnme.EMPTY, ofAugmentation = true).take(1)
2313+
val constr = makeConstructor(Nil, vparamss)
23152314
val templ = templateClauseOpt(constr, bodyRequired = true)
2316-
Augment(name, templ)
2315+
Augment(augmented, templ)
23172316
}
23182317

23192318
/* -------- TEMPLATES ------------------------------------------- */

docs/docs/internals/syntax.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ ArgumentPatterns ::= ‘(’ [Patterns] ‘)’
249249
250250
Augmentation ::= ‘augment’ BindingTypePattern
251251
[[nl] ImplicitParamClause] TemplateClause Augment(name, templ)
252-
BindingTypePattern::= Type
252+
BindingTypePattern::= AnnotType
253253
```
254254

255255
### Type and Value Parameters

tests/pos/augment.scala

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,17 @@ object augments {
2121

2222
// Generic trait implementations
2323

24-
augment List[T] {
24+
augment List[type T] {
2525
def second = this.tail.head
2626
}
2727

28-
// cf implementation of Array#summ below
29-
augment List[T <: Int] {
28+
// Specific trait implementations
29+
30+
augment List[Int] {
3031
def maxx = (0 /: this)(_ `max` _)
3132
}
3233

33-
// cf implementation of Array#summ below
34-
augment Array[T >: Int <: Int] {
34+
augment Array[Int] {
3535
def maxx = (0 /: this)(_ `max` _)
3636
}
3737

@@ -43,13 +43,13 @@ object augments {
4343
def eql (x: T, y: T): Boolean
4444
}
4545

46-
augment Rectangle[T: Eql] {
46+
augment Rectangle[type T: Eql] {
4747
def isSquare: Boolean = implicitly[Eql[T]].eql(this.width, this.height)
4848
}
4949

5050
// Simple generic augments
5151

52-
augment [T] {
52+
augment (type T) {
5353
def ~[U](that: U): (T, U) = (this, that)
5454
}
5555

@@ -59,33 +59,25 @@ object augments {
5959
def === (that: T): Boolean
6060
}
6161

62-
augment [T: Eql] extends HasEql[T] {
62+
augment (type T: Eql) extends HasEql[T] {
6363
def === (that: T): Boolean = implicitly[Eql[T]].eql(this, that)
6464
}
6565

66-
augment Rectangle[T: Eql] {
66+
augment Rectangle[type T: Eql] {
6767
def === (that: Rectangle[T]) =
6868
this.x === that.x &&
6969
this.y === that.y &&
7070
this.width == that.width &&
7171
this.height == that.height
7272
}
7373

74-
augment [T <: List[Int]] {
75-
def summ = (0 /: this)(_ + _)
76-
}
77-
78-
augment [T <: Array[Int]] {
79-
def summ = (0 /: this)(_ + _)
80-
}
81-
8274
// Generic augments with additional parameters
8375

84-
augment [T <: List[List[U]], U] {
76+
augment List[List[type U]] {
8577
def flattened: List[U] = (this :\ (Nil: List[U]))(_ ++ _)
8678
}
8779

88-
augment [T <: (U, U), U: Eql] {
80+
augment (type T: Eql, T) {
8981
def isSame = this._1 === this._2
9082
}
9183
}
@@ -110,9 +102,7 @@ object Test extends App {
110102
println(List(1, 2, 3).second)
111103
println(List(List(1), List(2, 3)).flattened)
112104
println(List(List(1), List(2, 3)).flattened.maxx)
113-
println(List(List(1), List(2, 3)).flattened.summ)
114105
println(Array(1, 2, 3).maxx)
115-
println(Array(1, 2, 3).summ)
116106
println((2, 3).isSame)
117107
println((3, 3).isSame)
118108
}

0 commit comments

Comments
 (0)