Revised macro defs, added a test case. Review by burmako.
git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@26082 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
parent
4254a02bb9
commit
e5b9ceba71
|
|
@ -220,7 +220,7 @@ class Flags extends ModifierFlags {
|
|||
|
||||
/** These modifiers appear in TreePrinter output. */
|
||||
final val PrintableFlags: Long =
|
||||
ExplicitFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR |
|
||||
ExplicitFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | MACRO |
|
||||
ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | BRIDGE | STATIC | VBRIDGE | SPECIALIZED
|
||||
|
||||
/** The two bridge flags */
|
||||
|
|
@ -352,7 +352,7 @@ class Flags extends ModifierFlags {
|
|||
case MUTABLE => "<mutable>" // (1L << 12)
|
||||
case PARAM => "<param>" // (1L << 13)
|
||||
case PACKAGE => "<package>" // (1L << 14)
|
||||
case 0x8000L => "" // (1L << 15)
|
||||
case MACRO => "macro" // (1L << 15)
|
||||
case BYNAMEPARAM => "<bynameparam/captured/covariant>" // (1L << 16)
|
||||
case CONTRAVARIANT => "<contravariant/inconstructor/label>" // (1L << 17)
|
||||
case ABSOVERRIDE => "absoverride" // (1L << 18)
|
||||
|
|
|
|||
|
|
@ -7,15 +7,16 @@ trait Macros { self: Analyzer =>
|
|||
import global._
|
||||
import definitions._
|
||||
|
||||
def macroMethName(name: Name) =
|
||||
newTermName((if (name.isTypeName) "type" else "def") + "macro$" + name)
|
||||
def macroMethName(sym: Symbol) =
|
||||
newTermName((if (sym.name.isTypeName) "type" else "def") + "macro$" +
|
||||
(if (sym.owner.isModuleClass) "obj$" else "cls$") + sym.name)
|
||||
|
||||
def macroMeth(mac: Symbol): Symbol = {
|
||||
var owner = mac.owner
|
||||
if (!owner.isModuleClass) owner = owner.companionModule.moduleClass
|
||||
owner.info.decl(macroMethName(mac.name))
|
||||
owner.info.decl(macroMethName(mac))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The definition of the method implementing a macro. Example:
|
||||
* Say we have
|
||||
|
|
@ -46,20 +47,22 @@ trait Macros { self: Analyzer =>
|
|||
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))
|
||||
atPos(mdef.pos) {
|
||||
new DefDef( // can't call DefDef here; need to find out why
|
||||
mods = mdef.mods &~ MACRO,
|
||||
name = macroMethName(mdef.symbol),
|
||||
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))
|
||||
val sym = namer.enterSyntheticSym(util.trace("macro def: ")(macroMethDef(ddef)))
|
||||
println("added to "+namer.context.owner.enclClass+": "+sym)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -783,8 +783,11 @@ trait Namers extends MethodSynthesis {
|
|||
val typedBody = defnTyper.computeType(tree.rhs, pt)
|
||||
val sym = if (owner.isMethod) owner else tree.symbol
|
||||
val typedDefn = widenIfNecessary(sym, typedBody, pt)
|
||||
|
||||
tree.tpt defineType typedDefn setPos tree.pos.focus
|
||||
assignTypeToTree(tree, typedDefn)
|
||||
}
|
||||
|
||||
private def assignTypeToTree(tree: ValOrDefDef, tpe: Type): Type = {
|
||||
tree.tpt defineType tpe setPos tree.pos.focus
|
||||
tree.tpt.tpe
|
||||
}
|
||||
|
||||
|
|
@ -1003,7 +1006,7 @@ trait Namers extends MethodSynthesis {
|
|||
if (!tpt.isEmpty) {
|
||||
typer.typedType(tpt).tpe
|
||||
} else if (meth.isMacro) {
|
||||
AnyClass.tpe
|
||||
assignTypeToTree(ddef, AnyClass.tpe)
|
||||
} else {
|
||||
// replace deSkolemized symbols with skolemized ones
|
||||
// (for resultPt computed by looking at overridden symbol, right?)
|
||||
|
|
|
|||
|
|
@ -1225,6 +1225,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
|
|||
List(tree1)
|
||||
}
|
||||
case Import(_, _) => Nil
|
||||
case DefDef(mods, _, _, _, _, _) if (mods hasFlag MACRO) => Nil
|
||||
case _ => List(transform(tree))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1676,7 +1676,6 @@ 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)
|
||||
|
|
@ -1712,6 +1711,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
|
|||
meth.owner.isAnonOrRefinementClass))
|
||||
error(ddef.pos, "constructor definition not allowed here")
|
||||
typed(ddef.rhs)
|
||||
} else if (meth.isMacro) {
|
||||
EmptyTree
|
||||
} else {
|
||||
transformedOrTyped(ddef.rhs, EXPRmode, tpt1.tpe)
|
||||
}
|
||||
|
|
@ -3444,7 +3445,7 @@ 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 if (fun2.hasSymbol && fun2.symbol.isMacro)
|
||||
} else if ((mode & FUNmode) == 0 && fun2.hasSymbol && fun2.symbol.isMacro)
|
||||
typed1(macroExpand(res), mode, pt)
|
||||
else
|
||||
res
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
-Xexperimental
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
object Test {
|
||||
|
||||
class C {
|
||||
def macro foo[T](xs: List[T]): T = (T, xs) match {
|
||||
case (t1: glob.Type, t2: glob.Tree) => t2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue