-
Notifications
You must be signed in to change notification settings - Fork 790
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] Nested Record Field Copy and Update Expression #4511
Closed
williamtetlow
wants to merge
51
commits into
dotnet:master
from
williamtetlow:nested-recd-update-recdexpr
+406
−59
Closed
Changes from 4 commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
f2f23a0
no message
williamtetlow 0f1a8fa
convert nested record fields to correct ast in TcRecdExpr - copyInfo …
williamtetlow e7520f9
WIP - TypeName.PropertyName now works for { person with Person.A = { …
williamtetlow a004c5a
got nested record field TypeName.PropertyName.PropertyName working
williamtetlow 6980070
fix ambiguities between TypeName.PropertyName and PropertyName.Proper…
williamtetlow a974cd7
wip
williamtetlow 9e54406
added Module/Namespace.TypeName.FieldName resolution. [WIP] need to a…
williamtetlow dc792d3
remove comments
williamtetlow 3eb2b23
Merge pull request #1 from williamtetlow/nested-recd-module-res
williamtetlow a05aa22
fix error
AviAvni 8ae92d2
Merge branch 'master' into nested-recd-update-recdexpr
AviAvni 413672d
resolve nested module and namespace access
williamtetlow c160937
search whole list of module or namespace refs returned
williamtetlow ba2492a
Updated ModuleOrNamespace search to handle Namespace.Module.FieldName…
williamtetlow 59975e0
search abbreviated type fields
williamtetlow 85b43bb
[WIP] Add copy info so nested fields not referenced in nested express…
williamtetlow e4b3cc1
added basic conformance test for single update with varying levels of…
williamtetlow b8fc206
Merge branch 'master' of https://github.com/williamtetlow/visualfshar…
williamtetlow dc0bf4d
fix long ident range to be the total range of longident
williamtetlow 79d141b
fix TypeName.Fieldname & NamespaceOrModule.FieldName copyInfo to only…
williamtetlow 8597c01
first pass of multi updates
williamtetlow 8911432
refactor module or namespace search
williamtetlow 4edaee3
WIP refactoring code to fix ModuleName.TypeName.FieldName.FieldName
williamtetlow 8fa2ec3
fix ModuleOrNamespace.TypeName.FieldName.FieldName
williamtetlow 1ec29b6
simplify expanding AST
williamtetlow 5f4bc72
refactoring
williamtetlow 5b287f8
use active pattern throughout
williamtetlow 5a17d31
more tidying up
williamtetlow 9d45340
module and namespace test
williamtetlow 295df45
Merge branch 'master' of https://github.com/williamtetlow/visualfshar…
williamtetlow 0141e9e
Merge branch 'nested-recd-update-recdexpr' of https://github.com/will…
williamtetlow 685ac8d
adding conformance tests
williamtetlow 08416a4
Merge branch 'master' into nested-recd-update-recdexpr
williamtetlow 990792c
Merge branch 'nested-recd-update-recdexpr' into nestd-recd-refactoring
williamtetlow efc1e19
fixing conformance tests
williamtetlow 98d610f
Merge pull request #2 from williamtetlow/nestd-recd-refactoring
williamtetlow 0d6c454
moving lid res to NameResolution module
williamtetlow 45780fd
added conformance test for Type vs Field ambiguities
williamtetlow fdb0b01
moved resolution of lid representing nested field access to NameResol…
williamtetlow 8498ba8
fixing issues from moving resolution code to NameResolution module
williamtetlow ab70071
Merge pull request #3 from williamtetlow/nestd-recd-refactoring
williamtetlow 03f5b22
add missing exit to conformance tests
williamtetlow b5cb6af
Merge branch 'master' into nested-recd-update-recdexpr
williamtetlow 33d7990
fixes to conformance tests
williamtetlow 3a366af
make id used not the recd field reference
williamtetlow 1207879
Check the same field is not declared twice in a nested field update
brokenprogrammer 9f79a3b
Merge branch 'master' of https://github.com/williamtetlow/visualfshar…
williamtetlow 35568d8
Merge branch 'master' into nested-recd-update-recdexpr
williamtetlow 9dfc288
resolve issues from feedback
williamtetlow 5af5fae
Merge branch 'nested-recd-update-recdexpr' of https://github.com/will…
williamtetlow a5c0b09
missed update to solution file
williamtetlow File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6878,101 +6878,7 @@ and TcAssertExpr cenv overallTy env (m:range) tpenv x = | |
|
||
and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr) = | ||
let buildForNestdFlds (lidwd : LongIdentWithDots) v = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think throwing a couple of chars saves a lot of space in this case. Why not |
||
let (|ModuleOrNamespace|RecdTy|RecdFld|Undefined|) = | ||
function | ||
| ((_, _, Some _), id) -> RecdFld id | ||
| ((_,Some _, _), id) -> RecdTy id | ||
| ((Some _, None, None), id) -> ModuleOrNamespace id | ||
| (_, id) -> Undefined id | ||
|
||
let resolveIds ids = | ||
let search mapFn mOrNsTyList = | ||
mOrNsTyList | ||
|> Option.bind (fun lst -> lst |> List.map mapFn |> List.tryFind Option.isSome) | ||
|> Option.flatten | ||
|
||
let modOrNsSearch (id : Ident) = | ||
search (fun (mOrNsTy : ModuleOrNamespaceType) -> mOrNsTy.ModulesAndNamespacesByDemangledName.TryFind id.idText) | ||
|
||
let tyconSearch (id : Ident) = | ||
search (fun (mOrNsTy : ModuleOrNamespaceType) -> mOrNsTy.TypesByAccessNames.TryFind id.idText) | ||
|
||
let rec abbrevTyconFieldSearch (abbrvTycon : TyconRef) (id : Ident) = | ||
match abbrvTycon.TypeAbbrev with | ||
| None -> abbrvTycon.GetFieldByName id.idText | ||
| Some (TType_app (abbrv, _)) -> abbrevTyconFieldSearch abbrv id | ||
| _ -> None | ||
|
||
let tyconFieldSearch (id : Ident) = | ||
search (fun (tycon : Tycon) -> match tycon.TypeAbbrev with | ||
| None -> tycon.GetFieldByName id.idText | ||
| Some (TType_app (abbrv, _)) -> abbrevTyconFieldSearch abbrv id | ||
| _ -> None) | ||
|
||
let searchFieldsOfAllTycons (id : Ident) = | ||
let searchForFld (lst : ModuleOrNamespaceType list) = | ||
lst | ||
|> List.map (fun mOrNs -> mOrNs.TypeDefinitions |> List.map (fun (t : Tycon) -> t)) | ||
|> List.concat | ||
|> Some | ||
|> tyconFieldSearch id | ||
|
||
Option.bind searchForFld | ||
let rec loop res mOrNs tycons ids = | ||
match ids with | ||
| [] -> success (res |> List.rev) | ||
| (id : Ident) :: ids -> | ||
match (mOrNs, tycons) with | ||
// If we're not given any namespaces, modules or tycons to restrict search - look in current env | ||
| (None, None) -> | ||
let mOrN = | ||
env.NameEnv.eModulesAndNamespaces.TryFind id.idText | ||
|> Option.bind (fun ml -> Some (ml |> List.map (fun m -> m.ModuleOrNamespaceType))) | ||
|
||
let ty : Tycon list option = | ||
env.NameEnv.eTyconsByAccessNames.TryFind id.idText | ||
|> Option.bind (fun tl -> Some (tl |> List.map (fun t -> t.Deref))) | ||
|
||
let fld = | ||
env.NameEnv.eFieldLabels.TryFind id.idText | ||
|> Option.bind (fun fl -> Some(fl |> List.map (fun f -> f.RecdField))) | ||
|
||
let searchResult = (mOrN, ty, fld) | ||
|
||
match searchResult with | ||
| (None, None, None) -> raze (UndefinedName(List.length res, FSComp.SR.undefinedNameRecordLabelOrNamespace, id, NoSuggestions)) | ||
| _ -> loop ((searchResult, id) :: res) mOrN None ids | ||
| (_, Some _) -> | ||
// If there is some tycons then search for id in their fields | ||
let search = (tyconFieldSearch id tycons) | ||
match search with | ||
| None -> raze (UndefinedName(List.length res, FSComp.SR.undefinedNameRecordLabelOrNamespace, id, NoSuggestions)) | ||
| Some s -> | ||
let tys = match s.FormalType with | ||
| TType_app (tycon, _) -> Some [tycon.Deref] | ||
| _ -> tycons | ||
loop (((None, None, Some [s]), id) :: res) mOrNs tys ids | ||
| _ -> | ||
// If no tycons search for namespace, module or type name | ||
let mOrN, tycon = (modOrNsSearch id mOrNs, tyconSearch id mOrNs) | ||
match (mOrN, tycon) with | ||
| (Some m, _) -> loop (((Some [m.ModuleOrNamespaceType], None, None), id) :: res) (Some [m.ModuleOrNamespaceType]) None ids | ||
| (_, Some _) -> loop (((None, tycons, None), id) :: res) mOrNs tycon ids | ||
| _ -> | ||
// As a last resort - search across fields of module's tycons for case ModuleName.FieldName | ||
let fld = searchFieldsOfAllTycons id mOrNs | ||
match fld with | ||
| Some f -> loop (((None, None, Some [f]), id) :: res) mOrNs tycons ids | ||
| None -> raze (UndefinedName(List.length res, FSComp.SR.undefinedNameRecordLabelOrNamespace, id, NoSuggestions)) | ||
|
||
loop [] None None ids |> ForceRaise | ||
|
||
let recdExprCopyInfo ids (optOrigExpr : (SynExpr * BlockSeparator) option) (id : Ident) = | ||
let lidOfFlds = | ||
ids | ||
|> List.filter (function | RecdFld _ -> true | _ -> false) | ||
|> List.map (fun (_, id) -> id) | ||
|
||
let upToId origSepRng id lidwd = | ||
let rec buildLid res (id : Ident) = | ||
function | ||
|
@@ -6997,52 +6903,38 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr | |
mkRange origId.idRange.FileName origId.idRange.End id.idRange.Start | ||
|
||
match optOrigExpr with | ||
| Some (SynExpr.Ident origId, (sepRange, _)) -> | ||
let lid, rng = upToId sepRange id (origId :: lidOfFlds) | ||
| Some (SynExpr.Ident origId, (sepRange, _)) -> | ||
let flds = ids |> List.map (fun (FieldResolution(rfref, _)) -> rfref.RecdField.Id) | ||
let lid, rng = upToId sepRange id (origId :: flds) | ||
Some (SynExpr.LongIdent (false, LongIdentWithDots(lid, rng), None, totalRange origId id), (id.idRange, None)) // TODO: id.idRange should be the range of the next separator | ||
| _ -> None | ||
|
||
let combineIdsUpToNextFld h rst = | ||
let rec loop lid rst = | ||
let lidAndRst l r = (l |> List.rev, r) | ||
match rst with | ||
| [] -> lidAndRst lid rst | ||
| h :: t -> | ||
match h with | ||
| RecdFld fld -> lidAndRst (fld :: lid) t | ||
| (_, id) -> loop (id :: lid) t | ||
|
||
loop [h] rst | ||
|
||
|
||
let rec synExprRecd copyInfo id idRng ids = | ||
Some(SynExpr.Record((None, (copyInfo id), [ | ||
match ids with | ||
let rec synExprRecd copyInfo id flds = | ||
Some(SynExpr.Record((None, (copyInfo id), [ match flds with | ||
| [] -> yield ((LongIdentWithDots ([], []), true), v, None) | ||
| [(_, fld)] -> yield ((LongIdentWithDots ([fld],[]), true), v, None) | ||
| (_, h) :: t -> yield ((LongIdentWithDots ([h], []), true), (synExprRecd copyInfo h h.idRange t), None)], idRng))) | ||
| [FieldResolution(rfref, _)] -> | ||
let fldId = rfref.RecdField.Id | ||
yield ((LongIdentWithDots ([fldId],[]), true), v, None) | ||
| FieldResolution(rfref, _) :: t -> | ||
let fldId = rfref.RecdField.Id | ||
let nestedFld = synExprRecd copyInfo fldId | ||
yield ((LongIdentWithDots ([fldId], []), true), nestedFld t, None)], id.idRange))) | ||
|
||
let ids = lidwd.Lid |> resolveIds | ||
let access, flds = lidwd.Lid |> ResolveNestedField cenv.tcSink cenv.nameResolver env.eNameResEnv env.eAccessRights overallTy | ||
|
||
[ | ||
match ids with | ||
| [] -> () | ||
| h :: t -> | ||
let lid, id, rng, rst = | ||
match h with | ||
| RecdFld id -> success (([], id), id, id.idRange, t) | ||
| RecdTy id | ||
| ModuleOrNamespace id -> | ||
let ids, rest = combineIdsUpToNextFld id t | ||
let f, b = List.frontAndBack ids | ||
success ((f, b), b, id.idRange, rest) | ||
| Undefined id -> raze (UndefinedName(0, FSComp.SR.undefinedNameRecordLabelOrNamespace, id, NoSuggestions)) | ||
|> ForceRaise | ||
|
||
match rst with | ||
| [] -> yield (lid, v) | ||
| _ -> yield (lid, synExprRecd (recdExprCopyInfo ids optOrigExpr) id rng rst) | ||
] | ||
let expanded = | ||
[ | ||
match (access, flds) with | ||
| [], [] -> () | ||
| ids, [] -> yield (ids |> List.frontAndBack), v | ||
| ids, [FieldResolution(rfref, _)] -> yield ((ids@[rfref.RecdField.Id]) |> List.frontAndBack), v | ||
| ids, FieldResolution(rfref, _) :: rest -> | ||
let id = rfref.RecdField.Id | ||
yield (ids, id), synExprRecd (recdExprCopyInfo flds optOrigExpr) id rest | ||
] | ||
|
||
expanded | ||
|
||
let grpMultipleNstdUpdates flds = | ||
let grpdByFld = flds |> Seq.groupBy (fun ((_, fld : Ident), _) -> fld.idText) | ||
|
@@ -7051,14 +6943,12 @@ and TcRecdExpr cenv overallTy env tpenv (inherits, optOrigExpr, flds, mWholeExpr | |
if (flds |> Seq.length < 2) then | ||
yield! flds | ||
else | ||
yield | ||
flds | ||
|> Seq.reduce ( | ||
fun a b -> | ||
match a, b with | ||
| (lidwid, Some(SynExpr.Record (aBI, aCI, aFlds, aRng))), (_, Some(SynExpr.Record (_, _, bFlds, _))) -> (lidwid, Some(SynExpr.Record (aBI, aCI, (aFlds @ bFlds), aRng))) | ||
| _ -> a | ||
) | ||
yield flds |> Seq.reduce | ||
(fun a b -> match a, b with | ||
| (lidwid, Some(SynExpr.Record (aBI, aCI, aFlds, aRng))), (_, Some(SynExpr.Record (_, _, bFlds, _))) -> | ||
let combinedFlds = aFlds @ bFlds | ||
(lidwid, Some(SynExpr.Record (aBI, aCI, combinedFlds, aRng))) | ||
| _ -> a) | ||
] | ||
|
||
let requiresCtor = (GetCtorShapeCounter env = 1) // Get special expression forms for constructors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not
Map.tryFind
with match?