Skip to content

Commit 296f048

Browse files
committed
Make inline a soft keyword
Analogous to `&` and `|`, treat `inline` as an identifier but intrepret it specially if it appears in places where it influences the syntax. This allows us to keep `@inline` as an annotation.
1 parent d83491a commit 296f048

File tree

2 files changed

+33
-35
lines changed

2 files changed

+33
-35
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ object Parsers {
169169
def isSimpleLiteral = simpleLiteralTokens contains in.token
170170
def isLiteral = literalTokens contains in.token
171171
def isNumericLit = numericLitTokens contains in.token
172-
def isModifier = modifierTokens contains in.token
172+
def isModifier = modifierTokens.contains(in.token) || isIdent(nme.INLINEkw)
173173
def isBindingIntro = canStartBindingTokens contains in.token
174174
def isTemplateIntro = templateIntroTokens contains in.token
175175
def isDclIntro = dclIntroTokens contains in.token
@@ -178,13 +178,13 @@ object Parsers {
178178

179179
def isExprIntro =
180180
(canStartExpressionTokens `contains` in.token) &&
181-
(in.token != INLINE || lookaheadIn(canStartExpressionTokens))
181+
(!isIdent(nme.INLINEkw) || lookaheadIn(canStartExpressionTokens))
182182

183183
def isDefIntro(allowedMods: BitSet) =
184184
in.token == AT ||
185185
(defIntroTokens `contains` in.token) ||
186-
(allowedMods `contains` in.token) &&
187-
(in.token != INLINE || lookaheadIn(BitSet(AT) | defIntroTokens | allowedMods))
186+
(allowedMods `contains` in.token) ||
187+
isIdent(nme.INLINEkw) && lookaheadIn(BitSet(AT) | defIntroTokens | allowedMods)
188188

189189
def isStatSep: Boolean =
190190
in.token == NEWLINE || in.token == NEWLINES || in.token == SEMI
@@ -461,7 +461,8 @@ object Parsers {
461461
/** Is the token following the current one in `tokens`? */
462462
def lookaheadIn(tokens: BitSet): Boolean = {
463463
val lookahead = in.lookaheadScanner
464-
lookahead.nextToken()
464+
do lookahead.nextToken()
465+
while (lookahead.token == NEWLINE || lookahead.token == NEWLINES)
465466
tokens.contains(lookahead.token)
466467
}
467468

@@ -1212,21 +1213,22 @@ object Parsers {
12121213
atPos(in.skipToken()) { Return(if (isExprIntro) expr() else EmptyTree, EmptyTree) }
12131214
case FOR =>
12141215
forExpr()
1215-
case INLINE =>
1216-
val start = in.skipToken()
1217-
in.token match {
1218-
case IF =>
1219-
ifExpr(start, InlineIf)
1220-
case _ =>
1221-
val t = postfixExpr()
1222-
if (in.token == MATCH) matchExpr(t, start, InlineMatch)
1223-
else {
1224-
syntaxErrorOrIncomplete("`match` or `if` expected but ${in.token} found")
1225-
t
1226-
}
1227-
}
12281216
case _ =>
1229-
expr1Rest(postfixExpr(), location)
1217+
if (isIdent(nme.INLINEkw)) {
1218+
val start = in.skipToken()
1219+
in.token match {
1220+
case IF =>
1221+
ifExpr(start, InlineIf)
1222+
case _ =>
1223+
val t = postfixExpr()
1224+
if (in.token == MATCH) matchExpr(t, start, InlineMatch)
1225+
else {
1226+
syntaxErrorOrIncomplete("`match` or `if` expected but ${in.token} found")
1227+
t
1228+
}
1229+
}
1230+
}
1231+
else expr1Rest(postfixExpr(), location)
12301232
}
12311233

12321234
def expr1Rest(t: Tree, location: Location.Value) = in.token match {
@@ -1771,18 +1773,18 @@ object Parsers {
17711773

17721774
/* -------- MODIFIERS and ANNOTATIONS ------------------------------------------- */
17731775

1774-
private def modOfToken(tok: Int): Mod = tok match {
1776+
private def modOfToken(tok: Int, name: Name): Mod = tok match {
17751777
case ABSTRACT => Mod.Abstract()
17761778
case FINAL => Mod.Final()
17771779
case IMPLICIT => Mod.Implicit()
17781780
case ERASED => Mod.Erased()
1779-
case INLINE => Mod.Inline()
17801781
case TRANSPARENT => Mod.Transparent()
17811782
case LAZY => Mod.Lazy()
17821783
case OVERRIDE => Mod.Override()
17831784
case PRIVATE => Mod.Private()
17841785
case PROTECTED => Mod.Protected()
17851786
case SEALED => Mod.Sealed()
1787+
case IDENTIFIER if name == nme.INLINEkw => Mod.Inline()
17861788
}
17871789

17881790
/** Drop `private' modifier when followed by a qualifier.
@@ -1798,7 +1800,8 @@ object Parsers {
17981800

17991801
private def addModifier(mods: Modifiers): Modifiers = {
18001802
val tok = in.token
1801-
val mod = atPos(in.skipToken()) { modOfToken(tok) }
1803+
val name = in.name
1804+
val mod = atPos(in.skipToken()) { modOfToken(tok, name) }
18021805

18031806
if (mods is mod.flags) syntaxError(RepeatedModifier(mod.flags.toString))
18041807
addMod(mods, mod)
@@ -1846,12 +1849,13 @@ object Parsers {
18461849
* Modifier ::= LocalModifier
18471850
* | AccessModifier
18481851
* | override
1849-
* LocalModifier ::= abstract | final | sealed | implicit | lazy
1852+
* LocalModifier ::= abstract | final | sealed | implicit | lazy | erased | inline
18501853
*/
18511854
def modifiers(allowed: BitSet = modifierTokens, start: Modifiers = Modifiers()): Modifiers = {
18521855
@tailrec
18531856
def loop(mods: Modifiers): Modifiers = {
1854-
if (allowed contains in.token) {
1857+
if (allowed.contains(in.token) ||
1858+
isIdent(nme.INLINEkw) && localModifierTokens.subsetOf(allowed)) {
18551859
val isAccessMod = accessModifierTokens contains in.token
18561860
val mods1 = addModifier(mods)
18571861
loop(if (isAccessMod) accessQualifierOpt(mods1) else mods1)
@@ -1888,10 +1892,7 @@ object Parsers {
18881892
*/
18891893
def annot() =
18901894
adjustStart(accept(AT)) {
1891-
val tpe =
1892-
if (in.token == INLINE) atPos(in.skipToken()) { BackquotedIdent(tpnme.INLINEkw) }
1893-
else simpleType()
1894-
ensureApplied(parArgumentExprss(wrapNew(tpe)))
1895+
ensureApplied(parArgumentExprss(wrapNew(simpleType())))
18951896
}
18961897

18971898
def annotations(skipNewLines: Boolean = false): List[Tree] = {
@@ -2648,7 +2649,7 @@ object Parsers {
26482649
if (in.token == IMPLICIT || in.token == ERASED) {
26492650
val start = in.offset
26502651
var imods = modifiers(funArgMods)
2651-
if (isBindingIntro)
2652+
if (isBindingIntro && !isIdent(nme.INLINEkw))
26522653
stats += implicitClosure(start, Location.InBlock, imods)
26532654
else if (in.token == MATCH)
26542655
stats += implicitMatch(start, imods)

compiler/src/dotty/tools/dotc/parsing/Tokens.scala

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ abstract class TokensCommon {
9191
//final val LAZY = 59; enter(LAZY, "lazy")
9292
//final val THEN = 60; enter(THEN, "then")
9393
//final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
94-
//final val INLINE = 62; enter(INLINE, "inline")
9594
//final val TRANSPARENT = 63; enter(TRANSPARENT, "transparent")
9695
//final val ENUM = 64; enter(ENUM, "enum")
9796
//final val ERASED = 65; enter(ERASED, "erased")
@@ -177,7 +176,6 @@ object Tokens extends TokensCommon {
177176
final val LAZY = 59; enter(LAZY, "lazy")
178177
final val THEN = 60; enter(THEN, "then")
179178
final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
180-
final val INLINE = 62; enter(INLINE, "inline")
181179
final val TRANSPARENT = 63; enter(TRANSPARENT, "transparent")
182180
final val ENUM = 64; enter(ENUM, "enum")
183181
final val ERASED = 65; enter(ERASED, "erased")
@@ -215,7 +213,7 @@ object Tokens extends TokensCommon {
215213
USCORE, NULL, THIS, SUPER, TRUE, FALSE, RETURN, XMLSTART)
216214

217215
final val canStartExpressionTokens = atomicExprTokens | BitSet(
218-
LBRACE, LPAREN, QBRACE, QPAREN, IF, DO, WHILE, FOR, NEW, TRY, THROW, INLINE)
216+
LBRACE, LPAREN, QBRACE, QPAREN, IF, DO, WHILE, FOR, NEW, TRY, THROW)
219217

220218
final val canStartTypeTokens = literalTokens | identifierTokens | BitSet(
221219
THIS, SUPER, USCORE, LPAREN, AT)
@@ -229,7 +227,7 @@ object Tokens extends TokensCommon {
229227
final val defIntroTokens = templateIntroTokens | dclIntroTokens
230228

231229
final val localModifierTokens = BitSet(
232-
ABSTRACT, FINAL, SEALED, IMPLICIT, INLINE, TRANSPARENT, LAZY, ERASED)
230+
ABSTRACT, FINAL, SEALED, IMPLICIT, TRANSPARENT, LAZY, ERASED)
233231

234232
final val accessModifierTokens = BitSet(
235233
PRIVATE, PROTECTED)
@@ -240,8 +238,7 @@ object Tokens extends TokensCommon {
240238
final val modifierTokensOrCase = modifierTokens | BitSet(CASE)
241239

242240
/** Is token only legal as start of statement (eof also included)? */
243-
final val mustStartStatTokens = defIntroTokens | (modifierTokens - INLINE) | BitSet(
244-
IMPORT, PACKAGE)
241+
final val mustStartStatTokens = defIntroTokens | modifierTokens | BitSet(IMPORT, PACKAGE)
245242

246243
final val canStartStatTokens = canStartExpressionTokens | mustStartStatTokens | BitSet(
247244
AT, CASE)

0 commit comments

Comments
 (0)