@@ -8,6 +8,14 @@ defmodule Macro do
8
8
@ doc """
9
9
Returns a list of binary operators. This is available
10
10
as a macro so it can be used in guard clauses.
11
+
12
+ ## Note
13
+
14
+ There is a bug in dialyzer that makes it hang (it actually
15
+ just takes a huge amount of time) when using `in` with a huge
16
+ list. That said, using `atom in Macro.binary_op` will trigger
17
+ this bug and should be avoided in modules you want to use
18
+ dialyzer with.
11
19
"""
12
20
defmacro binary_ops do
13
21
[
@@ -198,22 +206,24 @@ defmodule Macro do
198
206
"&#{ num } "
199
207
end
200
208
201
- # Binary ops
202
- def to_binary ( { op , _ , [ left , right ] } ) when op in binary_ops do
203
- op_to_binary ( left ) <> " #{ op } " <> op_to_binary ( right )
204
- end
205
-
206
- # Unary ops
207
- def to_binary ( { op , _ , [ arg ] } ) when op in unary_ops do
208
- atom_to_binary ( op , :utf8 ) <> to_binary ( arg )
209
- end
210
-
211
- # All other calls
209
+ # Binary, unary ops and other calls
210
+ #
211
+ # Originally, binary and unary ops were different function
212
+ # clauses but they were causing dialyzer to hang. We have
213
+ # rewritten it as `cond` as it seems to be fine to dialyzer.
212
214
def to_binary ( { target , _ , args } ) when is_list ( args ) do
213
- { list , last } = :elixir_tree_helpers . split_last ( args )
214
- case is_kw_blocks? ( last ) do
215
- true -> call_to_binary_with_args ( target , list ) <> kw_blocks_to_binary ( last )
216
- false -> call_to_binary_with_args ( target , args )
215
+ cond do
216
+ is_atom ( target ) and List . member? ( binary_ops , target ) and length ( args ) == 2 ->
217
+ [ left , right ] = args
218
+ op_to_binary ( left ) <> " #{ target } " <> op_to_binary ( right )
219
+ is_atom ( target ) and List . member? ( unary_ops , target ) and length ( args ) == 1 ->
220
+ atom_to_binary ( target , :utf8 ) <> to_binary ( hd ( args ) )
221
+ true ->
222
+ { list , last } = :elixir_tree_helpers . split_last ( args )
223
+ case is_kw_blocks? ( last ) do
224
+ true -> call_to_binary_with_args ( target , list ) <> kw_blocks_to_binary ( last )
225
+ false -> call_to_binary_with_args ( target , args )
226
+ end
217
227
end
218
228
end
219
229
@@ -278,8 +288,13 @@ defmodule Macro do
278
288
279
289
defp block_to_binary ( other ) , do: to_binary ( other )
280
290
281
- defp op_to_binary ( { op , _ , [ _ , _ ] } = expr ) when op in binary_ops do
282
- "(" <> to_binary ( expr ) <> ")"
291
+ defp op_to_binary ( { op , _ , [ _ , _ ] } = expr ) do
292
+ # Avoid op in binary_ops due to dialyzer bug
293
+ if List . member? ( binary_ops , op ) do
294
+ "(" <> to_binary ( expr ) <> ")"
295
+ else
296
+ to_binary ( expr )
297
+ end
283
298
end
284
299
285
300
defp op_to_binary ( expr ) , do: to_binary ( expr )
0 commit comments