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