Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
3508-syntax_tools-Implement-support-for-maybe-....
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3508-syntax_tools-Implement-support-for-maybe-.-end.patch of Package erlang
From 0793709fa4bc4a4c975086a2125e6931ba5d97a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Tue, 9 Nov 2021 13:16:45 +0100 Subject: [PATCH 08/12] syntax_tools: Implement support for maybe ... end --- lib/syntax_tools/src/epp_dodger.erl | 23 +- lib/syntax_tools/src/erl_prettypr.erl | 36 ++- lib/syntax_tools/src/erl_syntax.erl | 243 +++++++++++++++++- lib/syntax_tools/src/erl_syntax_lib.erl | 2 +- lib/syntax_tools/test/syntax_tools_SUITE.erl | 22 +- .../syntax_tools_SUITE_test_module.erl | 43 ++++ 6 files changed, 350 insertions(+), 19 deletions(-) diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl index eacfbc5d6b..edf092bfcd 100644 --- a/lib/syntax_tools/src/epp_dodger.erl +++ b/lib/syntax_tools/src/epp_dodger.erl @@ -430,7 +430,17 @@ quick_parse_form(Dev, L0, Options) -> parse_form(Dev, L0, Parser, Options) -> NoFail = proplists:get_bool(no_fail, Options), Opt = #opt{clever = proplists:get_bool(clever, Options)}, - case io:scan_erl_form(Dev, "", L0) of + + %% FIXME: This should not be hard-coded. Either all keywords from + %% all features should be retrieved here, or there should be an option + %% to passes in either the keywords or the feature names. + ResWordFun = + fun('maybe') -> true; + ('else') -> true; + (Other) -> erl_scan:reserved_word(Other) + end, + + case io:scan_erl_form(Dev, "", L0, [{reserved_word_fun,ResWordFun}]) of {ok, Ts, L1} -> case catch {ok, Parser(Ts, Opt)} of {'EXIT', Term} -> @@ -504,7 +514,9 @@ quickscan_form([{'-', _Anno}, {'if', AnnoA} | _Ts]) -> kill_form(AnnoA); quickscan_form([{'-', _Anno}, {atom, AnnoA, elif} | _Ts]) -> kill_form(AnnoA); -quickscan_form([{'-', _Anno}, {atom, AnnoA, else} | _Ts]) -> +quickscan_form([{'-', _Anno}, {atom, AnnoA, 'else'} | _Ts]) -> + kill_form(AnnoA); +quickscan_form([{'-', _Anno}, {'else', AnnoA} | _Ts]) -> kill_form(AnnoA); quickscan_form([{'-', _Anno}, {atom, AnnoA, endif} | _Ts]) -> kill_form(AnnoA); @@ -648,9 +660,12 @@ scan_form([{'-', _Anno}, {'if', AnnoA} | Ts], Opt) -> scan_form([{'-', _Anno}, {atom, AnnoA, elif} | Ts], Opt) -> [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, 'elif'} | scan_macros(Ts, Opt)]; -scan_form([{'-', _Anno}, {atom, AnnoA, else} | Ts], Opt) -> +scan_form([{'-', _Anno}, {atom, AnnoA, 'else'} | Ts], Opt) -> + [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, + {atom, AnnoA, 'else'} | scan_macros(Ts, Opt)]; +scan_form([{'-', _Anno}, {'else', AnnoA} | Ts], Opt) -> [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, - {atom, AnnoA, else} | scan_macros(Ts, Opt)]; + {atom, AnnoA, 'else'} | scan_macros(Ts, Opt)]; scan_form([{'-', _Anno}, {atom, AnnoA, endif} | Ts], Opt) -> [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, endif} | scan_macros(Ts, Opt)]; diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl index af1f2b4d11..d6c1c1e005 100644 --- a/lib/syntax_tools/src/erl_prettypr.erl +++ b/lib/syntax_tools/src/erl_prettypr.erl @@ -54,7 +54,7 @@ -type hook() :: 'none' | fun((syntaxTree(), _, _) -> prettypr:document()). -type clause_t() :: 'case_expr' | 'fun_expr' - | 'if_expr' | 'receive_expr' | 'try_expr' + | 'if_expr' | 'maybe_expr' | 'receive_expr' | 'try_expr' | {'function', prettypr:document()} | 'spec'. @@ -588,6 +588,8 @@ lay_2(Node, Ctxt) -> make_if_clause(D1, D2, D3, Ctxt); case_expr -> make_case_clause(D1, D2, D3, Ctxt); + maybe_expr -> + make_case_clause(D1, D2, D3, Ctxt); receive_expr -> make_case_clause(D1, D2, D3, Ctxt); try_expr -> @@ -648,6 +650,34 @@ lay_2(Node, Ctxt) -> set_prec(Ctxt, PrecR)), beside(D1, beside(text(":"), D2)); + maybe_expr -> + Ctxt1 = reset_prec(Ctxt), + D1 = vertical(seq(erl_syntax:maybe_expr_body(Node), + floating(text(",")), Ctxt1, fun lay/2)), + Es0 = [text("end")], + Es1 = case erl_syntax:maybe_expr_else(Node) of + none -> Es0; + ElseNode -> + ElseCs = erl_syntax:else_expr_clauses(ElseNode), + D3 = lay_clauses(ElseCs, maybe_expr, Ctxt1), + [text("else"), + nest(Ctxt1#ctxt.break_indent, D3) + | Es0] + end, + sep([par([text("maybe"), nest(Ctxt1#ctxt.break_indent, D1), + hd(Es1)]) | tl(Es1)]); + + maybe_match_expr -> + {PrecL, Prec, PrecR} = inop_prec('='), + D1 = lay(erl_syntax:maybe_match_expr_pattern(Node), + set_prec(Ctxt, PrecL)), + D2 = lay(erl_syntax:maybe_match_expr_body(Node), + set_prec(Ctxt, PrecR)), + D3 = follow(beside(D1, floating(text(" ?="))), D2, + Ctxt#ctxt.break_indent), + maybe_parentheses(D3, Prec, Ctxt); + + %% %% The rest is in alphabetical order (except map and types) %% @@ -759,7 +789,7 @@ lay_2(Node, Ctxt) -> nest(Ctxt1#ctxt.break_indent, sep(Es)), text("end")]); - catch_expr -> + 'catch_expr' -> %Quoted to help Emacs. {Prec, PrecR} = preop_prec('catch'), D = lay(erl_syntax:catch_expr_body(Node), set_prec(Ctxt, PrecR)), @@ -801,7 +831,7 @@ lay_2(Node, Ctxt) -> sep(seq(erl_syntax:disjunction_body(Node), floating(text(";")), reset_prec(Ctxt), fun lay/2)); - + error_marker -> E = erl_syntax:error_marker_info(Node), beside(text("** "), diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index f62cfb4108..4da1635aec 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -193,6 +193,8 @@ constraint_body/1, disjunction/1, disjunction_body/1, + else_expr/1, + else_expr_clauses/1, eof_marker/0, error_marker/1, error_marker_info/1, @@ -266,6 +268,13 @@ match_expr/2, match_expr_body/1, match_expr_pattern/1, + maybe_expr/1, + maybe_expr/2, + maybe_expr_body/1, + maybe_expr_else/1, + maybe_match_expr/2, + maybe_match_expr_pattern/1, + maybe_match_expr_body/1, module_qualifier/2, module_qualifier_argument/1, module_qualifier_body/1, @@ -505,13 +514,14 @@ %% <td>constrained_function_type</td> %% <td>constraint</td> %% <td>disjunction</td> -%% <td>eof_marker</td> %% </tr><tr> +%% <td>else_expr</td> +%% <td>eof_marker</td> %% <td>error_marker</td> +%% </tr><tr> %% <td>float</td> %% <td>form_list</td> %% <td>fun_expr</td> -%% </tr><tr> %% <td>fun_type</td> %% <td>function</td> %% <td>function_type</td> @@ -535,6 +545,9 @@ %% <td>map_type_assoc</td> %% <td>map_type_exact</td> %% <td>match_expr</td> +%% </tr><tr> +%% <td>maybe_expr</td> +%% <td>maybe_match_expr</td> %% <td>module_qualifier</td> %% </tr><tr> %% <td>named_fun_expr</td> @@ -597,6 +610,7 @@ %% @see constrained_function_type/2 %% @see constraint/2 %% @see disjunction/1 +%% @see else_expr/1 %% @see eof_marker/0 %% @see error_marker/1 %% @see float/1 @@ -623,6 +637,9 @@ %% @see map_type_assoc/2 %% @see map_type_exact/2 %% @see match_expr/2 +%% @see maybe_expr/1 +%% @see maybe_expr/2 +%% @see maybe_match_expr/2 %% @see module_qualifier/2 %% @see named_fun_expr/2 %% @see nil/0 @@ -683,6 +700,9 @@ type(Node) -> {'fun', _, {function, _, _}} -> implicit_fun; {'fun', _, {function, _, _, _}} -> implicit_fun; {'if', _, _} -> if_expr; + {'maybe', _, _} -> maybe_expr; + {'maybe', _, _, _} -> maybe_expr; + {'else', _, _} -> else_expr; {'receive', _, _, _, _} -> receive_expr; {'receive', _, _} -> receive_expr; {attribute, _, _, _} -> attribute; @@ -702,6 +722,7 @@ type(Node) -> {map, _, _} -> map_expr; {map_field_assoc, _, _, _} -> map_field_assoc; {map_field_exact, _, _, _} -> map_field_exact; + {maybe_match, _, _, _} -> maybe_match_expr; {op, _, _, _, _} -> infix_expr; {op, _, _, _} -> prefix_expr; {record, _, _, _, _} -> record_expr; @@ -4134,6 +4155,71 @@ match_expr_body(Node) -> end. +%% ===================================================================== +%% @doc Creates an abstract maybe-expression, as used in <code>maybe</code> +%% blocks. The result represents +%% "<code><em>Pattern</em> ?= <em>Body</em></code>". +%% +%% @see maybe_match_expr_pattern/1 +%% @see maybe_match_expr_body/1 +%% @see maybe_expr/2 + +-record(maybe_match_expr, {pattern :: syntaxTree(), body :: syntaxTree()}). + +%% type(Node) = maybe_expr +%% data(Node) = #maybe_expr{pattern :: Pattern, body :: Body} +%% +%% Pattern = Body = syntaxTree() +%% +%% `erl_parse' representation: +%% +%% {maybe_match, Pos, Pattern, Body} +%% +%% Pattern = Body = erl_parse() +%% + +-spec maybe_match_expr(syntaxTree(), syntaxTree()) -> syntaxTree(). + +maybe_match_expr(Pattern, Body) -> + tree(maybe_match_expr, #maybe_match_expr{pattern = Pattern, body = Body}). + +revert_maybe_match_expr(Node) -> + Pos = get_pos(Node), + Pattern = maybe_match_expr_pattern(Node), + Body = maybe_match_expr_body(Node), + {maybe_match, Pos, Pattern, Body}. + +%% ===================================================================== +%% @doc Returns the pattern subtree of a `maybe_expr' node. +%% +%% @see maybe_match_expr/2 + +-spec maybe_match_expr_pattern(syntaxTree()) -> syntaxTree(). + +maybe_match_expr_pattern(Node) -> + case unwrap(Node) of + {maybe_match, _, Pattern, _} -> + Pattern; + Node1 -> + (data(Node1))#maybe_match_expr.pattern + end. + + +%% ===================================================================== +%% @doc Returns the body subtree of a `maybe_expr' node. +%% +%% @see maybe_match_expr/2 + +-spec maybe_match_expr_body(syntaxTree()) -> syntaxTree(). + +maybe_match_expr_body(Node) -> + case unwrap(Node) of + {maybe_match, _, _, Body} -> + Body; + Node1 -> + (data(Node1))#maybe_match_expr.body + end. + %% ===================================================================== %% @doc Creates an abstract operator. The name of the operator is the %% character sequence represented by `Name'. This is @@ -6361,6 +6447,130 @@ case_expr_clauses(Node) -> (data(Node1))#case_expr.clauses end. +%% ===================================================================== +%% @doc Creates an abstract else-expression. If `Clauses' is `[C1, +%% ..., Cn]', the result represents "<code>else <em>C1</em>; ...; <em>Cn</em> +%% end</code>". More exactly, if each `Ci' represents +%% "<code>(<em>Pi</em>) <em>Gi</em> -> <em>Bi</em></code>", then the +%% result represents "<code>else <em>G1</em> -> <em>B1</em>; ...; +%% <em>Pn</em> <em>Gn</em> -> <em>Bn</em> end</code>". +%% +%% @see maybe_expr/2 +%% @see else_expr_clauses/1 +%% @see clause/3 + +else_expr(Clauses) -> + tree(else_expr, Clauses). + +revert_else_expr(Node) -> + Pos = get_pos(Node), + Clauses = else_expr_clauses(Node), + {'else', Pos, Clauses}. + +%% ===================================================================== +%% @doc Returns the list of clause subtrees of an `else_expr' node. +%% +%% @see else_expr/1 + +-spec else_expr_clauses(syntaxTree()) -> [syntaxTree()]. + +else_expr_clauses(Node) -> + case unwrap(Node) of + {'else', _, Clauses} -> + Clauses; + Node1 -> + data(Node1) + end. + +%% ===================================================================== +%% @equiv maybe_expr(Body, none) + +-spec maybe_expr([syntaxTree()]) -> syntaxTree(). + +maybe_expr(Body) -> + maybe_expr(Body, none). + +%% ===================================================================== +%% @doc Creates an abstract maybe-expression. If `Body' is `[B1, ..., +%% Bn]', and `OptionalElse' is `none', the result represents +%% "<code>maybe <em>B1</em>, ..., <em>Bn</em> end</code>". If `Body' +%% is `[B1, ..., Bn]', and `OptionalElse' reprsents an `else_expr' node +%% with clauses `[C1, ..., Cn]', the result represents "<code>maybe +%% <em>B1</em>, ..., <em>Bn</em> else <em>C1</em>; ..., <em>Cn</em> +%% end</code>". +%% +%% See `clause' for documentation on `erl_parse' clauses. +%% +%% @see maybe_expr_body/1 +%% @see maybe_expr_else/1 + +-record(maybe_expr, {body :: [syntaxTree()], + 'else' = none :: 'none' | syntaxTree()}). + +%% type(Node) = maybe_expr +%% data(Node) = #maybe_expr{body :: Body, 'else' :: 'none' | Else} +%% +%% Body = [syntaxTree()] +%% Else = syntaxTree() +%% +%% `erl_parse' representation: +%% +%% {block, Pos, Body} +%% {block, Pos, Body, Else} +%% +%% Body = [erl_parse()] \ [] +%% Else = {'else', Pos, Clauses} +%% Clauses = [Clause] \ [] +%% Clause = {clause, ...} + +-spec maybe_expr([syntaxTree()], 'none' | syntaxTree()) -> syntaxTree(). + +maybe_expr(Body, OptionalElse) -> + tree(maybe_expr, #maybe_expr{body = Body, + 'else' = OptionalElse}). +revert_maybe_expr(Node) -> + Pos = get_pos(Node), + Body = maybe_expr_body(Node), + case maybe_expr_else(Node) of + none -> + {'maybe', Pos, Body}; + Else -> + {'maybe', Pos, Body, Else} + end. + +%% ===================================================================== +%% @doc Returns the list of body subtrees of a `maybe_expr' node. +%% +%% @see maybe_expr/2 + +-spec maybe_expr_body(syntaxTree()) -> [syntaxTree()]. + +maybe_expr_body(Node) -> + case unwrap(Node) of + {'maybe', _, Body} -> + Body; + {'maybe', _, Body, _Else} -> + Body; + Node1 -> + (data(Node1))#maybe_expr.body + end. + +%% ===================================================================== +%% @doc Returns the else subtree of a `maybe_expr' node. +%% +%% @see maybe_expr/2 + +-spec maybe_expr_else(syntaxTree()) -> 'none' | syntaxTree(). + +maybe_expr_else(Node) -> + case unwrap(Node) of + {'maybe', _, _Body} -> + none; + {'maybe', _, _Body, Else} -> + Else; + Node1 -> + (data(Node1))#maybe_expr.'else' + end. %% ===================================================================== %% @equiv receive_expr(Clauses, none, []) @@ -7470,9 +7680,9 @@ revert_root(Node) -> revert_bitstring_type(Node); block_expr -> revert_block_expr(Node); - case_expr -> + 'case_expr' -> %Quoted to help Emacs. revert_case_expr(Node); - catch_expr -> + 'catch_expr' -> %Quoted to help Emacs. revert_catch_expr(Node); char -> revert_char(Node); @@ -7482,6 +7692,8 @@ revert_root(Node) -> revert_constrained_function_type(Node); constraint -> revert_constraint(Node); + else_expr -> + revert_else_expr(Node); eof_marker -> revert_eof_marker(Node); error_marker -> @@ -7526,6 +7738,10 @@ revert_root(Node) -> revert_map_type_exact(Node); match_expr -> revert_match_expr(Node); + maybe_match_expr -> + revert_maybe_match_expr(Node); + maybe_expr -> + revert_maybe_expr(Node); module_qualifier -> revert_module_qualifier(Node); named_fun_expr -> @@ -7730,7 +7946,7 @@ subtrees(T) -> case_expr -> [[case_expr_argument(T)], case_expr_clauses(T)]; - catch_expr -> + 'catch_expr' -> %Quoted to help Emacs. [[catch_expr_body(T)]]; class_qualifier -> [[class_qualifier_argument(T)], @@ -7755,6 +7971,8 @@ subtrees(T) -> constraint_body(T)]; disjunction -> [disjunction_body(T)]; + else_expr -> + [else_expr_clauses(T)]; form_list -> [form_list_elements(T)]; fun_expr -> @@ -7823,6 +8041,17 @@ subtrees(T) -> match_expr -> [[match_expr_pattern(T)], [match_expr_body(T)]]; + maybe_expr -> + case maybe_expr_else(T) of + none -> + [maybe_expr_body(T)]; + E -> + [maybe_expr_body(T), + [E]] + end; + maybe_match_expr -> + [[maybe_match_expr_pattern(T)], + [maybe_match_expr_body(T)]]; module_qualifier -> [[module_qualifier_argument(T)], [module_qualifier_body(T)]]; @@ -7962,6 +8191,7 @@ make_tree(constrained_function_type, [[F],C]) -> constrained_function_type(F, C); make_tree(constraint, [[N], Ts]) -> constraint(N, Ts); make_tree(disjunction, [E]) -> disjunction(E); +make_tree(else_expr, [E]) -> else_expr(E); make_tree(form_list, [E]) -> form_list(E); make_tree(fun_expr, [C]) -> fun_expr(C); make_tree(function, [[N], C]) -> function(N, C); @@ -7985,6 +8215,9 @@ 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); make_tree(match_expr, [[P], [E]]) -> match_expr(P, E); +make_tree(maybe_expr, [Body]) -> maybe_expr(Body); +make_tree(maybe_expr, [Body, [Else]]) -> maybe_expr(Body, Else); +make_tree(maybe_match_expr, [[P], [E]]) -> maybe_match_expr(P, E); make_tree(named_fun_expr, [[N], C]) -> named_fun_expr(N, C); make_tree(module_qualifier, [[M], [N]]) -> module_qualifier(M, N); make_tree(parentheses, [[E]]) -> parentheses(E); diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl index b2d31be4f5..78c7ab9e46 100644 --- a/lib/syntax_tools/src/erl_syntax_lib.erl +++ b/lib/syntax_tools/src/erl_syntax_lib.erl @@ -1314,7 +1314,7 @@ analyze_attribute(Node) -> ifndef -> preprocessor; 'if' -> preprocessor; elif -> preprocessor; - else -> preprocessor; + 'else' -> preprocessor; endif -> preprocessor; A -> {A, analyze_attribute(A, Node)} diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl index 3246ce7010..2ffec12740 100644 --- a/lib/syntax_tools/test/syntax_tools_SUITE.erl +++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl @@ -106,7 +106,8 @@ revert(Config) when is_list(Config) -> test_server:timetrap_cancel(Dog). revert_file(File, Path) -> - case epp:parse_file(File, Path, []) of + case epp:parse_file(File, [{includes,Path}, + res_word_option()]) of {ok,Fs0} -> Fs1 = erl_syntax:form_list(Fs0), Fs2 = erl_syntax_lib:map(fun (Node) -> Node end, Fs1), @@ -350,8 +351,7 @@ t_comment_scan(Config) when is_list(Config) -> t_prettypr(Config) when is_list(Config) -> DataDir = ?config(data_dir, Config), PrivDir = ?config(priv_dir, Config), - Filenames = ["type_specs.erl", - "specs_and_funs.erl"], + Filenames = test_files(), ok = test_prettypr(Filenames,DataDir,PrivDir), ok. @@ -391,15 +391,16 @@ test_comment_scan([File|Files],DataDir) -> test_prettypr([],_,_) -> ok; test_prettypr([File|Files],DataDir,PrivDir) -> Filename = filename:join(DataDir,File), + Options = [res_word_option()], io:format("Parsing ~p~n", [Filename]), - {ok, Fs0} = epp:parse_file(Filename, [], []), + {ok, Fs0} = epp:parse_file(Filename, Options), Fs = erl_syntax:form_list(Fs0), PP = erl_prettypr:format(Fs, [{paper, 120}, {ribbon, 110}]), io:put_chars(PP), OutFile = filename:join(PrivDir, File), ok = file:write_file(OutFile,unicode:characters_to_binary(PP)), io:format("Parsing OutFile: ~ts~n", [OutFile]), - {ok, Fs2} = epp:parse_file(OutFile, [], []), + {ok, Fs2} = epp:parse_file(OutFile, Options), case [Error || {error, _} = Error <- Fs2] of [] -> ok; @@ -408,7 +409,6 @@ test_prettypr([File|Files],DataDir,PrivDir) -> end, test_prettypr(Files,DataDir,PrivDir). - test_epp_dodger([], _, _) -> ok; test_epp_dodger([Filename|Files],DataDir,PrivDir) -> io:format("Parsing ~p~n", [Filename]), @@ -617,3 +617,13 @@ p_run_loop(Test, List, N, Refs0, Errors0) -> Refs = Refs0 -- [Ref], p_run_loop(Test, List, N, Refs, Errors) end. + +res_word_option() -> + %% FIXME: When the experimental features EEP has been implemented, we should + %% dig out all keywords defined in all features. + ResWordFun = + fun('maybe') -> true; + ('else') -> true; + (Other) -> erl_scan:reserved_word(Other) + end, + {reserved_word_fun, ResWordFun}. 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 95afffa7f6..9035139fea 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,6 +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]). -import(lists,[reverse/1,member/2]). @@ -538,3 +539,45 @@ join([], Sep) when is_list(Sep) -> []; join([H|T], Sep) -> H ++ lists:append([Sep ++ X || X <- T]). + +eep49() -> + maybe ok ?= ok end, + + {a,b} = + maybe + {ok,A} ?= {ok,a}, + {ok,B} ?= {ok,b}, + {A,B} + end, + + maybe + ok ?= {ok,x} + else + error -> error; + {error,_} -> error + end, + + maybe + ok ?= {ok,x} + else + error -> error + end, + + maybe + {ok,X} ?= {ok,x}, + {ok,Y} ?= {ok,y}, + {X,Y} + else + error -> error; + {error,_} -> error + end, + + maybe + {ok,X2} ?= {ok,x}, + {ok,Y2} ?= {ok,y}, + {X2,Y2} + else + error -> error + end, + + ok. -- 2.34.1
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