Skip to content

Commit eaaeb7c

Browse files
committed
Allow curried lambdas with indented blocks
1 parent d70de9a commit eaaeb7c

File tree

5 files changed

+50
-26
lines changed

5 files changed

+50
-26
lines changed

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

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,27 +1114,32 @@ object Parsers {
11141114
lookahead.observeArrowIndented()
11151115
if lookahead.token == INDENT || lookahead.token == EOF then
11161116
Some(() => expr(Location.InColonArg))
1117-
else if in.featureEnabled(Feature.relaxedLambdaSyntax)
1118-
&& !in.currentRegion.isInstanceOf[InParens]
1119-
then
1120-
Some: () =>
1121-
val t = inSepRegion(SingleLineLambda(_)):
1122-
expr(Location.InColonArg)
1123-
accept(ENDlambda)
1124-
t
1117+
else if in.featureEnabled(Feature.relaxedLambdaSyntax) then
1118+
isParamsAndArrow() match
1119+
case success @ Some(_) => success
1120+
case _ if !in.currentRegion.isInstanceOf[InParens] =>
1121+
Some: () =>
1122+
val t = inSepRegion(SingleLineLambda(_)):
1123+
expr(Location.InColonArg)
1124+
accept(ENDlambda)
1125+
t
1126+
case _ => None
11251127
else None
11261128
else None
1127-
lookahead.nextToken()
1128-
if lookahead.isIdent || lookahead.token == USCORE then
1129+
def isParamsAndArrow(): Option[() => Tree] =
11291130
lookahead.nextToken()
1130-
isArrowIndent()
1131-
else if lookahead.token == LPAREN || lookahead.token == LBRACKET then
1132-
lookahead.skipParens()
1133-
isArrowIndent()
1134-
else if lookahead.token == CASE && in.featureEnabled(Feature.relaxedLambdaSyntax) then
1135-
Some(() => singleCaseMatch())
1136-
else
1137-
None
1131+
if lookahead.isIdent || lookahead.token == USCORE then
1132+
lookahead.nextToken()
1133+
isArrowIndent()
1134+
else if lookahead.token == LPAREN || lookahead.token == LBRACKET then
1135+
lookahead.skipParens()
1136+
isArrowIndent()
1137+
else if lookahead.token == CASE && in.featureEnabled(Feature.relaxedLambdaSyntax) then
1138+
Some(() => singleCaseMatch())
1139+
else
1140+
None
1141+
isParamsAndArrow()
1142+
end followingIsLambdaAfterColon
11381143

11391144
/** Can the next lookahead token start an operand as defined by
11401145
* leadingOperandTokens, or is postfix ops enabled?
@@ -2804,7 +2809,7 @@ object Parsers {
28042809
* | SimpleExpr (TypeArgs | NamedTypeArgs)
28052810
* | SimpleExpr1 ArgumentExprs
28062811
* | SimpleExpr1 ColonArgument
2807-
* ColonArgument ::= colon [LambdaStart]
2812+
* ColonArgument ::= colon {LambdaStart}
28082813
* indent (CaseClauses | Block) outdent
28092814
* | colon LambdaStart expr ENDlambda -- under experimental.relaxedLambdaSyntax
28102815
* | colon ExprCaseClause -- under experimental.relaxedLambdaSyntax

docs/_docs/internals/syntax.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,9 @@ SimpleExpr ::= SimpleRef
294294
| SimpleExpr ColonArgument -- under language.experimental.fewerBraces
295295
| SimpleExpr ‘_’ PostfixOp(expr, _) (to be dropped)
296296
| XmlExpr -- to be dropped
297-
ColonArgument ::= colon [LambdaStart]
297+
ColonArgument ::= colon {LambdaStart}
298298
indent (CaseClauses | Block) outdent
299-
| colon LambdaStart expr ENDlambda -- ENDlambda is inserted for each production at next EOL
299+
| colon LambdaStart {LambdaStart} expr ENDlambda -- ENDlambda is inserted for each production at next EOL
300300
-- does not apply if enclosed in parens
301301
| colon ExprCaseClause
302302
LambdaStart ::= FunParams (‘=>’ | ‘?=>’)

tests/neg/closure-args.check

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
| expression expected but end of single-line lambda found
2121
|
2222
| longer explanation available when compiling with `-explain`
23-
-- [E040] Syntax Error: tests/neg/closure-args.scala:21:64 -------------------------------------------------------------
24-
21 |val fs: List[List[Int] => Int] = xs.map: x => case y :: ys => y case Nil => -1 // error
25-
| ^^^^
26-
| end of single-line lambda expected, but 'case' found
23+
-- [E040] Syntax Error: tests/neg/closure-args.scala:21:41 -------------------------------------------------------------
24+
21 |val fs: List[List[Int] => Int] = xs.map: x => case y :: ys => y case Nil => -1 // error // error
25+
| ^
26+
| 'case' expected, but identifier found
2727
-- [E008] Not Found Error: tests/neg/closure-args.scala:10:4 -----------------------------------------------------------
2828
8 |val b: Int = xs
2929
9 | .map: x => x
@@ -57,3 +57,10 @@
5757
| Not found: type y
5858
|
5959
| longer explanation available when compiling with `-explain`
60+
-- [E007] Type Mismatch Error: tests/neg/closure-args.scala:21:97 ------------------------------------------------------
61+
21 |val fs: List[List[Int] => Int] = xs.map: x => case y :: ys => y case Nil => -1 // error // error
62+
| ^
63+
| Found: Unit
64+
| Required: List[Int] => Int
65+
|
66+
| longer explanation available when compiling with `-explain`

tests/neg/closure-args.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ val c = List(xs.map: y => y + y) // error // error // error // error
1818
val e = xs.map: y => // error
1919
y + 1
2020

21-
val fs: List[List[Int] => Int] = xs.map: x => case y :: ys => y case Nil => -1 // error
21+
val fs: List[List[Int] => Int] = xs.map: x => case y :: ys => y case Nil => -1 // error // error
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import language.experimental.relaxedLambdaSyntax
2+
3+
def fun(f: Int => Int => Int): Int = f(1)(2)
4+
5+
val a = fun: (x: Int) =>
6+
(y: Int) => x + y
7+
8+
val b = fun: (x: Int) => (y: Int) => x + y
9+
10+
val c = fun: (x: Int) => (y: Int) =>
11+
x + y
12+

0 commit comments

Comments
 (0)