Skip to content

Commit b4bfbcb

Browse files
authored
Merge pull request #4399 from dotty-staging/explore-tasty-extractors
Add sample extractors to tasty/definitions test.
2 parents 09906ea + 3c98564 commit b4bfbcb

File tree

1 file changed

+247
-45
lines changed

1 file changed

+247
-45
lines changed

tests/pos/tasty/definitions.scala

Lines changed: 247 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package tasty
22

33
object definitions {
44

5-
// ------ Names --------------------------------
5+
// ====== Names ======================================
66

77
trait Name
88
trait PossiblySignedName
@@ -23,45 +23,62 @@ object definitions {
2323

2424
case class TypeName(name: TermName) extends Name
2525

26-
// ------ Positions ---------------------------
26+
// ====== Positions ==================================
2727

28-
case class Position(firstOffset: Int, lastOffset: Int)
28+
case class Position(firstOffset: Int, lastOffset: Int, sourceFile: String) {
29+
def startLine: Int = ???
30+
def startColumn: Int = ???
31+
def endLine: Int = ???
32+
def endColumn: Int = ???
33+
}
2934

3035
trait Positioned {
3136
def pos: Position = ???
3237
}
3338

39+
// ====== Trees ======================================
40+
41+
trait Tree extends Positioned
42+
3443
// ------ Statements ---------------------------------
3544

36-
sealed trait TopLevelStatement extends Positioned
45+
sealed trait TopLevelStatement extends Tree
3746
sealed trait Statement extends TopLevelStatement
3847

39-
case class Package(pkg: Term, body: List[TopLevelStatement]) extends TopLevelStatement
48+
case class PackageClause(pkg: Term, body: List[TopLevelStatement]) extends TopLevelStatement
4049

4150
case class Import(expr: Term, selector: List[ImportSelector]) extends Statement
4251

4352
enum ImportSelector {
44-
case Simple(id: Id)
45-
case Rename(id1: Id, id2: Id)
46-
case Omit(id1: Id)
53+
case SimpleSelector(id: Id)
54+
case RenameSelector(id1: Id, id2: Id)
55+
case OmitSelector(id1: Id)
4756
}
4857

4958
case class Id(name: String) extends Positioned // untyped ident
5059

5160
// ------ Definitions ---------------------------------
5261

53-
trait Definition extends Statement {
54-
def name: Name
62+
trait Definition {
5563
def owner: Definition = ???
5664
}
5765

58-
case class ValDef(name: TermName, tpt: Term, rhs: Option[Term], mods: List[Modifier]) extends Definition
66+
// Does DefDef need a `def tpe: MethodType | PolyType`?
67+
case class ValDef(name: TermName, tpt: TypeTree, rhs: Option[Term]) extends Definition {
68+
def mods: List[Modifier] = ???
69+
}
5970
case class DefDef(name: TermName, typeParams: List[TypeDef], paramss: List[List[ValDef]],
60-
returnTpt: Term, rhs: Option[Term], mods: List[Modifier]) extends Definition
61-
case class TypeDef(name: TypeName, rhs: Term, mods: List[Modifier]) extends Definition
62-
case class ClassDef(name: TypeName, constructor: DefDef, parents: List[Term],
63-
self: Option[ValDef], body: List[Statement], mods: List[Modifier]) extends Definition
64-
71+
returnTpt: TypeTree, rhs: Option[Term]) extends Definition {
72+
def mods: List[Modifier] = ???
73+
}
74+
case class TypeDef(name: TypeName, rhs: TypeTree | TypeBoundsTree) extends Definition {
75+
def mods: List[Modifier] = ???
76+
}
77+
case class ClassDef(name: TypeName, constructor: DefDef, parents: List[Term | TypeTree],
78+
self: Option[ValDef], body: List[Statement]) extends Definition {
79+
def mods: List[Modifier] = ???
80+
}
81+
case class PackageDef(name: TermName, members: List[Statement]) extends Definition
6582

6683
// ------ Terms ---------------------------------
6784

@@ -92,35 +109,39 @@ object definitions {
92109
}
93110

94111
/** Trees denoting types */
95-
enum TypeTree extends Positioned {
112+
enum TypeTree extends Tree {
96113
def tpe: Type = ???
97114
case Synthetic()
98115
case Ident(name: TypeName, override val tpe: Type)
99116
case Select(prefix: Term, name: TypeName)
100117
case Singleton(ref: Term)
101118
case Refined(underlying: TypeTree, refinements: List[Definition])
102119
case Applied(tycon: TypeTree, args: List[TypeTree])
103-
case TypeBounds(loBound: TypeTree, hiBound: TypeTree)
104120
case Annotated(tpt: TypeTree, annotation: Term)
105121
case And(left: TypeTree, right: TypeTree)
106122
case Or(left: TypeTree, right: TypeTree)
107123
case ByName(tpt: TypeTree)
108124
}
109125

126+
/** Trees denoting type bounds*/
127+
case class TypeBoundsTree(loBound: TypeTree, hiBound: TypeTree) extends Tree {
128+
def tpe: Type.TypeBounds = ???
129+
}
130+
110131
/** Trees denoting patterns */
111-
enum Pattern extends Positioned {
132+
enum Pattern extends Tree {
112133
def tpe: Type = ???
113134
case Value(v: Term)
114135
case Bind(name: TermName, pat: Pattern)
115136
case Unapply(unapply: Term, implicits: List[Term], pats: List[Pattern])
116137
case Alternative(pats: List[Pattern])
117138
case TypeTest(tpt: TypeTree)
118-
case Wildcard()
119139
}
120140

121-
case class CaseDef(pat: Pattern, guard: Option[Term], rhs: Term) extends Positioned
141+
/** Tree denoting pattern match case */
142+
case class CaseDef(pat: Pattern, guard: Option[Term], rhs: Term) extends Tree
122143

123-
// ------ Types ---------------------------------
144+
// ====== Types ======================================
124145

125146
sealed trait Type
126147

@@ -138,6 +159,7 @@ object definitions {
138159
case class OrType(left: Type, right: Type) extends Type
139160
case class ByNameType(underlying: Type) extends Type
140161
case class ParamRef(binder: LambdaType[_, _, _], idx: Int) extends Type
162+
case class ThisType(tp: Type) extends Type
141163
case class RecursiveThis(binder: RecursiveType) extends Type
142164

143165
case class RecursiveType private (private var _underlying: Type) extends Type {
@@ -198,43 +220,56 @@ object definitions {
198220
object ErasedImplicitMethodType extends SpecializedMethodTypeCompanion
199221

200222
case class TypeBounds(loBound: Type, hiBound: Type)
223+
201224
case class NoPrefix()
202225
object NoPrefix extends NoPrefix
203226
}
204227

205-
// ------ Modifiers ---------------------------------
206-
207-
enum Modifier extends Positioned {
208-
case Private, Protected, Abstract, Final, Sealed, Case, Implicit, Erased, Lazy, Override, Inline,
209-
Macro, // inline method containing toplevel splices
210-
Static, // mapped to static Java member
211-
Object, // an object or its class (used for a ValDef or a ClassDef, respectively)
212-
Trait, // a trait (used for a ClassDef)
213-
Local, // used in conjunction with Private/private[Type] to mean private[this], proctected[this]
214-
Synthetic, // generated by Scala compiler
215-
Artifact, // to be tagged Java Synthetic
216-
Mutable, // when used on a ValDef: a var
217-
Label, // method generated as a label
218-
FieldAccessor, // a getter or setter
219-
CaseAcessor, // getter for case class parameter
220-
Covariant, // type parameter marked “+”
221-
Contravariant, // type parameter marked “-”
222-
Scala2X, // Imported from Scala2.x
223-
DefaultParameterized, // Method with default parameters
224-
Stable // Method that is assumed to be stable
228+
// ====== Modifiers ==================================
229+
225230

231+
enum Modifier {
232+
case Flags(flags: FlagSet)
226233
case QualifiedPrivate(boundary: Type)
227234
case QualifiedProtected(boundary: Type)
228235
case Annotation(tree: Term)
229236
}
230237

231-
// ------ Constants ---------------------------------
238+
trait FlagSet {
239+
def isProtected: Boolean
240+
def isAbstract: Boolean
241+
def isFinal: Boolean
242+
def isSealed: Boolean
243+
def isCase: Boolean
244+
def isImplicit: Boolean
245+
def isErased: Boolean
246+
def isLazy: Boolean
247+
def isOverride: Boolean
248+
def isInline: Boolean
249+
def isMacro: Boolean // inline method containing toplevel splices
250+
def isStatic: Boolean // mapped to static Java member
251+
def isObject: Boolean // an object or its class (used for a ValDef or a ClassDef extends Modifier respectively)
252+
def isTrait: Boolean // a trait (used for a ClassDef)
253+
def isLocal: Boolean // used in conjunction with Private/private[Type] to mean private[this] extends Modifier proctected[this]
254+
def isSynthetic: Boolean // generated by Scala compiler
255+
def isArtifact: Boolean // to be tagged Java Synthetic
256+
def isMutable: Boolean // when used on a ValDef: a var
257+
def isLabel: Boolean // method generated as a label
258+
def isFieldAccessor: Boolean // a getter or setter
259+
def isCaseAcessor: Boolean // getter for class parameter
260+
def isCovariant: Boolean // type parameter marked “+”
261+
def isContravariant: Boolean // type parameter marked “-”
262+
def isScala2X: Boolean // Imported from Scala2.x
263+
def isDefaultParameterized: Boolean // Method with default parameters
264+
def isStable: Boolean // Method that is assumed to be stable
265+
}
266+
267+
// ====== Constants ==================================
232268

233269
enum Constant(val value: Any) {
234270
case Unit extends Constant(())
235-
case False extends Constant(false)
236-
case True extends Constant(true)
237271
case Null extends Constant(null)
272+
case Boolean(v: scala.Boolean) extends Constant(v)
238273
case Byte(v: scala.Byte) extends Constant(v)
239274
case Short(v: scala.Short) extends Constant(v)
240275
case Char(v: scala.Char) extends Constant(v)
@@ -247,3 +282,170 @@ object definitions {
247282
case Enum(v: Type) extends Constant(v)
248283
}
249284
}
285+
286+
// --- A sample extractor ------------------
287+
288+
// The abstract class, that's what we export to macro users
289+
abstract class Tasty {
290+
291+
type Type
292+
trait AbstractType {
293+
// exported type fields
294+
}
295+
implicit def TypeDeco(x: Type): AbstractType
296+
297+
type Symbol
298+
trait AbstractSymbol {
299+
// exported symbol fields
300+
}
301+
implicit def SymbolDeco(s: Symbol): AbstractSymbol
302+
303+
type Context
304+
trait AbstractContext {
305+
val owner: Symbol
306+
// more exported fields
307+
}
308+
implicit def ContextDeco(x: Context): AbstractContext
309+
310+
type Position
311+
trait AbstractPosition {
312+
val start: Int
313+
val end: Int
314+
// more fields
315+
}
316+
implicit def PositionDeco(p: Position): AbstractPosition
317+
318+
trait TypedPositioned {
319+
val pos: Position
320+
val tpe: Type
321+
}
322+
323+
type Pattern
324+
implicit def PatternDeco(p: Pattern): TypedPositioned
325+
326+
type Term
327+
implicit def TermDeco(t: Term): TypedPositioned
328+
329+
type CaseDef
330+
implicit def CaseDefDeco(c: CaseDef): TypedPositioned
331+
332+
val CaseDef: CaseDefExtractor
333+
abstract class CaseDefExtractor {
334+
def apply(pat: Pattern, guard: Term, rhs: Term)(implicit ctx: Context): CaseDef
335+
def unapply(x: CaseDef): Some[(Pattern, Term, Term)]
336+
}
337+
// and analogously for all other concrete trees, patterns, types, etc
338+
}
339+
340+
// The concrete implementation - hidden from users.
341+
object TastyImpl extends Tasty {
342+
import definitions._
343+
import dotty.tools.dotc._
344+
import ast.tpd
345+
import core.{Types, Symbols, Contexts}
346+
import util.{Positions}
347+
348+
type Type = Types.Type
349+
implicit class TypeDeco(x: Type) extends AbstractType {}
350+
351+
type Symbol = Symbols.Symbol
352+
implicit class SymbolDeco(s: Symbol) extends AbstractSymbol {}
353+
354+
type Context = Contexts.Context
355+
implicit class ContextDeco(c: Context) extends AbstractContext {
356+
val owner = c.owner
357+
}
358+
359+
type Position = Positions.Position
360+
implicit class PositionDeco(p: Position) extends AbstractPosition {
361+
val start = p.start
362+
val end = p.end
363+
}
364+
365+
type Pattern = tpd.Tree
366+
implicit class PatternDeco(p: Pattern) extends TypedPositioned {
367+
val pos = p.pos
368+
val tpe = p.tpe
369+
}
370+
371+
type Term = tpd.Tree
372+
implicit class TermDeco(t: Term) extends TypedPositioned {
373+
val pos = t.pos
374+
val tpe = t.tpe
375+
}
376+
377+
type CaseDef = tpd.CaseDef
378+
implicit class CaseDefDeco(c: CaseDef) extends TypedPositioned {
379+
val pos = c.pos
380+
val tpe = c.tpe
381+
}
382+
383+
object CaseDef extends CaseDefExtractor {
384+
def apply(pat: Pattern, guard: Term, rhs: Term)(implicit ctx: Context): CaseDef =
385+
tpd.CaseDef(pat, guard, rhs)
386+
def unapply(x: CaseDef): Some[(Pattern, Term, Term)] =
387+
Some((x.pat, x.guard, x.body))
388+
}
389+
}
390+
391+
/* Dependencies:
392+
393+
the reflect library (which is probably part of stdlib) contains a
394+
395+
val tasty: Tasty
396+
397+
this val is implemented reflectively, loading TastyImpl on demand. TastyImpl in turn
398+
depends on `tools.dotc`.
399+
400+
*/
401+
402+
403+
/* If the dotty implementations all inherit the ...Abstract traits,
404+
and the Abstract traits inherit thmeselves from ProductN, we can
405+
also do the following, faster implementation.
406+
This still does full information hiding, but should be almost
407+
as fast as native access.
408+
409+
object TastyImpl extends TastyAST {
410+
import definitions._
411+
import dotty.tools.dotc._
412+
import ast.tpd
413+
import core.{Types, Symbols, Contexts}
414+
import util.{Positions}
415+
416+
type Type = Types.Type
417+
implicit def TypeDeco(x: Type) = x
418+
419+
type Symbol = Symbols.Symbol
420+
implicit def SymbolDeco(s: Symbol) = s
421+
422+
type Context = Contexts.Context
423+
implicit def ContextDeco(c: Context) = c
424+
425+
type Position = Positions.Position
426+
implicit def PositionDeco(p: Position) = p
427+
428+
type Pattern = tpd.Tree
429+
implicit def PatternDeco(p: Pattern) = p
430+
431+
type Term = tpd.Tree
432+
implicit def TermDeco(t: Term) = t
433+
434+
type CaseDef = tpd.CaseDef
435+
implicit def CaseDefDeco(c: CaseDef) = c
436+
437+
object CaseDef extends CaseDefExtractor {
438+
def apply(pat: Pattern, guard: Term, rhs: Term)(implicit ctx: Context): CaseDef =
439+
tpd.CaseDef(pat, guard, rhs)
440+
def unapply(x: CaseDef): AbstractCaseDef = x
441+
}
442+
}
443+
444+
This approach is fast because all accesses work without boxing. But there are also downsides:
445+
446+
1. The added reflect supertypes for the dotty types might have a negative performance
447+
impact for normal compilation.
448+
449+
2. There would be an added dependency from compiler to reflect library, which
450+
complicates things.
451+
*/

0 commit comments

Comments
 (0)