alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (BaseTypeSeqs.scala)

This example Scala source code file (BaseTypeSeqs.scala) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Scala source code examples by using tags.

All credit for the original source code belongs to scala-lang.org; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Scala tags/keywords

array, basetypeseq, boolean, collection, cyclicinheritance, int, list, mappedbasetypeseq, math, refinedtype, symbol, type

The BaseTypeSeqs.scala Scala example source code

/* NSC -- new Scala compiler
 * Copyright 2005-2013 LAMP/EPFL
 * @author  Martin Odersky
 */
package scala
package reflect
package internal

// todo implement in terms of BitSet
import scala.collection.{ mutable, immutable }
import scala.math.max
import util.Statistics

/** A base type sequence (BaseTypeSeq) is an ordered sequence spanning all the base types
 *  of a type. It characterized by the following two laws:
 *
 *  (1) Each element of `tp.baseTypeSeq`  is a basetype of `tp`
 *  (2) For each basetype `bt1` of `tp` there is an element `bt` in `tp.baseTypeSeq` such that
 *
 *      bt.typeSymbol = bt1.typeSymbol
 *      bt <: bt1
 *
 *  (3) The type symbols of different elements are different.
 *
 *  Elements in the sequence are ordered by Symbol.isLess.
 *  @note base type sequences were called closures up to 2.7.1. The name has been changed
 *  to avoid confusion with function closures.
 */
trait BaseTypeSeqs {
  this: SymbolTable =>
  import definitions._
  import BaseTypeSeqsStats._

  protected def newBaseTypeSeq(parents: List[Type], elems: Array[Type]) =
    new BaseTypeSeq(parents, elems)

  /** Note: constructor is protected to force everyone to use the factory method newBaseTypeSeq instead.
   *  This is necessary because when run from reflection every base type sequence needs to have a
   *  SynchronizedBaseTypeSeq as mixin.
   */
  class BaseTypeSeq protected[reflect] (private[BaseTypeSeqs] val parents: List[Type], private[BaseTypeSeqs] val elems: Array[Type]) {
  self =>
    if (Statistics.canEnable) Statistics.incCounter(baseTypeSeqCount)
    if (Statistics.canEnable) Statistics.incCounter(baseTypeSeqLenTotal, elems.length)

    /** The number of types in the sequence */
    def length: Int = elems.length

    // #3676 shows why we can't store NoType in elems to mark cycles
    // (while NoType is in there to indicate a cycle in this BTS, during the execution of
    //  the mergePrefixAndArgs below, the elems get copied without the pending map,
    //  so that NoType's are seen instead of the original type --> spurious compile error)
    private val pending = new mutable.BitSet(length)

    /** The type at i'th position in this sequence; lazy types are returned evaluated. */
    def apply(i: Int): Type =
      if(pending contains i) {
        pending.clear()
        throw CyclicInheritance
      } else
        elems(i) match {
          case rtp @ RefinedType(variants, decls) =>
            // can't assert decls.isEmpty; see t0764
            //if (!decls.isEmpty) abort("computing closure of "+this+":"+this.isInstanceOf[RefinedType]+"/"+closureCache(j))
            //Console.println("compute closure of "+this+" => glb("+variants+")")
            pending += i
            try {
              mergePrefixAndArgs(variants, Variance.Contravariant, lubDepth(variants)) match {
                case NoType => typeError("no common type instance of base types "+(variants mkString ", and ")+" exists.")
                case tp0    =>
                  pending(i) = false
                  elems(i) = tp0
                  tp0
              }
            }
            catch {
              case CyclicInheritance =>
                typeError(
                  "computing the common type instance of base types "+(variants mkString ", and ")+" leads to a cycle.")
            }
          case tp =>
            tp
        }

    def rawElem(i: Int) = elems(i)

    /** The type symbol of the type at i'th position in this sequence;
     *  no evaluation needed.
     */
    def typeSymbol(i: Int): Symbol = {
      elems(i) match {
        case RefinedType(v :: vs, _) => v.typeSymbol
        case tp => tp.typeSymbol
      }
    }

    /** Return all evaluated types in this sequence as a list */
    def toList: List[Type] = elems.toList

    def copy(head: Type, offset: Int): BaseTypeSeq = {
      val arr = new Array[Type](elems.length + offset)
      scala.compat.Platform.arraycopy(elems, 0, arr, offset, elems.length)
      arr(0) = head
      newBaseTypeSeq(parents, arr)
    }

    /** Compute new base type sequence with `tp` prepended to this sequence */
    def prepend(tp: Type): BaseTypeSeq = copy(tp, 1)

    /** Compute new base type sequence with `tp` replacing the head of this sequence */
    def updateHead(tp: Type): BaseTypeSeq = copy(tp, 0)

    /** Compute new base type sequence where every element is mapped
     *  with function `f`. Lazy types are mapped but not evaluated */
    def map(f: Type => Type): BaseTypeSeq = {
	  // inlined `elems map f` for performance
      val len = length
      val arr = new Array[Type](len)
      var i = 0
      while (i < len) {
        arr(i) = f(elems(i))
        i += 1
      }
      newBaseTypeSeq(parents, arr)
    }

    def lateMap(f: Type => Type): BaseTypeSeq = new MappedBaseTypeSeq(this, f)

    def exists(p: Type => Boolean): Boolean = elems exists p

    lazy val maxDepth = maxDepthOfElems

    protected def maxDepthOfElems: Depth = {
      var d = Depth.Zero
      1 until length foreach (i => d = d max typeDepth(elems(i)))
      d
    }

    override def toString = elems.mkString("BTS(", ",", ")")

    private def typeError(msg: String): Nothing =
      throw new TypeError(
        "the type intersection "+(parents mkString " with ")+" is malformed"+
        "\n --- because ---\n"+msg)
  }

  /** A merker object for a base type sequence that's no yet computed.
   *  used to catch inheritance cycles
   */
  val undetBaseTypeSeq: BaseTypeSeq = newBaseTypeSeq(List(), Array())

  /** Create a base type sequence consisting of a single type */
  def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = newBaseTypeSeq(List(), Array(tp))

  /** Create the base type sequence of a compound type wuth given tp.parents */
  def compoundBaseTypeSeq(tp: Type): BaseTypeSeq = {
    val tsym = tp.typeSymbol
    val parents = tp.parents
//    Console.println("computing baseTypeSeq of " + tsym.tpe + " " + parents)//DEBUG
    val buf = new mutable.ListBuffer[Type]
    buf += tsym.tpe_*
    var btsSize = 1
    if (parents.nonEmpty) {
      val nparents = parents.length
      val pbtss = new Array[BaseTypeSeq](nparents)
      val index = new Array[Int](nparents)
      var i = 0
      for (p <- parents) {
        val parentBts = p.dealias.baseTypeSeq // dealias need for SI-8046.
        pbtss(i) =
          if (parentBts eq undetBaseTypeSeq) AnyClass.info.baseTypeSeq
          else parentBts
        index(i) = 0
        i += 1
      }
      def nextTypeSymbol(i: Int): Symbol = {
        val j = index(i)
        val pbts = pbtss(i)
        if (j < pbts.length) pbts.typeSymbol(j) else AnyClass
      }
      def nextRawElem(i: Int): Type = {
        val j = index(i)
        val pbts = pbtss(i)
        if (j < pbts.length) pbts.rawElem(j) else AnyTpe
      }
      var minSym: Symbol = NoSymbol
      while (minSym != AnyClass) {
        minSym = nextTypeSymbol(0)
        i = 1
        while (i < nparents) {
          val nextSym = nextTypeSymbol(i)
          if (nextSym isLess minSym)
            minSym = nextSym
          i += 1
        }
        var minTypes: List[Type] = List()
        def alreadyInMinTypes(tp: Type): Boolean = {
          @annotation.tailrec def loop(tps: List[Type]): Boolean = tps match {
            case Nil     => false
            case x :: xs => (tp =:= x) || loop(xs)
          }
          loop(minTypes)
        }

        i = 0
        while (i < nparents) {
          if (nextTypeSymbol(i) == minSym) {
            nextRawElem(i) match {
              case RefinedType(variants, decls) =>
                for (tp <- variants)
                  if (!alreadyInMinTypes(tp)) minTypes ::= tp
              case tp =>
                if (!alreadyInMinTypes(tp)) minTypes ::= tp
            }
            index(i) = index(i) + 1
          }
          i += 1
        }
        buf += intersectionType(minTypes)
        btsSize += 1
      }
    }
    val elems = new Array[Type](btsSize)
    buf.copyToArray(elems, 0)
//    Console.println("computed baseTypeSeq of " + tsym.tpe + " " + parents + ": "+elems.toString)//DEBUG
    newBaseTypeSeq(parents, elems)
  }

  class MappedBaseTypeSeq(orig: BaseTypeSeq, f: Type => Type) extends BaseTypeSeq(orig.parents map f, orig.elems) {
    override def apply(i: Int) = f(orig.apply(i))
    override def rawElem(i: Int) = f(orig.rawElem(i))
    override def typeSymbol(i: Int) = orig.typeSymbol(i)
    override def toList = orig.toList map f
    override def copy(head: Type, offset: Int) = (orig map f).copy(head, offset)
    override def map(g: Type => Type) = lateMap(g)
    override def lateMap(g: Type => Type) = orig.lateMap(x => g(f(x)))
    override def exists(p: Type => Boolean) = elems exists (x => p(f(x)))
    override protected def maxDepthOfElems: Depth = elems.map(x => typeDepth(f(x))).max
    override def toString = elems.mkString("MBTS(", ",", ")")
  }

  val CyclicInheritance = new Throwable
}

object BaseTypeSeqsStats {
  val baseTypeSeqCount = Statistics.newCounter("#base type seqs")
  val baseTypeSeqLenTotal = Statistics.newRelCounter("avg base type seq length", baseTypeSeqCount)
}

Other Scala source code examples

Here is a short list of links related to this Scala BaseTypeSeqs.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.