Skip to content

Add TASTy reflect constructors #5438

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
Dec 18, 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
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -975,13 +975,13 @@ object Trees {
* so that they selectively retype themselves. Retyping needs a context.
*/
abstract class TreeCopier {
def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T]
def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T]
protected def postProcess(tree: Tree, copied: untpd.Tree): copied.ThisTree[T]
protected def postProcess(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T]

def finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] =
protected def finalize(tree: Tree, copied: untpd.Tree): copied.ThisTree[T] =
postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree))

def finalize(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] =
protected def finalize(tree: Tree, copied: untpd.MemberDef): copied.ThisTree[T] =
postProcess(tree, copied.withPos(tree.pos).withAttachmentsFrom(tree))

def Ident(tree: Tree)(name: Name): Ident = tree match {
Expand Down
13 changes: 13 additions & 0 deletions compiler/src/dotty/tools/dotc/tastyreflect/CaseDefOpsImpl.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dotty.tools.dotc.tastyreflect

import dotty.tools.dotc.ast.tpd

trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with CoreImpl with Helpers {

Expand All @@ -10,6 +11,12 @@ trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with CoreImpl with H
}

object CaseDef extends CaseDefModule {
def apply(pattern: Pattern, guard: Option[Term], body: Term)(implicit ctx: Context): CaseDef =
tpd.CaseDef(pattern, guard.getOrElse(tpd.EmptyTree), body)

def copy(original: CaseDef)(pattern: Pattern, guard: Option[Term], body: Term)(implicit ctx: Context): CaseDef =
tpd.cpy.CaseDef(original)(pattern, guard.getOrElse(tpd.EmptyTree), body)

def unapply(x: CaseDef): Some[(Pattern, Option[Term], Term)] = Some(x.pat, optional(x.guard), x.body)
}

Expand All @@ -19,6 +26,12 @@ trait CaseDefOpsImpl extends scala.tasty.reflect.CaseDefOps with CoreImpl with H
}

object TypeCaseDef extends TypeCaseDefModule {
def apply(pattern: TypeTree, body: TypeTree)(implicit ctx: Context): TypeCaseDef =
tpd.CaseDef(pattern, tpd.EmptyTree, body)

def copy(original: TypeCaseDef)(pattern: TypeTree, body: TypeTree)(implicit ctx: Context): TypeCaseDef =
tpd.cpy.CaseDef(original)(pattern, tpd.EmptyTree, body)

def unapply(x: TypeCaseDef): Some[(TypeTree, TypeTree)] = Some((x.pat, x.body))
}
}
15 changes: 8 additions & 7 deletions compiler/src/dotty/tools/dotc/tastyreflect/CoreImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ trait CoreImpl extends scala.tasty.reflect.Core {
type Term = tpd.Tree
val Term: TermCoreModuleImpl
trait TermCoreModuleImpl extends TermCoreModule {
type Ident = tpd.Ident
type Select = tpd.Select
type Ref = tpd.RefTree
type Ident = tpd.Ident
type Select = tpd.Select
type Literal = tpd.Literal
type This = tpd.This
type New = tpd.New
Expand Down Expand Up @@ -56,8 +57,8 @@ trait CoreImpl extends scala.tasty.reflect.Core {
type Pattern = tpd.Tree
type Value = tpd.Tree
type Bind = tpd.Bind
type Unapply = tpd.Tree
type Alternative = tpd.Alternative
type Unapply = tpd.UnApply
type Alternatives = tpd.Alternative
type TypeTest = tpd.Typed

type TypeOrBoundsTree = tpd.Tree
Expand All @@ -67,7 +68,7 @@ trait CoreImpl extends scala.tasty.reflect.Core {
type Inferred = tpd.TypeTree
type Ident = tpd.Ident
type Select = tpd.Select
type Project = tpd.Select
type Projection = tpd.Select
type Singleton = tpd.SingletonTypeTree
type Refined = tpd.RefinedTypeTree
type Applied = tpd.AppliedTypeTree
Expand All @@ -77,8 +78,8 @@ trait CoreImpl extends scala.tasty.reflect.Core {
type MatchType = tpd.MatchTypeTree
type ByName = tpd.ByNameTypeTree
type LambdaTypeTree = tpd.LambdaTypeTree
type Bind = tpd.Bind
type Block = tpd.Block
type TypeBind = tpd.Bind
type TypeBlock = tpd.Block
}
type TypeBoundsTree = tpd.TypeBoundsTree
type WildcardType = tpd.TypeTree
Expand Down
109 changes: 97 additions & 12 deletions compiler/src/dotty/tools/dotc/tastyreflect/PatternOpsImpl.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
package dotty.tools.dotc.tastyreflect

import dotty.tools.dotc.ast.{Trees, tpd}
import dotty.tools.dotc.ast.{Trees, tpd, untpd}
import dotty.tools.dotc.core.Contexts
import dotty.tools.dotc.core.Decorators._
import dotty.tools.dotc.core.StdNames.nme

trait PatternOpsImpl extends scala.tasty.reflect.PatternOps with CoreImpl {

def ValueDeco(value: Value): Pattern.ValueAPI = new Pattern.ValueAPI {
def value(implicit ctx: Context): Term = value
}
def BindDeco(bind: Bind): Pattern.BindAPI = new Pattern.BindAPI {
def name(implicit ctx: Context): String = bind.name.toString
def pattern(implicit ctx: Context): Pattern = bind.body
}
def UnapplyDeco(unapply: Unapply): Pattern.UnapplyAPI = new Pattern.UnapplyAPI {
def fun(implicit ctx: Context): Term = unapply.fun
def implicits(implicit ctx: Context): List[Term] = unapply.implicits
def patterns(implicit ctx: Context): List[Pattern] = effectivePatterns(unapply.patterns)

private def effectivePatterns(patterns: List[Pattern]): List[Pattern] = patterns match {
case patterns0 :+ Trees.SeqLiteral(elems, _) => patterns0 ::: elems
case _ => patterns
}
}
def AlternativeDeco(alternatives: Alternatives): Pattern.AlternativesAPI = new Pattern.AlternativesAPI {
def patterns(implicit ctx: Context): List[Pattern] = alternatives.trees
}
def TypeTestDeco(typeTest: TypeTest): Pattern.TypeTestAPI = new Pattern.TypeTestAPI {
def tpt(implicit ctx: Context): TypeTree = typeTest.tpt
}

// ----- Patterns -------------------------------------------------

def PatternDeco(pattern: Pattern): PatternAPI = new PatternAPI {
Expand All @@ -14,45 +40,104 @@ trait PatternOpsImpl extends scala.tasty.reflect.PatternOps with CoreImpl {

object Pattern extends PatternModule {

object Value extends ValueModule {
def unapply(x: Pattern)(implicit ctx: Context): Option[Term] = x match {
object IsValue extends IsValueModule {
def unapply(pattern: Pattern)(implicit ctx: Context): Option[Value] = pattern match {
case lit: tpd.Literal => Some(lit)
case ref: tpd.RefTree if ref.isTerm => Some(ref)
case ths: tpd.This => Some(ths)
case _ => None
}
}

object Value extends ValueModule {
def apply(term: Term)(implicit ctx: Context): Value = term match {
case lit: tpd.Literal => lit
case ref: tpd.RefTree if ref.isTerm => ref
case ths: tpd.This => ths
}
def copy(original: Value)(term: Term)(implicit ctx: Context): Value = term match {
case lit: tpd.Literal => tpd.cpy.Literal(original)(lit.const)
case ref: tpd.RefTree if ref.isTerm => tpd.cpy.Ref(original.asInstanceOf[tpd.RefTree])(ref.name)
case ths: tpd.This => tpd.cpy.This(original)(ths.qual)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need apply and copy for Value? I have the impression that constructors are usually concrete.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am considering splitting the Value type into more concrete types for literals and term references

def unapply(x: Pattern)(implicit ctx: Context): Option[Term] = IsValue.unapply(x)
}

object IsBind extends IsBindModule {
def unapply(x: Pattern)(implicit ctx: Context): Option[Bind] = x match {
case x: tpd.Bind if x.name.isTermName => Some(x)
case _ => None
}
}

object Bind extends BindModule {
def unapply(x: Pattern)(implicit ctx: Context): Option[(String, Pattern)] = x match {
case x: tpd.Bind if x.name.isTermName => Some(x.name.toString, x.body)

def copy(original: Bind)(name: String, pattern: Pattern)(implicit ctx: Context): Bind =
tpd.cpy.Bind(original)(name.toTermName, pattern)

def unapply(pattern: Pattern)(implicit ctx: Context): Option[(String, Pattern)] = pattern match {
case IsBind(pattern) => Some((pattern.name.toString, pattern.body))
case _ => None
}
}

object IsUnapply extends IsUnapplyModule {
def unapply(pattern: Pattern)(implicit ctx: Context): Option[Unapply] = pattern match {
case pattern @ Trees.UnApply(_, _, _) => Some(pattern)
case Trees.Typed(pattern @ Trees.UnApply(_, _, _), _) => Some(pattern)
case _ => None
}
}

object Unapply extends UnapplyModule {

def copy(original: Unapply)(fun: Term, implicits: List[Term], patterns: List[Pattern])(implicit ctx: Context): Unapply =
tpd.cpy.UnApply(original)(fun, implicits, patterns)

def unapply(x: Pattern)(implicit ctx: Context): Option[(Term, List[Term], List[Pattern])] = x match {
case Trees.UnApply(fun, implicits, patterns) => Some((fun, implicits, effectivePatterns(patterns)))
case Trees.Typed(Trees.UnApply(fun, implicits, patterns), _) => Some((fun, implicits, effectivePatterns(patterns)))
case IsUnapply(x) => Some((x.fun, x.implicits, UnapplyDeco(x).patterns))
case _ => None
}
private def effectivePatterns(patterns: List[Pattern]): List[Pattern] = patterns match {
case patterns0 :+ Trees.SeqLiteral(elems, _) => patterns0 ::: elems
case _ => patterns
}

object IsAlternatives extends IsAlternativesModule {
def unapply(pattern: Pattern)(implicit ctx: Context): Option[Alternatives] = pattern match {
case pattern: tpd.Alternative => Some(pattern)
case _ => None
}
}

object Alternative extends AlternativeModule {
object Alternatives extends AlternativesModule {
def apply(patterns: List[Pattern])(implicit ctx: Context): Alternatives =
tpd.Alternative(patterns)

def copy(original: Alternatives)(patterns: List[Pattern])(implicit ctx: Context): Alternatives =
tpd.cpy.Alternative(original)(patterns)

def unapply(x: Pattern)(implicit ctx: Context): Option[List[Pattern]] = x match {
case x: tpd.Alternative => Some(x.trees)
case _ => None
}
}

object IsTypeTest extends IsTypeTestModule {
def unapply(pattern: Pattern)(implicit ctx: Context): Option[TypeTest] = pattern match {
case Trees.Typed(_: tpd.UnApply, _) => None
case pattern: tpd.Typed => Some(pattern)
case _ => None
}
}

object TypeTest extends TypeTestModule {
def apply(tpt: TypeTree)(implicit ctx: Context): TypeTest =
tpd.Typed(untpd.Ident(nme.WILDCARD).withType(tpt.tpe), tpt)

def copy(original: TypeTest)(tpt: TypeTree)(implicit ctx: Context): TypeTest =
tpd.cpy.Typed(original)(untpd.Ident(nme.WILDCARD).withType(tpt.tpe), tpt)

def unapply(x: Pattern)(implicit ctx: Context): Option[TypeTree] = x match {
case Trees.Typed(Trees.UnApply(_, _, _), _) => None
case Trees.Typed(_, tpt) => Some(tpt)
case Trees.Typed(expr, tpt) => Some(tpt)
case _ => None
}
}
Expand Down
Loading