Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
5606-erl_eval-Handle-map-comprehensions.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 5606-erl_eval-Handle-map-comprehensions.patch of Package erlang
From 6cbdf51d1dfab4e0e1f4acc873a6502c795b3e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Mon, 23 Jan 2023 05:05:13 +0100 Subject: [PATCH 06/12] erl_eval: Handle map comprehensions --- lib/stdlib/src/erl_eval.erl | 109 +++++++++++++++++++++++------ lib/stdlib/test/erl_eval_SUITE.erl | 33 ++++++++- 2 files changed, 118 insertions(+), 24 deletions(-) diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index 987ba0cf0a..ecb823a246 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -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} diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index bd76fc5a89..d3f6f951e2 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -56,7 +56,8 @@ otp_14708/1, otp_16545/1, otp_16865/1, - eep49/1]). + eep49/1, + eep58/1]). %% %% Define to run outside of test server @@ -97,7 +98,7 @@ all() -> otp_8133, otp_10622, otp_13228, otp_14826, funs, custom_stacktrace, try_catch, eval_expr_5, zero_width, eep37, eep43, otp_15035, otp_16439, otp_14708, otp_16545, otp_16865, - eep49]. + eep49, eep58]. groups() -> []. @@ -2002,6 +2003,34 @@ eep49(Config) when is_list(Config) -> {else_clause,simply_wrong}), ok. +%% EEP 58: Map comprehensions. +eep58(Config) when is_list(Config) -> + check(fun() -> X = 32, #{X => X*X || X <- [1,2,3]} end, + "begin X = 32, #{X => X*X || X <- [1,2,3]} end.", + #{1 => 1, 2 => 4, 3 => 9}), + check(fun() -> + K = V = none, + #{K => V*V || K := V <- #{1 => 1, 2 => 2, 3 => 3}} + end, + "begin K = V = none, #{K => V*V || K := V <- #{1 => 1, 2 => 2, 3 => 3}} end.", + #{1 => 1, 2 => 4, 3 => 9}), + check(fun() -> + #{K => V*V || K := V <- maps:iterator(#{1 => 1, 2 => 2, 3 => 3})} + end, + "#{K => V*V || K := V <- maps:iterator(#{1 => 1, 2 => 2, 3 => 3})}.", + #{1 => 1, 2 => 4, 3 => 9}), + check(fun() -> << <<K:8,V:24>> || K := V <- #{42 => 7777} >> end, + "<< <<K:8,V:24>> || K := V <- #{42 => 7777} >>.", + <<42:8,7777:24>>), + check(fun() -> [X || X := X <- #{a => 1, b => b}] end, + "[X || X := X <- #{a => 1, b => b}].", + [b]), + + error_check("[K+V || K := V <- a].", {bad_generator,a}), + error_check("[K+V || K := V <- [-1|#{}]].", {bad_generator,[-1|#{}]}), + + ok. + %% Check the string in different contexts: as is; in fun; from compiled code. check(F, String, Result) -> check1(F, String, Result), -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor