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

Only wrap Pexp_function in parens when necessary #2033

Merged
merged 3 commits into from Aug 9, 2018

Conversation

anmonteiro
Copy link
Member

fixes #2032

before:

let predicate =
  predicate === Functions.alwaysTrue1 ?
    defaultPredicate :
    (
      fun
      | None => false
      | Some(exn) => predicate(exn)
    );

after:

let predicate =
  predicate === Functions.alwaysTrue1 ?
    defaultPredicate :
    fun
    | None => false
    | Some(exn) => predicate(exn);

@@ -5603,9 +5606,6 @@ let printer = object(self:'self)
match x'.pexp_desc with
| Pexp_let _ ->
Some (makeLetSequence (self#letList x))
| Pexp_function l when (pipe || semi) ->
Copy link
Member Author

Choose a reason for hiding this comment

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

this case was useless. Pexp_function would be caught by expression_immediate_extension_sugar

@anmonteiro anmonteiro changed the title Unnecessarily wraps an anonymous fun function in parens Don't wrap Pexp_function in parens when unnecessary Jun 30, 2018
@anmonteiro anmonteiro changed the title Don't wrap Pexp_function in parens when unnecessary Only wrap Pexp_function in parens when necessary Jun 30, 2018
@jordwalke
Copy link
Member

I've found it very difficult to prove that it is safe to omit parenthesis around functions when they are embedded in infix expressions, and when they return infix function applications. To merge this I think we want to have a lot more test cases where the function returns something that applies infix x >>= y, and also when the function itself is the right hand/left hand side of similar infix. (Also, your ternary test is good too - let's combine it with a bunch of the infix tests I mentioned as well).

@anmonteiro
Copy link
Member Author

anmonteiro commented Jun 30, 2018

@jordwalke thanks for the feedback.

In coming up with test cases, the following example does indeed print incorrectly with the current changes:

(fun
| None => x >>= y
| Some(x) => x >>= y)
>>= bar ;

/* becomes this, which doesn't pass idempotency */
fun
| None => x >>= y
| Some(x) => x >>= y
>>= bar;

I wonder if we can play with the precedence rues to make it work? I'm trying that right now.

@anmonteiro
Copy link
Member Author

anmonteiro commented Jun 30, 2018

@jordwalke I think I added your suggested test cases, let me know if you'd like to see more (and which).

The latest changes introduce a custom "fun" precedence (in the printer) that's lower than e.g. bind operators (>..) but higher than the ternary operators, making Pexp_function print without paren wrapping in the ternary case (which is what the original issue is suggesting).

@anmonteiro anmonteiro force-pushed the gh-2032 branch 2 times, most recently from 79f6fe2 to 9f37e4d Compare July 6, 2018 06:06
fixes reasonml#2032

before:

```reason
let predicate =
  predicate === Functions.alwaysTrue1 ?
    defaultPredicate :
    (
      fun
      | None => false
      | Some(exn) => predicate(exn)
    );
```

after:

```reason
let predicate =
  predicate === Functions.alwaysTrue1 ?
    defaultPredicate :
    fun
    | None => false
    | Some(exn) => predicate(exn);
```
@IwanKaramazow
Copy link
Contributor

@chenglou I don't immediately see anything wrong with this PR, let's merge?

@chenglou
Copy link
Member

chenglou commented Aug 1, 2018

Thanks. Though I’ll hold off meeting for a day or two. New release now

@chenglou chenglou merged commit 37108c7 into reasonml:master Aug 9, 2018
@chenglou
Copy link
Member

chenglou commented Aug 9, 2018

Thanks!

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

Successfully merging this pull request may close these issues.

Unnecessarily wraps an anonymous fun function in parens
5 participants