Skip to content

Commit a34d8d6

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 41e7d95 commit a34d8d6

File tree

6 files changed

+68
-28
lines changed

6 files changed

+68
-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
@@ -3,6 +3,7 @@ package core.tasty
33

44
import scala.language.unsafeNulls
55
import scala.collection.immutable.BitSet
6+
import scala.collection.immutable.TreeMap
67

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

@@ -11,11 +12,18 @@ class AttributeUnpickler(reader: TastyReader):
1112

1213
lazy val attributes: Attributes = {
1314
val booleanTags = BitSet.newBuilder
15+
val stringTagValue = TreeMap.newBuilder[Int, String]
1416

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

18-
new Attributes(booleanTags.result())
26+
new Attributes(booleanTags.result(), stringTagValue.result())
1927
}
2028

2129
end AttributeUnpickler

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,32 @@ package dotty.tools.dotc.core.tasty
33
import dotty.tools.tasty.TastyFormat.*
44

55
import scala.collection.immutable.BitSet
6+
import scala.collection.immutable.TreeMap
67

78
class Attributes private[tasty](
89
private[tasty] val booleanTags: BitSet,
10+
private[tasty] val stringTagValues: TreeMap[Int, String],
911
) {
1012
def scala2StandardLibrary: Boolean = booleanTags(SCALA2STANDARDLIBRARYattr)
1113
def explicitNulls: Boolean = booleanTags(EXPLICITNULLSattr)
14+
def sourceFile: Option[String] = stringTagValues.get(SOURCEFILEattr)
1215
}
1316

1417
object Attributes:
1518
def apply(
19+
sourceFile: String,
1620
scala2StandardLibrary: Boolean,
1721
explicitNulls: Boolean,
1822
): Attributes =
1923
val booleanTags = BitSet.newBuilder
2024
if scala2StandardLibrary then booleanTags += SCALA2STANDARDLIBRARYattr
2125
if explicitNulls then booleanTags += EXPLICITNULLSattr
22-
new Attributes(booleanTags.result())
26+
27+
val stringTagValues = TreeMap.newBuilder[Int, String]
28+
stringTagValues += SOURCEFILEattr -> sourceFile
29+
30+
new Attributes(booleanTags.result(), stringTagValues.result())
2331
end apply
2432

2533
val empty: Attributes =
26-
new Attributes(BitSet.empty)
34+
new Attributes(BitSet.empty, TreeMap.empty)

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)