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:
odersky 2011-11-28 13:55:31 +00:00
parent 4254a02bb9
commit e5b9ceba71
7 changed files with 40 additions and 21 deletions

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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?)

View File

@ -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))
}

View File

@ -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

View File

@ -0,0 +1 @@
-Xexperimental

View File

@ -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
}
}
}