diff --git a/library/src/scala/quoted/meta/Constant.scala b/library/src/scala/quoted/meta/Constant.scala new file mode 100644 index 000000000000..dbeae23f7fb9 --- /dev/null +++ b/library/src/scala/quoted/meta/Constant.scala @@ -0,0 +1,4 @@ +package scala.quoted.meta + +// TODO (KR) : +sealed trait Constant diff --git a/library/src/scala/quoted/meta/Flags.scala b/library/src/scala/quoted/meta/Flags.scala new file mode 100644 index 000000000000..db55d5c0fb97 --- /dev/null +++ b/library/src/scala/quoted/meta/Flags.scala @@ -0,0 +1,23 @@ +package scala.quoted.meta + +trait Flags private[meta] { + + /** Is the given flag set a subset of this flag sets */ + def is(that: Flags): Boolean + + /** Union of the two flag sets */ + def |(that: Flags): Flags + + /** Intersection of the two flag sets */ + def &(that: Flags): Flags + + /** Shows the flags as a String */ + def show: String + +} +object Flags { + + def api(using meta: Meta): Meta.FlagsAPI = meta.internal.flags + given Meta => Conversion[Flags.type, Meta.FlagsAPI] = _.api + +} diff --git a/library/src/scala/quoted/meta/Meta.scala b/library/src/scala/quoted/meta/Meta.scala new file mode 100644 index 000000000000..e872adc24b3c --- /dev/null +++ b/library/src/scala/quoted/meta/Meta.scala @@ -0,0 +1,1355 @@ +package scala.quoted.meta + +import scala.annotation.experimental + +trait Meta { + val internal: Meta.Internal +} +object Meta { + + trait Internal { + + val position: PositionAPI + + val sourceFile: SourceFileAPI + + val signature: SignatureAPI + + val paramClause: ParamClauseAPI + val termParamClause: TermParamClauseAPI + val typeParamClause: TypeParamClauseAPI + + val flags: FlagsAPI + + val symbol: SymbolAPI + + val tree: TreeAPI + val packageClause: PackageClauseAPI + val statement: StatementAPI + val importOrExport: ImportOrExportAPI + val `import`: ImportAPI + val `export`: ExportAPI + val definition: DefinitionAPI + val classDef: ClassDefAPI + val typeDef: TypeDefAPI + val valOrDefDef: ValOrDefDefAPI + val defDef: DefDefAPI + val valDef: ValDefAPI + val term: TermAPI + val ref: RefAPI + val ident: IdentAPI + val wildcard: WildcardAPI + val select: SelectAPI + val literal: LiteralAPI + val `this`: ThisAPI + val `new`: NewAPI + val namedArg: NamedArgAPI + val apply: ApplyAPI + val typeApply: TypeApplyAPI + val `super`: SuperAPI + val assign: AssignAPI + val block: BlockAPI + val closure: ClosureAPI + val `if`: IfAPI + val `match`: MatchAPI + val summonFrom: SummonFromAPI + val `try`: TryAPI + val `return`: ReturnAPI + val repeated: RepeatedAPI + val inlined: InlinedAPI + val selectOuter: SelectOuterAPI + val `while`: WhileAPI + val typed: TypedAPI + val typedOrTest: TypedOrTestAPI + val bind: BindAPI + val unapply: UnapplyAPI + val alternatives: AlternativesAPI + val caseDef: CaseDefAPI + val typeCaseDef: TypeCaseDefAPI + val typeTree: TypeTreeAPI + val inferred: InferredAPI + val typeIdent: TypeIdentAPI + val typeSelect: TypeSelectAPI + val typeProjection: TypeProjectionAPI + val singleton: SingletonAPI + val refined: RefinedAPI + val applied: AppliedAPI + val annotated: AnnotatedAPI + val matchTypeTree: MatchTypeTreeAPI + val byName: ByNameAPI + val lambdaTypeTree: LambdaTypeTreeAPI + val typeBind: TypeBindAPI + val typeBlock: TypeBlockAPI + val typeBoundsTree: TypeBoundsTreeAPI + val wildcardTypeTree: WildcardTypeTreeAPI + + val typeRepr: TypeReprAPI + val namedType: NamedTypeAPI + val termRef: TermRefAPI + val typeRef: TypeRefAPI + val constantType: ConstantTypeAPI + val superType: SuperTypeAPI + val refinement: RefinementAPI + val appliedType: AppliedTypeAPI + val annotatedType: AnnotatedTypeAPI + val andOrType: AndOrTypeAPI + val andType: AndTypeAPI + val orType: OrTypeAPI + val matchType: MatchTypeAPI + val byNameType: ByNameTypeAPI + val paramRef: ParamRefAPI + val self: SelfAPI + val thisType: ThisTypeAPI + val recursiveThis: RecursiveThisAPI + val recursiveType: RecursiveTypeAPI + val lambdaType: LambdaTypeAPI + val methodOrPoly: MethodOrPolyAPI + val methodType: MethodTypeAPI + val polyType: PolyTypeAPI + val typeLambda: TypeLambdaAPI + val matchCase: MatchCaseAPI + val typeBounds: TypeBoundsAPI + val noPrefix: NoPrefixAPI + val flexibleType: FlexibleTypeAPI + + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Position + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + trait PositionAPI { + def ofMacroExpansion: Position + def apply(sourceFile: SourceFile, start: Int, end: Int): Position + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // SourceFile + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + trait SourceFileAPI { + def current: SourceFile + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Signature + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + trait SignatureAPI {} + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // ParamClause + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + trait ParamClauseAPI {} + + trait TermParamClauseAPI { + def apply(params: List[ValDef]): TermParamClause + } + + trait TypeParamClauseAPI { + def apply(params: List[ValDef]): TermParamClause + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Flags + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + trait FlagsAPI { + + /** Is this symbol `abstract` */ + def Abstract: Flags + + /** + * Is this an abstract override method? + * + * This corresponds to a definition declared as "abstract override def" in the source. + * See https://stackoverflow.com/questions/23645172/why-is-abstract-override-required-not-override-alone-in-subtrait for examples. + */ + def AbsOverride: Flags + + /** + * Is this generated by Scala compiler. + * Corresponds to ACC_SYNTHETIC in the JVM. + */ + def Artifact: Flags + + /** Is this symbol `case` */ + def Case: Flags + + /** Is this symbol a getter for case class parameter */ + def CaseAccessor: Flags + + /** Is this symbol a type parameter marked as contravariant `-` */ + def Contravariant: Flags + + /** Is this symbol a type parameter marked as covariant `+` */ + def Covariant: Flags + + /** Is a declared, but not defined member */ + def Deferred: Flags + + /** The empty set of flags */ + def EmptyFlags: Flags + + /** Is this symbol an enum */ + def Enum: Flags + + /** Is this symbol `erased` */ + def Erased: Flags + + /** Is this symbol exported from provided instance */ + def Exported: Flags + + /** Is this symbol a `def` defined in an `extension` */ + def ExtensionMethod: Flags + + /** Is this symbol a getter or a setter */ + def FieldAccessor: Flags + + /** Is this symbol `final` */ + def Final: Flags + + /** Is this symbol an inferable ("given") parameter */ + def Given: Flags + + /** Is this symbol a parameter with a default value? */ + def HasDefault: Flags + + /** Is this symbol `implicit` */ + def Implicit: Flags + + /** Is an infix method or type */ + def Infix: Flags + + /** Is this symbol `inline` */ + def Inline: Flags + + /** Is this symbol invisible when typechecking? */ + def Invisible: Flags + + /** Is this symbol defined in a Java class */ + def JavaDefined: Flags + + /** Is implemented as a Java static */ + def JavaStatic: Flags + + /** Is this an annotation defined in Java */ + def JavaAnnotation: Flags + + /** Is this symbol `lazy` */ + def Lazy: Flags + + /** Is this symbol local? Used in conjunction with private/private[T] to mean private[this] extends Modifier protected[this] */ + def Local: Flags + + /** Is this symbol marked as a macro. An inline method containing top level splices */ + def Macro: Flags + + /** Is this symbol `def` */ + def Method: Flags + + /** Is this symbol an object or its class (used for a ValDef or a ClassDef extends Modifier respectively) */ + def Module: Flags + + /** Is this symbol a `var` (when used on a ValDef) */ + def Mutable: Flags + + /** Trait does not have fields or initialization code. */ + def NoInits: Flags + + /** Is this symbol `opaque` */ + def Opaque: Flags + + /** Is this symbol `open` */ + def Open: Flags + + /** Is this symbol `override` */ + def Override: Flags + + /** Is this symbol a package */ + def Package: Flags + + /** Is this symbol a parameter */ + def Param: Flags + + /** Is this symbol a parameter accessor */ + def ParamAccessor: Flags + + /** Is this symbol `private` */ + def Private: Flags + + /** Is this symbol labeled private[this] */ + def PrivateLocal: Flags + + /** Is this symbol `protected` */ + def Protected: Flags + + /** Was this symbol imported from Scala2.x */ + def Scala2x: Flags + + /** Is this symbol `sealed` */ + def Sealed: Flags + + /** Is this symbol member that is assumed to be stable and realizable */ + def StableRealizable: Flags + + /** Is this symbol to be tagged Java Synthetic */ + def Synthetic: Flags + + /** Is this symbol a trait */ + def Trait: Flags + + /** Is a transparent inline method or trait */ + def Transparent: Flags + + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Symbol + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + trait SymbolAPI { + + /** + * Symbol of the definition that encloses the current splicing context. + * + * For example, the following call to `spliceOwner` would return the symbol `x`. + * ```scala sc:nocompile + * val x = ${ ... Symbol.spliceOwner ... } + * ``` + * + * For a macro splice, it is the symbol of the definition where the macro expansion happens. + */ + def spliceOwner: Symbol + + /** Get package symbol if package is either defined in current compilation run or present on classpath. */ + def requiredPackage(path: String): Symbol + + /** Get class symbol if class is either defined in current compilation run or present on classpath. */ + def requiredClass(path: String): Symbol + + /** Get module symbol if module is either defined in current compilation run or present on classpath. */ + def requiredModule(path: String): Symbol + + /** Get method symbol if method is either defined in current compilation run or present on classpath. Throws if the method has an overload. */ + def requiredMethod(path: String): Symbol + + /** The class Symbol of a global class definition */ + def classSymbol(fullName: String): Symbol + + /** + * Generates a new class symbol for a class with a public parameterless constructor. + * For more settings, look to the other newClass methods. + * + * Example usage: + * ``` + * val name: String = "myClass" + * val parents = List(TypeTree.of[Object], TypeTree.of[Foo]) + * def decls(cls: Symbol): List[Symbol] = + * List(Symbol.newMethod(cls, "foo", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]))) + * + * val cls = Symbol.newClass(Symbol.spliceOwner, name, parents = parents.map(_.tpe), decls, selfType = None) + * val fooSym = cls.declaredMethod("foo").head + * + * val fooDef = DefDef(fooSym, argss => Some('{println(s"Calling foo")}.asTerm)) + * val clsDef = ClassDef(cls, parents, body = List(fooDef)) + * val newCls = Typed(Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), Nil), TypeTree.of[Foo]) + * + * Block(List(clsDef), newCls).asExprOf[Foo] + * ``` + * constructs the equivalent to + * ``` + * '{ + * class myClass() extends Object with Foo { + * def foo(): Unit = println("Calling foo") + * } + * new myClass(): Foo + * } + * ``` + * + * @param owner The owner of the class + * @param name The name of the class + * @param parents The parent classes of the class. The first parent must not be a trait. + * @param decls The member declarations of the class provided the symbol of this class + * @param selfType The self type of the class if it has one + * + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the ClassDef constructor. + * + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + @experimental def newClass(owner: Symbol, name: String, parents: List[TypeRepr], decls: Symbol => List[Symbol], selfType: Option[TypeRepr]): Symbol + + /** + * Generates a new class symbol for a class with a public single term clause constructor. + * + * Example usage: + * ``` + * val name = "myClass" + * def decls(cls: Symbol): List[Symbol] = + * List(Symbol.newMethod(cls, "foo", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]))) + * val parents = List(TypeTree.of[Object]) + * val cls = Symbol.newClass( + * Symbol.spliceOwner, + * name, + * parents = _ => parents.map(_.tpe), + * decls, + * selfType = None, + * clsFlags = Flags.EmptyFlags, + * Symbol.noSymbol, + * List(("idx", TypeRepr.of[Int]), ("str", TypeRepr.of[String])) + * ) + * + * val fooSym = cls.declaredMethod("foo").head + * val idxSym = cls.fieldMember("idx") + * val strSym = cls.fieldMember("str") + * val fooDef = DefDef(fooSym, argss => + * Some('{println(s"Foo method call with (${${Ref(idxSym).asExpr}}, ${${Ref(strSym).asExpr}})")}.asTerm) + * ) + * val clsDef = ClassDef(cls, parents, body = List(fooDef)) + * val newCls = Apply(Select(New(TypeIdent(cls)), cls.primaryConstructor), List('{0}.asTerm, '{string}.asTerm)) + * + * Block(List(clsDef), Apply(Select(newCls, cls.methodMember("foo")(0)), Nil)).asExprOf[Unit] + * ``` + * construct the equivalent to + * ``` + * '{ + * class myClass(idx: Int, str: String) extends Object { + * def foo() = + * println(s"Foo method call with $idx, $str") + * } + * new myClass(0, "string").foo() + * } + * ``` + * @param owner The owner of the class + * @param name The name of the class + * @param parents Function returning the parent classes of the class. The first parent must not be a trait. + * Takes the constructed class symbol as an argument. Calling `cls.typeRef.asType` as part of this function will lead to cyclic reference errors. + * @param clsFlags extra flags with which the class symbol should be constructed. + * @param clsPrivateWithin the symbol within which this new class symbol should be private. May be noSymbol. + * @param conParams constructor parameter pairs of names and types. + * + * Parameters assigned by the constructor can be obtained via `classSymbol.memberField`. + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the ClassDef constructor. + * + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + @experimental def newClass( + owner: Symbol, + name: String, + parents: Symbol => List[TypeRepr], + decls: Symbol => List[Symbol], + selfType: Option[TypeRepr], + clsFlags: Flags, + clsPrivateWithin: Symbol, + conParams: List[(String, TypeRepr)], + ): Symbol + + /** + * Generates a new class symbol with a constructor of the shape signified by a passed PolyOrMethod parameter. + * + * Example usage: + * ``` + * val name = "myClass" + * def decls(cls: Symbol): List[Symbol] = + * List(Symbol.newMethod(cls, "getParam", MethodType(Nil)(_ => Nil, _ => cls.typeMember("T").typeRef))) + * val conMethodType = + * (classType: TypeRepr) => PolyType(List("T"))(_ => List(TypeBounds.empty), polyType => + * MethodType(List("param"))((_: MethodType) => List(polyType.param(0)), (_: MethodType) => + * AppliedType(classType, List(polyType.param(0))) + * ) + * ) + * val cls = Symbol.newClass( + * Symbol.spliceOwner, + * name, + * parents = _ => List(TypeRepr.of[Object]), + * decls, + * selfType = None, + * clsFlags = Flags.EmptyFlags, + * clsPrivateWithin = Symbol.noSymbol, + * clsAnnotations = Nil, + * conMethodType, + * conFlags = Flags.EmptyFlags, + * conPrivateWithin = Symbol.noSymbol, + * conParamFlags = List(List(Flags.EmptyFlags), List(Flags.EmptyFlags)), + * conParamPrivateWithins = List(List(Symbol.noSymbol), List(Symbol.noSymbol)) + * ) + * + * val getParamSym = cls.declaredMethod("getParam").head + * def getParamRhs(): Option[Term] = + * val paramValue = This(cls).select(cls.fieldMember("param")).asExpr + * Some('{ println("Calling getParam"); $paramValue }.asTerm) + * val getParamDef = DefDef(getParamSym, _ => getParamRhs()) + * + * val clsDef = ClassDef(cls, List(TypeTree.of[Object]), body = List(getParamDef)) + * val newCls = + * Apply( + * Select( + * Apply( + * TypeApply(Select(New(TypeIdent(cls)), cls.primaryConstructor), List(TypeTree.of[String])), + * List(Expr("test").asTerm) + * ), + * cls.methodMember("getParam").head + * ), + * Nil + * ) + * + * Block(List(clsDef), newCls).asExpr + * ``` + * constructs the equivalent to + * ``` + * '{ + * class myClass[T](val param: T) extends Object { + * def getParam: T = + * println("Calling getParam") + * param + * } + * new myClass[String]("test").getParam() + * } + * ``` + * + * @param owner The owner of the class + * @param name The name of the class + * @param parents Function returning the parent classes of the class. The first parent must not be a trait + * Takes the constructed class symbol as an argument. Calling `cls.typeRef.asType` as part of this function will lead to cyclic reference errors. + * @param decls The member declarations of the class provided the symbol of this class + * @param selfType The self type of the class if it has one + * @param clsFlags extra flags with which the class symbol should be constructed. Can be `Private` | `Protected` | `PrivateLocal` | `Local` | `Final` | `Trait` | `Abstract` | `Open` + * @param clsPrivateWithin the symbol within which this new class symbol should be private. May be noSymbol + * @param clsAnnotations annotations of the class + * @param conMethodType Function returning MethodOrPoly type representing the type of the constructor. + * Takes the result type as parameter which must be returned from the innermost MethodOrPoly and have type parameters applied if those are used. + * PolyType may only represent the first clause of the constructor. + * @param conFlags extra flags with which the constructor symbol should be constructed. Can be `Synthetic` | `Method` | `Private` | `Protected` | `PrivateLocal` | `Local` + * @param conPrivateWithin the symbol within which the constructor for this new class symbol should be private. May be noSymbol. + * @param conParamFlags extra flags with which the constructor parameter symbols should be constructed. Must match the shape of `conMethodType`. + * For type parameters those can be `Param` | `Deferred` | `Private` | `PrivateLocal` | `Local`. + * For term parameters those can be `ParamAccessor` | `Private` | `Protected` | `PrivateLocal` | `Local` + * @param conParamPrivateWithins the symbols within which the constructor parameters should be private. Must match the shape of `conMethodType`. Can consist of noSymbol. + * + * Term and type parameters assigned by the constructor can be obtained via `classSymbol.memberField`/`classSymbol.memberType`. + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the ClassDef constructor. + * + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + // Keep doc aligned with QuotesImpl's validFlags: `clsFlags` with `validClassFlags`, `conFlags` with `validClassConstructorFlags`, + // conParamFlags with `validClassTypeParamFlags` and `validClassTermParamFlags` + @experimental def newClass( + owner: Symbol, + name: String, + parents: Symbol => List[TypeRepr], + decls: Symbol => List[Symbol], + selfType: Option[TypeRepr], + clsFlags: Flags, + clsPrivateWithin: Symbol, + clsAnnotations: List[Term], + conMethodType: TypeRepr => MethodOrPoly, + conFlags: Flags, + conPrivateWithin: Symbol, + conParamFlags: List[List[Flags]], + conParamPrivateWithins: List[List[Symbol]], + ): Symbol + + /** + * Generates a new module symbol with an associated module class symbol, + * this is equivalent to an `object` declaration in source code. + * This method returns the module symbol. The module class can be accessed calling `moduleClass` on this symbol. + * + * Example usage: + * ```scala + * //{ + * given Quotes = ??? + * import quotes.reflect.* + * //} + * val moduleName: String = Symbol.freshName("MyModule") + * val parents = List(TypeTree.of[Object]) + * def decls(cls: Symbol): List[Symbol] = + * List(Symbol.newMethod(cls, "run", MethodType(Nil)(_ => Nil, _ => TypeRepr.of[Unit]), Flags.EmptyFlags, Symbol.noSymbol)) + * + * val mod = Symbol.newModule(Symbol.spliceOwner, moduleName, Flags.EmptyFlags, Flags.EmptyFlags, _ => parents.map(_.tpe), decls, Symbol.noSymbol) + * val cls = mod.moduleClass + * val runSym = cls.declaredMethod("run").head + * + * val runDef = DefDef(runSym, _ => Some('{ println("run") }.asTerm)) + * val modDef = ClassDef.module(mod, parents, body = List(runDef)) + * + * val callRun = Apply(Select(Ref(mod), runSym), Nil) + * + * Block(modDef.toList, callRun) + * ``` + * constructs the equivalent to + * ```scala + * //{ + * given Quotes = ??? + * import quotes.reflect.* + * //} + * '{ + * object MyModule$macro$1 extends Object: + * def run(): Unit = println("run") + * MyModule$macro$1.run() + * } + * ``` + * + * @param parent The owner of the class + * @param name The name of the class + * @param modFlags extra flags with which the module symbol should be constructed + * @param clsFlags extra flags with which the module class symbol should be constructed + * @param parents A function that takes the symbol of the module class as input and returns the parent classes of the class. The first parent must not be a trait. + * @param decls A function that takes the symbol of the module class as input and return the symbols of its declared members + * @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol. + * + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to `ClassDef.module`. + * + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + * + * @syntax markdown + */ + @experimental def newModule(owner: Symbol, name: String, modFlags: Flags, clsFlags: Flags, parents: Symbol => List[TypeRepr], decls: Symbol => List[Symbol], privateWithin: Symbol): Symbol + + /** + * Generates a new method symbol with the given parent, name and type. + * + * To define a member method of a class, use the `newMethod` within the `decls` function of `newClass`. + * + * @param parent The owner of the method + * @param name The name of the method + * @param tpe The type of the method (MethodType, PolyType, ByNameType) + * + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the DefDef constructor. + * + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + def newMethod(parent: Symbol, name: String, tpe: TypeRepr): Symbol + + /** + * Works as the other newMethod, but with additional parameters. + * + * To define a member method of a class, use the `newMethod` within the `decls` function of `newClass`. + * + * @param parent The owner of the method + * @param name The name of the method + * @param tpe The type of the method (MethodType, PolyType, ByNameType) + * @param flags extra flags to with which the symbol should be constructed. `Method` flag will be added. Can be `Private | Protected | Override | Deferred | Final | Method | Implicit | Given | Local | JavaStatic | Synthetic | Artifact` + * @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol. + */ + // Keep: `flags` doc aligned with QuotesImpl's `validMethodFlags` + def newMethod(parent: Symbol, name: String, tpe: TypeRepr, flags: Flags, privateWithin: Symbol): Symbol + + /** + * Generates a new val/var/lazy val symbol with the given parent, name and type. + * + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the ValDef constructor. + * + * Note: Also see ValDef.let + * + * @param parent The owner of the val/var/lazy val + * @param name The name of the val/var/lazy val + * @param tpe The type of the val/var/lazy val + * @param flags extra flags to with which the symbol should be constructed. Can be `Private | Protected | Override | Deferred | Final | Param | Implicit | Lazy | Mutable | Local | ParamAccessor | Module | Package | Case | CaseAccessor | Given | Enum | JavaStatic | Synthetic | Artifact` + * @param privateWithin the symbol within which this new method symbol should be private. May be noSymbol. + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + // Keep: `flags` doc aligned with QuotesImpl's `validValFlags` + def newVal(parent: Symbol, name: String, tpe: TypeRepr, flags: Flags, privateWithin: Symbol): Symbol + + /** + * Generates a pattern bind symbol with the given parent, name and type. + * + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the BindDef constructor. + * + * @param parent The owner of the binding + * @param name The name of the binding + * @param flags extra flags to with which the symbol should be constructed. `Case` flag will be added. Can be `Case` + * @param tpe The type of the binding + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + // Keep: `flags` doc aligned with QuotesImpl's `validBindFlags` + def newBind(parent: Symbol, name: String, flags: Flags, tpe: TypeRepr): Symbol + + /** + * Generate a new type symbol for a type alias with the given parent, name and type + * + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the TypeDef constructor. + * + * @param parent The owner of the type + * @param name The name of the type + * @param flags extra flags to with which symbol can be constructed. Can be `Private` | `Protected` | `Override` | `Final` | `Infix` | `Local` + * @param tpe The rhs the type alias + * @param privateWithin the symbol within which this new type symbol should be private. May be noSymbol. + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + @experimental + // Keep: `flags` doc aligned with QuotesImpl's `validTypeAliasFlags` + def newTypeAlias(parent: Symbol, name: String, flags: Flags, tpe: TypeRepr, privateWithin: Symbol): Symbol + + /** + * Generate a new type symbol for a type bounds with the given parent, name and type + * + * This symbol starts without an accompanying definition. + * It is the meta-programmer's responsibility to provide exactly one corresponding definition by passing + * this symbol to the TypeDef constructor. + * + * @param parent The owner of the type + * @param name The name of the type + * @param flags extra flags to with which symbol can be constructed. `Deferred` flag will be added. Can be `Private` | `Protected` | `Override` | `Deferred` | `Final` | `Infix` | `Local` + * @param tpe The bounds of the type + * @param privateWithin the symbol within which this new type symbol should be private. May be noSymbol. + * @note As a macro can only splice code into the point at which it is expanded, all generated symbols must be + * direct or indirect children of the reflection context's owner. + */ + @experimental + // Keep: `flags` doc aligned with QuotesImpl's `validBoundedTypeFlags` + def newBoundedType(parent: Symbol, name: String, flags: Flags, tpe: TypeBounds, privateWithin: Symbol): Symbol + + /** Definition not available */ + def noSymbol: Symbol + + /** + * A fresh name for class or member symbol names. + * + * Fresh names are constructed using the following format `prefix + "$macro$" + freshIndex`. + * The `freshIndex` are unique within the current source file. + * + * Examples: See `scala.annotation.MacroAnnotation` + * + * @param prefix Prefix of the fresh name + */ + @experimental + def freshName(prefix: String): String + + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // Tree + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + trait TreeAPI { + // TODO (KR) : functions + } + + trait PackageClauseAPI { + + /** Create a package clause `package pid { stats }` */ + def apply(pid: Ref, stats: List[Tree]): PackageClause + + /** Copy a package clause `package pid { stats }` */ + def copy(original: Tree)(pid: Ref, stats: List[Tree]): PackageClause + + } + + trait StatementAPI {} + + trait ImportOrExportAPI {} + + trait ImportAPI { + + /** Create an `Import` with the given qualifier and selectors */ + def apply(expr: Term, selectors: List[Selector]): Import + + /** Copy an `Import` with the given qualifier and selectors */ + def copy(original: Tree)(expr: Term, selectors: List[Selector]): Import + + } + + trait ExportAPI {} + + trait DefinitionAPI {} + + trait ClassDefAPI { + + /** + * Create a class definition tree + * + * @param cls The class symbol. A new class symbol can be created using `Symbol.newClass`. + * @param parents The parents trees class. The trees must align with the parent types of `cls`. + * Parents can be `TypeTree`s if they don't have term parameter, + * otherwise the can be `Term` containing the `New` applied to the parameters of the extended class. + * @param body List of members of the class. The members must align with the members of `cls`. + */ + // TODO add selfOpt: Option[ValDef]? + @experimental def apply(cls: Symbol, parents: List[Term | TypeTree], body: List[Statement]): ClassDef + + def copy(original: Tree)(name: String, constr: DefDef, parents: List[Term | TypeTree], selfOpt: Option[ValDef], body: List[Statement]): ClassDef + + /** + * Create the ValDef and ClassDef of a module (equivalent to an `object` declaration in source code). + * + * Equivalent to + * ``` + * def module(module: Symbol, parents: List[Tree], body: List[Statement]): (ValDef, ClassDef) = + * val modCls = module.moduleClass + * val modClassDef = ClassDef(modCls, parents, body) + * val modValDef = ValDef(module, Some(Apply(Select(New(TypeIdent(modCls)), cls.primaryConstructor), Nil))) + * List(modValDef, modClassDef) + * ``` + * + * @param module the module symbol (created using `Symbol.newModule`) + * @param parents parents of the module class + * @param body body of the module class + * @return The module lazy val definition and module class definition. + * These should be added one after the other (in that order) in the body of a class or statements of a block. + * + * @syntax markdown + */ + // TODO add selfOpt: Option[ValDef]? + @experimental def module(module: Symbol, parents: List[Term | TypeTree], body: List[Statement]): (ValDef, ClassDef) + + } + + trait TypeDefAPI { + + def apply(symbol: Symbol): TypeDef + + def copy(original: Tree)(name: String, rhs: Tree): TypeDef + + } + + trait ValOrDefDefAPI {} + + trait DefDefAPI { + + /** + * Create a method definition `def f[..](...)` with the signature defined in the symbol. + * + * The `rhsFn` is a function that receives references to its parameters, and should return + * `Some` containing the implementation of the method, or `None` if the method has no implementation. + * Any definition directly inside the implementation should have `symbol` as owner. + * + * Use `Symbol.asQuotes` to create the rhs using quoted code. + * + * See also: `Tree.changeOwner` + */ + def apply(symbol: Symbol, rhsFn: List[List[Tree]] => Option[Term]): DefDef + + def copy(original: Tree)(name: String, paramss: List[ParamClause], tpt: TypeTree, rhs: Option[Term]): DefDef + + } + + trait ValDefAPI { + + /** + * Create a value definition `val x`, `var x` or `lazy val x` with the signature defined in the symbol. + * + * The `rhs` should return `Some` containing the implementation of the method, + * or `None` if the method has no implementation. + * Any definition directly inside the implementation should have `symbol` as owner. + * + * Use `Symbol.asQuotes` to create the rhs using quoted code. + * + * See also: `Tree.changeOwner` + */ + def apply(symbol: Symbol, rhs: Option[Term]): ValDef + + def copy(original: Tree)(name: String, tpt: TypeTree, rhs: Option[Term]): ValDef + + /** + * Creates a block `{ val = ; }` + * + * Usage: + * ``` + * ValDef.let(owner, "x", rhs1) { x => + * ValDef.let(x.symbol.owner, "y", rhs2) { y => + * // use `x` and `y` + * } + * } + * ``` + */ + def let(owner: Symbol, name: String, rhs: Term)(body: Ref => Term): Term + + /** + * Creates a block `{ val x = ; }` + * + * Usage: + * ``` + * ValDef.let(owner, rhs1) { x => + * ValDef.let(owner, rhs2) { y => + * // use `x` and `y` + * } + * } + * ``` + */ + def let(owner: Symbol, rhs: Term)(body: Ref => Term): Term = + let(owner, "x", rhs)(body) + + /** + * Creates a block `{ val x1 = ; ...; val xn = ; }` + * + * Usage: + * ``` + * ValDef.let(owner, rhsList) { xs => + * ... + * } + * ``` + */ + def let(owner: Symbol, terms: List[Term])(body: List[Ref] => Term): Term + + } + + trait TermAPI { + + /** + * Returns a term that is functionally equivalent to `t`, + * however if `t` is of the form `((y1, ..., yn) => e2)(e1, ..., en)` + * then it optimizes the top most call by returning `Some` + * with the result of beta-reducing the function application. + * Similarly, all outermost curried function applications will be beta-reduced, if possible. + * Otherwise returns `None`. + * + * To retain semantics the argument `ei` is bound as `val yi = ei` and by-name arguments to `def yi = ei`. + * Some bindings may be elided as an early optimization. + * + * Example: + * ```scala sc:nocompile + * ((a: Int, b: Int) => a + b).apply(x, y) + * ``` + * will be reduced to + * ```scala sc:nocompile + * val a = x + * val b = y + * a + b + * ``` + * + * Generally: + * ```scala sc:nocompile + * ([X1, Y1, ...] => (x1, y1, ...) => ... => [Xn, Yn, ...] => (xn, yn, ...) => f[X1, Y1, ..., Xn, Yn, ...](x1, y1, ..., xn, yn, ...))).apply[Tx1, Ty1, ...](myX1, myY1, ...)....apply[Txn, Tyn, ...](myXn, myYn, ...) + * ``` + * will be reduced to + * ```scala sc:nocompile + * type X1 = Tx1 + * type Y1 = Ty1 + * ... + * val x1 = myX1 + * val y1 = myY1 + * ... + * type Xn = Txn + * type Yn = Tyn + * ... + * val xn = myXn + * val yn = myYn + * ... + * f[X1, Y1, ..., Xn, Yn, ...](x1, y1, ..., xn, yn, ...) + * ``` + */ + def betaReduce(term: Term): Option[Term] + + } + + trait RefAPI { + + /** A tree representing the same reference as the given type */ + def term(tp: TermRef): Ref + + /** + * Create a reference tree from a symbol + * + * If `sym` refers to a class member `foo` in class `C`, + * returns a tree representing `C.this.foo`. + * + * If `sym` refers to an object member `foo` in object C, itself in prefix + * `pre` (which might include `.this`, if it contains a class), + * returns `pre.C.foo`. + * + * If `sym` refers to a local definition `foo`, returns + * a tree representing `foo`. + * + * @note In all cases, the constructed tree should only + * be spliced into the places where such accesses make sense. + * For example, it is incorrect to have `C.this.foo` outside + * the class body of `C`, or have `foo` outside the lexical + * scope for the definition of `foo`. + */ + def apply(sym: Symbol): Ref + + } + + trait IdentAPI { + + def apply(tmref: TermRef): Term + + def copy(original: Tree)(name: String): Ident + + } + + trait WildcardAPI { + // TODO (KR) : functions + } + + trait SelectAPI { + + /** Select a term member by symbol */ + def apply(qualifier: Term, symbol: Symbol): Select + + /** + * Select a field or a non-overloaded method by name + * + * @note The method will produce an assertion error if the selected + * method is overloaded. The method `overloaded` should be used + * in that case. + */ + def unique(qualifier: Term, name: String): Select + + /** Call an overloaded method with the given type and term parameters */ + def overloaded(qualifier: Term, name: String, targs: List[TypeRepr], args: List[Term]): Term + + /** Call an overloaded method with the given type and term parameters */ + def overloaded(qualifier: Term, name: String, targs: List[TypeRepr], args: List[Term], returnType: TypeRepr): Term + + def copy(original: Tree)(qualifier: Term, name: String): Select + + } + + trait LiteralAPI { + + /** Create a literal constant */ + def apply(constant: Constant): Literal + + def copy(original: Tree)(constant: Constant): Literal + + } + + trait ThisAPI { + + /** Create a `C.this` for `C` pointing to `cls` */ + def apply(cls: Symbol): This + + def copy(original: Tree)(qual: Option[String]): This + + } + + trait NewAPI { + + /** Create a `new ` */ + def apply(tpt: TypeTree): New + + def copy(original: Tree)(tpt: TypeTree): New + + } + + trait NamedArgAPI { + + /** Create a named argument ` = ` */ + def apply(name: String, arg: Term): NamedArg + + def copy(original: Tree)(name: String, arg: Term): NamedArg + + } + + trait ApplyAPI { + + /** Create a function application `()` */ + def apply(fun: Term, args: List[Term]): Apply + + def copy(original: Tree)(fun: Term, args: List[Term]): Apply + + } + + trait TypeApplyAPI { + + /** Create a function type application `[]` */ + def apply(fun: Term, args: List[TypeTree]): TypeApply + + def copy(original: Tree)(fun: Term, args: List[TypeTree]): TypeApply + + } + + trait SuperAPI { + + /** Creates a `.super[` */ + def apply(qual: Term, mix: Option[String]): Super + + def copy(original: Tree)(qual: Term, mix: Option[String]): Super + + } + + trait AssignAPI { + + + /** Create an assignment ` = ` */ + def apply(lhs: Term, rhs: Term): Assign + + def copy(original: Tree)(lhs: Term, rhs: Term): Assign + + } + + trait BlockAPI { + + /** Creates a block `{ ; }` */ + def apply(stats: List[Statement], expr: Term): Block + + def copy(original: Tree)(stats: List[Statement], expr: Term): Block + + } + + trait ClosureAPI { + // TODO (KR) : functions + } + + trait IfAPI { + // TODO (KR) : functions + } + + trait MatchAPI { + // TODO (KR) : functions + } + + trait SummonFromAPI { + // TODO (KR) : functions + } + + trait TryAPI { + // TODO (KR) : functions + } + + trait ReturnAPI { + // TODO (KR) : functions + } + + trait RepeatedAPI { + // TODO (KR) : functions + } + + trait InlinedAPI { + // TODO (KR) : functions + } + + trait SelectOuterAPI { + // TODO (KR) : functions + } + + trait WhileAPI { + // TODO (KR) : functions + } + + trait TypedAPI { + // TODO (KR) : functions + } + + trait TypedOrTestAPI { + // TODO (KR) : functions + } + + trait BindAPI { + // TODO (KR) : functions + } + + trait UnapplyAPI { + // TODO (KR) : functions + } + + trait AlternativesAPI { + // TODO (KR) : functions + } + + trait CaseDefAPI { + // TODO (KR) : functions + } + + trait TypeCaseDefAPI { + // TODO (KR) : functions + } + + trait TypeTreeAPI { + // TODO (KR) : functions + } + + trait InferredAPI { + // TODO (KR) : functions + } + + trait TypeIdentAPI { + // TODO (KR) : functions + } + + trait TypeSelectAPI { + // TODO (KR) : functions + } + + trait TypeProjectionAPI { + // TODO (KR) : functions + } + + trait SingletonAPI { + // TODO (KR) : functions + } + + trait RefinedAPI { + // TODO (KR) : functions + } + + trait AppliedAPI { + // TODO (KR) : functions + } + + trait AnnotatedAPI { + // TODO (KR) : functions + } + + trait MatchTypeTreeAPI { + // TODO (KR) : functions + } + + trait ByNameAPI { + // TODO (KR) : functions + } + + trait LambdaTypeTreeAPI { + // TODO (KR) : functions + } + + trait TypeBindAPI { + // TODO (KR) : functions + } + + trait TypeBlockAPI { + // TODO (KR) : functions + } + + trait TypeBoundsTreeAPI { + // TODO (KR) : functions + } + + trait WildcardTypeTreeAPI { + // TODO (KR) : functions + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // TypeRepr + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + trait TypeReprAPI { + // TODO (KR) : functions + } + + trait NamedTypeAPI { + // TODO (KR) : functions + } + + trait TermRefAPI { + // TODO (KR) : functions + } + + trait TypeRefAPI { + // TODO (KR) : functions + } + + trait ConstantTypeAPI { + // TODO (KR) : functions + } + + trait SuperTypeAPI { + // TODO (KR) : functions + } + + trait RefinementAPI { + // TODO (KR) : functions + } + + trait AppliedTypeAPI { + // TODO (KR) : functions + } + + trait AnnotatedTypeAPI { + // TODO (KR) : functions + } + + trait AndOrTypeAPI { + // TODO (KR) : functions + } + + trait AndTypeAPI { + // TODO (KR) : functions + } + + trait OrTypeAPI { + // TODO (KR) : functions + } + + trait MatchTypeAPI { + // TODO (KR) : functions + } + + trait ByNameTypeAPI { + // TODO (KR) : functions + } + + trait ParamRefAPI { + // TODO (KR) : functions + } + + trait SelfAPI { + // TODO (KR) : functions + } + + trait ThisTypeAPI { + // TODO (KR) : functions + } + + trait RecursiveThisAPI { + // TODO (KR) : functions + } + + trait RecursiveTypeAPI { + // TODO (KR) : functions + } + + trait LambdaTypeAPI { + // TODO (KR) : functions + } + + trait MethodOrPolyAPI { + // TODO (KR) : functions + } + + trait MethodTypeAPI { + // TODO (KR) : functions + } + + trait PolyTypeAPI { + // TODO (KR) : functions + } + + trait TypeLambdaAPI { + // TODO (KR) : functions + } + + trait MatchCaseAPI { + // TODO (KR) : functions + } + + trait TypeBoundsAPI { + // TODO (KR) : functions + } + + trait NoPrefixAPI { + // TODO (KR) : functions + } + + trait FlexibleTypeAPI { + // TODO (KR) : functions + } + +} diff --git a/library/src/scala/quoted/meta/MethodTypeKind.scala b/library/src/scala/quoted/meta/MethodTypeKind.scala new file mode 100644 index 000000000000..4cb94e8e8835 --- /dev/null +++ b/library/src/scala/quoted/meta/MethodTypeKind.scala @@ -0,0 +1,15 @@ +package scala.quoted.meta + +/** Type which decides on the kind of parameter list represented by `MethodType`. */ +enum MethodTypeKind { + + /** Represents a parameter list without any implicitness of parameters, like (x1: X1, x2: X2, ...) */ + case Plain + + /** Represents a parameter list with implicit parameters, like `(implicit X1, ..., Xn)`, `(using X1, ..., Xn)`, `(using x1: X1, ..., xn: Xn)` */ + case Implicit + + /** Represents a parameter list of a contextual method, like `(using X1, ..., Xn)` or `(using x1: X1, ..., xn: Xn)` */ + case Contextual + +} diff --git a/library/src/scala/quoted/meta/ParamClause.scala b/library/src/scala/quoted/meta/ParamClause.scala new file mode 100644 index 000000000000..df8975c446ee --- /dev/null +++ b/library/src/scala/quoted/meta/ParamClause.scala @@ -0,0 +1,60 @@ +package scala.quoted.meta + +import scala.annotation.experimental + +sealed trait ParamClause { + + /** List of parameters of the clause */ + def params: List[ValDef] | List[TypeDef] + +} +object ParamClause { + + def api(using meta: Meta): Meta.ParamClauseAPI = meta.internal.paramClause + given Meta => Conversion[ParamClause.type, Meta.ParamClauseAPI] = _.api + +} + +trait TermParamClause private[meta] extends ParamClause { + + /** List of parameters of the clause */ + def params: List[ValDef] + + /** Is this an implicit parameter clause `(implicit x1: X1, ..., xn: Xn)` */ + def isImplicit: Boolean + + /** Is this a given parameter clause `(using X1, ..., Xn)` or `(using x1: X1, ..., xn: Xn)` */ + def isGiven: Boolean + + /** List of `erased` flags for each parameter of the clause */ + @experimental + def erasedArgs: List[Boolean] + + /** Whether the clause has any erased parameters */ + @experimental + def hasErasedArgs: Boolean + +} +object TermParamClause { + + def api(using meta: Meta): Meta.TermParamClauseAPI = meta.internal.termParamClause + given Meta => Conversion[TermParamClause.type, Meta.TermParamClauseAPI] = _.api + + def unapply(x: TermParamClause): Some[List[ValDef]] = Some(x.params) + +} + +trait TypeParamClause private[meta] extends ParamClause { + + /** List of parameters of the clause */ + def params: List[TypeDef] + +} +object TypeParamClause { + + def api(using meta: Meta): Meta.TypeParamClauseAPI = meta.internal.typeParamClause + given Meta => Conversion[TypeParamClause.type, Meta.TypeParamClauseAPI] = _.api + + def unapply(x: TypeParamClause): Some[List[TypeDef]] = Some(x.params) + +} diff --git a/library/src/scala/quoted/meta/Position.scala b/library/src/scala/quoted/meta/Position.scala new file mode 100644 index 000000000000..12077dacb6fb --- /dev/null +++ b/library/src/scala/quoted/meta/Position.scala @@ -0,0 +1,32 @@ +package scala.quoted.meta + +trait Position private[meta] { + + /** The start offset of the position in the source code */ + def start: Int + + /** The end offset of the position in the source code */ + def end: Int + + /** The source file name */ + def sourceFile: SourceFile + + /** The line number of the start of the position */ + def startLine: Int + + /** The line number of the end of the position */ + def endLine: Int + + /** The column number of the start of the position */ + def startColumn: Int + + /** The column number of the end of the position */ + def endColumn: Int + +} +object Position { + + def api(using meta: Meta): Meta.PositionAPI = meta.internal.position + given Meta => Conversion[Position.type, Meta.PositionAPI] = _.api + +} diff --git a/library/src/scala/quoted/meta/Printer.scala b/library/src/scala/quoted/meta/Printer.scala new file mode 100644 index 000000000000..5e7d4160934d --- /dev/null +++ b/library/src/scala/quoted/meta/Printer.scala @@ -0,0 +1,4 @@ +package scala.quoted.meta + +// TODO (KR) : +trait Printer[T] diff --git a/library/src/scala/quoted/meta/Selector.scala b/library/src/scala/quoted/meta/Selector.scala new file mode 100644 index 000000000000..0c56e2b4b720 --- /dev/null +++ b/library/src/scala/quoted/meta/Selector.scala @@ -0,0 +1,4 @@ +package scala.quoted.meta + +// TODO (KR) : +sealed trait Selector diff --git a/library/src/scala/quoted/meta/Signature.scala b/library/src/scala/quoted/meta/Signature.scala new file mode 100644 index 000000000000..addabe12c4b6 --- /dev/null +++ b/library/src/scala/quoted/meta/Signature.scala @@ -0,0 +1,27 @@ +package scala.quoted.meta + +trait Signature private[meta] { + + /** + * The signatures of the method parameters. + * + * Each *type parameter section* is represented by a single Int corresponding + * to the number of type parameters in the section. + * Each *term parameter* is represented by a String corresponding to the fully qualified + * name of the parameter type. + */ + def paramSigs: List[String | Int] + + /** The signature of the result type */ + def resultSig: String + +} +object Signature { + + def api(using meta: Meta): Meta.SignatureAPI = meta.internal.signature + given Meta => Conversion[Signature.type, Meta.SignatureAPI] = _.api + + /** Matches the method signature and returns its parameters and result type. */ + def unapply(sig: Signature): (List[String | Int], String) = (sig.paramSigs, sig.resultSig) + +} diff --git a/library/src/scala/quoted/meta/SourceFile.scala b/library/src/scala/quoted/meta/SourceFile.scala new file mode 100644 index 000000000000..9a906ad3c851 --- /dev/null +++ b/library/src/scala/quoted/meta/SourceFile.scala @@ -0,0 +1,28 @@ +package scala.quoted.meta + +trait SourceFile private[meta] { + + /** Path to this source file. May be `None` for virtual files such as in the REPL. */ + def getJPath: Option[java.nio.file.Path] + + /** Name of the source file */ + def name: String + + /** + * Path of the source file. + * + * It does not necessarily point to a path in the filesystem, it could be the path of a virtual file. + * Use `getJPath` to get paths to the filesystem. + */ + def path: String + + /** Content of this source file */ + def content: Option[String] + +} +object SourceFile { + + def api(using meta: Meta): Meta.SourceFileAPI = meta.internal.sourceFile + given Meta => Conversion[SourceFile.type, Meta.SourceFileAPI] = _.api + +} diff --git a/library/src/scala/quoted/meta/Symbol.scala b/library/src/scala/quoted/meta/Symbol.scala new file mode 100644 index 000000000000..92e94c90d063 --- /dev/null +++ b/library/src/scala/quoted/meta/Symbol.scala @@ -0,0 +1,287 @@ +package scala.quoted.meta + +import scala.annotation.experimental + +trait Symbol private[meta] { + + /** Owner of this symbol. The owner is the symbol in which this symbol is defined. Throws if this symbol does not have an owner. */ + def owner: Symbol + + /** Owner of this symbol. The owner is the symbol in which this symbol is defined. Returns `NoSymbol` if this symbol does not have an owner. */ + def maybeOwner: Symbol + + /** Flags of this symbol */ + def flags: Flags + + /** This symbol is private within the resulting type */ + def privateWithin: Option[TypeRepr] + + /** This symbol is protected within the resulting type */ + def protectedWithin: Option[TypeRepr] + + /** The name of this symbol */ + def name: String + + /** The full name of this symbol up to the root package */ + def fullName: String + + /** Type of the definition */ + @experimental + def info: TypeRepr + + /** The position of this symbol */ + def pos: Option[Position] + + /** The documentation for this symbol, if any */ + def docstring: Option[String] + + /** + * Tree of this definition + * + * If this symbol `isClassDef` it will return `a `ClassDef`, + * if this symbol `isTypeDef` it will return `a `TypeDef`, + * if this symbol `isValDef` it will return `a `ValDef`, + * if this symbol `isDefDef` it will return `a `DefDef` + * if this symbol `isBind` it will return `a `Bind`, + * else will throw + * + * **Warning**: avoid using this method in macros. + * + * **Caveat**: The tree is not guaranteed to exist unless the compiler + * option `-Yretain-trees` is enabled. + * + * **Anti-pattern**: The following code is an anti-pattern: + * + * symbol.tree.tpe + * + * It should be replaced by one of the following: + * + * tp.memberType(symbol) + * symbol.typeRef + * symbol.termRef + */ + def tree: Tree + + /** Is the annotation defined with `annotSym` attached to this symbol? */ + def hasAnnotation(annotSym: Symbol): Boolean + + /** Get the annotation defined with `annotSym` attached to this symbol */ + def getAnnotation(annotSym: Symbol): Option[Term] + + /** Annotations attached to this symbol */ + def annotations: List[Term] + + /** Does this symbol come from a currently compiled source file? */ + def isDefinedInCurrentRun: Boolean + + /** + * Dummy val symbol that owns all statements within the initialization of the class. + * This may also contain local definitions such as classes defined in a `locally` block in the class. + */ + def isLocalDummy: Boolean + + /** Is this symbol a class representing a refinement? */ + def isRefinementClass: Boolean + + /** Is this symbol an alias type? */ + def isAliasType: Boolean + + /** Is this symbol an anonymous class? */ + def isAnonymousClass: Boolean + + /** Is this symbol an anonymous function? */ + def isAnonymousFunction: Boolean + + /** Is this symbol an abstract type or a type parameter? */ + def isAbstractType: Boolean + + /** Is this the constructor of a class? */ + def isClassConstructor: Boolean + + /** Is this the super accessor? */ + def isSuperAccessor: Boolean + + /** Is this the definition of a type? */ + def isType: Boolean + + /** Is this the definition of a term? */ + def isTerm: Boolean + + /** Is this the definition of a PackageDef tree? */ + def isPackageDef: Boolean + + /** Is this the definition of a ClassDef tree? */ + def isClassDef: Boolean + + /** Is this the definition of a TypeDef tree */ + def isTypeDef: Boolean + + /** Is this the definition of a ValDef tree? */ + def isValDef: Boolean + + /** Is this the definition of a DefDef tree? */ + def isDefDef: Boolean + + /** Is this the definition of a Bind pattern? */ + def isBind: Boolean + + /** Does this symbol represent a no definition? */ + def isNoSymbol: Boolean + + /** Does this symbol represent a definition? */ + def exists: Boolean + + /** Field with the given name directly declared in the class */ + def declaredField(name: String): Symbol + + /** Fields directly declared in the class */ + def declaredFields: List[Symbol] + + /** Get named non-private fields declared or inherited */ + def fieldMember(name: String): Symbol + + /** Get all non-private fields declared or inherited */ + def fieldMembers: List[Symbol] + + /** Get non-private named methods defined directly inside the class */ + def declaredMethod(name: String): List[Symbol] + + /** Get all non-private methods defined directly inside the class, excluding constructors */ + def declaredMethods: List[Symbol] + + /** Get named non-private methods declared or inherited */ + def methodMember(name: String): List[Symbol] + + /** Get all non-private methods declared or inherited */ + def methodMembers: List[Symbol] + + /** Get non-private named type defined directly inside the class */ + def declaredType(name: String): List[Symbol] + + /** Get all non-private types defined directly inside the class */ + def declaredTypes: List[Symbol] + + /** Type member with the given name declared or inherited in the class */ + def typeMember(name: String): Symbol + + /** Type member directly declared or inherited in the class */ + def typeMembers: List[Symbol] + + /** All members directly declared in the class */ + def declarations: List[Symbol] + + /** + * The symbols of each type parameter list and value parameter list of this + * method, or Nil if this isn't a method. + */ + def paramSymss: List[List[Symbol]] + + /** Returns all symbols overridden by this symbol. */ + def allOverriddenSymbols: Iterator[Symbol] + + /** + * The symbol overriding this symbol in given subclass `ofclazz`. + * + * @param ofclazz is a subclass of this symbol's owner + */ + def overridingSymbol(ofclazz: Symbol): Symbol + + /** The primary constructor of a class or trait, `noSymbol` if not applicable. */ + def primaryConstructor: Symbol + + /** Fields of a case class type -- only the ones declared in primary constructor */ + def caseFields: List[Symbol] + + /** Is this the symbol of a type parameter */ + def isTypeParam: Boolean + + /** + * Variance flags for of this type parameter. + * + * Variance flags can be one of `Flags.{Covariant, Contravariant, EmptyFlags}`. + * If this is not the symbol of a type parameter the result is `Flags.EmptyFlags`. + */ + def paramVariance: Flags + + /** Signature of this definition */ + def signature: Signature + + /** The class symbol of the companion module class */ + def moduleClass: Symbol + + /** The symbol of the companion class */ + def companionClass: Symbol + + /** The symbol of the companion module */ + def companionModule: Symbol + + /** Case class or case object children of a sealed trait or cases of an `enum`. */ + def children: List[Symbol] + + /** + * Returns a nested quote with this symbol as splice owner (`Symbol.spliceOwner`). + * + * Changes the owner under which the definition in a quote are created. + * + * Usages: + * ```scala + * def rhsExpr(using q: Quotes): Expr[Unit] = + * import q.reflect.* + * '{ val y = ???; (y, y) } + * def aValDef(using q: Quotes)(owner: q.reflect.Symbol) = + * import q.reflect.* + * val sym = Symbol.newVal(owner, "x", TypeRepr.of[Unit], Flags.EmptyFlags, Symbol.noSymbol) + * val rhs = rhsExpr(using sym.asQuotes).asTerm + * ValDef(sym, Some(rhs)) + * ``` + * + * ```scala + * //{ + * def inQuotes(using q: Quotes) = { + * import q.reflect.* + * //} + * new TreeMap: + * override def transformTerm(tree: Term)(owner: Symbol): Term = + * tree match + * case tree: Ident => + * given Quotes = owner.asQuotes + * // Definitions contained in the quote will be owned by `owner`. + * // No need to use `changeOwner` in this case. + * '{ val x = ???; x }.asTerm + * //{ + * } + * //} + * ``` + */ + def nested: Meta + + /** + * @see [[nested]] + */ + def usingNested[A](f: Meta ?=> A): A = + f(using nested) + + /** + * Type reference to the symbol usable in the scope of its owner. + * + * To get a reference to a symbol from a specific prefix `tp`, use `tp.select(symbol)` instead. + * @see TypeReprMethods.select + * + * @pre symbol.isType returns true + */ + def typeRef: TypeRef + + /** + * Term reference to the symbol usable in the scope of its owner. + * + * @pre symbol.isType returns false + */ + def termRef: TermRef + +} +object Symbol { + + def api(using meta: Meta): Meta.SymbolAPI = meta.internal.symbol + given Meta => Conversion[Symbol.type, Meta.SymbolAPI] = _.api + +} diff --git a/library/src/scala/quoted/meta/Tree.scala b/library/src/scala/quoted/meta/Tree.scala new file mode 100644 index 000000000000..593e7ef46543 --- /dev/null +++ b/library/src/scala/quoted/meta/Tree.scala @@ -0,0 +1,1052 @@ +package scala.quoted.meta + +import scala.annotation.targetName +import scala.quoted.{Expr, Type} + +sealed trait Tree { + type Self <: Tree + + /** Position in the source code */ + def pos: Position + + /** Symbol of defined or referred by this tree */ + def symbol: Symbol + + /** Shows the tree as String */ + def show(using Printer[Tree]): String + + /** Does this tree represent a valid expression? */ + def isExpr: Boolean + + /** Convert this tree to an `quoted.Expr[Any]` if the tree is a valid expression or throws */ + def asExpr: Expr[Any] + + def asExprOf[T](using Type[T]): Expr[T] + + def changeOwner(newOwner: Symbol): Self + +} +object Tree { + + def api(using meta: Meta): Meta.TreeAPI = meta.internal.tree + given Meta => Conversion[Tree.type, Meta.TreeAPI] = _.api + +} + +trait PackageClause private[meta] extends Tree { + override type Self <: PackageClause + + /** Tree containing the package name */ + def pid: Ref + + /** Definitions, imports or exports within the package */ + def stats: List[Tree] + +} +object PackageClause { + + def api(using meta: Meta): Meta.PackageClauseAPI = meta.internal.packageClause + given Meta => Conversion[PackageClause.type, Meta.PackageClauseAPI] = _.api + + /** Matches a package clause `package pid { stats }` and extracts the `pid` and `stats` */ + def unapply(tree: PackageClause): (Ref, List[Tree]) = (tree.pid, tree.stats) + +} + +sealed trait Statement extends Tree { + override type Self <: Statement +} +object Statement { + + def api(using meta: Meta): Meta.StatementAPI = meta.internal.statement + given Meta => Conversion[Statement.type, Meta.StatementAPI] = _.api + +} + +sealed trait ImportOrExport extends Statement { + override type Self <: ImportOrExport + + /** Qualifier of the import/export */ + def expr: Term + + /** + * List selectors of the import/export + * + * See documentation on `Selector` + */ + def selectors: List[Selector] + +} +object ImportOrExport { + + def api(using meta: Meta): Meta.ImportOrExportAPI = meta.internal.importOrExport + given Meta => Conversion[ImportOrExport.type, Meta.ImportOrExportAPI] = _.api + +} + +trait Import private[meta] extends ImportOrExport { + override type Self <: Import +} +object Import { + + def api(using meta: Meta): Meta.ImportAPI = meta.internal.`import` + given Meta => Conversion[Import.type, Meta.ImportAPI] = _.api + + /** Matches an `Import` and extracts the qualifier and selectors */ + def unapply(tree: Import): (Term, List[Selector]) = (tree.expr, tree.selectors) + +} + +trait Export private[meta] extends ImportOrExport { + override type Self <: Export +} +object Export { + + def api(using meta: Meta): Meta.ExportAPI = meta.internal.`export` + given Meta => Conversion[Export.type, Meta.ExportAPI] = _.api + + /** Matches an `Export` and extracts the qualifier and selectors */ + def unapply(tree: Export): (Term, List[Selector]) = (tree.expr, tree.selectors) + +} + +sealed trait Definition extends Statement { + override type Self <: Definition + + /** Name of the definition */ + def name: String + +} +object Definition { + + def api(using meta: Meta): Meta.DefinitionAPI = meta.internal.definition + given Meta => Conversion[Definition.type, Meta.DefinitionAPI] = _.api + +} + +trait ClassDef private[meta] extends Definition { + override type Self <: ClassDef + + /** The primary constructor of this class */ + def constructor: DefDef + + /** + * List of extended parent classes or traits. + * The first parent is always a class. + */ + def parents: List[Term | TypeTree] + + /** + * Self-type of the class + * + * ```scala + * //{ + * type T + * //} + * class C { self: T => + * ??? + * } + * ``` + */ + def self: Option[ValDef] + + /** + * Statements within the class + * + * ```scala + * class C { + * ??? // statements + * } + * ``` + */ + def body: List[Statement] + +} +object ClassDef { + + def api(using meta: Meta): Meta.ClassDefAPI = meta.internal.classDef + given Meta => Conversion[ClassDef.type, Meta.ClassDefAPI] = _.api + + def unapply(cdef: ClassDef): (String, DefDef, List[Term | TypeTree], Option[ValDef], List[Statement]) = (cdef.name, cdef.constructor, cdef.parents, cdef.self, cdef.body) + +} + +trait TypeDef private[meta] extends Definition { + override type Self <: TypeDef + + /** The type bounds on the right-hand side of this `type` definition */ + def rhs: Tree + +} +object TypeDef { + + def api(using meta: Meta): Meta.TypeDefAPI = meta.internal.typeDef + given Meta => Conversion[TypeDef.type, Meta.TypeDefAPI] = _.api + + def unapply(tdef: TypeDef): (String, Tree) = (tdef.name, tdef.rhs) + +} + +sealed trait ValOrDefDef extends Definition { + override type Self <: ValOrDefDef + + /** The type tree of this `val` or `def` definition */ + def tpt: TypeTree + + /** The right-hand side of this `val` or `def` definition */ + def rhs: Option[Term] + +} +object ValOrDefDef { + + def api(using meta: Meta): Meta.ValOrDefDefAPI = meta.internal.valOrDefDef + given Meta => Conversion[ValOrDefDef.type, Meta.ValOrDefDefAPI] = _.api + +} + +trait DefDef private[meta] extends ValOrDefDef { + override type Self <: DefDef + + /** List of type and term parameter clauses */ + def paramss: List[ParamClause] + + /** + * List of leading type parameters or Nil if the method does not have leading type parameters. + * + * Note: Non leading type parameters can be found in extension methods such as + * ```scala + * //{ + * type A + * type T + * //} + * extension (a: A) def f[T]() = ??? + * ``` + */ + def leadingTypeParams: List[TypeDef] + + /** + * List of parameter clauses following the leading type parameters or all clauses. + * Return all parameter clauses if there are no leading type parameters. + * + * Non leading type parameters can be found in extension methods such as + * ```scala + * //{ + * type T + * type A + * //} + * extension (a: A) def f[T]() = ??? + * ``` + */ + def trailingParamss: List[ParamClause] + + /** List of term parameter clauses */ + def termParamss: List[TermParamClause] + + /** The tree of the return type of this `def` definition */ + def returnTpt: TypeTree + +} +object DefDef { + + def api(using meta: Meta): Meta.DefDefAPI = meta.internal.defDef + given Meta => Conversion[DefDef.type, Meta.DefDefAPI] = _.api + + def unapply(ddef: DefDef): (String, List[ParamClause], TypeTree, Option[Term]) = (ddef.name, ddef.paramss, ddef.returnTpt, ddef.rhs) + +} + +trait ValDef private[meta] extends ValOrDefDef { + override type Self <: ValDef +} +object ValDef { + + def api(using meta: Meta): Meta.ValDefAPI = meta.internal.valDef + given Meta => Conversion[ValDef.type, Meta.ValDefAPI] = _.api + + def unapply(vdef: ValDef): (String, TypeTree, Option[Term]) = (vdef.name, vdef.tpt, vdef.rhs) + +} + +sealed trait Term extends Statement { + override type Self <: Term + + /** TypeRepr of this term */ + def tpe: TypeRepr + + /** + * Replace Inlined nodes and InlineProxy references to underlying arguments. + * The resulting tree is useful for inspection of the value or content of a non-inline argument. + * + * Warning: This tree may contain references that are out of scope and should not be used in the generated code. + * This method should only used to port Scala 2 that used to access their outer scope unsoundly. + */ + def underlyingArgument: Term + + /** + * Replace Ident nodes references to the underlying tree that defined them. + * The resulting tree is useful for inspection of the definition of some bindings. + * + * Warning: This tree may contain references that are out of scope and should not be used in the generated code. + * This method should only used to port Scala 2 that used to access their outer scope unsoundly. + */ + def underlying: Term + + /** Converts a partially applied term into a lambda expression */ + def etaExpand(owner: Symbol): Term + + /** A unary apply node with given argument: `tree(arg)` */ + def appliedTo(arg: Term): Term + + /** An apply node with given arguments: `tree(arg, args0, ..., argsN)` */ + def appliedTo(arg: Term, args: Term*): Term + + /** An apply node with given argument list `tree(args(0), ..., args(args.length - 1))` */ + def appliedToArgs(args: List[Term]): Apply + + /** + * The current tree applied to given argument lists: + * `tree (argss(0)) ... (argss(argss.length -1))` + */ + def appliedToArgss(argss: List[List[Term]]): Term + + /** The current tree applied to (): `tree()` */ + def appliedToNone: Apply + + /** The current tree applied to given type argument: `tree[targ]` */ + def appliedToType(targ: TypeRepr): Term + + /** The current tree applied to given type arguments: `tree[targ0, ..., targN]` */ + def appliedToTypes(targs: List[TypeRepr]): Term + + /** The current tree applied to given type argument list: `tree[targs(0), ..., targs(targs.length - 1)]` */ + def appliedToTypeTrees(targs: List[TypeTree]): Term + + /** A select node that selects the given symbol. */ + def select(sym: Symbol): Select + +} +object Term { + + def api(using meta: Meta): Meta.TermAPI = meta.internal.term + given Meta => Conversion[Term.type, Meta.TermAPI] = _.api + +} + +sealed trait Ref extends Term { + override type Self <: Ref +} +object Ref { + + def api(using meta: Meta): Meta.RefAPI = meta.internal.ref + given Meta => Conversion[Ref.type, Meta.RefAPI] = _.api + +} + +trait Ident private[meta] extends Ref { + override type Self <: Ident + + /** Name of this `Ident` */ + def name: String + +} +object Ident { + + def api(using meta: Meta): Meta.IdentAPI = meta.internal.ident + given Meta => Conversion[Ident.type, Meta.IdentAPI] = _.api + + /** Matches a term identifier and returns its name */ + def unapply(tree: Ident): Some[String] = Some(tree.name) + +} + +// TODO (KR) : should this be an opaque type? trait? just a `.isWildcard`? +opaque type Wildcard <: Ident = Ident +object Wildcard { + + def api(using meta: Meta): Meta.WildcardAPI = meta.internal.wildcard + given Meta => Conversion[Wildcard.type, Meta.WildcardAPI] = _.api + + @targetName("unapplyIdent") + def unapply(x: Ident): Boolean = ??? // TODO (KR) : + + @targetName("unapplyWildcard") + def unapply(x: Wildcard): true = true + +} + +trait Select private[meta] extends Ref { + override type Self <: Select + + /** Qualifier of the `qualifier.name` */ + def qualifier: Term + + /** Name of this `Select` */ + def name: String + + /** Signature of this method */ + def signature: Option[Signature] + +} +object Select { + + def api(using meta: Meta): Meta.SelectAPI = meta.internal.select + given Meta => Conversion[Select.type, Meta.SelectAPI] = _.api + + /** Matches `.` */ + def unapply(x: Select): (Term, String) = (x.qualifier, x.name) + +} + +trait Literal private[meta] extends Term { + override type Self <: Literal + + /** Value of this literal */ + def constant: Constant + +} +object Literal { + + def api(using meta: Meta): Meta.LiteralAPI = meta.internal.literal + given Meta => Conversion[Literal.type, Meta.LiteralAPI] = _.api + + /** Matches a literal constant */ + def unapply(x: Literal): Some[Constant] = Some(x.constant) + +} + +trait This private[meta] extends Term { + override type Self <: This + + /** + * Returns `C` if the underlying tree is of the form `C.this` + * + * Otherwise, return `None`. + */ + def id: Option[String] + +} +object This { + + def api(using meta: Meta): Meta.ThisAPI = meta.internal.`this` + given Meta => Conversion[This.type, Meta.ThisAPI] = _.api + + /** Matches `this` or `qual.this` and returns the name of `qual` */ + def unapply(x: This): Some[Option[String]] = Some(x.id) + +} + +trait New private[meta] extends Term { + override type Self <: New + + /** Returns the type tree of this `new` */ + def tpt: TypeTree + +} +object New { + + def api(using meta: Meta): Meta.NewAPI = meta.internal.`new` + given Meta => Conversion[New.type, Meta.NewAPI] = _.api + + /** Matches `new ` */ + def unapply(x: New): Some[TypeTree] = Some(x.tpt) + +} + +trait NamedArg private[meta] extends Term { + override type Self <: NamedArg + + /** The name part of `name = arg` */ + def name: String + + /** The argument part of `name = arg` */ + def value: Term + +} +object NamedArg { + + def api(using meta: Meta): Meta.NamedArgAPI = meta.internal.namedArg + given Meta => Conversion[NamedArg.type, Meta.NamedArgAPI] = _.api + + /** Matches a named argument ` = ` */ + def unapply(x: NamedArg): (String, Term) = (x.name, x.value) + +} + +trait Apply private[meta] extends Term { + override type Self <: Apply + + /** + * The `fun` part of an (implicit) application like `fun(args)` + * + * It may be a partially applied method: + * ```scala + * def f(x1: Int)(x2: Int) = ??? + * f(1)(2) + * ``` + * - `fun` is `f(1)` in the `Apply` of `f(1)(2)` + * - `fun` is `f` in the `Apply` of `f(1)` + */ + def fun: Term + + /** + * The arguments (implicitly) passed to the method + * + * The `Apply` may be a partially applied method: + * ```scala + * def f(x1: Int)(x2: Int) = ??? + * f(1)(2) + * ``` + * - `args` is `(2)` in the `Apply` of `f(1)(2)` + * - `args` is `(1)` in the `Apply` of `f(1)` + */ + def args: List[Term] + +} +object Apply { + + def api(using meta: Meta): Meta.ApplyAPI = meta.internal.apply + given Meta => Conversion[Apply.type, Meta.ApplyAPI] = _.api + + /** Matches a function application `()` */ + def unapply(x: Apply): (Term, List[Term]) = (x.fun, x.args) + +} + +trait TypeApply private[meta] extends Term { + override type Self <: TypeApply + + /** + * The `fun` part of an (inferred) type application like `fun[Args]` + * + * It may be a partially applied method: + * ```scala + * //{ + * type T + * //} + * extension (x: Int) def f[T](y: T) = ??? + * // represented as + * // def f(x: Int)[T](y: T) = ??? + * + * 1.f[Int](2) + * // represented as + * // f(1)[Int](2) + * ``` + * - `fun` is `f(1)` in the `TypeApply` of `f(1)[Int]` + */ + def fun: Term + + /** + * The (inferred) type arguments passed to the method + * + * The `TypeApply` may be a partially applied method: + * ```scala + * //{ + * type T + * //} + * extension (x: Int) def f[T](y: T) = ??? + * // represented as + * // def f(x: Int)[T](y: T) = ??? + * + * 1.f[Int](2) + * // represented as + * // f(1)[Int](2) + * ``` + * - `fun` is `[Int]` in the `TypeApply` of `f(1)[Int]` + */ + def args: List[TypeTree] + +} +object TypeApply { + + def api(using meta: Meta): Meta.TypeApplyAPI = meta.internal.typeApply + given Meta => Conversion[TypeApply.type, Meta.TypeApplyAPI] = _.api + + /** Matches a function type application `[]` */ + def unapply(x: TypeApply): (Term, List[TypeTree]) = (x.fun, x.args) + +} + +trait Super private[meta] extends Term { + override type Self <: Super + + def qualifier: Term + + def id: Option[String] + + def idPos: Position + +} +object Super { + + def api(using meta: Meta): Meta.SuperAPI = meta.internal.`super` + given Meta => Conversion[Super.type, Meta.SuperAPI] = _.api + + /** Matches a `.super[` */ + def unapply(x: Super): (Term, Option[String]) = (x.qualifier, x.id) + +} + +trait Assign private[meta] extends Term { + override type Self <: Assign + + def lhs: Term + + def rhs: Term + +} +object Assign { + + def api(using meta: Meta): Meta.AssignAPI = meta.internal.assign + given Meta => Conversion[Assign.type, Meta.AssignAPI] = _.api + + /** Matches an assignment ` = ` */ + def unapply(x: Assign): (Term, Term) = (x.lhs, x.rhs) + +} + +trait Block private[meta] extends Term { + override type Self <: Block + + def statements: List[Statement] + + def expr: Term + +} +object Block { + + def api(using meta: Meta): Meta.BlockAPI = meta.internal.block + given Meta => Conversion[Block.type, Meta.BlockAPI] = _.api + + /** Matches a block `{ ; }` */ + def unapply(x: Block): (List[Statement], Term) = (x.statements, x.expr) + +} + +trait Closure private[meta] extends Term { + override type Self <: Closure + + // TODO (KR) : functions + +} +object Closure { + + def api(using meta: Meta): Meta.ClosureAPI = meta.internal.closure + given Meta => Conversion[Closure.type, Meta.ClosureAPI] = _.api + +} + +trait If private[meta] extends Term { + override type Self <: If + + // TODO (KR) : functions + +} +object If { + + def api(using meta: Meta): Meta.IfAPI = meta.internal.`if` + given Meta => Conversion[If.type, Meta.IfAPI] = _.api + +} + +trait Match private[meta] extends Term { + override type Self <: Match + + // TODO (KR) : functions + +} +object Match { + + def api(using meta: Meta): Meta.MatchAPI = meta.internal.`match` + given Meta => Conversion[Match.type, Meta.MatchAPI] = _.api + +} + +trait SummonFrom private[meta] extends Term { + override type Self <: SummonFrom + + // TODO (KR) : functions + +} +object SummonFrom { + + def api(using meta: Meta): Meta.SummonFromAPI = meta.internal.summonFrom + given Meta => Conversion[SummonFrom.type, Meta.SummonFromAPI] = _.api + +} + +trait Try private[meta] extends Term { + override type Self <: Try + + // TODO (KR) : functions + +} +object Try { + + def api(using meta: Meta): Meta.TryAPI = meta.internal.`try` + given Meta => Conversion[Try.type, Meta.TryAPI] = _.api + +} + +trait Return private[meta] extends Term { + override type Self <: Return + + // TODO (KR) : functions + +} +object Return { + + def api(using meta: Meta): Meta.ReturnAPI = meta.internal.`return` + given Meta => Conversion[Return.type, Meta.ReturnAPI] = _.api + +} + +trait Repeated private[meta] extends Term { + override type Self <: Repeated + + // TODO (KR) : functions + +} +object Repeated { + + def api(using meta: Meta): Meta.RepeatedAPI = meta.internal.repeated + given Meta => Conversion[Repeated.type, Meta.RepeatedAPI] = _.api + +} + +trait Inlined private[meta] extends Term { + override type Self <: Inlined + + // TODO (KR) : functions + +} +object Inlined { + + def api(using meta: Meta): Meta.InlinedAPI = meta.internal.inlined + given Meta => Conversion[Inlined.type, Meta.InlinedAPI] = _.api + +} + +trait SelectOuter private[meta] extends Term { + override type Self <: SelectOuter + + // TODO (KR) : functions + +} +object SelectOuter { + + def api(using meta: Meta): Meta.SelectOuterAPI = meta.internal.selectOuter + given Meta => Conversion[SelectOuter.type, Meta.SelectOuterAPI] = _.api + +} + +trait While private[meta] extends Term { + override type Self <: While + + // TODO (KR) : functions + +} +object While { + + def api(using meta: Meta): Meta.WhileAPI = meta.internal.`while` + given Meta => Conversion[While.type, Meta.WhileAPI] = _.api + +} + +sealed trait TypedOrTest extends Tree { + override type Self <: TypedOrTest + + // TODO (KR) : functions + +} +object TypedOrTest { + + def api(using meta: Meta): Meta.TypedOrTestAPI = meta.internal.typedOrTest + given Meta => Conversion[TypedOrTest.type, Meta.TypedOrTestAPI] = _.api + +} + +trait Typed private[meta] extends Term, TypedOrTest { + override type Self <: Typed + + // TODO (KR) : functions + +} +object Typed { + + def api(using meta: Meta): Meta.TypedAPI = meta.internal.typed + given Meta => Conversion[Typed.type, Meta.TypedAPI] = _.api + +} + +trait Bind private[meta] extends Tree { + override type Self <: Bind + + // TODO (KR) : functions + +} +object Bind { + + def api(using meta: Meta): Meta.BindAPI = meta.internal.bind + given Meta => Conversion[Bind.type, Meta.BindAPI] = _.api + +} + +trait Unapply private[meta] extends Tree { + override type Self <: Unapply + + // TODO (KR) : functions + +} +object Unapply { + + def api(using meta: Meta): Meta.UnapplyAPI = meta.internal.unapply + given Meta => Conversion[Unapply.type, Meta.UnapplyAPI] = _.api + +} + +trait Alternatives private[meta] extends Tree { + override type Self <: Alternatives + + // TODO (KR) : functions + +} +object Alternatives { + + def api(using meta: Meta): Meta.AlternativesAPI = meta.internal.alternatives + given Meta => Conversion[Alternatives.type, Meta.AlternativesAPI] = _.api + +} + +trait CaseDef private[meta] extends Tree { + override type Self <: CaseDef + + // TODO (KR) : functions + +} +object CaseDef { + + def api(using meta: Meta): Meta.CaseDefAPI = meta.internal.caseDef + given Meta => Conversion[CaseDef.type, Meta.CaseDefAPI] = _.api + +} + +trait TypeCaseDef private[meta] extends Tree { + override type Self <: TypeCaseDef + + // TODO (KR) : functions + +} +object TypeCaseDef { + + def api(using meta: Meta): Meta.TypeCaseDefAPI = meta.internal.typeCaseDef + given Meta => Conversion[TypeCaseDef.type, Meta.TypeCaseDefAPI] = _.api + +} + +sealed trait TypeTree extends Tree { + override type Self <: TypeTree + + // TODO (KR) : functions + +} +object TypeTree { + + def api(using meta: Meta): Meta.TypeTreeAPI = meta.internal.typeTree + given Meta => Conversion[TypeTree.type, Meta.TypeTreeAPI] = _.api + +} + +trait Inferred private[meta] extends TypeTree { + override type Self <: Inferred + + // TODO (KR) : functions + +} +object Inferred { + + def api(using meta: Meta): Meta.InferredAPI = meta.internal.inferred + given Meta => Conversion[Inferred.type, Meta.InferredAPI] = _.api + +} + +trait TypeIdent private[meta] extends TypeTree { + override type Self <: TypeIdent + + // TODO (KR) : functions + +} +object TypeIdent { + + def api(using meta: Meta): Meta.TypeIdentAPI = meta.internal.typeIdent + given Meta => Conversion[TypeIdent.type, Meta.TypeIdentAPI] = _.api + +} + +trait TypeSelect private[meta] extends TypeTree { + override type Self <: TypeSelect + + // TODO (KR) : functions + +} +object TypeSelect { + + def api(using meta: Meta): Meta.TypeSelectAPI = meta.internal.typeSelect + given Meta => Conversion[TypeSelect.type, Meta.TypeSelectAPI] = _.api + +} + +trait TypeProjection private[meta] extends TypeTree { + override type Self <: TypeProjection + + // TODO (KR) : functions + +} +object TypeProjection { + + def api(using meta: Meta): Meta.TypeProjectionAPI = meta.internal.typeProjection + given Meta => Conversion[TypeProjection.type, Meta.TypeProjectionAPI] = _.api + +} + +trait Singleton private[meta] extends TypeTree { + override type Self <: Singleton + + // TODO (KR) : functions + +} +object Singleton { + + def api(using meta: Meta): Meta.SingletonAPI = meta.internal.singleton + given Meta => Conversion[Singleton.type, Meta.SingletonAPI] = _.api + +} + +trait Refined private[meta] extends TypeTree { + override type Self <: Refined + + // TODO (KR) : functions + +} +object Refined { + + def api(using meta: Meta): Meta.RefinedAPI = meta.internal.refined + given Meta => Conversion[Refined.type, Meta.RefinedAPI] = _.api + +} + +trait Applied private[meta] extends TypeTree { + override type Self <: Applied + + // TODO (KR) : functions + +} +object Applied { + + def api(using meta: Meta): Meta.AppliedAPI = meta.internal.applied + given Meta => Conversion[Applied.type, Meta.AppliedAPI] = _.api + +} + +trait Annotated private[meta] extends TypeTree { + override type Self <: Annotated + + // TODO (KR) : functions + +} +object Annotated { + + def api(using meta: Meta): Meta.AnnotatedAPI = meta.internal.annotated + given Meta => Conversion[Annotated.type, Meta.AnnotatedAPI] = _.api + +} + +trait MatchTypeTree private[meta] extends TypeTree { + override type Self <: MatchTypeTree + + // TODO (KR) : functions + +} +object MatchTypeTree { + + def api(using meta: Meta): Meta.MatchTypeTreeAPI = meta.internal.matchTypeTree + given Meta => Conversion[MatchTypeTree.type, Meta.MatchTypeTreeAPI] = _.api + +} + +trait ByName private[meta] extends TypeTree { + override type Self <: ByName + + // TODO (KR) : functions + +} +object ByName { + + def api(using meta: Meta): Meta.ByNameAPI = meta.internal.byName + given Meta => Conversion[ByName.type, Meta.ByNameAPI] = _.api + +} + +trait LambdaTypeTree private[meta] extends TypeTree { + override type Self <: LambdaTypeTree + + // TODO (KR) : functions + +} +object LambdaTypeTree { + + def api(using meta: Meta): Meta.LambdaTypeTreeAPI = meta.internal.lambdaTypeTree + given Meta => Conversion[LambdaTypeTree.type, Meta.LambdaTypeTreeAPI] = _.api + +} + +trait TypeBind private[meta] extends TypeTree { + override type Self <: TypeBind + + // TODO (KR) : functions + +} +object TypeBind { + + def api(using meta: Meta): Meta.TypeBindAPI = meta.internal.typeBind + given Meta => Conversion[TypeBind.type, Meta.TypeBindAPI] = _.api + +} + +trait TypeBlock private[meta] extends TypeTree { + override type Self <: TypeBlock + + // TODO (KR) : functions + +} +object TypeBlock { + + def api(using meta: Meta): Meta.TypeBlockAPI = meta.internal.typeBlock + given Meta => Conversion[TypeBlock.type, Meta.TypeBlockAPI] = _.api + +} + +trait TypeBoundsTree private[meta] extends Tree { + override type Self <: TypeBoundsTree + + // TODO (KR) : functions + +} +object TypeBoundsTree { + + def api(using meta: Meta): Meta.TypeBoundsTreeAPI = meta.internal.typeBoundsTree + given Meta => Conversion[TypeBoundsTree.type, Meta.TypeBoundsTreeAPI] = _.api + +} + +trait WildcardTypeTree private[meta] extends Tree { + override type Self <: WildcardTypeTree + + // TODO (KR) : functions + +} +object WildcardTypeTree { + + def api(using meta: Meta): Meta.WildcardTypeTreeAPI = meta.internal.wildcardTypeTree + given Meta => Conversion[WildcardTypeTree.type, Meta.WildcardTypeTreeAPI] = _.api + +} diff --git a/library/src/scala/quoted/meta/TypeRepr.scala b/library/src/scala/quoted/meta/TypeRepr.scala new file mode 100644 index 000000000000..620d362a1e0c --- /dev/null +++ b/library/src/scala/quoted/meta/TypeRepr.scala @@ -0,0 +1,354 @@ +package scala.quoted.meta + +import scala.quoted.Type + +trait TypeRepr private[meta] extends AnyRef { + type Self <: TypeRepr + + // TODO (KR) : functions + +} +object TypeRepr { + + def api(using meta: Meta): Meta.TypeReprAPI = meta.internal.typeRepr + given Meta => Conversion[TypeRepr.type, Meta.TypeReprAPI] = _.api + +} + +trait NamedType private[meta] extends TypeRepr { + override type Self <: NamedType + + // TODO (KR) : functions + +} +object NamedType { + + def api(using meta: Meta): Meta.NamedTypeAPI = meta.internal.namedType + given Meta => Conversion[NamedType.type, Meta.NamedTypeAPI] = _.api + +} + +trait TermRef private[meta] extends NamedType { + override type Self <: TermRef + + // TODO (KR) : functions + +} +object TermRef { + + def api(using meta: Meta): Meta.TermRefAPI = meta.internal.termRef + given Meta => Conversion[TermRef.type, Meta.TermRefAPI] = _.api + +} + +trait TypeRef private[meta] extends NamedType { + override type Self <: TypeRef + + // TODO (KR) : functions + +} +object TypeRef { + + def api(using meta: Meta): Meta.TypeRefAPI = meta.internal.typeRef + given Meta => Conversion[TypeRef.type, Meta.TypeRefAPI] = _.api + +} + +trait ConstantType private[meta] extends TypeRepr { + override type Self <: ConstantType + + // TODO (KR) : functions + +} +object ConstantType { + + def api(using meta: Meta): Meta.ConstantTypeAPI = meta.internal.constantType + given Meta => Conversion[ConstantType.type, Meta.ConstantTypeAPI] = _.api + +} + +trait SuperType private[meta] extends TypeRepr { + override type Self <: SuperType + + // TODO (KR) : functions + +} +object SuperType { + + def api(using meta: Meta): Meta.SuperTypeAPI = meta.internal.superType + given Meta => Conversion[SuperType.type, Meta.SuperTypeAPI] = _.api + +} + +trait Refinement private[meta] extends TypeRepr { + override type Self <: Refinement + + // TODO (KR) : functions + +} +object Refinement { + + def api(using meta: Meta): Meta.RefinementAPI = meta.internal.refinement + given Meta => Conversion[Refinement.type, Meta.RefinementAPI] = _.api + +} + +trait AppliedType private[meta] extends TypeRepr { + override type Self <: AppliedType + + // TODO (KR) : functions + +} +object AppliedType { + + def api(using meta: Meta): Meta.AppliedTypeAPI = meta.internal.appliedType + given Meta => Conversion[AppliedType.type, Meta.AppliedTypeAPI] = _.api + +} + +trait AnnotatedType private[meta] extends TypeRepr { + override type Self <: AnnotatedType + + // TODO (KR) : functions + +} +object AnnotatedType { + + def api(using meta: Meta): Meta.AnnotatedTypeAPI = meta.internal.annotatedType + given Meta => Conversion[AnnotatedType.type, Meta.AnnotatedTypeAPI] = _.api + +} + +trait AndOrType private[meta] extends TypeRepr { + override type Self <: AndOrType + + // TODO (KR) : functions + +} +object AndOrType { + + def api(using meta: Meta): Meta.AndOrTypeAPI = meta.internal.andOrType + given Meta => Conversion[AndOrType.type, Meta.AndOrTypeAPI] = _.api + +} + +trait AndType private[meta] extends AndOrType { + override type Self <: AndType + + // TODO (KR) : functions + +} +object AndType { + + def api(using meta: Meta): Meta.AndTypeAPI = meta.internal.andType + given Meta => Conversion[AndType.type, Meta.AndTypeAPI] = _.api + +} + +trait OrType private[meta] extends AndOrType { + override type Self <: OrType + + // TODO (KR) : functions + +} +object OrType { + + def api(using meta: Meta): Meta.OrTypeAPI = meta.internal.orType + given Meta => Conversion[OrType.type, Meta.OrTypeAPI] = _.api + +} + +trait MatchType private[meta] extends TypeRepr { + override type Self <: MatchType + + // TODO (KR) : functions + +} +object MatchType { + + def api(using meta: Meta): Meta.MatchTypeAPI = meta.internal.matchType + given Meta => Conversion[MatchType.type, Meta.MatchTypeAPI] = _.api + +} + +trait ByNameType private[meta] extends TypeRepr { + override type Self <: ByNameType + + // TODO (KR) : functions + +} +object ByNameType { + + def api(using meta: Meta): Meta.ByNameTypeAPI = meta.internal.byNameType + given Meta => Conversion[ByNameType.type, Meta.ByNameTypeAPI] = _.api + +} + +trait ParamRef private[meta] extends TypeRepr { + override type Self <: ParamRef + + // TODO (KR) : functions + +} +object ParamRef { + + def api(using meta: Meta): Meta.ParamRefAPI = meta.internal.paramRef + given Meta => Conversion[ParamRef.type, Meta.ParamRefAPI] = _.api + +} + +trait Self private[meta] extends TypeRepr { + override type Self <: scala.quoted.meta.Self + + // TODO (KR) : functions + +} +object Self { + + def api(using meta: Meta): Meta.SelfAPI = meta.internal.self + given Meta => Conversion[Self.type, Meta.SelfAPI] = _.api + +} + +trait RecursiveThis private[meta] extends TypeRepr { + override type Self <: RecursiveThis + + // TODO (KR) : functions + +} +object RecursiveThis { + + def api(using meta: Meta): Meta.RecursiveThisAPI = meta.internal.recursiveThis + given Meta => Conversion[RecursiveThis.type, Meta.RecursiveThisAPI] = _.api + +} + +trait RecursiveType private[meta] extends TypeRepr { + override type Self <: RecursiveType + + // TODO (KR) : functions + +} +object RecursiveType { + + def api(using meta: Meta): Meta.RecursiveTypeAPI = meta.internal.recursiveType + given Meta => Conversion[RecursiveType.type, Meta.RecursiveTypeAPI] = _.api + +} + +trait LambdaType private[meta] extends TypeRepr { + override type Self <: LambdaType + + // TODO (KR) : functions + +} +object LambdaType { + + def api(using meta: Meta): Meta.LambdaTypeAPI = meta.internal.lambdaType + given Meta => Conversion[LambdaType.type, Meta.LambdaTypeAPI] = _.api + +} + +trait MethodOrPoly private[meta] extends LambdaType { + override type Self <: MethodOrPoly + + // TODO (KR) : functions + +} +object MethodOrPoly { + + def api(using meta: Meta): Meta.MethodOrPolyAPI = meta.internal.methodOrPoly + given Meta => Conversion[MethodOrPoly.type, Meta.MethodOrPolyAPI] = _.api + +} + +trait MethodType private[meta] extends MethodOrPoly { + override type Self <: MethodType + + // TODO (KR) : functions + +} +object MethodType { + + def api(using meta: Meta): Meta.MethodTypeAPI = meta.internal.methodType + given Meta => Conversion[MethodType.type, Meta.MethodTypeAPI] = _.api + +} + +trait PolyType private[meta] extends MethodOrPoly { + override type Self <: PolyType + + // TODO (KR) : functions + +} +object PolyType { + + def api(using meta: Meta): Meta.PolyTypeAPI = meta.internal.polyType + given Meta => Conversion[PolyType.type, Meta.PolyTypeAPI] = _.api + +} + +trait TypeLambda private[meta] extends LambdaType { + override type Self <: TypeLambda + + // TODO (KR) : functions + +} +object TypeLambda { + + def api(using meta: Meta): Meta.TypeLambdaAPI = meta.internal.typeLambda + given Meta => Conversion[TypeLambda.type, Meta.TypeLambdaAPI] = _.api + +} + +trait MatchCase private[meta] extends TypeRepr { + override type Self <: MatchCase + + // TODO (KR) : functions + +} +object MatchCase { + + def api(using meta: Meta): Meta.MatchCaseAPI = meta.internal.matchCase + given Meta => Conversion[MatchCase.type, Meta.MatchCaseAPI] = _.api + +} + +trait TypeBounds private[meta] extends TypeRepr { + override type Self <: TypeBounds + + // TODO (KR) : functions + +} +object TypeBounds { + + def api(using meta: Meta): Meta.TypeBoundsAPI = meta.internal.typeBounds + given Meta => Conversion[TypeBounds.type, Meta.TypeBoundsAPI] = _.api + +} + +trait NoPrefix private[meta] extends TypeRepr { + override type Self <: NoPrefix + + // TODO (KR) : functions + +} +object NoPrefix { + + def api(using meta: Meta): Meta.NoPrefixAPI = meta.internal.noPrefix + given Meta => Conversion[NoPrefix.type, Meta.NoPrefixAPI] = _.api + +} + +trait FlexibleType private[meta] extends TypeRepr { + override type Self <: FlexibleType + + // TODO (KR) : functions + +} +object FlexibleType { + + def api(using meta: Meta): Meta.FlexibleTypeAPI = meta.internal.flexibleType + given Meta => Conversion[FlexibleType.type, Meta.FlexibleTypeAPI] = _.api + +}