@@ -46,7 +46,7 @@ translate({'__CALLER__', Meta, Atom}, #elixir_erl{def=Kind}=S) when is_atom(Atom
4646 {{atom , ? ann (Meta ), nil }, S }
4747 end ;
4848
49- translate ({'super' , Meta , [{Kind ,Name }| Args ]}, S ) ->
49+ translate ({'super' , Meta , [{Kind , Name } | Args ]}, S ) ->
5050 % % In the expanded AST, super is used to invoke a function
5151 % % in the current module originated from a default clause
5252 % % or a super call.
@@ -76,8 +76,8 @@ translate({'&', Meta, [{'/', _, [{Fun, _, Atom}, Arity]}]}, S)
7676translate ({fn , Meta , Clauses }, S ) ->
7777 Transformer = fun ({'->' , CMeta , [ArgsWithGuards , Expr ]}, Acc ) ->
7878 {Args , Guards } = elixir_utils :extract_splat_guards (ArgsWithGuards ),
79- {TClause , TS } = elixir_erl_clauses :clause (CMeta , fun translate_fn_match /2 ,
80- Args , Expr , Guards , Acc ),
79+ {TClause , TS } = elixir_erl_clauses :clause (CMeta , fun translate_fn_match /2 ,
80+ Args , Expr , Guards , Acc ),
8181 {TClause , elixir_erl_var :mergec (S , TS )}
8282 end ,
8383 {TClauses , NS } = lists :mapfoldl (Transformer , S , Clauses ),
@@ -107,29 +107,28 @@ translate({'case', Meta, [Expr, Opts]}, S) ->
107107% % Try
108108
109109translate ({'try' , Meta , [Opts ]}, S ) ->
110- SN = S # elixir_erl {extra = nil },
111110 Do = proplists :get_value ('do' , Opts , nil ),
112- {TDo , SB } = translate (Do , SN ),
111+ {TDo , SB } = translate (Do , S ),
113112
114113 Catch = [Tuple || {X , _ } = Tuple <- Opts , X == 'rescue' orelse X == 'catch' ],
115- {TCatch , SC } = elixir_erl_try :clauses (Meta , Catch , mergec (SN , SB )),
114+ {TCatch , SC } = elixir_erl_try :clauses (Meta , Catch , mergec (S , SB )),
116115
117116 {TAfter , SA } = case lists :keyfind ('after' , 1 , Opts ) of
118117 {'after' , After } ->
119- {TBlock , SAExtracted } = translate (After , mergec (SN , SC )),
118+ {TBlock , SAExtracted } = translate (After , mergec (S , SC )),
120119 {unblock (TBlock ), SAExtracted };
121120 false ->
122- {[], mergec (SN , SC )}
121+ {[], mergec (S , SC )}
123122 end ,
124123
125124 Else = elixir_erl_clauses :get_clauses (else , Opts , match ),
126- {TElse , SE } = elixir_erl_clauses :clauses (Meta , Else , mergec (SN , SA )),
125+ {TElse , SE } = elixir_erl_clauses :clauses (Meta , Else , mergec (S , SA )),
127126 {{'try' , ? ann (Meta ), unblock (TDo ), TElse , TCatch , TAfter }, mergec (S , SE )};
128127
129128% % Receive
130129
131130translate ({'receive' , Meta , [Opts ]}, S ) ->
132- Do = elixir_erl_clauses :get_clauses (do , Opts , match , true ),
131+ Do = elixir_erl_clauses :get_clauses (do , Opts , match ),
133132
134133 case lists :keyfind ('after' , 1 , Opts ) of
135134 false ->
@@ -143,11 +142,17 @@ translate({'receive', Meta, [Opts]}, S) ->
143142 {{'receive' , ? ann (Meta ), FClauses , FExpr , FAfter }, SC }
144143 end ;
145144
146- % % Comprehensions
145+ % % Comprehensions and with
147146
148147translate ({for , Meta , [_ | _ ] = Args }, S ) ->
149148 elixir_erl_for :translate (Meta , Args , true , S );
150149
150+ translate ({with , Meta , [_ | _ ] = Args }, S ) ->
151+ {Exprs , [{do , Do } | Opts ]} = elixir_utils :split_last (Args ),
152+ {ElseClause , SE } = translate_with_else (Meta , Opts , S ),
153+ {With , SD } = translate_with_do (Exprs , Do , ElseClause , elixir_erl_var :mergec (S , SE )),
154+ {With , elixir_erl_var :mergec (S , SD )};
155+
151156% % Variables
152157
153158translate ({'^' , Meta , [{Name , VarMeta , Kind }]}, # elixir_erl {context = match , file = File } = S ) when is_atom (Name ), is_atom (Kind ) ->
@@ -240,10 +245,10 @@ translate(Other, S) ->
240245translate_case (true , Meta , Expr , Opts , S ) ->
241246 Clauses = elixir_erl_clauses :get_clauses (do , Opts , match ),
242247 {TExpr , SE } = translate (Expr , S ),
243- {TClauses , SC } = elixir_erl_clauses :clauses (Meta , Clauses , SE # elixir_erl { extra = nil } ),
244- {{'case' , ? ann (Meta ), TExpr , TClauses }, SC # elixir_erl { extra = SE # elixir_erl . extra } };
248+ {TClauses , SC } = elixir_erl_clauses :clauses (Meta , Clauses , SE ),
249+ {{'case' , ? ann (Meta ), TExpr , TClauses }, SC };
245250translate_case (false , Meta , Expr , Opts , S ) ->
246- {Case , SC } = translate_case (true , Meta , Expr , Opts , S # elixir_erl { extra = nil } ),
251+ {Case , SC } = translate_case (true , Meta , Expr , Opts , S ),
247252 {Case , elixir_erl_var :mergec (S , SC )}.
248253
249254translate_list ([{'|' , _ , [_ , _ ]= Args }], Fun , Acc , List ) ->
@@ -355,6 +360,43 @@ returns_boolean(Condition, Body) ->
355360 false -> false
356361 end .
357362
363+ % % with
364+
365+ translate_with_else (Meta , [], S ) ->
366+ Ann = ? ann (? generated (Meta )),
367+ {VarName , _ , SC } = elixir_erl_var :build ('_' , S ),
368+ Var = {var , Ann , VarName },
369+ {{clause , Ann , [Var ], [], [Var ]}, SC };
370+ translate_with_else (Meta , [{else , Else }], S ) ->
371+ Generated = ? generated (Meta ),
372+ ElseVarEx = {else , Generated , ? var_context },
373+ {ElseVarErl , SV } = elixir_erl_var :assign (Generated , else , ? var_context , S ),
374+
375+ RaiseVar = {catch_all , Generated , ? var_context },
376+ RaiseExpr = {{'.' , Generated , [erlang , error ]}, Generated , [{with_clause , RaiseVar }]},
377+ RaiseClause = {'->' , Generated , [[RaiseVar ], RaiseExpr ]},
378+
379+ Case = {'case' , [{export_vars , false } | Meta ], [ElseVarEx , [{do , Else ++ [RaiseClause ]}]]},
380+ {TranslatedCase , SC } = elixir_erl_pass :translate (Case , SV ),
381+ {{clause , ? ann (Generated ), [ElseVarErl ], [], [TranslatedCase ]}, SC }.
382+
383+ translate_with_do ([{'<-' , Meta , [Left , Expr ]} | Rest ], Do , Else , S ) ->
384+ {Args , Guards } = elixir_utils :extract_guards (Left ),
385+ {TExpr , SR } = elixir_erl_pass :translate (Expr , S ),
386+ {TArgs , SA } = elixir_erl_clauses :match (fun elixir_erl_pass :translate /2 , Args , SR ),
387+ TGuards = elixir_erl_clauses :guards (Guards , [], SA ),
388+ {TBody , SB } = translate_with_do (Rest , Do , Else , SA ),
389+
390+ Ann = ? ann (? generated (Meta )),
391+ Clause = {clause , Ann , [TArgs ], TGuards , unblock (TBody )},
392+ {{'case' , Ann , TExpr , [Clause , Else ]}, SB };
393+ translate_with_do ([Expr | Rest ], Do , Else , S ) ->
394+ {TExpr , TS } = elixir_erl_pass :translate (Expr , S ),
395+ {TRest , RS } = translate_with_do (Rest , Do , Else , TS ),
396+ {{block , 0 , [TExpr | unblock (TRest )]}, RS };
397+ translate_with_do ([], Do , _Else , S ) ->
398+ elixir_erl_pass :translate (Do , S ).
399+
358400% % Maps and structs
359401
360402translate_map (Meta , [{'|' , _Meta , [Update , Assocs ]}], S ) ->
0 commit comments