@@ -194,12 +194,16 @@ object Parsers {
194
194
/** Is current token a hard or soft modifier (in modifier position or not)? */
195
195
def isModifier : Boolean = modifierTokens.contains(in.token) || in.isSoftModifier
196
196
197
- def isBindingIntro : Boolean =
198
- canStartBindingTokens.contains(in.token) &&
199
- ! in.isSoftModifierInModifierPosition
197
+ def isBindingIntro : Boolean = {
198
+ in.token match {
199
+ case USCORE | LPAREN => true
200
+ case IDENTIFIER | BACKQUOTED_IDENT => in.lookaheadIn(BitSet (COLON , ARROW ))
201
+ case _ => false
202
+ }
203
+ } && ! in.isSoftModifierInModifierPosition
200
204
201
205
def isExprIntro : Boolean =
202
- if (in.token == IMPLIED ) in.lookaheadIn(BitSet (MATCH ))
206
+ if (in.token == IMPLIED || in.token == GIVEN ) in.lookaheadIn(BitSet (MATCH ))
203
207
else (canStartExpressionTokens.contains(in.token) && ! in.isSoftModifierInModifierPosition)
204
208
205
209
def isDefIntro (allowedMods : BitSet , excludedSoftModifiers : Set [TermName ] = Set .empty): Boolean =
@@ -1274,7 +1278,7 @@ object Parsers {
1274
1278
* | SimpleExpr1 ArgumentExprs `=' Expr
1275
1279
* | Expr2
1276
1280
* | [‘inline’] Expr2 `match' `{' CaseClauses `}'
1277
- * | `delegate ' `match' `{' ImplicitCaseClauses `}'
1281
+ * | `given ' `match' `{' ImplicitCaseClauses `}'
1278
1282
* Bindings ::= `(' [Binding {`,' Binding}] `)'
1279
1283
* Binding ::= (id | `_') [`:' Type]
1280
1284
* Expr2 ::= PostfixExpr [Ascription]
@@ -1293,7 +1297,7 @@ object Parsers {
1293
1297
if (in.token == MATCH ) impliedMatch(start, imods)
1294
1298
else implicitClosure(start, location, imods)
1295
1299
}
1296
- else if (in.token == IMPLIED ) {
1300
+ else if (in.token == IMPLIED || in.token == GIVEN ) {
1297
1301
in.nextToken()
1298
1302
if (in.token == MATCH )
1299
1303
impliedMatch(start, EmptyModifiers )
@@ -1478,7 +1482,7 @@ object Parsers {
1478
1482
*/
1479
1483
def impliedMatch (start : Int , imods : Modifiers ) = {
1480
1484
def markFirstIllegal (mods : List [Mod ]) = mods match {
1481
- case mod :: _ => syntaxError(em " illegal modifier for delegate match " , mod.span)
1485
+ case mod :: _ => syntaxError(em " illegal modifier for given match " , mod.span)
1482
1486
case _ =>
1483
1487
}
1484
1488
imods.mods match {
@@ -1493,7 +1497,7 @@ object Parsers {
1493
1497
case pat => isVarPattern(pat)
1494
1498
}
1495
1499
if (! isImplicitPattern(pat))
1496
- syntaxError(em " not a legal pattern for a delegate match " , pat.span)
1500
+ syntaxError(em " not a legal pattern for a given match " , pat.span)
1497
1501
}
1498
1502
result
1499
1503
}
@@ -2303,8 +2307,59 @@ object Parsers {
2303
2307
def paramClauses (ofClass : Boolean = false ,
2304
2308
ofCaseClass : Boolean = false ,
2305
2309
ofInstance : Boolean = false ): List [List [ValDef ]] = {
2310
+
2311
+ def followingIsParamClause : Boolean = {
2312
+ val lookahead = in.lookaheadScanner
2313
+ lookahead.nextToken()
2314
+ paramIntroTokens.contains(lookahead.token) && {
2315
+ lookahead.token != IDENTIFIER ||
2316
+ lookahead.name == nme.inline || {
2317
+ lookahead.nextToken()
2318
+ lookahead.token == COLON
2319
+ }
2320
+ }
2321
+ }
2322
+
2323
+ /** For given instance definitions we have a disambiguation problem:
2324
+ * given A as B
2325
+ * given C ...
2326
+ * Is the second line a parameter `given C` for the first `given` definition, or is it
2327
+ * a second `given` definition? We only know if we find a `for` or `as` in `...`
2328
+ * The same problem arises for
2329
+ * class A
2330
+ * given C ...
2331
+ * For method definitions we do not have this problem since a parameter clause
2332
+ * in a method definition is always followed by something else. So in
2333
+ * def m(...)
2334
+ * given C ...
2335
+ * we know that `given` must start a parameter list. It cannot be a new given` definition.
2336
+ */
2337
+ def followingIsInstanceDef =
2338
+ (ofClass || ofInstance) && {
2339
+ val lookahead = in.lookaheadScanner // skips newline on startup
2340
+ lookahead.nextToken() // skip the `given`
2341
+ if (lookahead.token == IDENTIFIER || lookahead.token == BACKQUOTED_IDENT ) {
2342
+ lookahead.nextToken()
2343
+ if (lookahead.token == LBRACKET ) {
2344
+ lookahead.nextToken()
2345
+ var openBrackets = 1
2346
+ while (openBrackets > 0 && lookahead.token != EOF ) {
2347
+ if (lookahead.token == LBRACKET ) openBrackets += 1
2348
+ else if (lookahead.token == RBRACKET ) openBrackets -= 1
2349
+ lookahead.nextToken()
2350
+ }
2351
+ }
2352
+ }
2353
+ lookahead.token == FOR ||
2354
+ lookahead.token == IDENTIFIER && lookahead.name == nme.as
2355
+ }
2356
+
2306
2357
def recur (firstClause : Boolean , nparams : Int , contextualOnly : Boolean ): List [List [ValDef ]] = {
2307
2358
var initialMods = EmptyModifiers
2359
+ val isNewLine = in.token == NEWLINE
2360
+ newLineOptWhenFollowedBy(LPAREN )
2361
+ if (in.token == NEWLINE && in.next.token == GIVEN && ! followingIsInstanceDef)
2362
+ in.nextToken()
2308
2363
if (in.token == GIVEN ) {
2309
2364
in.nextToken()
2310
2365
initialMods |= Given
@@ -2313,22 +2368,10 @@ object Parsers {
2313
2368
in.nextToken()
2314
2369
initialMods |= Erased
2315
2370
}
2316
- val isContextual = initialMods.is(Given )
2371
+ val isGiven = initialMods.is(Given )
2317
2372
newLineOptWhenFollowedBy(LPAREN )
2318
- def isParamClause : Boolean =
2319
- ! isContextual || {
2320
- val lookahead = in.lookaheadScanner
2321
- lookahead.nextToken()
2322
- paramIntroTokens.contains(lookahead.token) && {
2323
- lookahead.token != IDENTIFIER ||
2324
- lookahead.name == nme.inline || {
2325
- lookahead.nextToken()
2326
- lookahead.token == COLON
2327
- }
2328
- }
2329
- }
2330
- if (in.token == LPAREN && isParamClause) {
2331
- if (contextualOnly && ! isContextual)
2373
+ if (in.token == LPAREN && (! isGiven || followingIsParamClause)) {
2374
+ if (contextualOnly && ! isGiven)
2332
2375
if (ofInstance) syntaxError(em " parameters of instance definitions must come after `given' " )
2333
2376
else syntaxError(em " normal parameters cannot come after `given' clauses " )
2334
2377
val params = paramClause(
@@ -2337,15 +2380,15 @@ object Parsers {
2337
2380
firstClause = firstClause,
2338
2381
initialMods = initialMods)
2339
2382
val lastClause = params.nonEmpty && params.head.mods.flags.is(Implicit )
2340
- params :: (if (lastClause) Nil else recur(firstClause = false , nparams + params.length, isContextual ))
2383
+ params :: (if (lastClause) Nil else recur(firstClause = false , nparams + params.length, isGiven ))
2341
2384
}
2342
- else if (isContextual ) {
2385
+ else if (isGiven ) {
2343
2386
val tps = commaSeparated(() => annotType())
2344
2387
var counter = nparams
2345
2388
def nextIdx = { counter += 1 ; counter }
2346
2389
val paramFlags = if (ofClass) Private | Local | ParamAccessor else Param
2347
2390
val params = tps.map(makeSyntheticParameter(nextIdx, _, paramFlags | Synthetic | Given ))
2348
- params :: recur(firstClause = false , nparams + params.length, isContextual )
2391
+ params :: recur(firstClause = false , nparams + params.length, isGiven )
2349
2392
}
2350
2393
else Nil
2351
2394
}
@@ -2359,12 +2402,12 @@ object Parsers {
2359
2402
2360
2403
type ImportConstr = (Boolean , Tree , List [Tree ]) => Tree
2361
2404
2362
- /** Import ::= import [delegate ] [ImportExpr {`,' ImportExpr}
2363
- * Export ::= export [delegate ] [ImportExpr {`,' ImportExpr}
2405
+ /** Import ::= ` import' [`given' ] [ImportExpr {`,' ImportExpr}
2406
+ * Export ::= ` export' [`given' ] [ImportExpr {`,' ImportExpr}
2364
2407
*/
2365
2408
def importClause (leading : Token , mkTree : ImportConstr ): List [Tree ] = {
2366
2409
val offset = accept(leading)
2367
- val importDelegate = in.token == IMPLIED
2410
+ val importDelegate = in.token == IMPLIED || in.token == GIVEN
2368
2411
if (importDelegate) in.nextToken()
2369
2412
commaSeparated(importExpr(importDelegate, mkTree)) match {
2370
2413
case t :: rest =>
@@ -2383,15 +2426,21 @@ object Parsers {
2383
2426
2384
2427
/** ImportSelectors ::= `{' {ImportSelector `,'} FinalSelector ‘}’
2385
2428
* FinalSelector ::= ImportSelector
2386
- * | ‘_’
2387
- * | ‘for’ InfixType {‘,’ InfixType}
2429
+ * | ‘_’ [‘:’ Type]
2388
2430
*/
2389
2431
def importSelectors (): List [Tree ] = in.token match {
2390
2432
case USCORE =>
2391
- wildcardIdent() :: Nil
2433
+ atSpan(in.skipToken()) {
2434
+ val id = Ident (nme.WILDCARD )
2435
+ if (in.token == COLON ) {
2436
+ in.nextToken()
2437
+ TypeBoundsTree (EmptyTree , typ())
2438
+ }
2439
+ else id
2440
+ } :: Nil
2392
2441
case FOR =>
2393
2442
if (! importDelegate)
2394
- syntaxError(em " `for` qualifier only allowed in `import delegate ` " )
2443
+ syntaxError(em " `for` qualifier only allowed in `import given ` " )
2395
2444
atSpan(in.skipToken()) {
2396
2445
var t = infixType()
2397
2446
while (in.token == COMMA ) {
@@ -2695,7 +2744,7 @@ object Parsers {
2695
2744
/** TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef
2696
2745
* | [‘case’] ‘object’ ObjectDef
2697
2746
* | ‘enum’ EnumDef
2698
- * | ‘instance’ InstanceDef
2747
+ * | ‘given’ GivenDef
2699
2748
*/
2700
2749
def tmplDef (start : Int , mods : Modifiers ): Tree = {
2701
2750
in.token match {
@@ -2711,8 +2760,8 @@ object Parsers {
2711
2760
objectDef(start, posMods(start, mods | Case | Module ))
2712
2761
case ENUM =>
2713
2762
enumDef(start, posMods(start, mods | Enum ))
2714
- case IMPLIED =>
2715
- instanceDef(start, mods, atSpan(in.skipToken()) { Mod .Delegate () })
2763
+ case IMPLIED | GIVEN =>
2764
+ instanceDef(in.token == GIVEN , start, mods, atSpan(in.skipToken()) { Mod .Delegate () })
2716
2765
case _ =>
2717
2766
syntaxErrorOrIncomplete(ExpectedStartOfTopLevelDefinition ())
2718
2767
EmptyTree
@@ -2804,17 +2853,16 @@ object Parsers {
2804
2853
Template (constr, parents, Nil , EmptyValDef , Nil )
2805
2854
}
2806
2855
2807
- /** InstanceDef ::= [id] [DefTypeParamClause] InstanceBody
2808
- * InstanceParams ::= [DefTypeParamClause] {GivenParamClause}
2809
- * InstanceBody ::= [‘for’ ConstrApp {‘,’ ConstrApp }] {GivenParamClause} [TemplateBody]
2810
- * | ‘for’ Type {GivenParamClause} ‘=’ Expr
2856
+ /** GivenDef ::= [id] [DefTypeParamClause] GivenBody
2857
+ * GivenBody ::= [‘as ConstrApp {‘,’ ConstrApp }] {GivenParamClause} [TemplateBody]
2858
+ * | ‘as’ Type {GivenParamClause} ‘=’ Expr
2811
2859
*/
2812
- def instanceDef (start : Offset , mods : Modifiers , instanceMod : Mod ) = atSpan(start, nameStart) {
2860
+ def instanceDef (newStyle : Boolean , start : Offset , mods : Modifiers , instanceMod : Mod ) = atSpan(start, nameStart) {
2813
2861
var mods1 = addMod(mods, instanceMod)
2814
- val name = if (isIdent) ident() else EmptyTermName
2862
+ val name = if (isIdent && ( ! newStyle || in.name != nme.as) ) ident() else EmptyTermName
2815
2863
val tparams = typeParamClauseOpt(ParamOwner .Def )
2816
2864
val parents =
2817
- if (in.token == FOR ) {
2865
+ if (! newStyle && in.token == FOR || isIdent(nme.as)) { // for the moment, accept both `given for` and `given as`
2818
2866
in.nextToken()
2819
2867
tokenSeparated(COMMA , constrApp)
2820
2868
}
@@ -3121,8 +3169,16 @@ object Parsers {
3121
3169
setLastStatOffset()
3122
3170
if (in.token == IMPORT )
3123
3171
stats ++= importClause(IMPORT , Import )
3124
- else if (in.token == GIVEN )
3125
- stats += implicitClosure(in.offset, Location .InBlock , modifiers(closureMods))
3172
+ else if (in.token == GIVEN ) {
3173
+ val start = in.offset
3174
+ val mods = modifiers(closureMods)
3175
+ mods.mods match {
3176
+ case givenMod :: Nil if ! isBindingIntro =>
3177
+ stats += instanceDef(true , start, EmptyModifiers , Mod .Delegate ().withSpan(givenMod.span))
3178
+ case _ =>
3179
+ stats += implicitClosure(in.offset, Location .InBlock , mods)
3180
+ }
3181
+ }
3126
3182
else if (isExprIntro)
3127
3183
stats += expr(Location .InBlock )
3128
3184
else if (isDefIntro(localModifierTokens, excludedSoftModifiers = Set (nme.`opaque`)))
0 commit comments