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 the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

anyclass, array, array, basetypeseq, basetypeseq, boolean, cyclicinheritance, int, int, list, refinedtype, symbol, type, type

The Scala BaseTypeSeqs.scala source code

/* NSC -- new Scala compiler
 * Copyright 2005-2011 LAMP/EPFL
 * @author  Martin Odersky
 */
package scala.tools.nsc
package symtab

// todo implement in terms of BitSet
import scala.collection.mutable.{ListBuffer, BitSet}
import 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._

  class BaseTypeSeq(parents: List[Type], elems: Array[Type]) {
  self =>
    incCounter(baseTypeSeqCount)
    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)
    val pending = new 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) assert(false, "computing closure of "+this+":"+this.isInstanceOf[RefinedType]+"/"+closureCache(j))
            //Console.println("compute closure of "+this+" => glb("+variants+")")
            pending += i
            try {
              mergePrefixAndArgs(variants, -1, lubDepth(variants)) match {
                case Some(tp0) =>
                  pending(i) = false
                  elems(i) = tp0
                  tp0
                case None =>
                  typeError(
                    "no common type instance of base types "+(variants mkString ", and ")+" exists.")
              }
            } 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

    protected def copy(head: Type, offset: Int): BaseTypeSeq = {
      val arr = new Array[Type](elems.length + offset)
      compat.Platform.arraycopy(elems, 0, arr, offset, elems.length)
      arr(0) = head
      new BaseTypeSeq(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
      var arr = new Array[Type](len)
      var i = 0
      while (i < len) {
        arr(i) = f(elems(i))
        i += 1
      }
      new BaseTypeSeq(parents, arr)
    }

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

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

    lazy val maxDepth: Int = maxDepthOfElems

    protected def maxDepthOfElems = {
      var d = 0
      for (i <- 0 until length) d = max(d, maxDpth(elems(i)))
      d
    }

    /** The maximum depth of type `tp' */ 
    protected def maxDpth(tp: Type): Int = tp match {
      case TypeRef(pre, sym, args) => 
        max(maxDpth(pre), maxDpth(args) + 1)
      case RefinedType(parents, decls) =>
        max(maxDpth(parents), maxDpth(decls.toList.map(_.info)) + 1)
      case TypeBounds(lo, hi) =>
        max(maxDpth(lo), maxDpth(hi))
      case MethodType(paramtypes, result) =>
        maxDpth(result)
      case NullaryMethodType(result) =>
        maxDpth(result)
      case PolyType(tparams, result) =>
        max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
      case ExistentialType(tparams, result) =>
        max(maxDpth(result), maxDpth(tparams map (_.info)) + 1)
      case _ =>
        1
    }

    /** The maximum depth of all types `tps' */ 
    private def maxDpth(tps: Seq[Type]): Int = {
      var d = 0
      for (tp <- tps) d = max(d, maxDpth(tp))
      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 = new BaseTypeSeq(List(), Array())

  /** Create a base type sequence consisting of a single type */
  def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = new BaseTypeSeq(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 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) {
        pbtss(i) = 
          if (p.baseTypeSeq eq undetBaseTypeSeq) AnyClass.info.baseTypeSeq 
          else p.baseTypeSeq
        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 AnyClass.tpe
      }
      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()
        i = 0
        while (i < nparents) {
          if (nextTypeSymbol(i) == minSym) {
            nextRawElem(i) match {
              case RefinedType(variants, decls) =>
                for (tp <- variants) 
                  if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes
              case tp =>
                if (!(minTypes exists (tp =:=))) minTypes = tp :: minTypes
            }
            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
    new BaseTypeSeq(parents, elems)
  }

  val CyclicInheritance = new Throwable
}

Other Scala examples (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.