Experimental version of macro definitions. Macro calls need to be done next. No review.
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@26079 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
7bce33982a
commit
0095854ff0
|
|
@ -243,10 +243,6 @@ trait Definitions extends reflect.api.StandardDefinitions {
|
|||
def arrayCloneMethod = getMember(ScalaRunTimeModule, "array_clone")
|
||||
def ensureAccessibleMethod = getMember(ScalaRunTimeModule, "ensureAccessible")
|
||||
def scalaRuntimeSameElements = getMember(ScalaRunTimeModule, nme.sameElements)
|
||||
lazy val ReflectRuntimeMirror = getModule("scala.reflect.runtime.Mirror")
|
||||
def freeValueMethod = getMember(ReflectRuntimeMirror, "freeValue")
|
||||
lazy val ReflectPackage = getPackageObject("scala.reflect")
|
||||
def Reflect_mirror = getMember(ReflectPackage, "mirror")
|
||||
|
||||
// classes with special meanings
|
||||
lazy val StringAddClass = getClass("scala.runtime.StringAdd")
|
||||
|
|
@ -354,6 +350,13 @@ trait Definitions extends reflect.api.StandardDefinitions {
|
|||
def methodCache_add = getMember(MethodCacheClass, nme.add_)
|
||||
|
||||
// scala.reflect
|
||||
lazy val ReflectApiUniverse = getClass("scala.reflect.api.Universe")
|
||||
lazy val ReflectRuntimeMirror = getModule("scala.reflect.runtime.Mirror")
|
||||
def freeValueMethod = getMember(ReflectRuntimeMirror, "freeValue")
|
||||
lazy val ReflectPackage = getPackageObject("scala.reflect")
|
||||
def Reflect_mirror = getMember(ReflectPackage, "mirror")
|
||||
|
||||
|
||||
lazy val PartialManifestClass = getClass("scala.reflect.ClassManifest")
|
||||
lazy val PartialManifestModule = getModule("scala.reflect.ClassManifest")
|
||||
lazy val FullManifestClass = getClass("scala.reflect.Manifest")
|
||||
|
|
|
|||
|
|
@ -526,6 +526,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|
|||
// unfortunately having the CASEACCESSOR flag does not actually mean you
|
||||
// are a case accessor (you can also be a field.)
|
||||
def isCaseAccessorMethod = isMethod && isCaseAccessor
|
||||
|
||||
def isMacro = isMethod && hasFlag(MACRO)
|
||||
|
||||
/** Does this symbol denote the primary constructor of its enclosing class? */
|
||||
final def isPrimaryConstructor =
|
||||
|
|
@ -712,8 +714,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|
|||
def originalOwnerChain: List[Symbol] = this :: originalOwner.getOrElse(this, rawowner).originalOwnerChain
|
||||
|
||||
def enclClassChain: List[Symbol] = {
|
||||
if (this eq NoSymbol) Nil
|
||||
else if (isClass && !isPackageClass) this :: owner.enclClassChain
|
||||
if ((this eq NoSymbol) || isPackageClass) Nil
|
||||
else if (isClass) this :: owner.enclClassChain
|
||||
else owner.enclClassChain
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2408,6 +2408,7 @@ self =>
|
|||
* FunDef ::= FunSig `:' Type `=' Expr
|
||||
* | FunSig [nl] `{' Block `}'
|
||||
* | this ParamClause ParamClauses (`=' ConstrExpr | [nl] ConstrBlock)
|
||||
* | `macro' FunSig [`:' Type] `=' Expr
|
||||
* FunDcl ::= FunSig [`:' Type]
|
||||
* FunSig ::= id [FunTypeParamClause] ParamClauses
|
||||
* }}}
|
||||
|
|
@ -2426,35 +2427,46 @@ self =>
|
|||
}
|
||||
}
|
||||
else {
|
||||
var newmods = mods
|
||||
val nameOffset = in.offset
|
||||
val name = ident()
|
||||
val result = atPos(start, if (name == nme.ERROR) start else nameOffset) {
|
||||
// contextBoundBuf is for context bounded type parameters of the form
|
||||
// [T : B] or [T : => B]; it contains the equivalent implicit parameter type,
|
||||
// i.e. (B[T] or T => B)
|
||||
val contextBoundBuf = new ListBuffer[Tree]
|
||||
val tparams = typeParamClauseOpt(name, contextBoundBuf)
|
||||
val vparamss = paramClauses(name, contextBoundBuf.toList, false)
|
||||
newLineOptWhenFollowedBy(LBRACE)
|
||||
var restype = fromWithinReturnType(typedOpt())
|
||||
val rhs =
|
||||
if (isStatSep || in.token == RBRACE) {
|
||||
if (restype.isEmpty) restype = scalaUnitConstr
|
||||
newmods |= Flags.DEFERRED
|
||||
EmptyTree
|
||||
} else if (restype.isEmpty && in.token == LBRACE) {
|
||||
restype = scalaUnitConstr
|
||||
blockExpr()
|
||||
} else {
|
||||
equalsExpr()
|
||||
}
|
||||
DefDef(newmods, name, tparams, vparamss, restype, rhs)
|
||||
}
|
||||
signalParseProgress(result.pos)
|
||||
result
|
||||
if (name == nme.macro_ && isIdent && settings.Xexperimental.value)
|
||||
funDefRest(start, in.offset, mods | Flags.MACRO, ident())
|
||||
else
|
||||
funDefRest(start, nameOffset, mods, name)
|
||||
}
|
||||
}
|
||||
|
||||
def funDefRest(start: Int, nameOffset: Int, mods: Modifiers, name: Name): Tree = {
|
||||
val result = atPos(start, if (name.toTermName == nme.ERROR) start else nameOffset) {
|
||||
val isMacro = mods hasFlag Flags.MACRO
|
||||
val isTypeMacro = isMacro && name.isTypeName
|
||||
var newmods = mods
|
||||
// contextBoundBuf is for context bounded type parameters of the form
|
||||
// [T : B] or [T : => B]; it contains the equivalent implicit parameter type,
|
||||
// i.e. (B[T] or T => B)
|
||||
val contextBoundBuf = new ListBuffer[Tree]
|
||||
val tparams = typeParamClauseOpt(name, contextBoundBuf)
|
||||
val vparamss = paramClauses(name, contextBoundBuf.toList, false)
|
||||
if (!isMacro) newLineOptWhenFollowedBy(LBRACE)
|
||||
var restype = if (isTypeMacro) TypeTree() else fromWithinReturnType(typedOpt())
|
||||
val rhs =
|
||||
if (isMacro)
|
||||
equalsExpr()
|
||||
else if (isStatSep || in.token == RBRACE) {
|
||||
if (restype.isEmpty) restype = scalaUnitConstr
|
||||
newmods |= Flags.DEFERRED
|
||||
EmptyTree
|
||||
} else if (restype.isEmpty && in.token == LBRACE) {
|
||||
restype = scalaUnitConstr
|
||||
blockExpr()
|
||||
} else {
|
||||
equalsExpr()
|
||||
}
|
||||
DefDef(newmods, name, tparams, vparamss, restype, rhs)
|
||||
}
|
||||
signalParseProgress(result.pos)
|
||||
result
|
||||
}
|
||||
|
||||
/** {{{
|
||||
* ConstrExpr ::= SelfInvocation
|
||||
|
|
@ -2498,6 +2510,7 @@ self =>
|
|||
|
||||
/** {{{
|
||||
* TypeDef ::= type Id [TypeParamClause] `=' Type
|
||||
* | `macro' FunSig `=' Expr
|
||||
* TypeDcl ::= type Id [TypeParamClause] TypeBounds
|
||||
* }}}
|
||||
*/
|
||||
|
|
@ -2506,17 +2519,21 @@ self =>
|
|||
newLinesOpt()
|
||||
atPos(start, in.offset) {
|
||||
val name = identForType()
|
||||
// @M! a type alias as well as an abstract type may declare type parameters
|
||||
val tparams = typeParamClauseOpt(name, null)
|
||||
in.token match {
|
||||
case EQUALS =>
|
||||
in.nextToken()
|
||||
TypeDef(mods, name, tparams, typ())
|
||||
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE =>
|
||||
TypeDef(mods | Flags.DEFERRED, name, tparams, typeBounds())
|
||||
case _ =>
|
||||
syntaxErrorOrIncomplete("`=', `>:', or `<:' expected", true)
|
||||
EmptyTree
|
||||
if (name == nme.macro_.toTypeName && isIdent && settings.Xexperimental.value) {
|
||||
funDefRest(start, in.offset, mods | Flags.MACRO, identForType())
|
||||
} else {
|
||||
// @M! a type alias as well as an abstract type may declare type parameters
|
||||
val tparams = typeParamClauseOpt(name, null)
|
||||
in.token match {
|
||||
case EQUALS =>
|
||||
in.nextToken()
|
||||
TypeDef(mods, name, tparams, typ())
|
||||
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE =>
|
||||
TypeDef(mods | Flags.DEFERRED, name, tparams, typeBounds())
|
||||
case _ =>
|
||||
syntaxErrorOrIncomplete("`=', `>:', or `<:' expected", true)
|
||||
EmptyTree
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ trait Analyzer extends AnyRef
|
|||
with EtaExpansion
|
||||
with SyntheticMethods
|
||||
with Unapplies
|
||||
with Macros
|
||||
with NamesDefaults
|
||||
with TypeDiagnostics
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
package scala.tools.nsc
|
||||
package typechecker
|
||||
|
||||
import symtab.Flags._
|
||||
|
||||
trait Macros { self: Analyzer =>
|
||||
import global._
|
||||
import definitions._
|
||||
|
||||
def macroMethName(name: Name) =
|
||||
newTermName((if (name.isTypeName) "type" else "def") + "macro$" + name)
|
||||
|
||||
def macroMeth(mac: Symbol): Symbol = {
|
||||
var owner = mac.owner
|
||||
if (!owner.isModuleClass) owner = owner.companionModule.moduleClass
|
||||
owner.info.decl(macroMethName(mac.name))
|
||||
}
|
||||
|
||||
/**
|
||||
* The definition of the method implementing a macro. Example:
|
||||
* Say we have
|
||||
*
|
||||
* def macro foo[T](xs: List[T]): T = expr
|
||||
*
|
||||
* Then the following macro method is generated for `foo`:
|
||||
*
|
||||
* def foo(glob: scala.reflect.api.Universe)
|
||||
* (_this: glob.Tree)
|
||||
* (T: glob.Type)
|
||||
* (xs: glob.Tree): glob.Tree = {
|
||||
* implicit val $glob = glob
|
||||
* expr
|
||||
* }
|
||||
*/
|
||||
def macroMethDef(mdef: DefDef): Tree = {
|
||||
def paramDef(name: Name, tpt: Tree) = ValDef(Modifiers(PARAM), name, tpt, EmptyTree)
|
||||
val universeType = TypeTree(ReflectApiUniverse.tpe)
|
||||
val globParam = paramDef("glob", universeType)
|
||||
def globSelect(name: Name) = Select(Ident("glob"), name)
|
||||
def globTree = globSelect(newTypeName("Tree"))
|
||||
def globType = globSelect(newTypeName("Type"))
|
||||
val thisParam = paramDef("_this", globTree)
|
||||
def tparamInMacro(tdef: TypeDef) = paramDef(tdef.name.toTermName, globType)
|
||||
def vparamInMacro(vdef: ValDef): ValDef = paramDef(vdef.name, globTree)
|
||||
def wrapImplicit(tree: Tree) = atPos(tree.pos) {
|
||||
Block(List(ValDef(Modifiers(IMPLICIT), "$glob", universeType, Ident("glob"))), tree)
|
||||
}
|
||||
|
||||
treeCopy.DefDef(
|
||||
mdef,
|
||||
mods = mdef.mods &~ MACRO,
|
||||
name = mdef.name.toTermName,
|
||||
tparams = List(),
|
||||
vparamss = List(globParam) :: List(thisParam) :: (mdef.tparams map tparamInMacro) ::
|
||||
(mdef.vparamss map (_ map vparamInMacro)),
|
||||
tpt = globTree,
|
||||
wrapImplicit(mdef.rhs))
|
||||
}
|
||||
|
||||
def addMacroMethods(templ: Template, namer: Namer): Unit = {
|
||||
for (ddef @ DefDef(mods, _, _, _, _, _) <- templ.body if mods hasFlag MACRO) {
|
||||
namer.enterSyntheticSym(macroMethDef(ddef))
|
||||
}
|
||||
}
|
||||
|
||||
def macroExpand(tree: Tree): Tree = ???
|
||||
|
||||
}
|
||||
|
|
@ -59,8 +59,8 @@ trait Namers extends MethodSynthesis {
|
|||
// is stored in this map. The map is cleared lazily, i.e. when the new symbol
|
||||
// is created with the same name, the old one (if present) is wiped out, or the
|
||||
// entry is deleted when it is used and no longer needed.
|
||||
private val caseClassOfModuleClass = perRunCaches.newWeakMap[Symbol, WeakReference[ClassDef]]()
|
||||
|
||||
private val classOfModuleClass = perRunCaches.newWeakMap[Symbol, WeakReference[ClassDef]]()
|
||||
|
||||
// Default getters of constructors are added to the companion object in the
|
||||
// typeCompleter of the constructor (methodSig). To compute the signature,
|
||||
// we need the ClassDef. To create and enter the symbols into the companion
|
||||
|
|
@ -421,8 +421,8 @@ trait Namers extends MethodSynthesis {
|
|||
* class definition tree.
|
||||
* @return the companion object symbol.
|
||||
*/
|
||||
def ensureCompanionObject(tree: ClassDef, creator: => Tree): Symbol = {
|
||||
val m = companionModuleOf(tree.symbol, context)
|
||||
def ensureCompanionObject(cdef: ClassDef, creator: ClassDef => Tree = companionModuleDef(_)): Symbol = {
|
||||
val m = companionModuleOf(cdef.symbol, context)
|
||||
// @luc: not sure why "currentRun.compiles(m)" is needed, things breaks
|
||||
// otherwise. documentation welcome.
|
||||
//
|
||||
|
|
@ -435,8 +435,16 @@ trait Namers extends MethodSynthesis {
|
|||
// Map(class Foo -> Nil)
|
||||
// What exactly this implies and whether this is a sensible way to
|
||||
// enforce it, I don't know.
|
||||
//
|
||||
// @martin: currentRun.compiles is needed because we might have a stale
|
||||
// companion object from another run in scope. In that case we should still
|
||||
// overwrite the object. I.e.
|
||||
// Compile run #1: object Foo { ... }
|
||||
// Compile run #2: case class Foo ...
|
||||
// The object Foo is still in scope, but because it is not compiled in current run
|
||||
// it should be ditched and a new one created.
|
||||
if (m != NoSymbol && currentRun.compiles(m)) m
|
||||
else enterSyntheticSym(creator)
|
||||
else enterSyntheticSym(creator(cdef))
|
||||
}
|
||||
|
||||
private def checkSelectors(tree: Import): Unit = {
|
||||
|
|
@ -599,6 +607,11 @@ trait Namers extends MethodSynthesis {
|
|||
enterCopyMethodOrGetter(tree, tparams)
|
||||
else
|
||||
sym setInfo completerOf(tree, tparams)
|
||||
|
||||
if (mods hasFlag MACRO) {
|
||||
if (!(sym.owner.isClass && sym.owner.isStatic))
|
||||
context.error(tree.pos, "macro definition must appear in globally accessible class")
|
||||
}
|
||||
}
|
||||
|
||||
def enterClassDef(tree: ClassDef) {
|
||||
|
|
@ -610,17 +623,25 @@ trait Namers extends MethodSynthesis {
|
|||
if (treeInfo.firstConstructorArgs(impl.body).size > MaxFunctionArity)
|
||||
context.error(tree.pos, "Implementation restriction: case classes cannot have more than " + MaxFunctionArity + " parameters.")
|
||||
|
||||
val m = ensureCompanionObject(tree, caseModuleDef(tree))
|
||||
caseClassOfModuleClass(m.moduleClass) = new WeakReference(tree)
|
||||
val m = ensureCompanionObject(tree, caseModuleDef)
|
||||
classOfModuleClass(m.moduleClass) = new WeakReference(tree)
|
||||
}
|
||||
val hasDefault = impl.body exists {
|
||||
case DefDef(_, nme.CONSTRUCTOR, _, vparamss, _, _) => listutil.mexists(vparamss)(_.mods.hasDefault)
|
||||
case _ => false
|
||||
}
|
||||
if (hasDefault) {
|
||||
val m = ensureCompanionObject(tree, companionModuleDef(tree))
|
||||
val m = ensureCompanionObject(tree)
|
||||
classAndNamerOfModule(m) = (tree, null)
|
||||
}
|
||||
val hasMacro = impl.body exists {
|
||||
case DefDef(mods, _, _, _, _, _) => mods hasFlag MACRO
|
||||
case _ => false
|
||||
}
|
||||
if (hasMacro) {
|
||||
val m = ensureCompanionObject(tree)
|
||||
classOfModuleClass(m.moduleClass) = new WeakReference(tree)
|
||||
}
|
||||
val owner = tree.symbol.owner
|
||||
if (owner.isPackageObjectClass) {
|
||||
context.unit.warning(tree.pos,
|
||||
|
|
@ -816,25 +837,27 @@ trait Namers extends MethodSynthesis {
|
|||
// add apply and unapply methods to companion objects of case classes,
|
||||
// unless they exist already; here, "clazz" is the module class
|
||||
if (clazz.isModuleClass) {
|
||||
Namers.this.caseClassOfModuleClass get clazz foreach { cdefRef =>
|
||||
Namers.this.classOfModuleClass get clazz foreach { cdefRef =>
|
||||
val cdef = cdefRef()
|
||||
addApplyUnapply(cdef, templateNamer)
|
||||
caseClassOfModuleClass -= clazz
|
||||
if (cdef.mods.isCase) addApplyUnapply(cdef, templateNamer)
|
||||
addMacroMethods(cdef.impl, templateNamer)
|
||||
classOfModuleClass -= clazz
|
||||
}
|
||||
addMacroMethods(templ, templateNamer)
|
||||
}
|
||||
|
||||
// add the copy method to case classes; this needs to be done here, not in SyntheticMethods, because
|
||||
// the namer phase must traverse this copy method to create default getters for its parameters.
|
||||
// here, clazz is the ClassSymbol of the case class (not the module).
|
||||
// @check: this seems to work only if the type completer of the class runs before the one of the
|
||||
// module class: the one from the module class removes the entry from caseClassOfModuleClass (see above).
|
||||
// module class: the one from the module class removes the entry from classOfModuleClass (see above).
|
||||
if (clazz.isClass && !clazz.hasModuleFlag) {
|
||||
val modClass = companionModuleOf(clazz, context).moduleClass
|
||||
Namers.this.caseClassOfModuleClass get modClass map { cdefRef =>
|
||||
Namers.this.classOfModuleClass get modClass map { cdefRef =>
|
||||
val cdef = cdefRef()
|
||||
|
||||
def hasCopy(decls: Scope) = (decls lookup nme.copy) != NoSymbol
|
||||
if (!hasCopy(decls) &&
|
||||
if (cdef.mods.isCase && !hasCopy(decls) &&
|
||||
!parents.exists(p => hasCopy(p.typeSymbol.info.decls)) &&
|
||||
!parents.flatMap(_.baseClasses).distinct.exists(bc => hasCopy(bc.info.decls)))
|
||||
addCopyMethod(cdef, templateNamer)
|
||||
|
|
@ -977,13 +1000,16 @@ trait Namers extends MethodSynthesis {
|
|||
|
||||
thisMethodType({
|
||||
val rt = (
|
||||
if (tpt.isEmpty) {
|
||||
if (!tpt.isEmpty) {
|
||||
typer.typedType(tpt).tpe
|
||||
} else if (meth.isMacro) {
|
||||
AnyClass.tpe
|
||||
} else {
|
||||
// replace deSkolemized symbols with skolemized ones
|
||||
// (for resultPt computed by looking at overridden symbol, right?)
|
||||
val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol))
|
||||
assignTypeToTree(ddef, typer, pt)
|
||||
}
|
||||
else typer.typedType(tpt).tpe
|
||||
)
|
||||
// #2382: return type of default getters are always @uncheckedVariance
|
||||
if (meth.hasDefaultFlag)
|
||||
|
|
|
|||
|
|
@ -755,7 +755,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
|
|||
case Block(_, tree1) => tree1.symbol
|
||||
case _ => tree.symbol
|
||||
}
|
||||
if (!meth.isConstructor && isFunctionType(pt)) { // (4.2)
|
||||
if (!meth.isConstructor && !meth.isMacro && isFunctionType(pt)) { // (4.2)
|
||||
debuglog("eta-expanding " + tree + ":" + tree.tpe + " to " + pt)
|
||||
checkParamsConvertible(tree.pos, tree.tpe)
|
||||
val tree0 = etaExpand(context.unit, tree)
|
||||
|
|
@ -1676,6 +1676,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
|
|||
*/
|
||||
def typedDefDef(ddef: DefDef): DefDef = {
|
||||
val meth = ddef.symbol.initialize
|
||||
if (meth.isMacro) return ddef
|
||||
|
||||
reenterTypeParams(ddef.tparams)
|
||||
reenterValueParams(ddef.vparamss)
|
||||
|
|
@ -2100,13 +2101,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
|
|||
var e1 = scope.lookupNextEntry(e)
|
||||
while ((e1 ne null) && e1.owner == scope) {
|
||||
if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
|
||||
(e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe)))
|
||||
(e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe) || e.sym.isMacro && e1.sym.isMacro))
|
||||
// default getters are defined twice when multiple overloads have defaults. an
|
||||
// error for this is issued in RefChecks.checkDefaultsInOverloaded
|
||||
if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefaultFlag &&
|
||||
!e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) {
|
||||
error(e.sym.pos, e1.sym+" is defined twice"+
|
||||
{if(!settings.debug.value) "" else " in "+unit.toString})
|
||||
{if(!settings.debug.value) "" else " in "+unit.toString}+
|
||||
{if (e.sym.isMacro && e1.sym.isMacro) " \n(note that macros cannot be overloaded)" else ""})
|
||||
scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779
|
||||
}
|
||||
e1 = scope.lookupNextEntry(e1)
|
||||
|
|
@ -3442,7 +3444,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
|
|||
// (calling typed1 more than once for the same tree)
|
||||
if (checked ne res) typed { atPos(tree.pos)(checked) }
|
||||
else res
|
||||
} else res
|
||||
} else if (fun2.hasSymbol && fun2.symbol.isMacro)
|
||||
typed1(macroExpand(res), mode, pt)
|
||||
else
|
||||
res
|
||||
case ex: TypeError =>
|
||||
fun match {
|
||||
case Select(qual, name)
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe =>
|
|||
/** A common base class for ValDefs and DefDefs.
|
||||
*/
|
||||
abstract class ValOrDefDef extends MemberDef {
|
||||
def name: TermName
|
||||
def name: Name // can't be a TermName because macros can be type names.
|
||||
def tpt: Tree
|
||||
def rhs: Tree
|
||||
}
|
||||
|
|
@ -325,9 +325,10 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe =>
|
|||
*/
|
||||
case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef
|
||||
|
||||
/** A method definition.
|
||||
/** A method or macro definition.
|
||||
* @param name The name of the method or macro. Can be a type name in case this is a type macro
|
||||
*/
|
||||
case class DefDef(mods: Modifiers, name: TermName, tparams: List[TypeDef],
|
||||
case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef],
|
||||
vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef
|
||||
|
||||
/** An abstract type, a type parameter, or a type alias.
|
||||
|
|
|
|||
Loading…
Reference in New Issue