Skip to content

Commit

Permalink
Add attributes section to TASTy
Browse files Browse the repository at this point in the history
The `Attributes` section contains a list of UTF-8 string that represent
the attributes.
  • Loading branch information
nicolasstucki committed Sep 27, 2023
1 parent 982c91b commit 9481cf9
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 12 deletions.
25 changes: 25 additions & 0 deletions compiler/src/dotty/tools/dotc/core/tasty/AttributePickler.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dotty.tools.dotc.core.tasty

import dotty.tools.dotc.ast.{tpd, untpd}

import dotty.tools.tasty.TastyBuffer
import dotty.tools.tasty.TastyFormat.AttributesSection

import java.nio.charset.StandardCharsets

object AttributePickler:

def pickleAttributes(
attributes: List[String],
pickler: TastyPickler,
buf: TastyBuffer): Unit =
if attributes != Nil then
pickler.newSection(AttributesSection, buf)
for attribute <- attributes do
val bytes = attribute.getBytes(StandardCharsets.UTF_8).nn
val length = bytes.length
buf.writeNat(length)
buf.writeBytes(bytes, length)
end pickleAttributes

end AttributePickler
26 changes: 26 additions & 0 deletions compiler/src/dotty/tools/dotc/core/tasty/AttributeUnpickler.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dotty.tools.dotc
package core.tasty

import scala.language.unsafeNulls

import dotty.tools.tasty.{TastyReader, TastyBuffer}

import java.nio.charset.StandardCharsets

class AttributeUnpickler(reader: TastyReader):
import reader._

private[tasty] lazy val attributes: List[String] = {
val attributesBuilder = List.newBuilder[String]
while (!isAtEnd) {
val length = readNat()
if (length > 0) {
val bytes = readBytes(length)
val attribute = new String(bytes, StandardCharsets.UTF_8)
attributesBuilder += attribute
}
}
attributesBuilder.result()
}

end AttributeUnpickler
21 changes: 15 additions & 6 deletions compiler/src/dotty/tools/dotc/core/tasty/DottyUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ import Names.SimpleName
import TreeUnpickler.UnpickleMode

import dotty.tools.tasty.TastyReader
import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSection}
import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSection, AttributesSection}

object DottyUnpickler {

/** Exception thrown if classfile is corrupted */
class BadSignature(msg: String) extends RuntimeException(msg)

class TreeSectionUnpickler(posUnpickler: Option[PositionUnpickler], commentUnpickler: Option[CommentUnpickler])
class TreeSectionUnpickler(posUnpickler: Option[PositionUnpickler], commentUnpickler: Option[CommentUnpickler], attributeUnpickler: Option[AttributeUnpickler])
extends SectionUnpickler[TreeUnpickler](ASTsSection) {
def unpickle(reader: TastyReader, nameAtRef: NameTable): TreeUnpickler =
new TreeUnpickler(reader, nameAtRef, posUnpickler, commentUnpickler)
new TreeUnpickler(reader, nameAtRef, posUnpickler, commentUnpickler, attributeUnpickler)
}

class PositionsSectionUnpickler extends SectionUnpickler[PositionUnpickler](PositionsSection) {
Expand All @@ -35,6 +35,10 @@ object DottyUnpickler {
def unpickle(reader: TastyReader, nameAtRef: NameTable): CommentUnpickler =
new CommentUnpickler(reader)
}
class AttributesSectionUnpickler extends SectionUnpickler[AttributeUnpickler](AttributesSection) {
def unpickle(reader: TastyReader, nameAtRef: NameTable): AttributeUnpickler =
new AttributeUnpickler(reader)
}
}

/** A class for unpickling Tasty trees and symbols.
Expand All @@ -48,16 +52,21 @@ class DottyUnpickler(bytes: Array[Byte], mode: UnpickleMode = UnpickleMode.TopLe
val unpickler: TastyUnpickler = new TastyUnpickler(bytes)
private val posUnpicklerOpt = unpickler.unpickle(new PositionsSectionUnpickler)
private val commentUnpicklerOpt = unpickler.unpickle(new CommentsSectionUnpickler)
private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt)).get
private val attributeUnpicklerOpt = unpickler.unpickle(new AttributesSectionUnpickler)
private val treeUnpickler = unpickler.unpickle(treeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt, attributeUnpicklerOpt)).get

/** Enter all toplevel classes and objects into their scopes
* @param roots a set of SymDenotations that should be overwritten by unpickling
*/
def enter(roots: Set[SymDenotation])(using Context): Unit =
treeUnpickler.enter(roots)

protected def treeSectionUnpickler(posUnpicklerOpt: Option[PositionUnpickler], commentUnpicklerOpt: Option[CommentUnpickler]): TreeSectionUnpickler =
new TreeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt)
protected def treeSectionUnpickler(
posUnpicklerOpt: Option[PositionUnpickler],
commentUnpicklerOpt: Option[CommentUnpickler],
attributeUnpicklerOpt: Option[AttributeUnpickler]
): TreeSectionUnpickler =
new TreeSectionUnpickler(posUnpicklerOpt, commentUnpicklerOpt, attributeUnpicklerOpt)

protected def computeRootTrees(using Context): List[Tree] = treeUnpickler.unpickle(mode)

Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/core/tasty/ScratchData.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ class ScratchData:
val pickledIndices = new mutable.BitSet

val commentBuffer = new TastyBuffer(5000)
val attributeBuffer = new TastyBuffer(128)

def reset() =
assert(delta ne delta1)
assert(delta.length == delta1.length)
positionBuffer.reset()
pickledIndices.clear()
commentBuffer.reset()
attributeBuffer.reset()

26 changes: 21 additions & 5 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Contexts._, Decorators._
import Names.Name
import TastyUnpickler._
import util.Spans.offsetToInt
import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSection}
import dotty.tools.tasty.TastyFormat.{ASTsSection, PositionsSection, CommentsSection, AttributesSection}
import java.nio.file.{Files, Paths}
import dotty.tools.io.{JarArchive, Path}

Expand Down Expand Up @@ -84,14 +84,16 @@ class TastyPrinter(bytes: Array[Byte]) {
case Some(s) => sb.append(s)
case _ =>
}
sb.append("\n\n")
unpickle(new PositionSectionUnpickler) match {
case Some(s) => sb.append(s)
case Some(s) => sb.append("\n\n").append(s)
case _ =>
}
sb.append("\n\n")
unpickle(new CommentSectionUnpickler) match {
case Some(s) => sb.append(s)
case Some(s) => sb.append("\n\n").append(s)
case _ =>
}
unpickle(new AttributesSectionUnpickler) match {
case Some(s) => sb.append("\n\n").append(s)
case _ =>
}
sb.result
Expand Down Expand Up @@ -222,6 +224,20 @@ class TastyPrinter(bytes: Array[Byte]) {
}
}

class AttributesSectionUnpickler extends SectionUnpickler[String](AttributesSection) {

private val sb: StringBuilder = new StringBuilder

def unpickle(reader: TastyReader, tastyName: NameTable): String = {
sb.append(s" ${reader.endAddr.index - reader.currentAddr.index}")
val attributes = new AttributeUnpickler(reader).attributes
sb.append(s" attributes bytes:\n")
for attribute <- attributes do
sb.append(" ").append(attribute).append("\n")
sb.result
}
}

protected def nameStr(str: String): String = str
protected def treeStr(str: String): String = str
protected def lengthStr(str: String): String = str
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ import scala.annotation.internal.sharable
* @param reader the reader from which to unpickle
* @param posUnpicklerOpt the unpickler for positions, if it exists
* @param commentUnpicklerOpt the unpickler for comments, if it exists
* @param attributeUnpicklerOpt the unpickler for attributes, if it exists
*/
class TreeUnpickler(reader: TastyReader,
nameAtRef: NameTable,
posUnpicklerOpt: Option[PositionUnpickler],
commentUnpicklerOpt: Option[CommentUnpickler]) {
commentUnpicklerOpt: Option[CommentUnpickler],
attributeUnpicklerOpt: Option[AttributeUnpickler]) {
import TreeUnpickler._
import tpd._

Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/Pickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class Pickler extends Phase {
pickler, treePkl.buf.addrOfTree, treePkl.docString, tree,
scratch.commentBuffer)

val attributes = Nil // TODO add attributes here
AttributePickler.pickleAttributes(attributes, pickler, scratch.attributeBuffer)

val pickled = pickler.assembleParts()

def rawBytes = // not needed right now, but useful to print raw format.
Expand Down
4 changes: 4 additions & 0 deletions tasty/src/dotty/tools/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@ Standard Section: "Comments" Comment*
```none
Comment = Length Bytes LongInt // Raw comment's bytes encoded as UTF-8, followed by the comment's coordinates.
```
Standard Section: "Attributes" UTF8*
**************************************************************************************/

object TastyFormat {
Expand Down Expand Up @@ -361,6 +364,7 @@ object TastyFormat {
final val ASTsSection = "ASTs"
final val PositionsSection = "Positions"
final val CommentsSection = "Comments"
final val AttributesSection = "Attributes"

/** Tags used to serialize names, should update [[TastyFormat$.nameTagToString]] if a new constant is added */
class NameTags {
Expand Down

0 comments on commit 9481cf9

Please sign in to comment.