d2ad352f78
meta.yap contains meta-expansion new mod.yap contains module declarations module.yap keeps the rest. undefcode refers to meta expansion lots of annoying little errors.
176 lines
4.7 KiB
Prolog
176 lines
4.7 KiB
Prolog
/*************************************************************************
|
|
* *
|
|
* YAP Prolog *
|
|
* *
|
|
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
|
* *
|
|
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
|
* *
|
|
**************************************************************************
|
|
* *
|
|
* File: undefined.yap *
|
|
* Last rev: 8/2/88 *
|
|
* mods: *
|
|
* comments: Predicate Undefined for YAP *
|
|
* *
|
|
*************************************************************************/
|
|
|
|
/** @defgroup Undefined_Procedures Handling Undefined Procedures
|
|
@ingroup YAPControl
|
|
@{
|
|
|
|
A predicate in a module is said to be undefined if there are no clauses
|
|
defining the predicate, and if the predicate has not been declared to be
|
|
dynamic. What YAP does when trying to execute undefined predicates can
|
|
be specified in three different ways:
|
|
|
|
|
|
+ By setting an YAP flag, through the yap_flag/2 or
|
|
set_prolog_flag/2 built-ins. This solution generalizes the
|
|
ISO standard by allowing module-specific behavior.
|
|
+ By using the unknown/2 built-in (this deprecated solution is
|
|
compatible with previous releases of YAP).
|
|
+ By defining clauses for the hook predicate
|
|
`user:unknown_predicate_handler/3`. This solution is compatible
|
|
with SICStus Prolog.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
* @pred '$undefp_expand'(+ M0:G0, -MG)
|
|
*
|
|
* @param G0 input goal
|
|
* @param M0 current module
|
|
* @param G1 new goal
|
|
*
|
|
* @return succeeds on finding G1, otherwise fails.
|
|
*
|
|
* Tries:
|
|
* 1 - `user:unknown_predicate_handler`
|
|
* 2 - `goal_expansion`
|
|
* 1 - `import` mechanism`
|
|
*/
|
|
'$undefp_expand'(M0:G0, MG) :-
|
|
user:unknown_predicate_handler(G0,M0,M1:G1),
|
|
M0:G0 \== M1:G1,
|
|
!,
|
|
(
|
|
'$pred_exists'(G1, M1)
|
|
->
|
|
MG = M1:G1
|
|
;
|
|
'$undefp_expand_user'(M1:G1, MG)
|
|
).
|
|
'$undefp_expand'(MG0, MG) :-
|
|
'$undefp_expand_user'(MG0, MG).
|
|
|
|
'$undefp_expand_user'(M0:G0, MG) :-
|
|
'_user_expand_goal'(M0:G0, MG1),
|
|
M0:G0 \== MG1,
|
|
!,
|
|
'$yap_strip_module'( MG1, M1, G1),
|
|
(
|
|
'$pred_exists'(G1, M1)
|
|
->
|
|
MG = M1:G1
|
|
;
|
|
'$undefp_expand_import'(M1:G1, MG)
|
|
).
|
|
'$undefp_expand_user'(MG0, MG) :-
|
|
'$undefp_expand_import'(MG0, MG).
|
|
|
|
'$undefp_expand_import'(M0:G0, M1:G1) :-
|
|
'$get_undefined_pred'(G0, M0, G1, M1),
|
|
M0:G0 \== M1:G1.
|
|
|
|
'$undefp'([M0|G0], Default) :-
|
|
% make sure we do not loop on undefined predicates
|
|
yap_flag( unknown, Unknown, fast_fail),
|
|
yap_flag( debug, Debug, false),
|
|
(
|
|
'$undefp_expand'(M0:G0, NM:Goal),
|
|
Goal \= fail,
|
|
'$complete_goal'(M0, G0, Goal, NM, NG)
|
|
->
|
|
yap_flag( unknown, _, Unknown),
|
|
yap_flag( debug, _, Debug),
|
|
'$execute0'(NG, NM)
|
|
;
|
|
yap_flag( unknown, _, Unknown),
|
|
yap_flag( debug, _, Debug),
|
|
'$handle_error'(Default,G0,M0)
|
|
).
|
|
|
|
/** @pred unknown(- _O_,+ _N_)
|
|
|
|
The unknown predicate, informs about what the user wants to be done
|
|
when there are no clauses for a certain predicate.
|
|
|
|
This predicate is strongly deprecated. Use prolog_flag for generic
|
|
behaviour, and user:unknown_predicate_handler/3 for flexible behaviour
|
|
on undefined goals.
|
|
|
|
*/
|
|
|
|
unknown(P, NP) :-
|
|
prolog_flag( unknown, P, NP ).
|
|
|
|
/** @pred user:unknown_predicate_handler(+ _Call_, + _M_, - _N_)
|
|
|
|
In YAP, the default action on undefined predicates is to output an
|
|
`error` message. Alternatives are to silently `fail`, or to print a
|
|
`warning` message and then fail. This follows the ISO Prolog standard
|
|
where the default action is `error`.
|
|
|
|
The user:unknown_predicate_handler/3 hook was originally include in
|
|
SICStus Prolog. It allows redefining the answer for specifici
|
|
calls. As an example. after defining `undefined/1` by:
|
|
|
|
~~~~~{.prolog}
|
|
undefined(A) :- format('Undefined predicate: ~w~n',[A]), fail.
|
|
~~~~~
|
|
and executing the goal:
|
|
|
|
~~~~~{.prolog}
|
|
:- assert(user:unknown_predicate_handler(U,M,undefined(M:U)) )
|
|
~~~~~
|
|
a call to a predicate for which no clauses were defined will result in
|
|
the output of a message of the form:
|
|
|
|
~~~~~{.prolog}
|
|
Undefined predicate: user:xyz(A1,A2)
|
|
~~~~~
|
|
followed by the failure of that call.
|
|
*/
|
|
:- multifile user:unknown_predicate_handler/3.
|
|
|
|
'$handle_error'(error,Goal,Mod) :-
|
|
functor(Goal,Name,Arity),
|
|
'program_continuation'(PMod,PName,PAr),
|
|
'$do_error'(existence_error(procedure,Name/Arity),context(Mod:Goal,PMod:PName/PAr)).
|
|
'$handle_error'(warning,Goal,Mod) :-
|
|
functor(Goal,Name,Arity),
|
|
'program_continuation'(PMod,PName,PAr),
|
|
print_message(warning,error(existence_error(procedure,Name/Arity), context(Mod:Goal,PMod:PName/PAr))),
|
|
fail.
|
|
'$handle_error'(fail,_Goal,_Mod) :-
|
|
fail.
|
|
|
|
:- '$set_no_trace'('$handle_error'(_,_,_), prolog).
|
|
|
|
'$complete_goal'(M, _G, CurG, CurMod, NG) :-
|
|
(
|
|
'$is_metapredicate'(CurG,CurMod)
|
|
->
|
|
'$expand_meta_call'(CurMod:CurG, [], NG)
|
|
;
|
|
NG = CurG
|
|
).
|
|
|
|
/**
|
|
@}
|
|
*/
|