summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-11-28 11:01:12 +0000
committerMartin Odersky <odersky@gmail.com>2011-11-28 11:01:12 +0000
commit311d813910a2ec590b11b84c28fac2ae6e086270 (patch)
tree4a35454e77a8d09d822a7b7c3126b10c7c3861bb /src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
parent0bea2ab5f6b211a83bbf14ea46fe57b8163c6334 (diff)
downloadscala-311d813910a2ec590b11b84c28fac2ae6e086270.tar.gz
scala-311d813910a2ec590b11b84c28fac2ae6e086270.tar.bz2
scala-311d813910a2ec590b11b84c28fac2ae6e086270.zip
Experimental version of macro definitions.
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/Parsers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala89
1 files changed, 53 insertions, 36 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index cfe8716d9f..e27d5cacda 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -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,36 +2427,47 @@ 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
* | ConstrBlock
@@ -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
+ }
}
}
}