Skip to content

Commit 8f71739

Browse files
committed
Add source file attribute to TASTY files
This introduces the first non-boolean attribute to the TASTY format. We Split the tags into a set of boolean tags and string tags to handle This new kind of attribute. We keep some tags as unknown to allow for additional kinds of tags in the future.
1 parent 438250f commit 8f71739

File tree

7 files changed

+72
-28
lines changed

7 files changed

+72
-28
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@ object AttributePickler:
1212
pickler: TastyPickler,
1313
buf: TastyBuffer
1414
): Unit =
15-
if attributes.booleanTags.nonEmpty then
16-
pickler.newSection(AttributesSection, buf)
15+
pickler.newSection(AttributesSection, buf)
1716

1817
for tag <- attributes.booleanTags do
18+
assert(tag < TastyFormat.firstStringAttrTag, "Not a boolean attribute tag: " + tag)
1919
buf.writeByte(tag)
2020

21+
assert(attributes.stringTagValues.contains(TastyFormat.SOURCEFILEattr))
22+
for (tag, value) <- attributes.stringTagValues do
23+
assert(TastyFormat.firstStringAttrTag <= tag && tag < TastyFormat.firstUnassignedAttrTag, "Not a string attribute tag: " + tag)
24+
buf.writeByte(tag)
25+
buf.writeUtf8(value)
26+
2127
end pickleAttributes
2228

2329
end AttributePickler

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dotty.tools.dotc
22
package core.tasty
33

44
import scala.language.unsafeNulls
5+
import scala.collection.immutable.TreeMap
56

67
import dotty.tools.tasty.{TastyFormat, TastyReader, TastyBuffer}
78

@@ -10,11 +11,18 @@ class AttributeUnpickler(reader: TastyReader):
1011

1112
lazy val attributes: Attributes = {
1213
val booleanTags = List.newBuilder[Int]
14+
val stringTagValue = TreeMap.newBuilder[Int, String]
1315

1416
while !isAtEnd do
15-
booleanTags += readByte()
17+
val tag = readByte()
18+
if tag < TastyFormat.firstStringAttrTag then
19+
booleanTags += tag
20+
else if tag < TastyFormat.firstUnassignedAttrTag then
21+
stringTagValue += ((tag, readUtf8()))
22+
else
23+
assert(false, "unknown attribute tag: " + tag)
1624

17-
new Attributes(booleanTags.result())
25+
new Attributes(booleanTags.result(), stringTagValue.result())
1826
}
1927

2028
end AttributeUnpickler

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,34 @@ package dotty.tools.dotc.core.tasty
22

33
import dotty.tools.tasty.TastyFormat
44

5+
import scala.collection.immutable.TreeMap
6+
57
class Attributes(
68
val booleanTags: List[Int],
9+
val stringTagValues: TreeMap[Int, String],
710
) {
811
def scala2StandardLibrary: Boolean =
912
booleanTags.contains(TastyFormat.SCALA2STANDARDLIBRARYattr)
1013
def explicitNulls: Boolean =
1114
booleanTags.contains(TastyFormat.EXPLICITNULLSattr)
15+
def sourceFile: String =
16+
stringTagValues(TastyFormat.SOURCEFILEattr)
1217
}
1318

1419
object Attributes:
1520
def apply(
21+
sourceFile: String,
1622
scala2StandardLibrary: Boolean,
1723
explicitNulls: Boolean,
1824
): Attributes =
1925
val booleanTags = List.newBuilder[Int]
2026
if scala2StandardLibrary then booleanTags += TastyFormat.SCALA2STANDARDLIBRARYattr
2127
if explicitNulls then booleanTags += TastyFormat.EXPLICITNULLSattr
22-
new Attributes(booleanTags.result())
28+
29+
val stringTagValues = TreeMap.newBuilder[Int, String]
30+
stringTagValues += TastyFormat.SOURCEFILEattr -> sourceFile
31+
32+
new Attributes(booleanTags.result(), stringTagValues.result())
2333
end apply
34+
35+
def empty: Attributes = new Attributes(Nil, TreeMap.empty)

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

Lines changed: 1 addition & 1 deletion
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(new Attributes(booleanTags = Nil))
60+
attributeUnpicklerOpt.map(_.attributes).getOrElse(Attributes.empty)
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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,9 @@ class TastyPrinter(bytes: Array[Byte]) {
237237

238238
for tag <- attributes.booleanTags do
239239
sb.append(" ").append(attributeTagToString(tag)).append("\n")
240-
240+
for (tag, value) <- attributes.stringTagValues do
241+
sb.append(" ").append(attributeTagToString(tag))
242+
.append(" ").append(value).append("\n")
241243
sb.result
242244
}
243245
}

compiler/src/dotty/tools/dotc/transform/Pickler.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,11 @@ class Pickler extends Phase {
108108
pickler, treePkl.buf.addrOfTree, treePkl.docString, tree,
109109
scratch.commentBuffer)
110110

111+
val sourceRelativePath =
112+
val reference = ctx.settings.sourceroot.value
113+
util.SourceFile.relativePath(unit.source, reference)
111114
val attributes = Attributes(
115+
sourceFile = sourceRelativePath,
112116
scala2StandardLibrary = ctx.settings.YcompileScala2Library.value,
113117
explicitNulls = ctx.settings.YexplicitNulls.value,
114118
)

tasty/src/dotty/tools/tasty/TastyFormat.scala

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,11 @@ Note: The signature of a SELECTin or TERMREFin node is the signature of the sele
235235
236236
Note: Tree tags are grouped into 5 categories that determine what follows, and thus allow to compute the size of the tagged tree in a generic way.
237237
```none
238-
Category 1 (tags 1-59) : tag
239-
Category 2 (tags 60-89) : tag Nat
240-
Category 3 (tags 90-109) : tag AST
241-
Category 4 (tags 110-127): tag Nat AST
242-
Category 5 (tags 128-255): tag Length <payload>
238+
Tree Category 1 (tags 1-59) : tag
239+
Tree Category 2 (tags 60-89) : tag Nat
240+
Tree Category 3 (tags 90-109) : tag AST
241+
Tree Category 4 (tags 110-127): tag Nat AST
242+
Tree Category 5 (tags 128-255): tag Length <payload>
243243
```
244244
245245
Standard-Section: "Positions" LinesSizes Assoc*
@@ -273,6 +273,13 @@ Standard Section: "Attributes" Attribute*
273273
```none
274274
Attribute = SCALA2STANDARDLIBRARYattr
275275
EXPLICITNULLSattr
276+
SOURCEFILEattr Utf8
277+
```
278+
279+
Note: Attribute tags are grouped into 2 categories that determine what follows, and thus allow to compute the size of the tagged tree in a generic way.
280+
```none
281+
Attribute Category 1 (tags 1-64) : tag
282+
Attribute Category 2 (tags 65-128): tag UTF8
276283
```
277284
278285
**************************************************************************************/
@@ -436,9 +443,9 @@ object TastyFormat {
436443

437444
final val SOURCE = 4
438445

439-
// AST tags
440-
// Cat. 1: tag
446+
// AST tags
441447

448+
// Tree Cat. 1: tag
442449
final val firstSimpleTreeTag = UNITconst
443450
// final val ??? = 1
444451
final val UNITconst = 2
@@ -487,8 +494,8 @@ object TastyFormat {
487494
final val EMPTYCLAUSE = 45
488495
final val SPLITCLAUSE = 46
489496

490-
// Cat. 2: tag Nat
491-
497+
// Tree Cat. 2: tag Nat
498+
final val firstNatTreeTag = SHAREDterm
492499
final val SHAREDterm = 60
493500
final val SHAREDtype = 61
494501
final val TERMREFdirect = 62
@@ -507,8 +514,8 @@ object TastyFormat {
507514
final val IMPORTED = 75
508515
final val RENAMED = 76
509516

510-
// Cat. 3: tag AST
511-
517+
// Tree Cat. 3: tag AST
518+
final val firstASTTreeTag = THIS
512519
final val THIS = 90
513520
final val QUALTHIS = 91
514521
final val CLASSconst = 92
@@ -525,8 +532,8 @@ object TastyFormat {
525532
final val EXPLICITtpt = 103
526533

527534

528-
// Cat. 4: tag Nat AST
529-
535+
// Tree Cat. 4: tag Nat AST
536+
final val firstNatASTTreeTag = IDENT
530537
final val IDENT = 110
531538
final val IDENTtpt = 111
532539
final val SELECT = 112
@@ -538,8 +545,8 @@ object TastyFormat {
538545
final val SELFDEF = 118
539546
final val NAMEDARG = 119
540547

541-
// Cat. 5: tag Length ...
542-
548+
// Tree Cat. 5: tag Length ...
549+
final val firstLengthTreeTag = PACKAGE
543550
final val PACKAGE = 128
544551
final val VALDEF = 129
545552
final val DEFDEF = 130
@@ -601,17 +608,21 @@ object TastyFormat {
601608

602609
final val HOLE = 255
603610

604-
final val firstNatTreeTag = SHAREDterm
605-
final val firstASTTreeTag = THIS
606-
final val firstNatASTTreeTag = IDENT
607-
final val firstLengthTreeTag = PACKAGE
608-
609-
610611
// Attributes tags
611612

613+
// Attr Cat. 1: tag
614+
final val firstBooleanAttrTag = SCALA2STANDARDLIBRARYattr
612615
final val SCALA2STANDARDLIBRARYattr = 1
613616
final val EXPLICITNULLSattr = 2
614617

618+
// Attr Cat. 2: tag UTF8
619+
final val firstStringAttrTag = SOURCEFILEattr
620+
final val SOURCEFILEattr = 128
621+
622+
// Attr Cat. 3: unassigned
623+
final val firstUnassignedAttrTag = 129
624+
625+
615626
/** Useful for debugging */
616627
def isLegalTag(tag: Int): Boolean =
617628
firstSimpleTreeTag <= tag && tag <= SPLITCLAUSE ||
@@ -830,6 +841,7 @@ object TastyFormat {
830841
def attributeTagToString(tag: Int): String = tag match {
831842
case SCALA2STANDARDLIBRARYattr => "SCALA2STANDARDLIBRARYattr"
832843
case EXPLICITNULLSattr => "EXPLICITNULLSattr"
844+
case SOURCEFILEattr => "SOURCEFILEattr"
833845
}
834846

835847
/** @return If non-negative, the number of leading references (represented as nats) of a length/trees entry.

0 commit comments

Comments
 (0)