
scala.tools.tasty.TastyFormat.scala Maven / Gradle / Ivy
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala.tools.tasty
// revision: https://github.com/scala/scala3/commit/5189e6854ad1dacc3454542c2f124f5bcb7e2a9c
object TastyFormat {
/** The first four bytes of a TASTy file, followed by four values:
* - `MajorVersion: Int` - see definition in `TastyFormat`
* - `MinorVersion: Int` - see definition in `TastyFormat`
* - `ExperimentalVersion: Int` - see definition in `TastyFormat`
* - `ToolingVersion: String` - arbitrary length string representing the tool that produced the TASTy.
*/
final val header: Array[Int] = Array(0x5C, 0xA1, 0xAB, 0x1F)
/** Natural number. Each increment of the `MajorVersion` begins a
* new series of backward compatible TASTy versions.
*
* A TASTy file in either the preceeding or succeeding series is
* incompatible with the current value.
*/
final val MajorVersion: Int = 28
/** Natural number. Each increment of the `MinorVersion`, within
* a series declared by the `MajorVersion`, breaks forward
* compatibility, but remains backwards compatible, with all
* preceding `MinorVersion`.
*/
final val MinorVersion: Int = 5
/** Natural Number. The `ExperimentalVersion` allows for
* experimentation with changes to TASTy without committing
* to any guarantees of compatibility.
*
* A zero value indicates that the TASTy version is from a
* stable, final release.
*
* A strictly positive value indicates that the TASTy
* version is experimental. An experimental TASTy file
* can only be read by a tool with the same version.
* However, tooling with an experimental TASTy version
* is able to read final TASTy documents if the file's
* `MinorVersion` is strictly less than the current value.
*/
final val ExperimentalVersion: Int = 0
/**This method implements a binary relation (`<:<`) between two TASTy versions.
*
* We label the lhs `file` and rhs `compiler`.
* if `file <:< compiler` then the TASTy file is valid to be read.
*
* A TASTy version, e.g. `v := 28.0-3` is composed of three fields:
* - v.major == 28
* - v.minor == 0
* - v.experimental == 3
*
* TASTy versions have a partial order, for example,
* `a <:< b` and `b <:< a` are both false if
* - `a` and `b` have different `major` fields.
* - `a` and `b` have the same `major` & `minor` fields,
* but different `experimental` fields, both non-zero.
*
* A TASTy version with a zero value for its `experimental` field
* is considered to be stable. Files with a stable TASTy version
* can be read by a compiler with an unstable TASTy version,
* (where the compiler's TASTy version has a higher `minor` field).
*
* A compiler with a stable TASTy version can never read a file
* with an unstable TASTy version.
*
* We follow the given algorithm:
*
* ```
* (fileMajor, fileMinor, fileExperimental) match
* case (`compilerMajor`, `compilerMinor`, `compilerExperimental`) => true // full equality
* case (`compilerMajor`, minor, 0) if minor < compilerMinor => true // stable backwards compatibility
* case _ => false
* ```
* @syntax markdown
*/
def isVersionCompatible(
fileMajor: Int,
fileMinor: Int,
fileExperimental: Int,
compilerMajor: Int,
compilerMinor: Int,
compilerExperimental: Int
): Boolean = (
fileMajor == compilerMajor &&
( fileMinor == compilerMinor && fileExperimental == compilerExperimental // full equality
|| fileMinor < compilerMinor && fileExperimental == 0 // stable backwards compatibility
)
)
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 {
final val UTF8 = 1 // A simple name in UTF8 encoding.
final val QUALIFIED = 2 // A fully qualified name `.`.
final val EXPANDED = 3 // An expanded name `$$`,
// used by Scala-2 for private names.
final val EXPANDPREFIX = 4 // An expansion prefix `$`,
// used by Scala-2 for private names.
final val UNIQUE = 10 // A unique name `$` where ``
// is used only once for each ``.
final val DEFAULTGETTER = 11 // The name `$default$`
// of a default getter that returns a default argument.
final val SUPERACCESSOR = 20 // The name of a super accessor `super$name` created by SuperAccesors.
final val INLINEACCESSOR = 21 // The name of an inline accessor `inline$name`
final val BODYRETAINER = 22 // The name of a synthetic method that retains the runtime
// body of an inline method
final val OBJECTCLASS = 23 // The name of an object class (or: module class) `$`.
final val SIGNED = 63 // A pair of a name and a signature, used to identify
// possibly overloaded methods.
final val TARGETSIGNED = 62 // A triple of a name, a targetname and a signature, used to identify
// possibly overloaded methods that carry a @targetName annotation.
// TODO swap SIGNED and TARGETSIGNED codes on next major version bump
}
object NameTags extends NameTags
/**Should be kept in sync with [[NameTags]]. Converts constants to a String representing their identifier,
* or NotANameTag(tag) if unrecognised.
*
* For debugging purposes when unpickling names in a TASTy file.
*/
def nameTagToString(tag: Int) = {
import NameTags._
tag match {
case UTF8 => "UTF8"
case QUALIFIED => "QUALIFIED"
case EXPANDED => "EXPANDED"
case EXPANDPREFIX => "EXPANDPREFIX"
case UNIQUE => "UNIQUE"
case DEFAULTGETTER => "DEFAULTGETTER"
case SUPERACCESSOR => "SUPERACCESSOR"
case INLINEACCESSOR => "INLINEACCESSOR"
case BODYRETAINER => "BODYRETAINER"
case OBJECTCLASS => "OBJECTCLASS"
case SIGNED => "SIGNED"
case TARGETSIGNED => "TARGETSIGNED"
case id => s"NotANameTag($id)"
}
}
// Position header
final val SOURCE = 4
// AST tags
// Tree Cat. 1: tag
final val firstSimpleTreeTag = UNITconst
// final val ??? = 1
final val UNITconst = 2
final val FALSEconst = 3
final val TRUEconst = 4
final val NULLconst = 5
final val PRIVATE = 6
// final val ??? = 7
final val PROTECTED = 8
final val ABSTRACT = 9
final val FINAL = 10
final val SEALED = 11
final val CASE = 12
final val IMPLICIT = 13
final val LAZY = 14
final val OVERRIDE = 15
final val INLINEPROXY = 16
final val INLINE = 17
final val STATIC = 18
final val OBJECT = 19
final val TRAIT = 20
final val ENUM = 21
final val LOCAL = 22
final val SYNTHETIC = 23
final val ARTIFACT = 24
final val MUTABLE = 25
final val FIELDaccessor = 26
final val CASEaccessor = 27
final val COVARIANT = 28
final val CONTRAVARIANT = 29
// final val ??? = 30
final val HASDEFAULT = 31
final val STABLE = 32
final val MACRO = 33
final val ERASED = 34
final val OPAQUE = 35
final val EXTENSION = 36
final val GIVEN = 37
final val PARAMsetter = 38
final val EXPORTED = 39
final val OPEN = 40
final val PARAMalias = 41
final val TRANSPARENT = 42
final val INFIX = 43
final val INVISIBLE = 44
final val EMPTYCLAUSE = 45
final val SPLITCLAUSE = 46
final val TRACKED = 47
// Tree Cat. 2: tag Nat
final val firstNatTreeTag = SHAREDterm
final val SHAREDterm = 60
final val SHAREDtype = 61
final val TERMREFdirect = 62
final val TYPEREFdirect = 63
final val TERMREFpkg = 64
final val TYPEREFpkg = 65
final val RECthis = 66
final val BYTEconst = 67
final val SHORTconst = 68
final val CHARconst = 69
final val INTconst = 70
final val LONGconst = 71
final val FLOATconst = 72
final val DOUBLEconst = 73
final val STRINGconst = 74
final val IMPORTED = 75
final val RENAMED = 76
// Tree Cat. 3: tag AST
final val firstASTTreeTag = THIS
final val THIS = 90
final val QUALTHIS = 91
final val CLASSconst = 92
final val BYNAMEtype = 93
final val BYNAMEtpt = 94
final val NEW = 95
final val THROW = 96
final val IMPLICITarg = 97
final val PRIVATEqualified = 98
final val PROTECTEDqualified = 99
final val RECtype = 100
final val SINGLETONtpt = 101
final val BOUNDED = 102
final val EXPLICITtpt = 103
final val ELIDED = 104
// Tree Cat. 4: tag Nat AST
final val firstNatASTTreeTag = IDENT
final val IDENT = 110
final val IDENTtpt = 111
final val SELECT = 112
final val SELECTtpt = 113
final val TERMREFsymbol = 114
final val TERMREF = 115
final val TYPEREFsymbol = 116
final val TYPEREF = 117
final val SELFDEF = 118
final val NAMEDARG = 119
// Tree Cat. 5: tag Length ...
final val firstLengthTreeTag = PACKAGE
final val PACKAGE = 128
final val VALDEF = 129
final val DEFDEF = 130
final val TYPEDEF = 131
final val IMPORT = 132
final val TYPEPARAM = 133
final val PARAM = 134
// final val ??? = 135
final val APPLY = 136
final val TYPEAPPLY = 137
final val TYPED = 138
final val ASSIGN = 139
final val BLOCK = 140
final val IF = 141
final val LAMBDA = 142
final val MATCH = 143
final val RETURN = 144
final val WHILE = 145
final val TRY = 146
final val INLINED = 147
final val SELECTouter = 148
final val REPEATED = 149
final val BIND = 150
final val ALTERNATIVE = 151
final val UNAPPLY = 152
final val ANNOTATEDtype = 153
final val ANNOTATEDtpt = 154
final val CASEDEF = 155
final val TEMPLATE = 156
final val SUPER = 157
final val SUPERtype = 158
final val REFINEDtype = 159
final val REFINEDtpt = 160
final val APPLIEDtype = 161
final val APPLIEDtpt = 162
final val TYPEBOUNDS = 163
final val TYPEBOUNDStpt = 164
final val ANDtype = 165
// final val ??? = 166
final val ORtype = 167
// final val ??? = 168
final val POLYtype = 169
final val TYPELAMBDAtype = 170
final val LAMBDAtpt = 171
final val PARAMtype = 172
final val ANNOTATION = 173
final val TERMREFin = 174
final val TYPEREFin = 175
final val SELECTin = 176
final val EXPORT = 177
final val QUOTE = 178
final val SPLICE = 179
final val METHODtype = 180
final val APPLYsigpoly = 181
final val QUOTEPATTERN = 182
final val SPLICEPATTERN = 183
final val MATCHtype = 190
final val MATCHtpt = 191
final val MATCHCASEtype = 192
final val FLEXIBLEtype = 193
final val HOLE = 255
// Attributes tags
// Attribute Category 1 (tags 1-32) : tag
def isBooleanAttrTag(tag: Int): Boolean = 1 <= tag && tag <= 32
final val SCALA2STANDARDLIBRARYattr = 1
final val EXPLICITNULLSattr = 2
final val CAPTURECHECKEDattr = 3
final val WITHPUREFUNSattr = 4
final val JAVAattr = 5
final val OUTLINEattr = 6
// Attribute Category 2 (tags 33-128): unassigned
// Attribute Category 3 (tags 129-160): tag Utf8Ref
def isStringAttrTag(tag: Int): Boolean = 129 <= tag && tag <= 160
final val SOURCEFILEattr = 129
// Attribute Category 4 (tags 161-255): unassigned
// end of Attributes tags
/** Useful for debugging */
def isLegalTag(tag: Int): Boolean =
firstSimpleTreeTag <= tag && tag <= SPLITCLAUSE ||
firstNatTreeTag <= tag && tag <= RENAMED ||
firstASTTreeTag <= tag && tag <= BOUNDED ||
firstNatASTTreeTag <= tag && tag <= NAMEDARG ||
firstLengthTreeTag <= tag && tag <= FLEXIBLEtype ||
tag == HOLE
def isParamTag(tag: Int): Boolean = tag == PARAM || tag == TYPEPARAM
def isModifierTag(tag: Int): Boolean = tag match {
case PRIVATE
| PROTECTED
| ABSTRACT
| FINAL
| SEALED
| CASE
| IMPLICIT
| GIVEN
| ERASED
| LAZY
| OVERRIDE
| INLINE
| INLINEPROXY
| MACRO
| OPAQUE
| STATIC
| OBJECT
| TRAIT
| TRANSPARENT
| INFIX
| ENUM
| LOCAL
| SYNTHETIC
| ARTIFACT
| MUTABLE
| FIELDaccessor
| CASEaccessor
| COVARIANT
| CONTRAVARIANT
| HASDEFAULT
| STABLE
| EXTENSION
| PARAMsetter
| PARAMalias
| EXPORTED
| OPEN
| INVISIBLE
| ANNOTATION
| PRIVATEqualified
| PROTECTEDqualified
| TRACKED => true
case _ => false
}
def isTypeTreeTag(tag: Int): Boolean = tag match {
case IDENTtpt
| SELECTtpt
| SINGLETONtpt
| REFINEDtpt
| APPLIEDtpt
| LAMBDAtpt
| TYPEBOUNDStpt
| ANNOTATEDtpt
| BYNAMEtpt
| MATCHtpt
| EXPLICITtpt
| BIND => true
case _ => false
}
def astTagToString(tag: Int): String = tag match {
case UNITconst => "UNITconst"
case FALSEconst => "FALSEconst"
case TRUEconst => "TRUEconst"
case NULLconst => "NULLconst"
case PRIVATE => "PRIVATE"
case PROTECTED => "PROTECTED"
case ABSTRACT => "ABSTRACT"
case FINAL => "FINAL"
case SEALED => "SEALED"
case CASE => "CASE"
case IMPLICIT => "IMPLICIT"
case ERASED => "ERASED"
case LAZY => "LAZY"
case OVERRIDE => "OVERRIDE"
case INLINE => "INLINE"
case INLINEPROXY => "INLINEPROXY"
case MACRO => "MACRO"
case OPAQUE => "OPAQUE"
case STATIC => "STATIC"
case OBJECT => "OBJECT"
case TRAIT => "TRAIT"
case TRANSPARENT => "TRANSPARENT"
case INFIX => "INFIX"
case ENUM => "ENUM"
case LOCAL => "LOCAL"
case SYNTHETIC => "SYNTHETIC"
case ARTIFACT => "ARTIFACT"
case MUTABLE => "MUTABLE"
case FIELDaccessor => "FIELDaccessor"
case CASEaccessor => "CASEaccessor"
case COVARIANT => "COVARIANT"
case CONTRAVARIANT => "CONTRAVARIANT"
case HASDEFAULT => "HASDEFAULT"
case STABLE => "STABLE"
case EXTENSION => "EXTENSION"
case GIVEN => "GIVEN"
case PARAMsetter => "PARAMsetter"
case EXPORTED => "EXPORTED"
case OPEN => "OPEN"
case INVISIBLE => "INVISIBLE"
case PARAMalias => "PARAMalias"
case EMPTYCLAUSE => "EMPTYCLAUSE"
case SPLITCLAUSE => "SPLITCLAUSE"
case SHAREDterm => "SHAREDterm"
case SHAREDtype => "SHAREDtype"
case TERMREFdirect => "TERMREFdirect"
case TYPEREFdirect => "TYPEREFdirect"
case TERMREFpkg => "TERMREFpkg"
case TYPEREFpkg => "TYPEREFpkg"
case RECthis => "RECthis"
case BYTEconst => "BYTEconst"
case SHORTconst => "SHORTconst"
case CHARconst => "CHARconst"
case INTconst => "INTconst"
case LONGconst => "LONGconst"
case FLOATconst => "FLOATconst"
case DOUBLEconst => "DOUBLEconst"
case STRINGconst => "STRINGconst"
case RECtype => "RECtype"
case IDENT => "IDENT"
case IDENTtpt => "IDENTtpt"
case SELECT => "SELECT"
case SELECTtpt => "SELECTtpt"
case TERMREFsymbol => "TERMREFsymbol"
case TERMREF => "TERMREF"
case TYPEREFsymbol => "TYPEREFsymbol"
case TYPEREF => "TYPEREF"
case PACKAGE => "PACKAGE"
case VALDEF => "VALDEF"
case DEFDEF => "DEFDEF"
case TYPEDEF => "TYPEDEF"
case IMPORT => "IMPORT"
case EXPORT => "EXPORT"
case TYPEPARAM => "TYPEPARAM"
case PARAM => "PARAM"
case IMPORTED => "IMPORTED"
case RENAMED => "RENAMED"
case BOUNDED => "BOUNDED"
case APPLY => "APPLY"
case TYPEAPPLY => "TYPEAPPLY"
case APPLYsigpoly => "APPLYsigpoly"
case NEW => "NEW"
case THROW => "THROW"
case TYPED => "TYPED"
case NAMEDARG => "NAMEDARG"
case ASSIGN => "ASSIGN"
case BLOCK => "BLOCK"
case IF => "IF"
case LAMBDA => "LAMBDA"
case MATCH => "MATCH"
case RETURN => "RETURN"
case WHILE => "WHILE"
case INLINED => "INLINED"
case SELECTouter => "SELECTouter"
case TRY => "TRY"
case REPEATED => "REPEATED"
case BIND => "BIND"
case ALTERNATIVE => "ALTERNATIVE"
case UNAPPLY => "UNAPPLY"
case ANNOTATEDtype => "ANNOTATEDtype"
case ANNOTATEDtpt => "ANNOTATEDtpt"
case CASEDEF => "CASEDEF"
case IMPLICITarg => "IMPLICITarg"
case TEMPLATE => "TEMPLATE"
case SELFDEF => "SELFDEF"
case THIS => "THIS"
case QUALTHIS => "QUALTHIS"
case SUPER => "SUPER"
case CLASSconst => "CLASSconst"
case SINGLETONtpt => "SINGLETONtpt"
case SUPERtype => "SUPERtype"
case TERMREFin => "TERMREFin"
case TYPEREFin => "TYPEREFin"
case SELECTin => "SELECTin"
case REFINEDtype => "REFINEDtype"
case REFINEDtpt => "REFINEDtpt"
case APPLIEDtype => "APPLIEDtype"
case APPLIEDtpt => "APPLIEDtpt"
case TYPEBOUNDS => "TYPEBOUNDS"
case TYPEBOUNDStpt => "TYPEBOUNDStpt"
case ANDtype => "ANDtype"
case ORtype => "ORtype"
case BYNAMEtype => "BYNAMEtype"
case BYNAMEtpt => "BYNAMEtpt"
case POLYtype => "POLYtype"
case METHODtype => "METHODtype"
case TYPELAMBDAtype => "TYPELAMBDAtype"
case LAMBDAtpt => "LAMBDAtpt"
case MATCHtype => "MATCHtype"
case MATCHCASEtype => "MATCHCASEtype"
case MATCHtpt => "MATCHtpt"
case PARAMtype => "PARAMtype"
case FLEXIBLEtype => "FLEXIBLEtype"
case ANNOTATION => "ANNOTATION"
case PRIVATEqualified => "PRIVATEqualified"
case PROTECTEDqualified => "PROTECTEDqualified"
case EXPLICITtpt => "EXPLICITtpt"
case ELIDED => "ELIDED"
case QUOTE => "QUOTE"
case SPLICE => "SPLICE"
case QUOTEPATTERN => "QUOTEPATTERN"
case SPLICEPATTERN => "SPLICEPATTERN"
case HOLE => "HOLE"
}
def attributeTagToString(tag: Int): String = tag match {
case SCALA2STANDARDLIBRARYattr => "SCALA2STANDARDLIBRARYattr"
case EXPLICITNULLSattr => "EXPLICITNULLSattr"
case CAPTURECHECKEDattr => "CAPTURECHECKEDattr"
case WITHPUREFUNSattr => "WITHPUREFUNSattr"
case JAVAattr => "JAVAattr"
case OUTLINEattr => "OUTLINEattr"
case SOURCEFILEattr => "SOURCEFILEattr"
}
/** @return If non-negative, the number of leading references (represented as nats) of a length/trees entry.
* If negative, minus the number of leading non-reference trees.
*/
def numRefs(tag: Int): Int = tag match {
case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | RETURN | BIND |
SELFDEF | REFINEDtype | TERMREFin | TYPEREFin | SELECTin | HOLE => 1
case RENAMED | PARAMtype => 2
case POLYtype | TYPELAMBDAtype | METHODtype => -1
case _ => 0
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy