Skip to content

Commit df38e1c

Browse files
committed
Parse inline and implicit matches
Just syntax and parsing, no interpretation yet.
1 parent a5db7f7 commit df38e1c

File tree

4 files changed

+53
-10
lines changed

4 files changed

+53
-10
lines changed

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

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import StdNames._
2020
import util.Positions._
2121
import Constants._
2222
import ScriptParsers._
23+
import Decorators._
2324
import scala.annotation.{tailrec, switch}
2425
import rewrites.Rewrites.patch
2526

@@ -1101,8 +1102,8 @@ object Parsers {
11011102
* | Expr
11021103
* BlockResult ::= [FunArgMods] FunParams =>' Block
11031104
* | Expr1
1104-
* Expr1 ::= [‘inline’] `if' `(' Expr `)' {nl} Expr [[semi] else Expr]
1105-
* | [‘inline’] `if' Expr `then' Expr [[semi] else Expr]
1105+
* Expr1 ::= `if' `(' Expr `)' {nl} Expr [[semi] else Expr]
1106+
* | `if' Expr `then' Expr [[semi] else Expr]
11061107
* | `while' `(' Expr `)' {nl} Expr
11071108
* | `while' Expr `do' Expr
11081109
* | `do' Expr [semi] `while' Expr
@@ -1130,7 +1131,8 @@ object Parsers {
11301131
val start = in.offset
11311132
if (in.token == IMPLICIT || in.token == ERASED) {
11321133
val imods = modifiers(funArgMods)
1133-
implicitClosure(start, location, imods)
1134+
if (in.token == MATCH) implicitMatch(start, imods)
1135+
else implicitClosure(start, location, imods)
11341136
} else {
11351137
val saved = placeholderParams
11361138
placeholderParams = Nil
@@ -1210,7 +1212,13 @@ object Parsers {
12101212
case FOR =>
12111213
forExpr()
12121214
case _ =>
1213-
expr1Rest(postfixExpr(), location)
1215+
if (isIdent(nme.INLINEkw)) {
1216+
val start = in.skipToken()
1217+
val t = postfixExpr()
1218+
accept(MATCH)
1219+
matchExpr(t, start, MatchKind.Inline)
1220+
}
1221+
else expr1Rest(postfixExpr(), location)
12141222
}
12151223

12161224
def expr1Rest(t: Tree, location: Location.Value): Tree = in.token match {
@@ -1224,7 +1232,7 @@ object Parsers {
12241232
case COLON =>
12251233
ascription(t, location)
12261234
case MATCH =>
1227-
matchExpr(t, startOffset(t))
1235+
matchExpr(t, startOffset(t), MatchKind.Regular)
12281236
case _ =>
12291237
t
12301238
}
@@ -1269,12 +1277,34 @@ object Parsers {
12691277
}
12701278

12711279
/** `match' { CaseClauses }
1272-
* `match' { ImplicitCaseClauses }
12731280
*/
1274-
def matchExpr(t: Tree, start: Offset): Match =
1281+
def matchExpr(t: Tree, start: Offset, kind: MatchKind): Match =
12751282
atPos(start, in.skipToken()) {
1276-
inBraces(Match(t, caseClauses(caseClause)))
1283+
inBraces(Match(t, caseClauses(caseClause), kind))
1284+
}
1285+
1286+
/** `match' { ImplicitCaseClauses }
1287+
*/
1288+
def implicitMatch(start: Int, imods: Modifiers) = {
1289+
def markFirstIllegal(mods: List[Mod]) = mods match {
1290+
case mod :: _ => syntaxError(em"illegal modifier for implicit match", mod.pos)
1291+
case _ =>
12771292
}
1293+
imods.mods match {
1294+
case Mod.Implicit() :: mods => markFirstIllegal(mods)
1295+
case mods => markFirstIllegal(mods)
1296+
}
1297+
val result @ Match(t, cases) = matchExpr(EmptyTree, start, MatchKind.Implicit)
1298+
for (CaseDef(pat, _, _) <- cases) {
1299+
def isImplicitPattern(pat: Tree) = pat match {
1300+
case Typed(pat1, _) => isVarPattern(pat1)
1301+
case pat => isVarPattern(pat)
1302+
}
1303+
if (!isImplicitPattern(pat))
1304+
syntaxError(em"not a legal pattern for an implicit match", pat.pos)
1305+
}
1306+
result
1307+
}
12781308

12791309
/** `match' { TypeCaseClauses }
12801310
*/
@@ -2617,6 +2647,8 @@ object Parsers {
26172647
var imods = modifiers(funArgMods)
26182648
if (isBindingIntro && !isIdent(nme.INLINEkw))
26192649
stats += implicitClosure(start, Location.InBlock, imods)
2650+
else if (in.token == MATCH)
2651+
stats += implicitMatch(start, imods)
26202652
else
26212653
stats +++= localDef(start, imods)
26222654
} else {

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,8 @@ class Typer extends Namer
564564
def typedTpt = checkSimpleKinded(typedType(tree.tpt))
565565
def handlePattern: Tree = {
566566
val tpt1 = typedTpt
567-
if (!ctx.isAfterTyper) constrainPatternType(tpt1.tpe, pt)(ctx.addMode(Mode.GADTflexible))
567+
if (!ctx.isAfterTyper /* && pt != defn.ImplicitScrutineeTypeRef @@@ */)
568+
constrainPatternType(tpt1.tpe, pt)(ctx.addMode(Mode.GADTflexible))
568569
// special case for an abstract type that comes with a class tag
569570
tryWithClassTag(ascription(tpt1, isWildcard = true), pt)
570571
}
@@ -970,6 +971,11 @@ class Typer extends Namer
970971
val (protoFormals, _) = decomposeProtoFunction(pt, 1)
971972
val unchecked = pt.isRef(defn.PartialFunctionClass)
972973
typed(desugar.makeCaseLambda(tree.cases, protoFormals.length, unchecked) withPos tree.pos, pt)
974+
/* @@@ case id @ untpd.ImplicitScrutinee() =>
975+
checkInInlineContext("implicit match", tree.pos)
976+
val sel1 = id.withType(defn.ImplicitScrutineeTypeRef)
977+
typedMatchFinish(tree, sel1, sel1.tpe, pt)
978+
*/
973979
case _ =>
974980
val sel1 = typedExpr(tree.selector)
975981
val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.pos).widen
@@ -1378,6 +1384,7 @@ class Typer extends Namer
13781384
if (body1.tpe.isInstanceOf[TermRef]) pt1
13791385
else body1.tpe.underlyingIfRepeated(isJava = false)
13801386
val sym = ctx.newPatternBoundSymbol(tree.name, symTp, tree.pos)
1387+
// @@@ if (pt == defn.ImplicitScrutineeTypeRef) sym.setFlag(Implicit)
13811388
if (ctx.mode.is(Mode.InPatternAlternative))
13821389
ctx.error(i"Illegal variable ${sym.name} in pattern alternative", tree.pos)
13831390
assignType(cpy.Bind(tree)(tree.name, body1), sym)

compiler/test/dotc/run-test-pickling.blacklist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ t8133
88
t8133b
99
tuples1.scala
1010
tuples1a.scala
11+
implicitMatch.scala

docs/docs/internals/syntax.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ Expr1 ::= ‘if’ ‘(’ Expr ‘)’ {nl}
177177
| [SimpleExpr ‘.’] id ‘=’ Expr Assign(expr, expr)
178178
| SimpleExpr1 ArgumentExprs ‘=’ Expr Assign(expr, expr)
179179
| PostfixExpr [Ascription]
180-
| PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’ Match(expr, cases) -- point on match
180+
| [‘inline’] PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’ Match(expr, cases) -- point on match
181+
| ‘implicit’ ‘match’ ‘{’ ImplicitCaseClauses ‘}’
181182
Ascription ::= ‘:’ InfixType Typed(expr, tp)
182183
| ‘:’ Annotation {Annotation} Typed(expr, Annotated(EmptyTree, annot)*)
183184
Catches ::= ‘catch’ Expr
@@ -226,6 +227,8 @@ Guard ::= ‘if’ PostfixExpr
226227
227228
CaseClauses ::= CaseClause { CaseClause } Match(EmptyTree, cases)
228229
CaseClause ::= ‘case’ (Pattern [Guard] ‘=>’ Block | INT) CaseDef(pat, guard?, block) // block starts at =>
230+
ImplicitCaseClauses ::= ImplicitCaseClause { ImplicitCaseClause }
231+
ImplicitCaseClause ::= ‘case’ PatVar [‘:’ RefinedType] [Guard] ‘=>’ Block
229232
TypeCaseClauses ::= TypeCaseClause { TypeCaseClause }
230233
TypeCaseClause ::= ‘case’ InfixType ‘=>’ Type [nl]
231234

0 commit comments

Comments
 (0)