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

View File

@ -2108,7 +2108,7 @@ static Int jump_env(USES_REGS1) {
Yap_find_prolog_culprit(PASS_REGS1);
// LOCAL_Error_TYPE = ERROR_EVENT;
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->classAsText = NameOfFunctor(FunctorOfTerm(t1));
} else if (IsAtomTerm(t)) {

View File

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

View File

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

View File

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

View File

@ -12,24 +12,27 @@
:- use_module( library(maplist) ).
:- use_module( library(rbtrees) ).
:- use_module( library(terms) ).
:- use_module( library(python) ).
%% @pred yap_query(sGoal, + VarList, +OutStream, - Dictionary)
%% @pred yap_query(sGoal, + VarList, +OutStream, - Dictionary)
%% @pred yap_query(0:Goal, + VarList, - Dictionary)
%%
%% dictionary, Examples
%%
%%
python_query( Engine, String, Dict ) :-
python_query( String, D ) :-
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)
%%
%% dictionary, Examples
%%
%%
prologun:yapi_query( VarNames, Dict ) :-
yapi_query( VarNames, Dict ) :-
show_answer(VarNames, Dict).
@ -42,34 +45,48 @@ python_query( Engine, String, Dict ) :-
%%
yap_query( Goal, VarNames, Stream, Dictionary) :-
(
call(Goal)
call(Goal)
*->
!,
show_answer(VarNames, Stream, Dictionary)
).
!,
show_answer(VarNames, Stream, Dictionary)
).
yapi_query( VarNames, Dictionary) :-
yap_query( VarNames, Dictionary) :-
yap_query( VarNames, user_output, Dictionary).
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),
writeln(ivs-IVs),
term_variables(Goal, IVs),
foldl(enumerate, IVs, 0, _Ns),
copy_term(QVs0, QVs1),
rb_new(RB),
foldl2(bind_qv, QVs, QVs1, [], LP, {}-RB, Dict-_),
!,
out(QVs, Stream, D).
Dictt := {D}.
term_variables(QVs, IVs),
term_variables(QVs1, IVs1),
foldl( enumerate, IVs, IVs1, 1, _ ),
out(LP, Stream ).
show_answer(_, _, {}) :-
format(' yes.~n', [] ).
format(' yes.~n', [] ).
bind_qv(V=V0, Vs, Vs) :- var(V0), !, V0='$VAR'(V).
bind_qv(V=V, Vs, Vs) :- !.
bind_qv(V=S, Vs, [V=S|Vs]).
bind_qv(V=V0, V1 = V01, Vs, Vs, Vs1-RB, Vs1-RB) :-
var(V0),
!,
'$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),
atom_codes(A,[0'_|Chars]),
I1 is I + 1.
@ -84,65 +101,18 @@ enum(I, [C|Cs]) :-
C is "A" +K,
enum(J, Cs).
out(Bs, S, _Dict) :-
out(Bs, S) :-
output(Bs, S),
fail.
out(Bs, _S, Dict) :-
bvs(Bs, Dict).
v2py(v(I0) = _V, I0, I) :-
!,
I is I0+1.
v2py(v(I0) = v(I0), I0, I) :-
I is I0+1.
!.
out([_|Bs], S) :-
out(Bs, S).
output([V=B], S) :-
!,
format(S, '~a = ~q~n', [V, B]).
output([V=B|Ns], S) :-
format( S, '~a = ~q.~n', [V, B]),
output( Ns, S).
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, _).
output([V=B|_Ns], S) :-
format( S, '~a = ~q.~n', [V, B]),
fail.
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) YAP_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(3) double { $1 = PyFloat_Check($input); }

View File

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

View File

@ -142,7 +142,7 @@ system_error(Type,Goal,Culprit) :-
functor(Error, Severity, _),
print_message(Severity, Error), !.
%'$process_error'(error(Msg, Where), _) :-
% print_message(error,error(Msg, [g|Where])), !.
% Print_message(error,error(Msg, [g|Where])), !.
'$process_error'(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]).
%:- start_low_level_trace.
:- multifile prolog:message/3.
%:- stop_low_level_trace.
:- 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
invent new ones, you can define corresponding error messages by
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
confusing to YAP (who will process the error?). So we write this small

View File

@ -60,15 +60,15 @@ 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)
Undefined predicate:
~~~~~
followed by the failure of that call.
*/
:- multifile user:unknown_predicate_handler/3.
undefined_query(G0, M0, Cut) :-
'$undefp_search'(M0:G0, M:G),
'$call'(G, Cut, G, M).
recorded('$import','$import'(M,M0,G,G0,_,_),_),
'$call'(G, Cut, G, M).
'$handle_error'(error,Goal,Mod) :-
functor(Goal,Name,Arity),