@@ -47,6 +47,9 @@ guard(Other, E) ->
47
47
'case' (Meta , KV , E ) when not is_list (KV ) ->
48
48
compile_error (Meta , ? m (E , file ), " invalid arguments for case" );
49
49
'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 ),
50
53
EE = E #{export_vars := []},
51
54
{EClauses , EVars } = lists :mapfoldl (fun (X , Acc ) -> do_case (Meta , X , Acc , EE ) end , [], KV ),
52
55
{EClauses , elixir_env :mergev (EVars , E )}.
@@ -64,6 +67,9 @@ do_case(Meta, {Key, _}, _Acc, E) ->
64
67
'cond' (Meta , KV , E ) when not is_list (KV ) ->
65
68
compile_error (Meta , ? m (E , file ), " invalid arguments for cond" );
66
69
'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 ),
67
73
EE = E #{export_vars := []},
68
74
{EClauses , EVars } = lists :mapfoldl (fun (X , Acc ) -> do_cond (Meta , X , Acc , EE ) end , [], KV ),
69
75
{EClauses , elixir_env :mergev (EVars , E )}.
@@ -81,6 +87,11 @@ do_cond(Meta, {Key, _}, _Acc, E) ->
81
87
'receive' (Meta , KV , E ) when not is_list (KV ) ->
82
88
compile_error (Meta , ? m (E , file ), " invalid arguments for receive" );
83
89
'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 ),
84
95
EE = E #{export_vars := []},
85
96
{EClauses , EVars } = lists :mapfoldl (fun (X , Acc ) -> do_receive (Meta , X , Acc , EE ) end , [], KV ),
86
97
{EClauses , elixir_env :mergev (EVars , E )}.
@@ -105,8 +116,16 @@ do_receive(Meta, {Key, _}, _Acc, E) ->
105
116
'try' (Meta , [{do , _ }], E ) ->
106
117
compile_error (Meta , ? m (E , file ), " missing catch/rescue/after/else keyword in try" );
107
118
'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" );
109
120
'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 ),
110
129
{lists :map (fun (X ) -> do_try (Meta , X , E ) end , KV ), E }.
111
130
112
131
do_try (_Meta , {'do' , Expr }, E ) ->
@@ -214,3 +233,11 @@ expand_without_export(Meta, Kind, Fun, {Key, Clauses}, E) when is_list(Clauses)
214
233
{Key , lists :map (Transformer , Clauses )};
215
234
expand_without_export (Meta , Kind , _Fun , {Key , _ }, E ) ->
216
235
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