diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/debugger/src/dbg_ieval.erl | 16 | ||||
-rw-r--r-- | lib/debugger/test/int_eval_SUITE.erl | 9 | ||||
-rw-r--r-- | lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl | 3 | ||||
-rw-r--r-- | lib/debugger/test/map_SUITE.erl | 6 | ||||
-rw-r--r-- | lib/stdlib/src/erl_eval.erl | 25 | ||||
-rw-r--r-- | lib/stdlib/test/erl_eval_SUITE.erl | 2 |
6 files changed, 43 insertions, 18 deletions
diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl index 1d36aae8ee..0653ce4c00 100644 --- a/lib/debugger/src/dbg_ieval.erl +++ b/lib/debugger/src/dbg_ieval.erl @@ -663,12 +663,16 @@ expr({map,Line,Fs0}, Bs0, Ieval) -> expr({map,Line,E0,Fs0}, Bs0, Ieval0) -> Ieval = Ieval0#ieval{line=Line,top=false}, {value,E,Bs1} = expr(E0, Bs0, Ieval), - {Fs,Bs2} = eval_map_fields(Fs0, Bs1, Ieval), - Value = lists:foldl(fun ({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi); - ({map_exact,K,V}, Mi) -> maps:update(K,V,Mi) end, - E, Fs), - {value,Value,Bs2}; - + case E of + #{} -> + {Fs,Bs2} = eval_map_fields(Fs0, Bs1, Ieval), + Value = lists:foldl(fun ({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi); + ({map_exact,K,V}, Mi) -> maps:update(K,V,Mi) + end, E, Fs), + {value,Value,Bs2}; + _ -> + exception(error, {badarg,E}, Bs1, Ieval) + end; %% A block of statements expr({block,Line,Es},Bs,Ieval) -> seq(Es, Bs, Ieval#ieval{line=Line}); diff --git a/lib/debugger/test/int_eval_SUITE.erl b/lib/debugger/test/int_eval_SUITE.erl index 4ffcf7888e..ecbd68ab40 100644 --- a/lib/debugger/test/int_eval_SUITE.erl +++ b/lib/debugger/test/int_eval_SUITE.erl @@ -28,7 +28,7 @@ bifs_outside_erlang/1, spawning/1, applying/1, catch_and_throw/1, external_call/1, test_module_info/1, apply_interpreted_fun/1, apply_uninterpreted_fun/1, - interpreted_exit/1, otp_8310/1, stacktrace/1]). + interpreted_exit/1, otp_8310/1, stacktrace/1, maps/1]). %% Helpers. -export([applier/3]). @@ -44,7 +44,7 @@ all() -> [bifs_outside_erlang, spawning, applying, catch_and_throw, external_call, test_module_info, apply_interpreted_fun, apply_uninterpreted_fun, - interpreted_exit, otp_8310, stacktrace]. + interpreted_exit, otp_8310, stacktrace, maps]. groups() -> []. @@ -291,6 +291,11 @@ stacktrace(Config) when is_list(Config) -> end, ok. +maps(Config) when is_list(Config) -> + Fun = fun () -> ?IM:empty_map_update([camembert]) end, + {'EXIT',{{badarg,[camembert]},_}} = spawn_eval(Fun), + ok. + do_eval(Config, Mod) -> ?line DataDir = ?config(data_dir, Config), diff --git a/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl index ab485fd350..e047a33d8c 100644 --- a/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl +++ b/lib/debugger/test/int_eval_SUITE_data/my_int_eval_module.erl @@ -29,6 +29,7 @@ -export([more_catch/1,more_nocatch/1,exit_me/0]). -export([f/1, f_try/1, f_catch/1]). -export([otp_5837/1, otp_8310/0]). +-export([empty_map_update/1]). %% Internal exports. -export([echo/2,my_subtract/2,catch_a_ball/0,throw_a_ball/0]). @@ -241,3 +242,5 @@ otp_8310() -> true = begin (X3 = true) orelse X3, X3 end, false = begin (X4 = false) orelse X4, X4 end, ok. + +empty_map_update(Map) -> Map#{}. diff --git a/lib/debugger/test/map_SUITE.erl b/lib/debugger/test/map_SUITE.erl index 741ad2dc41..0076193725 100644 --- a/lib/debugger/test/map_SUITE.erl +++ b/lib/debugger/test/map_SUITE.erl @@ -226,8 +226,8 @@ t_update_map_expressions(Config) when is_list(Config) -> #{ "a" :=1, "b":=42, "c":=42 } = (maps:from_list([{"a",1},{"b",2}]))#{ "b" := 42, "c" => 42 }, %% Error cases, FIXME: should be 'badmap'? - {'EXIT',{badarg,_}} = (catch (id(<<>>))#{ a := 42, b => 2 }), - {'EXIT',{badarg,_}} = (catch (id([]))#{ a := 42, b => 2 }), + {'EXIT',{{badarg,<<>>},_}} = (catch (id(<<>>))#{ a := 42, b => 2 }), + {'EXIT',{{badarg,[]},_}} = (catch (id([]))#{ a := 42, b => 2 }), ok. @@ -244,7 +244,7 @@ t_update_assoc(Config) when is_list(Config) -> %% Errors cases. BadMap = id(badmap), - {'EXIT',{badarg,_}} = (catch BadMap#{nonexisting=>val}), + {'EXIT',{{badarg,BadMap},_}} = (catch BadMap#{nonexisting=>val}), ok. diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl index 3a4108e297..acde3ad5d6 100644 --- a/lib/stdlib/src/erl_eval.erl +++ b/lib/stdlib/src/erl_eval.erl @@ -18,6 +18,9 @@ %% -module(erl_eval). +%% Guard is_map/1 is not yet supported in HiPE. +-compile(no_native). + %% An evaluator for Erlang abstract syntax. -export([exprs/2,exprs/3,exprs/4,expr/2,expr/3,expr/4,expr/5, @@ -243,11 +246,18 @@ expr({record,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs) -> %% map expr({map,_, Binding,Es}, Bs0, Lf, Ef, RBs) -> {value, Map0, Bs1} = expr(Binding, Bs0, Lf, Ef, RBs), - {Vs,Bs} = eval_map_fields(Es, Bs1, Lf, Ef), - ret_expr(lists:foldl(fun - ({map_assoc,K,V}, Mi) -> maps:put(K,V,Mi); - ({map_exact,K,V}, Mi) -> maps:update(K,V,Mi) - end, Map0, Vs), Bs, RBs); + case Map0 of + #{} -> + {Vs,Bs} = eval_map_fields(Es, Bs1, Lf, Ef), + Map1 = lists:foldl(fun ({map_assoc,K,V}, Mi) -> + maps:put(K, V, Mi); + ({map_exact,K,V}, Mi) -> + maps:update(K, V, Mi) + end, Map0, Vs), + ret_expr(Map1, Bs, RBs); + _ -> + erlang:raise(error, {badarg,Map0}, stacktrace()) + end; expr({map,_,Es}, Bs0, Lf, Ef, RBs) -> {Vs,Bs} = eval_map_fields(Es, Bs0, Lf, Ef), ret_expr(lists:foldl(fun @@ -1113,9 +1123,10 @@ match1({tuple,_,Elts}, Tuple, Bs, BBs) match_tuple(Elts, Tuple, 1, Bs, BBs); match1({tuple,_,_}, _, _Bs, _BBs) -> throw(nomatch); -match1({map,_,Fs}, Map, Bs, BBs) -> +match1({map,_,Fs}, #{}=Map, Bs, BBs) -> match_map(Fs, Map, Bs, BBs); - +match1({map,_,_}, _, _Bs, _BBs) -> + throw(nomatch); match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs) -> eval_bits:match_bits(Fs, B, Bs0, BBs, match_fun(BBs), diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl index e6512b7d71..b91d14b5b8 100644 --- a/lib/stdlib/test/erl_eval_SUITE.erl +++ b/lib/stdlib/test/erl_eval_SUITE.erl @@ -1451,6 +1451,8 @@ eep43(Config) when is_list(Config) -> " {Map#{a := B},Map#{a => c},Map#{d => e}} " "end.", {#{a => b},#{a => c},#{a => b,d => e}}), + error_check("[camembert]#{}.", {badarg,[camembert]}), + error_check("#{} = 1.", {badmatch,1}), ok. %% Check the string in different contexts: as is; in fun; from compiled code. |