Skip to content

Commit c8c0aab

Browse files
committed
Add untyped types to Tasty
Allow UNTYPEDSPLICE roots with TYPEDSPLICE subtrees. Trees between them are untyped.
1 parent 1821b50 commit c8c0aab

File tree

4 files changed

+448
-25
lines changed

4 files changed

+448
-25
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
642642

643643
override def skipTransform(tree: Tree)(implicit ctx: Context) = tree.tpe.isError
644644

645-
implicit class TreeOps[ThisTree <: tpd.Tree](val tree: ThisTree) extends AnyVal {
645+
implicit class TreeOps[ThisTree <: tpd.Tree](private val tree: ThisTree) extends AnyVal {
646646

647647
def isValue(implicit ctx: Context): Boolean =
648648
tree.isTerm && tree.tpe.widen.isValueType

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Standard-Section: "ASTs" TopLevelStat*
5959
DEFDEF Length NameRef TypeParam* Params* returnType_Term rhs_Term?
6060
Modifier*
6161
TYPEDEF Length NameRef (type_Term | Template) Modifier*
62+
OBJECTDEF Length NameRef Template Mods
6263
IMPORT Length qual_Term Selector*
6364
Selector = IMPORTED name_NameRef
6465
RENAMED to_NameRef
@@ -109,6 +110,7 @@ Standard-Section: "ASTs" TopLevelStat*
109110
EMPTYTREE
110111
SHAREDterm term_ASTRef
111112
HOLE Length idx_Nat arg_Tree*
113+
UNTYPEDSPLICE Length splice_TermUntyped splice_Type
112114
113115
CaseDef = CASEDEF Length pat_Term rhs_Tree guard_Tree?
114116
ImplicitArg = IMPLICITARG arg_Term
@@ -203,6 +205,13 @@ Standard-Section: "ASTs" TopLevelStat*
203205
204206
Annotation = ANNOTATION Length tycon_Type fullAnnotation_Term
205207
208+
// --------------- untyped additions ------------------------------------------
209+
210+
TermUntyped = Term
211+
FUNCTION Length body_Term arg_Term*
212+
INFIXOP Length op_NameRef left_Term right_Term
213+
TYPEDSPLICE Length splice_Term
214+
206215
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.
207216
208217
Category 1 (tags 1-49) : tag
@@ -402,6 +411,7 @@ object TastyFormat {
402411
final val ANNOTATION = 172
403412
final val TERMREFin = 173
404413
final val TYPEREFin = 174
414+
final val OBJECTDEF = 175
405415

406416
// In binary: 101100EI
407417
// I = implicit method type
@@ -411,6 +421,13 @@ object TastyFormat {
411421
final val ERASEDMETHODtype = 178
412422
final val ERASEDIMPLICITMETHODtype = 179
413423

424+
final val UNTYPEDSPLICE = 199
425+
426+
// Tags for untyped trees only:
427+
final val TYPEDSPLICE = 200
428+
final val FUNCTION = 201
429+
final val INFIXOP = 202
430+
414431
def methodType(isImplicit: Boolean = false, isErased: Boolean = false) = {
415432
val implicitOffset = if (isImplicit) 1 else 0
416433
val erasedOffset = if (isErased) 2 else 0
@@ -554,6 +571,7 @@ object TastyFormat {
554571
case VALDEF => "VALDEF"
555572
case DEFDEF => "DEFDEF"
556573
case TYPEDEF => "TYPEDEF"
574+
case OBJECTDEF => "OBJECTDEF"
557575
case IMPORT => "IMPORT"
558576
case TYPEPARAM => "TYPEPARAM"
559577
case PARAMS => "PARAMS"
@@ -621,13 +639,18 @@ object TastyFormat {
621639
case PRIVATEqualified => "PRIVATEqualified"
622640
case PROTECTEDqualified => "PROTECTEDqualified"
623641
case HOLE => "HOLE"
642+
643+
case UNTYPEDSPLICE => "UNTYPEDSPLICE"
644+
case TYPEDSPLICE => "TYPEDSPLICE"
645+
case FUNCTION => "FUNCTION"
646+
case INFIXOP => "INFIXOP"
624647
}
625648

626649
/** @return If non-negative, the number of leading references (represented as nats) of a length/trees entry.
627650
* If negative, minus the number of leading non-reference trees.
628651
*/
629652
def numRefs(tag: Int) = tag match {
630-
case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM | NAMEDARG | RETURN | BIND |
653+
case VALDEF | DEFDEF | TYPEDEF | OBJECTDEF | TYPEPARAM | PARAM | NAMEDARG | RETURN | BIND |
631654
SELFDEF | REFINEDtype | TERMREFin | TYPEREFin | HOLE => 1
632655
case RENAMED | PARAMtype => 2
633656
case POLYtype | METHODtype | TYPELAMBDAtype => -1

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

Lines changed: 210 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package core
44
package tasty
55

66
import ast.Trees._
7-
import ast.{untpd, tpd}
7+
import ast.{untpd, tpd, desugar}
88
import TastyFormat._
99
import Contexts._, Symbols._, Types._, Names._, Constants._, Decorators._, Annotations._, StdNames.tpnme, NameOps._
1010
import collection.mutable
@@ -546,6 +546,10 @@ class TreePickler(pickler: TastyPickler) {
546546
pickleTree(lo);
547547
if (hi ne lo) pickleTree(hi)
548548
}
549+
case tpd.UntypedSplice(splice) =>
550+
//println(i"UNTYPED: $splice")
551+
writeByte(UNTYPEDSPLICE)
552+
withLength { pickleUntyped(splice); pickleType(tree.tpe) }
549553
case Hole(idx, args) =>
550554
writeByte(HOLE)
551555
withLength {
@@ -644,6 +648,211 @@ class TreePickler(pickler: TastyPickler) {
644648
withLength { pickleType(ann.symbol.typeRef); pickleTree(ann.tree) }
645649
}
646650

651+
// ---- pickling untyped trees ----------------------------------
652+
653+
def pickleUntyped(tree: untpd.Tree)(implicit ctx: Context): Unit = {
654+
try desugar(tree) match {
655+
case Ident(name) =>
656+
writeByte(if (name.isTypeName) TYPEREF else TERMREF)
657+
pickleName(name)
658+
pickleDummyType()
659+
case This(qual) =>
660+
writeByte(QUALTHIS)
661+
pickleUntyped(qual)
662+
case Select(qual, name) =>
663+
writeByte(if (name.isTypeName) SELECTtpt else SELECT)
664+
pickleName(name)
665+
pickleUntyped(qual)
666+
case Apply(fun, args) =>
667+
writeByte(APPLY)
668+
withLength {
669+
pickleUntyped(fun)
670+
args.foreach(pickleUntyped)
671+
}
672+
case untpd.Throw(exc) =>
673+
writeByte(THROW)
674+
pickleUntyped(exc)
675+
case TypeApply(fun, args) =>
676+
writeByte(TYPEAPPLY)
677+
withLength {
678+
pickleUntyped(fun)
679+
args.foreach(pickleUntyped)
680+
}
681+
case Literal(const) =>
682+
pickleConstant(const)
683+
case Super(qual, mix) =>
684+
writeByte(SUPER)
685+
withLength {
686+
pickleUntyped(qual);
687+
if (!mix.isEmpty) pickleUntyped(mix)
688+
}
689+
case New(tpt) =>
690+
writeByte(NEW)
691+
pickleUntyped(tpt)
692+
case Typed(expr, tpt) =>
693+
writeByte(TYPED)
694+
withLength { pickleUntyped(expr); pickleUntyped(tpt) }
695+
case NamedArg(name, arg) =>
696+
writeByte(NAMEDARG)
697+
pickleName(name)
698+
pickleUntyped(arg)
699+
case Assign(lhs, rhs) =>
700+
writeByte(ASSIGN)
701+
withLength { pickleUntyped(lhs); pickleUntyped(rhs) }
702+
case Block(stats, expr) =>
703+
writeByte(BLOCK)
704+
withLength { pickleUntyped(expr); stats.foreach(pickleUntyped) }
705+
case If(cond, thenp, elsep) =>
706+
writeByte(IF)
707+
withLength { pickleUntyped(cond); pickleUntyped(thenp); pickleUntyped(elsep) }
708+
case Match(selector, cases) =>
709+
writeByte(MATCH)
710+
withLength { pickleUntyped(selector); cases.foreach(pickleUntyped) }
711+
case CaseDef(pat, guard, rhs) =>
712+
writeByte(CASEDEF)
713+
withLength { pickleUntyped(pat); pickleUntyped(rhs); pickleUntypedUnlessEmpty(guard) }
714+
case Return(expr, from) =>
715+
writeByte(RETURN)
716+
withLength { pickleDummyRef(); pickleUntypedUnlessEmpty(expr) }
717+
case Try(block, cases, finalizer) =>
718+
writeByte(TRY)
719+
withLength { pickleUntyped(block); cases.foreach(pickleUntyped); pickleUntypedUnlessEmpty(finalizer) }
720+
case Bind(name, body) =>
721+
writeByte(BIND)
722+
withLength {
723+
pickleName(name); pickleDummyType(); pickleUntyped(body)
724+
}
725+
case Alternative(alts) =>
726+
writeByte(ALTERNATIVE)
727+
withLength { alts.foreach(pickleUntyped) }
728+
case tree: untpd.ValDef =>
729+
pickleUntypedDef(VALDEF, tree, tree.tpt, tree.rhs)
730+
case tree: untpd.DefDef =>
731+
pickleUntypedDef(DEFDEF, tree, tree.tpt, tree.rhs, pickleAllUntypedParams(tree))
732+
case tree: untpd.TypeDef =>
733+
pickleUntypedDef(TYPEDEF, tree, tree.rhs)
734+
case tree: untpd.ModuleDef =>
735+
pickleUntypedDef(OBJECTDEF, tree, tree.impl)
736+
case tree: untpd.Template =>
737+
writeByte(TEMPLATE)
738+
tree.parents.foreach(pickleUntyped)
739+
if (!tree.self.isEmpty) {
740+
writeByte(SELFDEF); pickleName(tree.self.name); pickleUntyped(tree.self.tpt)
741+
}
742+
pickleUntyped(tree.constr)
743+
tree.body.foreach(pickleUntyped)
744+
case Import(expr, selectors) =>
745+
writeByte(IMPORT)
746+
withLength { pickleUntyped(expr); pickleSelectors(selectors) }
747+
case tree: untpd.TypeTree =>
748+
pickleDummyType()
749+
case SingletonTypeTree(ref) =>
750+
writeByte(SINGLETONtpt)
751+
pickleUntyped(ref)
752+
case RefinedTypeTree(parent, refinements) =>
753+
writeByte(REFINEDtpt)
754+
withLength { pickleUntyped(parent); refinements.foreach(pickleUntyped) }
755+
case AppliedTypeTree(tycon, args) =>
756+
writeByte(APPLIEDtpt)
757+
withLength { pickleUntyped(tycon); args.foreach(pickleUntyped) }
758+
case AndTypeTree(tp1, tp2) =>
759+
writeByte(ANDtpt)
760+
withLength { pickleUntyped(tp1); pickleUntyped(tp2) }
761+
case OrTypeTree(tp1, tp2) =>
762+
writeByte(ORtpt)
763+
withLength { pickleUntyped(tp1); pickleUntyped(tp2) }
764+
case ByNameTypeTree(tp) =>
765+
writeByte(BYNAMEtpt)
766+
pickleUntyped(tp)
767+
case Annotated(tree, annot) =>
768+
writeByte(ANNOTATEDtpt)
769+
withLength { pickleUntyped(tree); pickleUntyped(annot) }
770+
case LambdaTypeTree(tparams, body) =>
771+
writeByte(LAMBDAtpt)
772+
withLength { pickleUntypedParams(tparams); pickleUntyped(body) }
773+
case TypeBoundsTree(lo, hi) =>
774+
writeByte(TYPEBOUNDStpt)
775+
withLength {
776+
pickleUntyped(lo);
777+
if (hi ne lo) pickleUntyped(hi)
778+
}
779+
case untpd.Function(args, body) =>
780+
writeByte(FUNCTION)
781+
withLength { pickleUntyped(body); args.foreach(pickleUntyped) }
782+
case untpd.InfixOp(l, op, r) =>
783+
writeByte(INFIXOP)
784+
withLength { pickleUntyped(l); pickleUntyped(op); pickleUntyped(r) }
785+
case Thicket(trees) =>
786+
trees.foreach(pickleUntyped)
787+
case untpd.TypedSplice(splice) =>
788+
writeByte(TYPEDSPLICE)
789+
withLength { pickleTree(splice) }
790+
}
791+
catch {
792+
case ex: AssertionError =>
793+
println(i"error when pickling tree $tree")
794+
throw ex
795+
}
796+
}
797+
798+
def pickleUntypedUnlessEmpty(tree: untpd.Tree)(implicit ctx: Context): Unit =
799+
if (!tree.isEmpty) pickleUntyped(tree)
800+
801+
def pickleAllUntypedParams(tree: untpd.DefDef)(implicit ctx: Context): Unit = {
802+
pickleUntypedParams(tree.tparams)
803+
for (vparams <- tree.vparamss) {
804+
writeByte(PARAMS)
805+
withLength { pickleUntypedParams(vparams) }
806+
}
807+
}
808+
809+
def pickleUntypedParams(trees: List[untpd.Tree])(implicit ctx: Context): Unit =
810+
trees.foreach(pickleUntypedParam)
811+
812+
def pickleUntypedDef(tag: Int, tree: untpd.MemberDef, tpt: untpd.Tree, rhs: untpd.Tree = untpd.EmptyTree, pickleParams: => Unit = ())(implicit ctx: Context) = {
813+
import untpd.modsDeco
814+
writeByte(tag)
815+
withLength {
816+
pickleName(tree.name)
817+
pickleParams
818+
pickleUntyped(tpt)
819+
pickleUntypedUnlessEmpty(rhs)
820+
pickleUntypedModifiers(tree.mods)
821+
}
822+
}
823+
824+
def pickleUntypedParam(tree: untpd.Tree)(implicit ctx: Context): Unit = tree match {
825+
case tree: untpd.ValDef => pickleUntypedDef(PARAM, tree, tree.tpt)
826+
case tree: untpd.DefDef => pickleUntypedDef(PARAM, tree, tree.tpt, tree.rhs)
827+
case tree: untpd.TypeDef => pickleUntypedDef(TYPEPARAM, tree, tree.rhs)
828+
}
829+
830+
def pickleUntypedModifiers(mods: untpd.Modifiers)(implicit ctx: Context): Unit = {
831+
import Flags._
832+
var flags = mods.flags
833+
val privateWithin = mods.privateWithin
834+
if (!privateWithin.isEmpty) {
835+
writeByte(if (flags is Protected) PROTECTEDqualified else PRIVATEqualified)
836+
pickleUntyped(untpd.Ident(privateWithin))
837+
flags = flags &~ Protected
838+
}
839+
mods.annotations.foreach(pickleUntypedAnnotation)
840+
}
841+
842+
def pickleUntypedAnnotation(annotTree: untpd.Tree)(implicit ctx: Context) = {
843+
writeByte(ANNOTATION)
844+
withLength { pickleDummyType(); pickleUntyped(annotTree) }
845+
}
846+
847+
def pickleDummyRef(): Unit = writeNat(0)
848+
849+
def pickleDummyType(): Unit = {
850+
writeByte(SHAREDtype)
851+
pickleDummyRef()
852+
}
853+
854+
// ---- main entry points ---------------------------------------
855+
647856
def pickle(trees: List[Tree])(implicit ctx: Context) = {
648857
trees.foreach(tree => if (!tree.isEmpty) pickleTree(tree))
649858
def missing = forwardSymRefs.keysIterator.map(_.showLocated).toList

0 commit comments

Comments
 (0)