diff options
Diffstat (limited to 'lib/stdlib/src/erl_eval.erl')
-rw-r--r-- | lib/stdlib/src/erl_eval.erl | 111 |
1 files changed, 88 insertions, 23 deletions
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index 987ba0cf0a..f88cba1ba3 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2021. All Rights Reserved. +%% Copyright Ericsson AB 1996-2023. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -286,6 +286,8 @@ expr({lc,_,E,Qs}, Bs, Lf, Ef, RBs, FUVs) -> eval_lc(E, Qs, Bs, Lf, Ef, RBs, FUVs); expr({bc,_,E,Qs}, Bs, Lf, Ef, RBs, FUVs) -> eval_bc(E, Qs, Bs, Lf, Ef, RBs, FUVs); +expr({mc,_,E,Qs}, Bs, Lf, Ef, RBs, FUVs) -> + eval_mc(E, Qs, Bs, Lf, Ef, RBs, FUVs); expr({tuple,_,Es}, Bs0, Lf, Ef, RBs, FUVs) -> {Vs,Bs} = expr_list(Es, Bs0, Lf, Ef, FUVs), ret_expr(list_to_tuple(Vs), Bs, RBs); @@ -760,17 +762,15 @@ do_apply(F, _Anno, FunOrModFun, Args) when is_function(F, 2) -> eval_lc(E, Qs, Bs, Lf, Ef, RBs, FUVs) -> ret_expr(lists:reverse(eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, [])), Bs, RBs). -eval_lc1(E, [{generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) -> - {value,L1,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs), - CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end, - eval_generate(L1, P, Anno, Bs0, Lf, Ef, CompFun, Acc0); -eval_lc1(E, [{b_generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) -> - {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs), - CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end, - eval_b_generate(Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc0); -eval_lc1(E, [F|Qs], Bs0, Lf, Ef, FUVs, Acc) -> - CompFun = fun(Bs) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end, - eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc); +eval_lc1(E, [Q|Qs], Bs0, Lf, Ef, FUVs, Acc0) -> + case is_generator(Q) of + true -> + CF = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end, + eval_generator(Q, Bs0, Lf, Ef, FUVs, Acc0, CF); + false -> + CF = fun(Bs) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc0) end, + eval_filter(Q, Bs0, Lf, Ef, CF, FUVs, Acc0) + end; eval_lc1(E, [], Bs, Lf, Ef, FUVs, Acc) -> {value,V,_} = expr(E, Bs, Lf, Ef, none, FUVs), [V|Acc]. @@ -782,21 +782,66 @@ eval_lc1(E, [], Bs, Lf, Ef, FUVs, Acc) -> eval_bc(E, Qs, Bs, Lf, Ef, RBs, FUVs) -> ret_expr(eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, <<>>), Bs, RBs). -eval_bc1(E, [{b_generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) -> - {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs), - CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end, - eval_b_generate(Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc0); -eval_bc1(E, [{generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) -> - {value,List,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs), - CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end, - eval_generate(List, P, Anno, Bs0, Lf, Ef, CompFun, Acc0); -eval_bc1(E, [F|Qs], Bs0, Lf, Ef, FUVs, Acc) -> - CompFun = fun(Bs) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end, - eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc); +eval_bc1(E, [Q|Qs], Bs0, Lf, Ef, FUVs, Acc0) -> + case is_generator(Q) of + true -> + CF = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end, + eval_generator(Q, Bs0, Lf, Ef, FUVs, Acc0, CF); + false -> + CF = fun(Bs) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc0) end, + eval_filter(Q, Bs0, Lf, Ef, CF, FUVs, Acc0) + end; eval_bc1(E, [], Bs, Lf, Ef, FUVs, Acc) -> {value,V,_} = expr(E, Bs, Lf, Ef, none, FUVs), <<Acc/bitstring,V/bitstring>>. +%% eval_mc(Expr, [Qualifier], Bindings, LocalFunctionHandler, +%% ExternalFuncHandler, RetBindings) -> +%% {value,Value,Bindings} | Value + +eval_mc(E, Qs, Bs, Lf, Ef, RBs, FUVs) -> + L = eval_mc1(E, Qs, Bs, Lf, Ef, FUVs, []), + Map = maps:from_list(L), + ret_expr(Map, Bs, RBs). + +eval_mc1(E, [Q|Qs], Bs0, Lf, Ef, FUVs, Acc0) -> + case is_generator(Q) of + true -> + CF = fun(Bs, Acc) -> eval_mc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end, + eval_generator(Q, Bs0, Lf, Ef, FUVs, Acc0, CF); + false -> + CF = fun(Bs) -> eval_mc1(E, Qs, Bs, Lf, Ef, FUVs, Acc0) end, + eval_filter(Q, Bs0, Lf, Ef, CF, FUVs, Acc0) + end; +eval_mc1({map_field_assoc,Lfa,K0,V0}, [], Bs, Lf, Ef, FUVs, Acc) -> + {value,KV,_} = expr({tuple,Lfa,[K0,V0]}, Bs, Lf, Ef, none, FUVs), + [KV|Acc]. + +eval_generator({generate,Anno,P,L0}, Bs0, Lf, Ef, FUVs, Acc0, CompFun) -> + {value,L1,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs), + eval_generate(L1, P, Anno, Bs0, Lf, Ef, CompFun, Acc0); +eval_generator({b_generate,Anno,P,Bin0}, Bs0, Lf, Ef, FUVs, Acc0, CompFun) -> + {value,Bin,_Bs1} = expr(Bin0, Bs0, Lf, Ef, none, FUVs), + eval_b_generate(Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc0); +eval_generator({m_generate,Anno,P,Map0}, Bs0, Lf, Ef, FUVs, Acc0, CompFun) -> + {map_field_exact,_,K,V} = P, + {value,Map,_Bs1} = expr(Map0, Bs0, Lf, Ef, none, FUVs), + Iter = case is_map(Map) of + true -> + maps:iterator(Map); + false -> + %% Validate iterator. + try maps:foreach(fun(_, _) -> ok end, Map) of + _ -> + Map + catch + _:_ -> + apply_error({bad_generator,Map}, ?STACKTRACE, + Anno, Bs0, Ef, none) + end + end, + eval_m_generate(Iter, {tuple,Anno,[K,V]}, Anno, Bs0, Lf, Ef, CompFun, Acc0). + eval_generate([V|Rest], P, Anno, Bs0, Lf, Ef, CompFun, Acc) -> case match(P, V, Anno, new_bindings(Bs0), Bs0, Ef) of {match,Bsn} -> @@ -828,6 +873,21 @@ eval_b_generate(<<_/bitstring>>=Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc) -> eval_b_generate(Term, _P, Anno, Bs0, _Lf, Ef, _CompFun, _Acc) -> apply_error({bad_generator,Term}, ?STACKTRACE, Anno, Bs0, Ef, none). +eval_m_generate(Iter0, P, Anno, Bs0, Lf, Ef, CompFun, Acc0) -> + case maps:next(Iter0) of + {K,V,Iter} -> + case match(P, {K,V}, Anno, new_bindings(Bs0), Bs0, Ef) of + {match,Bsn} -> + Bs2 = add_bindings(Bsn, Bs0), + Acc = CompFun(Bs2, Acc0), + eval_m_generate(Iter, P, Anno, Bs0, Lf, Ef, CompFun, Acc); + nomatch -> + eval_m_generate(Iter, P, Anno, Bs0, Lf, Ef, CompFun, Acc0) + end; + none -> + Acc0 + end. + eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc) -> case erl_lint:is_guard_test(F) of true -> @@ -844,6 +904,11 @@ eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc) -> end end. +is_generator({generate,_,_,_}) -> true; +is_generator({b_generate,_,_,_}) -> true; +is_generator({m_generate,_,_,_}) -> true; +is_generator(_) -> false. + %% eval_map_fields([Field], Bindings, LocalFunctionHandler, %% ExternalFuncHandler) -> %% {[{map_assoc | map_exact,Key,Value}],Bindings} |