Skip to content

Commit dec2e3a

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

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

@@ -1098,8 +1099,8 @@ object Parsers {
10981099
* | Expr
10991100
* BlockResult ::= [FunArgMods] FunParams =>' Block
11001101
* | Expr1
1101-
* Expr1 ::= [‘inline’] `if' `(' Expr `)' {nl} Expr [[semi] else Expr]
1102-
* | [‘inline’] `if' Expr `then' Expr [[semi] else Expr]
1102+
* Expr1 ::= `if' `(' Expr `)' {nl} Expr [[semi] else Expr]
1103+
* | `if' Expr `then' Expr [[semi] else Expr]
11031104
* | `while' `(' Expr `)' {nl} Expr
11041105
* | `while' Expr `do' Expr
11051106
* | `do' Expr [semi] `while' Expr
@@ -1127,7 +1128,8 @@ object Parsers {
11271128
val start = in.offset
11281129
if (in.token == IMPLICIT || in.token == ERASED) {
11291130
val imods = modifiers(funArgMods)
1130-
implicitClosure(start, location, imods)
1131+
if (in.token == MATCH) implicitMatch(start, imods)
1132+
else implicitClosure(start, location, imods)
11311133
} else {
11321134
val saved = placeholderParams
11331135
placeholderParams = Nil
@@ -1207,7 +1209,13 @@ object Parsers {
12071209
case FOR =>
12081210
forExpr()
12091211
case _ =>
1210-
expr1Rest(postfixExpr(), location)
1212+
if (isIdent(nme.INLINEkw)) {
1213+
val start = in.skipToken()
1214+
val t = postfixExpr()
1215+
accept(MATCH)
1216+
matchExpr(t, start, MatchKind.Inline)
1217+
}
1218+
else expr1Rest(postfixExpr(), location)
12111219
}
12121220

12131221
def expr1Rest(t: Tree, location: Location.Value): Tree = in.token match {
@@ -1221,7 +1229,7 @@ object Parsers {
12211229
case COLON =>
12221230
ascription(t, location)
12231231
case MATCH =>
1224-
matchExpr(t, startOffset(t))
1232+
matchExpr(t, startOffset(t), MatchKind.Regular)
12251233
case _ =>
12261234
t
12271235
}
@@ -1266,12 +1274,34 @@ object Parsers {
12661274
}
12671275

12681276
/** `match' { CaseClauses }
1269-
* `match' { ImplicitCaseClauses }
12701277
*/
1271-
def matchExpr(t: Tree, start: Offset): Match =
1278+
def matchExpr(t: Tree, start: Offset, kind: MatchKind): Match =
12721279
atPos(start, in.skipToken()) {
1273-
inBraces(Match(t, caseClauses(caseClause)))
1280+
inBraces(Match(t, caseClauses(caseClause), kind))
1281+
}
1282+
1283+
/** `match' { ImplicitCaseClauses }
1284+
*/
1285+
def implicitMatch(start: Int, imods: Modifiers) = {
1286+
def markFirstIllegal(mods: List[Mod]) = mods match {
1287+
case mod :: _ => syntaxError(em"illegal modifier for implicit match", mod.pos)
1288+
case _ =>
12741289
}
1290+
imods.mods match {
1291+
case Mod.Implicit() :: mods => markFirstIllegal(mods)
1292+
case mods => markFirstIllegal(mods)
1293+
}
1294+
val result @ Match(t, cases) = matchExpr(EmptyTree, start, MatchKind.Implicit)
1295+
for (CaseDef(pat, _, _) <- cases) {
1296+
def isImplicitPattern(pat: Tree) = pat match {
1297+
case Typed(pat1, _) => isVarPattern(pat1)
1298+
case pat => isVarPattern(pat)
1299+
}
1300+
if (!isImplicitPattern(pat))
1301+
syntaxError(em"not a legal pattern for an implicit match", pat.pos)
1302+
}
1303+
result
1304+
}
12751305

12761306
/** `match' { TypeCaseClauses }
12771307
*/
@@ -2620,6 +2650,8 @@ object Parsers {
26202650
var imods = modifiers(funArgMods)
26212651
if (isBindingIntro)
26222652
stats += implicitClosure(start, Location.InBlock, imods)
2653+
else if (in.token == MATCH)
2654+
stats += implicitMatch(start, imods)
26232655
else
26242656
stats +++= localDef(start, imods)
26252657
} 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)