From b4f901be72117e4867d06c464d1d8954ef06f5a9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 5 Nov 2019 16:22:14 +0100 Subject: [PATCH 1/2] Change Tasty parameter encoding New way is to have PARAM, TYPEPAAM, and PARAMEND tags. A PARAMEND is needed to mark a preceding empty parameter section, or a following parameter section. Bumps Tasty version. --- .../tools/dotc/core/tasty/TastyFormat.scala | 17 ++++++------ .../tools/dotc/core/tasty/TreePickler.scala | 14 +++++----- .../tools/dotc/core/tasty/TreeUnpickler.scala | 26 +++++++++++-------- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index 8437ea9b4c6b..db1a727f86da 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -69,9 +69,10 @@ Standard-Section: "ASTs" TopLevelStat* BOUNDED type_Term -- type bound TypeParam = TYPEPARAM Length NameRef type_Term Modifier* -- modifiers name bounds - Params = PARAMS Length Param* Param = PARAM Length NameRef type_Term rhs_Term? Modifier* -- modifiers name : type (= rhs_Term)?. `rhsTerm` is present in the case of an aliased class parameter - Template = TEMPLATE Length TypeParam* Params* parent_Term* Self? Stat* -- [typeparams] paramss extends parents { self => stats }, where Stat* always starts with the primary constructor. + PARAMEND -- ends a parameter clause + -- needed if previous parameter clause is empty or another parameter clause follows + Template = TEMPLATE Length TypeParam* Param* parent_Term* Self? Stat* -- [typeparams] paramss extends parents { self => stats }, where Stat* always starts with the primary constructor. Self = SELFDEF selfName_NameRef selfType_Term -- selfName : selfType Term = Path -- Paths represent both types and terms @@ -252,7 +253,7 @@ Standard Section: "Comments" Comment* object TastyFormat { final val header: Array[Int] = Array(0x5C, 0xA1, 0xAB, 0x1F) - val MajorVersion: Int = 17 + val MajorVersion: Int = 18 val MinorVersion: Int = 0 /** Tags used to serialize names */ @@ -273,7 +274,7 @@ object TastyFormat { final val DEFAULTGETTER = 11 // The name `$default$` // of a default getter that returns a default argument. - final val VARIANT = 12 // A name `+` o `-` indicating + final val VARIANT = 12 // A name `+` or `-` indicating // a co- or contra-variant parameter of a type lambda. final val SUPERACCESSOR = 20 // The name of a super accessor `super$name` created by SuperAccesors. @@ -334,6 +335,7 @@ object TastyFormat { final val PARAMsetter = 38 final val EXPORTED = 39 final val OPEN = 40 + final val PARAMEND = 41 // Cat. 2: tag Nat @@ -394,8 +396,7 @@ object TastyFormat { final val TYPEDEF = 131 final val IMPORT = 132 final val TYPEPARAM = 133 - final val PARAMS = 134 - final val PARAM = 135 + final val PARAM = 134 final val APPLY = 136 final val TYPEAPPLY = 137 final val TYPED = 138 @@ -462,7 +463,7 @@ object TastyFormat { /** Useful for debugging */ def isLegalTag(tag: Int): Boolean = - firstSimpleTreeTag <= tag && tag <= OPEN || + firstSimpleTreeTag <= tag && tag <= PARAMEND || firstNatTreeTag <= tag && tag <= RENAMED || firstASTTreeTag <= tag && tag <= BOUNDED || firstNatASTTreeTag <= tag && tag <= NAMEDARG || @@ -569,6 +570,7 @@ object TastyFormat { case PARAMsetter => "PARAMsetter" case EXPORTED => "EXPORTED" case OPEN => "OPEN" + case PARAMEND => "PARAMEND" case SHAREDterm => "SHAREDterm" case SHAREDtype => "SHAREDtype" @@ -602,7 +604,6 @@ object TastyFormat { case TYPEDEF => "TYPEDEF" case IMPORT => "IMPORT" case TYPEPARAM => "TYPEPARAM" - case PARAMS => "PARAMS" case PARAM => "PARAM" case IMPORTED => "IMPORTED" case RENAMED => "RENAMED" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index f8c73bd8441f..feb96a4929b0 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -494,13 +494,15 @@ class TreePickler(pickler: TastyPickler) { case tree: ValDef => pickleDef(VALDEF, tree.symbol, tree.tpt, tree.rhs) case tree: DefDef => - def pickleAllParams = { + def pickleParamss(paramss: List[List[ValDef]]): Unit = paramss match + case Nil => + case params :: rest => + pickleParams(params) + if params.isEmpty || rest.nonEmpty then writeByte(PARAMEND) + pickleParamss(rest) + def pickleAllParams = pickleParams(tree.tparams) - for (vparams <- tree.vparamss) { - writeByte(PARAMS) - withLength { pickleParams(vparams) } - } - } + pickleParamss(tree.vparamss) pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleAllParams) case tree: TypeDef => pickleDef(TYPEDEF, tree.symbol, tree.rhs) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 48ed7014db4c..acacd0f0cfdd 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -131,7 +131,10 @@ class TreeUnpickler(reader: TastyReader, def skipTree(): Unit = skipTree(readByte()) def skipParams(): Unit = - while (nextByte == PARAMS || nextByte == TYPEPARAM) skipTree() + while + val tag = nextByte + tag == PARAM || tag == TYPEPARAM || tag == PARAMEND + do skipTree() /** Record all directly nested definitions and templates in current tree * as `OwnerTree`s in `buf`. @@ -747,12 +750,12 @@ class TreeUnpickler(reader: TastyReader, val tag = readByte() val end = readEnd() - def readParamss(implicit ctx: Context): List[List[ValDef]] = - collectWhile(nextByte == PARAMS) { - readByte() - readEnd() - readParams[ValDef](PARAM) - } + def readParamss(implicit ctx: Context): List[List[ValDef]] = nextByte match + case PARAM | PARAMEND => + readParams[ValDef](PARAM) :: + (if nextByte == PARAMEND then { readByte(); readParamss } else Nil) + case _ => + Nil val localCtx = localContext(sym) @@ -987,10 +990,11 @@ class TreeUnpickler(reader: TastyReader, def readIndexedParams[T <: MemberDef](tag: Int)(implicit ctx: Context): List[T] = collectWhile(nextByte == tag) { readIndexedDef().asInstanceOf[T] } - def readParams[T <: MemberDef](tag: Int)(implicit ctx: Context): List[T] = { - fork.indexParams(tag) - readIndexedParams(tag) - } + def readParams[T <: MemberDef](tag: Int)(implicit ctx: Context): List[T] = + if nextByte == tag then + fork.indexParams(tag) + readIndexedParams(tag) + else Nil // ------ Reading trees ----------------------------------------------------- From 058fc4f1de704934c753cd7200a9dc5ad908b3a5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 6 Nov 2019 16:15:38 +0100 Subject: [PATCH 2/2] Fix comment indent --- compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index db1a727f86da..927a5477f311 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -71,7 +71,7 @@ Standard-Section: "ASTs" TopLevelStat* TypeParam = TYPEPARAM Length NameRef type_Term Modifier* -- modifiers name bounds Param = PARAM Length NameRef type_Term rhs_Term? Modifier* -- modifiers name : type (= rhs_Term)?. `rhsTerm` is present in the case of an aliased class parameter PARAMEND -- ends a parameter clause - -- needed if previous parameter clause is empty or another parameter clause follows + -- needed if previous parameter clause is empty or another parameter clause follows Template = TEMPLATE Length TypeParam* Param* parent_Term* Self? Stat* -- [typeparams] paramss extends parents { self => stats }, where Stat* always starts with the primary constructor. Self = SELFDEF selfName_NameRef selfType_Term -- selfName : selfType