Skip to content

stdlib: support 'fun f/a' expressions in the shell #9898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: maint-26
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion lib/stdlib/src/shell.erl
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,23 @@ get_command(Prompt, Eval, Bs, RT, FT, Ds) ->
io:scan_erl_exprs(group_leader(), Prompt, {1,1},
[text,{reserved_word_fun,ResWordFun}])
of
{ok,Toks,_EndPos} ->
{ok,Toks0,_EndPos} ->
%% local 'fun' fixer
%% when we parse a 'fun' expression within a shell call or function definition
%% we need to add a local prefix (if the 'fun' expression did not have a module specified)
LocalFunFixer = fun F([{'fun',Anno}=A,{atom,_,Func}=B,{'/',_}=C,{integer,_,Arity}=D| Rest],Acc) ->
case erl_internal:bif(Func, Arity) of
true ->
F(Rest, [D,C,B,{':',A},{atom,Anno,'erlang'},A | Acc]);
false ->
F(Rest, [D,C,B,{':',A},{atom,Anno,'shell_default'},A | Acc])
end;
F([H|Rest], Acc) ->
F(Rest, [H | Acc]);
F([], Acc) ->
lists:reverse(Acc)
end,
Toks = LocalFunFixer(Toks0, []),
%% NOTE: we can handle function definitions, records and type declarations
%% but this cannot be handled by the function which only expects erl_parse:abstract_expressions()
%% for now just pattern match against those types and pass the string to shell local func.
Expand Down
12 changes: 11 additions & 1 deletion lib/stdlib/test/shell_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
progex_lc/1, progex_funs/1,
otp_5990/1, otp_6166/1, otp_6554/1,
otp_7184/1, otp_7232/1, otp_8393/1, otp_10302/1, otp_13719/1,
otp_14285/1, otp_14296/1, typed_records/1, types/1]).
otp_14285/1, otp_14296/1, typed_records/1, types/1, funs/1]).

-export([ start_restricted_from_shell/1,
start_restricted_on_command_line/1,restricted_local/1]).
Expand Down Expand Up @@ -348,6 +348,16 @@ forget(Config) when is_list(Config) ->
"exception error: no function clause matching call to f/1" =
comm_err(<<"f(a).">>),
ok.
funs(Config) when is_list(Config) ->
[[2,3,4]] = scan(<<"lists:map(fun ceil/1, [1.1, 2.1, 3.1]).">>),
rtnode:run(
[{putline, "add_one(X)-> X + 1."},
{expect, "ok"},
{putline, "lists:map(fun add_one/1, [1, 2, 3])."},
{expect, "[2,3,4]"}
],[],"", ["[\"init:stop().\"]"]),
receive after 1000 -> ok end,
ok.

%% type definition support
types(Config) when is_list(Config) ->
Expand Down
Loading