@@ -47,6 +47,9 @@ guard(Other, E) ->
4747'case' (Meta , KV , E ) when not is_list (KV ) ->
4848 compile_error (Meta , ? m (E , file ), " invalid arguments for case" );
4949'case' (Meta , KV , E ) ->
50+ ok = assert_at_most_once ('do' , KV , 0 , fun (Kind ) ->
51+ compile_error (Meta , ? m (E , file ), " duplicated ~ts clauses given for case" , [Kind ])
52+ end ),
5053 EE = E #{export_vars := []},
5154 {EClauses , EVars } = lists :mapfoldl (fun (X , Acc ) -> do_case (Meta , X , Acc , EE ) end , [], KV ),
5255 {EClauses , elixir_env :mergev (EVars , E )}.
@@ -64,6 +67,9 @@ do_case(Meta, {Key, _}, _Acc, E) ->
6467'cond' (Meta , KV , E ) when not is_list (KV ) ->
6568 compile_error (Meta , ? m (E , file ), " invalid arguments for cond" );
6669'cond' (Meta , KV , E ) ->
70+ ok = assert_at_most_once ('do' , KV , 0 , fun (Kind ) ->
71+ compile_error (Meta , ? m (E , file ), " duplicated ~ts clauses given for cond" , [Kind ])
72+ end ),
6773 EE = E #{export_vars := []},
6874 {EClauses , EVars } = lists :mapfoldl (fun (X , Acc ) -> do_cond (Meta , X , Acc , EE ) end , [], KV ),
6975 {EClauses , elixir_env :mergev (EVars , E )}.
@@ -81,6 +87,11 @@ do_cond(Meta, {Key, _}, _Acc, E) ->
8187'receive' (Meta , KV , E ) when not is_list (KV ) ->
8288 compile_error (Meta , ? m (E , file ), " invalid arguments for receive" );
8389'receive' (Meta , KV , E ) ->
90+ RaiseError = fun (Kind ) ->
91+ compile_error (Meta , ? m (E , file ), " duplicated ~ts clauses given for receive" , [Kind ])
92+ end ,
93+ ok = assert_at_most_once ('do' , KV , 0 , RaiseError ),
94+ ok = assert_at_most_once ('after' , KV , 0 , RaiseError ),
8495 EE = E #{export_vars := []},
8596 {EClauses , EVars } = lists :mapfoldl (fun (X , Acc ) -> do_receive (Meta , X , Acc , EE ) end , [], KV ),
8697 {EClauses , elixir_env :mergev (EVars , E )}.
@@ -105,8 +116,16 @@ do_receive(Meta, {Key, _}, _Acc, E) ->
105116'try' (Meta , [{do , _ }], E ) ->
106117 compile_error (Meta , ? m (E , file ), " missing catch/rescue/after/else keyword in try" );
107118'try' (Meta , KV , E ) when not is_list (KV ) ->
108- elixir_errors : compile_error (Meta , ? m (E , file ), " invalid arguments for try" );
119+ compile_error (Meta , ? m (E , file ), " invalid arguments for try" );
109120'try' (Meta , KV , E ) ->
121+ RaiseError = fun (Kind ) ->
122+ compile_error (Meta , ? m (E , file ), " duplicated ~ts clauses given for try" , [Kind ])
123+ end ,
124+ ok = assert_at_most_once ('do' , KV , 0 , RaiseError ),
125+ ok = assert_at_most_once ('rescue' , KV , 0 , RaiseError ),
126+ ok = assert_at_most_once ('catch' , KV , 0 , RaiseError ),
127+ ok = assert_at_most_once ('else' , KV , 0 , RaiseError ),
128+ ok = assert_at_most_once ('after' , KV , 0 , RaiseError ),
110129 {lists :map (fun (X ) -> do_try (Meta , X , E ) end , KV ), E }.
111130
112131do_try (_Meta , {'do' , Expr }, E ) ->
@@ -214,3 +233,11 @@ expand_without_export(Meta, Kind, Fun, {Key, Clauses}, E) when is_list(Clauses)
214233 {Key , lists :map (Transformer , Clauses )};
215234expand_without_export (Meta , Kind , _Fun , {Key , _ }, E ) ->
216235 compile_error (Meta , ? m (E , file ), " expected -> clauses for ~ts in ~ts " , [Key , Kind ]).
236+
237+ assert_at_most_once (_Kind , [], _Count , _Fun ) -> ok ;
238+ assert_at_most_once (Kind , [{Kind , _ } | _ ], 1 , ErrorFun ) ->
239+ ErrorFun (Kind );
240+ assert_at_most_once (Kind , [{Kind , _ } | Rest ], Count , Fun ) ->
241+ assert_at_most_once (Kind , Rest , Count + 1 , Fun );
242+ assert_at_most_once (Kind , [_ | Rest ], Count , Fun ) ->
243+ assert_at_most_once (Kind , Rest , Count , Fun ).
0 commit comments