Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
5610-Support-map-comprehensions-in-syntax_tools...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 5610-Support-map-comprehensions-in-syntax_tools.patch of Package erlang
From 246e08cdad39d836f73c2a9a42aaaa529d470c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Tue, 24 Jan 2023 12:15:45 +0100 Subject: [PATCH 10/12] Support map comprehensions in syntax_tools --- lib/syntax_tools/src/erl_prettypr.erl | 15 ++ lib/syntax_tools/src/erl_syntax.erl | 153 +++++++++++++++++- .../syntax_tools_SUITE_test_module.erl | 11 +- 3 files changed, 177 insertions(+), 2 deletions(-) diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl index d6c1c1e005..89ff4bf134 100644 --- a/lib/syntax_tools/src/erl_prettypr.erl +++ b/lib/syntax_tools/src/erl_prettypr.erl @@ -858,6 +858,12 @@ lay_2(Node, Ctxt) -> D2 = lay(erl_syntax:binary_generator_body(Node), Ctxt1), par([D1, beside(text("<= "), D2)], Ctxt1#ctxt.break_indent); + map_generator -> + Ctxt1 = reset_prec(Ctxt), + D1 = lay(erl_syntax:map_generator_pattern(Node), Ctxt1), + D2 = lay(erl_syntax:map_generator_body(Node), Ctxt1), + par([D1, beside(text("<- "), D2)], Ctxt1#ctxt.break_indent); + implicit_fun -> D = lay(erl_syntax:implicit_fun_name(Node), reset_prec(Ctxt)), @@ -883,6 +889,15 @@ lay_2(Node, Ctxt) -> par([D1, beside(floating(text(" || ")), beside(D2, floating(text(" >>"))))])); + map_comp -> + Ctxt1 = set_prec(Ctxt, max_prec()), + D1 = lay(erl_syntax:map_comp_template(Node), Ctxt1), + D2 = par(seq(erl_syntax:map_comp_body(Node), + floating(text(",")), Ctxt1, + fun lay/2)), + beside(floating(text("#{")), + par([D1, beside(floating(text("|| ")), + beside(D2, floating(text("}"))))])); macro -> %% This is formatted similar to a normal function call, but %% prefixed with a "?". diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 4da1635aec..1958865b3b 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -246,6 +246,9 @@ macro/2, macro_arguments/1, macro_name/1, + map_comp/2, + map_comp_template/1, + map_comp_body/1, map_expr/1, map_expr/2, map_expr_argument/1, @@ -256,6 +259,9 @@ map_field_exact/2, map_field_exact_name/1, map_field_exact_value/1, + map_generator/2, + map_generator_body/1, + map_generator_pattern/1, map_type/0, map_type/1, map_type_fields/1, @@ -715,8 +721,10 @@ type(Node) -> {function, _, _, _, _} -> function; {b_generate, _, _, _} -> binary_generator; {generate, _, _, _} -> generator; + {m_generate, _, _, _} -> map_generator; {lc, _, _, _} -> list_comp; - {bc, _, _, _} -> binary_comp; + {bc, _, _, _} -> binary_comp; + {mc, _, _, _} -> map_comp; {match, _, _, _} -> match_expr; {map, _, _, _} -> map_expr; {map, _, _} -> map_expr; @@ -6138,6 +6146,72 @@ binary_comp_body(Node) -> (data(Node1))#binary_comp.body end. +%% ===================================================================== +%% @doc Creates an abstract map comprehension. If `Body' is +%% `[E1, ..., En]', the result represents +%% "<code>#{<em>Template</em> || <em>E1</em>, ..., <em>En</em>}</code>". +%% +%% @see map_comp_template/1 +%% @see map_comp_body/1 +%% @see generator/2 + +-record(map_comp, {template :: syntaxTree(), body :: [syntaxTree()]}). + +%% type(Node) = map_comp +%% data(Node) = #map_comp{template :: Template, body :: Body} +%% +%% Template = Node = syntaxTree() +%% Body = [syntaxTree()] +%% +%% `erl_parse' representation: +%% +%% {mc, Pos, Template, Body} +%% +%% Template = erl_parse() +%% Body = [erl_parse()] \ [] + +-spec map_comp(syntaxTree(), [syntaxTree()]) -> syntaxTree(). + +map_comp(Template, Body) -> + tree(map_comp, #map_comp{template = Template, body = Body}). + +revert_map_comp(Node) -> + Pos = get_pos(Node), + Template = map_comp_template(Node), + Body = map_comp_body(Node), + {mc, Pos, Template, Body}. + + +%% ===================================================================== +%% @doc Returns the template subtree of a `map_comp' node. +%% +%% @see map_comp/2 + +-spec map_comp_template(syntaxTree()) -> syntaxTree(). + +map_comp_template(Node) -> + case unwrap(Node) of + {mc, _, Template, _} -> + Template; + Node1 -> + (data(Node1))#map_comp.template + end. + + +%% ===================================================================== +%% @doc Returns the list of body subtrees of a `map_comp' node. +%% +%% @see map_comp/2 + +-spec map_comp_body(syntaxTree()) -> [syntaxTree()]. + +map_comp_body(Node) -> + case unwrap(Node) of + {mc, _, _, Body} -> + Body; + Node1 -> + (data(Node1))#map_comp.body + end. %% ===================================================================== %% @doc Creates an abstract generator. The result represents @@ -6271,6 +6345,72 @@ binary_generator_body(Node) -> end. +%% ===================================================================== +%% @doc Creates an abstract map_generator. The result represents +%% "<code><em>Pattern</em> <- <em>Body</em></code>". +%% +%% @see map_generator_pattern/1 +%% @see map_generator_body/1 +%% @see list_comp/2 +%% @see map_comp/2 + +-record(map_generator, {pattern :: syntaxTree(), body :: syntaxTree()}). + +%% type(Node) = map_generator +%% data(Node) = #map_generator{pattern :: Pattern, body :: Body} +%% +%% Pattern = Argument = syntaxTree() +%% +%% `erl_parse' representation: +%% +%% {m_generate, Pos, Pattern, Body} +%% +%% Pattern = Body = erl_parse() + +-spec map_generator(syntaxTree(), syntaxTree()) -> syntaxTree(). + +map_generator(Pattern, Body) -> + tree(map_generator, #map_generator{pattern = Pattern, body = Body}). + +revert_map_generator(Node) -> + Pos = get_pos(Node), + Pattern = map_generator_pattern(Node), + Body = map_generator_body(Node), + {m_generate, Pos, Pattern, Body}. + + +%% ===================================================================== +%% @doc Returns the pattern subtree of a `generator' node. +%% +%% @see map_generator/2 + +-spec map_generator_pattern(syntaxTree()) -> syntaxTree(). + +map_generator_pattern(Node) -> + case unwrap(Node) of + {m_generate, _, Pattern, _} -> + Pattern; + Node1 -> + (data(Node1))#map_generator.pattern + end. + + +%% ===================================================================== +%% @doc Returns the body subtree of a `generator' node. +%% +%% @see map_generator/2 + +-spec map_generator_body(syntaxTree()) -> syntaxTree(). + +map_generator_body(Node) -> + case unwrap(Node) of + {m_generate, _, _, Body} -> + Body; + Node1 -> + (data(Node1))#map_generator.body + end. + + %% ===================================================================== %% @doc Creates an abstract block expression. If `Body' is %% `[B1, ..., Bn]', the result represents "<code>begin @@ -7724,12 +7864,16 @@ revert_root(Node) -> revert_list(Node); list_comp -> revert_list_comp(Node); + map_comp -> + revert_map_comp(Node); map_expr -> revert_map_expr(Node); map_field_assoc -> revert_map_field_assoc(Node); map_field_exact -> revert_map_field_exact(Node); + map_generator -> + revert_map_generator(Node); map_type -> revert_map_type(Node); map_type_assoc -> @@ -8017,6 +8161,8 @@ subtrees(T) -> As -> [[macro_name(T)], As] end; + map_comp -> + [[map_comp_template(T)], map_comp_body(T)]; map_expr -> case map_expr_argument(T) of none -> @@ -8030,6 +8176,9 @@ subtrees(T) -> map_field_exact -> [[map_field_exact_name(T)], [map_field_exact_value(T)]]; + map_generator -> + [[map_generator_pattern(T)], + [map_generator_body(T)]]; map_type -> [map_type_fields(T)]; map_type_assoc -> @@ -8207,10 +8356,12 @@ make_tree(list, [P, [S]]) -> list(P, S); make_tree(list_comp, [[T], B]) -> list_comp(T, B); make_tree(macro, [[N]]) -> macro(N); make_tree(macro, [[N], A]) -> macro(N, A); +make_tree(map_comp, [[T], B]) -> map_comp(T, B); make_tree(map_expr, [Fs]) -> map_expr(Fs); make_tree(map_expr, [[E], Fs]) -> map_expr(E, Fs); make_tree(map_field_assoc, [[K], [V]]) -> map_field_assoc(K, V); make_tree(map_field_exact, [[K], [V]]) -> map_field_exact(K, V); +make_tree(map_generator, [[P], [E]]) -> map_generator(P, E); make_tree(map_type, [Fs]) -> map_type(Fs); make_tree(map_type_assoc, [[N],[V]]) -> map_type_assoc(N, V); make_tree(map_type_exact, [[N],[V]]) -> map_type_exact(N, V); diff --git a/lib/syntax_tools/test/syntax_tools_SUITE_data/syntax_tools_SUITE_test_module.erl b/lib/syntax_tools/test/syntax_tools_SUITE_data/syntax_tools_SUITE_test_module.erl index 9035139fea..daa95b6a25 100644 --- a/lib/syntax_tools/test/syntax_tools_SUITE_data/syntax_tools_SUITE_test_module.erl +++ b/lib/syntax_tools/test/syntax_tools_SUITE_data/syntax_tools_SUITE_test_module.erl @@ -8,7 +8,7 @@ sub_word/2,sub_word/3,left/2,left/3,right/2,right/3, sub_string/2,sub_string/3,centre/2,centre/3, join/2]). -export([to_upper/1, to_lower/1]). --export([eep49/0]). +-export([eep49/0, eep58/0]). -import(lists,[reverse/1,member/2]). @@ -581,3 +581,12 @@ eep49() -> end, ok. + +%% EEP-58: Map comprehensions. +eep58() -> + Seq = lists:seq(1, 10), + Map = #{{key,I} => I || I <- Seq}, + MapDouble = #{K => 2 * V || K := V <- Map}, + MapDouble = maps:from_list([{{key,I}, 2 * I} || I <- Seq]), + + ok. -- 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