From ac264cba1435bf84eecc6b31809bd996c4c8e9c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 23 Oct 2014 19:49:12 +0200 Subject: syntax_tools: Teach Maps to erl_syntax Affected functions: * erl_syntax:abstract/1 * erl_syntax:concrete/1 * erl_syntax:is_leaf/1 * erl_syntax:is_literal/1 --- lib/syntax_tools/src/erl_syntax.erl | 28 ++++++++++++++++++++++++++++ lib/syntax_tools/test/syntax_tools_SUITE.erl | 4 ++++ 2 files changed, 32 insertions(+) (limited to 'lib') diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 5da53113e0..40372a2106 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -669,6 +669,9 @@ is_leaf(Node) -> operator -> true; % nonstandard type string -> true; text -> true; % nonstandard type + map_expr -> + map_expr_fields(Node) =:= [] andalso + map_expr_argument(Node) =:= none; tuple -> tuple_elements(Node) =:= []; underscore -> true; variable -> true; @@ -6093,6 +6096,9 @@ abstract([]) -> nil(); abstract(T) when is_tuple(T) -> tuple(abstract_list(tuple_to_list(T))); +abstract(T) when is_map(T) -> + map_expr([map_field_assoc(abstract(Key),abstract(Value)) + || {Key,Value} <- maps:to_list(T)]); abstract(T) when is_binary(T) -> binary([binary_field(integer(B)) || B <- binary_to_list(T)]); abstract(T) -> @@ -6154,6 +6160,14 @@ concrete(Node) -> | concrete(list_tail(Node))]; tuple -> list_to_tuple(concrete_list(tuple_elements(Node))); + map_expr -> + As = [tuple([map_field_assoc_name(F), + map_field_assoc_value(F)]) || F <- map_expr_fields(Node)], + M0 = maps:from_list(concrete_list(As)), + case map_expr_argument(Node) of + none -> M0; + Node0 -> maps:merge(concrete(Node0),M0) + end; binary -> Fs = [revert_binary_field( binary_field(binary_field_body(F), @@ -6209,6 +6223,11 @@ is_literal(T) -> is_literal(list_head(T)) andalso is_literal(list_tail(T)); tuple -> lists:all(fun is_literal/1, tuple_elements(T)); + map_expr -> + case map_expr_argument(T) of + none -> true; + Arg -> is_literal(Arg) + end andalso lists:all(fun is_literal_map_field/1, map_expr_fields(T)); binary -> lists:all(fun is_literal_binary_field/1, binary_fields(T)); _ -> @@ -6221,6 +6240,15 @@ is_literal_binary_field(F) -> _ -> false end. +is_literal_map_field(F) -> + case type(F) of + map_field_assoc -> + is_literal(map_field_assoc_name(F)) andalso + is_literal(map_field_assoc_value(F)); + map_field_exact -> + false + end. + %% ===================================================================== %% @doc Returns an `erl_parse'-compatible representation of a %% syntax tree, if possible. If `Tree' represents a diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl index b4141956e6..721d1fd87c 100644 --- a/lib/syntax_tools/test/syntax_tools_SUITE.erl +++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl @@ -136,6 +136,8 @@ t_abstract_type(Config) when is_list(Config) -> {[$a,$b,$c],string}, {"hello world",string}, {<<1,2,3>>,binary}, + {#{a=>1,"b"=>2},map_expr}, + {#{#{i=>1}=>1,"b"=>#{v=>2}},map_expr}, {{a,b,c},tuple}]), ok. @@ -152,6 +154,7 @@ t_erl_parse_type(Config) when is_list(Config) -> {"_", underscore,true}, {"[]", nil,true}, {"{}", tuple,true}, + {"#{}",map_expr,true}, {"'some atom'", atom, true}]), %% composite types ok = validate(F,[{"case X of t -> t; f -> f end", case_expr,false}, @@ -175,6 +178,7 @@ t_erl_parse_type(Config) when is_list(Config) -> {"[<<1>>,<<2>>,-2,<<>>,[more,list]]", list,false}, {"[1|[2|[3|[4|[]]]]]", list,false}, {"#{ a=>1, b=>2 }", map_expr,false}, + {"#{3=>3}#{ a=>1, b=>2 }", map_expr,false}, {"#{ a:=1, b:=2 }", map_expr,false}, {"M#{ a=>1, b=>2 }", map_expr,false}, {"[V||V <- Vs]", list_comp,false}, -- cgit v1.2.3