Skip to content

Commit 61f857c

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 6bb23dd commit 61f857c

File tree

6 files changed

+69
-27
lines changed

6 files changed

+69
-27
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.exists(_._1 == 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 = List.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,20 +3,24 @@ 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: List[(Int, String)],
911
) {
1012
def scala2StandardLibrary: Boolean = booleanTags(SCALA2STANDARDLIBRARYattr)
1113
def explicitNulls: Boolean = booleanTags(EXPLICITNULLSattr)
1214
def captureChecked: Boolean = booleanTags(CAPTURECHECKEDattr)
1315
def withPureFuns: Boolean = booleanTags(WITHPUREFUNSattr)
1416
def isJava: Boolean = booleanTags(JAVAattr)
1517
def isOutline: Boolean = booleanTags(OUTLINEattr)
18+
def sourceFile: Option[String] = stringTagValues.find(_._1 == SOURCEFILEattr).map(_._2)
1619
}
1720

1821
object Attributes:
1922
def apply(
23+
sourceFile: String,
2024
scala2StandardLibrary: Boolean,
2125
explicitNulls: Boolean,
2226
captureChecked: Boolean,
@@ -31,8 +35,12 @@ object Attributes:
3135
if withPureFuns then booleanTags += WITHPUREFUNSattr
3236
if isJava then booleanTags += JAVAattr
3337
if isOutline then booleanTags += OUTLINEattr
34-
new Attributes(booleanTags.result())
38+
39+
val stringTagValues = List.newBuilder[(Int, String)]
40+
stringTagValues += SOURCEFILEattr -> sourceFile
41+
42+
new Attributes(booleanTags.result(), stringTagValues.result())
3543
end apply
3644

3745
val empty: Attributes =
38-
new Attributes(BitSet.empty)
46+
new Attributes(BitSet.empty, Nil)

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ class TastyPrinter(bytes: Array[Byte]) {
233233

234234
for tag <- attributes.booleanTags do
235235
sb.append(" ").append(attributeTagToString(tag)).append("\n")
236+
for (tag, value) <- attributes.stringTagValues do
237+
sb.append(" ").append(attributeTagToString(tag))
238+
.append(" ").append(value).append("\n")
239+
sb.result
236240
}
237241
}
238242

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,16 @@ class Pickler extends Phase {
9696
do
9797
if ctx.settings.YtestPickler.value then beforePickling(cls) = tree.show
9898

99+
val sourceRelativePath =
100+
val reference = ctx.settings.sourceroot.value
101+
util.SourceFile.relativePath(unit.source, reference)
99102
val isJavaAttr = unit.isJava // we must always set JAVAattr when pickling Java sources
100103
if isJavaAttr then
101104
// assert that Java sources didn't reach Pickler without `-Yjava-tasty`.
102105
assert(ctx.settings.YjavaTasty.value, "unexpected Java source file without -Yjava-tasty")
103106
val isOutline = isJavaAttr // TODO: later we may want outline for Scala sources too
104107
val attributes = Attributes(
108+
sourceFile = sourceRelativePath,
105109
scala2StandardLibrary = ctx.settings.YcompileScala2Library.value,
106110
explicitNulls = ctx.settings.YexplicitNulls.value,
107111
captureChecked = Feature.ccEnabled,

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

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,11 @@ Note: The signature of a SELECTin or TERMREFin node is the signature of the sele
236236
237237
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.
238238
```none
239-
Category 1 (tags 1-59) : tag
240-
Category 2 (tags 60-89) : tag Nat
241-
Category 3 (tags 90-109) : tag AST
242-
Category 4 (tags 110-127): tag Nat AST
243-
Category 5 (tags 128-255): tag Length <payload>
239+
Tree Category 1 (tags 1-59) : tag
240+
Tree Category 2 (tags 60-89) : tag Nat
241+
Tree Category 3 (tags 90-109) : tag AST
242+
Tree Category 4 (tags 110-127): tag Nat AST
243+
Tree Category 5 (tags 128-255): tag Length <payload>
244244
```
245245
246246
Standard-Section: "Positions" LinesSizes Assoc*
@@ -278,6 +278,13 @@ Standard Section: "Attributes" Attribute*
278278
WITHPUREFUNSattr
279279
JAVAattr
280280
OUTLINEattr
281+
SOURCEFILEattr Utf8
282+
```
283+
284+
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.
285+
```none
286+
Attribute Category 1 (tags 1-64) : tag
287+
Attribute Category 2 (tags 65-128): tag UTF8
281288
```
282289
283290
**************************************************************************************/
@@ -441,9 +448,9 @@ object TastyFormat {
441448

442449
final val SOURCE = 4
443450

444-
// AST tags
445-
// Cat. 1: tag
451+
// AST tags
446452

453+
// Tree Cat. 1: tag
447454
final val firstSimpleTreeTag = UNITconst
448455
// final val ??? = 1
449456
final val UNITconst = 2
@@ -492,8 +499,8 @@ object TastyFormat {
492499
final val EMPTYCLAUSE = 45
493500
final val SPLITCLAUSE = 46
494501

495-
// Cat. 2: tag Nat
496-
502+
// Tree Cat. 2: tag Nat
503+
final val firstNatTreeTag = SHAREDterm
497504
final val SHAREDterm = 60
498505
final val SHAREDtype = 61
499506
final val TERMREFdirect = 62
@@ -512,8 +519,8 @@ object TastyFormat {
512519
final val IMPORTED = 75
513520
final val RENAMED = 76
514521

515-
// Cat. 3: tag AST
516-
522+
// Tree Cat. 3: tag AST
523+
final val firstASTTreeTag = THIS
517524
final val THIS = 90
518525
final val QUALTHIS = 91
519526
final val CLASSconst = 92
@@ -531,8 +538,8 @@ object TastyFormat {
531538
final val ELIDED = 104
532539

533540

534-
// Cat. 4: tag Nat AST
535-
541+
// Tree Cat. 4: tag Nat AST
542+
final val firstNatASTTreeTag = IDENT
536543
final val IDENT = 110
537544
final val IDENTtpt = 111
538545
final val SELECT = 112
@@ -544,8 +551,8 @@ object TastyFormat {
544551
final val SELFDEF = 118
545552
final val NAMEDARG = 119
546553

547-
// Cat. 5: tag Length ...
548-
554+
// Tree Cat. 5: tag Length ...
555+
final val firstLengthTreeTag = PACKAGE
549556
final val PACKAGE = 128
550557
final val VALDEF = 129
551558
final val DEFDEF = 130
@@ -607,21 +614,25 @@ object TastyFormat {
607614

608615
final val HOLE = 255
609616

610-
final val firstNatTreeTag = SHAREDterm
611-
final val firstASTTreeTag = THIS
612-
final val firstNatASTTreeTag = IDENT
613-
final val firstLengthTreeTag = PACKAGE
614-
615-
616617
// Attributes tags
617618

619+
// Attr Cat. 1: tag
620+
final val firstBooleanAttrTag = SCALA2STANDARDLIBRARYattr
618621
final val SCALA2STANDARDLIBRARYattr = 1
619622
final val EXPLICITNULLSattr = 2
620623
final val CAPTURECHECKEDattr = 3
621624
final val WITHPUREFUNSattr = 4
622625
final val JAVAattr = 5
623626
final val OUTLINEattr = 6
624627

628+
// Attr Cat. 2: tag UTF8
629+
final val firstStringAttrTag = SOURCEFILEattr
630+
final val SOURCEFILEattr = 128
631+
632+
// Attr Cat. 3: unassigned
633+
final val firstUnassignedAttrTag = 129
634+
635+
625636
/** Useful for debugging */
626637
def isLegalTag(tag: Int): Boolean =
627638
firstSimpleTreeTag <= tag && tag <= SPLITCLAUSE ||
@@ -845,6 +856,7 @@ object TastyFormat {
845856
case WITHPUREFUNSattr => "WITHPUREFUNSattr"
846857
case JAVAattr => "JAVAattr"
847858
case OUTLINEattr => "OUTLINEattr"
859+
case SOURCEFILEattr => "SOURCEFILEattr"
848860
}
849861

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

0 commit comments

Comments
 (0)