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

Parser: recover on unfinished qualified operator #16469

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

auduchinok
Copy link
Member

Adds parser recovery for some of the unfinished operators from #16260:

Module.()
Module.Nested.()

@auduchinok auduchinok requested a review from a team as a code owner December 25, 2023 14:15
@auduchinok
Copy link
Member Author

Well, this fix has turned out to be a breaking change, there's a test for .() operator:

I have a serious doubt that it was purposefully added to the language, along with other FUNKY_OPERATOR_NAME tokens. Looking at these, it seems like it could've been an overthought in the lexer and parser recovery routines and tests were added just to make the behaviour stable. 😞

I haven't ever seen any actual F# code written with these operators, and GitHub doesn't highlight them correctly either:

let (.()) v1 v2 = v1 + v2 
let _ = (.()) 1 2

let (.()<-) v1 v2 = v1 + v2 
let _ = (.()<-) 1 2

@auduchinok
Copy link
Member Author

I think there's a way to make it work for many cases without doing the breaking changes, but it'd be rather hacky in comparison with possible removing support for these hardcoded operators:

| ".[]" 
| ".[]<-"
| ".[,]<-"
| ".[,,]<-"
| ".[,,,]<-"
| ".[,,,]"
| ".[,,]"
| ".[,]"
| ".[..]"
| ".[..,..]"
| ".[..,..,..]"
| ".[..,..,..,..]"
| ".()" 
| ".()<-"

I'm wondering is there actually any known use of any of them? I think I've never seen anything like this:

SomeModule.(.[..,..]) 1 arg2
(.[..]<-) arg1 "hello"

@psfinaki
Copy link
Member

psfinaki commented Jan 3, 2024

@KevinRansom @dsyme any opinion on this?

@T-Gro
Copy link
Member

T-Gro commented Jan 3, 2024

I think there's a way to make it work for many cases without doing the breaking changes, but it'd be rather hacky in comparison with possible removing support for these hardcoded operators:

Let's unleash imagination of who could have used it by now - what about 'point-free style' fans who want to apply a collection indexer indexer in a point-free way?

let (.()) (index:int) (array: _[])  = array[index]
let inline getFirstElementOfEvery arr  = arr |> Array.map ((.()) 0 )
let firstIndices = getFirstElementOfEvery [| [|0|] ; [|1;0|]  |]

@vzarytovskii
Copy link
Member

I have a serious doubt that it was purposefully added to the language

I think it was for future use if we wanted to allow users to have their own indexing operators for types.

The following can't be defined in the user code:

| ".[]" 
| ".[]<-"
| ".[,]<-"
| ".[,,]<-"
| ".[,,,]<-"
| ".[,,,]"
| ".[,,]"
| ".[,]"
| ".[..]"
| ".[..,..]"
| ".[..,..,..]"
| ".[..,..,..,..]"

These can:

| ".()" 
| ".()<-"

@vzarytovskii
Copy link
Member

Ok, now I remember where I've seen those. They are for ML compatibility for one:

// Compile with --mlcompatibility
let op_ArrayLookup (a : int []) (i : int) = 
    a.[i]
    
let op_ArrayAssign (a : int []) (i : int) (v : int) = 
    a.[i] <- v

let a = [|1;2;3;4;5|]

a.(1) <- 9 ;
a.(1) |> ignore

So, unless they're deprecated, we can't really get rid of them.

@auduchinok
Copy link
Member Author

@vzarytovskii Hm, I don't see any of these operators in your example. The concerns in this PR are only about these operators used without any spaces and IIRC in parens, like (.()<-) 1 2. In all other cases this is parsed properly, because the lexer produces proper tokens if there're spaces or other tokens in between (i.e. i in your examples).

The example by @T-Gro is the only way I see of how they could be used in theory, but I'm not sure if it is documented or actually used anywhere.

@vzarytovskii
Copy link
Member

@vzarytovskii Hm, I don't see any of these operators in your example. The concerns in this PR are only about these operators used without any spaces and IIRC in parens, like (.()<-) 1 2. In all other cases this is parsed properly, because the lexer produces proper tokens if there're spaces or other tokens in between (i.e. i in your examples).

The example by @T-Gro is the only way I see of how they could be used in theory, but I'm not sure if it is documented or actually used anywhere.

@auduchinok .() = parenGet = op_ArrayLookup and .()<- = parenSet = op_ArrayAssign:

image

@vzarytovskii
Copy link
Member

Or am I missing something?

@T-Gro
Copy link
Member

T-Gro commented Jan 4, 2024

Or am I missing something?

The problem in the parser rules faced by @auduchinok is only exposed when you use the operator WITHOUT putting in the arguments.

.(0) => not a problem
.() => this is the problem, i.e. refering to the operator function without applying it.

@T-Gro
Copy link
Member

T-Gro commented Jan 4, 2024

The example by @T-Gro is the only way I see of how they could be used in theory, but I'm not sure if it is documented or actually used anywhere.

Documented not.
Recommended not.

Actually used - I am afraid we do not have a mechanism for answering that for private repositories.

@edgarfgp
Copy link
Contributor

I personally think in the effort of providing better error recovery and tooling experience this should be considered.

Copy link
Contributor

github-actions bot commented Mar 7, 2024

Caution

Repository is on lockdown for maintenance, all merges are on hold.

Copy link
Contributor

github-actions bot commented Mar 7, 2024

❗ Release notes required

@auduchinok,

Caution

No release notes found for the changed paths (see table below).

Please make sure to add an entry with an informative description of the change as well as link to this pull request, issue and language suggestion if applicable. Release notes for this repository are based on Keep A Changelog format.

The following format is recommended for this repository:

* <Informative description>. ([PR #XXXXX](https://github.com/dotnet/fsharp/pull/XXXXX))

See examples in the files, listed in the table below or in th full documentation at https://fsharp.github.io/fsharp-compiler-docs/release-notes/About.html.

If you believe that release notes are not necessary for this PR, please add NO_RELEASE_NOTES label to the pull request.

You can open this PR in browser to add release notes: open in github.dev

Change path Release notes path Description
src/Compiler docs/release-notes/.FSharp.Compiler.Service/8.0.300.md No release notes found or release notes format is not correct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants