aboutsummaryrefslogblamecommitdiff
path: root/src/dotty/tools/dotc/core/pickling/NameBuffer.scala
blob: a60767fe69f2eefb017020147ffdea00a4a256a7 (plain) (tree)
1
2
3
4
5
6
7
8






                         
                              






                                              
                                                                      
 
                                                                      


                     
                                      


                          






                                                                       
                                                                 
  







                                                                                        








                                                         
                                                      


                                                      


                                                        




                                          
                                                                    

                                             
                                                                                               
                                      
                         
                                                                 
                               
                            
                                         

                                   

                                              
                              
                                                                


                                           










                                   
package dotty.tools
package dotc
package core
package pickling

import collection.mutable
import Names.{Name, chrs}
import Decorators._, NameOps._
import TastyBuffer._
import scala.io.Codec
import TastyName._
import PickleFormat._

class NameBuffer extends TastyBuffer(100000) {

  private val nameRefs = new mutable.LinkedHashMap[TastyName, NameRef]

  def nameIndex(name: TastyName): NameRef = nameRefs.get(name) match {
    case Some(ref) =>
      ref
    case None =>
      val ref = NameRef(nameRefs.size)
      nameRefs(name) = ref
      ref
  }
  def nameIndex(name: Name): NameRef = {
    val tname = 
      if (name.isShadowedName) Shadowed(nameIndex(name.revertShadowed))
      else Simple(name.toTermName)
    nameIndex(tname)
  }
  
  def nameIndex(str: String): NameRef = nameIndex(str.toTermName)
  
  def fullNameIndex(name: Name): NameRef = {
    val pos = name.lastIndexOf('.')
    if (pos > 0)
      nameIndex(Qualified(fullNameIndex(name.take(pos)), nameIndex(name.drop(pos + 1))))
    else
      nameIndex(name)
  }
  
  private def withLength(op: => Unit): Unit = {
    val lengthAddr = currentAddr
    writeByte(0)
    op
    val length = currentAddr.index - lengthAddr.index - 1
    assert(length < 128)
    putNat(lengthAddr, length, 1)
  }
  
  def writeNameRef(ref: NameRef) = writeNat(ref.index)
  
  def pickleName(name: TastyName): Unit = name match {
    case Simple(name) => 
      val bytes = 
        if (name.length == 0) new Array[Byte](0)
        else Codec.toUTF8(chrs, name.start, name.length)
      writeByte(UTF8)
      writeNat(bytes.length)
      writeBytes(bytes, bytes.length)
    case Qualified(qualified, selector) =>
      writeByte(QUALIFIED)
      withLength { writeNameRef(qualified); writeNameRef(selector) }
    case Signed(original, params, result) => 
      writeByte(SIGNED)
      withLength { writeNameRef(original); writeNameRef(result); params.foreach(writeNameRef) }
    case Expanded(prefix, original) =>
      writeByte(EXPANDED)
      withLength { writeNameRef(prefix); writeNameRef(original) }
    case ModuleClass(module) =>
      writeByte(OBJECTCLASS)
      withLength { writeNameRef(module) }
    case SuperAccessor(accessed) =>
      writeByte(SUPERACCESSOR)
      withLength { writeNameRef(accessed) }
    case DefaultGetter(method, paramNumber) =>
      writeByte(DEFAULTGETTER)
      withLength { writeNameRef(method); writeNat(paramNumber) }
    case Shadowed(original) =>
      writeByte(SHADOWED)
      withLength { writeNameRef(original) }
  }
  
  override def assemble(): Unit = {
    var i = 0
    for ((name, ref) <- nameRefs) {
      assert(ref.index == i)
      i += 1
      pickleName(name)
    }
  }
}