mnemosyne_op.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 604 行 · 第 1/2 页
ERL
604 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(mnemosyne_op).-export([bindings/3, funcall/4, erl_expr/2, split/2, table/2, negation/3, negation_help/0, call_recursive_op/2, split_list/2, get_from_table/3, new_end_token/1, start_op/2, add_tid/5, update_endc/3 ]).%%-define(debug,3).-define(no_not_yet, yes).-include("mnemosyne_debug.hrl").-include("mnemosyne_internal_form.hrl").-record(acc, {sols=[], bss=[]}).-ifdef(debug).-define(trace_printout(Type,Args,Where), case Type of negation_help when Where==1 -> wait_a_bit; _ -> ?debugmsg(1, "~w (~w) -> ~w. Args: ~s\n", [self(), Type, hd(Args), type_dependent_args(Type, Args)]) end).type_dependent_args(bindings, [_,_,Bs]) -> [" ",mnemosyne_pp:e({'#bindings',1,Bs})];type_dependent_args(table, [_,P]) when ?debug==2 -> [" line=",mnemosyne_pp:e({'#line',P#pred_sym.line}), " p=",mnemosyne_pp:e(P#pred_sym.pattern), " bp=",mnemosyne_pp:e(P#pred_sym.back_pattern), " idx=",io_lib:write(P#pred_sym.idx_method) ];type_dependent_args(table, [_,P]) when ?debug>2 -> [" line=",mnemosyne_pp:e({'#line',P#pred_sym.line}), " goal=",mnemosyne_pp:e(P), " p=",mnemosyne_pp:e(P#pred_sym.pattern), " bp=",mnemosyne_pp:e(P#pred_sym.back_pattern), " idx=",io_lib:write(P#pred_sym.idx_method), " defvars=",io_lib:write(P#pred_sym.defvars) ];type_dependent_args(negation, [_,HelpPid]) -> [" help=",io_lib:write(HelpPid) ];type_dependent_args(negation_help, [Qpid,MainPid]) -> [" QueryPid=",io_lib:write(Qpid), " MainPid=",io_lib:write(MainPid) ];type_dependent_args(Type, Args) -> [" ",mnemosyne_pp:e(Args)].-else.-define(trace_printout(Type,Args,Where),ok).-endif.%%%================================================================%%% Exportsstart_op(Type, Args) -> ?trace_printout(Type, Args, 1), %% The Type(Args) call never returns unless there is an exception: case catch apply(?MODULE, Type, Args) of {'EXIT',Cause} -> exit(Cause); Others -> exit({throw,Others}) end.new_end_token(N) -> {{make_ref(),erlang:now()}, N}.%%%----------------------------------------------------------------%%%---- Adds bindings to a set of bindingsbindings(NextPid, BCount,Bs) -> bindings(NextPid, BCount,Bs, Bs, {[],[],[]}).bindings(NextPid, BCount,Bs, BsOrig, {Tid, PidL, EndC}) -> receive {bss, Bss, Max, EndCntrl, Stack, LastMarker} when Bss =/= [] -> NewEndC = update_endc (PidL, EndC, LastMarker), case check_lastmarker (NewEndC, BCount, LastMarker) of true -> NextPid ! {bss, bss_union(Bss,Bs), Max, EndCntrl, Stack, {true, self()}}; _ -> NextPid ! {bss, bss_union(Bss,Bs), Max, EndCntrl, Stack, false} end, bindings(NextPid, BCount, [], BsOrig, {Tid, PidL, NewEndC}); {bss, _, Max, EndCntrl, Stack, LastMarker} -> NewEndC = update_endc (PidL, EndC, LastMarker), case check_lastmarker (NewEndC, BCount, LastMarker) of true -> NextPid ! {bss, [], Max, EndCntrl, Stack, {true, self()}}; _ -> NextPid ! {bss, [], Max, EndCntrl, Stack, false} end, bindings(NextPid, BCount, [], BsOrig, {Tid, PidL, NewEndC}); {fail, SomePid, Cause} -> NextPid ! {fail, self(), Cause}, bindings(NextPid, BCount, BsOrig); {tid, NTid, Pid} -> NextPid ! {tid,Tid}, bindings(NextPid, BCount,Bs, BsOrig, add_tid (Tid, PidL, EndC, NTid, Pid)) end.%%%----------------------------------------------------------------%%%---- Call an Erlang functi nfuncall (NextPid, LeftSide, FunCall, Count) -> funcall_loop (NextPid, LeftSide, FunCall, Count, {[], [], []}).funcall_loop(NextPid, LeftSide, FunCall, Count, {Tid, PidL, EndC}) -> receive {bss, Bss, Max, EndCntrl, Stack, LastMarker} -> NewEndC = update_endc (PidL, EndC, LastMarker), case eval_funcall(Bss,LeftSide,FunCall,[]) of {fail, Cause} -> NextPid ! {fail, self(), Cause}; {ok, NewBss} -> ?debugmsg(3,"~w: ~w ! ~w\n", [self(), NextPid, {bss, NewBss, Max, EndCntrl, Stack}]), case check_lastmarker (NewEndC, Count, LastMarker) of true -> NextPid ! {bss, NewBss, Max, EndCntrl, Stack, {true, self ()}}; _ -> NextPid ! {bss, NewBss, Max, EndCntrl, Stack, false} end end, funcall_loop (NextPid, LeftSide, FunCall, Count, {Tid, PidL, NewEndC}); {fail, SomePid, Cause} -> NextPid ! {fail, self(), Cause}, funcall (NextPid, LeftSide, FunCall, Count); {tid, NTid, Pid} -> NextPid ! {tid,NTid, self()}, funcall_loop(NextPid, LeftSide, FunCall, Count, add_tid (Tid, PidL, EndC, NTid, Pid)) end. eval_funcall([Bs|Bss], LeftSide, FunCall, Acc) -> {'#funcall',M,F,Args} = mnemosyne_unify:instantiate(FunCall,Bs), Ref = make_ref(), case catch {Ref, apply(M,F,Args)} of {Ref, Res} -> case mnemosyne_unify:unify(LeftSide, apply(M,F,Args), Bs) of fail -> eval_funcall(Bss, LeftSide, FunCall, Acc); NewBs -> eval_funcall(Bss, LeftSide, FunCall, [NewBs|Acc]) end; {'EXIT', Cause} -> {fail, Cause}; Other -> {fail, {throw, Other}} end; eval_funcall([], LeftSide, FunCall, Acc) -> {ok, Acc}. %%%----------------------------------------------------------------%%%---- erl_expr(NextPid, Expr) -> erl_expr(NextPid, Expr, [], {[],[],[]}).erl_expr(NextPid, Expr, Sols, {Tid, PidL, EndC}) -> receive {bss, Bss, Max, EndCntrl, Stack, LastMarker} -> NewEndC = update_endc (PidL, EndC, LastMarker), {First, Last} = split_list(Max, get_values(Bss,Expr,Sols)), case {Last, check_lastmarker(NewEndC, Expr#erl_expr.rec_count, LastMarker)} of {[], true} -> NextPid ! {bss, First, Max, EndCntrl, Stack, {true, self ()}}; _ -> NextPid ! {bss, First, Max, EndCntrl, Stack, false} end, erl_expr(NextPid, Expr, Last, {Tid, PidL, NewEndC}); {fail, SomePid, Cause} -> NextPid ! {fail, self(), Cause}, erl_expr (NextPid, Expr); {tid, NTid, Pid} -> NextPid ! {tid, NTid, self()}, erl_expr(NextPid, Expr, [], add_tid (Tid, PidL, EndC, NTid, Pid)) end.get_values(Bss, Expr, Acc0) -> lists:foldl( fun(Bs,Acc) -> ?debugmsg(2,"~w: Value = ~w\n", [self(), mnemosyne_unify:instantiate(Expr#erl_expr.expr,Bs)]),% case mnemosyne_unify:unify(% mnemosyne_unify:instantiate(Expr#erl_expr.expr,Bs),% Expr#erl_expr.alias_var,% Bs) of% fail -> Acc;% NewBs -> [NewBs|Acc]% end unify_list(mnemosyne_unify:instantiate(Expr#erl_expr.expr,Bs), Expr#erl_expr.alias_var, Bs, Acc) end, Acc0, Bss).%%%----------------------------------------------------------------%%%---- Multiplexes a message to many receiverssplit (NextPids, Count) -> split_loop (NextPids, Count, {[],[],[]}).split_loop(NextPids, Count, {Tid, PidL,EndC}) -> receive {bss, Bss, Max, EndCntrl, Stack, LastMarker} -> NewEndC = update_endc (PidL, EndC, LastMarker), NewEnd = new_end_token(length(NextPids)), case check_lastmarker (NewEndC, Count, LastMarker) of true -> hd(NextPids) ! {bss, Bss, Max, [NewEnd|EndCntrl], Stack, {true, self ()}}, send(tl(NextPids), {bss, Bss, Max, [NewEnd], Stack, {true, self ()}}); _ -> hd(NextPids) ! {bss, Bss, Max, [NewEnd|EndCntrl], Stack, false}, send(tl(NextPids), {bss, Bss, Max, [NewEnd], Stack, false}) end, split_loop (NextPids, Count, {Tid, PidL, NewEndC}); {fail, SomePid, Cause} -> send(NextPids, {fail, self(), Cause}), split (NextPids, Count); {tid, NTid,Pid} -> send(NextPids, {tid,NTid, self ()}), split_loop (NextPids, Count, add_tid (Tid, PidL, EndC, NTid, Pid)) end.%%%----------------------------------------------------------------%%%---- Table lookuptable(NextPid, P) when is_record(P,pred_sym) -> table_loop(NextPid, P, #acc{}, {[], [], []}).%%%----------------------------------------------------------------%%%---- Negationnegation(NextPid, Count,HelpPid) -> negation(NextPid, Count,HelpPid, [], {[], [], []}).negation_help() -> receive {pids, Buddie, NextPid} -> ?trace_printout(negation_help, [NextPid,Buddie], 2), negation_help(NextPid,Buddie,[], {[],[], []}) end.%%%----------------------------------------------------------------%%---- Recursion%% A first solution. For each binding, get ALL solutions from SLG and%% THEN pass them on to the DestPid.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?