Skip to content

Commit 96e7a36

Browse files
committed
Tasty Reflection
As a first step towards a reflective macro system based on Tasty, a high-level view of what tasty trees are. So far omitted are positions and how to compute types. This first commit should serve ad a blueprint for an extractor-based approach that connects to the underling trees.
1 parent 58fe948 commit 96e7a36

File tree

3 files changed

+290
-15
lines changed

3 files changed

+290
-15
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2862,15 +2862,16 @@ object Types {
28622862

28632863
type This = MethodType
28642864

2865+
val paramInfos = paramInfosExp(this)
2866+
val resType = resultTypeExp(this)
2867+
assert(resType.exists)
2868+
28652869
def companion: MethodTypeCompanion
28662870

28672871
final override def isJavaMethod: Boolean = companion eq JavaMethodType
28682872
final override def isImplicitMethod: Boolean = companion.eq(ImplicitMethodType) || companion.eq(ErasedImplicitMethodType)
28692873
final override def isErasedMethod: Boolean = companion.eq(ErasedMethodType) || companion.eq(ErasedImplicitMethodType)
28702874

2871-
val paramInfos = paramInfosExp(this)
2872-
val resType = resultTypeExp(this)
2873-
assert(resType.exists)
28742875

28752876
def computeSignature(implicit ctx: Context): Signature = {
28762877
val params = if (isErasedMethod) Nil else paramInfos

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ Standard-Section: "ASTs" TopLevelStat*
5656
Stat
5757
5858
Stat = Term
59-
VALDEF Length NameRef Type rhs_Term? Modifier*
60-
DEFDEF Length NameRef TypeParam* Params* return_Type rhs_Term?
59+
VALDEF Length NameRef type_Term rhs_Term? Modifier*
60+
DEFDEF Length NameRef TypeParam* Params* returnType_Term rhs_Term?
6161
Modifier*
62-
TYPEDEF Length NameRef (Type | Template) Modifier*
62+
TYPEDEF Length NameRef (type_Term | Template) Modifier*
6363
IMPORT Length qual_Term Selector*
6464
Selector = IMPORTED name_NameRef
6565
RENAMED to_NameRef
@@ -69,20 +69,19 @@ Standard-Section: "ASTs" TopLevelStat*
6969
TypeParam = TYPEPARAM Length NameRef Type Modifier*
7070
Params = PARAMS Length Param*
7171
Param = PARAM Length NameRef Type rhs_Term? Modifier* // rhs_Term is present in the case of an aliased class parameter
72-
Template = TEMPLATE Length TypeParam* Param* Parent* Self? Stat* // Stat* always starts with the primary constructor.
73-
Parent = Application
74-
Type
72+
Template = TEMPLATE Length TypeParam* Param* parent_Term* Self? Stat* // Stat* always starts with the primary constructor.
7573
Self = SELFDEF selfName_NameRef selfType_Type
7674
7775
Term = Path
78-
Application
7976
IDENT NameRef Type // used when term ident’s type is not a TermRef
8077
SELECT possiblySigned_NameRef qual_Term
8178
QUALTHIS typeIdent_Tree
82-
NEW cls_Type
79+
NEW clsType_Term
8380
NAMEDARG paramName_NameRef arg_Term
81+
APPLY Length fn_Term arg_Term*
82+
TYPEAPPLY Length fn_Term arg_Type*
8483
SUPER Length this_Term mixinTypeIdent_Tree?
85-
TYPED Length expr_Term ascription_Type
84+
TYPED Length expr_Term ascriptionType_Tern
8685
ASSIGN Length lhs_Term rhs_Term
8786
BLOCK Length expr_Term Stat*
8887
INLINED Length call_Term expr_Term Stat*
@@ -98,7 +97,7 @@ Standard-Section: "ASTs" TopLevelStat*
9897
UNAPPLY Length fun_Term ImplicitArg* pat_Type pat_Term*
9998
IDENTtpt NameRef Type // used for all type idents
10099
SELECTtpt NameRef qual_Term
101-
SINGLETONtpt Path
100+
SINGLETONtpt ref_Term
102101
REFINEDtpt Length underlying_Term refinement_Stat*
103102
APPLIEDtpt Length tycon_Term arg_Term*
104103
POLYtpt Length TypeParam* body_Term
@@ -110,9 +109,7 @@ Standard-Section: "ASTs" TopLevelStat*
110109
EMPTYTREE
111110
SHAREDterm term_ASTRef
112111
HOLE Length idx_Nat arg_Tree*
113-
Application = APPLY Length fn_Term arg_Term*
114112
115-
TYPEAPPLY Length fn_Term arg_Type*
116113
CaseDef = CASEDEF Length pat_Term rhs_Tree guard_Tree?
117114
ImplicitArg = IMPLICITARG arg_Term
118115
ASTRef = Nat // byte position in AST payload
@@ -179,6 +176,7 @@ Standard-Section: "ASTs" TopLevelStat*
179176
SEALED
180177
CASE
181178
IMPLICIT
179+
ERASED
182180
LAZY
183181
OVERRIDE
184182
INLINE // inline method

tests/pos/TastyADT.scala

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
object tasty {
2+
3+
trait PossiblySignedName
4+
5+
enum Name extends PossiblySignedName {
6+
case Simple(str: String)
7+
case Qualified(prefix: Name, selector: String) // s"$prefix.$name"
8+
case Unique(underlying: Name, separator: String, idx: Int) // s"$underlying$separator$idx"
9+
case DefaultGetter(methodName: Name, idx: String) // s"$methodName${"$default$"}${idx+1}"
10+
case Variant(underlying: Name, covariant: Boolean) // s"${if (covariant) "+" else "-"}$underlying"
11+
case SuperAccessor(underlying: Name) // s"${"super$"}$underlying"
12+
case ProtectedAccessor(underlying: Name) // s"${"protectded$"}$underlying"
13+
case ProtectedSetter(underlying: Name) // s"${"protectded$set"}$underlying"
14+
case ObjectClass(underlying: Name) // s"$underlying${"$"}"
15+
16+
case Expanded(prefix: Name, selector: String) // s"$prefix${"$$"}$name" , used only for symbols coming from Scala 2
17+
case ExpandedPrefix(prefix: Name, selector: String) // s"$prefix${"$"}$name" , used only for symbols coming from Scala 2
18+
}
19+
20+
case class SignedName(name: Name, resultSig: Name, paramSigs: List[Name]) extends PossiblySignedName
21+
22+
trait TopLevelStatement
23+
24+
trait Statement extends TopLevelStatement
25+
26+
case class Package(pkg: Term, body: List[TopLevelStatement]) extends TopLevelStatement
27+
28+
trait Definition extends Statement {
29+
def tpe: Type = Type.SymRef(this, ???)
30+
}
31+
32+
class ValDef(
33+
val name: Name,
34+
val tpt: Term,
35+
rhsExp: ValDef => Term | Empty,
36+
val mods: List[Modifier])
37+
extends Definition {
38+
lazy val rhs = rhsExp(this)
39+
}
40+
object ValDef {
41+
def apply(name: Name, tpt: Term, rhs: Term | Empty, mods: List[Modifier] = Nil) =
42+
new ValDef(name, tpt, _ => rhs, mods)
43+
def unapply(vdef: ValDef) = Some((vdef.name, vdef.tpt, vdef.rhs, vdef.mods))
44+
}
45+
46+
class DefDef(
47+
val name: Name,
48+
typeParamsExp: DefDef => List[TypeDef],
49+
paramssExp: DefDef => List[List[ValDef]],
50+
returnTptExp: DefDef => Term,
51+
rhsExp: DefDef => Term | Empty,
52+
val mods: List[Modifier])
53+
extends Definition {
54+
val typeParams = typeParamsExp(this)
55+
val paramss = paramssExp(this)
56+
val returnTpt = returnTptExp(this)
57+
lazy val rhs = rhsExp(this)
58+
}
59+
object DefDef {
60+
def apply(name: Name, typeParams: List[TypeDef], paramss: List[List[ValDef]], returnTpt: Term, rhs: Term | Empty, mods: List[Modifier] = Nil) =
61+
new DefDef(name, _ => typeParams, _ => paramss, _ => returnTpt, _ => rhs, mods)
62+
def unapply(ddef: DefDef) = Some((ddef.name, ddef.typeParams, ddef.paramss, ddef.returnTpt, ddef.rhs))
63+
}
64+
65+
class TypeDef(
66+
val name: Name,
67+
rhsExp: TypeDef => Term,
68+
val mods: List[Modifier])
69+
extends Definition {
70+
val rhs = rhsExp(this),
71+
}
72+
object TypeDef {
73+
def apply(name: Name, rhs: Term, mods: List[Modifier] = Nil) = new TypeDef(name, _ => rhs, mods)
74+
def unapply(tdef: TypeDef) = Some((tdef.name, tdef.rhs))
75+
}
76+
77+
class ClassDef(
78+
val name: Name,
79+
rhsExp: ClassDef => Template,
80+
val mods: List[Modifier])
81+
extends Definition {
82+
val rhs = rhsExp(this)
83+
}
84+
object ClassDef {
85+
def apply(name: Name, rhs: Template, mods: List[Modifier] = Nil) = new ClassDef(name, _ => rhs, mods)
86+
def unapply(tdef: ClassDef) = Some((tdef.name, tdef.rhs))
87+
}
88+
89+
case class Template(
90+
typeParams: List[TypeDef],
91+
paramss: List[List[ValDef]],
92+
parents: List[Term],
93+
self: ValDef | Empty,
94+
body: List[Statement])
95+
96+
case class Import(expr: Term, selector: List[ImportSelector])
97+
98+
enum ImportSelector {
99+
case Simple(id: Id)
100+
case Rename(id1: Id, id2: Id)
101+
case Omit(id1: Id)
102+
}
103+
104+
case class Id(name: Name) // untyped ident
105+
106+
enum Term {
107+
def tpe: Type = ???
108+
case Ident(name: Name, override val tpe: Type)
109+
case Select(prefix: Term, name: PossiblySignedName)
110+
case Literal(value: Constant)
111+
case This(id: Id | Empty)
112+
case New(tpt: Term)
113+
case NamedArg(name: Name, arg: Term)
114+
case Apply(fn: Term, args: List[Term])
115+
case TypeApply(fn: Term, args: List[Term])
116+
case Super(thiz: Term, mixin: Id | Empty)
117+
case Typed(expr: Term, tpt: Term)
118+
case Assign(lhs: Term, rhs: Term)
119+
case Block(stats: List[Statement], expr: Term)
120+
case Inlined(call: Term, bindings: List[Definition], expr: Term)
121+
case Lambda(method: Term, tpt: Term | Empty)
122+
case If(cond: Term, thenPart: Term, elsePart: Term)
123+
case Match(scrutinee: Term, cases: List[CaseDef])
124+
case Try(body: Term, catches: List[CaseDef], finalizer: Term | Empty)
125+
case Return(expr: Term)
126+
case Repeated(args: List[Term])
127+
case SelectOuter(from: Term, levels: Int, target: Type) // can be generated by inlining
128+
case Tpt(underlying: TypeTerm | Empty)
129+
}
130+
131+
enum TypeTerm {
132+
def tpe: Type = ???
133+
case Ident(name: Name, override val tpe: Type)
134+
case Select(prefix: Term, name: Name)
135+
case Singleton(ref: Term)
136+
case Refined(underlying: TypeTerm, refinements: List[Definition])
137+
case Applied(tycon: TypeTerm, args: List[TypeTerm])
138+
case TypeBounds(loBound: TypeTerm, hiBound: TypeTerm)
139+
case Annotated(tpt: TypeTerm, annotation: Term)
140+
case And(left: TypeTerm, right: TypeTerm)
141+
case Or(left: TypeTerm, right: TypeTerm)
142+
case ByName(tpt: TypeTerm)
143+
}
144+
145+
enum Pattern {
146+
def tpe: Type = ???
147+
case Value(v: Term)
148+
case Bind(name: Name, pat: Pattern)
149+
case Unapply(unapply: Term, implicits: List[Term], pats: List[Pattern])
150+
case Alternative(pats: List[Pattern])
151+
case TypeTest(tpt: Term)
152+
case Wildcard()
153+
}
154+
155+
case class CaseDef(pat: Pattern, guard: Term | Empty, rhs: Term)
156+
157+
sealed trait Type
158+
159+
object Type {
160+
case class ConstantType(value: Constant) extends Type
161+
case class SymRef(sym: Definition, qualifier: Type | Empty = Empty) extends Type
162+
case class TypeNameRef(name: Name, qualifier: Type | Empty = Empty) extends Type // Empty means: select from _root_
163+
case class TermNameRef(name: Name, qualifier: Type | Empty = Empty) extends Type // Empty means: select from _root_
164+
case class SuperType(thistp: Type, underlying: Type) extends Type
165+
case class TermRefinement(underlying: Type, name: Name, tpe: Type) extends Type
166+
case class TypeRefinement(underlying: Type, name: Name, info: TypeBounds) extends Type
167+
case class AppliedType(tycon: Type, args: Type | TypeBounds) extends Type
168+
case class AnnotatedType(underlying: Type, annotation: Term) extends Type
169+
case class AndType(left: Type, right: Type) extends Type
170+
case class OrType(left: Type, right: Type) extends Type
171+
case class ByNameType(underlying: Type) extends Type
172+
case class ParamRef(binder: LambdaType, idx: Int) extends Type
173+
case class RecThis(binder: RecursiveType) extends Type
174+
175+
class RecursiveType(underlyingExp: RecursiveType => Type) extends Type {
176+
val underlying = underlyingExp(this)
177+
}
178+
object RecursiveType {
179+
def unapply(tp: RecursiveType): Option[Type] = Some(tp.underlying)
180+
}
181+
182+
trait LambdaType extends Type {
183+
type ParamInfo
184+
def paramNames: List[Name]
185+
def paramInfos: List[ParamInfo]
186+
def resultType: Type
187+
}
188+
189+
class MethodType(val paramNames: List[Name], paramTypesExp: MethodType => List[Type],
190+
resultTypeExp: MethodType => Type, val mods: List[Modifier]) extends LambdaType {
191+
type ParamInfo = Type
192+
val paramTypes = paramTypesExp(this)
193+
val resultType = resultTypeExp(this)
194+
def paramInfos = paramTypes
195+
}
196+
object MethodType {
197+
def apply(paramNames: List[Name], paramTypes: List[Type], resultType: Type, mods: List[Modifier] = Nil) =
198+
new MethodType(paramNames, _ => paramTypes, _ => resultType, mods)
199+
def unapply(tp: MethodType) = Some((tp.paramNames, tp.paramTypes, tp.resultType, tp.mods))
200+
}
201+
202+
class PolyType(val paramNames: List[Name], paramBoundsExp: PolyType => List[TypeBounds],
203+
resultTypeExp: PolyType => Type) extends LambdaType {
204+
type This = PolyType
205+
type ParamInfo = TypeBounds
206+
val paramBounds = paramBoundsExp(this)
207+
val resultType = resultTypeExp(this)
208+
def paramInfos = paramBounds
209+
}
210+
object PolyType {
211+
def apply(paramNames: List[Name], paramBounds: List[TypeBounds], resultType: Type) =
212+
new PolyType(paramNames, _ => paramBounds, _ => resultType)
213+
def unapply(tp: PolyType) = Some((tp.paramNames, tp.paramBounds, tp.resultType))
214+
}
215+
216+
class TypeLambda(val paramNames: List[Name], paramBoundsExp: TypeLambda => List[TypeBounds],
217+
resultTypeExp: TypeLambda => Type) extends LambdaType {
218+
type This = TypeLambda
219+
type ParamInfo = TypeBounds
220+
val paramBounds = paramBoundsExp(this)
221+
val resultType = resultTypeExp(this)
222+
def paramInfos = paramBounds
223+
}
224+
object TypeLambda {
225+
def apply(paramNames: List[Name], paramBounds: List[TypeBounds], resultType: Type) =
226+
new TypeLambda(paramNames, _ => paramBounds, _ => resultType)
227+
def unapply(tp: TypeLambda) = Some((tp.paramNames, tp.paramBounds, tp.resultType))
228+
}
229+
230+
case class TypeBounds(loBound: Type, hiBound: Type)
231+
}
232+
233+
enum Modifier {
234+
case Private, Protected, Abstract, Final, Sealed, Case, Implicit, Erased, Lazy, Override, Inline,
235+
Macro, // inline method containing toplevel splices
236+
Static, // mapped to static Java member
237+
Object, // an object or its class (used for a ValDef or a ClassDef, respectively)
238+
Trait, // a trait (used for a ClassDef)
239+
Local, // used in conjunction with Private/Protected to mean private[this], proctected[this]
240+
Synthetic, // generated by Scala compiler
241+
Artifact, // to be tagged Java Synthetic
242+
Mutable, // when used on a ValDef: a var
243+
Label, // method generated as a label
244+
FieldAccessor, // a getter or setter
245+
CaseAcessor, // getter for case class parameter
246+
Covariant, // type parameter marked “+”
247+
Contravariant, // type parameter marked “-”
248+
Scala2X, // Imported from Scala2.x
249+
DefaultParameterized, // Method with default parameters
250+
Stable // Method that is assumed to be stable
251+
252+
case QualifiedPrivate(boundary: Type)
253+
case QualifiedProtected(boundary: Type)
254+
case Annotation(tree: Term)
255+
}
256+
257+
enum Constant(value: Any) {
258+
case Unit extends Constant(())
259+
case False extends Constant(false)
260+
case True extends Constant(true)
261+
case Null extends Constant(null)
262+
case Byte(value: scala.Byte) extends Constant(value)
263+
case Short(value: scala.Short) extends Constant(value)
264+
case Char(value: scala.Char) extends Constant(value)
265+
case Int(value: scala.Int) extends Constant(value)
266+
case Long(value: scala.Long) extends Constant(value)
267+
case Float(value: scala.Float) extends Constant(value)
268+
case Double(value: scala.Double) extends Constant(value)
269+
case String(value: java.lang.String) extends Constant(value)
270+
case Class(value: Type) extends Constant(value)
271+
case Enum(value: Type) extends Constant(value)
272+
}
273+
274+
sealed class Empty()
275+
object Empty extends Empty
276+
}

0 commit comments

Comments
 (0)