From f69d3e34dd165eb0f3242fcba3e6bbdc3d61e5d1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 28 Nov 2011 13:55:31 +0000 Subject: Revised macro defs, added a test case. --- src/compiler/scala/reflect/internal/Flags.scala | 4 +-- .../scala/tools/nsc/typechecker/Macros.scala | 29 ++++++++++++---------- .../scala/tools/nsc/typechecker/Namers.scala | 7 ++++-- .../scala/tools/nsc/typechecker/RefChecks.scala | 1 + .../scala/tools/nsc/typechecker/Typers.scala | 5 ++-- 5 files changed, 27 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala index 50d5b5cb82..b95042341a 100644 --- a/src/compiler/scala/reflect/internal/Flags.scala +++ b/src/compiler/scala/reflect/internal/Flags.scala @@ -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 => "" // (1L << 12) case PARAM => "" // (1L << 13) case PACKAGE => "" // (1L << 14) - case 0x8000L => "" // (1L << 15) + case MACRO => "macro" // (1L << 15) case BYNAMEPARAM => "" // (1L << 16) case CONTRAVARIANT => "" // (1L << 17) case ABSOVERRIDE => "absoverride" // (1L << 18) diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 05eadb03ae..d0640e76af 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -7,13 +7,14 @@ 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)) } /** @@ -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) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 4c85830311..0f57285480 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -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) + assignTypeToTree(tree, typedDefn) + } - tree.tpt defineType typedDefn setPos tree.pos.focus + 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?) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 66a7f90f0a..645d3ecfa0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -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)) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index f9c056e16d..b969e9629f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -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 -- cgit v1.2.3