1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
package dotty.tools
package dotc
package core
package tasty
import collection.mutable
import Names.{Name, chrs, DerivedTermName, SimpleTermName}
import Decorators._, NameOps._
import TastyBuffer._
import scala.io.Codec
import TastyName._
import TastyFormat._
class NameBuffer extends TastyBuffer(10000) {
import NameBuffer._
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, toTasty: SimpleTermName => TastyName): NameRef = {
val tname = name.toTermName match {
case DerivedTermName(name1, NameInfo.ModuleClass) =>
ModuleClass(nameIndex(name1, toTasty))
case DerivedTermName(prefix, qual: NameInfo.Qualified) =>
val tcon: (NameRef, NameRef) => TastyName = qual match {
case _: NameInfo.Select => Qualified
case _: NameInfo.Flatten => Flattened
case _: NameInfo.Expand => Expanded
}
tcon(nameIndex(prefix, toTasty), nameIndex(qual.name))
case DerivedTermName(prefix, NameInfo.DefaultGetter(num)) =>
DefaultGetter(nameIndex(prefix, toTasty), num)
case DerivedTermName(prefix, NameInfo.Variant(sign)) =>
Variant(nameIndex(prefix, toTasty), sign)
case name1 =>
if (name1.isShadowedName) Shadowed(nameIndex(name1.revertShadowed, toTasty))
else toTasty(name1.asSimpleName)
}
nameIndex(tname)
}
def nameIndex(name: Name): NameRef = nameIndex(name, Simple)
def nameIndex(str: String): NameRef = nameIndex(str.toTermName)
def fullNameIndex(name: Name): NameRef = {
def split(name: SimpleTermName): TastyName = {
val pos = name.lastIndexOf('.')
if (pos <= 0) Simple(name)
else Qualified(fullNameIndex(name.take(pos)), nameIndex(name.drop(pos + 1)))
}
nameIndex(name, split)
}
private def withLength(op: => Unit, lengthWidth: Int = 1): Unit = {
val lengthAddr = currentAddr
for (i <- 0 until lengthWidth) writeByte(0)
op
val length = currentAddr.index - lengthAddr.index - 1
putNat(lengthAddr, length, lengthWidth)
}
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 Flattened(qualified, selector) =>
writeByte(FLATTENED)
withLength { writeNameRef(qualified); writeNameRef(selector) }
case Expanded(prefix, original) =>
writeByte(EXPANDED)
withLength { writeNameRef(prefix); writeNameRef(original) }
case Signed(original, params, result) =>
writeByte(SIGNED)
withLength(
{ writeNameRef(original); writeNameRef(result); params.foreach(writeNameRef) },
if ((params.length + 2) * maxIndexWidth <= maxNumInByte) 1 else 2)
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) }
case Variant(original, sign) =>
writeByte(VARIANT)
withLength { writeNameRef(original); writeNat(sign + 1) }
}
override def assemble(): Unit = {
var i = 0
for ((name, ref) <- nameRefs) {
assert(ref.index == i)
i += 1
pickleName(name)
}
}
}
object NameBuffer {
private val maxIndexWidth = 3 // allows name indices up to 2^21.
private val payloadBitsPerByte = 7 // determined by nat encoding in TastyBuffer
private val maxNumInByte = (1 << payloadBitsPerByte) - 1
}
|