erl_eval.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,167 行 · 第 1/3 页

ERL
1,167
字号
unhide_calls({atom,Id,ok}, MaxLine, D) when Id > MaxLine ->    dict:fetch(Id, D);unhide_calls({call,Id,{remote,L,_M,_F},Args}, MaxLine, D) when Id > MaxLine ->    {call,Atom} = dict:fetch(Id, D),    {call,L,Atom,unhide_calls(Args, MaxLine, D)};unhide_calls(T, MaxLine, D) when is_tuple(T) ->     list_to_tuple(unhide_calls(tuple_to_list(T), MaxLine, D));unhide_calls([E | Es], MaxLine, D) ->     [unhide_calls(E, MaxLine, D) | unhide_calls(Es, MaxLine, D)];unhide_calls(E, _MaxLine, _D) ->     E.%% local_func(Function, Arguments, Bindings, LocalFuncHandler, RBs) ->%%	{value,Value,Bindings} | Value when%%	LocalFuncHandler = {value,F} | {value,F,Eas} |%%                         {eval,F}  | {eval,F,Eas}  | none.local_func(Func, As0, Bs0, {value,F}, value) ->    {As1,_Bs1} = expr_list(As0, Bs0, {value,F}),    %% Make tail recursive calls when possible.    F(Func, As1);local_func(Func, As0, Bs0, {value,F}, RBs) ->    {As1,Bs1} = expr_list(As0, Bs0, {value,F}),    ret_expr(F(Func, As1), Bs1, RBs);local_func(Func, As0, Bs0, {value,F,Eas}, value) ->    {As1,_Bs1} = expr_list(As0, Bs0, {value,F,Eas}),    apply(F, [Func,As1|Eas]);local_func(Func, As0, Bs0, {value,F,Eas}, RBs) ->    {As1,Bs1} = expr_list(As0, Bs0, {value,F,Eas}),    ret_expr(apply(F, [Func,As1|Eas]), Bs1, RBs);local_func(Func, As, Bs, {eval,F}, RBs) ->    local_func2(F(Func, As, Bs), RBs);local_func(Func, As, Bs, {eval,F,Eas}, RBs) ->    local_func2(apply(F, [Func,As,Bs|Eas]), RBs);%% These two clauses are for backwards compatibility.local_func(Func, As0, Bs0, {M,F}, RBs) ->    {As1,Bs1} = expr_list(As0, Bs0, {M,F}),    ret_expr(M:F(Func,As1), Bs1, RBs);local_func(Func, As, _Bs, {M,F,Eas}, RBs) ->    local_func2(apply(M, F, [Func,As|Eas]), RBs);%% Default unknown function handler to undefined function.local_func(Func, As0, _Bs0, none, _RBs) ->    erlang:raise(error, undef, [{erl_eval,Func,length(As0)}|stacktrace()]).local_func2({value,V,Bs}, RBs) ->    ret_expr(V, Bs, RBs);local_func2({eval,F,As,Bs}, RBs) -> % This reply is not documented.    %% The shell found F. erl_eval tries to do a tail recursive call,    %% something the shell cannot do. Do not use Ef here.    do_apply(F, As, Bs, none, RBs).%% bif(Name, Arguments, RBs)%%  Evaluate the Erlang auto-imported function Name. erlang:apply/2,3%%  are "hidden" from the external function handler.bif(apply, [erlang,apply,As], Bs, Ef, RBs) ->    bif(apply, As, Bs, Ef, RBs);bif(apply, [M,F,As], Bs, Ef, RBs) ->    do_apply({M,F}, As, Bs, Ef, RBs);bif(apply, [F,As], Bs, Ef, RBs) ->    do_apply(F, As, Bs, Ef, RBs);bif(Name, As, Bs, Ef, RBs) ->    do_apply({erlang,Name}, As, Bs, Ef, RBs).%% do_apply(MF, Arguments, Bindings, ExternalFuncHandler, RBs) ->%%	{value,Value,Bindings} | Value when%%	ExternalFuncHandler = {value,F} | none.%% MF is a tuple {Module,Function} or a fun.do_apply({M,F}=Func, As, Bs0, Ef, RBs)  when is_tuple(M), size(M) >= 1, is_atom(element(1, M)), is_atom(F) ->    case Ef of        none when RBs =:= value ->            %% Make tail recursive calls when possible.            apply(M, F, As);        none ->            ret_expr(apply(M, F, As), Bs0, RBs);        {value,Fun} when RBs =:= value ->            Fun(Func, As);        {value,Fun} ->            ret_expr(Fun(Func, As), Bs0, RBs)    end;do_apply(Func, As, Bs0, Ef, RBs) ->    Env = if              is_function(Func) ->                   case {erlang:fun_info(Func, module),                        erlang:fun_info(Func, env)} of                      {{module,?MODULE},{env,Env1}} when Env1 =/= [] ->                          {env,Env1};                      _ ->                          no_env                  end;              true ->                   no_env          end,    case {Env,Ef} of        {{env,[FBs, FEf, FLf, FCs]},_} ->            %% If we are evaluting within another function body             %% (RBs =/= none), we return RBs when this function body            %% has been evalutated, otherwise we return Bs0, the            %% bindings when evalution of this function body started.            NRBs = if                       RBs =:= none -> Bs0;                       true -> RBs                   end,            case {erlang:fun_info(Func, arity), length(As)} of                {{arity, Arity}, Arity} ->                    eval_fun(FCs, As, FBs, FLf, FEf, NRBs);                _ ->                    erlang:raise(error, {badarity,{Func,As}},stacktrace())            end;        {no_env,none} when RBs =:= value ->            %% Make tail recursive calls when possible.            apply(Func, As);        {no_env,none} ->            ret_expr(apply(Func, As), Bs0, RBs);        {no_env,{value,F}} when RBs =:= value ->            F(Func,As);        {no_env,{value,F}} ->            ret_expr(F(Func, As), Bs0, RBs)    end.%% eval_lc(Expr, [Qualifier], Bindings, LocalFunctionHandler, %%         ExternalFuncHandler, RetBindings) ->%%	{value,Value,Bindings} | Valueeval_lc(E, Qs, Bs, Lf, Ef, RBs) ->    ret_expr(lists:reverse(eval_lc1(E, Qs, Bs, Lf, Ef, [])), Bs, RBs).eval_lc1(E, [{generate,_,P,L0}|Qs], Bs0, Lf, Ef, Acc0) ->    {value,L1,_Bs1} = expr(L0, Bs0, Lf, Ef, none),    CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, Acc) end,    eval_generate(L1, P, Bs0, Lf, Ef, CompFun, Acc0);eval_lc1(E, [{b_generate,_,P,L0}|Qs], Bs0, Lf, Ef, Acc0) ->    {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none),    CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, Acc) end,    eval_b_generate(Bin, P, Bs0, Lf, Ef, CompFun, Acc0);eval_lc1(E, [F|Qs], Bs0, Lf, Ef, Acc) ->    CompFun = fun(Bs) -> eval_lc1(E, Qs, Bs, Lf, Ef, Acc) end,    eval_filter(F, Bs0, Lf, Ef, CompFun, Acc);eval_lc1(E, [], Bs, Lf, Ef, Acc) ->    {value,V,_} = expr(E, Bs, Lf, Ef, none),    [V|Acc].%% eval_bc(Expr, [Qualifier], Bindings, LocalFunctionHandler, %%         ExternalFuncHandler, RetBindings) ->%%	{value,Value,Bindings} | Valueeval_bc(E, Qs, Bs, Lf, Ef, RBs) ->    ret_expr(eval_bc1(E, Qs, Bs, Lf, Ef, <<>>), Bs, RBs).eval_bc1(E, [{b_generate,_,P,L0}|Qs], Bs0, Lf, Ef, Acc0) ->    {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none),    CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, Acc) end,    eval_b_generate(Bin, P, Bs0, Lf, Ef, CompFun, Acc0);eval_bc1(E, [{generate,_,P,L0}|Qs], Bs0, Lf, Ef, Acc0) ->    {value,List,_Bs1} = expr(L0, Bs0, Lf, Ef, none),    CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, Acc) end,    eval_generate(List, P, Bs0, Lf, Ef, CompFun, Acc0);eval_bc1(E, [F|Qs], Bs0, Lf, Ef, Acc) ->    CompFun = fun(Bs) -> eval_bc1(E, Qs, Bs, Lf, Ef, Acc) end,    eval_filter(F, Bs0, Lf, Ef, CompFun, Acc);eval_bc1(E, [], Bs, Lf, Ef, Acc) ->    {value,V,_} = expr(E, Bs, Lf, Ef, none),    <<Acc/bitstr,V/bitstr>>.eval_generate([V|Rest], P, Bs0, Lf, Ef, CompFun, Acc) ->    case match(P, V, new_bindings(), Bs0) of	{match,Bsn} ->	    Bs2 = add_bindings(Bsn, Bs0),	    NewAcc = CompFun(Bs2, Acc),	    eval_generate(Rest, P, Bs0, Lf, Ef, CompFun, NewAcc);	nomatch -> 	    eval_generate(Rest, P, Bs0, Lf, Ef, CompFun, Acc)	end;eval_generate([], _P, _Bs0, _Lf, _Ef, _CompFun, Acc) ->    Acc;eval_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->    erlang:raise(error, {bad_generator,Term}, stacktrace()).eval_b_generate(<<_/bitstr>>=Bin, P, Bs0, Lf, Ef, CompFun, Acc) ->    Mfun = fun(L, R, Bs) -> match1(L, R, Bs, Bs0) end,    Efun = fun(Exp, Bs) -> expr(Exp, Bs, Lf, Ef, none) end,    case eval_bits:bin_gen(P, Bin, new_bindings(), Bs0, Mfun, Efun) of	{match, Rest, Bs1} ->	    Bs2 = add_bindings(Bs1, Bs0),	    NewAcc = CompFun(Bs2, Acc),	    eval_b_generate(Rest, P, Bs0, Lf, Ef, CompFun, NewAcc);	{nomatch, Rest} ->	    eval_b_generate(Rest, P, Bs0, Lf, Ef, CompFun, Acc);	done ->	    Acc    end;eval_b_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->    erlang:raise(error, {bad_generator,Term}, stacktrace()).eval_filter(F, Bs0, Lf, Ef, CompFun, Acc) ->    case erl_lint:is_guard_test(F) of	true ->	    case guard_test(F, Bs0, Lf, Ef) of		{value,true,Bs1} -> CompFun(Bs1);		{value,false,_} -> Acc	    end;	false ->	    case expr(F, Bs0, Lf, Ef, none) of		{value,true,Bs1} -> CompFun(Bs1);		{value,false,_} -> Acc;		{value,V,_} ->                     erlang:raise(error, {bad_filter,V}, stacktrace())	    end    end.%% RBs is the bindings to return when the evalution of a function%% (fun) has finished. If RBs =:= none, then the evalution took place%% outside a function. If RBs =:= value, only the value (not the bindings)%% is to be returned (to a compiled function).ret_expr(V, _Bs, value) ->    V;ret_expr(V, Bs, none) ->    {value,V,Bs};ret_expr(V, _Bs, RBs) when is_list(RBs) ->    {value,V,RBs}.%% eval_fun(Clauses, Arguments, Bindings, LocalFunctionHandler, %%          ExternalFunctionHandler) -> Value%% This function is called when the fun is called from compiled code%% or from apply.eval_fun(Cs, As, Bs0, Lf, Ef) ->    eval_fun(Cs, As, Bs0, Lf, Ef, value).eval_fun([{clause,_,H,G,B}|Cs], As, Bs0, Lf, Ef, RBs) ->    case match_list(H, As, new_bindings(), Bs0) of	{match,Bsn} ->                      % The new bindings for the head	    Bs1 = add_bindings(Bsn, Bs0),   % which then shadow!	    case guard(G, Bs1, Lf, Ef) of		true -> exprs(B, Bs1, Lf, Ef, RBs);		false -> eval_fun(Cs, As, Bs0, Lf, Ef, RBs)	    end;	nomatch ->	    eval_fun(Cs, As, Bs0, Lf, Ef, RBs)    end;eval_fun([], As, _Bs, _Lf, _Ef, _RBs) ->    '-inside-a-shell-fun-'(), % Dummy call to avoid warning.    %% list_to_tuple/1 below to avoid arity check.    erlang:raise(error, function_clause, 		 [{?MODULE,'-inside-a-shell-fun-',As}|stacktrace()]).'-inside-a-shell-fun-'() -> ok.%% expr_list(ExpressionList, Bindings)%% expr_list(ExpressionList, Bindings, LocalFuncHandler)%% expr_list(ExpressionList, Bindings, LocalFuncHandler, ExternalFuncHandler)%%  Evaluate a list of expressions "in parallel" at the same level.expr_list(Es, Bs) ->    expr_list(Es, Bs, none, none).expr_list(Es, Bs, Lf) ->    expr_list(Es, Bs, Lf, none).expr_list(Es, Bs, Lf, Ef) ->    expr_list(Es, [], Bs, Bs, Lf, Ef).    expr_list([E|Es], Vs, BsOrig, Bs0, Lf, Ef) ->    {value,V,Bs1} = expr(E, BsOrig, Lf, Ef, none),    expr_list(Es, [V|Vs], BsOrig, merge_bindings(Bs1, Bs0), Lf, Ef);expr_list([], Vs, _, Bs, _Lf, _Ef) ->    {reverse(Vs),Bs}.eval_op(Op, Arg1, Arg2, Bs, Ef, RBs) ->    do_apply({erlang,Op}, [Arg1,Arg2], Bs, Ef, RBs).eval_op(Op, Arg, Bs, Ef, RBs) ->    do_apply({erlang,Op}, [Arg], Bs, Ef, RBs).%% if_clauses(Clauses, Bindings, LocalFuncHandler, ExtFuncHandler, RBs)if_clauses([{clause,_,[],G,B}|Cs], Bs, Lf, Ef, RBs) ->    case guard(G, Bs, Lf, Ef) of	true -> exprs(B, Bs, Lf, Ef, RBs);	false -> if_clauses(Cs, Bs, Lf, Ef, RBs)    end;if_clauses([], _Bs, _Lf, _Ef, _RBs) ->    erlang:raise(error, if_clause, stacktrace()).%% try_clauses(Body, CaseClauses, CatchClauses, AfterBody, Bindings, %%             LocalFuncHandler, ExtFuncHandler, RBs)%% When/if variable bindings between the different parts of a%% try-catch expression are introduced this will have to be rewritten.try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs) ->    try exprs(B, Bs, Lf, Ef, none) of	{value,V,Bs1} when Cases =:= [] ->	    ret_expr(V, Bs1, RBs);	{value,V,Bs1} ->	    case match_clause(Cases, [V], Bs1, Lf, Ef) of		{B2,Bs2} ->		    exprs(B2, Bs2, Lf, Ef, RBs);		nomatch ->		    erlang:raise(error, {try_clause,V}, stacktrace())	    end    catch	Class:Reason when Catches =:= [] ->	    %% Rethrow	    erlang:raise(Class, Reason, stacktrace());	Class:Reason ->%%% 	    %% Set stacktrace%%% 	    try erlang:raise(Class, Reason, stacktrace())%%% 	    catch _:_ -> ok %%% 	    end,            V = {Class,Reason,erlang:get_stacktrace()},	    case match_clause(Catches, [V],Bs, Lf, Ef) of		{B2,Bs2} ->		    exprs(B2, Bs2, Lf, Ef, RBs);		nomatch ->		    erlang:raise(Class, Reason, stacktrace())	    end    after	if AB =:= [] -> 		Bs; % any	   true ->		exprs(AB, Bs, Lf, Ef, none)	end    end.%% case_clauses(Value, Clauses, Bindings, LocalFuncHandler, ExtFuncHandler, %%              RBs)case_clauses(Val, Cs, Bs, Lf, Ef, RBs) ->    case match_clause(Cs, [Val], Bs, Lf, Ef) of	{B, Bs1} ->	    exprs(B, Bs1, Lf, Ef, RBs);	nomatch ->	    erlang:raise(error, {case_clause,Val}, stacktrace())    end.%%%% receive_clauses(Clauses, Bindings, LocalFuncHnd,ExtFuncHnd, Messages, RBs) %%receive_clauses(Cs, Bs, Lf, Ef, Ms, RBs) ->    receive	Val ->	    case match_clause(Cs, [Val], Bs, Lf, Ef) of		{B, Bs1} ->		    merge_queue(Ms),		    exprs(B, Bs1, Lf, Ef, RBs);		nomatch ->		    receive_clauses(Cs, Bs, Lf, Ef, [Val|Ms], RBs)	    end    end.%%%% receive_clauses(TimeOut, Clauses, TimeoutBody, Bindings, %%                 ExternalFuncHandler, LocalFuncHandler, RBs)%%receive_clauses(T, Cs, TB, Bs, Lf, Ef, Ms, RBs) ->    {_,_} = statistics(runtime),    receive	Val ->	    case match_clause(Cs, [Val], Bs, Lf, Ef) of		{B, Bs1} ->		    merge_queue(Ms),		    exprs(B, Bs1, Lf, Ef, RBs);		nomatch ->		    {_,T1} = statistics(runtime),		    if			T =:= infinity ->			    receive_clauses(T, Cs, TB,Bs,Lf,Ef,[Val|Ms],RBs);			T-T1 =< 0 ->			    receive_clauses(0, Cs, TB,Bs,Lf,Ef,[Val|Ms],RBs);			true ->			    receive_clauses(T-T1, Cs,TB,Bs,Lf,Ef,[Val|Ms],RBs)		    end	    end    after T ->	    merge_queue(Ms),	    {B, Bs1} = TB,	    exprs(B, Bs1, Lf, Ef, RBs)    end.merge_queue(Ms) ->    send_all(recv_all(Ms), self()).recv_all(Xs) ->    receive	X -> recv_all([X|Xs])    after 0 ->

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?