Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Imply record label from expressions #17857

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions src/Compiler/Checking/Expressions/CheckSequenceExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,40 @@ let TcSequenceExpressionEntry (cenv: TcFileState) env (overallTy: OverallTy) tpe
| _ -> ()

if not hasBuilder && not cenv.g.compilingFSharpCore then
error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m))

TcSequenceExpression cenv env tpenv comp overallTy m
let (|MaybeRecordField|_|) =
function
| LongOrSingleIdent(false, (SynLongIdent _ as ident), None, _) as expr1 ->
let f =
ParseHelpers.mkRecdField (SynLongIdent([ List.last ident.LongIdent ], [], []))

ValueSome(SynExprRecordField(f, None, Some expr1, None))
| SynExpr.App(ExprAtomicFlag.NonAtomic,
false,
SynExpr.App(ExprAtomicFlag.NonAtomic,
true,
SynExpr.LongIdent(longDotId = SynLongIdent(id = [ ident ])),
LongOrSingleIdent(false, (SynLongIdent _ as lid), None, _),
_),
rhs,
_) when ident.idText = "op_Equality" ->
let f = ParseHelpers.mkRecdField lid
ValueSome(SynExprRecordField(f, Some ident.idRange, Some rhs, None))
| _ -> ValueNone

let rec sequentialToRecordExpression fields (comp: SynExpr) =
match comp with
| SynExpr.Sequential(expr1 = MaybeRecordField field; expr2 = expr2) -> sequentialToRecordExpression (field :: fields) expr2
| MaybeRecordField field -> ValueSome(SynExpr.Record(None, None, List.rev (field :: fields), comp.Range))
| _ -> ValueNone

match comp with
| MaybeRecordField field ->
SynExpr.Record(None, None, [ field ], comp.Range)
|> TcExpr cenv overallTy env tpenv
| SynExpr.Sequential _ ->
match sequentialToRecordExpression [] comp with
| ValueSome expr -> TcExpr cenv overallTy env tpenv expr
| ValueNone -> error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m))
| _ -> error (Error(FSComp.SR.tcInvalidSequenceExpressionSyntaxForm (), m))
else
TcSequenceExpression cenv env tpenv comp overallTy m
30 changes: 20 additions & 10 deletions src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -5562,10 +5562,22 @@ recdExprCore:
None, l
| _ -> raiseParseErrorAt (rhs parseState 2) (FSComp.SR.parsFieldBinding ()) }

/* handles case like { x } */
Copy link
Contributor

@edgarfgp edgarfgp Oct 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we also include error recovering recover / ends_coming_soon_or_recover ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will also work with struct {| x |} ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will also work with struct {| x |} ?

yes

| appExpr recdExprBindings opt_seps_recd
{ match $1 with
| LongOrSingleIdent(false, (SynLongIdent _ as ident), None, m) ->
let f = mkRecdField (SynLongIdent([List.last ident.LongIdent], [], []))
let l = List.rev $2
let l = rebindRanges (f, None, Some $1) l $3
(None, l)
| _ -> raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) }

| appExpr
{ let mExpr = rhs parseState 1
reportParseErrorAt mExpr (FSComp.SR.parsFieldBinding ())
Some($1, (mExpr.EndRange, None)), [] }
{ match $1 with
| LongOrSingleIdent(false, (SynLongIdent _ as ident), None, m) ->
let f = mkRecdField (SynLongIdent([List.last ident.LongIdent], [], []))
(None, [ SynExprRecordField(f, None, Some $1, None) ])
| _ -> raiseParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding()) }

/*
handles cases when identifier can start from the underscore
Expand Down Expand Up @@ -5632,7 +5644,7 @@ seps_recd:


/* identifier can start from the underscore */
pathOrUnderscore :
pathOrUnderscore:
| path
{ mkRecdField $1 }

Expand Down Expand Up @@ -5664,12 +5676,10 @@ recdBinding:
($1, Some mEquals, None) }

| pathOrUnderscore
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding())
($1, None, None) }

| pathOrUnderscore ends_coming_soon_or_recover
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsFieldBinding())
($1, None, None) }
{ let ident, b = $1
let f = SynLongIdent([List.last ident.LongIdent], [], []), b
let expr = SynExpr.LongIdent(false, ident, None, rhs parseState 1)
(f, None, Some expr) }

/* There is a minor conflict between
seq { new ty() } // sequence expression with one very odd 'action' expression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,8 @@ ImplFile
(AnonRecd
(true, None, [], (4,0--4,12), { OpeningBraceRange = (4,7--4,9) }),
(4,0--4,12));
Expr
(AnonRecd
(false, Some (Null (5,3--5,7), ((5,7--5,7), None)), [],
(5,0--5,10), { OpeningBraceRange = (5,0--5,2) }), (5,0--5,10));
Expr
(AnonRecd
(true, Some (Null (6,10--6,14), ((6,14--6,14), None)), [],
(6,0--6,17), { OpeningBraceRange = (6,7--6,9) }), (6,0--6,17))],
Expr (ArbitraryAfterError ("braceBarExpr", (5,0--5,10)), (5,0--5,10));
Expr (ArbitraryAfterError ("braceBarExpr", (6,0--6,17)), (6,0--6,17))],
PreXmlDocEmpty, [], None, (1,0--6,17), { LeadingKeyword = None })],
(true, true), { ConditionalDirectives = []
CodeComments = [] }, set []))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ ImplFile
([Module], false, NamedModule,
[Expr
(AnonRecd
(false, Some (Ident F, ((3,4--3,4), None)), [], (3,0--3,7),
{ OpeningBraceRange = (3,0--3,2) }), (3,0--3,7))],
(false, None, [(SynLongIdent ([F], [], []), None, Ident F)],
(3,0--3,7), { OpeningBraceRange = (3,0--3,2) }), (3,0--3,7))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--3,7), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(3,3)-(3,4) parse error Field bindings must have the form 'id = expr;'
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@ ImplFile
[], [],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Expr
(AnonRecd
(false,
Some
(App
(Atomic, false, Ident f, Const (Unit, (3,4--3,6)),
(3,3--3,6)), ((3,6--3,6), None)), [], (3,0--3,9),
{ OpeningBraceRange = (3,0--3,2) }), (3,0--3,9))],
[Expr (ArbitraryAfterError ("braceBarExpr", (3,0--3,9)), (3,0--3,9))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--3,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,7 @@ ImplFile
[], [],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Expr
(AnonRecd
(false,
Some
(DiscardAfterMissingQualificationAfterDot
(App
(Atomic, false, Ident f, Const (Unit, (3,4--3,6)),
(3,3--3,6)), (3,6--3,7), (3,3--3,7)),
((3,10--3,10), None)), [], (3,0--3,10),
{ OpeningBraceRange = (3,0--3,2) }), (3,0--3,10))],
[Expr (ArbitraryAfterError ("braceBarExpr", (3,0--3,10)), (3,0--3,10))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--3,10), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,7 @@ ImplFile
[], [],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Expr
(AnonRecd
(false,
Some
(DotGet
(App
(Atomic, false, Ident f, Const (Unit, (3,4--3,6)),
(3,3--3,6)), (3,6--3,7),
SynLongIdent ([F], [], [None]), (3,3--3,8)),
((3,8--3,8), None)), [], (3,0--3,11),
{ OpeningBraceRange = (3,0--3,2) }), (3,0--3,11))],
[Expr (ArbitraryAfterError ("braceBarExpr", (3,0--3,11)), (3,0--3,11))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--3,11), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ ImplFile
(false, None,
[(SynLongIdent ([F1], [], [None]), Some (3,6--3,7),
Const (Int32 1, (3,8--3,9)));
(SynLongIdent ([F2], [], [None]), None,
ArbitraryAfterError ("anonField", (4,3--4,5)))], (3,0--4,8),
{ OpeningBraceRange = (3,0--3,2) }), (3,0--4,8))],
(SynLongIdent ([F2], [], []), None,
LongIdent
(false, SynLongIdent ([F2], [], [None]), None, (4,3--4,5)))],
(3,0--4,8), { OpeningBraceRange = (3,0--3,2) }), (3,0--4,8))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,8), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(4,3)-(4,5) parse error Field bindings must have the form 'id = expr;'
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ ImplFile
(false, None,
[(SynLongIdent ([F1], [], [None]), Some (3,6--3,7),
Const (Int32 1, (3,8--3,9)));
(SynLongIdent ([F2], [], [None]), None,
ArbitraryAfterError ("anonField", (4,3--4,5)));
(SynLongIdent ([F2], [], []), None,
LongIdent
(false, SynLongIdent ([F2], [], [None]), None, (4,3--4,5)));
(SynLongIdent ([F3], [], [None]), Some (5,6--5,7),
Const (Int32 3, (5,8--5,9)))], (3,0--5,12),
{ OpeningBraceRange = (3,0--3,2) }), (3,0--5,12))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--5,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(4,3)-(4,5) parse error Field bindings must have the form 'id = expr;'
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,12 @@ ImplFile
([Module], false, NamedModule,
[Expr
(AnonRecd
(false, Some (Ident F1, ((3,5--3,5), None)), [], (3,0--3,5),
{ OpeningBraceRange = (3,0--3,2) }), (3,0--3,5));
Expr
(App
(NonAtomic, false,
App
(NonAtomic, true,
LongIdent
(false,
SynLongIdent
([op_Equality], [], [Some (OriginalNotation "=")]),
None, (4,6--4,7)), Ident F2, (4,3--4,7)),
Const (Int32 2, (4,8--4,9)), (4,3--4,9)), (4,3--4,9))],
(false, None,
[(SynLongIdent ([F1], [], []), None, Ident F1);
(SynLongIdent ([F2], [], [None]), Some (4,6--4,7),
Const (Int32 2, (4,8--4,9)))], (3,0--4,12),
{ OpeningBraceRange = (3,0--3,2) }), (3,0--4,12))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,9), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
(1,0--4,12), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(3,3)-(3,5) parse error Field bindings must have the form 'id = expr;'
(3,6)-(4,3) parse error Incomplete structured construct at or before this point in definition. Expected '|}' or other token.
(3,0)-(3,2) parse error Unmatched '{|'
(4,10)-(4,12) parse error Unexpected symbol '|}' in definition. Expected incomplete structured construct at or before this point or other token.
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ ImplFile
((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5),
Some (Const (Int32 1, (3,6--3,7))), Some ((3,8--4,2), None));
SynExprRecordField
((SynLongIdent ([B], [(4,3--4,4)], [None]), true), None,
None, None)], (3,0--4,6)), (3,0--4,6))],
((SynLongIdent ([B], [], []), true), None,
Some
(LongIdent
(false, SynLongIdent ([B], [(4,3--4,4)], [None]), None,
(4,2--4,6))), None)], (3,0--4,6)), (3,0--4,6))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,6), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(4,3)-(4,4) parse error Unexpected end of type. Expected a name after this point.
(4,2)-(4,6) parse error Field bindings must have the form 'id = expr;'
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ ImplFile
((SynLongIdent ([A], [], [None]), true), Some (3,4--3,5),
Some (Const (Int32 1, (3,6--3,7))), Some ((3,8--4,2), None));
SynExprRecordField
((SynLongIdent ([B], [], [None]), true), None, None, None)],
(3,0--4,5)), (3,0--4,5))],
((SynLongIdent ([B], [], []), true), None,
Some
(LongIdent
(false, SynLongIdent ([B], [], [None]), None,
(4,2--4,3))), None)], (3,0--4,5)), (3,0--4,5))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,5), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(4,2)-(4,3) parse error Field bindings must have the form 'id = expr;'
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ module CompletionProviderTests =

if actualNames <> expected then
failwithf
"Expected:\n%s,\nbut was:\n%s\nactual with sort text:\n%s"
"After marker \"%s\" expected:\n%s,\nbut was:\n%s\nactual with sort text:\n%s"
marker
(String.Join("; ", expected |> List.map (sprintf "\"%s\"")))
(String.Join("; ", actualNames |> List.map (sprintf "\"%s\"")))
(String.Join("\n", actual |> List.map (fun x -> sprintf "%s => %s" x.DisplayText x.SortText)))
Expand Down
Loading