fix predicate search

This commit is contained in:
Vitor Santos Costa 2017-06-06 12:47:59 +01:00
parent 2ad3420fac
commit f1ddb5822e
12 changed files with 95 additions and 121 deletions

View File

@ -834,7 +834,7 @@ Prop Yap_PredPropByFunctorNonThreadLocal(Functor f, Term cur_mod)
if ((p->ModuleOfPred == cur_mod || !(p->ModuleOfPred))) { if ((p->ModuleOfPred == cur_mod || !(p->ModuleOfPred))) {
/* don't match multi-files */ /* don't match multi-files */
if (!(p->PredFlags & MultiFileFlag) || p->ModuleOfPred || !cur_mod || if (/*!(p->PredFlags & MultiFileFlag) ||*/ true || p->ModuleOfPred || !cur_mod ||
cur_mod == TermProlog) { cur_mod == TermProlog) {
FUNC_WRITE_UNLOCK(f); FUNC_WRITE_UNLOCK(f);
return AbsPredProp(p); return AbsPredProp(p);
@ -871,7 +871,7 @@ Prop Yap_PredPropByAtomNonThreadLocal(Atom at, Term cur_mod)
if (pe->KindOfPE == PEProp && if (pe->KindOfPE == PEProp &&
(pe->ModuleOfPred == cur_mod || !pe->ModuleOfPred)) { (pe->ModuleOfPred == cur_mod || !pe->ModuleOfPred)) {
/* don't match multi-files */ /* don't match multi-files */
if (!(pe->PredFlags & MultiFileFlag) || pe->ModuleOfPred || !cur_mod || if (/*!(pe->PredFlags & MultiFileFlag) ||*/ true || pe->ModuleOfPred || !cur_mod ||
cur_mod == TermProlog) { cur_mod == TermProlog) {
WRITE_UNLOCK(ae->ARWLock); WRITE_UNLOCK(ae->ARWLock);
return (p0); return (p0);

View File

@ -1019,7 +1019,7 @@ static void retract_all(PredEntry *p, int in_use) {
} }
p->cs.p_code.FirstClause = NULL; p->cs.p_code.FirstClause = NULL;
p->cs.p_code.LastClause = NULL; p->cs.p_code.LastClause = NULL;
if (p->PredFlags & (DynamicPredFlag | LogUpdatePredFlag | MultiFileFlag)) { if (is_live(p)) {
p->OpcodeOfPred = FAIL_OPCODE; p->OpcodeOfPred = FAIL_OPCODE;
} else { } else {
p->OpcodeOfPred = UNDEF_OPCODE; p->OpcodeOfPred = UNDEF_OPCODE;
@ -1742,8 +1742,9 @@ bool Yap_addclause(Term t, yamop *cp, Term tmode, Term mod, Term *t4ref)
if (pflags & IndexedPredFlag) { if (pflags & IndexedPredFlag) {
Yap_AddClauseToIndex(p, cp, mode == asserta); Yap_AddClauseToIndex(p, cp, mode == asserta);
} }
if (pflags & (SpiedPredFlag | CountPredFlag | ProfiledPredFlag)) if (pflags & (SpiedPredFlag | CountPredFlag | ProfiledPredFlag)) {
spy_flag = true; spy_flag = true;
}
if (Yap_discontiguous(p, tmode PASS_REGS)) { if (Yap_discontiguous(p, tmode PASS_REGS)) {
Term disc[3], sc[4]; Term disc[3], sc[4];
if (p->ArityOfPE) { if (p->ArityOfPE) {
@ -1914,7 +1915,7 @@ void Yap_EraseStaticClause(StaticClause *cl, PredEntry *ap, Term mod) {
if (ap->cs.p_code.LastClause == cl->ClCode) { if (ap->cs.p_code.LastClause == cl->ClCode) {
/* got rid of all clauses */ /* got rid of all clauses */
ap->cs.p_code.LastClause = ap->cs.p_code.FirstClause = NULL; ap->cs.p_code.LastClause = ap->cs.p_code.FirstClause = NULL;
if (!(ap->PredFlags & MultiFileFlag)) { if (is_live(ap)) {
ap->OpcodeOfPred = FAIL_OPCODE; ap->OpcodeOfPred = FAIL_OPCODE;
} else { } else {
ap->OpcodeOfPred = UNDEF_OPCODE; ap->OpcodeOfPred = UNDEF_OPCODE;
@ -2434,23 +2435,21 @@ static Int p_new_multifile(USES_REGS1) { /* '$new_multifile'(+N,+Ar,+Mod) */
else else
pe = RepPredProp(PredPropByFunc(Yap_MkFunctor(at, arity), mod)); pe = RepPredProp(PredPropByFunc(Yap_MkFunctor(at, arity), mod));
PELOCK(26, pe); PELOCK(26, pe);
if (pe->PredFlags &
(UserCPredFlag | CArgsPredFlag | NumberDBPredFlag | AtomDBPredFlag |
TestPredFlag | AsmPredFlag | CPredFlag | BinaryPredFlag)) {
UNLOCKPE(26, pe);
addcl_permission_error(RepAtom(at), arity, FALSE);
return false;
}
pe->PredFlags &= ~UndefPredFlag;
if (pe->PredFlags & MultiFileFlag) { if (pe->PredFlags & MultiFileFlag) {
UNLOCKPE(26, pe); UNLOCKPE(26, pe);
return true; return true;
} }
if (pe->PredFlags & (TabledPredFlag|ForeignPredFlags)) {
UNLOCKPE(26, pe);
addcl_permission_error(RepAtom(at), arity, FALSE);
return false;
}
if (pe->cs.p_code.NOfClauses) { if (pe->cs.p_code.NOfClauses) {
UNLOCKPE(26, pe); UNLOCKPE(26, pe);
addcl_permission_error(RepAtom(at), arity, FALSE); addcl_permission_error(RepAtom(at), arity, FALSE);
return false; return false;
} }
pe->PredFlags &= ~UndefPredFlag;
pe->PredFlags |= MultiFileFlag; pe->PredFlags |= MultiFileFlag;
/* mutifile-predicates are weird, they do not seat really on the default /* mutifile-predicates are weird, they do not seat really on the default
* module */ * module */
@ -2727,7 +2726,7 @@ static Int p_pred_exists(USES_REGS1) { /* '$pred_exists'(+P,+M) */
UNLOCKPE(54, pe); UNLOCKPE(54, pe);
return false; return false;
} }
out = (pe->OpcodeOfPred != UNDEF_OPCODE); out = (is_live(pe) || pe->OpcodeOfPred != UNDEF_OPCODE);
UNLOCKPE(55, pe); UNLOCKPE(55, pe);
return out; return out;
} }
@ -2786,8 +2785,7 @@ static Int undefp_handler(USES_REGS1) { /* '$undefp_handler'(P,Mod) */
if (EndOfPAEntr(pe)) if (EndOfPAEntr(pe))
return false; return false;
PELOCK(59, pe); PELOCK(59, pe);
if (pe->OpcodeOfPred == UNDEF_OPCODE && if (pe->OpcodeOfPred == UNDEF_OPCODE) {
!(pe->PredFlags & (LogUpdatePredFlag|DynamicPredFlag|MultiFileFlag))) {
UNLOCKPE(59, pe); UNLOCKPE(59, pe);
return false; return false;
} }
@ -2803,12 +2801,7 @@ static Int p_undefined(USES_REGS1) { /* '$undefined'(P,Mod) */
if (EndOfPAEntr(pe)) if (EndOfPAEntr(pe))
return TRUE; return TRUE;
PELOCK(36, pe); PELOCK(36, pe);
if (pe->PredFlags & (CPredFlag | UserCPredFlag | TestPredFlag | AsmPredFlag |MultiFileFlag| if (!is_live(pe) && pe->OpcodeOfPred == UNDEF_OPCODE) {
DynamicPredFlag | LogUpdatePredFlag | TabledPredFlag)) {
UNLOCKPE(57, pe);
return FALSE;
}
if (pe->OpcodeOfPred == UNDEF_OPCODE) {
UNLOCKPE(58, pe); UNLOCKPE(58, pe);
return TRUE; return TRUE;
} }

View File

@ -2108,7 +2108,7 @@ static Int jump_env(USES_REGS1) {
Yap_find_prolog_culprit(PASS_REGS1); Yap_find_prolog_culprit(PASS_REGS1);
// LOCAL_Error_TYPE = ERROR_EVENT; // LOCAL_Error_TYPE = ERROR_EVENT;
Term t1 = ArgOfTerm(1, t); Term t1 = ArgOfTerm(1, t);
if (IsApplTerm(t) && IsAtomTerm((t2 = ArgOfTerm(1, t1)))) { if (IsApplTerm(t1) && IsAtomTerm((t2 = ArgOfTerm(1, t1)))) {
LOCAL_ActiveError->errorAsText = AtomOfTerm(t2); LOCAL_ActiveError->errorAsText = AtomOfTerm(t2);
LOCAL_ActiveError->classAsText = NameOfFunctor(FunctorOfTerm(t1)); LOCAL_ActiveError->classAsText = NameOfFunctor(FunctorOfTerm(t1));
} else if (IsAtomTerm(t)) { } else if (IsAtomTerm(t)) {

View File

@ -487,10 +487,9 @@ bool YAPEngine::mgoal(Term t, Term tmod)
if (ap == nullptr || ap->OpcodeOfPred == UNDEF_OPCODE) if (ap == nullptr || ap->OpcodeOfPred == UNDEF_OPCODE)
{ {
ap = rewriteUndefEngineQuery(ap, t, tmod); ap = rewriteUndefEngineQuery(ap, t, tmod);
} if (ap == nullptr || ap->OpcodeOfPred == UNDEF_OPCODE)
if (ap==nullptr)
return false; return false;
} else
{ {
/* legal ap */ /* legal ap */
arity_t arity = ap->ArityOfPE; arity_t arity = ap->ArityOfPE;

View File

@ -487,6 +487,8 @@ typedef uint64_t pred_flags_t;
#define ForeignPredFlags \ #define ForeignPredFlags \
(AsmPredFlag | SWIEnvPredFlag | CPredFlag | BinaryPredFlag | UDIPredFlag | \ (AsmPredFlag | SWIEnvPredFlag | CPredFlag | BinaryPredFlag | UDIPredFlag | \
CArgsPredFlag | UserCPredFlag | SafePredFlag | BackCPredFlag) CArgsPredFlag | UserCPredFlag | SafePredFlag | BackCPredFlag)
#define LivePredFlags \
(LogUpdatePredFlag|MultiFileFlag|TabledPredFlag|ForeignPredFlags)
#define StatePredFlags \ #define StatePredFlags \
(InUsePredFlag | CountPredFlag | SpiedPredFlag | IndexedPredFlag) (InUsePredFlag | CountPredFlag | SpiedPredFlag | IndexedPredFlag)
@ -495,6 +497,7 @@ typedef uint64_t pred_flags_t;
#define is_foreign(pe) (pe->PredFlags & ForeignPredFlags) #define is_foreign(pe) (pe->PredFlags & ForeignPredFlags)
#define is_static(pe) (pe->PredFlags & CompiledPredFlag) #define is_static(pe) (pe->PredFlags & CompiledPredFlag)
#define is_logupd(pe) (pe->PredFlags & LogUpdatePredFlag) #define is_logupd(pe) (pe->PredFlags & LogUpdatePredFlag)
#define is_live(pe) (pe->PredFlags & LivePredFlags)
#ifdef TABLING #ifdef TABLING
#define is_tabled(pe) (pe->PredFlags & TabledPredFlag) #define is_tabled(pe) (pe->PredFlags & TabledPredFlag)
#endif /* TABLING */ #endif /* TABLING */
@ -1414,7 +1417,7 @@ GetPredPropByFuncAndModHavingLock(FunctorEntry *fe, Term cur_mod) {
if (!(p = RepPredProp(fe->PropsOfFE))) { if (!(p = RepPredProp(fe->PropsOfFE))) {
return NIL; return NIL;
} }
if (p->ModuleOfPred == cur_mod) { if (p->ModuleOfPred == cur_mod || p->ModuleOfPred == 0) {
#ifdef THREADS #ifdef THREADS
/* Thread Local Predicates */ /* Thread Local Predicates */
if (p->PredFlags & ThreadLocalPredFlag) { if (p->PredFlags & ThreadLocalPredFlag) {
@ -1498,7 +1501,7 @@ INLINE_ONLY EXTERN inline Prop PredPropByAtomAndMod(Atom at, Term cur_mod)
p0 = ae->PropsOfAE; p0 = ae->PropsOfAE;
while (p0) { while (p0) {
PredEntry *pe = RepPredProp(p0); PredEntry *pe = RepPredProp(p0);
if (pe->KindOfPE == PEProp && (pe->ModuleOfPred == cur_mod)) { if (pe->KindOfPE == PEProp && (pe->ModuleOfPred == cur_mod || pe->ModuleOfPred == 0)) {
#ifdef THREADS #ifdef THREADS
/* Thread Local Predicates */ /* Thread Local Predicates */
if (pe->PredFlags & ThreadLocalPredFlag) { if (pe->PredFlags & ThreadLocalPredFlag) {

View File

@ -18,12 +18,15 @@ yap_query = namedtuple( 'yap_query', 'query owner')
jupyter_query = namedtuple( 'jupyter_query', 'vars dict') jupyter_query = namedtuple( 'jupyter_query', 'vars dict')
python_query = namedtuple( 'python_query', 'vars dict') python_query = namedtuple( 'python_query', 'vars dict')
yapi_query = namedtuple( 'yapi_query', 'vars dict') yapi_query = namedtuple( 'yapi_query', 'vars dict')
show_answer = namedtuple( 'show_answer', 'vars dict')
def v():
return yap.YAPVarTerm()
def numbervars( q ): def numbervars( q ):
Dict = {} Dict = {}
if True: if True:
engine.goal(yapi_query( q.namedVars(), Dict)) engine.goal(show_answer( q.namedVars(), Dict))
return Dict return Dict
rc = q.namedVarsVector() rc = q.namedVarsVector()
q.r = q.goal().numbervars() q.r = q.goal().numbervars()
@ -42,7 +45,10 @@ def numbervars( q ):
def answer(q): def answer(q):
try: try:
return q.next() v = q.next()
if v:
print( bindings )
return v
except Exception as e: except Exception as e:
print(e.args[1]) print(e.args[1])
return False return False
@ -52,7 +58,8 @@ def query_prolog(engine, s):
# #
# construct a query from a one-line string # construct a query from a one-line string
# q is opaque to Python # q is opaque to Python
q = engine.query(s) bindings = {}
q = engine.query(python_query(s, bindings))
# vs is the list of variables # vs is the list of variables
# you can print it out, the left-side is the variable name, # you can print it out, the left-side is the variable name,
# the right side wraps a handle to a variable # the right side wraps a handle to a variable
@ -64,10 +71,9 @@ def query_prolog(engine, s):
# if not isinstance(eq[0],str): # if not isinstance(eq[0],str):
# print( "Error: Variable Name matches a Python Symbol") # print( "Error: Variable Name matches a Python Symbol")
# return # return
# ask = True ask = True
# launch the query # launch the query
while answer(q): while answer(q):
print( handler( q ))
# deterministic = one solution # deterministic = one solution
if q.deterministic(): if q.deterministic():
# done # done
@ -98,7 +104,7 @@ def boot_yap(**kwargs):
args.setYapLibDir(yap_lib_path) args.setYapLibDir(yap_lib_path)
args.setSavedState(os.path.join(yap_lib_path,"startup.yss")) args.setSavedState(os.path.join(yap_lib_path,"startup.yss"))
engine = yap.YAPEngine(args) engine = yap.YAPEngine(args)
engine.goal( use_module(library('python') ) ) engine.goal( use_module(library('yapi') ) )
return engine return engine
def live(**kwargs): def live(**kwargs):

View File

@ -12,6 +12,7 @@
:- use_module( library(maplist) ). :- use_module( library(maplist) ).
:- use_module( library(rbtrees) ). :- use_module( library(rbtrees) ).
:- use_module( library(terms) ). :- use_module( library(terms) ).
:- use_module( library(python) ).
%% @pred yap_query(sGoal, + VarList, +OutStream, - Dictionary) %% @pred yap_query(sGoal, + VarList, +OutStream, - Dictionary)
@ -20,16 +21,18 @@
%% dictionary, Examples %% dictionary, Examples
%% %%
%% %%
python_query( Engine, String, Dict ) :- python_query( String, D ) :-
atomic_to_term( String, Goal, VarNames ), atomic_to_term( String, Goal, VarNames ),
yap_query( Goal, VarNames, user_error, Dict). yap_query( Goal, VarNames, user_error, Dict),
D := Dict,
yap4py.yapi.bindings := Dict.
%% @pred yapi_query( + VarList, - Dictionary) %% @pred yapi_query( + VarList, - Dictionary)
%% %%
%% dictionary, Examples %% dictionary, Examples
%% %%
%% %%
prologun:yapi_query( VarNames, Dict ) :- yapi_query( VarNames, Dict ) :-
show_answer(VarNames, Dict). show_answer(VarNames, Dict).
@ -48,28 +51,42 @@ yap_query( Goal, VarNames, Stream, Dictionary) :-
show_answer(VarNames, Stream, Dictionary) show_answer(VarNames, Stream, Dictionary)
). ).
yapi_query( VarNames, Dictionary) :- yap_query( VarNames, Dictionary) :-
yap_query( VarNames, user_output, Dictionary). yap_query( VarNames, user_output, Dictionary).
show_answer(QVs0, Dict) :- show_answer(QVs0, Dict) :-
show_answer(QVs0, user_error, Dict). show_answer(QVs0, user_error, Dict).
show_answer(QVs0, Stream, {Dict}) :- show_answer(QVs0, Stream, Dict) :-
copy_term(QVs0, QVs), copy_term(QVs0, QVs),
writeln(ivs-IVs), copy_term(QVs0, QVs1),
term_variables(Goal, IVs), rb_new(RB),
foldl(enumerate, IVs, 0, _Ns), foldl2(bind_qv, QVs, QVs1, [], LP, {}-RB, Dict-_),
!, !,
out(QVs, Stream, D). term_variables(QVs, IVs),
Dictt := {D}. term_variables(QVs1, IVs1),
foldl( enumerate, IVs, IVs1, 1, _ ),
out(LP, Stream ).
show_answer(_, _, {}) :- show_answer(_, _, {}) :-
format(' yes.~n', [] ). format(' yes.~n', [] ).
bind_qv(V=V0, Vs, Vs) :- var(V0), !, V0='$VAR'(V). bind_qv(V=V0, V1 = V01, Vs, Vs, Vs1-RB, Vs1-RB) :-
bind_qv(V=V, Vs, Vs) :- !. var(V0),
bind_qv(V=S, Vs, [V=S|Vs]). !,
'$VAR'(V) = V0,
V1 = V01.
% atom_string(V1, V01).
bind_qv(V='$VAR'(Vi), V1=S1, Vs, [V='$VAR'(Vi)|Vs], D0-RB, D-RB) :- !,
add2dict(D0, V1:S1, D).
bind_qv(V=S, V1=S1, Vs, [V=S|Vs], D0-RB0, D-RB0) :-
% fix_tree( S, SS, S1, SS1, RB0, RBT),
add2dict(D0, V1:S1, D).
enumerate('$VAR'(A), I, I1) :-
add2dict({}, B, {B}).
add2dict({C}, B, {B,C}).
enumerate('$VAR'(A), A, I, I1) :-
enum(I, Chars), enum(I, Chars),
atom_codes(A,[0'_|Chars]), atom_codes(A,[0'_|Chars]),
I1 is I + 1. I1 is I + 1.
@ -84,65 +101,18 @@ enum(I, [C|Cs]) :-
C is "A" +K, C is "A" +K,
enum(J, Cs). enum(J, Cs).
out(Bs, S, _Dict) :- out(Bs, S) :-
output(Bs, S), output(Bs, S),
fail. !.
out(Bs, _S, Dict) :- out([_|Bs], S) :-
bvs(Bs, Dict). out(Bs, S).
v2py(v(I0) = _V, I0, I) :-
!,
I is I0+1.
v2py(v(I0) = v(I0), I0, I) :-
I is I0+1.
output([V=B], S) :- output([V=B], S) :-
!, !,
format(S, '~a = ~q~n', [V, B]). format(S, '~a = ~q~n', [V, B]).
output([V=B|Ns], S) :- output([V=B|_Ns], S) :-
format( S, '~a = ~q.~n', [V, B]), format( S, '~a = ~q.~n', [V, B]),
output( Ns, S). fail.
bvs([V=B], S:B) :-
atom_atring(V,S),
!.
bvs([V=B|Ns], (S:B,N) ) :-
atom_string(V,S),
output( Ns, N).
bindvars( L, NL ) :-
rb_new(T),
foldl2( bind, L, NL, T, _ , 0, _),
term_variables(NL, Vs),
foldl( bind_new, Vs, 0, _).
bind(X=Y, X=X, T0, T, N, N) :-
var(Y),
!,
rb_update(T0, Y, X, T).
bind(X = G, X = G, T, T, N0, N0) :-
ground(G),
!.
bind(X = C, X = NC, T, NT, N0, NF) :-
C =.. [N|L],
foldl2( bind_new, L, NL, T, NT, N0, NF),
NC =.. [N|NL].
bind_new(Y, X, T, T, N, N) :-
var(Y),
rb_lookup(Y, X, T),
!.
bind_new(Y, X, T, TN, N, NF) :-
var(Y),
!,
rb_insert(Y, T, X, TN),
NF is N+1,
atomic_concat('_',N,X).
bind_new(Y, Y, T, T, N, N) :-
ground(Y),
!.
bind_new(Y, X, T, NT, N0, NF) :-
Y =.. [N|L],
foldl2(v, L, NL, T, NT, N0, NF),
X =.. [N|NL].

View File

@ -108,6 +108,7 @@ class YAPEngine;
//%typemap(in) YAPTerm { $1 = new YAPTerm(pythonToYAP($input)); PyErr_Clear(); } //%typemap(in) YAPTerm { $1 = new YAPTerm(pythonToYAP($input)); PyErr_Clear(); }
%typemap(in) YAP_Term { $1 = pythonToYAP($input); PyErr_Clear(); } %typemap(in) YAP_Term { $1 = pythonToYAP($input); PyErr_Clear(); }
%typemap(in) Term { $1 = pythonToYAP($input); PyErr_Clear(); } %typemap(in) Term { $1 = pythonToYAP($input); PyErr_Clear(); }
%typemap(in) YAPTerm { YAPTerm(($1 = pythonToYAP($input))); PyErr_Clear(); }
%typecheck(2) Int { $1 = PyLong_Check($input); } %typecheck(2) Int { $1 = PyLong_Check($input); }
%typecheck(3) double { $1 = PyFloat_Check($input); } %typecheck(3) double { $1 = PyFloat_Check($input); }

View File

@ -115,6 +115,7 @@
'$discontiguous'(D,M). '$discontiguous'(D,M).
/** @pred initialization /** @pred initialization
Execute the goals defined by initialization/1. Only the first answer is Execute the goals defined by initialization/1. Only the first answer is
considered. considered.

View File

@ -142,7 +142,7 @@ system_error(Type,Goal,Culprit) :-
functor(Error, Severity, _), functor(Error, Severity, _),
print_message(Severity, Error), !. print_message(Severity, Error), !.
%'$process_error'(error(Msg, Where), _) :- %'$process_error'(error(Msg, Where), _) :-
% print_message(error,error(Msg, [g|Where])), !. % Print_message(error,error(Msg, [g|Where])), !.
'$process_error'(Throw, _) :- '$process_error'(Throw, _) :-
print_message(error,error(unhandled_exception,Throw)). print_message(error,error(unhandled_exception,Throw)).

View File

@ -108,8 +108,9 @@ In YAP, the infoo field describes:
:- use_system_module( user, [message_hook/3]). :- use_system_module( user, [message_hook/3]).
%:- start_low_level_trace.
:- multifile prolog:message/3. :- multifile prolog:message/3.
%:- stop_low_level_trace.
:- multifile user:message_hook/3. :- multifile user:message_hook/3.
@ -910,7 +911,7 @@ If you need to report errors from your own predicates, we advise you to
stick to the existing error terms if you can; but should you need to stick to the existing error terms if you can; but should you need to
invent new ones, you can define corresponding error messages by invent new ones, you can define corresponding error messages by
asserting clauses for `prolog:message/2`. You will need to declare asserting clauses for `prolog:message/2`. You will need to declare
the predicate as multifile. the predicate as multifile/1.
Note: errors in the implementation of print_message/2 are very Note: errors in the implementation of print_message/2 are very
confusing to YAP (who will process the error?). So we write this small confusing to YAP (who will process the error?). So we write this small

View File

@ -60,14 +60,14 @@ a call to a predicate for which no clauses were defined will result in
the output of a message of the form: the output of a message of the form:
~~~~~{.prolog} ~~~~~{.prolog}
Undefined predicate: user:xyz(A1 ,A2) Undefined predicate:
~~~~~ ~~~~~
followed by the failure of that call. followed by the failure of that call.
*/ */
:- multifile user:unknown_predicate_handler/3. :- multifile user:unknown_predicate_handler/3.
undefined_query(G0, M0, Cut) :- undefined_query(G0, M0, Cut) :-
'$undefp_search'(M0:G0, M:G), recorded('$import','$import'(M,M0,G,G0,_,_),_),
'$call'(G, Cut, G, M). '$call'(G, Cut, G, M).
'$handle_error'(error,Goal,Mod) :- '$handle_error'(error,Goal,Mod) :-