Skip to content

Fix #5404: Add MatchType to TASTy reflect #5416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,12 @@ trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with CoreImpl with H
def unapply(x: CaseDef): Some[(Pattern, Option[Term], Term)] = Some(x.pat, optional(x.guard), x.body)
}

def TypeCaseDefDeco(caseDef: TypeCaseDef): TypeCaseDefAPI = new TypeCaseDefAPI {
def pattern(implicit ctx: Context): Pattern = caseDef.pat
def rhs(implicit ctx: Context): Term = caseDef.body
}

object TypeCaseDef extends TypeCaseDefExtractor {
def unapply(x: TypeCaseDef): Some[(TypeTree, TypeTree)] = Some((x.pat, x.body))
}
}
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/tastyreflect/CoreImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ trait CoreImpl extends scala.tasty.reflect.Core {
type Term = tpd.Tree

type CaseDef = tpd.CaseDef
type TypeCaseDef = tpd.CaseDef

type Pattern = tpd.Tree
type Value = tpd.Tree
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ trait TypeOrBoundsOpsImpl extends scala.tasty.reflect.TypeOrBoundsOps with CoreI
}
}

object MatchType extends MatchTypeExtractor {
def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type, List[Type])] = x match {
case Types.MatchType(bound, scrutinee, cases) => Some((bound, scrutinee, cases))
case _ => None
}
}

object ByNameType extends ByNameTypeExtractor {
def unapply(x: TypeOrBounds)(implicit ctx: Context): Option[Type] = x match {
case Types.ExprType(resType) => Some(resType.stripTypeVar)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w
}
}

object MatchType extends MatchTypeExtractor {
def unapply(x: TypeOrBoundsTree)(implicit ctx: Context): Option[(Option[TypeTree], TypeTree, List[CaseDef])] = x match {
case x: tpd.MatchTypeTree => Some((if (x.bound == tpd.EmptyTree) None else Some(x.bound), x.selector, x.cases))
case _ => None
}
}

object ByName extends ByNameExtractor {
def unapply(x: TypeTree)(implicit ctx: Context): Option[TypeTree] = x match {
case x: tpd.ByNameTypeTree => Some(x.result)
Expand Down
3 changes: 0 additions & 3 deletions compiler/test/dotc/pos-from-tasty.blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ repeatedArgs213.scala
# Error printing parent constructors that are blocks
default-super.scala

# Need to implement printing of match types
matchtype.scala

# Did not survive addition of type ascriptions in decompiled tests
i3050.scala
i4006b.scala
Expand Down
1 change: 0 additions & 1 deletion compiler/test/dotc/pos-recompilation.whitelist
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,6 @@ lookupswitch
macro-deprecate-dont-touch-backquotedidents
Map
match
matchtype
matthias3
matthias4
matthias5
Expand Down
11 changes: 11 additions & 0 deletions library/src/scala/tasty/reflect/CaseDefOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,15 @@ trait CaseDefOps extends Core {
def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)]
}


trait TypeCaseDefAPI {
def pattern(implicit ctx: Context): TypeTree
def rhs(implicit ctx: Context): TypeTree
}
implicit def TypeCaseDefDeco(caseDef: TypeCaseDef): TypeCaseDefAPI

val TypeCaseDef: TypeCaseDefExtractor
abstract class TypeCaseDefExtractor {
def unapply(x: TypeCaseDef): Option[(TypeTree, TypeTree)]
}
}
6 changes: 6 additions & 0 deletions library/src/scala/tasty/reflect/Core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ package scala.tasty.reflect
* | +- Annotated
* | +- And
* | +- Or
* | +- MatchType
* | +- ByName
* | +- TypeLambdaTree
* | +- Bind
Expand All @@ -54,6 +55,7 @@ package scala.tasty.reflect
* +- SyntheticBounds
*
* +- CaseDef
* +- TypeCaseDef
*
* +- Pattern --+- Value
* +- Bind
Expand All @@ -75,6 +77,7 @@ package scala.tasty.reflect
* +- AnnotatedType
* +- AndType
* +- OrType
* +- MatchType
* +- ByNameType
* +- ParamRef
* +- ThisType
Expand Down Expand Up @@ -137,6 +140,9 @@ trait Core {
/** Branch of a pattern match or catch clause */
type CaseDef

/** Branch of a type pattern match */
type TypeCaseDef

/** Pattern tree of the pattern part of a CaseDef */
type Pattern
type Value <: Pattern
Expand Down
66 changes: 65 additions & 1 deletion library/src/scala/tasty/reflect/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,20 @@ trait Printers
this += "TypeBoundsTree(" += lo += ", " += hi += ")"
case SyntheticBounds() =>
this += s"SyntheticBounds()"
case TypeTree.MatchType(bound, selector, cases) =>
this += "TypeTree.MatchType(" += bound += ", " += selector += ", " ++= cases += ")"
}

def visitCaseDef(x: CaseDef): Buffer = {
val CaseDef(pat, guard, body) = x
this += "CaseDef(" += pat += ", " += guard += ", " += body += ")"
}

def visitTypeCaseDef(x: TypeCaseDef): Buffer = {
val TypeCaseDef(pat, body) = x
this += "TypeCaseDef(" += pat += ", " += body += ")"
}

def visitPattern(x: Pattern): Buffer = x match {
case Pattern.Value(v) =>
this += "Pattern.Value(" += v += ")"
Expand Down Expand Up @@ -252,6 +259,8 @@ trait Printers
this += "Type.AndType(" += left += ", " += right += ")"
case Type.OrType(left, right) =>
this += "Type.OrType(" += left += ", " += right += ")"
case Type.MatchType(bound, scrutinee, cases) =>
this += "Type.MatchType(" += bound += ", " += scrutinee += ", " ++= cases += ")"
case Type.ByNameType(underlying) =>
this += "Type.ByNameType(" += underlying += ")"
case Type.ParamRef(binder, idx) =>
Expand Down Expand Up @@ -326,6 +335,11 @@ trait Printers
def ++=(x: List[CaseDef]): Buffer = { visitList(x, visitCaseDef); buff }
}

private implicit class TypeCaseDefOps(buff: Buffer) {
def +=(x: TypeCaseDef): Buffer = { visitTypeCaseDef(x); buff }
def ++=(x: List[TypeCaseDef]): Buffer = { visitList(x, visitTypeCaseDef); buff }
}

private implicit class PatternOps(buff: Buffer) {
def +=(x: Pattern): Buffer = { visitPattern(x); buff }
def ++=(x: List[Pattern]): Buffer = { visitList(x, visitPattern); buff }
Expand Down Expand Up @@ -871,6 +885,19 @@ trait Printers
this
}

def printTypes(trees: List[Type], sep: String): Buffer = {
def printSeparated(list: List[Type]): Unit = list match {
case Nil =>
case x :: Nil => printType(x)
case x :: xs =>
printType(x)
this += sep
printSeparated(xs)
}
printSeparated(trees)
this
}

def printImportSelectors(selectors: List[ImportSelector]): Buffer = {
def printSeparated(list: List[ImportSelector]): Unit = list match {
case Nil =>
Expand Down Expand Up @@ -898,6 +925,19 @@ trait Printers
this
}

def printTypeCases(cases: List[TypeCaseDef], sep: String): Buffer = {
def printSeparated(list: List[TypeCaseDef]): Unit = list match {
case Nil =>
case x :: Nil => printTypeCaseDef(x)
case x :: xs =>
printTypeCaseDef(x)
this += sep
printSeparated(xs)
}
printSeparated(cases)
this
}

def printPatterns(cases: List[Pattern], sep: String): Buffer = {
def printSeparated(list: List[Pattern]): Unit = list match {
case Nil =>
Expand Down Expand Up @@ -976,6 +1016,12 @@ trait Printers
}
inSquare(printSeparated(tparams))
if (isMember) {
body match {
case TypeTree.MatchType(Some(bound), _, _) =>
this += " <: "
printTypeTree(bound)
case _ =>
}
this += " = "
printTypeOrBoundsTree(body)
}
Expand Down Expand Up @@ -1067,6 +1113,14 @@ trait Printers
this
}

def printTypeCaseDef(caseDef: TypeCaseDef): Buffer = {
this += highlightValDef("case ", color)
printTypeTree(caseDef.pattern)
this += highlightValDef(" => ", color)
printTypeTree(caseDef.rhs)
this
}

def printPattern(pattern: Pattern): Buffer = pattern match {
case Pattern.Value(v) =>
v match {
Expand Down Expand Up @@ -1201,6 +1255,11 @@ trait Printers
this += highlightTypeDef(" | ", color)
printTypeTree(right)

case TypeTree.MatchType(bound, selector, cases) =>
printTypeTree(selector)
this += highlightKeyword(" match ", color)
inBlock(printTypeCases(cases, lineBreak()))

case TypeTree.ByName(result) =>
this += highlightTypeDef("=> ", color)
printTypeTree(result)
Expand Down Expand Up @@ -1300,6 +1359,11 @@ trait Printers
this += highlightTypeDef(" | ", color)
printType(right)

case Type.MatchType(bound, scrutinee, cases) =>
printType(scrutinee)
this += highlightKeyword(" match ", color)
inBlock(printTypes(cases, lineBreak()))

case Type.ByNameType(tp) =>
this += highlightTypeDef(" => ", color)
printType(tp)
Expand Down Expand Up @@ -1553,7 +1617,7 @@ trait Printers
}
}

// TODO Provide some of these in scala.tasty.Reflect.scala and implement them using checks on symbols for performance
// TODO Provide some of these in scala.tasty.Reflection.scala and implement them using checks on symbols for performance
private object Types {

object JavaLangObject {
Expand Down
5 changes: 5 additions & 0 deletions library/src/scala/tasty/reflect/TypeOrBoundsOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ trait TypeOrBoundsOps extends Core {
def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type)]
}

val MatchType: MatchTypeExtractor
abstract class MatchTypeExtractor {
def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[(Type, Type, List[Type])]
}

val ByNameType: ByNameTypeExtractor
abstract class ByNameTypeExtractor {
def unapply(typeOrBounds: TypeOrBounds)(implicit ctx: Context): Option[Type]
Expand Down
5 changes: 5 additions & 0 deletions library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ trait TypeOrBoundsTreeOps extends Core {
def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(TypeTree, TypeTree)]
}

val MatchType: MatchTypeExtractor
abstract class MatchTypeExtractor {
def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(Option[TypeTree], TypeTree, List[TypeCaseDef])]
}

val ByName: ByNameExtractor
abstract class ByNameExtractor {
def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[TypeTree]
Expand Down