Interactively-defined functions
Julian Fondren
cleverjulian@REDACTED
Tue Nov 26 18:51:40 CET 2002
This should be a gen_server, but I'm too busy right now to clean it
up -- hopefully this is clear enough. I won't be available to respond
to email (and my hotmail account will probably be frozen before I can
get back to it), sorry.
Note: The server's state is a list of parsed functions
-module(shell_funs).
-author('cleverjulian@REDACTED').
-export([start/0,
load/0, save/0, list/0, show/2,
add/0, add/1, add/3, remove/2, get/2]).
-export([loop/1]).
-define(SERVER, ?MODULE).
% ----------------------------------------------------------------------
start() ->
register(?SERVER, spawn(?MODULE, loop, [[]])).
% ----------------------------------------------------------------------
load() ->
Funs = load_funs(),
?SERVER ! {load, Funs},
ok.
save() ->
save_funs(funs()).
% ----------------------------------------------------------------------
list() ->
lists:map(fun name_of_fun/1, funs()).
show(Name, Arity) ->
case fun_by_name of
{ok, Fun} ->
io:format("~s", [erl_pp:function(Fun)]);
not_found ->
not_found
end.
get(Name, Arity) ->
?SERVER ! {self(), get, Name, Arity},
receive
{?SERVER, function, Fun} ->
{ok, Fun};
{?SERVER, not_found} ->
not_found
end.
% ----------------------------------------------------------------------
add() ->
{ok, Fun={function, _What_is_this, Name, Arity, _Clauses}, _} =
io:parse_erl_form(': '),
?SERVER ! {add, Fun, Name, Arity},
ok.
add(FunString) ->
{ok, Tokens, _} = erl_scan:string(FunString),
{ok, Fun={function, _What_is_this, Name, Arity, _Clauses}} =
erl_parse:parse_form(Tokens),
?SERVER ! {add, Fun, Name, Arity},
ok.
add(Fun, Name, Arity) ->
?SERVER ! {add, Fun, Name, Arity},
ok.
remove(Name, Arity) ->
?SERVER ! {remove, Name, Arity}.
% ----------------------------------------------------------------------
funs() ->
?SERVER ! {self(), save},
receive
{?SERVER, functions, Funs} ->
Funs
end.
% ----------------------------------------------------------------------
loop(Funs) ->
receive
{add, Fun, Name, Arity} ->
NewFuns = [Fun|case fun_by_name(Name, Arity, Funs) of
{ok, CollideFun} ->
lists:delete(CollideFun, Funs);
not_found ->
Funs
end],
make_module(NewFuns),
loop(NewFuns);
{remove, Name, Arity} ->
case fun_by_name(Name, Arity, Funs) of
{ok, Fun} ->
NewFuns = lists:delete(Fun, Funs),
make_module(NewFuns),
loop(NewFuns);
not_found ->
loop(Funs)
end;
{load, Funs1} ->
make_module(Funs1),
loop(Funs1);
{Pid, save} ->
Pid ! {?SERVER, functions, Funs},
loop(Funs);
{Pid, get, Name, Arity} ->
case fun_by_name(Name, Arity, funs) of
{ok, Fun} ->
Pid ! {?SERVER, function, Fun};
not_found ->
Pid ! {?SERVER, not_found}
end,
loop(Funs)
end.
% ----------------------------------------------------------------------
name_of_fun({function, _What_is_this, Name, Arity, _Clauses}) ->
{Name, Arity}.
fun_by_name(Name, Arity, [Fun={function, _What_is_this,
Name, Arity, _Clauses}|_]) ->
{ok, Fun};
fun_by_name(Name, Arity, [_|T]) ->
fun_by_name(Name, Arity, T);
fun_by_name(_, _, []) ->
not_found.
% ----------------------------------------------------------------------
the_save_file() ->
os:getenv("HOME") ++ "/.user_default.erl".
load_funs() ->
{ok, Bin} = file:read_file(the_save_file()),
functions(binary_to_list(Bin)).
save_funs(Funs) ->
% Syntax error:
% FunStrings = lists:map(fun erl_pp:function/1, Funs),
FunStrings = lists:map(fun (F) -> erl_pp:function(F) end, Funs),
file:write_file(the_save_file(), FunStrings).
functions([]) ->
[];
functions(S) ->
case erl_scan:tokens([], S, 0) of
{done, {ok, Tokens, _}, Rest} ->
{ok, Parsed} = erl_parse:parse_form(Tokens),
[Parsed|functions(Rest)]
end.
make_module(Funs) ->
{ok, Module, Bin} =
compile:forms([{attribute,1,module,user_default}|Funs],
[export_all]),
code:load_binary(Module, the_save_file(), Bin).
_________________________________________________________________
The new MSN 8: advanced junk mail protection and 2 months FREE*
http://join.msn.com/?page=features/junkmail
More information about the erlang-questions
mailing list