Skip to content

Commit 3866ad0

Browse files
committed
Add sample extractors to tasty/definitions test.
1 parent e77604d commit 3866ad0

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

@@ -91,35 +108,39 @@ object definitions {
91108
}
92109

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

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

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

122-
// ------ Types ---------------------------------
143+
// ====== Types ======================================
123144

124145
sealed trait Type
125146

@@ -137,6 +158,7 @@ object definitions {
137158
case class OrType(left: Type, right: Type) extends Type
138159
case class ByNameType(underlying: Type) extends Type
139160
case class ParamRef(binder: LambdaType[_, _, _], idx: Int) extends Type
161+
case class ThisType(tp: Type) extends Type
140162
case class RecursiveThis(binder: RecursiveType) extends Type
141163

142164
case class RecursiveType private (private var _underlying: Type) extends Type {
@@ -197,43 +219,56 @@ object definitions {
197219
object ErasedImplicitMethodType extends SpecializedMethodTypeCompanion
198220

199221
case class TypeBounds(loBound: Type, hiBound: Type)
222+
200223
case class NoPrefix()
201224
object NoPrefix extends NoPrefix
202225
}
203226

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

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

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

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

0 commit comments

Comments
 (0)