diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2014-01-29 18:15:31 +0300 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2014-02-14 14:19:44 +0100 |
commit | 2c05f0139758613fbe26a5c03d60a9da29f2f5e5 (patch) | |
tree | 7c64843ff5137539172fee6106282b8b7bda94e9 /src | |
parent | 0268e03cb461b0c7e8ae2082894988395fc0994a (diff) | |
download | scala-2c05f0139758613fbe26a5c03d60a9da29f2f5e5.tar.gz scala-2c05f0139758613fbe26a5c03d60a9da29f2f5e5.tar.bz2 scala-2c05f0139758613fbe26a5c03d60a9da29f2f5e5.zip |
SI-6814 adds typechecker modes to c.typecheck
As per multiple user requests, this commit introduces a shortcut
to typecheck trees under multiple different modes: terms (EXPRmode,
was exposed in Scala 2.10) and types (TYPEmode).
Looking into the rest of a dozen of internal typechecker modes, to the
best of my knowledge, I can’t find other modes that we could expose.
FUNmode is useful, but very situational. PATTERNmode is useful, but
also situational, because we don’t expand macros inside patterns
except for whitebox extractor macros. The rest (e.g. POLYmode or TAPPmode)
are too low-level.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/reflect/macros/contexts/Typers.scala | 11 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/ToolBox.scala | 28 | ||||
-rw-r--r-- | src/compiler/scala/tools/reflect/ToolBoxFactory.scala | 13 | ||||
-rw-r--r-- | src/reflect/scala/reflect/macros/Typers.scala | 34 |
4 files changed, 69 insertions, 17 deletions
diff --git a/src/compiler/scala/reflect/macros/contexts/Typers.scala b/src/compiler/scala/reflect/macros/contexts/Typers.scala index c1ab17027f..0c3881fdcf 100644 --- a/src/compiler/scala/reflect/macros/contexts/Typers.scala +++ b/src/compiler/scala/reflect/macros/contexts/Typers.scala @@ -1,8 +1,6 @@ package scala.reflect.macros package contexts -import scala.reflect.internal.Mode - trait Typers { self: Context => @@ -10,10 +8,15 @@ trait Typers { def openImplicits: List[ImplicitCandidate] = callsiteTyper.context.openImplicits.map(_.toImplicitCandidate) + type TypecheckMode = scala.reflect.internal.Mode + val TypecheckMode = scala.reflect.internal.Mode + val TERMmode = TypecheckMode.EXPRmode + val TYPEmode = TypecheckMode.TYPEmode | TypecheckMode.FUNmode + /** * @see [[scala.tools.reflect.ToolBox.typeCheck]] */ - def typecheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { + def typecheck(tree: Tree, mode: TypecheckMode = TERMmode, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { macroLogVerbose("typechecking %s with expected type %s, implicit views = %s, macros = %s".format(tree, pt, !withImplicitViewsDisabled, !withMacrosDisabled)) val context = callsiteTyper.context val wrapper1 = if (!withImplicitViewsDisabled) (context.withImplicitsEnabled[Tree] _) else (context.withImplicitsDisabled[Tree] _) @@ -24,7 +27,7 @@ trait Typers { // typechecking uses silent anyways (e.g. in typedSelect), so you'll only waste your time // I'd advise fixing the root cause: finding why the context is not set to report errors // (also see reflect.runtime.ToolBoxes.typeCheckExpr for a workaround that might work for you) - wrapper(callsiteTyper.silent(_.typed(universe.duplicateAndKeepPositions(tree), pt), reportAmbiguousErrors = false) match { + wrapper(callsiteTyper.silent(_.typed(universe.duplicateAndKeepPositions(tree), mode, pt), reportAmbiguousErrors = false) match { case universe.analyzer.SilentResultValue(result) => macroLogVerbose(result) result diff --git a/src/compiler/scala/tools/reflect/ToolBox.scala b/src/compiler/scala/tools/reflect/ToolBox.scala index 4a3db09909..f47db49718 100644 --- a/src/compiler/scala/tools/reflect/ToolBox.scala +++ b/src/compiler/scala/tools/reflect/ToolBox.scala @@ -21,19 +21,35 @@ trait ToolBox[U <: scala.reflect.api.Universe] { */ def frontEnd: FrontEnd + /** Represents mode of operations of the typechecker underlying `c.typecheck` calls. + * Is necessary since the shape of the typechecked tree alone is not enough to guess how it should be typechecked. + * Can be EXPRmode (typecheck as a term) or TYPEmode (typecheck as a type). + */ + type TypecheckMode + + /** Indicates that an argument to `c.typecheck` should be typechecked as a term. + * This is the default typechecking mode in Scala 2.11 and the only one supported in Scala 2.10. + */ + val TERMmode: TypecheckMode + + /** Indicates that an argument to `c.typecheck` should be typechecked as a type. + */ + val TYPEmode: TypecheckMode + /** @see `Typers.typecheck` */ @deprecated("Use `tb.typecheck` instead", "2.11.0") def typeCheck(tree: u.Tree, pt: u.Type = u.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = - typecheck(tree, pt, silent, withImplicitViewsDisabled, withMacrosDisabled) + typecheck(tree, TERMmode, pt, silent, withImplicitViewsDisabled, withMacrosDisabled) - /** Typechecks a tree using this ToolBox. + /** Typechecks a tree against the expected type `pt` + * under typechecking mode specified in `mode` with [[EXPRmode]] being default. * This populates symbols and types of the tree and possibly transforms it to reflect certain desugarings. * * If the tree has unresolved type variables (represented as instances of `FreeTypeSymbol` symbols), * then they all have to be resolved first using `Tree.substituteTypes`, or an error occurs. * - * If `silent` is false, `TypeError` will be thrown in case of a typecheck error. + * If `silent` is false, `ToolBoxError` will be thrown in case of a typecheck error. * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. * Such errors don't vanish and can be inspected by turning on -Ydebug. * @@ -41,7 +57,7 @@ trait ToolBox[U <: scala.reflect.api.Universe] { * `withImplicitViewsDisabled` recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false * `withMacrosDisabled` recursively prohibits macro expansions and macro-based implicits, default value is false */ - def typecheck(tree: u.Tree, pt: u.Type = u.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree + def typecheck(tree: u.Tree, mode: TypecheckMode = TERMmode, pt: u.Type = u.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree /** Infers an implicit value of the expected type `pt` in top-level context. * Optional `pos` parameter provides a position that will be associated with the implicit search. @@ -50,7 +66,7 @@ trait ToolBox[U <: scala.reflect.api.Universe] { * this API won't take into account the lexical context of the callsite, because * currently it's impossible to reify it. * - * If `silent` is false, `TypeError` will be thrown in case of an inference error. + * If `silent` is false, `ToolBoxError` will be thrown in case of an inference error. * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. * Unlike in `typecheck`, `silent` is true by default. @@ -64,7 +80,7 @@ trait ToolBox[U <: scala.reflect.api.Universe] { * this API won't take into account the lexical context of the callsite, because * currently it's impossible to reify it. * - * If `silent` is false, `TypeError` will be thrown in case of an inference error. + * If `silent` is false, `ToolBoxError` will be thrown in case of an inference error. * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. * Such errors don't vanish and can be inspected by turning on -Xlog-implicits. * Unlike in `typecheck`, `silent` is true by default. diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 7bae3203c2..b43b4653eb 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -171,11 +171,11 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => unwrapped } - def typecheck(expr: Tree, pt: Type, silent: Boolean, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): Tree = + def typecheck(expr: Tree, pt: Type, mode: scala.reflect.internal.Mode, silent: Boolean, withImplicitViewsDisabled: Boolean, withMacrosDisabled: Boolean): Tree = transformDuringTyper(expr, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)( (currentTyper, expr) => { trace("typing (implicit views = %s, macros = %s): ".format(!withImplicitViewsDisabled, !withMacrosDisabled))(showAttributed(expr, true, true, settings.Yshowsymkinds.value)) - currentTyper.silent(_.typed(expr, pt), reportAmbiguousErrors = false) match { + currentTyper.silent(_.typed(expr, mode, pt), reportAmbiguousErrors = false) match { case analyzer.SilentResultValue(result) => trace("success: ")(showAttributed(result, true, true, settings.Yshowsymkinds.value)) result @@ -361,7 +361,12 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => } } - def typecheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = withCompilerApi { compilerApi => + type TypecheckMode = scala.reflect.internal.Mode + val TypecheckMode = scala.reflect.internal.Mode + val TERMmode = TypecheckMode.EXPRmode + val TYPEmode = TypecheckMode.TYPEmode | TypecheckMode.FUNmode + + def typecheck(tree: u.Tree, mode: TypecheckMode = TERMmode, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = withCompilerApi { compilerApi => import compilerApi._ if (compiler.settings.verbose) println("importing "+tree+", expectedType = "+expectedType) @@ -369,7 +374,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => val cexpectedType: compiler.Type = importer.importType(expectedType) if (compiler.settings.verbose) println("typing "+ctree+", expectedType = "+expectedType) - val ttree: compiler.Tree = compiler.typecheck(ctree, cexpectedType, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled) + val ttree: compiler.Tree = compiler.typecheck(ctree, cexpectedType, mode, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled) val uttree = exporter.importTree(ttree) uttree } diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala index 6c077de1d2..f1d8575774 100644 --- a/src/reflect/scala/reflect/macros/Typers.scala +++ b/src/reflect/scala/reflect/macros/Typers.scala @@ -2,6 +2,8 @@ package scala package reflect package macros +import scala.reflect.internal.{Mode => InternalMode} + /** * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span> * @@ -23,13 +25,39 @@ trait Typers { */ def openMacros: List[blackbox.Context] + /** Represents mode of operations of the typechecker underlying `c.typecheck` calls. + * Is necessary since the shape of the typechecked tree alone is not enough to guess how it should be typechecked. + * Can be EXPRmode (typecheck as a term) or TYPEmode (typecheck as a type). + */ + // I'd very much like to make use of https://github.com/dsl-paradise/dsl-paradise here! + type TypecheckMode + + /** Indicates that an argument to `c.typecheck` should be typechecked as a term. + * This is the default typechecking mode in Scala 2.11 and the only one supported in Scala 2.10. + */ + val TERMmode: TypecheckMode + + /** Indicates that an argument to `c.typecheck` should be typechecked as a type. + */ + val TYPEmode: TypecheckMode + + /** @see `scala.reflect.macros.TypecheckException` + */ + type TypecheckException = scala.reflect.macros.TypecheckException + + /** @see `scala.reflect.macros.TypecheckException` + */ + val TypecheckException = scala.reflect.macros.TypecheckException + /** @see `Typers.typecheck` */ @deprecated("Use `c.typecheck` instead", "2.11.0") def typeCheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = - typecheck(tree, pt, silent, withImplicitViewsDisabled, withMacrosDisabled) + typecheck(tree, TERMmode, pt, silent, withImplicitViewsDisabled, withMacrosDisabled) - /** Typechecks the provided tree against the expected type `pt` in the macro callsite context. + /** Typechecks the provided tree against the expected type `pt` in the macro callsite context + * under typechecking mode specified in `mode` with [[EXPRmode]] being default. + * This populates symbols and types of the tree and possibly transforms it to reflect certain desugarings. * * If `silent` is false, `TypecheckException` will be thrown in case of a typecheck error. * If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs. @@ -42,7 +70,7 @@ trait Typers { * * @throws [[scala.reflect.macros.TypecheckException]] */ - def typecheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree + def typecheck(tree: Tree, mode: TypecheckMode = TERMmode, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree /** Infers an implicit value of the expected type `pt` in the macro callsite context. * Optional `pos` parameter provides a position that will be associated with the implicit search. |