aboutsummaryrefslogblamecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/DenotTransformers.scala
blob: 02d27ea3389e74e3e0252b9aadd4375ea072daa9 (plain) (tree)
1
2
3
4
5
6
7
8
9


                        



                       
                
                    
               
                               
                                     
 
                          
 


                                                                   
     
 
                                                              
                                        

                                                                            
                                                                               


                                                                      
                                        


                                                                                 
   
 
                                                                         



                                                                         
                                                                                     








                                                                        

       





                                                                                      
   
 










                                                                                               






                                                                                       
 
package dotty.tools.dotc
package core

import Periods._
import SymDenotations._
import Contexts._
import Types._
import Symbols._
import Denotations._
import Phases._
import java.lang.AssertionError
import dotty.tools.dotc.util.DotClass

object DenotTransformers {

  /** A transformer group contains a sequence of transformers,
   *  ordered by the phase where they apply. Transformers are added
   *  to a group via `install`.
   */

  /** A transformer transforms denotations at a given phase */
  trait DenotTransformer extends Phase {

    /** The last phase during which the transformed denotations are valid */
    def lastPhaseId(implicit ctx: Context) = ctx.nextDenotTransformerId(id + 1)

    /** The validity period of the transformer in the given context */
    def validFor(implicit ctx: Context): Period =
      Period(ctx.runId, id, lastPhaseId)

    /** The transformation method */
    def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation
  }

  /** A transformer that only transforms the info field of denotations */
  trait InfoTransformer extends DenotTransformer {

    def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type

    def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = {
      val sym = ref.symbol
      if (sym.exists && !mayChange(sym)) ref
      else {
        val info1 = transformInfo(ref.info, ref.symbol)
        if (info1 eq ref.info) ref
        else ref match {
          case ref: SymDenotation => ref.copySymDenotation(info = info1)
          case _ => ref.derivedSingleDenotation(ref.symbol, info1)
        }
      }
    }

    /** Denotations with a symbol where `mayChange` is false are guaranteed to be
     *  unaffected by this transform, so `transformInfo` need not be run. This
     *  can save time, and more importantly, can help avoid forcing symbol completers.
     */
    protected def mayChange(sym: Symbol)(implicit ctx: Context): Boolean = true
  }

  /** A transformer that only transforms SymDenotations */
  trait SymTransformer extends DenotTransformer {

    def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation

    def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match {
      case ref: SymDenotation => transformSym(ref)
      case _ => ref
    }
  }

  /** A `DenotTransformer` trait that has the identity as its `transform` method.
   *  You might want to inherit from this trait so that new denotations can be
   *  installed using `installAfter` and `enteredAfter` at the end of the phase.
   */
  trait IdentityDenotTransformer extends DenotTransformer {
    def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref
  }
}