1%% Handle code related to args, guard and -> matching for case,
2%% fn, receive and friends. try is handled in elixir_try.
3-module(elixir_clauses).
4-export([match/4, clause/5, def/2, head/2, head/3,
5         'case'/3, 'receive'/3, 'try'/3, 'cond'/3, with/3,
6         format_error/1]).
7-import(elixir_errors, [form_error/4, form_warn/4]).
8-include("elixir.hrl").
9
10match(Fun, Expr, E, #{context := match}) ->
11  Fun(Expr, E);
12match(Fun, Expr, #{current_vars := Current, unused_vars := {_, Counter} = Unused} = AfterE, BeforeE) ->
13  #{
14    context := Context,
15    prematch_vars := Prematch,
16    current_vars := {Read, _}
17  } = BeforeE,
18
19  CallE = BeforeE#{
20    context := match,
21    prematch_vars := {Read, Counter},
22    current_vars := Current,
23    unused_vars := Unused
24  },
25
26  {EExpr, #{current_vars := NewCurrent, unused_vars := NewUnused}} = Fun(Expr, CallE),
27
28  EndE = AfterE#{
29    context := Context,
30    prematch_vars := Prematch,
31    current_vars := NewCurrent,
32    unused_vars := NewUnused
33  },
34
35  {EExpr, EndE}.
36
37def({Meta, Args, Guards, Body}, E) ->
38  {EArgs, EA}   = elixir_expand:expand_args(Args, E#{context := match, prematch_vars := {#{}, 0}}),
39  {EGuards, EG} = guard(Guards, EA#{context := guard, prematch_vars := warn}),
40  {EBody, EB}   = elixir_expand:expand(Body, EG#{context := nil}),
41  elixir_env:check_unused_vars(EB),
42  {Meta, EArgs, EGuards, EBody}.
43
44clause(Meta, Kind, Fun, {'->', ClauseMeta, [_, _]} = Clause, E) when is_function(Fun, 3) ->
45  clause(Meta, Kind, fun(X, Acc) -> Fun(ClauseMeta, X, Acc) end, Clause, E);
46clause(_Meta, _Kind, Fun, {'->', Meta, [Left, Right]}, E) ->
47  {ELeft, EL}  = Fun(Left, E),
48  {ERight, ER} = elixir_expand:expand(Right, EL),
49  {{'->', Meta, [ELeft, ERight]}, ER};
50clause(Meta, Kind, _Fun, _, E) ->
51  form_error(Meta, E, ?MODULE, {bad_or_missing_clauses, Kind}).
52
53head(Args, E) ->
54  head(Args, E, E).
55head([{'when', Meta, [_ | _] = All}], AfterE, BeforeE) ->
56  {Args, Guard} = elixir_utils:split_last(All),
57
58  {{EArgs, EGuard}, EG} =
59    match(fun(ok, EM) ->
60      {EArgs, EA} = elixir_expand:expand_args(Args, EM),
61      {EGuard, EG} = guard(Guard, EA#{context := guard, prematch_vars := ?key(BeforeE, prematch_vars)}),
62      {{EArgs, EGuard}, EG}
63    end, ok, AfterE, BeforeE),
64
65  {[{'when', Meta, EArgs ++ [EGuard]}], EG};
66head(Args, AfterE, BeforeE) ->
67  match(fun elixir_expand:expand_args/2, Args, AfterE, BeforeE).
68
69guard({'when', Meta, [Left, Right]}, E) ->
70  {ELeft, EL}  = guard(Left, E),
71  {ERight, ER} = guard(Right, EL),
72  {{'when', Meta, [ELeft, ERight]}, ER};
73guard(Guard, E) ->
74  {EGuard, EG} = elixir_expand:expand(Guard, E),
75  warn_zero_length_guard(EGuard, EG),
76  {EGuard, EG}.
77
78warn_zero_length_guard({{'.', _, [erlang, Op]}, Meta,
79                        [{{'.', _, [erlang, length]}, _, [Arg]}, 0]}, E) when Op == '=='; Op == '>' ->
80  Warn =
81    case Op of
82      '==' -> {zero_list_length_in_guard, Arg};
83      '>' -> {positive_list_length_in_guard, Arg}
84    end,
85  form_warn(Meta, ?key(E, file), ?MODULE, Warn);
86warn_zero_length_guard({Op, _, [L, R]}, E) when Op == 'or'; Op == 'and' ->
87  warn_zero_length_guard(L, E),
88  warn_zero_length_guard(R, E);
89warn_zero_length_guard(_, _) ->
90  ok.
91
92%% Case
93
94'case'(Meta, [], E) ->
95  form_error(Meta, E, elixir_expand, {missing_option, 'case', [do]});
96'case'(Meta, Opts, E) when not is_list(Opts) ->
97  form_error(Meta, E, elixir_expand, {invalid_args, 'case'});
98'case'(Meta, Opts, E) ->
99  ok = assert_at_most_once('do', Opts, 0, fun(Key) ->
100    form_error(Meta, E, ?MODULE, {duplicated_clauses, 'case', Key})
101  end),
102  lists:mapfoldl(fun(X, Acc) -> expand_case(Meta, X, Acc) end, E, Opts).
103
104expand_case(Meta, {'do', _} = Do, E) ->
105  Fun = expand_head(Meta, 'case', 'do'),
106  expand_clauses(Meta, 'case', Fun, Do, E);
107expand_case(Meta, {Key, _}, E) ->
108  form_error(Meta, E, ?MODULE, {unexpected_option, 'case', Key}).
109
110%% Cond
111
112'cond'(Meta, [], E) ->
113  form_error(Meta, E, elixir_expand, {missing_option, 'cond', [do]});
114'cond'(Meta, Opts, E) when not is_list(Opts) ->
115  form_error(Meta, E, elixir_expand, {invalid_args, 'cond'});
116'cond'(Meta, Opts, E) ->
117  ok = assert_at_most_once('do', Opts, 0, fun(Key) ->
118    form_error(Meta, E, ?MODULE, {duplicated_clauses, 'cond', Key})
119  end),
120  lists:mapfoldl(fun(X, Acc) -> expand_cond(Meta, X, Acc) end, E, Opts).
121
122expand_cond(Meta, {'do', _} = Do, E) ->
123  Fun = expand_one(Meta, 'cond', 'do', fun elixir_expand:expand_args/2),
124  expand_clauses(Meta, 'cond', Fun, Do, E);
125expand_cond(Meta, {Key, _}, E) ->
126  form_error(Meta, E, ?MODULE, {unexpected_option, 'cond', Key}).
127
128%% Receive
129
130'receive'(Meta, [], E) ->
131  form_error(Meta, E, elixir_expand, {missing_option, 'receive', [do, 'after']});
132'receive'(Meta, Opts, E) when not is_list(Opts) ->
133  form_error(Meta, E, elixir_expand, {invalid_args, 'receive'});
134'receive'(Meta, Opts, E) ->
135  RaiseError = fun(Key) ->
136    form_error(Meta, E, ?MODULE, {duplicated_clauses, 'receive', Key})
137  end,
138  ok = assert_at_most_once('do', Opts, 0, RaiseError),
139  ok = assert_at_most_once('after', Opts, 0, RaiseError),
140  lists:mapfoldl(fun(X, Acc) -> expand_receive(Meta, X, Acc) end, E, Opts).
141
142expand_receive(_Meta, {'do', {'__block__', _, []}} = Do, E) ->
143  {Do, E};
144expand_receive(Meta, {'do', _} = Do, E) ->
145  Fun = expand_head(Meta, 'receive', 'do'),
146  expand_clauses(Meta, 'receive', Fun, Do, E);
147expand_receive(Meta, {'after', [_]} = After, E) ->
148  Fun = expand_one(Meta, 'receive', 'after', fun elixir_expand:expand_args/2),
149  expand_clauses(Meta, 'receive', Fun, After, E);
150expand_receive(Meta, {'after', _}, E) ->
151  form_error(Meta, E, ?MODULE, multiple_after_clauses_in_receive);
152expand_receive(Meta, {Key, _}, E) ->
153  form_error(Meta, E, ?MODULE, {unexpected_option, 'receive', Key}).
154
155%% With
156
157with(Meta, Args, E) ->
158  {Exprs, Opts0} =
159    case elixir_utils:split_last(Args) of
160      {_, LastArg} = SplitResult when is_list(LastArg) ->
161        SplitResult;
162      _ ->
163        {Args, []}
164    end,
165
166  E0 = elixir_env:reset_unused_vars(E),
167  {EExprs, {E1, HasMatch}} = lists:mapfoldl(fun expand_with/2, {E0, false}, Exprs),
168  {EDo, Opts1, E2} = expand_with_do(Meta, Opts0, E, E1),
169  {EOpts, Opts2, E3} = expand_with_else(Meta, Opts1, E2, HasMatch),
170
171  case Opts2 of
172    [{Key, _} | _] ->
173      form_error(Meta, E, elixir_clauses, {unexpected_option, with, Key});
174    [] ->
175      ok
176  end,
177
178  {{with, Meta, EExprs ++ [[{do, EDo} | EOpts]]}, E3}.
179
180expand_with({'<-', Meta, [{Name, _, Ctx}, _] = Args}, Acc) when is_atom(Name), is_atom(Ctx) ->
181  expand_with({'=', Meta, Args}, Acc);
182expand_with({'<-', Meta, [Left, Right]}, {E, _HasMatch}) ->
183  {ERight, ER} = elixir_expand:expand(Right, E),
184  {[ELeft], EL}  = head([Left], ER, E),
185  {{'<-', Meta, [ELeft, ERight]}, {EL, true}};
186expand_with(Expr, {E, HasMatch}) ->
187  {EExpr, EE} = elixir_expand:expand(Expr, E),
188  {EExpr, {EE, HasMatch}}.
189
190expand_with_do(Meta, Opts, E, Acc) ->
191  case lists:keytake(do, 1, Opts) of
192    {value, {do, Expr}, RestOpts} ->
193      {EExpr, EAcc} = elixir_expand:expand(Expr, Acc),
194      {EExpr, RestOpts, elixir_env:merge_and_check_unused_vars(E, EAcc)};
195    false ->
196      form_error(Meta, E, elixir_expand, {missing_option, 'with', [do]})
197  end.
198
199expand_with_else(Meta, Opts, E, HasMatch) ->
200  case lists:keytake(else, 1, Opts) of
201    {value, Pair, RestOpts} ->
202      if
203        HasMatch -> ok;
204        true -> form_warn(Meta, ?key(E, file), ?MODULE, unmatchable_else_in_with)
205      end,
206      Fun = expand_head(Meta, 'with', 'else'),
207      {EPair, EE} = expand_clauses(Meta, 'with', Fun, Pair, E),
208      {[EPair], RestOpts, EE};
209    false ->
210      {[], Opts, E}
211  end.
212
213%% Try
214
215'try'(Meta, [], E) ->
216  form_error(Meta, E, elixir_expand, {missing_option, 'try', [do]});
217'try'(Meta, [{do, _}], E) ->
218  form_error(Meta, E, elixir_expand, {missing_option, 'try', ['catch', 'rescue', 'after']});
219'try'(Meta, Opts, E) when not is_list(Opts) ->
220  form_error(Meta, E, elixir_expand, {invalid_args, 'try'});
221'try'(Meta, Opts, E) ->
222  % TODO: Make this an error on v2.0
223  case Opts of
224    [{do, _}, {else, _}] ->
225      form_warn(Meta, ?key(E, file), ?MODULE, {try_with_only_else_clause, origin(Meta, 'try')});
226    _ ->
227      ok
228  end,
229  RaiseError = fun(Key) ->
230    form_error(Meta, E, ?MODULE, {duplicated_clauses, 'try', Key})
231  end,
232  ok = assert_at_most_once('do', Opts, 0, RaiseError),
233  ok = assert_at_most_once('rescue', Opts, 0, RaiseError),
234  ok = assert_at_most_once('catch', Opts, 0, RaiseError),
235  ok = assert_at_most_once('else', Opts, 0, RaiseError),
236  ok = assert_at_most_once('after', Opts, 0, RaiseError),
237  ok = warn_catch_before_rescue(Opts, Meta, E, false),
238  lists:mapfoldl(fun(X, Acc) -> expand_try(Meta, X, Acc) end, E, Opts).
239
240expand_try(_Meta, {'do', Expr}, E) ->
241  {EExpr, EE} = elixir_expand:expand(Expr, elixir_env:reset_unused_vars(E)),
242  {{'do', EExpr}, elixir_env:merge_and_check_unused_vars(E, EE)};
243expand_try(_Meta, {'after', Expr}, E) ->
244  {EExpr, EE} = elixir_expand:expand(Expr, elixir_env:reset_unused_vars(E)),
245  {{'after', EExpr}, elixir_env:merge_and_check_unused_vars(E, EE)};
246expand_try(Meta, {'else', _} = Else, E) ->
247  Fun = expand_head(Meta, 'try', 'else'),
248  expand_clauses(Meta, 'try', Fun, Else, E);
249expand_try(Meta, {'catch', _} = Catch, E) ->
250  expand_clauses_with_stacktrace(Meta, fun expand_catch/3, Catch, E);
251expand_try(Meta, {'rescue', _} = Rescue, E) ->
252  expand_clauses_with_stacktrace(Meta, fun expand_rescue/3, Rescue, E);
253expand_try(Meta, {Key, _}, E) ->
254  form_error(Meta, E, ?MODULE, {unexpected_option, 'try', Key}).
255
256expand_clauses_with_stacktrace(Meta, Fun, Clauses, E) ->
257  OldContextualVars = ?key(E, contextual_vars),
258  ES = E#{contextual_vars := ['__STACKTRACE__' | OldContextualVars]},
259  {Ret, EE} = expand_clauses(Meta, 'try', Fun, Clauses, ES),
260  {Ret, EE#{contextual_vars := OldContextualVars}}.
261
262expand_catch(_Meta, [_] = Args, E) ->
263  head(Args, E);
264expand_catch(_Meta, [_, _] = Args, E) ->
265  head(Args, E);
266expand_catch(Meta, _, E) ->
267  Error = {wrong_number_of_args_for_clause, "one or two args", origin(Meta, 'try'), 'catch'},
268  form_error(Meta, E, ?MODULE, Error).
269
270expand_rescue(Meta, [Arg], E) ->
271  case expand_rescue(Arg, E) of
272    {EArg, EA} ->
273      {[EArg], EA};
274    false ->
275      form_error(Meta, E, ?MODULE, invalid_rescue_clause)
276  end;
277expand_rescue(Meta, _, E) ->
278  Error = {wrong_number_of_args_for_clause, "one argument", origin(Meta, 'try'), 'rescue'},
279  form_error(Meta, E, ?MODULE, Error).
280
281%% rescue var
282expand_rescue({Name, _, Atom} = Var, E) when is_atom(Name), is_atom(Atom) ->
283  match(fun elixir_expand:expand/2, Var, E, E);
284
285%% rescue var in _ => rescue var
286expand_rescue({in, _, [{Name, _, VarContext} = Var, {'_', _, UnderscoreContext}]}, E)
287    when is_atom(Name), is_atom(VarContext), is_atom(UnderscoreContext) ->
288  expand_rescue(Var, E);
289
290%% rescue var in [Exprs]
291expand_rescue({in, Meta, [Left, Right]}, E) ->
292  {ELeft, EL}  = match(fun elixir_expand:expand/2, Left, E, E),
293  {ERight, ER} = elixir_expand:expand(Right, EL),
294
295  case ELeft of
296    {Name, _, Atom} when is_atom(Name), is_atom(Atom) ->
297      case normalize_rescue(ERight) of
298        false -> false;
299        Other -> {{in, Meta, [ELeft, Other]}, ER}
300      end;
301    _ ->
302      false
303  end;
304
305%% rescue Error => _ in [Error]
306expand_rescue(Arg, E) ->
307  expand_rescue({in, [], [{'_', [], ?key(E, module)}, Arg]}, E).
308
309normalize_rescue({'_', _, Atom} = N) when is_atom(Atom) -> N;
310normalize_rescue(Atom) when is_atom(Atom) -> [Atom];
311normalize_rescue(Other) ->
312  is_list(Other) andalso lists:all(fun is_atom/1, Other) andalso Other.
313
314%% Expansion helpers
315
316expand_head(Meta, Kind, Key) ->
317  fun
318    ([{'when', _, [_, _, _ | _]}], E) ->
319      form_error(Meta, E, ?MODULE, {wrong_number_of_args_for_clause, "one argument", Kind, Key});
320    ([_] = Args, E) ->
321      head(Args, E);
322    (_, E) ->
323      form_error(Meta, E, ?MODULE, {wrong_number_of_args_for_clause, "one argument", Kind, Key})
324  end.
325
326%% Returns a function that expands arguments
327%% considering we have at maximum one entry.
328expand_one(Meta, Kind, Key, Fun) ->
329  fun
330    ([_] = Args, E) ->
331      Fun(Args, E);
332    (_, E) ->
333      form_error(Meta, E, ?MODULE, {wrong_number_of_args_for_clause, "one argument", Kind, Key})
334  end.
335
336%% Expands all -> pairs in a given key but do not keep the overall vars.
337expand_clauses(Meta, Kind, Fun, Clauses, E) ->
338  NewKind = origin(Meta, Kind),
339  expand_clauses_origin(Meta, NewKind, Fun, Clauses, E).
340
341expand_clauses_origin(Meta, Kind, Fun, {Key, [_ | _] = Clauses}, E) ->
342  Transformer = fun(Clause, Acc) ->
343    {EClause, EAcc} = clause(Meta, {Kind, Key}, Fun, Clause, elixir_env:reset_unused_vars(Acc)),
344    {EClause, elixir_env:merge_and_check_unused_vars(Acc, EAcc)}
345  end,
346  {Values, EE} = lists:mapfoldl(Transformer, E, Clauses),
347  {{Key, Values}, EE};
348expand_clauses_origin(Meta, Kind, _Fun, {Key, _}, E) ->
349  form_error(Meta, E, ?MODULE, {bad_or_missing_clauses, {Kind, Key}}).
350
351assert_at_most_once(_Kind, [], _Count, _Fun) -> ok;
352assert_at_most_once(Kind, [{Kind, _} | _], 1, ErrorFun) ->
353  ErrorFun(Kind);
354assert_at_most_once(Kind, [{Kind, _} | Rest], Count, Fun) ->
355  assert_at_most_once(Kind, Rest, Count + 1, Fun);
356assert_at_most_once(Kind, [_ | Rest], Count, Fun) ->
357  assert_at_most_once(Kind, Rest, Count, Fun).
358
359warn_catch_before_rescue([], _, _, _) ->
360  ok;
361warn_catch_before_rescue([{'rescue', _} | _], Meta, E, true) ->
362  form_warn(Meta, ?key(E, file), ?MODULE, {catch_before_rescue, origin(Meta, 'try')});
363warn_catch_before_rescue([{'catch', _} | Rest], Meta, E, _) ->
364  warn_catch_before_rescue(Rest, Meta, E, true);
365warn_catch_before_rescue([_ | Rest], Meta, E, Found) ->
366  warn_catch_before_rescue(Rest, Meta, E, Found).
367
368origin(Meta, Default) ->
369  case lists:keyfind(origin, 1, Meta) of
370    {origin, Origin} -> Origin;
371    false -> Default
372  end.
373
374format_error({bad_or_missing_clauses, {Kind, Key}}) ->
375  io_lib:format("expected -> clauses for :~ts in \"~ts\"", [Key, Kind]);
376format_error({bad_or_missing_clauses, Kind}) ->
377  io_lib:format("expected -> clauses in \"~ts\"", [Kind]);
378
379format_error({duplicated_clauses, Kind, Key}) ->
380  io_lib:format("duplicated :~ts clauses given for \"~ts\"", [Key, Kind]);
381
382format_error({unexpected_option, Kind, Option}) ->
383  io_lib:format("unexpected option ~ts in \"~ts\"", ['Elixir.Macro':to_string(Option), Kind]);
384
385format_error({wrong_number_of_args_for_clause, Expected, Kind, Key}) ->
386  io_lib:format("expected ~ts for :~ts clauses (->) in \"~ts\"", [Expected, Key, Kind]);
387
388format_error(multiple_after_clauses_in_receive) ->
389  "expected a single -> clause for :after in \"receive\"";
390
391format_error(invalid_rescue_clause) ->
392  "invalid \"rescue\" clause. The clause should match on an alias, a variable "
393    "or be in the \"var in [alias]\" format";
394
395format_error({catch_before_rescue, Origin}) ->
396  io_lib:format("\"catch\" should always come after \"rescue\" in ~ts", [Origin]);
397
398format_error({try_with_only_else_clause, Origin}) ->
399  io_lib:format("\"else\" shouldn't be used as the only clause in \"~ts\", use \"case\" instead",
400                [Origin]);
401
402format_error(unmatchable_else_in_with) ->
403  "\"else\" clauses will never match because all patterns in \"with\" will always match";
404
405format_error({zero_list_length_in_guard, ListArg}) ->
406  Arg = 'Elixir.Macro':to_string(ListArg),
407  io_lib:format("do not use \"length(~ts) == 0\" to check if a list is empty since length "
408                "always traverses the whole list. Prefer to pattern match on an empty list or "
409                "use \"~ts == []\" as a guard", [Arg, Arg]);
410
411format_error({positive_list_length_in_guard, ListArg}) ->
412  Arg = 'Elixir.Macro':to_string(ListArg),
413  io_lib:format("do not use \"length(~ts) > 0\" to check if a list is not empty since length "
414                "always traverses the whole list. Prefer to pattern match on a non-empty list, "
415                "such as [_ | _], or use \"~ts != []\" as a guard", [Arg, Arg]).
416