That's a bug in how the capture of keyword operators work. It has also been
fixed in master. Thank you for the report!



*José Valim*
www.plataformatec.com.br
Skype: jv.ptec
Founder and Director of R&D

On Sun, May 14, 2017 at 6:52 PM, Luke Imhoff <[email protected]> wrote:

> I don't know if this effects your planned change to the grammar, but as a
> side-effect of `not` being treated as a normal function instead of a
> keyword, `not` when captured allows any arity (you may have already
> realized this, I did not).
>
> For uncaptured, `not` with a different arity than 1 is a syntax error
>
> iex> Code.string_to_quoted("not 1")
> {:ok, {:not, [line: 1], [1]}}
> iex> Code.string_to_quoted("not 1, 2")
> {:error, {1, "syntax error before: ", "','"}}
>
> While captured it doesn't care
>
> iex> Code.string_to_quoted("&not 1")
> {:ok, {:&, [line: 1], [{:not, [line: 1], [1]}]}}
> iex> Code.string_to_quoted("&not 1, 2")
> {:ok, {:&, [line: 1], [{:not, [line: 1], [1, 2]}]}}
>
> This may count as a separated bug just a related depending on how it's
> fixed.
>
> On Sunday, May 14, 2017 at 2:41:53 AM UTC-5, José Valim wrote:
>>
>> Thank you Luke for the detailed bug report.
>>
>> I think we should fix this by making "!" behave like "not" and remove
>> this special case from the grammar. The only unary operator that will bind
>> tightly to numbers then will be &, which is already behaves differently
>> from the others as it has very low precedence.
>>
>> Note that @ will still bind tightly to numbers but that's rather because
>> it has very high precedence and not a special case.
>>
>> I will push a commit to master later today.
>>
>>
>> *José Valim*
>> www.plataformatec.com.br
>> Skype: jv.ptec
>> Founder and Director of R&D
>>
>> On Sun, May 14, 2017 at 4:18 AM, Luke Imhoff <[email protected]> wrote:
>>
>>> I noticed this when splitting `not` from the other unary operators in
>>> IntelliJ Elixir's lexer grammar (because I can only do spacing rules on
>>> lexer tokens, so I need NOT_OPERATOR separate from UNARY_OPERATOR for
>>> https://github.com/KronicDeth/intellij-elixir/issues/98 so I can have
>>> no space between the symbolic operators, but require the space after `not`
>>> as it will blend into the argument otherwise).  I'm not sure this is really
>>> a problem or not.  It's just a weird edge-case that I produced since I test
>>> unary numeric and unary non-numeric operators.
>>>
>>> `not` is part of `unary_op_eol` (https://github.com/elixir-lan
>>> g/elixir/blob/39dd31c7d96f302986579bb6938d23c9db101661/lib/
>>> elixir/src/elixir_parser.yrl#L73), which also contains `+`, `-`, `!`,
>>> `^`, `~~~`.
>>>
>>> Let's start with unary numeric at the top-level
>>>
>>> iex> Code.string_to_quoted("not 1")
>>> {:ok, {:not, [line: 1], [1]}}
>>> iex> Code.string_to_quoted("! 1")
>>> {:ok, {:!, [line: 1], [1]}}
>>>
>>> Next, let's do something weird and make the `1` act something you can do
>>> dot calls on.  This is gibberish semantically in current Elixir, but
>>> something the syntax allows.
>>>
>>> iex> Code.string_to_quoted("not 1.(2)")
>>> {:ok, {{:., [line: 1], [{:not, [line: 1], [1]}]}, [line: 1], [2]}}
>>> iex> Code.string_to_quoted("! 1.(2)")
>>> {:ok, {{:., [line: 1], [{:!, [line: 1], [1]}]}, [line: 1], [2]}}
>>>
>>> So, the precedence of the AST is the same: (1) `not`/`!` on `1`; (2) dot
>>> call with `2` on the result of (1).
>>>
>>> Finally, let's try to capture the weird syntax
>>>
>>> iex> Code.string_to_quoted("&not 1.(2)")
>>> {:ok, {:&, [line: 1], [{:not, [line: 1], [{{:., [line: 1], [1]}, [line:
>>> 1], [2]}]}]}}
>>> iex> Code.string_to_quoted("&! 1.(2)")
>>> {:ok, {:&, [line: 1], [{{:., [line: 1], [{:!, [line: 1], [1]}]}, [line:
>>> 1], [2]}]}}
>>>
>>> So the precedence of the symbolic `!` and word `not` is no longer the
>>> same.
>>> For `not`: (1) `1.(2)` is called; (2) `not` the  result of (1)`; (3)
>>> capture
>>> For `!`: `!1` is called; (2) `.(2)` is called on the result of (1); (3)
>>> capture
>>>
>>> What has happened is that `not` has lost it's "keywordness" and is
>>> moving the position of a normal function name (like `foo` below)
>>>
>>> iex> Code.string_to_quoted("&foo 1.(2)")
>>> {:ok, {:&, [line: 1], [{:foo, [line: 1], [{{:., [line: 1], [1]}, [line:
>>> 1], [2]}]}]}}
>>>
>>> So, this example is gibberish.  Does it apply to non-numeric unary
>>> operations?
>>>
>>> iex> Code.string_to_quoted("&! a.(2)")
>>> {:ok, {:&, [line: 1], [{:!, [line: 1], [{{:., [line: 1], [{:a, [line:
>>> 1], nil}]}, [line: 1], [2]}]}]}}
>>> iex> Code.string_to_quoted("&not a.(2)")
>>> {:ok, {:&, [line: 1], [{:not, [line: 1], [{{:., [line: 1], [{:a, [line:
>>> 1], nil}]}, [line: 1], [2]}]}]}}
>>> iex(56)> Code.string_to_quoted("&foo a.(2)")
>>> {:ok, {:&, [line: 1], [{:foo, [line: 1], [{{:., [line: 1], [{:a, [line:
>>> 1], nil}]}, [line: 1], [2]}]}]}}
>>>
>>> So, it's all consistent there: (1) `a.(2)` is evaluated; (2) the
>>> operator/function call; and (3) it's all captured.
>>>
>>> So, is the inconsistency in unary numeric `not` a bug in the native
>>> grammar or something to be expected?  If the unary operators should bind
>>> more tightly to numerics than non-numerics (as is my understanding of the
>>> current grammar) then `{:ok, {:&, [line: 1], [{{:., [line: 1], [{:!, [line:
>>> 1], [1]}]}, [line: 1], [2]}]}}` is correct and `not` should be `{:ok, {:&,
>>> [line: 1], [{{:., [line: 1], [{:not, [line: 1], [1]}]}, [line: 1], [2]}]}}`.
>>>
>>> The unary numeric operations in current language semantics seem to be
>>> there for positional captures, like `&1`, so this is mostly me bringing it
>>> up because I have to change IntelliJ Elixir's grammar to take this
>>> behaviour for unary numeric `not` into account separately from symbolic
>>> unary numerics.
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "elixir-lang-core" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to [email protected].
>>> To view this discussion on the web visit https://groups.google.com/d/ms
>>> gid/elixir-lang-core/f5f75451-93dc-4163-bd9a-7055dab69d62%
>>> 40googlegroups.com
>>> <https://groups.google.com/d/msgid/elixir-lang-core/f5f75451-93dc-4163-bd9a-7055dab69d62%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4L8_NjAkcGp%3Df2u%2B2kcSSj6fZX0fvfT8icqMr7pyi3Kcw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to