aboutsummaryrefslogblamecommitdiff
path: root/src/dotty/tools/dotc/ast/UntypedTrees.scala
blob: f8a03385eef9e2fd22564e4861d7f55ccbf5d545 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11





                                                                                      
                                                                      



                                    
                                                                     
 
                                                                      
 
                                                                               
                                                     
 

                                                                       
                       

                                                                                                      
   
 



                                                                                                     



                                                       







                                                                                         
 
                                                                                                    






                                                                                                                         
 


                                                                                                                   

                                                                                                
                                                                        
 
                                                              
 

                                                       
 
                                                                            
 
                                                                                                                                                    
                                                                     
 
                                                       
                                          
 
                                                                     
                                                    
 



                                                                           
 



                                                                   
 

                                                                                                               



                                                                                                
                                                                        
 

                                                                        








                                                                        


       


                                                                           






                                                                                             
                                                                                                       
                                                                   
     
                                                                                                                  
                                                                                                                                    
                                                                           
     
                                                         
                                                       
                                                      
     
                                                                                                              
                                                                                                                    
                                                                              
     
                                                                         
                                                                               
                                                            
     
                                                                             
                                                                                                   
                                                                
     
                                                                
                                                                        
                                                         
     
                                                               
                                                                       
                                                        
     
                                                  
                                                
                                                 
     
                                                           
                                                       
                                                    
     
                                                                  
                                                                              
                                                           
     
                                                                  
                                                                              
                                                           
     
                                                                          
                                                                                 
                                                             
     
                                                                       
                                                                              
                                                          
     
                                                                 
                                                                            
                                                          
     
                                                                  
                                                                             
                                                           
     
                                                                                              
                                                                                                
                                                                       
     
                                                                                                  
                                                                                                                       
                                                                    


     

                                                                                                          
                                         
                                                           
                            
                                
                                                    
                                                                                 
                                  
                                                            
                                      
                                                                
                               
                                              
                              
                                             
                       
                                      
                          
                                         
                                 
                                                           
                                 
                                                           
                                   
                                                             
                                
                                                          
                                
                                                          
                                 
                                                           
                                             
                                                                          
                                          
                                                                               
                               
                                                                                                    




                             
                                                                       


































                                                             

                                             



                               
 
package dotty.tools
package dotc
package ast

import core._
import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
import Decorators._
import language.higherKinds
import collection.mutable.ListBuffer

object untpd extends Trees.Instance[Untyped] with TreeInfo[Untyped] {

// ----- Tree cases that exist in untyped form only ------------------

  /** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice */
  case class TypedSplice(tree: tpd.Tree) extends Tree

  /** mods object name impl */
  case class ModuleDef(mods: Modifiers, name: TermName, impl: Template)
    extends MemberDef {
    type ThisTree[-T >: Untyped] <: Trees.NameTree[T] with Trees.MemberDef[T] with ModuleDef
    def withName(name: Name)(implicit ctx: Context) = cpy.ModuleDef(this, mods, name.toTermName, impl)
  }

  case class SymbolLit(str: String) extends Tree
  case class InterpolatedString(id: TermName, strings: List[Literal], elems: List[Tree]) extends Tree
  case class Function(args: List[Tree], body: Tree) extends Tree
  case class InfixOp(left: Tree, op: Name, right: Tree) extends Tree
  case class PostfixOp(od: Tree, op: Name) extends Tree
  case class PrefixOp(op: Name, od: Tree) extends Tree
  case class Parens(t: Tree) extends Tree
  case class Tuple(trees: List[Tree]) extends Tree
  case class WhileDo(cond: Tree, body: Tree) extends TermTree
  case class DoWhile(body: Tree, cond: Tree) extends TermTree
  case class ForYield(enums: List[Tree], expr: Tree) extends TermTree
  case class ForDo(enums: List[Tree], body: Tree) extends TermTree
  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

  class PolyTypeDef(mods: Modifiers, name: TypeName, override val tparams: List[TypeDef], rhs: Tree)
    extends TypeDef(mods, name, rhs) {
    override def withName(name: Name)(implicit ctx: Context) = cpy.PolyTypeDef(this, mods, name.toTypeName, tparams, rhs)
  }

// ------ Additional creation methods for untyped only -----------------

  def Literal(const: Constant) = new Literal(const)

  def TypeTree(tpe: Type)(implicit ctx: Context): TypedSplice = TypedSplice(TypeTree().withType(tpe))

  def TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree)(implicit ctx: Context): TypeDef =
    if (tparams.isEmpty) TypeDef(mods, name, rhs) else new PolyTypeDef(mods, name, tparams, rhs)

// ------ Untyped tree values and creation methods ---------------------

  def unitLiteral(implicit ctx: Context) = Literal(Constant())

  def ref(tp: NamedType)(implicit ctx: Context): Tree =
    TypedSplice(tpd.ref(tp))

  def scalaUnit(implicit ctx: Context) = ref(defn.UnitClass.typeConstructor)

  def makeConstructor(mods: Modifiers, tparams: List[TypeDef], vparamss: List[List[ValDef]], rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef =
    DefDef(mods, nme.CONSTRUCTOR, tparams, vparamss, TypeTree(), rhs)

  def emptyConstructor(implicit ctx: Context): DefDef =
    makeConstructor(Modifiers(), Nil, Nil)

  def makeSelfDef(name: TermName, tpt: Tree)(implicit ctx: Context) =
    ValDef(Modifiers(Private), name, tpt, EmptyTree)

  def makeTupleOrParens(ts: List[Tree])(implicit ctx: Context) = ts match {
    case t :: Nil => Parens(t)
    case _ => Tuple(ts)
  }

  def makeTuple(ts: List[Tree])(implicit ctx: Context) = ts match {
    case t :: Nil => t
    case _ => Tuple(ts)
  }

  def makeParameter(pname: TermName, tpe: Tree, mods: Modifiers = Modifiers())(implicit ctx: Context): 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)(implicit ctx: Context) = Ident(tree.name)

// ------- A decorator for producing a path to a location --------------

  implicit class UntypedTreeDecorator(val self: Tree) extends AnyVal {
    def locateEnclosing(base: List[Tree], pos: Position): List[Tree] = {
      def encloses(elem: Any) = elem match {
        case t: Tree => t.envelope contains pos
        case _ => false
      }
      base.productIterator find encloses match {
        case Some(tree: Tree) => locateEnclosing(tree :: base, pos)
        case none => base
      }
    }
  }

// --------- Copier/Transformer/Accumulator classes for untyped trees -----

  override val cpy: UntypedTreeCopier = new UntypedTreeCopier

  class UntypedTreeCopier extends TreeCopier {
    def postProcess(tree: Tree, copied: Tree): copied.ThisTree[Untyped] =
      copied.asInstanceOf[copied.ThisTree[Untyped]]

    def ModuleDef(tree: Tree, mods: Modifiers, name: TermName, impl: Template) = tree match {
      case tree: ModuleDef if (mods eq tree.mods) && (name eq tree.name) && (impl eq tree.impl) => tree
      case _ => untpd.ModuleDef(mods, name, impl).withPos(tree.pos)
    }
    def PolyTypeDef(tree: Tree, mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree) = tree match {
      case tree: PolyTypeDef if (mods eq tree.mods) && (name eq tree.name) && (tparams eq tree.tparams) && (rhs eq tree.rhs) => tree
      case _ => new PolyTypeDef(mods, name, tparams, rhs).withPos(tree.pos)
    }
    def SymbolLit(tree: Tree, str: String) = tree match {
      case tree: SymbolLit if (str == tree.str) => tree
      case _ => untpd.SymbolLit(str).withPos(tree.pos)
    }
    def InterpolatedString(tree: Tree, id: TermName, strings: List[Literal], elems: List[Tree]) = tree match {
      case tree: InterpolatedString if (id eq tree.id) && (strings eq tree.strings) && (elems eq tree.elems) => tree
      case _ => untpd.InterpolatedString(id, strings, elems).withPos(tree.pos)
    }
    def Function(tree: Tree, args: List[Tree], body: Tree) = tree match {
      case tree: Function if (args eq tree.args) && (body eq tree.body) => tree
      case _ => untpd.Function(args, body).withPos(tree.pos)
    }
    def InfixOp(tree: Tree, left: Tree, op: Name, right: Tree) = tree match {
      case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree
      case _ => untpd.InfixOp(left, op, right).withPos(tree.pos)
    }
    def PostfixOp(tree: Tree, od: Tree, op: Name) = tree match {
      case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree
      case _ => untpd.PostfixOp(od, op).withPos(tree.pos)
    }
    def PrefixOp(tree: Tree, op: Name, od: Tree) = tree match {
      case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree
      case _ => untpd.PrefixOp(op, od).withPos(tree.pos)
    }
    def Parens(tree: Tree, t: Tree) = tree match {
      case tree: Parens if (t eq tree.t) => tree
      case _ => untpd.Parens(t).withPos(tree.pos)
    }
    def Tuple(tree: Tree, trees: List[Tree]) = tree match {
      case tree: Tuple if (trees eq tree.trees) => tree
      case _ => untpd.Tuple(trees).withPos(tree.pos)
    }
    def WhileDo(tree: Tree, cond: Tree, body: Tree) = tree match {
      case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) => tree
      case _ => untpd.WhileDo(cond, body).withPos(tree.pos)
    }
    def DoWhile(tree: Tree, body: Tree, cond: Tree) = tree match {
      case tree: DoWhile if (body eq tree.body) && (cond eq tree.cond) => tree
      case _ => untpd.DoWhile(body, cond).withPos(tree.pos)
    }
    def ForYield(tree: Tree, enums: List[Tree], expr: Tree) = tree match {
      case tree: ForYield if (enums eq tree.enums) && (expr eq tree.expr) => tree
      case _ => untpd.ForYield(enums, expr).withPos(tree.pos)
    }
    def ForDo(tree: Tree, enums: List[Tree], body: Tree) = tree match {
      case tree: ForDo if (enums eq tree.enums) && (body eq tree.body) => tree
      case _ => untpd.ForDo(enums, body).withPos(tree.pos)
    }
    def GenFrom(tree: Tree, pat: Tree, expr: Tree) = tree match {
      case tree: GenFrom if (pat eq tree.pat) && (expr eq tree.expr) => tree
      case _ => untpd.GenFrom(pat, expr).withPos(tree.pos)
    }
    def GenAlias(tree: Tree, pat: Tree, expr: Tree) = tree match {
      case tree: GenAlias if (pat eq tree.pat) && (expr eq tree.expr) => tree
      case _ => untpd.GenAlias(pat, expr).withPos(tree.pos)
    }
    def ContextBounds(tree: Tree, bounds: TypeBoundsTree, cxBounds: List[Tree]) = tree match {
      case tree: ContextBounds if (bounds eq tree.bounds) && (cxBounds eq tree.cxBounds) => tree
      case _ => untpd.ContextBounds(bounds, cxBounds).withPos(tree.pos)
    }
    def PatDef(tree: Tree, mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) = tree match {
      case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree
      case _ => untpd.PatDef(mods, pats, tpt, rhs).withPos(tree.pos)
    }
  }

  abstract class UntypedTreeTransformer(cpy: UntypedTreeCopier = untpd.cpy) extends TreeTransformer(cpy) {
    override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
      case ModuleDef(mods, name, impl) =>
        cpy.ModuleDef(tree, mods, name, transformSub(impl))
      case SymbolLit(str) =>
        cpy.SymbolLit(tree, str)
      case InterpolatedString(id, strings, elems) =>
        cpy.InterpolatedString(tree, id, transformSub(strings), transform(elems))
      case Function(args, body) =>
        cpy.Function(tree, transform(args), transform(body))
      case InfixOp(left, op, right) =>
        cpy.InfixOp(tree, transform(left), op, transform(right))
      case PostfixOp(od, op) =>
        cpy.PostfixOp(tree, transform(od), op)
      case PrefixOp(op, od) =>
        cpy.PrefixOp(tree, op, transform(od))
      case Parens(t) =>
        cpy.Parens(tree, transform(t))
      case Tuple(trees) =>
        cpy.Tuple(tree, transform(trees))
      case WhileDo(cond, body) =>
        cpy.WhileDo(tree, transform(cond), transform(body))
      case DoWhile(body, cond) =>
        cpy.DoWhile(tree, transform(body), transform(cond))
      case ForYield(enums, expr) =>
        cpy.ForYield(tree, transform(enums), transform(expr))
      case ForDo(enums, body) =>
        cpy.ForDo(tree, transform(enums), transform(body))
      case GenFrom(pat, expr) =>
        cpy.GenFrom(tree, transform(pat), transform(expr))
      case GenAlias(pat, expr) =>
        cpy.GenAlias(tree, transform(pat), transform(expr))
      case ContextBounds(bounds, cxBounds) =>
        cpy.ContextBounds(tree, transformSub(bounds), transform(cxBounds))
      case PatDef(mods, pats, tpt, rhs) =>
        cpy.PatDef(tree, mods, transform(pats), transform(tpt), transform(rhs))
      case tree: PolyTypeDef =>
        cpy.PolyTypeDef(tree, tree.mods, tree.name, transformSub(tree.tparams), transform(tree.rhs))
      case _ =>
        super.transform(tree)
    }
  }

  abstract class UntypedTreeAccumulator[X] extends TreeAccumulator[X] {
    override def foldOver(x: X, tree: Tree): X = tree match {
      case ModuleDef(mods, name, impl) =>
        this(x, impl)
      case SymbolLit(str) =>
        x
      case InterpolatedString(id, strings, elems) =>
        this(this(x, strings), elems)
      case Function(args, body) =>
        this(this(x, args), body)
      case InfixOp(left, op, right) =>
        this(this(x, left), right)
      case PostfixOp(od, op) =>
        this(x, od)
      case PrefixOp(op, od) =>
        this(x, od)
      case Parens(t) =>
        this(x, t)
      case Tuple(trees) =>
        this(x, trees)
      case WhileDo(cond, body) =>
        this(this(x, cond), body)
      case DoWhile(body, cond) =>
        this(this(x, body), cond)
      case ForYield(enums, expr) =>
        this(this(x, enums), expr)
      case ForDo(enums, body) =>
        this(this(x, enums), body)
      case GenFrom(pat, expr) =>
        this(this(x, pat), expr)
      case GenAlias(pat, expr) =>
        this(this(x, pat), expr)
      case ContextBounds(bounds, cxBounds) =>
        this(this(x, bounds), cxBounds)
      case PatDef(mods, pats, tpt, rhs) =>
        this(this(this(x, pats), tpt), rhs)
      case tree: PolyTypeDef =>
        this(this(x, tree.tparams), tree.rhs)
      case _ =>
        super.foldOver(x, tree)
    }
  }
}