aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-09-10 20:58:34 +0200
committerMartin Odersky <odersky@gmail.com>2016-10-02 16:11:21 +0200
commitd575e585389b025d7b8056bcb43fea67dddd15d0 (patch)
tree657453c9e17f109e29ead11d52807d1e335930ae /src/dotty/tools/dotc
parente93b7bfe770c8950a52d17bb0aebd3e0a5e93b3c (diff)
downloaddotty-d575e585389b025d7b8056bcb43fea67dddd15d0.tar.gz
dotty-d575e585389b025d7b8056bcb43fea67dddd15d0.tar.bz2
dotty-d575e585389b025d7b8056bcb43fea67dddd15d0.zip
Make inline a keyword
`inline` is now a modifier keyword. To keep disruption tolerable, we still allow `@inline` as an annotation as well. Other uses of `inline` are supported only under `-language:Scala2` and are rewritten to identifiers in backticks.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/config/ScalaSettings.scala1
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala5
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala1
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala19
-rw-r--r--src/dotty/tools/dotc/parsing/Scanners.scala29
-rw-r--r--src/dotty/tools/dotc/parsing/Tokens.scala6
-rw-r--r--src/dotty/tools/dotc/printing/SyntaxHighlighting.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala15
8 files changed, 58 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala
index 42e761c2e..ff17a9939 100644
--- a/src/dotty/tools/dotc/config/ScalaSettings.scala
+++ b/src/dotty/tools/dotc/config/ScalaSettings.scala
@@ -121,7 +121,6 @@ class ScalaSettings extends Settings.SettingGroup {
val debugOwners = BooleanSetting("-Ydebug-owners", "Print all owners of definitions (requires -Yprint-syms)")
//val doc = BooleanSetting ("-Ydoc", "Generate documentation")
val termConflict = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error")
- val inline = BooleanSetting("-Yinline", "Perform inlining when possible.")
val inlineHandlers = BooleanSetting("-Yinline-handlers", "Perform exception handler inlining when possible.")
val YinlinerWarnings = BooleanSetting("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)")
val Ylinearizer = ChoiceSetting("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 0cdae6b98..bc5953a2c 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -450,7 +450,7 @@ object Flags {
AccessFlags | Module | Package | Deferred | Final | MethodOrHKCommon | Param | ParamAccessor | Scala2ExistentialCommon |
Mutable.toCommonFlags | InSuperCall | Touched | JavaStatic | CovariantOrOuter | ContravariantOrLabel | ExpandedName | AccessorOrSealed |
CaseAccessorOrBaseTypeArg | Fresh | Frozen | Erroneous | ImplicitCommon | Permanent | Synthetic |
- LazyOrTrait | SuperAccessorOrScala2x | SelfNameOrImplClass
+ Inline | LazyOrTrait | SuperAccessorOrScala2x | SelfNameOrImplClass
assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags)
// TODO: Should check that FromStartFlags do not change in completion
@@ -541,6 +541,9 @@ object Flags {
/** A type parameter with synthesized name */
final val ExpandedTypeParam = allOf(ExpandedName, TypeParam)
+ /** An inline method */
+ final val InlineMethod = allOf(Inline, Method)
+
/** A parameter or parameter accessor */
final val ParamOrAccessor = Param | ParamAccessor
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 9ef7caa68..c52264637 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -46,6 +46,7 @@ object StdNames {
final val IFkw: N = kw("if")
final val IMPLICITkw: N = kw("implicit")
final val IMPORTkw: N = kw("import")
+ final val INLINEkw: N = kw("inline")
final val LAZYkw: N = kw("lazy")
final val MACROkw: N = kw("macro")
final val MATCHkw: N = kw("match")
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 86330f3ab..2fd79f999 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -275,21 +275,12 @@ object Parsers {
} finally inFunReturnType = saved
}
- private val isScala2Mode =
- ctx.settings.language.value.contains(nme.Scala2.toString)
-
def migrationWarningOrError(msg: String, offset: Int = in.offset) =
- if (isScala2Mode)
+ if (in.isScala2Mode)
ctx.migrationWarning(msg, source atPos Position(offset))
else
syntaxError(msg, offset)
- /** Cannot use ctx.featureEnabled because accessing the context would force too much */
- private def testScala2Mode(msg: String, pos: Position = Position(in.offset)) = {
- if (isScala2Mode) ctx.migrationWarning(msg, source atPos pos)
- isScala2Mode
- }
-
/* ---------- TREE CONSTRUCTION ------------------------------------------- */
/** Convert tree to formal parameter list
@@ -1467,6 +1458,7 @@ object Parsers {
case ABSTRACT => Abstract
case FINAL => Final
case IMPLICIT => ImplicitCommon
+ case INLINE => Inline
case LAZY => Lazy
case OVERRIDE => Override
case PRIVATE => Private
@@ -1570,7 +1562,10 @@ object Parsers {
/** Annotation ::= `@' SimpleType {ParArgumentExprs}
*/
def annot() =
- adjustStart(accept(AT)) { ensureApplied(parArgumentExprss(wrapNew(simpleType()))) }
+ adjustStart(accept(AT)) {
+ if (in.token == INLINE) in.token = BACKQUOTED_IDENT // allow for now
+ ensureApplied(parArgumentExprss(wrapNew(simpleType())))
+ }
def annotations(skipNewLines: Boolean = false): List[Tree] = {
if (skipNewLines) newLineOptWhenFollowedBy(AT)
@@ -1856,7 +1851,7 @@ object Parsers {
val toInsert =
if (in.token == LBRACE) s"$resultTypeStr ="
else ": Unit " // trailing space ensures that `def f()def g()` works.
- testScala2Mode(s"Procedure syntax no longer supported; `$toInsert' should be inserted here") && {
+ in.testScala2Mode(s"Procedure syntax no longer supported; `$toInsert' should be inserted here") && {
patch(source, Position(in.lastOffset), toInsert)
true
}
diff --git a/src/dotty/tools/dotc/parsing/Scanners.scala b/src/dotty/tools/dotc/parsing/Scanners.scala
index b46ab6348..a1a21583c 100644
--- a/src/dotty/tools/dotc/parsing/Scanners.scala
+++ b/src/dotty/tools/dotc/parsing/Scanners.scala
@@ -12,7 +12,7 @@ import scala.annotation.{ switch, tailrec }
import scala.collection.mutable
import mutable.ListBuffer
import Utility.isNameStart
-
+import rewrite.Rewrites.patch
object Scanners {
@@ -108,6 +108,7 @@ object Scanners {
target.token = toToken(idx)
}
}
+
def toToken(idx: Int): Token
/** Clear buffer and set string */
@@ -212,8 +213,22 @@ object Scanners {
/** A buffer for comments */
val commentBuf = new StringBuilder
+ private def handleMigration(keyword: Token): Token =
+ if (!isScala2Mode) keyword
+ else if (keyword == INLINE) treatAsIdent()
+ else keyword
+
+
+ private def treatAsIdent() = {
+ testScala2Mode(i"$name is now a keyword, put in `...` to keep as an identifier")
+ patch(source, Position(offset), "`")
+ patch(source, Position(offset + name.length), "`")
+ IDENTIFIER
+ }
+
def toToken(idx: Int): Token =
- if (idx >= 0 && idx <= lastKeywordStart) kwArray(idx) else IDENTIFIER
+ if (idx >= 0 && idx <= lastKeywordStart) handleMigration(kwArray(idx))
+ else IDENTIFIER
private class TokenData0 extends TokenData
@@ -235,6 +250,16 @@ object Scanners {
*/
var sepRegions: List[Token] = List()
+// Scala 2 compatibility
+
+ val isScala2Mode = ctx.settings.language.value.contains(nme.Scala2.toString)
+
+ /** Cannot use ctx.featureEnabled because accessing the context would force too much */
+ def testScala2Mode(msg: String, pos: Position = Position(offset)) = {
+ if (isScala2Mode) ctx.migrationWarning(msg, source atPos pos)
+ isScala2Mode
+ }
+
// Get next token ------------------------------------------------------------
/** Are we directly in a string interpolation expression?
diff --git a/src/dotty/tools/dotc/parsing/Tokens.scala b/src/dotty/tools/dotc/parsing/Tokens.scala
index b490cd133..5324207db 100644
--- a/src/dotty/tools/dotc/parsing/Tokens.scala
+++ b/src/dotty/tools/dotc/parsing/Tokens.scala
@@ -91,6 +91,7 @@ abstract class TokensCommon {
//final val LAZY = 59; enter(LAZY, "lazy")
//final val THEN = 60; enter(THEN, "then")
//final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
+ //final val INLINE = 62; enter(INLINE, "inline")
/** special symbols */
final val COMMA = 70; enter(COMMA, "','")
@@ -171,6 +172,7 @@ object Tokens extends TokensCommon {
final val LAZY = 59; enter(LAZY, "lazy")
final val THEN = 60; enter(THEN, "then")
final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
+ final val INLINE = 62; enter(INLINE, "inline")
/** special symbols */
final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line")
@@ -188,7 +190,7 @@ object Tokens extends TokensCommon {
/** XML mode */
final val XMLSTART = 96; enter(XMLSTART, "$XMLSTART$<") // TODO: deprecate
- final val alphaKeywords = tokenRange(IF, FORSOME)
+ final val alphaKeywords = tokenRange(IF, INLINE)
final val symbolicKeywords = tokenRange(USCORE, VIEWBOUND)
final val symbolicTokens = tokenRange(COMMA, VIEWBOUND)
final val keywords = alphaKeywords | symbolicKeywords
@@ -214,7 +216,7 @@ object Tokens extends TokensCommon {
final val defIntroTokens = templateIntroTokens | dclIntroTokens
final val localModifierTokens = BitSet(
- ABSTRACT, FINAL, SEALED, IMPLICIT, LAZY)
+ ABSTRACT, FINAL, SEALED, IMPLICIT, INLINE, LAZY)
final val accessModifierTokens = BitSet(
PRIVATE, PROTECTED)
diff --git a/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala
index 67aa24243..83c428976 100644
--- a/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala
+++ b/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala
@@ -22,7 +22,7 @@ object SyntaxHighlighting {
private def annotation(str: String) = AnnotationColor + str + NoColor
private val keywords: Seq[String] = for {
- index <- IF to FORSOME // All alpha keywords
+ index <- IF to INLINE // All alpha keywords
} yield tokenString(index)
private val interpolationPrefixes =
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 5e2ff4164..a33061453 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -562,11 +562,24 @@ class Namer { typer: Typer =>
protected def addAnnotations(denot: SymDenotation): Unit = original match {
case original: untpd.MemberDef =>
+ var hasInlineAnnot = false
for (annotTree <- untpd.modsDeco(original).mods.annotations) {
val cls = typedAheadAnnotation(annotTree)
val ann = Annotation.deferred(cls, implicit ctx => typedAnnotation(annotTree))
denot.addAnnotation(ann)
- if (cls == defn.InlineAnnot) addInlineInfo(denot, original)
+ if (cls == defn.InlineAnnot) {
+ hasInlineAnnot = true
+ addInlineInfo(denot, original)
+ }
+ }
+ if (!hasInlineAnnot && denot.is(InlineMethod)) {
+ // create a @inline annotation. Currently, the inlining trigger
+ // is really the annotation, not the flag. This is done so that
+ // we can still compile inline methods from Scala2x. Once we stop
+ // being compatible with Scala2 we should revise the logic to
+ // be based on the flag. Then creating a separate annotation becomes unnecessary.
+ denot.addAnnotation(Annotation(defn.InlineAnnot))
+ addInlineInfo(denot, original)
}
case _ =>
}