Skip to content

Commit e7f8a2c

Browse files
Refactor TASTy Attributes (#19091)
We generalize the internal encoding of `Attributes` to be a list of tags. Then we add add helper methods to have simpler ways to interact with this abstraction using booleans. This implies that the pickling/unpickling can be agnostic of the semantics of each tag. Therefore reducing the number of places that need to be updated when we add a new tag. Useful for #19074, #19033, and #18948.
2 parents b730be1 + 540f20a commit e7f8a2c

File tree

5 files changed

+39
-34
lines changed

5 files changed

+39
-34
lines changed

compiler/src/dotty/tools/dotc/core/tasty/AttributePickler.scala

+4-7
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,18 @@ import dotty.tools.dotc.ast.{tpd, untpd}
55
import dotty.tools.tasty.TastyBuffer
66
import dotty.tools.tasty.TastyFormat, TastyFormat.AttributesSection
77

8-
import java.nio.charset.StandardCharsets
9-
108
object AttributePickler:
119

1210
def pickleAttributes(
1311
attributes: Attributes,
1412
pickler: TastyPickler,
1513
buf: TastyBuffer
1614
): Unit =
17-
if attributes.scala2StandardLibrary || attributes.explicitNulls then // or any other attribute is set
15+
if attributes.booleanTags.nonEmpty then
1816
pickler.newSection(AttributesSection, buf)
19-
// Pickle attributes
20-
if attributes.scala2StandardLibrary then buf.writeNat(TastyFormat.SCALA2STANDARDLIBRARYattr)
21-
if attributes.explicitNulls then buf.writeNat(TastyFormat.EXPLICITNULLSattr)
22-
end if
17+
18+
for tag <- attributes.booleanTags do
19+
buf.writeByte(tag)
2320

2421
end pickleAttributes
2522

compiler/src/dotty/tools/dotc/core/tasty/AttributeUnpickler.scala

+6-19
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,16 @@ import scala.language.unsafeNulls
55

66
import dotty.tools.tasty.{TastyFormat, TastyReader, TastyBuffer}
77

8-
import java.nio.charset.StandardCharsets
9-
108
class AttributeUnpickler(reader: TastyReader):
119
import reader._
1210

13-
lazy val attributeTags: List[Int] =
14-
val listBuilder = List.newBuilder[Int]
15-
while !isAtEnd do listBuilder += readNat()
16-
listBuilder.result()
17-
1811
lazy val attributes: Attributes = {
19-
var scala2StandardLibrary = false
20-
var explicitNulls = false
21-
for attributeTag <- attributeTags do
22-
attributeTag match
23-
case TastyFormat.SCALA2STANDARDLIBRARYattr => scala2StandardLibrary = true
24-
case TastyFormat.EXPLICITNULLSattr => explicitNulls = true
25-
case attribute =>
26-
assert(false, "Unexpected attribute value: " + attribute)
27-
Attributes(
28-
scala2StandardLibrary,
29-
explicitNulls,
30-
)
12+
val booleanTags = List.newBuilder[Int]
13+
14+
while !isAtEnd do
15+
booleanTags += readByte()
16+
17+
new Attributes(booleanTags.result())
3118
}
3219

3320
end AttributeUnpickler
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
package dotty.tools.dotc.core.tasty
22

3+
import dotty.tools.tasty.TastyFormat
4+
35
class Attributes(
4-
val scala2StandardLibrary: Boolean,
5-
val explicitNulls: Boolean,
6-
)
6+
val booleanTags: List[Int],
7+
) {
8+
def scala2StandardLibrary: Boolean =
9+
booleanTags.contains(TastyFormat.SCALA2STANDARDLIBRARYattr)
10+
def explicitNulls: Boolean =
11+
booleanTags.contains(TastyFormat.EXPLICITNULLSattr)
12+
}
13+
14+
object Attributes:
15+
def apply(
16+
scala2StandardLibrary: Boolean,
17+
explicitNulls: Boolean,
18+
): Attributes =
19+
val booleanTags = List.newBuilder[Int]
20+
if scala2StandardLibrary then booleanTags += TastyFormat.SCALA2STANDARDLIBRARYattr
21+
if explicitNulls then booleanTags += TastyFormat.EXPLICITNULLSattr
22+
new Attributes(booleanTags.result())
23+
end apply

compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class DottyUnpickler(bytes: Array[Byte], mode: UnpickleMode = UnpickleMode.TopLe
5757
private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt, attributeUnpicklerOpt)).get
5858

5959
def tastyAttributes: Attributes =
60-
attributeUnpicklerOpt.map(_.attributes).getOrElse(Attributes(false, false))
60+
attributeUnpicklerOpt.map(_.attributes).getOrElse(new Attributes(booleanTags = Nil))
6161

6262
/** Enter all toplevel classes and objects into their scopes
6363
* @param roots a set of SymDenotations that should be overwritten by unpickling

compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala

+8-4
Original file line numberDiff line numberDiff line change
@@ -225,15 +225,19 @@ class TastyPrinter(bytes: Array[Byte]) {
225225
}
226226

227227
class AttributesSectionUnpickler extends SectionUnpickler[String](AttributesSection) {
228-
import dotty.tools.tasty.TastyFormat.attributeTagToString
228+
import dotty.tools.tasty.TastyFormat.*
229+
229230
private val sb: StringBuilder = new StringBuilder
230231

231232
def unpickle(reader: TastyReader, tastyName: NameTable): String = {
233+
import reader.*
232234
sb.append(s" ${reader.endAddr.index - reader.currentAddr.index}")
233-
val attributeTags = new AttributeUnpickler(reader).attributeTags
235+
val attributes = new AttributeUnpickler(reader).attributes
234236
sb.append(s" attributes bytes:\n")
235-
for attributeTag <- attributeTags do
236-
sb.append(" ").append(attributeTagToString(attributeTag)).append("\n")
237+
238+
for tag <- attributes.booleanTags do
239+
sb.append(" ").append(attributeTagToString(tag)).append("\n")
240+
237241
sb.result
238242
}
239243
}

0 commit comments

Comments
 (0)