This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/pl/top.yap

1046 lines
26 KiB
Plaintext
Raw Normal View History

2018-04-07 19:45:18 +01:00
/**
* @file top.yap
* @author VITOR SANTOS COSTA <vsc@vcosta-laptop.dcc.fc.up.pt>
* @date Sat Apr 7 03:14:17 2018
*
2018-05-20 18:40:56 +01:00
* @brief top-level implementation plus system booting.
2018-04-07 19:45:18 +01:00
*
2018-05-20 18:40:56 +01:00
* @addtogroup TopLevel Top-Level and Boot Predicates
2018-04-07 19:45:18 +01:00
* @ingroup YAPControl
2018-10-15 13:47:36 +01:00
*
* [TOC]
*
* @{
2019-01-27 10:11:56 +00:00
*
*/
2019-05-10 03:05:40 +01:00
:- '$system_meta_predicates'([gated_call(0, 0, ?, 0), catch(0, ?, 0), log_event(+, :)]).
2018-04-07 19:45:18 +01:00
2018-05-20 18:40:56 +01:00
% @pred live
%
% start a Prolog engine.
2018-05-24 12:00:10 +01:00
live :-
repeat,
2019-05-10 03:05:40 +01:00
yap_flag(verbose, normal),
current_source_module(Module, Module),
( Module==user
-> true % '$compile_mode'(_,0)
; format(user_error, '[~w]~n', [Module])
2018-05-24 12:00:10 +01:00
),
2019-05-10 03:05:40 +01:00
'$system_catch'('$enter_top_level',
Module,
Error,
'$Error'(Error)).
2018-01-22 13:53:17 +00:00
% Start file for yap
/* I/O predicates */
/* meaning of flags for '$write' is
1 quote illegal atoms
2 ignore operator declarations
4 output '$VAR'(N) terms as A, B, C, ...
8 use portray(_)
*/
/* main execution loop */
2018-01-27 10:17:27 +00:00
'$read_toplevel'(Goal, Bindings, Pos) :-
2019-05-20 01:00:41 +01:00
'$prompt',
2019-05-10 03:05:40 +01:00
catch(read_term(user_input,
Goal,
[ variable_names(Bindings),
syntax_errors(dec10),
2019-05-17 17:49:30 +01:00
term_position(Pos),
input_closing_blank(true)
2019-05-10 03:05:40 +01:00
]),
E,
'$handle_toplevel_error'(E)).
'$handle_toplevel_error'(syntax_error(_)) :-
!,
fail.
'$handle_toplevel_error'(error(io_error(read, user_input), _)) :-
!.
2018-01-22 13:53:17 +00:00
'$handle_toplevel_error'(_, E) :-
2019-05-10 03:05:40 +01:00
throw(E).
2018-01-22 13:53:17 +00:00
% reset alarms when entering top-level.
'$enter_top_level' :-
2019-05-10 03:05:40 +01:00
'$alarm'(0, 0, _, _),
fail.
2018-01-22 13:53:17 +00:00
'$enter_top_level' :-
2019-05-10 03:05:40 +01:00
'$clean_up_dead_clauses',
fail.
2018-01-22 13:53:17 +00:00
'$enter_top_level' :-
2019-05-10 03:05:40 +01:00
get_value('$top_level_goal', GA),
GA\=[],
!,
set_value('$top_level_goal', []),
'$run_atom_goal'(GA),
fail.
2018-01-27 10:17:27 +00:00
'$enter_top_level' :-
2018-05-24 12:00:10 +01:00
flush_output,
2019-05-10 03:05:40 +01:00
'$run_toplevel_hooks',
prompt1(' ?- '),
'$read_toplevel'(Command, Varnames, Pos),
'$init_debugger',
'$command'(Command, Varnames, Pos, top),
current_prolog_flag(break_level, BreakLevel),
( BreakLevel\=0
-> true
; '$pred_exists'(halt(_), user)
-> halt(0)
; '$halt'(0)
).
2018-01-22 13:53:17 +00:00
'$erase_sets' :-
2019-05-10 03:05:40 +01:00
eraseall($),
eraseall('$$set'),
eraseall('$$one'),
eraseall('$reconsulted'),
fail.
'$erase_sets' :-
\+ recorded('$path', _, _),
recorda('$path', [], _).
2018-01-22 13:53:17 +00:00
'$erase_sets'.
'$start_corouts' :-
eraseall('$corout'),
eraseall('$result'),
eraseall('$actual'),
fail.
'$start_corouts' :- recorda('$actual',main,_),
recordz('$corout','$corout'(main,main,'$corout'([],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[])),_Ref),
recorda('$result',going,_).
%
% Hack in case expand_term has created a list of commands.
%
2018-02-07 21:48:37 +00:00
'$execute_commands'(V,_,_,_,_,Source) :- var(V), !,
2018-01-22 13:53:17 +00:00
'$do_error'(instantiation_error,meta_call(Source)).
2018-02-07 21:48:37 +00:00
'$execute_commands'([],_,_,_,_,_) :- !.
'$execute_commands'([C|Cs],M,VL,Pos,Con,Source) :-
2018-02-02 11:50:07 +00:00
!,
(
2018-02-07 21:48:37 +00:00
'$system_catch'('$execute_command'(C,M,VL,Pos,Con,Source),prolog,Error,'$LoopError'(Error, Con)),
2018-02-02 11:50:07 +00:00
fail
;
2018-02-07 21:48:37 +00:00
'$execute_commands'(Cs,M,VL,Pos,Con,Source)
2018-02-02 11:50:07 +00:00
).
2018-02-07 21:48:37 +00:00
'$execute_commands'(C,M,VL,Pos,Con,Source) :-
'$execute_command'(C,M,VL,Pos,Con,Source).
2018-01-22 13:53:17 +00:00
%
%
%
2018-02-07 21:48:37 +00:00
'$execute_command'(C,_,_,_,_,Source) :-
2018-01-22 13:53:17 +00:00
var(C),
!,
'$do_error'(instantiation_error,meta_call(Source)).
2018-02-07 21:48:37 +00:00
'$execute_command'(C,_,_,_,_top,Source) :-
2018-01-22 13:53:17 +00:00
number(C),
!,
'$do_error'(type_error(callable,C),meta_call(Source)).
2018-02-07 21:48:37 +00:00
'$execute_command'(R,_,_,_,_top,Source) :-
2018-01-22 13:53:17 +00:00
db_reference(R),
!,
'$do_error'(type_error(callable,R),meta_call(Source)).
2018-02-07 21:48:37 +00:00
'$execute_command'(end_of_file,_,_,_,_,_) :- !.
'$execute_command'(Command,_,_,_,_,_) :-
2018-01-22 13:53:17 +00:00
'__NB_getval__'('$if_skip_mode', skip, fail),
\+ '$if_directive'(Command),
!.
2018-02-07 21:48:37 +00:00
'$execute_command'((:-G),M,VL,Pos,Option,_) :-
2018-02-02 11:50:07 +00:00
Option \= top,
!, % allow user expansion
2018-02-07 21:48:37 +00:00
'$expand_term'((:- M:G), O),
'$yap_strip_module'(O, NM, NO),
2018-02-02 11:50:07 +00:00
(
2018-02-07 21:48:37 +00:00
NO = (:- G1)
2018-01-27 10:17:27 +00:00
->
2018-02-07 21:48:37 +00:00
'$process_directive'(G1, Option, NM, VL, Pos)
2018-01-27 10:17:27 +00:00
;
2018-02-07 21:48:37 +00:00
'$execute_commands'(G1,NM,VL,Pos,Option,O)
2018-01-27 10:17:27 +00:00
).
2018-02-07 21:48:37 +00:00
'$execute_command'((?-G), M, VL, Pos, Option, Source) :-
2018-01-22 13:53:17 +00:00
Option \= top,
!,
2018-02-07 21:48:37 +00:00
'$execute_command'(G, M, VL, Pos, top, Source).
'$execute_command'(G, M, VL, Pos, Option, Source) :-
'$continue_with_command'(Option, VL, Pos, M:G, Source).
2018-01-22 13:53:17 +00:00
2018-02-02 11:50:07 +00:00
'$expand_term'(T,O) :-
2018-02-20 22:59:17 +00:00
'$expand_term'(T,top,O).
'$expand_term'(T,Con,O) :-
2019-05-10 03:05:40 +01:00
catch( '$expand_term0'(T,Con,O), _,( '$reenter_debugger'(exit), fail) ),
2018-02-02 11:50:07 +00:00
!.
2019-01-31 11:54:17 +00:00
'$expand_term0'(T,consult,O) :-
expand_term( T, O).
'$expand_term0'(T,reconsult,O) :-
expand_term( T, O).
'$expand_term0'(T,top,O) :-
2018-02-20 22:59:17 +00:00
expand_term( T, T1),
2018-02-02 11:50:07 +00:00
!,
2018-02-07 21:48:37 +00:00
'$expand_term1'(T1,O).
2018-02-20 22:59:17 +00:00
'$expand_term0'(T,_,T).
2018-02-02 11:50:07 +00:00
'$expand_term1'(T,O) :-
2019-02-19 15:53:36 +00:00
'$expand_meta_call'(T, none, O).
2018-02-02 11:50:07 +00:00
2018-01-22 13:53:17 +00:00
'$continue_with_command'(Where,V,'$stream_position'(C,_P,A1,A2,A3),'$source_location'(_F,L):G,Source) :-
!,
'$continue_with_command'(Where,V,'$stream_position'(C,L,A1,A2,A3),G,Source).
'$continue_with_command'(reconsult,V,Pos,G,Source) :-
% writeln(G),
'$go_compile_clause'(G,V,Pos,reconsult,Source),
fail.
'$continue_with_command'(consult,V,Pos,G,Source) :-
'$go_compile_clause'(G,V,Pos,consult,Source),
fail.
'$continue_with_command'(top,V,_,G,_) :-
'$query'(G,V).
%%
% @pred '$go_compile_clause'(G,Vs,Pos, Where, Source) is det
%
% interfaces the loader and the compiler
% not 100% compatible with SICStus Prolog, as SICStus Prolog would put
% module prefixes all over the place, although unnecessarily so.
%
% @param [in] _G_ is the clause to compile
% @param [in] _Vs_ a list of variables and their name
% @param [in] _Pos_ the source-code position
% @param [in] _N_ a flag telling whether to add first or last
% @param [out] _Source_ the user-tranasformed clause
'$go_compile_clause'(G, _Vs, _Pos, Where, Source) :-
'$precompile_term'(G, Source, G1),
!,
2019-03-06 10:49:55 +00:00
'$$compile'(G1, Where, Source, _).
2018-01-22 13:53:17 +00:00
'$go_compile_clause'(G,_Vs,_Pos, _Where, _Source) :-
throw(error(system, compilation_failed(G))).
'$$compile'(C, Where, C0, R) :-
2019-03-06 10:49:55 +00:00
'$head_and_body'( C, H, B ),
'$yap_strip_module'(H,Mod,H0),
2018-01-22 13:53:17 +00:00
(
2019-03-06 10:49:55 +00:00
'$undefined'(H0, Mod)
2018-01-22 13:53:17 +00:00
->
2019-03-06 10:49:55 +00:00
'$init_pred'(H0, Mod, Where)
2018-01-22 13:53:17 +00:00
;
2019-03-06 10:49:55 +00:00
true
2018-01-22 13:53:17 +00:00
),
% writeln(Mod:((H:-B))),
2019-03-06 10:49:55 +00:00
'$compile'((H0:-B), Where, C0, Mod, R).
2018-01-22 13:53:17 +00:00
'$init_pred'(H, Mod, _Where ) :-
recorded('$import','$import'(NM,Mod,NH,H,_,_),RI),
% NM \= Mod,
functor(NH,N,Ar),
print_message(warning,redefine_imported(Mod,NM,Mod:N/Ar)),
erase(RI),
2019-01-31 11:52:03 +00:00
clause(Mod:H,_,R), erase(R),
2018-01-22 13:53:17 +00:00
fail.
'$init_pred'(H, Mod, Where ) :-
'$init_as_dynamic'(Where),
!,
functor(H, Na, Ar),
'$dynamic'(Na/Ar, Mod).
'$init_pred'(_H, _Mod, _Where ).
'$init_as_dynamic'( asserta ).
'$init_as_dynamic'( assertz ).
'$init_as_dynamic'( consult ) :-
'__NB_getval__'('$assert_all',on,fail).
'$init_as_dynamic'( reconsult ) :-
'__NB_getval__'('$assert_all',on,fail).
'$check_if_reconsulted'(N,A) :-
once(recorded('$reconsulted',N/A,_)),
recorded('$reconsulted',X,_),
( X = N/A , !;
X = '$', !, fail;
fail
).
'$inform_as_reconsulted'(N,A) :-
recorda('$reconsulted',N/A,_).
'$clear_reconsulting' :-
recorded('$reconsulted',X,Ref),
erase(Ref),
X == '$',
!,
( recorded('$reconsulting',_,R) -> erase(R) ).
'$prompt_alternatives_on'(determinism).
/* Executing a query */
'$query'(end_of_file,_).
'$query'(G,[]) :-
'$prompt_alternatives_on'(OPT),
( OPT = groundness ; OPT = determinism),
!,
'$yes_no'(G,(?-)).
'$query'(G,V) :-
(
'$current_module'(M),
'$current_choice_point'(CP),
'$user_call'(G, M),
'$current_choice_point'(NCP),
'$delayed_goals'(G, V, Vs, LGs, DCP),
'$write_answer'(Vs, LGs, Written),
'$write_query_answer_true'(Written),
(
2019-02-20 10:45:21 +00:00
yap_flag(prompt_alternatives_on,determinism), CP == NCP, DCP = 0
2018-01-22 13:53:17 +00:00
->
format(user_error, '.~n', []),
!
;
'$another',
!
),
fail
;
'$out_neg_answer'
).
'$yes_no'(G,C) :-
'$current_module'(M),
'$do_yes_no'(G,M),
'$delayed_goals'(G, [], NV, LGs, _),
'$write_answer'(NV, LGs, Written),
( Written = [] ->
!,'$present_answer'(C, true)
;
'$another', !
),
fail.
'$yes_no'(_,_) :-
'$out_neg_answer'.
'$add_env_and_fail' :- fail.
'$process_answer'(Vs, LGs, Bindings) :-
2019-01-27 10:11:56 +00:00
%'$purge_dontcares'(Vs,IVs),
'$sort'(Vs, NVs),
2018-12-21 20:57:53 +00:00
'$prep_answer_var_by_var'(NVs, LAnsw, LGs),
'$name_vars_in_goals'(LAnsw, Vs, Bindings).
2018-01-22 13:53:17 +00:00
%
% *-> at this point would require compiler support, which does not exist.
%
'$delayed_goals'(G, V, NV, LGs, NCP) :-
(
2018-10-25 13:57:18 +01:00
'$$save_by'(NCP1),
2018-01-22 13:53:17 +00:00
attributes:delayed_goals(G, V, NV, LGs),
2018-10-25 13:57:18 +01:00
'$clean_ifcp'(NCP1),
'$$save_by'(NCP2),
2018-01-22 13:53:17 +00:00
NCP is NCP2-NCP1
;
copy_term_nat(V, NV),
LGs = [],
% term_factorized(V, NV, LGs),
NCP = 0
).
'$out_neg_answer' :-
print_message( help, false),
fail.
'$do_yes_no'([X|L], M) :-
!,
'$csult'([X|L], M).
'$do_yes_no'(G, M) :-
'$user_call'(G, M).
'$write_query_answer_true'([]) :- !,
format(user_error,true,[]).
'$write_query_answer_true'(_).
%
% present_answer has three components. First it flushes the streams,
% then it presents the goals, and last it shows any goals frozen on
% the arguments.
%
'$present_answer'(_,_):-
flush_output,
fail.
'$present_answer'((?-), Answ) :-
current_prolog_flag(break_level, BL ),
( BL \= 0 -> format(user_error, '[~p] ',[BL]) ;
true ),
2019-02-10 00:18:08 +00:00
current_prolog_flag(toplevel_print_options, Opts),
write_term(user_error,Answ,Opts).
2018-01-22 13:53:17 +00:00
'$another' :-
'$clear_input'(user_input),
2019-05-19 09:48:13 +01:00
prompt1(' ? '),
2018-01-22 13:53:17 +00:00
get_code(user_input,C),
'$do_another'(C).
'$do_another'(C) :-
2019-05-19 09:48:13 +01:00
( C=:= ";" ->
2019-05-10 03:05:40 +01:00
skip(user_input,10),
2018-01-22 13:53:17 +00:00
% '$add_nl_outside_console',
fail
;
C== 10
->
'$add_nl_outside_console',
(
'$undefined'(print_message(_,_),prolog)
->
format(user_error,'yes~n', [])
;
print_message(help,yes)
)
;
C== 13
->
get0(user_input,NC),
'$do_another'(NC)
;
C== -1
->
halt
;
skip(user_input,10), '$ask_again_for_another'
).
%'$add_nl_outside_console' :-
% '$is_same_tty'(user_input, user_error), !.
'$add_nl_outside_console' :-
format(user_error,'~n',[]).
'$ask_again_for_another' :-
format(user_error,'Action (\";\" for more choices, <return> for exit)', []),
'$another'.
'$write_answer'(_,_,_) :-
flush_output,
fail.
'$write_answer'(Vs, LBlk, FLAnsw) :-
'$process_answer'(Vs, LBlk, NLAnsw),
'$write_vars_and_goals'(NLAnsw, first, FLAnsw).
2018-06-01 08:37:25 +01:00
%% @pred write_query_answer( +Bindings )
2018-05-20 18:40:56 +01:00
%
% YAP uses this routine to output the answer to a query.
% _Bindings_ are
% - unifications
% - suspended or floundered goals, representing constraints.
%
2018-01-22 13:53:17 +00:00
write_query_answer( Bindings ) :-
'$write_vars_and_goals'(Bindings, first, _FLAnsw).
'$purge_dontcares'([],[]).
'$purge_dontcares'([Name=_|Vs],NVs) :-
2019-05-09 12:44:50 +01:00
atom_codes(Name, [C|_]),
C is "_",
!,
'$purge_dontcares'(Vs,NVs).
2018-01-22 13:53:17 +00:00
'$purge_dontcares'([V|Vs],[V|NVs]) :-
2019-05-09 12:44:50 +01:00
'$purge_dontcares'(Vs,NVs).
2018-01-22 13:53:17 +00:00
'$prep_answer_var_by_var'([], L, L).
'$prep_answer_var_by_var'([Name=Value|L], LF, L0) :-
'$delete_identical_answers'(L, Value, NL, Names),
'$prep_answer_var'([Name|Names], Value, LF, LI),
'$prep_answer_var_by_var'(NL, LI, L0).
% fetch all cases that have the same solution.
'$delete_identical_answers'([], _, [], []).
'$delete_identical_answers'([(Name=Value)|L], Value0, FL, [Name|Names]) :-
Value == Value0, !,
'$delete_identical_answers'(L, Value0, FL, Names).
'$delete_identical_answers'([VV|L], Value0, [VV|FL], Names) :-
'$delete_identical_answers'(L, Value0, FL, Names).
% now create a list of pairs that will look like goals.
'$prep_answer_var'(Names, Value, LF, L0) :- var(Value), !,
'$prep_answer_unbound_var'(Names, LF, L0).
'$prep_answer_var'(Names, Value, [nonvar(Names,Value)|L0], L0).
% ignore unbound variables
'$prep_answer_unbound_var'([_], L, L) :- !.
'$prep_answer_unbound_var'(Names, [var(Names)|L0], L0).
'$gen_name_string'(I,L,[C|L]) :- I < 26, !, C is I+65.
'$gen_name_string'(I,L0,LF) :-
I1 is I mod 26,
I2 is I // 26,
C is I1+65,
'$gen_name_string'(I2,[C|L0],LF).
'$write_vars_and_goals'([], _, []).
'$write_vars_and_goals'([nl,G1|LG], First, NG) :- !,
nl(user_error),
'$write_goal_output'(G1, First, NG, Next, IG),
'$write_vars_and_goals'(LG, Next, IG).
'$write_vars_and_goals'([G1|LG], First, NG) :-
'$write_goal_output'(G1, First, NG, Next, IG),
'$write_vars_and_goals'(LG, Next, IG).
2018-12-14 14:53:39 +00:00
2018-01-22 13:53:17 +00:00
'$write_goal_output'(var([V|VL]), First, [var([V|VL])|L], next, L) :- !,
( First = first -> true ; format(user_error,',~n',[]) ),
format(user_error,'~a',[V]),
'$write_output_vars'(VL).
'$write_goal_output'(nonvar([V|VL],B), First, [nonvar([V|VL],B)|L], next, L) :- !,
( First = first -> true ; format(user_error,',~n',[]) ),
format(user_error,'~a',[V]),
'$write_output_vars'(VL),
format(user_error,' = ', []),
2018-06-01 13:22:13 +01:00
( yap_flag(toplevel_print_options, Opts) ->
2018-01-22 13:53:17 +00:00
write_term(user_error,B,[priority(699)|Opts]) ;
write_term(user_error,B,[priority(699)])
).
'$write_goal_output'(nl, First, NG, First, NG) :- !,
format(user_error,'~n',[]).
'$write_goal_output'(Format-G, First, NG, Next, IG) :- !,
G = [_|_], !,
% dump on string first so that we can check whether we actually
% had any output from the solver.
2018-12-14 14:53:39 +00:00
format(string(String),Format,G),
2018-12-12 00:39:17 +00:00
( String == `` ->
2018-01-22 13:53:17 +00:00
% we didn't
IG = NG, First = Next
;
% we did
2018-12-12 00:39:17 +00:00
format(user_error, '~N~s', [String]),
2018-01-22 13:53:17 +00:00
NG = [G|IG]
).
'$write_goal_output'(_-G, First, [G|NG], next, NG) :- !,
( First = first -> true ; format(user_error,',~n',[]) ),
( yap_flag(toplevel_print_options, Opts) ->
write_term(user_error,G,Opts) ;
format(user_error,'~w',[G])
).
'$write_goal_output'(_M:G, First, [G|NG], next, NG) :- !,
( First = first -> true ; format(user_error,',~n',[]) ),
( yap_flag(toplevel_print_options, Opts) ->
write_term(user_error,G,Opts) ;
format(user_error,'~w',[G])
).
2019-04-07 23:09:01 +01:00
'$write_goal_output'(G0, First, [M:G|NG], next, NG) :-
'$yap_strip_module'(G0,M,G),
2018-01-22 13:53:17 +00:00
( First = first -> true ; format(user_error,',~n',[]) ),
( yap_flag(toplevel_print_options, Opts) ->
write_term(user_error,G,Opts) ;
format(user_error,'~w',[G])
).
'$name_vars_in_goals'(G, VL0, G) :-
'$name_well_known_vars'(VL0),
'$variables_in_term'(G, [], GVL),
'$name_vars_in_goals1'(GVL, 0, _).
'$name_well_known_vars'([]).
'$name_well_known_vars'([Name=V|NVL0]) :-
var(V), !,
V = '$VAR'(Name),
'$name_well_known_vars'(NVL0).
'$name_well_known_vars'([_|NVL0]) :-
'$name_well_known_vars'(NVL0).
'$name_vars_in_goals1'([], I, I).
'$name_vars_in_goals1'([V|NGVL], I0, IF) :-
2018-12-16 02:25:48 +00:00
I is I0+1,
2018-01-22 13:53:17 +00:00
'$gen_name_string'(I0,[],SName), !,
atom_codes(Name, [95|SName]),
V = '$VAR'(Name),
'$name_vars_in_goals1'(NGVL, I, IF).
'$name_vars_in_goals1'([NV|NGVL], I0, IF) :-
nonvar(NV),
'$name_vars_in_goals1'(NGVL, I0, IF).
'$write_output_vars'([]).
'$write_output_vars'([V|VL]) :-
format(user_error,' = ~a',[V]),
'$write_output_vars'(VL).
%
% standard meta-call, called if $execute could not do everything.
%
'$meta_call'(G, M) :-
'$current_choice_point'(CP),
'$call'(G, CP, G, M).
'$user_call'(G, M) :-
2019-05-20 01:00:41 +01:00
'$current_choice_point'(CP),
gated_call('$start_user_code',M:G,Port,'$reenter_debugger'(Port)).
2018-01-22 13:53:17 +00:00
'$cut_by'(CP) :- '$$cut_by'(CP).
%
% do it in ISO mode.
%
'$meta_call'(G,_ISO,M) :-
'$iso_check_goal'(G,G),
'$current_choice_point'(CP),
'$call'(G, CP, G, M).
'$meta_call'(G, CP, G0, M) :-
'$call'(G, CP, G0, M).
'$call'(G, CP, G0, _, M) :- /* iso version */
'$iso_check_goal'(G,G0),
'$call'(G, CP, G0, M).
2018-02-07 21:48:37 +00:00
'$call'(M:G,CP,G0,_M0) :- !,
2019-05-24 15:26:21 +01:00
expand_goal(M:G, NG),
must_be_callable(NG),
'$yap_strip_module'(NG,NM,NC),
2018-02-07 21:48:37 +00:00
'$call'(NC,CP,G0,NM).
2018-01-22 13:53:17 +00:00
'$call'((X,Y),CP,G0,M) :- !,
'$call'(X,CP,G0,M),
'$call'(Y,CP,G0,M).
'$call'((X->Y),CP,G0,M) :- !,
(
'$call'(X,CP,G0,M)
->
'$call'(Y,CP,G0,M)
).
'$call'((X*->Y),CP,G0,M) :- !,
'$call'(X,CP,G0,M),
'$call'(Y,CP,G0,M).
'$call'((X->Y; Z),CP,G0,M) :- !,
(
'$call'(X,CP,G0,M)
->
'$call'(Y,CP,G0,M)
;
'$call'(Z,CP,G0,M)
).
'$call'((X*->Y; Z),CP,G0,M) :- !,
(
'$current_choice_point'(DCP),
'$call'(X,CP,G0,M),
yap_hacks:cut_at(DCP),
'$call'(Y,CP,G0,M)
;
'$call'(Z,CP,G0,M)
).
'$call'((A;B),CP,G0,M) :- !,
(
'$call'(A,CP,G0,M)
;
'$call'(B,CP,G0,M)
).
'$call'((X->Y| Z),CP,G0,M) :- !,
(
'$call'(X,CP,G0,M)
->
'$call'(Y,CP,G0,M)
;
'$call'(Z,CP,G0,M)
).
2018-04-20 14:59:17 +01:00
2018-01-22 13:53:17 +00:00
'$call'((X*->Y| Z),CP,G0,M) :- !,
(
'$current_choice_point'(DCP),
'$call'(X,CP,G0,M),
yap_hacks:cut_at(DCP),
'$call'(Y,CP,G0,M)
;
'$call'(Z,CP,G0,M)
).
'$call'((A|B),CP, G0,M) :- !,
(
'$call'(A,CP,G0,M)
;
'$call'(B,CP,G0,M)
).
'$call'(\+ X, _CP, G0, M) :- !,
\+ ('$current_choice_point'(CP),
'$call'(X,CP,G0,M) ).
'$call'(not(X), _CP, G0, M) :- !,
\+ ('$current_choice_point'(CP),
'$call'(X,CP,G0,M) ).
2019-02-17 23:19:26 +00:00
'$call'(!, CP, _G0, _m) :- !,
2018-01-22 13:53:17 +00:00
'$$cut_by'(CP).
2018-07-31 22:15:06 +01:00
'$call'([X|Y], _, _, M) :-
(Y == [] ->
consult(M:X)
;
'$csult'([X|Y] ,M)
2018-11-22 13:48:21 +00:00
).
'$call'(G, _CP, _G0, CurMod) :-
2018-01-22 13:53:17 +00:00
% /*
% (
% '$is_metapredicate'(G,CurMod)
% ->
2019-05-10 03:05:40 +01:00
% '$reenter_debugger'(exit)',
2018-01-22 13:53:17 +00:00
% ( '$expand_meta_call'(CurMod:G, [], NG) -> true ; true ),
% '$enable_debugging'
% ;
% NG = G
% ),
% */
'$execute0'(G, CurMod).
'$loop'(Stream,exo) :-
2019-03-20 10:52:38 +00:00
prolog_flag(agc_margin,Old,0),
2019-05-19 09:48:13 +01:00
prompt1(': '), prompt(_,'| '),
2019-04-08 13:16:21 +01:00
source_module(OldModule,OldModule),
2019-03-20 10:52:38 +00:00
repeat,
'$system_catch'(dbload_from_stream(Stream, OldModule, exo), '$db_load', Error,
user:'$LoopError'(Error, top)),
prolog_flag(agc_margin,_,Old),
!.
2018-01-22 13:53:17 +00:00
'$loop'(Stream,db) :-
2019-03-20 10:52:38 +00:00
prolog_flag(agc_margin,Old,0),
2019-05-19 09:48:13 +01:00
prompt1(': '), prompt(_,'| '),
2019-04-08 13:16:21 +01:00
source_module(OldModule,OldModule),
2019-03-21 09:02:43 +00:00
repeat,
'$system_catch'(dbload_from_stream(Stream, OldModule, db), '$db_load', Error, user:'$LoopError'(Error, db)
),
prolog_flag(agc_margin,_,Old),
2018-01-22 13:53:17 +00:00
!.
'$loop'(Stream,Status) :-
2019-02-27 04:23:21 +00:00
repeat,
'$current_module'( OldModule, OldModule ),
'$system_catch'( '$enter_command'(Stream,OldModule,Status),
2018-01-22 13:53:17 +00:00
OldModule, Error,
2019-02-27 04:23:21 +00:00
user:'$LoopError'(Error, Status)
2018-01-22 13:53:17 +00:00
),
2019-02-27 04:23:21 +00:00
!.
2018-01-22 13:53:17 +00:00
'$boot_loop'(Stream,Where) :-
repeat,
2019-04-08 13:16:21 +01:00
source_module( OldModule, OldModule ),
2018-01-22 13:53:17 +00:00
read_clause(Stream, Command, [module(OldModule), syntax_errors(dec10),variable_names(_Vars), term_position(_Pos)]),
(Command == end_of_file
->
!
;
Command = (:- Goal) ->
'$system_catch'('$boot_execute'(Goal), prolog, Error,
user:'$LoopError'(Error, consult) ),
fail
;
Command = (H --> B) ->
'$system_catch'('$boot_dcg'(H,B, Where), prolog, Error,
user:'$LoopError'(Error, consult) ),
fail
;
'$system_catch'('$boot_clause'( Command, Where ), prolog, Error,
user:'$LoopError'(Error, consult) ),
fail
).
'$boot_execute'( Goal ) :-
'$execute'( Goal ),
!.
'$boot_execute'( Goal ) :-
format(user_error, ':- ~w failed.~n', [Goal]).
'$boot_dcg'( H, B, Where ) :-
'$translate_rule'((H --> B), (NH :- NB) ),
2019-03-06 10:49:55 +00:00
'$$compile'((NH :- NB), Where, ( H --> B), _R),
2018-01-22 13:53:17 +00:00
!.
'$boot_dcg'( H, B, _ ) :-
format(user_error, ' ~w --> ~w failed.~n', [H,B]).
'$boot_clause'( Command, Where ) :-
'$$compile'(Command, Where, Command, _R),
!.
'$boot_clause'( Command, _ ) :-
format(user_error, ' ~w failed.~n', [Command]).
'$enter_command'(Stream, Mod, Status) :-
prompt1(': '), prompt(_,' '),
Options = [module(Mod), syntax_errors(dec10),variable_names(Vars), term_position(Pos)],
(
Status == top
->
read_term(Stream, Command, Options)
;
read_clause(Stream, Command, Options)
),
2019-02-27 04:23:21 +00:00
'$command'(Command,Vars,Pos, Status) .
2018-01-22 13:53:17 +00:00
/** @pred user:expand_term( _T_,- _X_) is dynamic,multifile.
This user-defined predicate is called by YAP after
reading goals and clauses.
- _Module_:`expand_term(` _T_ , _X_) is called first on the
current source module _Module_ ; if i
- `user:expand_term(` _T_ , _X_ `)` is available on every module.
*/
/* General purpose predicates */
2018-10-25 13:57:18 +01:00
'$head_and_body'(M:(H:-B),M:H,M:B) :- !.
2018-01-22 13:53:17 +00:00
'$head_and_body'((H:-B),H,B) :- !.
'$head_and_body'(H,H,true).
gated_call(Setup, Goal, Catcher, Cleanup) :-
'$setup_call_catcher_cleanup'(Setup),
'$gated_call'( true , Goal, Catcher, Cleanup) .
'$gated_call'( All , Goal, Catcher, Cleanup) :-
Task0 = cleanup( All, Catcher, Cleanup, Tag, true, CP0),
TaskF = cleanup( All, Catcher, Cleanup, Tag, false, CP0),
'$tag_cleanup'(CP0, Task0),
2018-04-23 14:34:52 +01:00
call( Goal ),
2018-01-22 13:53:17 +00:00
'$cleanup_on_exit'(CP0, TaskF).
%
% split head and body, generate an error if body is unbound.
%
2019-01-21 01:11:42 +00:00
'$check_head_and_body'(C,M,H,B,_P) :-
2018-01-22 13:53:17 +00:00
'$yap_strip_module'(C,M1,(MH:-B0)),
!,
'$yap_strip_module'(M1:MH,M,H),
( M == M1 -> B = B0 ; B = M1:B0),
2019-05-24 15:26:21 +01:00
must_be_callable(M:H).
2018-01-22 13:53:17 +00:00
2019-01-21 01:11:42 +00:00
'$check_head_and_body'(MH, M, H, true, _XsP) :-
2018-01-22 13:53:17 +00:00
'$yap_strip_module'(MH,M,H),
2019-05-24 15:26:21 +01:00
must_be_callable(M:H).
2018-01-22 13:53:17 +00:00
% term expansion
%
% return two arguments: Expanded0 is the term after "USER" expansion.
% Expanded is the final expanded term.
%
'$precompile_term'(Term, ExpandedUser, Expanded) :-
%format('[ ~w~n',[Term]),
'$expand_clause'(Term, ExpandedUser, ExpandedI),
!,
%format(' -> ~w~n',[Expanded0]),
(
current_prolog_flag(strict_iso, true) /* strict_iso on */
->
Expanded = ExpandedI,
'$check_iso_strict_clause'(ExpandedUser)
;
'$expand_array_accesses_in_term'(ExpandedI,Expanded)
-> true
;
Expanded = ExpandedI
).
'$precompile_term'(Term, Term, Term).
'$expand_clause'(InputCl, C1, CO) :-
2019-03-06 10:49:55 +00:00
'$expand_a_clause'( InputCl, C1, CO),
2018-01-22 13:53:17 +00:00
!.
'$expand_clause'(Cl, Cl, Cl).
/** @pred expand_term( _T_,- _X_)
This predicate is used by YAP for preprocessing each top level
term read when consulting a file and before asserting or executing it.
It rewrites a term _T_ to a term _X_ according to the following
rules: first try term_expansion/2 in the current module, and then try to use the user defined predicate user:term_expansion/2`. If this call fails then the translating process
for DCG rules is applied, together with the arithmetic optimizer
whenever the compilation of arithmetic expressions is in progress.
*/
expand_term(Term,Expanded) :-
(
'$do_term_expansion'(Term,Expanded)
->
true
;
'$expand_term_grammar'(Term,Expanded)
).
%
% Grammar Rules expansion
%
'$expand_term_grammar'((A-->B), C) :-
prolog:'$translate_rule'((A-->B),C), !.
'$expand_term_grammar'(A, A).
%
% Arithmetic expansion
%
'$expand_array_accesses_in_term'(Expanded0,ExpandedF) :-
'$array_refs_compiled',
'$arrays':'$c_arrays'(Expanded0,ExpandedF), !.
'$expand_array_accesses_in_term'(Expanded,Expanded).
2018-05-20 18:40:56 +01:00
%% @}
2019-01-30 11:17:53 +00:00
%% @addtogroup CathThrow Catch and Throw
% @ingroup YAPControl
% @{
2018-05-20 18:40:56 +01:00
2018-01-22 13:53:17 +00:00
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% catch/throw implementation
% at each catch point I need to know:
% what is ball;
% where was the previous catch
2019-01-30 11:17:53 +00:00
/**
@pred catch( : _Goal_,+ _Exception_,+ _Action_) is iso
2018-01-22 13:53:17 +00:00
The goal `catch( _Goal_, _Exception_, _Action_)` tries to
execute goal _Goal_. If during its execution, _Goal_ throws an
exception _E'_ and this exception unifies with _Exception_, the
exception is considered to be caught and _Action_ is executed. If
the exception _E'_ does not unify with _Exception_, control
again throws the exception.
The top-level of YAP maintains a default exception handler that
is responsible to capture uncaught exceptions.
*/
catch(G, C, A) :-
'$catch'(G,C,A).
% makes sure we have an environment.
'$true'.
% system_catch is like catch, but it avoids the overhead of a full
% meta-call by calling '$execute0' instead of $execute.
% This way it
% also avoids module preprocessing and goal_expansion
%
'$system_catch'(G, M, C, A) :-
% check current trail
'$catch'(M:G,C,A).
'$catch'(MG,_,_) :-
'$$save_by'(CP0),
'$execute'(MG),
'$$save_by'(CP1),
% remove catch
(
CP0 == CP1
->
!
;
2018-05-24 12:00:10 +01:00
true
2018-01-22 13:53:17 +00:00
).
'$catch'(_,C,A) :-
2018-04-17 17:47:40 +01:00
'$get_exception'(C0),
2018-04-20 14:59:17 +01:00
( C = C0 -> '$execute_nonstop'(A, prolog) ; throw(C0) ).
% variable throws are user-handled.
'$run_catch'(G,E) :-
2018-04-16 14:54:53 +01:00
var(E),
!,
call(G ).
'$run_catch'(abort,_) :-
abort.
'$run_catch'('$Error'(E),E) :-
!,
'$LoopError'(E, top ).
'$run_catch'('$LoopError'(E, Where),E) :-
!,
'$LoopError'(E, Where).
'$run_catch'('$TraceError'(E, GoalNumber, G, Module, CalledFromDebugger),E) :-
!,
'$TraceError'(E, GoalNumber, G, Module, CalledFromDebugger).
'$run_catch'(_Signal,E) :-
functor( E, N, _),
'$hidden_atom'(N), !,
throw(E).
'$run_catch'( Signal, _E) :-
call( Signal ).
2018-04-10 00:54:34 +01:00
2018-01-22 13:53:17 +00:00
%
% throw has to be *exactly* after system catch!
%
/** @pred throw(+ _Ball_) is iso
The goal `throw( _Ball_)` throws an exception. Execution is
stopped, and the exception is sent to the ancestor goals until reaching
a matching catch/3, or until reaching top-level.
*/
'$run_toplevel_hooks' :-
current_prolog_flag(break_level, 0 ),
recorded('$toplevel_hooks',H,_),
H \= fail, !,
( call(user:H) -> true ; true).
'$run_toplevel_hooks'.
'$run_at_thread_start' :-
recorded('$thread_initialization',M:D,_),
'$meta_call'(D, M),
fail.
'$run_at_thread_start'.
log_event( String, Args ) :-
format( atom( M ), String, Args),
log_event( M ).
'$prompt' :-
current_prolog_flag(break_level, BreakLevel),
(
BreakLevel == 0
->
LF = LD
;
LF = ['Break (level ', BreakLevel, ')'|LD]
),
current_prolog_flag(debug, DBON),
2019-03-28 14:06:16 +00:00
(
DBON = true
2018-01-22 13:53:17 +00:00
->
2019-03-28 14:06:16 +00:00
(
2019-05-20 01:00:41 +01:00
'$get_debugger_state'( trace,on),
2019-03-28 14:06:16 +00:00
(
var(LF)
->
LD = ['trace'|LP]
;
LD = [', trace '|LP]
)
2018-01-22 13:53:17 +00:00
;
2019-03-28 14:06:16 +00:00
(var(LF)
2018-01-22 13:53:17 +00:00
->
2019-03-28 14:06:16 +00:00
LD = ['debug'|LP]
;
LD = [', debug'|LP]
)
)
2018-01-22 13:53:17 +00:00
;
LD = LP
2019-03-28 14:06:16 +00:00
),
2018-01-22 13:53:17 +00:00
(
var(LF)
->
LP = [P]
;
LP = [' ',P]
),
yap_flag(toplevel_prompt, P),
atomic_concat(LF, PF),
prompt1(PF),
prompt(_,' | '),
'$ensure_prompting'.
/**
2018-05-20 18:40:56 +01:00
@}
2018-01-22 13:53:17 +00:00
*/