Skip to content

Commit 9f9c0ec

Browse files
committed
Parser: Update OBLOCKSEP token passing
1 parent c4001e5 commit 9f9c0ec

37 files changed

+130
-151
lines changed

src/Compiler/Checking/CheckRecordSyntaxHelpers.fs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,14 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid
9191
withStartEnd origId.idRange.End id.idRange.Start origId.idRange
9292

9393
match withExpr with
94-
| SynExpr.Ident origId, (blockSep: BlockSeparator) ->
94+
| SynExpr.Ident origId, Some(blockSep: BlockSeparator) ->
9595
let lid, rng = upToId blockSep.Range id (origId :: ids)
96-
97-
Some(
98-
SynExpr.LongIdent(false, LongIdentWithDots(lid, rng), None, totalRange origId id),
99-
BlockSeparator.Offside(blockSep.Range, None)
100-
)
96+
Some(SynExpr.LongIdent(false, LongIdentWithDots(lid, rng), None, totalRange origId id), Some blockSep)
97+
| SynExpr.Ident origId, None ->
98+
// Synthesize a zero-width separator range at the end of the identifier when missing
99+
let zero = origId.idRange.EndRange
100+
let lid, rng = upToId zero id (origId :: ids)
101+
Some(SynExpr.LongIdent(false, LongIdentWithDots(lid, rng), None, totalRange origId id), None)
101102
| _ -> None
102103

103104
let rec synExprRecd copyInfo (outerFieldId: Ident) innerFields exprBeingAssigned =
@@ -120,7 +121,13 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid
120121
AnonRecdTypeInfo.TupInfo = TupInfo.Const isStruct
121122
}) ->
122123
let fields = [ LongIdentWithDots([ fieldId ], []), None, nestedField ]
123-
SynExpr.AnonRecd(isStruct, copyInfo outerFieldId, fields, outerFieldId.idRange, { OpeningBraceRange = range0 })
124+
// Pass through optional separator for anonymous records
125+
let copyInfoAnon =
126+
match copyInfo outerFieldId with
127+
| Some(exprWhenWith, sepOpt) -> Some(exprWhenWith, sepOpt)
128+
| None -> None
129+
130+
SynExpr.AnonRecd(isStruct, copyInfoAnon, fields, outerFieldId.idRange, { OpeningBraceRange = range0 })
124131
| _ ->
125132
let fields =
126133
[
@@ -153,11 +160,11 @@ let TransformAstForNestedUpdates (cenv: TcFileState) (env: TcEnv) overallTy (lid
153160

154161
/// When the original expression in copy-and-update is more complex than `{ x with ... }`, like `{ f () with ... }`,
155162
/// we bind it first, so that it's not evaluated multiple times during a nested update
156-
let BindOriginalRecdExpr (withExpr: SynExpr * BlockSeparator) mkRecdExpr =
157-
let originalExpr, blockSep = withExpr
163+
let BindOriginalRecdExpr (withExpr: SynExpr * BlockSeparator option) mkRecdExpr =
164+
let originalExpr, blockSepOpt = withExpr
158165
let mOrigExprSynth = originalExpr.Range.MakeSynthetic()
159166
let id = mkSynId mOrigExprSynth "bind@"
160-
let withExpr = SynExpr.Ident id, blockSep
167+
let withExpr = SynExpr.Ident id, blockSepOpt
161168

162169
let binding =
163170
mkSynBinding

src/Compiler/Checking/CheckRecordSyntaxHelpers.fsi

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ val TransformAstForNestedUpdates:
1616
overallTy: TType ->
1717
lid: LongIdent ->
1818
exprBeingAssigned: SynExpr ->
19-
withExpr: SynExpr * BlockSeparator ->
19+
withExpr: SynExpr * BlockSeparator option ->
2020
(Ident list * Ident) * SynExpr option
2121

2222
val BindOriginalRecdExpr:
23-
withExpr: SynExpr * BlockSeparator -> mkRecdExpr: ((SynExpr * BlockSeparator) option -> SynExpr) -> SynExpr
23+
withExpr: SynExpr * BlockSeparator option ->
24+
mkRecdExpr: ((SynExpr * BlockSeparator option) option -> SynExpr) ->
25+
SynExpr

src/Compiler/Checking/Expressions/CheckExpressions.fs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5898,7 +5898,8 @@ and TcExprUndelayed (cenv: cenv) (overallTy: OverallTy) env tpenv (synExpr: SynE
58985898
TcAnonRecdExpr cenv overallTy env tpenv (isStruct, withExprOpt, unsortedFieldExprs, mWholeExpr)
58995899
)
59005900
| Some withExpr ->
5901-
BindOriginalRecdExpr withExpr (fun withExpr -> SynExpr.AnonRecd (isStruct, withExpr, unsortedFieldExprs, mWholeExpr, trivia))
5901+
BindOriginalRecdExpr withExpr (fun withExprOpt ->
5902+
SynExpr.AnonRecd (isStruct, withExprOpt, unsortedFieldExprs, mWholeExpr, trivia))
59025903
|> TcExpr cenv overallTy env tpenv
59035904

59045905
| SynExpr.ArrayOrList (isArray, args, m) ->
@@ -7907,7 +7908,7 @@ and TcNewAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, unsortedField
79077908

79087909
mkAnonRecd g mWholeExpr anonInfo unsortedFieldIds unsortedCheckedArgs unsortedFieldTys, tpenv
79097910

7910-
and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (origExpr, blockSeparator), unsortedFieldIdsAndSynExprsGiven, mWholeExpr) =
7911+
and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (origExpr, blockSeparatorOpt), unsortedFieldIdsAndSynExprsGiven, mWholeExpr) =
79117912
// The fairly complex case '{| origExpr with X = 1; Y = 2 |}'
79127913
// The origExpr may be either a record or anonymous record.
79137914
// The origExpr may be either a struct or not.
@@ -7933,7 +7934,7 @@ and TcCopyAndUpdateAnonRecdExpr cenv (overallTy: TType) env tpenv (isStruct, (or
79337934
match synLongIdent.LongIdent with
79347935
| [] -> error(Error(FSComp.SR.nrUnexpectedEmptyLongId(), mWholeExpr))
79357936
| [ id ] -> ([], id), Some exprBeingAssigned
7936-
| lid -> TransformAstForNestedUpdates cenv env origExprTy lid exprBeingAssigned (origExpr, blockSeparator))
7937+
| lid -> TransformAstForNestedUpdates cenv env origExprTy lid exprBeingAssigned (origExpr, blockSeparatorOpt))
79377938
|> GroupUpdatesToNestedFields
79387939

79397940
let unsortedFieldSynExprsGiven = unsortedFieldIdsAndSynExprsGiven |> List.choose snd

src/Compiler/Service/ServiceParseTreeWalk.fs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ module SyntaxTraversal =
445445
| SynExpr.AnonRecd(copyInfo = copyOpt; recordFields = fields) ->
446446
[
447447
match copyOpt with
448-
| Some(expr, blockSep) ->
448+
| Some(expr, Some blockSep) ->
449449
yield dive expr expr.Range traverseSynExpr
450450

451451
yield
@@ -456,6 +456,9 @@ module SyntaxTraversal =
456456
visitor.VisitRecordField(path, Some expr, None)
457457
else
458458
None)
459+
| Some(expr, None) ->
460+
// No explicit separator (implicit OBLOCKSEP). Still dive into expr.
461+
yield dive expr expr.Range traverseSynExpr
459462
| _ -> ()
460463

461464
for field, _, x in fields do
@@ -466,19 +469,11 @@ module SyntaxTraversal =
466469

467470
| SynExpr.Record(baseInfo = inheritOpt; copyInfo = copyOpt; recordFields = fields) ->
468471
[
469-
let diveIntoSeparator offsideColumn scPosOpt copyOpt =
470-
match scPosOpt with
471-
| Some scPos ->
472-
if posGeq pos scPos then
473-
visitor.VisitRecordField(path, copyOpt, None) // empty field after the inherits
474-
else
475-
None
476-
| None ->
477-
//semicolon position is not available - use offside rule
478-
if pos.Column = offsideColumn then
479-
visitor.VisitRecordField(path, copyOpt, None) // empty field after the inherits
480-
else
481-
None
472+
let diveIntoSeparator scPos copyOpt =
473+
if posGeq pos scPos then
474+
visitor.VisitRecordField(path, copyOpt, None) // empty field after the inherits
475+
else
476+
None
482477

483478
match inheritOpt with
484479
| Some(_ty, expr, _range, sepOpt, inheritRange) ->
@@ -505,12 +500,12 @@ module SyntaxTraversal =
505500
// inherit A()
506501
// $
507502
// field1 = 5
508-
diveIntoSeparator inheritRange.StartColumn blockSep.Position None)
503+
diveIntoSeparator blockSep.Position None)
509504
| None -> ()
510505
| _ -> ()
511506

512507
match copyOpt with
513-
| Some(expr, blockSep) ->
508+
| Some(expr, Some blockSep) ->
514509
yield dive expr expr.Range traverseSynExpr
515510

516511
yield
@@ -521,6 +516,9 @@ module SyntaxTraversal =
521516
visitor.VisitRecordField(path, Some expr, None)
522517
else
523518
None)
519+
| Some(expr, None) ->
520+
// No explicit separator (implicit OBLOCKSEP). Still dive into expr.
521+
yield dive expr expr.Range traverseSynExpr
524522
| _ -> ()
525523

526524
let copyOpt = Option.map fst copyOpt
@@ -563,7 +561,7 @@ module SyntaxTraversal =
563561
// field1 = 5
564562
// $
565563
// field2 = 5
566-
diveIntoSeparator offsideColumn blockSep.Position copyOpt)
564+
diveIntoSeparator blockSep.Position copyOpt)
567565
| _ -> ()
568566

569567
]

src/Compiler/SyntaxTree/SyntaxTree.fs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -308,21 +308,18 @@ type SeqExprOnly = SeqExprOnly of bool
308308

309309
[<NoEquality; NoComparison; RequireQualifiedAccess>]
310310
type BlockSeparator =
311-
| Semicolon of range: range * position: pos option
312-
| Comma of range: range * position: pos option
313-
| Offside of range: range * position: pos option
311+
| Semicolon of range: range * position: pos
312+
| Comma of range: range * position: pos
314313

315314
member this.Range =
316315
match this with
317316
| Semicolon(range = m)
318-
| Comma(range = m)
319-
| Offside(range = m) -> m
317+
| Comma(range = m) -> m
320318

321319
member this.Position =
322320
match this with
323-
| Semicolon(position = p)
324-
| Comma(position = p)
325-
| Offside(position = p) -> p
321+
| Semicolon(position = p) -> p
322+
| Comma(position = p) -> p
326323

327324
type RecordFieldName = SynLongIdent * bool
328325

@@ -549,7 +546,7 @@ type SynExpr =
549546

550547
| AnonRecd of
551548
isStruct: bool *
552-
copyInfo: (SynExpr * BlockSeparator) option *
549+
copyInfo: (SynExpr * BlockSeparator option) option *
553550
recordFields: (SynLongIdent * range option * SynExpr) list *
554551
range: range *
555552
trivia: SynExprAnonRecdTrivia
@@ -558,7 +555,7 @@ type SynExpr =
558555

559556
| Record of
560557
baseInfo: (SynType * SynExpr * range * BlockSeparator option * range) option *
561-
copyInfo: (SynExpr * BlockSeparator) option *
558+
copyInfo: (SynExpr * BlockSeparator option) option *
562559
recordFields: SynExprRecordField list *
563560
range: range
564561

src/Compiler/SyntaxTree/SyntaxTree.fsi

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -359,21 +359,16 @@ type SeqExprOnly =
359359
type BlockSeparator =
360360
/// A separator consisting of a semicolon ';'
361361
/// range is the range of the semicolon
362-
/// position is the position of the semicolon (if available)
363-
| Semicolon of range: range * position: pos option
362+
/// position is the position of the semicolon
363+
| Semicolon of range: range * position: pos
364364
/// A separator consisting of a comma ','
365365
/// range is the range of the comma
366-
/// position is the position of the comma (if available)
367-
| Comma of range: range * position: pos option
368-
369-
// A separator consisting of a newline
370-
/// range is the range of the newline
371-
/// position is the position of the newline (if available)
372-
| Offside of range: range * position: pos option
366+
/// position is the position of the comma
367+
| Comma of range: range * position: pos
373368

374369
member Range: range
375370

376-
member Position: pos option
371+
member Position: pos
377372

378373
/// Represents a record field name plus a flag indicating if given record field name is syntactically
379374
/// correct and can be used in name resolution.
@@ -607,7 +602,7 @@ type SynExpr =
607602
/// F# syntax: struct {| id1=e1; ...; idN=eN |}
608603
| AnonRecd of
609604
isStruct: bool *
610-
copyInfo: (SynExpr * BlockSeparator) option *
605+
copyInfo: (SynExpr * BlockSeparator option) option *
611606
recordFields: (SynLongIdent * range option * SynExpr) list *
612607
range: range *
613608
trivia: SynExprAnonRecdTrivia
@@ -621,7 +616,7 @@ type SynExpr =
621616
/// every field includes range of separator after the field (for tooling)
622617
| Record of
623618
baseInfo: (SynType * SynExpr * range * BlockSeparator option * range) option *
624-
copyInfo: (SynExpr * BlockSeparator) option *
619+
copyInfo: (SynExpr * BlockSeparator option) option *
625620
recordFields: SynExprRecordField list *
626621
range: range
627622

src/Compiler/pars.fsy

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3668,14 +3668,13 @@ namePatPairs:
36683668
{ let (id: Ident), mEq, (pat: SynPat) = $1
36693669
let m = unionRanges id.idRange pat.Range
36703670
let lid = SynLongIdent([id], [], [None])
3671-
NamePatPairField(lid, mEq, m, pat, Some $2) :: $3 }
3671+
NamePatPairField(lid, mEq, m, pat, $2) :: $3 }
36723672

36733673
| namePatPair seps_block seps_block namePatPairs
3674-
{ reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsExpectingPattern ())
3675-
let (id: Ident), mEq, (pat: SynPat) = $1
3674+
{ let (id: Ident), mEq, (pat: SynPat) = $1
36763675
let m = unionRanges id.idRange pat.Range
36773676
let lid = SynLongIdent([id], [], [None])
3678-
NamePatPairField(lid, mEq, m, pat, Some $2) :: $4 }
3677+
NamePatPairField(lid, mEq, m, pat, $2) :: $4 }
36793678

36803679
namePatPair:
36813680
| ident EQUALS parenPattern
@@ -4016,13 +4015,13 @@ recordPatternElementsAux:
40164015
| recordPatternElement seps_block recordPatternElementsAux
40174016
{ let (lid: SynLongIdent), mEq, (pat: SynPat) = $1
40184017
let m = unionRanges lid.Range pat.Range
4019-
NamePatPairField(lid, mEq, m, pat, Some $2) :: $3 }
4018+
NamePatPairField(lid, mEq, m, pat, $2) :: $3 }
40204019

40214020
| recordPatternElement seps_block seps_block recordPatternElementsAux
40224021
{ reportParseErrorAt (rhs parseState 3) (FSComp.SR.parsExpectingPattern ())
40234022
let (lid: SynLongIdent), mEq, (pat: SynPat) = $1
40244023
let m = unionRanges lid.Range pat.Range
4025-
NamePatPairField(lid, mEq, m, pat, Some $2) :: $4 }
4024+
NamePatPairField(lid, mEq, m, pat, $2) :: $4 }
40264025

40274026
recordPatternElement:
40284027
| path EQUALS parenPattern
@@ -5709,7 +5708,7 @@ recdExprCore:
57095708
| appExpr
57105709
{ let mExpr = rhs parseState 1
57115710
reportParseErrorAt mExpr (FSComp.SR.parsFieldBinding ())
5712-
Some($1, BlockSeparator.Offside(mExpr.EndRange, None)), [] }
5711+
(Some($1, None), []) }
57135712

57145713
/*
57155714
handles cases when identifier can start from the underscore
@@ -5743,36 +5742,40 @@ recdExprCore:
57435742
| appExpr WITH recdBinding recdExprBindings opt_seps_block
57445743
{ let l = List.rev $4
57455744
let l = rebindRanges $3 l $5
5746-
(Some($1, BlockSeparator.Offside(rhs parseState 2, None)), l) }
5745+
(Some($1, $5), l) }
57475746

57485747
| appExpr OWITH opt_seps_block OEND
5749-
{ (Some($1, BlockSeparator.Offside(rhs parseState 2, None)), []) }
5748+
{ (Some($1, $3), []) }
57505749

57515750
| appExpr OWITH recdBinding recdExprBindings opt_seps_block OEND
57525751
{ let l = List.rev $4
57535752
let l = rebindRanges $3 l $5
5754-
(Some($1, BlockSeparator.Offside(rhs parseState 2, None)), l) }
5753+
(Some($1, $5), l) }
57555754

57565755
opt_seps_block:
57575756
| seps_block
5758-
{ Some $1 }
5757+
{ $1 }
57595758

57605759
| /* EMPTY */
57615760
{ None }
57625761

57635762
seps_block:
57645763
| OBLOCKSEP
5765-
{ BlockSeparator.Offside((rhs parseState 1), None) }
5764+
{
5765+
// OBLOCKSEP is purely syntactic: do not produce a BlockSeparator value
5766+
// Treat it as absence of an explicit separator
5767+
None
5768+
}
57665769

57675770
| SEMICOLON
57685771
{ let m = (rhs parseState 1)
5769-
BlockSeparator.Semicolon(m, Some m.End) }
5772+
Some (BlockSeparator.Semicolon(m, m.End)) }
57705773

57715774
| SEMICOLON OBLOCKSEP
5772-
{ BlockSeparator.Semicolon((rhs2 parseState 1 2), Some (rhs parseState 1).End) }
5775+
{ Some (BlockSeparator.Semicolon((rhs2 parseState 1 2), (rhs parseState 1).End)) }
57735776

57745777
| OBLOCKSEP SEMICOLON
5775-
{ BlockSeparator.Semicolon((rhs2 parseState 1 2), Some (rhs parseState 2).End) }
5778+
{ Some (BlockSeparator.Semicolon((rhs2 parseState 1 2), (rhs parseState 2).End)) }
57765779

57775780

57785781
/* identifier can start from the underscore */
@@ -5787,7 +5790,7 @@ pathOrUnderscore :
57875790

57885791
recdExprBindings:
57895792
| recdExprBindings seps_block recdBinding
5790-
{ ($3, Some $2) :: $1 }
5793+
{ ($3, $2) :: $1 }
57915794

57925795
| /* EMPTY */
57935796
{ [] }

0 commit comments

Comments
 (0)