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/C/exec.c

2453 lines
67 KiB
C
Raw Normal View History

2018-07-18 17:36:01 +01:00
/*************************************************************************
* *
* YAP Prolog *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* *
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
* *
**************************************************************************
* *
2015-10-20 08:10:39 +01:00
* File: exec.c *
* Last rev: 8/2/88 *
2015-10-20 08:10:39 +01:00
* mods: *
* comments: Execute Prolog code *
* *
*************************************************************************/
#ifdef SCCS
2015-10-20 08:10:39 +01:00
static char SccsId[] = "@(#)cdmgr.c 1.1 05/02/98";
#endif
2018-05-01 23:25:58 +01:00
/**
* @file exec.c
* @author VITOR SANTOS COSTA <vsc@VITORs-MBP-2.lan>
* @date Mon Apr 30 13:48:35 2018
2018-06-14 11:27:43 +01:00
*
2018-05-01 23:25:58 +01:00
* @brief meta-call
*
* @namespace prolog
*
2018-06-14 11:27:43 +01:00
*
*
2018-05-01 23:25:58 +01:00
*/
#include "absmi.h"
#include "attvar.h"
#include "cut_c.h"
2016-03-29 01:55:12 +01:00
#include "yapio.h"
2016-03-29 01:55:12 +01:00
static bool CallPredicate(PredEntry *, choiceptr, yamop *CACHE_TYPE);
// must hold thread worker comm lock at call.
2016-03-29 01:55:12 +01:00
static bool EnterCreepMode(Term, Term CACHE_TYPE);
2015-10-20 08:10:39 +01:00
static Int current_choice_point(USES_REGS1);
static Int execute(USES_REGS1);
static Int execute0(USES_REGS1);
2015-10-20 08:10:39 +01:00
static Term cp_as_integer(choiceptr cp USES_REGS) {
return (MkIntegerTerm(LCL0 - (CELL *)cp));
}
2015-10-20 08:10:39 +01:00
static choiceptr cp_from_integer(Term cpt USES_REGS) {
return (choiceptr)(LCL0 - IntegerOfTerm(cpt));
}
2016-03-29 01:55:12 +01:00
/**
* Represents a choice-point as an offset to the top of local stack. This should
* *be stable acroos gc or stack shifts.
* @param cp pointer to choice-point
* @return Term with offset
*/
2015-10-20 08:10:39 +01:00
Term Yap_cp_as_integer(choiceptr cp) {
CACHE_REGS
2018-06-14 11:27:43 +01:00
return cp_as_integer(cp PASS_REGS);
}
2016-03-29 01:55:12 +01:00
/**
* Sets up the engine to run a different predicate.
* @method CallPredicate
* @param pen the new code
* @param cut_pt cut boundary
* @param USES_REGS thread support
* @return success
*/
static inline bool CallPredicate(PredEntry *pen, choiceptr cut_pt,
yamop *code USES_REGS) {
#ifdef LOW_LEVEL_TRACER
2015-10-20 08:10:39 +01:00
if (Yap_do_low_level_trace)
low_level_trace(enter_pred, pen, XREGS + 1);
#endif /* LOW_LEVEL_TRACE */
#ifdef DEPTH_LIMIT
2015-10-20 08:10:39 +01:00
if (DEPTH <= MkIntTerm(1)) { /* I assume Module==0 is prolog */
if (pen->ModuleOfPred) {
if (DEPTH == MkIntTerm(0)) {
UNLOCK(pen->PELock);
2016-01-03 01:31:21 +00:00
return false;
2015-10-20 08:10:39 +01:00
} else
DEPTH = RESET_DEPTH();
}
2015-10-20 08:10:39 +01:00
} else if (pen->ModuleOfPred)
DEPTH -= MkIntConstant(2);
#endif /* DEPTH_LIMIT */
if (P->opc != EXECUTE_CPRED_OP_CODE) {
// YENV[E_CP] = CP;
// YENV[E_E] = ENV;
//#ifdef DEPTH_LIMIT
// YENV[E_DEPTH] = DEPTH;
//#endif
// ENV = YENV;
ENV = YENV;
YENV = ASP;
CP = P;
}
/* make sure we have access to the user given cut */
YENV[E_CB] = (CELL)cut_pt;
P = code;
2016-01-03 01:31:21 +00:00
return true;
}
2016-03-29 01:55:12 +01:00
/**
* calls a meta-predicate or anything weird
* @method CallMetaCall
* @param t the called goal
* @param USES_REGS MT
* @return did we fiid it?
*/
inline static bool CallMetaCall(Term t, Term mod USES_REGS) {
2018-11-03 10:49:35 +00:00
// we have a creep requesr waiting
2015-07-23 01:05:06 +01:00
2019-03-03 02:01:39 +00:00
if (IsVarTerm(t))
Yap_ThrowError(INSTANTIATION_ERROR, t, "meta-call");
if (IsIntTerm(t) || (IsApplTerm(t) && IsExtensionFunctor(FunctorOfTerm(t))))
Yap_ThrowError(TYPE_ERROR_CALLABLE, Yap_TermToIndicator(t, mod), "meta-call");
ARG1 = t;
2015-10-20 08:10:39 +01:00
ARG2 = cp_as_integer(B PASS_REGS); /* p_current_choice_point */
ARG3 = t;
if (mod) {
ARG4 = mod;
} else {
ARG4 = TermProlog;
2019-03-03 02:01:39 +00:00
}
2015-10-20 08:10:39 +01:00
if (Yap_GetGlobal(AtomDebugMeta) == TermOn) {
return CallPredicate(PredTraceMetaCall, B,
PredTraceMetaCall->CodeOfPred PASS_REGS);
} else {
return CallPredicate(PredMetaCall, B, PredMetaCall->CodeOfPred PASS_REGS);
}
}
2016-03-29 01:55:12 +01:00
/**
* Transfer control to a meta-call in ARG1, cut up to B.
2018-06-14 11:27:43 +01:00
*
2018-05-01 23:25:58 +01:00
* @param g goal
2019-02-17 07:58:06 +00:00
* @param mod curre1nt module
2016-03-29 01:55:12 +01:00
* @return su
*/
2017-06-05 13:06:12 +01:00
Term Yap_ExecuteCallMetaCall(Term g, Term mod) {
2015-10-20 08:10:39 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
Term ts[4];
2019-03-03 02:01:39 +00:00
if (IsVarTerm(g))
Yap_ThrowError(INSTANTIATION_ERROR, g, "meta-call");
if (IsIntTerm(g) || (IsApplTerm(g) && IsExtensionFunctor(FunctorOfTerm(g))))
Yap_ThrowError(TYPE_ERROR_CALLABLE, Yap_TermToIndicator(g, mod), "meta-call");
2017-06-05 13:06:12 +01:00
ts[0] = g;
2015-10-20 08:10:39 +01:00
ts[1] = cp_as_integer(B PASS_REGS); /* p_current_choice_point */
2017-06-05 13:06:12 +01:00
ts[2] = g;
2015-10-20 08:10:39 +01:00
ts[3] = mod;
if (Yap_GetGlobal(AtomDebugMeta) == TermOn) {
return Yap_MkApplTerm(PredTraceMetaCall->FunctorOfPred, 3, ts);
}
return Yap_MkApplTerm(PredMetaCall->FunctorOfPred, 4, ts);
}
2019-02-28 21:57:48 +00:00
PredEntry *Yap_get_pred(Term t, Term tmod, const char *pname) {
Term t0 = t;
restart:
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t0, pname);
return NULL;
} else if (IsAtomTerm(t)) {
PredEntry *ap = RepPredProp(Yap_GetPredPropByAtom(AtomOfTerm(t), tmod));
return ap;
} else if (IsIntegerTerm(t) && tmod == IDB_MODULE) {
return Yap_FindLUIntKey(IntegerOfTerm(t));
} else if (IsPairTerm(t)) {
t = Yap_MkApplTerm(FunctorCsult, 1, &t);
goto restart;
} else if (IsApplTerm(t)) {
Functor fun = FunctorOfTerm(t);
if (IsExtensionFunctor(fun)) {
Yap_Error(TYPE_ERROR_CALLABLE, Yap_TermToIndicator(t, tmod), pname);
return NULL;
}
if (fun == FunctorModule) {
Term tmod = ArgOfTerm(1, t);
if (IsVarTerm(tmod)) {
Yap_Error(INSTANTIATION_ERROR, t0, pname);
return NULL;
}
if (!IsAtomTerm(tmod)) {
Yap_Error(TYPE_ERROR_ATOM, t0, pname);
return NULL;
}
t = ArgOfTerm(2, t);
goto restart;
}
PredEntry *ap = RepPredProp(Yap_GetPredPropByFunc(fun, tmod));
return ap;
} else {
Yap_Error(TYPE_ERROR_CALLABLE, t0, pname);
}
return NULL;
}
2019-02-27 15:54:20 +00:00
Term Yap_TermToIndicator(Term t, Term mod) {
2015-10-20 08:10:39 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
// generate predicate indicator in this case
Term ti[2];
t = Yap_YapStripModule(t, &mod);
2015-10-20 08:10:39 +01:00
if (IsApplTerm(t) && !IsExtensionFunctor(FunctorOfTerm(t))) {
ti[0] = MkAtomTerm(NameOfFunctor(FunctorOfTerm(t)));
ti[1] = MkIntegerTerm(ArityOfFunctor(FunctorOfTerm(t)));
} else if (IsPairTerm(t)) {
ti[0] = MkAtomTerm(AtomDot);
ti[1] = MkIntTerm(2);
} else {
ti[0] = t;
ti[1] = MkIntTerm(0);
}
t = Yap_MkApplTerm(FunctorSlash, 2, ti);
2019-03-03 02:01:39 +00:00
if (mod != PROLOG_MODULE && mod != USER_MODULE && mod != TermProlog) {
2015-10-20 08:10:39 +01:00
ti[0] = mod;
ti[1] = t;
return Yap_MkApplTerm(FunctorModule, 2, ti);
}
return t;
}
2019-02-27 15:54:20 +00:00
Term Yap_PredicateToIndicator(PredEntry *pe) {
CACHE_REGS
// generate predicate indicator in this case
Term ti[2];
if (pe->ArityOfPE) {
ti[0] = MkAtomTerm(NameOfFunctor(pe->FunctorOfPred));
ti[1] = MkIntegerTerm(ArityOfFunctor(pe->FunctorOfPred));
} else {
2019-02-28 21:57:48 +00:00
ti[0] = MkAtomTerm((Atom)(pe->FunctorOfPred));
2019-02-27 15:54:20 +00:00
ti[1] = MkIntTerm(0);
}
2019-02-28 21:57:48 +00:00
Term t = Yap_MkApplTerm(FunctorSlash, 2, ti);
Term mod = pe->ModuleOfPred;
2019-03-03 02:01:39 +00:00
if (mod != PROLOG_MODULE && mod != USER_MODULE && mod != TermProlog) {
2019-02-27 15:54:20 +00:00
ti[0] = mod;
ti[1] = t;
return Yap_MkApplTerm(FunctorModule, 2, ti);
}
return t;
}
2016-03-29 01:55:12 +01:00
static bool CallError(yap_error_number err, Term t, Term mod USES_REGS) {
2015-10-20 08:10:39 +01:00
if (isoLanguageFlag()) {
return (CallMetaCall(t, mod PASS_REGS));
} else {
if (err == TYPE_ERROR_CALLABLE) {
t = Yap_YapStripModule(t, &mod);
2015-10-20 08:10:39 +01:00
}
Yap_Error(err, t, "call/1");
2016-03-29 01:55:12 +01:00
return false;
2015-10-20 08:10:39 +01:00
}
}
2016-03-29 01:55:12 +01:00
/** @pred current_choice_point( -CP )
2015-07-06 11:57:47 +01:00
*
2019-01-31 11:54:17 +00:00
* unify the logic variable _CP_ with a number that identifies the
* last alternative taken, or current choice-point. This number is
* only valid as long as we do not backtrack by or cut _CP_, and is
* safe in the presence of stack shifting and/or garbage collection.
2015-07-06 11:57:47 +01:00
*/
2015-10-20 08:10:39 +01:00
static Int current_choice_point(USES_REGS1) {
Term t = Deref(ARG1);
Term td;
#if SHADOW_HB
2015-10-20 08:10:39 +01:00
register CELL *HBREG = HB;
#endif
2015-10-20 08:10:39 +01:00
if (!IsVarTerm(t))
return (FALSE);
td = cp_as_integer(B PASS_REGS);
YapBind((CELL *)t, td);
return TRUE;
}
2019-01-31 11:54:17 +00:00
/** @pred parent_choice_point( +CP, -PCP )
*
* given that _CP_ identifies an
* alternative taken, or choice-point, _PCP_ identifies its parent.
*
* The call will fail if _CP_ is topmost in the search tree.
*/
2019-02-17 23:19:26 +00:00
static Int parent_choice_point(USES_REGS1) {
2019-01-31 11:54:17 +00:00
Term t = Deref(ARG1);
Term td;
#if SHADOW_HB
register CELL *HBREG = HB;
#endif
2019-02-17 07:58:06 +00:00
if (!IsVarTerm(t)) {
Yap_ThrowError(INSTANTIATION_ERROR, t, "child choicr-point missing");
}
2019-01-31 11:54:17 +00:00
choiceptr cp = cp_from_integer(t);
if (cp == NULL || cp->cp_b == NULL)
return false;
td = cp_as_integer(cp->cp_b PASS_REGS);
YapBind((CELL *)t, td);
return TRUE;
}
2019-02-17 07:58:06 +00:00
/** @pred parent_choice_point( -PB )
*
* PB is a number identifying the parent of the current choice-point.
* It storing the offset of the current ch
*
* The call will fail if _CP_ is topmost in the search tree.
*/
2019-02-17 23:19:26 +00:00
static Int parent_choice_point1(USES_REGS1) {
2019-02-17 07:58:06 +00:00
Term t = Deref(ARG1);
Term td;
#if SHADOW_HB
register CELL *HBREG = HB;
#endif
if (B == NULL || B->cp_b == NULL)
return false;
td = cp_as_integer(B->cp_b PASS_REGS);
YapBind((CELL *)t, td);
return true;
}
2015-10-20 08:10:39 +01:00
static Int save_env_b(USES_REGS1) {
Term t = Deref(ARG1);
Term td;
#if SHADOW_HB
2015-10-20 08:10:39 +01:00
register CELL *HBREG = HB;
#endif
2015-10-20 08:10:39 +01:00
if (!IsVarTerm(t))
return (FALSE);
td = cp_as_integer((choiceptr)YENV[E_CB] PASS_REGS);
YapBind((CELL *)t, td);
2016-03-29 01:55:12 +01:00
return true;
2015-10-20 08:10:39 +01:00
}
2016-09-21 04:48:28 +01:00
/** Look for a predicate with same functor as t,
create a new one of it cannot find it.
*/
2016-09-21 04:48:28 +01:00
static PredEntry *new_pred(Term t, Term tmod, char *pname) {
Term t0 = t;
2018-06-14 11:27:43 +01:00
restart:
2016-09-21 04:48:28 +01:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t0, pname);
return NULL;
} else if (IsAtomTerm(t)) {
return RepPredProp(PredPropByAtom(AtomOfTerm(t), tmod));
} else if (IsIntegerTerm(t) && tmod == IDB_MODULE) {
return Yap_FindLUIntKey(IntegerOfTerm(t));
} else if (IsApplTerm(t)) {
2019-02-28 21:57:48 +00:00
Functor fun = FunctorOfTerm(t);
2016-09-21 04:48:28 +01:00
if (IsExtensionFunctor(fun)) {
2019-02-27 15:54:20 +00:00
Yap_Error(TYPE_ERROR_CALLABLE, Yap_TermToIndicator(t, tmod), pname);
2016-09-21 04:48:28 +01:00
return NULL;
}
if (fun == FunctorModule) {
Term tmod = ArgOfTerm(1, t);
if (IsVarTerm(tmod)) {
Yap_Error(INSTANTIATION_ERROR, t0, pname);
return NULL;
}
if (!IsAtomTerm(tmod)) {
Yap_Error(TYPE_ERROR_ATOM, t0, pname);
return NULL;
}
t = ArgOfTerm(2, t);
goto restart;
}
return RepPredProp(PredPropByFunc(fun, tmod));
} else
return NULL;
}
static bool CommaCall(Term t, Term mod) {
PredEntry *pen;
arity_t i;
if (IsVarTerm(t) || (pen = new_pred(t, mod, "_,_")))
return false;
for (i = 0; i < pen->ArityOfPE; i++) {
YENV[-EnvSizeInCells - i] = XREGS[i + 1];
}
YENV[E_CB] = (CELL)B;
YENV[E_CP] = (CELL)P;
YENV[E_E] = (CELL)ENV;
YENV[E_DEPTH] = DEPTH;
ASP = YENV - (EnvSizeInCells + i);
ENV = YENV;
YENV = ASP;
if ((P = pen->MetaEntryOfPred) == NULL) {
P = Yap_InitCommaContinuation(pen);
}
return P == NULL;
}
2016-03-29 01:55:12 +01:00
inline static bool do_execute(Term t, Term mod USES_REGS) {
2018-02-01 01:44:34 +00:00
Term t0 = t, mod0 = mod;
2016-05-12 11:49:04 +01:00
t = Yap_YapStripModule(t, &mod);
/* first do predicate expansion, even before you process signals.
This way you don't get to spy goal_expansion(). */
if (Yap_has_a_signal() && !LOCAL_InterruptsDisabled &&
2016-01-03 01:31:21 +00:00
!(LOCAL_PrologMode & (AbortMode | InterruptMode | SystemMode))) {
2015-10-20 08:10:39 +01:00
return EnterCreepMode(t, mod PASS_REGS);
}
2016-05-12 11:49:04 +01:00
if (IsVarTerm(t) || IsVarTerm(mod)) {
2018-02-01 01:44:34 +00:00
return CallError(INSTANTIATION_ERROR, t0, mod0 PASS_REGS);
2016-09-21 04:48:28 +01:00
}
if (IsApplTerm(t)) {
2015-10-20 08:10:39 +01:00
register Functor f = FunctorOfTerm(t);
register CELL *pt;
PredEntry *pen;
unsigned int i, arity;
2015-07-23 01:05:06 +01:00
2015-10-20 08:10:39 +01:00
f = FunctorOfTerm(t);
2016-09-21 04:48:28 +01:00
if (f == FunctorComma && false) {
Term t2 = ArgOfTerm(2, t);
if (IsVarTerm(t2))
2018-02-01 01:44:34 +00:00
return CallMetaCall(t0, mod0 PASS_REGS);
2016-11-08 07:37:36 +00:00
if (1 || !CommaCall(t2, mod))
2018-02-01 01:44:34 +00:00
return CallMetaCall(t0, mod0 PASS_REGS);
2016-09-21 04:48:28 +01:00
Term t1 = ArgOfTerm(1, t);
t = t1;
pen = new_pred(t, mod, "_,_");
if (pen == NULL || (arity = pen->ArityOfPE) == 0) {
return do_execute(t, mod);
}
} else if (IsExtensionFunctor(f)) {
2018-02-01 01:44:34 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod0 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
arity = ArityOfFunctor(f);
if (arity > MaxTemps) {
2018-02-01 01:44:34 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod0 PASS_REGS);
}
pen = RepPredProp(PredPropByFunc(f, mod));
/* You thought we would be over by now */
/* but no meta calls require special preprocessing */
/* now let us do what we wanted to do from the beginning !! */
/* I cannot use the standard macro here because
2016-03-29 01:55:12 +01:00
otherwise I would dereference the argument and
might skip a svar */
2018-10-05 10:27:03 +01:00
if (pen->PredFlags & (MetaPredFlag | UndefPredFlag | SpiedPredFlag)) {
2018-02-01 01:44:34 +00:00
return CallMetaCall(t0, mod0 PASS_REGS);
2016-11-24 04:35:39 +00:00
}
2015-10-20 08:10:39 +01:00
pt = RepAppl(t) + 1;
for (i = 1; i <= arity; i++) {
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
2015-10-20 08:10:39 +01:00
Term d0 = *pt++;
if (d0 == 0)
2016-09-21 04:48:28 +01:00
XREGS[i] = (CELL)(pt - 1);
2015-10-20 08:10:39 +01:00
else
XREGS[i] = d0;
#else
2015-10-20 08:10:39 +01:00
XREGS[i] = *pt++;
#endif
}
2016-09-21 04:48:28 +01:00
return CallPredicate(pen, B, pen->CodeOfPred PASS_REGS);
}
if (IsAtomTerm(t)) {
2015-10-20 08:10:39 +01:00
PredEntry *pe;
Atom a = AtomOfTerm(t);
if (a == AtomTrue || a == AtomOtherwise || a == AtomCut)
2016-03-29 01:55:12 +01:00
return true;
2015-10-20 08:10:39 +01:00
else if (a == AtomFail ||
(a == AtomFalse &&
!RepPredProp(PredPropByAtom(a, mod))->ModuleOfPred))
2016-03-29 01:55:12 +01:00
return false;
2015-10-20 08:10:39 +01:00
/* call may not define new system predicates!! */
pe = RepPredProp(PredPropByAtom(a, mod));
return (CallPredicate(pe, B, pe->CodeOfPred PASS_REGS));
}
2018-02-01 01:44:34 +00:00
return CallMetaCall(t0, mod0 PASS_REGS);
2015-10-20 08:10:39 +01:00
}
static Term copy_execn_to_heap(Functor f, CELL *pt, unsigned int n,
unsigned int arity, Term mod USES_REGS) {
CELL *h0 = HR;
Term tf;
unsigned int i;
if (arity == 2 && NameOfFunctor(f) == AtomDot) {
for (i = 0; i < arity - n; i++) {
*HR++ = pt[i];
}
for (i = 0; i < n; i++) {
*HR++ = h0[(int)(i - n)];
}
tf = AbsPair(h0);
} else {
*HR++ = (CELL)f;
for (i = 0; i < arity - n; i++) {
*HR++ = pt[i];
}
for (i = 0; i < n; i++) {
*HR++ = h0[(int)(i - n)];
}
tf = AbsAppl(h0);
}
if (mod != CurrentModule) {
CELL *h0 = HR;
*HR++ = (CELL)FunctorModule;
*HR++ = mod;
*HR++ = tf;
tf = AbsAppl(h0);
}
return tf;
}
2016-03-29 01:55:12 +01:00
inline static bool do_execute_n(Term t, Term mod, unsigned int n USES_REGS) {
2015-10-20 08:10:39 +01:00
Functor f;
Atom Name;
register CELL *pt;
PredEntry *pen;
unsigned int i, arity;
int j = -n;
2018-02-01 01:44:34 +00:00
Term t0 = t, mod0 = mod;
2015-10-20 08:10:39 +01:00
2018-06-14 11:27:43 +01:00
restart_exec:
2015-10-20 08:10:39 +01:00
if (IsVarTerm(t)) {
2018-02-01 01:44:34 +00:00
return CallError(INSTANTIATION_ERROR, t0, mod0 PASS_REGS);
2015-10-20 08:10:39 +01:00
} else if (IsAtomTerm(t)) {
arity = n;
Name = AtomOfTerm(t);
pt = NULL;
} else if (IsIntTerm(t)) {
2018-02-01 01:44:34 +00:00
return CallError(TYPE_ERROR_CALLABLE, t, mod0 PASS_REGS);
2015-10-20 08:10:39 +01:00
} else if (IsPairTerm(t)) {
arity = n + 2;
pt = RepPair(t);
Name = AtomOfTerm(TermNil);
} else /* if (IsApplTerm(t)) */ {
f = FunctorOfTerm(t);
while (f == FunctorModule) {
Term tmod = ArgOfTerm(1, t);
if (!IsVarTerm(tmod) && IsAtomTerm(tmod)) {
mod = tmod;
t = ArgOfTerm(2, t);
goto restart_exec;
} else {
if (IsVarTerm(tmod)) {
2018-02-01 01:44:34 +00:00
return CallError(INSTANTIATION_ERROR, t0, mod0 PASS_REGS);
2015-10-20 08:10:39 +01:00
} else {
2018-02-01 01:44:34 +00:00
return CallError(TYPE_ERROR_ATOM, t0, mod0 PASS_REGS);
2015-10-20 08:10:39 +01:00
}
}
}
arity = ArityOfFunctor(f) + n;
Name = NameOfFunctor(f);
pt = RepAppl(t) + 1;
}
f = Yap_MkFunctor(Name, arity);
if (IsExtensionFunctor(f)) {
2018-02-01 01:44:34 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod0 PASS_REGS);
2015-10-20 08:10:39 +01:00
}
if (Yap_has_a_signal() && !LOCAL_InterruptsDisabled) {
2015-10-20 08:10:39 +01:00
return EnterCreepMode(
2018-06-14 11:27:43 +01:00
copy_execn_to_heap(f, pt, n, arity, CurrentModule PASS_REGS),
mod PASS_REGS);
2015-10-20 08:10:39 +01:00
}
if (arity > MaxTemps) {
2018-02-01 01:44:34 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod0 PASS_REGS);
2015-10-20 08:10:39 +01:00
}
pen = RepPredProp(PredPropByFunc(f, mod));
/* You thought we would be over by now */
/* but no meta calls require special preprocessing */
2018-02-08 09:56:01 +00:00
// if (pen->PredFlags & (MetaPredFlag | UndefPredFlag)) {
2018-04-07 19:45:18 +01:00
// Term t = copy_execn_to_heap(f, pt, n, arity, mod PASS_REGS);
2018-06-14 11:27:43 +01:00
// return (CallMetaCall(t0, mod0 PASS_REGS));
2018-02-08 09:56:01 +00:00
//}
2015-10-20 08:10:39 +01:00
/* now let us do what we wanted to do from the beginning !! */
/* I cannot use the standard macro here because
2016-03-29 01:55:12 +01:00
otherwise I would dereference the argument and
might skip a svar */
2015-10-20 08:10:39 +01:00
for (i = 1; i <= arity - n; i++) {
#if YAPOR_SBA
Term d0 = *pt++;
if (d0 == 0)
XREGS[i] = (CELL)(pt - 1);
else
XREGS[i] = d0;
#else
XREGS[i] = *pt++;
#endif
}
for (i = arity - n + 1; i <= arity; i++, j++) {
XREGS[i] = HR[j];
}
return CallPredicate(pen, B, pen->CodeOfPred PASS_REGS);
}
// enter locked
2016-03-29 01:55:12 +01:00
static bool EnterCreepMode(Term t, Term mod USES_REGS) {
2015-10-20 08:10:39 +01:00
PredEntry *PredCreep;
if (Yap_get_signal(YAP_CDOVF_SIGNAL)) {
ARG1 = t;
if (!Yap_locked_growheap(FALSE, 0, NULL)) {
Yap_Error(RESOURCE_ERROR_HEAP, TermNil,
"YAP failed to grow heap at meta-call");
}
if (!Yap_has_a_signal()) {
return do_execute(ARG1, mod PASS_REGS);
}
}
PredCreep = RepPredProp(PredPropByFunc(FunctorCreep, 1));
PP = PredCreep;
if (!IsVarTerm(t) && IsApplTerm(t) && FunctorOfTerm(t) == FunctorModule) {
ARG1 = MkPairTerm(ArgOfTerm(1, t), ArgOfTerm(2, t));
} else {
if (mod) {
ARG1 = MkPairTerm(mod, t);
2013-02-08 16:36:45 +00:00
} else {
2015-10-20 08:10:39 +01:00
ARG1 = MkPairTerm(TermProlog, t);
2013-02-08 16:36:45 +00:00
}
2015-10-20 08:10:39 +01:00
}
CalculateStackGap(PASS_REGS1);
P_before_spy = P;
return CallPredicate(PredCreep, B, PredCreep->CodeOfPred PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
2015-07-06 11:57:47 +01:00
return do_execute(t, CurrentModule PASS_REGS);
}
2016-03-29 01:55:12 +01:00
bool Yap_Execute(Term t USES_REGS) { /* '$execute'(Goal) */
2015-07-06 11:57:47 +01:00
return do_execute(t, CurrentModule PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static void heap_store(Term t USES_REGS) {
if (IsVarTerm(t)) {
if (VarOfTerm(t) < HR) {
*HR++ = t;
} else {
2015-10-20 08:10:39 +01:00
RESET_VARIABLE(HR);
Bind_Local(VarOfTerm(t), (CELL)HR);
HR++;
}
} else {
*HR++ = t;
}
}
static Int execute2(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
return do_execute_n(t, CurrentModule, 1 PASS_REGS);
}
static Int execute3(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
return do_execute_n(t, CurrentModule, 2 PASS_REGS);
}
static Int execute4(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
heap_store(Deref(ARG4) PASS_REGS);
return do_execute_n(t, CurrentModule, 3 PASS_REGS);
}
static Int execute5(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
heap_store(Deref(ARG4) PASS_REGS);
heap_store(Deref(ARG5) PASS_REGS);
return do_execute_n(t, CurrentModule, 4 PASS_REGS);
}
static Int execute6(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
heap_store(Deref(ARG4) PASS_REGS);
heap_store(Deref(ARG5) PASS_REGS);
heap_store(Deref(ARG6) PASS_REGS);
return do_execute_n(t, CurrentModule, 5 PASS_REGS);
}
static Int execute7(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
heap_store(Deref(ARG4) PASS_REGS);
heap_store(Deref(ARG5) PASS_REGS);
heap_store(Deref(ARG6) PASS_REGS);
heap_store(Deref(ARG7) PASS_REGS);
return do_execute_n(t, CurrentModule, 6 PASS_REGS);
}
static Int execute8(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
heap_store(Deref(ARG4) PASS_REGS);
heap_store(Deref(ARG5) PASS_REGS);
heap_store(Deref(ARG6) PASS_REGS);
heap_store(Deref(ARG7) PASS_REGS);
heap_store(Deref(ARG8) PASS_REGS);
return do_execute_n(t, CurrentModule, 7 PASS_REGS);
}
static Int execute9(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
heap_store(Deref(ARG4) PASS_REGS);
heap_store(Deref(ARG5) PASS_REGS);
heap_store(Deref(ARG6) PASS_REGS);
heap_store(Deref(ARG7) PASS_REGS);
heap_store(Deref(ARG8) PASS_REGS);
heap_store(Deref(ARG9) PASS_REGS);
return do_execute_n(t, CurrentModule, 8 PASS_REGS);
}
static Int execute10(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
heap_store(Deref(ARG4) PASS_REGS);
heap_store(Deref(ARG5) PASS_REGS);
heap_store(Deref(ARG6) PASS_REGS);
heap_store(Deref(ARG7) PASS_REGS);
heap_store(Deref(ARG8) PASS_REGS);
heap_store(Deref(ARG9) PASS_REGS);
heap_store(Deref(ARG10) PASS_REGS);
return (do_execute_n(t, CurrentModule, 9 PASS_REGS));
}
static Int execute11(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
heap_store(Deref(ARG4) PASS_REGS);
heap_store(Deref(ARG5) PASS_REGS);
heap_store(Deref(ARG6) PASS_REGS);
heap_store(Deref(ARG7) PASS_REGS);
heap_store(Deref(ARG8) PASS_REGS);
heap_store(Deref(ARG9) PASS_REGS);
heap_store(Deref(ARG10) PASS_REGS);
heap_store(Deref(ARG11) PASS_REGS);
return (do_execute_n(t, CurrentModule, 10 PASS_REGS));
}
static Int execute12(USES_REGS1) { /* '$execute'(Goal) */
Term t = Deref(ARG1);
2016-01-03 01:31:21 +00:00
2015-10-20 08:10:39 +01:00
heap_store(Deref(ARG2) PASS_REGS);
heap_store(Deref(ARG3) PASS_REGS);
heap_store(Deref(ARG4) PASS_REGS);
heap_store(Deref(ARG5) PASS_REGS);
heap_store(Deref(ARG6) PASS_REGS);
heap_store(Deref(ARG7) PASS_REGS);
heap_store(Deref(ARG8) PASS_REGS);
heap_store(Deref(ARG9) PASS_REGS);
heap_store(Deref(ARG10) PASS_REGS);
heap_store(Deref(ARG11) PASS_REGS);
heap_store(Deref(ARG12) PASS_REGS);
return (do_execute_n(t, CurrentModule, 11 PASS_REGS));
}
static Int execute_clause(USES_REGS1) { /* '$execute_clause'(Goal) */
Term t = Deref(ARG1);
Term mod = Deref(ARG2);
choiceptr cut_cp = cp_from_integer(Deref(ARG4) PASS_REGS);
unsigned int arity;
Prop pe;
yamop *code;
Term clt = Deref(ARG3);
2015-07-23 01:05:06 +01:00
2018-06-14 11:27:43 +01:00
restart_exec:
2015-10-20 08:10:39 +01:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, ARG3, "call/1");
return FALSE;
} else if (IsAtomTerm(t)) {
Atom a = AtomOfTerm(t);
pe = PredPropByAtom(a, mod);
} else if (IsApplTerm(t)) {
register Functor f = FunctorOfTerm(t);
register unsigned int i;
register CELL *pt;
if (IsExtensionFunctor(f))
return (FALSE);
if (f == FunctorModule) {
Term tmod = ArgOfTerm(1, t);
if (!IsVarTerm(tmod) && IsAtomTerm(tmod)) {
mod = tmod;
t = ArgOfTerm(2, t);
goto restart_exec;
}
}
pe = PredPropByFunc(f, mod);
arity = ArityOfFunctor(f);
if (arity > MaxTemps) {
return CallError(TYPE_ERROR_CALLABLE, t, mod PASS_REGS);
}
/* I cannot use the standard macro here because
2016-03-29 01:55:12 +01:00
otherwise I would dereference the argument and
might skip a svar */
2015-10-20 08:10:39 +01:00
pt = RepAppl(t) + 1;
for (i = 1; i <= arity; ++i) {
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
2015-10-20 08:10:39 +01:00
Term d0 = *pt++;
if (d0 == 0)
XREGS[i] = (CELL)(pt - 1);
else
XREGS[i] = d0;
#else
2015-10-20 08:10:39 +01:00
XREGS[i] = *pt++;
#endif
}
2015-10-20 08:10:39 +01:00
} else {
return CallError(TYPE_ERROR_CALLABLE, t, mod PASS_REGS);
}
/* N = arity; */
/* call may not define new system predicates!! */
if (RepPredProp(pe)->PredFlags & MegaClausePredFlag) {
code = Yap_MegaClauseFromTerm(clt);
} else {
code = Yap_ClauseFromTerm(clt)->ClCode;
}
if (Yap_get_signal(YAP_CREEP_SIGNAL)) {
Yap_signal(YAP_CREEP_SIGNAL);
}
return CallPredicate(RepPredProp(pe), cut_cp, code PASS_REGS);
}
static Int execute_in_mod(USES_REGS1) { /* '$execute'(Goal) */
2016-01-03 01:31:21 +00:00
return do_execute(Deref(ARG1), Deref(ARG2) PASS_REGS);
2015-10-20 08:10:39 +01:00
}
2016-03-29 01:55:12 +01:00
/**
* remove choice points created since a call to top-goal.
*
* @method prune_inner_computation
*/
static void prune_inner_computation(choiceptr parent) {
/* code */
choiceptr cut_pt;
yamop *oP = P, *oCP = CP;
Int oENV = LCL0 - ENV;
cut_pt = B;
while (cut_pt->cp_b < parent) {
2016-03-29 01:55:12 +01:00
cut_pt = cut_pt->cp_b;
}
#ifdef YAPOR
CUT_prune_to(cut_pt);
#endif
B = cut_pt;
2016-03-29 01:55:12 +01:00
Yap_TrimTrail();
LOCAL_AllowRestart = FALSE;
P = oP;
CP = oCP;
ENV = LCL0 - oENV;
B = parent;
2016-03-29 01:55:12 +01:00
}
2017-07-30 21:53:07 +01:00
2016-03-29 01:55:12 +01:00
/**
* restore abstract machine state
* after completing a computation.
* @method complete_inner_computation
*/
static void complete_inner_computation(choiceptr old_B) {
choiceptr myB = B;
if (myB == NULL) {
return;
} else if (myB->cp_b == old_B) {
B = old_B;
#ifdef DEPTH_LIMIT
DEPTH = myB->cp_depth;
#endif
} else if (myB->cp_b && myB->cp_b < old_B) {
while (myB->cp_b < old_B) {
// we're recovering from a non-deterministic computation...
myB = myB->cp_b;
}
} else {
return;
}
// restore environment at call...
CP = myB->cp_cp;
ENV = myB->cp_env;
}
2017-09-03 00:15:54 +01:00
static Int Yap_ignore(Term t, bool fail USES_REGS) {
2017-07-30 21:53:07 +01:00
yamop *oP = P, *oCP = CP;
Int oENV = LCL0 - ENV;
Int oYENV = LCL0 - YENV;
Int oB = LCL0 - (CELL *)B;
2018-06-14 11:27:43 +01:00
yap_error_descriptor_t *ctx = malloc(sizeof(yap_error_descriptor_t));
bool newxp = Yap_pushErrorContext(true, ctx);
2017-07-30 21:53:07 +01:00
bool rc = Yap_RunTopGoal(t, false);
if (!rc) {
complete_inner_computation((choiceptr)(LCL0 - oB));
// We'll pass it through
2016-03-29 01:55:12 +01:00
} else {
2017-07-30 21:53:07 +01:00
prune_inner_computation((choiceptr)(LCL0 - oB));
2016-03-29 01:55:12 +01:00
}
2018-06-14 11:27:43 +01:00
Yap_popErrorContext(newxp, true);
2017-07-30 21:53:07 +01:00
P = oP;
CP = oCP;
ENV = LCL0 - oENV;
YENV = LCL0 - oYENV;
B = (choiceptr)(LCL0 - oB);
return true;
}
extern void *Yap_blob_info(Term t);
static bool set_watch(Int Bv, Term task) {
CELL *pt;
Term t = Yap_AllocExternalDataInStack((CELL)setup_call_catcher_cleanup_tag,
sizeof(Int), &pt);
if (t == TermNil)
2016-03-29 01:55:12 +01:00
return false;
2017-07-30 21:53:07 +01:00
*pt = Bv;
*HR++ = t;
*HR++ = task;
TrailTerm(TR) = AbsPair(HR - 2);
TR++;
2016-03-29 01:55:12 +01:00
return true;
}
2017-07-30 21:53:07 +01:00
static bool watch_cut(Term ext USES_REGS) {
// called after backtracking..
//
Term task = TailOfTerm(ext);
Term cleanup = ArgOfTerm(3, task);
2017-09-03 00:15:54 +01:00
Term e = 0;
bool complete = IsNonVarTerm(Deref(ArgOfTerm(4, task)));
bool active = ArgOfTerm(5, task) == TermTrue;
2017-09-03 00:15:54 +01:00
bool ex_mode = false;
if (complete) {
2016-03-29 01:55:12 +01:00
return true;
}
CELL *port_pt = deref_ptr(RepAppl(task) + 2);
2017-09-03 00:15:54 +01:00
CELL *completion_pt = deref_ptr(RepAppl(task) + 4);
2018-06-14 11:27:43 +01:00
if (LOCAL_ActiveError && LOCAL_ActiveError->errorNo != YAP_NO_ERROR) {
e = MkErrorTerm(LOCAL_ActiveError);
2017-07-30 21:53:07 +01:00
Term t;
if (active) {
2017-07-30 21:53:07 +01:00
t = Yap_MkApplTerm(FunctorException, 1, &e);
} else {
t = Yap_MkApplTerm(FunctorExternalException, 1, &e);
2017-07-30 21:53:07 +01:00
}
port_pt[0] = t;
2017-09-03 00:15:54 +01:00
completion_pt[0] = TermException;
2017-07-30 21:53:07 +01:00
} else {
2017-09-03 00:15:54 +01:00
completion_pt[0] = port_pt[0] = TermCut;
2016-03-29 01:55:12 +01:00
}
2017-09-03 00:15:54 +01:00
Yap_ignore(cleanup, false);
CELL *complete_pt = deref_ptr(RepAppl(task) + 4);
complete_pt[0] = TermTrue;
2017-09-03 00:15:54 +01:00
if (ex_mode) {
2018-06-14 11:27:43 +01:00
// Yap_PutException(e);
2017-09-03 00:15:54 +01:00
return true;
}
2017-07-30 21:53:07 +01:00
if (Yap_RaiseException())
return false;
2016-03-29 01:55:12 +01:00
return true;
}
/**
* external backtrack to current stack frame: call method
* and control backtracking.
*
2017-04-07 23:10:59 +01:00
* @method protect_stack_from_restore
2016-03-29 01:55:12 +01:00
* @param USES_REGS1 [env for threaded execution]
* @return c
2017-07-30 21:53:07 +01:00
*/
static bool watch_retry(Term d0 USES_REGS) {
2016-03-29 01:55:12 +01:00
// called after backtracking..
//
2017-07-30 21:53:07 +01:00
Term task = TailOfTerm(d0);
bool box = ArgOfTerm(1, task) == TermTrue;
2017-07-30 21:53:07 +01:00
Term cleanup = ArgOfTerm(3, task);
bool complete = !IsVarTerm(ArgOfTerm(4, task));
bool active = ArgOfTerm(5, task) == TermTrue;
2017-09-03 00:15:54 +01:00
choiceptr B0 = (choiceptr)(LCL0 - IntegerOfTerm(ArgOfTerm(6, task)));
2017-09-03 00:15:54 +01:00
if (complete)
2017-07-30 21:53:07 +01:00
return true;
2017-09-03 00:15:54 +01:00
CELL *port_pt = deref_ptr(RepAppl(Deref(task)) + 2);
CELL *complete_pt = deref_ptr(RepAppl(Deref(task)) + 4);
Term t, e = 0;
bool ex_mode = false;
2017-07-30 21:53:07 +01:00
while (B->cp_ap->opc == FAIL_OPCODE)
B = B->cp_b;
2017-09-03 00:15:54 +01:00
// just do the frrpest
if (B >= B0 && !ex_mode && !active)
return true;
2018-06-14 11:27:43 +01:00
if (LOCAL_ActiveError && LOCAL_ActiveError->errorNo != YAP_NO_ERROR) {
e = MkErrorTerm(LOCAL_ActiveError);
if (active) {
2017-07-30 21:53:07 +01:00
t = Yap_MkApplTerm(FunctorException, 1, &e);
} else {
2017-07-30 21:53:07 +01:00
t = Yap_MkApplTerm(FunctorExternalException, 1, &e);
}
2017-09-03 00:15:54 +01:00
complete_pt[0] = TermException;
} else if (B >= B0) {
t = TermFail;
complete_pt[0] = t;
} else if (box) {
2017-09-17 07:48:21 +01:00
t = TermRedo;
2017-07-30 21:53:07 +01:00
} else {
return true;
}
port_pt[0] = t;
2017-09-03 00:15:54 +01:00
Yap_ignore(cleanup, true);
if (ex_mode) {
2018-06-14 11:27:43 +01:00
// Yap_PutException(e);
2017-09-03 00:15:54 +01:00
return true;
}
if (Yap_RaiseException())
2016-03-29 01:55:12 +01:00
return false;
2017-07-30 21:53:07 +01:00
return true;
2016-03-29 01:55:12 +01:00
}
/**
* First call to non deterministic predicate. Just leaves a choice-point
* hanging about for the future.
*
* @method protect_stack
* @param USES_REGS1 [env for threaded execution]
* @return [always succeed]
*/
2016-04-15 11:28:07 +01:00
static Int setup_call_catcher_cleanup(USES_REGS1) {
2016-03-29 01:55:12 +01:00
Term Setup = Deref(ARG1);
choiceptr B0 = B;
2017-07-30 21:53:07 +01:00
yamop *oP = P, *oCP = CP;
Int oENV = LCL0 - ENV;
Int oYENV = LCL0 - YENV;
2016-03-29 01:55:12 +01:00
bool rc;
Yap_DisableInterrupts(worker_id);
rc = Yap_RunTopGoal(Setup, false);
Yap_EnableInterrupts(worker_id);
2016-03-29 01:55:12 +01:00
if (Yap_RaiseException()) {
return false;
}
if (!rc) {
complete_inner_computation(B0);
// We'll pass it throughs
2016-03-29 01:55:12 +01:00
return false;
} else {
prune_inner_computation(B0);
}
2017-07-30 21:53:07 +01:00
P = oP;
CP = oCP;
ENV = LCL0 - oENV;
YENV = LCL0 - oYENV;
return rc;
}
2016-03-29 01:55:12 +01:00
static Int tag_cleanup(USES_REGS1) {
2017-07-30 21:53:07 +01:00
Int iB = LCL0 - (CELL *)B;
set_watch(iB, Deref(ARG2));
return Yap_unify(ARG1, MkIntegerTerm(iB));
}
static Int cleanup_on_exit(USES_REGS1) {
2017-07-30 21:53:07 +01:00
2018-04-16 14:54:53 +01:00
choiceptr B0 = (choiceptr)(LCL0 - IntegerOfTerm(Deref(ARG1)));
Term task = Deref(ARG2);
bool box = ArgOfTerm(1, task) == TermTrue;
Term cleanup = ArgOfTerm(3, task);
2017-09-03 00:15:54 +01:00
Term complete = IsNonVarTerm(ArgOfTerm(4, task));
while (B->cp_ap->opc == FAIL_OPCODE)
B = B->cp_b;
2017-09-03 00:15:54 +01:00
if (complete) {
return true;
2017-09-03 00:15:54 +01:00
}
CELL *catcher_pt = deref_ptr(RepAppl(Deref(task)) + 2);
CELL *complete_pt = deref_ptr(RepAppl(Deref(task)) + 4);
if (B < B0) {
// non-deterministic
set_watch(LCL0 - (CELL *)B, task);
if (!box) {
2017-07-30 21:53:07 +01:00
return true;
}
2017-09-03 00:15:54 +01:00
catcher_pt[0] = TermAnswer;
} else {
2017-09-03 00:15:54 +01:00
catcher_pt[0] = TermExit;
complete_pt[0] = TermExit;
}
Yap_ignore(cleanup, false);
if (B0->cp_ap == NOCODE)
B0->cp_ap = TRUSTFAILCODE;
2017-09-03 00:15:54 +01:00
if (Yap_RaiseException()) {
return false;
}
return true;
2016-03-29 01:55:12 +01:00
}
2016-01-03 01:31:21 +00:00
static bool complete_ge(bool out, Term omod, yhandle_t sl, bool creeping) {
CACHE_REGS
2018-06-14 11:27:43 +01:00
if (creeping) {
Yap_signal(YAP_CREEP_SIGNAL);
}
2016-01-03 01:31:21 +00:00
CurrentModule = omod;
Yap_CloseSlots(sl);
if (out) {
}
return out;
}
static Int _user_expand_goal(USES_REGS1) {
2016-01-03 01:31:21 +00:00
yhandle_t sl = Yap_StartSlots();
2015-10-20 08:10:39 +01:00
Int creeping = Yap_get_signal(YAP_CREEP_SIGNAL);
PredEntry *pe;
Term cmod = CurrentModule, omod = cmod;
2016-01-03 01:31:21 +00:00
Term mg_args[2];
Term g = Yap_YapStripModule(ARG1, &cmod);
yhandle_t h1 = Yap_InitSlot(g), h2 = Yap_InitSlot(ARG2);
2015-10-20 08:10:39 +01:00
/* CurMod:goal_expansion(A,B) */
ARG1 = g;
2015-10-20 08:10:39 +01:00
if ((pe = RepPredProp(Yap_GetPredPropByFunc(FunctorGoalExpansion2, cmod))) &&
2016-01-03 01:31:21 +00:00
pe->OpcodeOfPred != FAIL_OPCODE && pe->OpcodeOfPred != UNDEF_OPCODE &&
2019-02-27 04:23:21 +00:00
Yap_execute_pred(pe, NULL, false PASS_REGS)) {
return complete_ge(true , omod, sl, creeping);
2015-10-20 08:10:39 +01:00
}
/* system:goal_expansion(A,B) */
mg_args[0] = cmod;
mg_args[1] = Yap_GetFromSlot(h1);
2016-01-03 01:31:21 +00:00
ARG1 = Yap_MkApplTerm(FunctorModule, 2, mg_args);
ARG2 = Yap_GetFromSlot(h2);
2015-10-20 08:10:39 +01:00
if ((pe = RepPredProp(
2018-06-14 11:27:43 +01:00
Yap_GetPredPropByFunc(FunctorGoalExpansion2, SYSTEM_MODULE))) &&
2015-10-20 08:10:39 +01:00
pe->OpcodeOfPred != FAIL_OPCODE && pe->OpcodeOfPred != UNDEF_OPCODE &&
2019-02-27 04:23:21 +00:00
Yap_execute_pred(pe, NULL, false PASS_REGS)) {
2016-01-03 01:31:21 +00:00
return complete_ge(true, omod, sl, creeping);
2015-10-20 08:10:39 +01:00
}
2019-02-19 15:53:36 +00:00
Yap_ResetException(NULL);
ARG1 = Yap_GetFromSlot(h1);
2015-10-20 08:10:39 +01:00
ARG2 = cmod;
2016-01-03 01:31:21 +00:00
ARG3 = Yap_GetFromSlot(h2);
2015-10-20 08:10:39 +01:00
/* user:goal_expansion(A,CurMod,B) */
if ((pe = RepPredProp(
2018-06-14 11:27:43 +01:00
Yap_GetPredPropByFunc(FunctorGoalExpansion, USER_MODULE))) &&
2015-10-20 08:10:39 +01:00
pe->OpcodeOfPred != FAIL_OPCODE && pe->OpcodeOfPred != UNDEF_OPCODE &&
2019-02-27 04:23:21 +00:00
Yap_execute_pred(pe, NULL, false PASS_REGS)) {
2016-01-03 01:31:21 +00:00
return complete_ge(true, omod, sl, creeping);
2015-10-20 08:10:39 +01:00
}
2019-02-19 15:53:36 +00:00
Yap_ResetException(NULL);
mg_args[0] = cmod;
mg_args[1] = Yap_GetFromSlot(h1);
2016-01-03 01:31:21 +00:00
ARG1 = Yap_MkApplTerm(FunctorModule, 2, mg_args);
ARG2 = Yap_GetFromSlot(h2);
2015-10-20 08:10:39 +01:00
/* user:goal_expansion(A,B) */
if (cmod != USER_MODULE && /* we have tried this before */
(pe = RepPredProp(
2018-06-14 11:27:43 +01:00
Yap_GetPredPropByFunc(FunctorGoalExpansion2, USER_MODULE))) &&
2015-10-20 08:10:39 +01:00
pe->OpcodeOfPred != FAIL_OPCODE && pe->OpcodeOfPred != UNDEF_OPCODE &&
2019-02-27 04:23:21 +00:00
Yap_execute_pred(pe, NULL, false PASS_REGS)) {
2016-01-03 01:31:21 +00:00
return complete_ge(true, omod, sl, creeping);
2015-10-20 08:10:39 +01:00
}
2019-02-19 15:53:36 +00:00
Yap_ResetException(NULL);
2016-01-03 01:31:21 +00:00
return complete_ge(false, omod, sl, creeping);
2015-10-20 08:10:39 +01:00
}
static Int do_term_expansion(USES_REGS1) {
yhandle_t sl = Yap_StartSlots();
2015-10-20 08:10:39 +01:00
Int creeping = Yap_get_signal(YAP_CREEP_SIGNAL);
PredEntry *pe;
2016-01-03 01:31:21 +00:00
Term cmod = CurrentModule, omod = cmod;
Term mg_args[2];
Term g = Yap_YapStripModule(ARG1, &cmod);
yhandle_t h1 = Yap_InitSlot(g), h2 = Yap_InitSlot(ARG2);
2016-04-28 21:59:06 +01:00
/* user:term_expansion(A,B) */
2016-06-02 10:51:36 +01:00
2016-04-28 21:59:06 +01:00
ARG1 = g;
if ((pe = RepPredProp(
2018-06-14 11:27:43 +01:00
Yap_GetPredPropByFunc(FunctorTermExpansion, USER_MODULE))) &&
2016-04-28 21:59:06 +01:00
pe->OpcodeOfPred != FAIL_OPCODE && pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL, false PASS_REGS)) {
return complete_ge(true, omod, sl, creeping);
}
2015-10-20 08:10:39 +01:00
/* CurMod:term_expansion(A,B) */
2016-01-03 01:31:21 +00:00
ARG1 = g;
2016-04-28 21:59:06 +01:00
if (cmod != USER_MODULE &&
(pe = RepPredProp(Yap_GetPredPropByFunc(FunctorTermExpansion, cmod))) &&
2015-10-20 08:10:39 +01:00
pe->OpcodeOfPred != FAIL_OPCODE && pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL, false PASS_REGS)) {
2016-01-03 01:31:21 +00:00
return complete_ge(true, omod, sl, creeping);
2015-10-20 08:10:39 +01:00
}
/* system:term_expansion(A,B) */
2016-01-03 01:31:21 +00:00
mg_args[0] = cmod;
mg_args[1] = Yap_GetFromSlot(h1);
ARG1 = Yap_MkApplTerm(FunctorModule, 2, mg_args);
ARG2 = Yap_GetFromSlot(h2);
2015-10-20 08:10:39 +01:00
if ((pe = RepPredProp(
2018-06-14 11:27:43 +01:00
Yap_GetPredPropByFunc(FunctorTermExpansion, SYSTEM_MODULE))) &&
2015-10-20 08:10:39 +01:00
pe->OpcodeOfPred != FAIL_OPCODE && pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL, false PASS_REGS)) {
2016-01-03 01:31:21 +00:00
return complete_ge(true, omod, sl, creeping);
2015-10-20 08:10:39 +01:00
}
2016-01-03 01:31:21 +00:00
return complete_ge(false, omod, sl, creeping);
}
2015-10-20 08:10:39 +01:00
static Int execute0(USES_REGS1) { /* '$execute0'(Goal,Mod) */
Term t = Deref(ARG1), t0 = t;
Term mod = Deref(ARG2);
unsigned int arity;
Prop pe;
2015-07-23 01:05:06 +01:00
2015-10-20 08:10:39 +01:00
if (Yap_has_a_signal() && !LOCAL_InterruptsDisabled) {
return EnterCreepMode(t, mod PASS_REGS);
}
2016-09-21 04:48:28 +01:00
t = Yap_YapStripModule(t, &mod);
2018-06-14 11:27:43 +01:00
restart_exec:
2015-10-20 08:10:39 +01:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, ARG3, "call/1");
2016-03-29 01:55:12 +01:00
return false;
2015-10-20 08:10:39 +01:00
} else if (IsAtomTerm(t)) {
Atom a = AtomOfTerm(t);
pe = PredPropByAtom(a, mod);
2019-02-27 04:23:21 +00:00
} else if (IsPairTerm(t)) {
Term ts[2];
ts[0] = t;
ts[1] = (CurrentModule == 0 ? TermProlog : CurrentModule);
t = Yap_MkApplTerm(FunctorCsult, 2, ts);
goto restart_exec;
2015-10-20 08:10:39 +01:00
} else if (IsApplTerm(t)) {
register Functor f = FunctorOfTerm(t);
register unsigned int i;
register CELL *pt;
if (IsExtensionFunctor(f))
return FALSE;
if (f == FunctorModule) {
Term tmod = ArgOfTerm(1, t);
if (!IsVarTerm(tmod) && IsAtomTerm(tmod)) {
mod = tmod;
t = ArgOfTerm(2, t);
goto restart_exec;
} else {
if (IsVarTerm(tmod)) {
return CallError(INSTANTIATION_ERROR, t0, mod PASS_REGS);
} else {
return CallError(TYPE_ERROR_ATOM, t0, mod PASS_REGS);
}
2015-10-20 08:10:39 +01:00
}
}
pe = PredPropByFunc(f, mod);
2016-03-29 01:55:12 +01:00
// Yap_DebugPlWrite(mod);ffprintf(stderr, stderr,"\n");
2015-10-20 08:10:39 +01:00
arity = ArityOfFunctor(f);
if (arity > MaxTemps) {
return CallError(TYPE_ERROR_CALLABLE, t, mod PASS_REGS);
}
/* I cannot use the standard macro here because
2016-03-29 01:55:12 +01:00
otherwise I would dereference the argument and
might skip a svar */
2015-10-20 08:10:39 +01:00
pt = RepAppl(t) + 1;
for (i = 1; i <= arity; ++i) {
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
2015-10-20 08:10:39 +01:00
Term d0 = *pt++;
if (d0 == 0)
XREGS[i] = (CELL)(pt - 1);
else
XREGS[i] = d0;
#else
2015-10-20 08:10:39 +01:00
XREGS[i] = *pt++;
#endif
}
2015-10-20 08:10:39 +01:00
} else {
2019-02-27 04:23:21 +00:00
//Yap_Error(TYPE_ERROR_CALLABLE, t, "call/1");
//return false;
return CallMetaCall(t, mod);
2015-10-20 08:10:39 +01:00
}
/* N = arity; */
/* call may not define new system predicates!! */
return CallPredicate(RepPredProp(pe), B,
RepPredProp(pe)->CodeOfPred PASS_REGS);
}
2017-09-17 07:48:21 +01:00
static Int creep_step(USES_REGS1) { /* '$execute_nonstop'(Goal,Mod)
*/
Term t = Deref(ARG1);
Term mod = Deref(ARG2);
unsigned int arity;
Prop pe;
bool rc;
t = Yap_YapStripModule(t, &mod);
if (IsVarTerm(mod)) {
mod = CurrentModule;
} else if (!IsAtomTerm(mod)) {
Yap_Error(TYPE_ERROR_ATOM, ARG2, "call/1");
return FALSE;
}
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, ARG1, "call/1");
return FALSE;
} else if (IsAtomTerm(t)) {
Atom a = AtomOfTerm(t);
pe = PredPropByAtom(a, mod);
} else if (IsApplTerm(t)) {
register Functor f = FunctorOfTerm(t);
register unsigned int i;
register CELL *pt;
if (IsExtensionFunctor(f))
return (FALSE);
pe = PredPropByFunc(f, mod);
arity = ArityOfFunctor(f);
if (arity > MaxTemps) {
return CallError(TYPE_ERROR_CALLABLE, t, mod PASS_REGS);
}
/* I cannot use the standard macro here because
otherwise I would dereference the argument and
might skip a svar */
pt = RepAppl(t) + 1;
for (i = 1; i <= arity; ++i) {
#if YAPOR_SBA
Term d0 = *pt++;
if (d0 == 0)
XREGS[i] = (CELL)(pt - 1);
else
XREGS[i] = d0;
#else
XREGS[i] = *pt++;
#endif
}
} else {
2019-02-27 04:23:21 +00:00
return CallMetaCall(t, mod);
2017-09-17 07:48:21 +01:00
}
/* N = arity; */
/* call may not define new system predicates!! */
if (RepPredProp(pe)->PredFlags & SpiedPredFlag) {
if (!LOCAL_InterruptsDisabled && Yap_get_signal(YAP_CREEP_SIGNAL)) {
Yap_signal(YAP_CREEP_SIGNAL);
}
#if defined(YAPOR) || defined(THREADS)
if (RepPredProp(pe)->PredFlags & LogUpdatePredFlag) {
PP = RepPredProp(pe);
PELOCK(80, PP);
}
#endif
rc = CallPredicate(RepPredProp(pe), B,
RepPredProp(pe)->cs.p_code.TrueCodeOfPred PASS_REGS);
} else {
rc = CallPredicate(RepPredProp(pe), B,
RepPredProp(pe)->CodeOfPred PASS_REGS);
}
if (!LOCAL_InterruptsDisabled &&
(!(RepPredProp(pe)->PredFlags & (AsmPredFlag | CPredFlag)) ||
RepPredProp(pe)->OpcodeOfPred == Yap_opcode(_call_bfunc_xx))) {
Yap_signal(YAP_CREEP_SIGNAL);
}
return rc;
}
2018-04-20 14:59:17 +01:00
/**
* @brief Two argument version of non-interruptible execution: this will
* ignore signals including debugging requests.
2018-06-14 11:27:43 +01:00
*
2018-04-20 14:59:17 +01:00
* @return Int succeeds if it can transfer control.
*/
2018-06-14 11:27:43 +01:00
static Int execute_nonstop(USES_REGS1) {
Term t = Deref(ARG1);
2015-10-20 08:10:39 +01:00
Term mod = Deref(ARG2);
unsigned int arity;
Prop pe;
2015-07-23 01:05:06 +01:00
2016-05-12 11:49:04 +01:00
t = Yap_YapStripModule(t, &mod);
2015-10-20 08:10:39 +01:00
if (IsVarTerm(mod)) {
mod = CurrentModule;
} else if (!IsAtomTerm(mod)) {
Yap_Error(TYPE_ERROR_ATOM, ARG2, "call/1");
return FALSE;
}
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, ARG1, "call/1");
return FALSE;
} else if (IsAtomTerm(t)) {
Atom a = AtomOfTerm(t);
pe = PredPropByAtom(a, mod);
} else if (IsApplTerm(t)) {
register Functor f = FunctorOfTerm(t);
register unsigned int i;
register CELL *pt;
if (IsExtensionFunctor(f))
return (FALSE);
pe = PredPropByFunc(f, mod);
arity = ArityOfFunctor(f);
if (arity > MaxTemps) {
return CallError(TYPE_ERROR_CALLABLE, t, mod PASS_REGS);
}
/* I cannot use the standard macro here because
2016-03-29 01:55:12 +01:00
otherwise I would dereference the argument and
might skip a svar */
2015-10-20 08:10:39 +01:00
pt = RepAppl(t) + 1;
for (i = 1; i <= arity; ++i) {
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
2015-10-20 08:10:39 +01:00
Term d0 = *pt++;
if (d0 == 0)
XREGS[i] = (CELL)(pt - 1);
else
XREGS[i] = d0;
#else
2015-10-20 08:10:39 +01:00
XREGS[i] = *pt++;
#endif
}
2015-10-20 08:10:39 +01:00
} else {
Yap_Error(TYPE_ERROR_CALLABLE, t, "call/1");
return FALSE;
}
/* N = arity; */
/* call may not define new system predicates!! */
if (RepPredProp(pe)->PredFlags & SpiedPredFlag) {
if (!LOCAL_InterruptsDisabled && Yap_get_signal(YAP_CREEP_SIGNAL)) {
Yap_signal(YAP_CREEP_SIGNAL);
}
#if defined(YAPOR) || defined(THREADS)
2015-10-20 08:10:39 +01:00
if (RepPredProp(pe)->PredFlags & LogUpdatePredFlag) {
PP = RepPredProp(pe);
PELOCK(80, PP);
}
#endif
2015-10-20 08:10:39 +01:00
return CallPredicate(RepPredProp(pe), B,
RepPredProp(pe)->cs.p_code.TrueCodeOfPred PASS_REGS);
} else {
if (Yap_get_signal(YAP_CREEP_SIGNAL) && !LOCAL_InterruptsDisabled &&
(!(RepPredProp(pe)->PredFlags & (AsmPredFlag | CPredFlag)) ||
RepPredProp(pe)->OpcodeOfPred == Yap_opcode(_call_bfunc_xx))) {
Yap_signal(YAP_CREEP_SIGNAL);
}
2015-10-20 08:10:39 +01:00
return CallPredicate(RepPredProp(pe), B,
RepPredProp(pe)->CodeOfPred PASS_REGS);
}
}
2018-04-20 14:59:17 +01:00
/**
* @brief One argument version of non-interruptible execution: this will
* ignore signals including debugging requests.
2018-06-14 11:27:43 +01:00
*
2018-04-20 14:59:17 +01:00
* @return Int succeeds if it can transfer control.
*/
2018-06-14 11:27:43 +01:00
static Int execute_nonstop1(USES_REGS1) {
ARG2 = CurrentModule;
return execute_nonstop(PASS_REGS1);
2018-04-20 14:59:17 +01:00
}
2015-10-20 08:10:39 +01:00
static Int execute_0(USES_REGS1) { /* '$execute_0'(Goal) */
Term mod = CurrentModule;
Term t = Yap_YapStripModule(Deref(ARG1), &mod);
2016-03-29 01:55:12 +01:00
if (t == 0)
return false;
2015-10-20 08:10:39 +01:00
return do_execute(t, mod PASS_REGS);
}
2016-03-29 01:55:12 +01:00
static bool call_with_args(int i USES_REGS) {
2015-10-20 08:10:39 +01:00
Term mod = CurrentModule, t;
int j;
2015-07-23 01:05:06 +01:00
t = Yap_YapStripModule(Deref(ARG1), &mod);
2016-03-29 01:55:12 +01:00
if (t == 0)
return false;
2015-10-20 08:10:39 +01:00
for (j = 0; j < i; j++)
heap_store(Deref(XREGS[j + 2]) PASS_REGS);
return (do_execute_n(t, mod, i PASS_REGS));
}
2015-10-20 08:10:39 +01:00
static Int execute_1(USES_REGS1) { /* '$execute_0'(Goal) */
return call_with_args(1 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute_2(USES_REGS1) { /* '$execute_2'(Goal) */
return call_with_args(2 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute_3(USES_REGS1) { /* '$execute_3'(Goal) */
return call_with_args(3 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute_4(USES_REGS1) { /* '$execute_4'(Goal) */
return call_with_args(4 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute_5(USES_REGS1) { /* '$execute_5'(Goal) */
return call_with_args(5 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute_6(USES_REGS1) { /* '$execute_6'(Goal) */
return call_with_args(6 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute_7(USES_REGS1) { /* '$execute_7'(Goal) */
return call_with_args(7 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute_8(USES_REGS1) { /* '$execute_8'(Goal) */
return call_with_args(8 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute_9(USES_REGS1) { /* '$execute_9'(Goal) */
return call_with_args(9 PASS_REGS);
}
2015-10-20 08:10:39 +01:00
static Int execute_10(USES_REGS1) { /* '$execute_10'(Goal) */
return call_with_args(10 PASS_REGS);
}
#ifdef DEPTH_LIMIT
2015-10-20 08:10:39 +01:00
static Int execute_depth_limit(USES_REGS1) {
Term d = Deref(ARG2);
if (IsVarTerm(d)) {
Yap_Error(INSTANTIATION_ERROR, d, "depth_bound_call/2");
2016-03-29 01:55:12 +01:00
return false;
2015-10-20 08:10:39 +01:00
} else if (!IsIntegerTerm(d)) {
if (IsFloatTerm(d) && isinf(FloatOfTerm(d))) {
DEPTH = RESET_DEPTH();
2013-01-28 23:21:54 +00:00
} else {
2015-10-20 08:10:39 +01:00
Yap_Error(TYPE_ERROR_INTEGER, d, "depth_bound_call/2");
2016-03-29 01:55:12 +01:00
return false;
2013-01-28 23:21:54 +00:00
}
2015-10-20 08:10:39 +01:00
} else {
DEPTH = MkIntTerm(IntegerOfTerm(d) * 2);
}
return execute(PASS_REGS1);
}
#endif
2016-03-29 01:55:12 +01:00
static bool exec_absmi(bool top, yap_reset_t reset_mode USES_REGS) {
2018-04-04 15:55:45 +01:00
int lval = 0, out;
2016-03-29 01:55:12 +01:00
Int OldBorder = LOCAL_CBorder;
2018-05-14 16:03:02 +01:00
// yap_error_descriptor_t *err_info= LOCAL_ActiveError;
2018-04-04 10:06:54 +01:00
LOCAL_CBorder = LCL0 - ENV;
2018-06-18 10:25:17 +01:00
LOCAL_MallocDepth = AllocLevel();
2018-05-15 12:36:18 +01:00
yhandle_t sls = Yap_CurrentSlot();
2018-04-04 10:06:54 +01:00
sigjmp_buf signew, *sighold = LOCAL_RestartEnv;
LOCAL_RestartEnv = &signew;
2018-06-18 10:25:17 +01:00
volatile int i = AllocLevel();
2018-06-14 11:27:43 +01:00
if /* top &&*/ ((lval = sigsetjmp(signew, 1)) != 0) {
2018-04-07 19:45:18 +01:00
switch (lval) {
case 1: { /* restart */
2018-03-29 22:33:53 +01:00
/* otherwise, SetDBForThrow will fail entering critical mode */
2018-05-14 16:03:02 +01:00
// LOCAL_ActiveError = err_info;
2018-04-07 19:45:18 +01:00
LOCAL_PrologMode = UserMode;
2018-06-25 13:44:09 +01:00
LOCAL_DoingUndefp = false;
2018-04-07 19:45:18 +01:00
/* find out where to cut to */
/* siglongjmp resets the TR hardware register */
/* TR and B are crucial, they might have been changed, or not */
restore_TR();
restore_B();
/* H is not so important, because we're gonna backtrack */
restore_H();
/* set stack */
2018-06-14 11:27:43 +01:00
ASP = (CELL *)PROTECT_FROZEN_B(B);
2018-04-07 19:45:18 +01:00
/* forget any signals active, we're reborne */
LOCAL_Signals = 0;
CalculateStackGap(PASS_REGS1);
LOCAL_PrologMode = UserMode;
2018-05-15 12:36:18 +01:00
Yap_CloseSlots(sls);
2018-06-14 11:27:43 +01:00
P = (yamop *)FAILCODE;
} break;
2018-04-07 19:45:18 +01:00
case 2: {
2018-05-14 16:03:02 +01:00
// LOCAL_ActiveError = err_info;
2018-04-07 19:45:18 +01:00
/* arithmetic exception */
/* must be done here, otherwise siglongjmp will clobber all the
* registers
*/
/* reset the registers so that we don't have trash in abstract
* machine */
2018-07-09 00:50:00 +01:00
pop_text_stack(i + 1);
2018-04-07 19:45:18 +01:00
Yap_set_fpu_exceptions(
2018-06-14 11:27:43 +01:00
getAtomicGlobalPrologFlag(ARITHMETIC_EXCEPTIONS_FLAG));
P = (yamop *)FAILCODE;
2018-04-07 19:45:18 +01:00
LOCAL_PrologMode = UserMode;
2018-06-25 13:44:09 +01:00
LOCAL_DoingUndefp = false;
2018-05-15 12:36:18 +01:00
Yap_CloseSlots(sls);
2018-06-14 11:27:43 +01:00
} break;
2018-04-07 19:45:18 +01:00
case 3: { /* saved state */
2018-05-14 16:03:02 +01:00
// LOCAL_ActiveError = err_info;
2018-07-09 00:50:00 +01:00
pop_text_stack(i + 1);
2018-04-07 19:45:18 +01:00
LOCAL_CBorder = OldBorder;
LOCAL_RestartEnv = sighold;
LOCAL_PrologMode = UserMode;
2018-07-09 00:50:00 +01:00
LOCAL_DoingUndefp = false;
Yap_CloseSlots(sls);
2018-06-14 11:27:43 +01:00
return false;
2018-04-07 19:45:18 +01:00
}
case 4:
/* abort */
/* can be called from anywhere, must reset registers,
*/
2018-05-14 16:03:02 +01:00
// LOCAL_ActiveError = err_info;
2018-04-07 19:45:18 +01:00
while (B) {
2018-06-14 11:27:43 +01:00
LOCAL_ActiveError->errorNo = ABORT_EVENT;
2018-07-09 00:50:00 +01:00
pop_text_stack(i + 1);
2018-06-14 11:27:43 +01:00
Yap_CloseSlots(sls);
Yap_JumpToEnv();
2017-03-23 12:28:46 +00:00
}
2018-04-07 19:45:18 +01:00
LOCAL_PrologMode = UserMode;
2018-07-09 00:50:00 +01:00
LOCAL_DoingUndefp = false;
P = (yamop *)FAILCODE;
2018-04-07 19:45:18 +01:00
LOCAL_RestartEnv = sighold;
2018-05-15 12:36:18 +01:00
Yap_CloseSlots(sls);
2018-07-09 00:50:00 +01:00
pop_text_stack(i + 1);
2018-04-07 19:45:18 +01:00
return false;
break;
case 5:
// going up, unless there is no up to go to. or someone
// but we should inform the caller on what happened.
// Yap_regp = old_rs;
2018-05-14 16:03:02 +01:00
// LOCAL_ActiveError = err_info;
2018-04-07 19:45:18 +01:00
restore_TR();
restore_B();
/* H is not so important, because we're gonna backtrack */
restore_H();
/* set stack */
Yap_JumpToEnv();
2018-05-14 16:03:02 +01:00
Yap_CloseTemporaryStreams();
2018-05-26 00:22:27 +01:00
Yap_CloseSlots(sls);
2018-06-14 11:27:43 +01:00
ASP = (CELL *)PROTECT_FROZEN_B(B);
2018-04-07 19:45:18 +01:00
2018-06-14 11:27:43 +01:00
if (B == NULL || B->cp_b == NULL ||
(CELL *)(B->cp_b) > LCL0 - LOCAL_CBorder) {
LOCAL_RestartEnv = sighold;
LOCAL_CBorder = OldBorder;
2018-07-09 00:50:00 +01:00
pop_text_stack(i + 1);
return false;
2018-04-07 19:45:18 +01:00
}
P = FAILCODE;
}
2015-10-20 08:10:39 +01:00
}
YENV = ASP;
YENV[E_CB] = Unsigned(B);
2018-07-09 00:50:00 +01:00
pop_text_stack(i + 1);
2018-04-07 19:45:18 +01:00
out = Yap_absmi(0);
/* make sure we don't leave a FAIL signal hanging around */
2015-10-20 08:10:39 +01:00
Yap_get_signal(YAP_FAIL_SIGNAL);
if (!Yap_has_a_signal())
CalculateStackGap(PASS_REGS1);
2016-03-29 01:55:12 +01:00
LOCAL_CBorder = OldBorder;
LOCAL_RestartEnv = sighold;
2018-07-09 00:50:00 +01:00
pop_text_stack(i + 1);
2016-03-30 17:35:03 +01:00
return out;
2015-10-20 08:10:39 +01:00
}
2016-09-21 04:48:28 +01:00
void Yap_PrepGoal(arity_t arity, CELL *pt, choiceptr saved_b USES_REGS) {
2015-10-20 08:10:39 +01:00
/* create an initial pseudo environment so that when garbage
2016-03-29 01:55:12 +01:00
collection is going up in the environment chain it doesn't get
confused */
Yap_ResetException(worker_id);
2015-10-20 08:10:39 +01:00
// sl = Yap_InitSlot(t);
YENV = ASP;
YENV[E_CP] = (CELL)YESCODE;
YENV[E_CB] = (CELL)B;
YENV[E_E] = (CELL)ENV;
#ifdef TABLING
YENV[E_B] = (CELL)B;
2011-04-15 23:05:03 +01:00
#endif
2015-10-20 08:10:39 +01:00
#ifdef DEPTH_LIMIT
YENV[E_DEPTH] = DEPTH;
#endif
2015-10-20 08:10:39 +01:00
ENV = YENV;
ASP -= EnvSizeInCells;
/* and now create a pseudo choicepoint for much the same reasons */
/* CP = YESCODE; */
/* keep a place where you can inform you had an exception */
if (pt) {
int i;
for (i = 0; i < arity; i++) {
XREGS[i + 1] = *pt++;
}
}
B = (choiceptr)ASP;
B--;
B->cp_h = HR;
B->cp_tr = TR;
B->cp_cp = CP;
B->cp_ap = NOCODE;
B->cp_env = ENV;
B->cp_b = saved_b;
#ifdef DEPTH_LIMIT
2015-10-20 08:10:39 +01:00
B->cp_depth = DEPTH;
#endif /* DEPTH_LIMIT */
2015-10-20 08:10:39 +01:00
YENV = ASP = (CELL *)B;
YENV[E_CB] = (CELL)B;
HB = HR;
CP = YESCODE;
}
2016-03-29 01:55:12 +01:00
static bool do_goal(yamop *CodeAdr, int arity, CELL *pt, bool top USES_REGS) {
2015-10-20 08:10:39 +01:00
choiceptr saved_b = B;
2016-03-29 01:55:12 +01:00
bool out;
2015-10-20 08:10:39 +01:00
Yap_PrepGoal(arity, pt, saved_b PASS_REGS);
2018-06-18 12:16:36 +01:00
// CACHE_A1();
2015-10-20 08:10:39 +01:00
P = (yamop *)CodeAdr;
// S = CellPtr(RepPredProp(
// PredPropByFunc(Yap_MkFunctor(AtomCall, 1), 0))); /* A1 mishaps */
2017-04-08 11:29:29 +01:00
2015-10-20 08:10:39 +01:00
out = exec_absmi(top, YAP_EXEC_ABSMI PASS_REGS);
// if (out) {
// out = Yap_GetFromSlot(sl);
// }
// Yap_RecoverSlots(1);
2016-03-29 01:55:12 +01:00
LOCAL_PrologMode &= ~TopGoalMode;
2015-10-20 08:10:39 +01:00
return out;
}
2016-03-29 01:55:12 +01:00
bool Yap_exec_absmi(bool top, yap_reset_t has_reset) {
2015-10-20 08:10:39 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
return exec_absmi(top, has_reset PASS_REGS);
}
2016-03-29 01:55:12 +01:00
/**
* Fails computation up to choice-point bb
2018-06-14 11:27:43 +01:00
*
2018-05-01 23:25:58 +01:00
* @param USES_REGS thread support
2016-03-29 01:55:12 +01:00
*/
2015-10-20 08:10:39 +01:00
void Yap_fail_all(choiceptr bb USES_REGS) {
yamop *saved_p, *saved_cp;
2017-04-08 11:29:29 +01:00
2015-10-20 08:10:39 +01:00
saved_p = P;
saved_cp = CP;
/* prune away choicepoints */
2018-08-09 16:42:43 +01:00
if (B == bb)
return;
2016-03-29 01:55:12 +01:00
while (B->cp_b && B->cp_b != bb && B->cp_ap != NOCODE) {
2015-10-20 08:10:39 +01:00
B = B->cp_b;
2014-10-23 02:10:55 +01:00
#ifdef YAPOR
2015-10-20 08:10:39 +01:00
CUT_prune_to(B);
2014-10-23 02:10:55 +01:00
#endif
2015-10-20 08:10:39 +01:00
}
P = FAILCODE;
2016-03-29 01:55:12 +01:00
exec_absmi(true, YAP_EXEC_ABSMI PASS_REGS);
2015-10-20 08:10:39 +01:00
/* recover stack space */
HR = B->cp_h;
TR = B->cp_tr;
2014-10-23 02:10:55 +01:00
#ifdef DEPTH_LIMIT
2015-10-20 08:10:39 +01:00
DEPTH = B->cp_depth;
2014-10-23 02:10:55 +01:00
#endif /* DEPTH_LIMIT */
2015-10-20 08:10:39 +01:00
YENV = ENV = B->cp_env;
2018-04-07 19:45:18 +01:00
/* recover local stack */
2014-10-23 02:10:55 +01:00
#ifdef DEPTH_LIMIT
2015-10-20 08:10:39 +01:00
DEPTH = ENV[E_DEPTH];
2014-10-23 02:10:55 +01:00
#endif
2015-10-20 08:10:39 +01:00
/* make sure we prune C-choicepoints */
if (POP_CHOICE_POINT(B->cp_b)) {
POP_EXECUTE();
}
ENV = (CELL *)(ENV[E_E]);
/* ASP should be set to the top of the local stack when we
2016-03-29 01:55:12 +01:00
did the call */
2015-10-20 08:10:39 +01:00
ASP = B->cp_env;
/* YENV should be set to the current environment */
YENV = ENV = (CELL *)((B->cp_env)[E_E]);
2016-03-29 01:55:12 +01:00
if (B->cp_b) {
B = B->cp_b;
}
2015-10-20 08:10:39 +01:00
// SET_BB(B);
HB = PROTECT_FROZEN_H(B);
CP = saved_cp;
P = saved_p;
}
2016-09-21 04:48:28 +01:00
bool Yap_execute_pred(PredEntry *ppe, CELL *pt, bool pass_ex USES_REGS) {
2015-10-20 08:10:39 +01:00
yamop *saved_p, *saved_cp;
yamop *CodeAdr;
2016-03-29 01:55:12 +01:00
bool out;
2018-11-03 10:49:35 +00:00
2015-10-20 08:10:39 +01:00
saved_p = P;
saved_cp = CP;
2016-03-29 01:55:12 +01:00
LOCAL_PrologMode |= TopGoalMode;
2017-04-08 11:29:29 +01:00
2015-10-20 08:10:39 +01:00
PELOCK(81, ppe);
CodeAdr = ppe->CodeOfPred;
UNLOCK(ppe->PELock);
out = do_goal(CodeAdr, ppe->ArityOfPE, pt, false PASS_REGS);
2017-04-08 11:29:29 +01:00
2016-03-29 01:55:12 +01:00
if (out) {
2015-10-20 08:10:39 +01:00
choiceptr cut_B;
/* we succeeded, let's prune */
/* restore the old environment */
/* get to previous environment */
cut_B = (choiceptr)ENV[E_CB];
#ifdef YAPOR
2015-10-20 08:10:39 +01:00
CUT_prune_to(cut_B);
#endif /* YAPOR */
#ifdef TABLING
2015-10-20 08:10:39 +01:00
if (B != cut_B) {
while (B->cp_b < cut_B) {
B = B->cp_b;
}
#ifdef TABLING
2015-10-20 08:10:39 +01:00
abolish_incomplete_subgoals(B);
#endif
2015-10-20 08:10:39 +01:00
}
#endif /* TABLING */
2015-10-20 08:10:39 +01:00
B = cut_B;
CP = saved_cp;
P = saved_p;
ASP = ENV;
#ifdef DEPTH_LIMIT
2015-10-20 08:10:39 +01:00
DEPTH = ENV[E_DEPTH];
#endif
2015-10-20 08:10:39 +01:00
ENV = (CELL *)(ENV[E_E]);
/* we have failed, and usually we would backtrack to this B,
2016-03-29 01:55:12 +01:00
trouble is, we may also have a delayed cut to do */
2015-10-20 08:10:39 +01:00
if (B != NULL)
HB = B->cp_h;
YENV = ENV;
// should we catch the exception or pass it through?
2019-02-19 15:56:22 +00:00
// We'll pass it through
if ( Yap_HasException()) {
if (pass_ex &&
((LOCAL_PrologMode & BootMode) || !CurrentModule )) {
Yap_ResetException(LOCAL_ActiveError);
} else {
Yap_RaiseException();
}
2016-03-29 01:55:12 +01:00
return false;
2015-10-20 08:10:39 +01:00
}
2019-02-19 15:56:22 +00:00
return true;
2015-10-20 08:10:39 +01:00
} else if (out == 0) {
P = saved_p;
CP = saved_cp;
HR = B->cp_h;
#ifdef DEPTH_LIMIT
2015-10-20 08:10:39 +01:00
DEPTH = B->cp_depth;
#endif
2015-10-20 08:10:39 +01:00
/* ASP should be set to the top of the local stack when we
2016-03-29 01:55:12 +01:00
did the call */
2015-10-20 08:10:39 +01:00
ASP = B->cp_env;
/* YENV should be set to the current environment */
YENV = ENV = (CELL *)((B->cp_env)[E_E]);
B = B->cp_b;
SET_BB(B);
HB = PROTECT_FROZEN_H(B);
// should we catch the exception or pass it through?
// We'll pass it through
2019-02-19 15:56:22 +00:00
if ( Yap_HasException()) {
if (pass_ex &&
((LOCAL_PrologMode & BootMode) || !CurrentModule )) {
Yap_ResetException(LOCAL_ActiveError);
} else {
Yap_RaiseException();
}
2015-10-20 08:10:39 +01:00
}
2016-03-29 01:55:12 +01:00
return false;
2015-10-20 08:10:39 +01:00
} else {
Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "emulator crashed");
2016-03-29 01:55:12 +01:00
return false;
2015-10-20 08:10:39 +01:00
}
}
2016-03-29 01:55:12 +01:00
bool Yap_execute_goal(Term t, int nargs, Term mod, bool pass_ex) {
2015-10-20 08:10:39 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
Prop pe;
2015-10-20 08:10:39 +01:00
PredEntry *ppe;
CELL *pt;
/* preserve the current restart environment */
/* visualc*/
2016-03-29 01:55:12 +01:00
/* just keep the difference because of possible garbage collections
*/
2017-04-08 11:29:29 +01:00
2015-10-20 08:10:39 +01:00
if (IsAtomTerm(t)) {
Atom a = AtomOfTerm(t);
pt = NULL;
pe = PredPropByAtom(a, mod);
} else if (IsApplTerm(t)) {
Functor f = FunctorOfTerm(t);
2017-04-08 11:29:29 +01:00
2015-10-20 08:10:39 +01:00
if (IsBlobFunctor(f)) {
Yap_Error(TYPE_ERROR_CALLABLE, t, "call/1");
2016-03-29 01:55:12 +01:00
return false;
}
2015-10-20 08:10:39 +01:00
/* I cannot use the standard macro here because
2016-03-29 01:55:12 +01:00
otherwise I would dereference the argument and
might skip a svar */
2015-10-20 08:10:39 +01:00
pt = RepAppl(t) + 1;
pe = PredPropByFunc(f, mod);
} else {
Yap_Error(TYPE_ERROR_CALLABLE, t, "call/1");
2016-03-29 01:55:12 +01:00
return false;
2015-10-20 08:10:39 +01:00
}
ppe = RepPredProp(pe);
if (pe == NIL) {
return CallMetaCall(t, mod PASS_REGS);
}
return Yap_execute_pred(ppe, pt, pass_ex PASS_REGS);
}
void Yap_trust_last(void) {
CACHE_REGS
2018-06-14 11:27:43 +01:00
ASP = B->cp_env;
2015-10-20 08:10:39 +01:00
CP = B->cp_cp;
HR = B->cp_h;
#ifdef DEPTH_LIMIT
2015-10-20 08:10:39 +01:00
DEPTH = B->cp_depth;
#endif
2015-10-20 08:10:39 +01:00
YENV = ASP = B->cp_env;
ENV = (CELL *)((B->cp_env)[E_E]);
B = B->cp_b;
P = (yamop *)(ENV[E_CP]);
if (B) {
SET_BB(B);
HB = PROTECT_FROZEN_H(B);
}
}
2016-03-29 01:55:12 +01:00
Term Yap_RunTopGoal(Term t, bool handle_errors) {
2015-10-20 08:10:39 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
yamop *CodeAdr;
2015-10-20 08:10:39 +01:00
Prop pe;
PredEntry *ppe;
CELL *pt;
UInt arity;
Term tmod = CurrentModule;
2015-10-20 08:10:39 +01:00
Term goal_out = 0;
2016-03-29 01:55:12 +01:00
LOCAL_PrologMode |= TopGoalMode;
2017-04-08 11:29:29 +01:00
t = Yap_YapStripModule(t, &tmod);
2016-03-29 01:55:12 +01:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, "call/1");
LOCAL_PrologMode &= ~TopGoalMode;
return (FALSE);
2018-06-14 11:27:43 +01:00
}
if (IsPairTerm(t)) {
2018-04-07 19:45:18 +01:00
Term ts[2];
ts[0] = t;
2018-06-14 11:27:43 +01:00
ts[1] = (CurrentModule == 0 ? TermProlog : CurrentModule);
t = Yap_MkApplTerm(FunctorCsult, 2, ts);
2018-01-18 14:47:27 +00:00
}
if (IsAtomTerm(t)) {
2015-10-20 08:10:39 +01:00
Atom a = AtomOfTerm(t);
pt = NULL;
pe = Yap_GetPredPropByAtom(a, tmod);
2015-10-20 08:10:39 +01:00
arity = 0;
} else if (IsApplTerm(t)) {
Functor f = FunctorOfTerm(t);
2017-04-08 11:29:29 +01:00
2015-10-20 08:10:39 +01:00
if (IsBlobFunctor(f)) {
Yap_Error(TYPE_ERROR_CALLABLE, t, "call/1");
2016-03-29 01:55:12 +01:00
LOCAL_PrologMode &= ~TopGoalMode;
2015-10-20 08:10:39 +01:00
return (FALSE);
}
/* I cannot use the standard macro here because
2016-03-29 01:55:12 +01:00
otherwise I would dereference the argument and
might skip a svar */
pe = Yap_GetPredPropByFunc(f, tmod);
2015-10-20 08:10:39 +01:00
pt = RepAppl(t) + 1;
arity = ArityOfFunctor(f);
} else {
2019-02-27 15:54:20 +00:00
Yap_Error(TYPE_ERROR_CALLABLE, Yap_TermToIndicator(t, tmod), "call/1");
2016-03-29 01:55:12 +01:00
LOCAL_PrologMode &= ~TopGoalMode;
2015-10-20 08:10:39 +01:00
return (FALSE);
}
ppe = RepPredProp(pe);
if (pe == NIL || ppe->cs.p_code.TrueCodeOfPred->opc == UNDEF_OPCODE) {
pe = AbsPredProp(ppe = UndefCode);
pt = HR;
HR[0] = MkPairTerm(tmod, t);
HR[1] = MkAtomTerm(Yap_LookupAtom("top"));
arity = 2;
HR += 2;
2017-07-30 21:53:07 +01:00
} else if (ppe->PredFlags & (MetaPredFlag | UndefPredFlag)) {
// we're in a meta-call, rake care about modules
//
Term ts[2];
ts[0] = tmod;
ts[1] = t;
Functor f = Yap_MkFunctor(Yap_LookupAtom("call"), 1);
2017-04-08 11:29:29 +01:00
pt = &t;
t = Yap_MkApplTerm(FunctorModule, 2, ts);
pe = Yap_GetPredPropByFunc(f, tmod);
ppe = RepPredProp(pe);
arity = 1;
2015-10-20 08:10:39 +01:00
}
PELOCK(82, ppe);
CodeAdr = ppe->CodeOfPred;
UNLOCK(ppe->PELock);
2017-04-08 11:29:29 +01:00
#if !USE_SYSTEM_MALLOC
2015-10-20 08:10:39 +01:00
if (LOCAL_TrailTop - HeapTop < 2048) {
Yap_Error(RESOURCE_ERROR_TRAIL, TermNil,
"unable to boot because of too little Trail space");
}
#endif
2016-03-29 01:55:12 +01:00
goal_out = do_goal(CodeAdr, arity, pt, handle_errors PASS_REGS);
2015-10-20 08:10:39 +01:00
return goal_out;
}
static void do_restore_regs(Term t, int restore_all USES_REGS) {
if (IsApplTerm(t)) {
Int i;
Int max = ArityOfFunctor(FunctorOfTerm(t)) - 4;
CELL *ptr = RepAppl(t) + 5;
2017-04-08 11:29:29 +01:00
2015-10-20 08:10:39 +01:00
P = (yamop *)IntegerOfTerm(ptr[-4]);
CP = (yamop *)IntegerOfTerm(ptr[-3]);
ENV = (CELL *)(LCL0 - IntegerOfTerm(ptr[-2]));
YENV = (CELL *)(LCL0 - IntegerOfTerm(ptr[-1]));
for (i = 0; i < max; i += 2) {
Int j = IntOfTerm(ptr[0]);
XREGS[j] = ptr[1];
ptr += 2;
}
2015-10-20 08:10:39 +01:00
}
}
/* low level voodoo to restore temporary registers after a call */
2015-10-20 08:10:39 +01:00
static Int restore_regs(USES_REGS1) {
Term t = Deref(ARG1);
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, "support for coroutining");
return (FALSE);
}
if (IsAtomTerm(t))
return (TRUE);
do_restore_regs(t, FALSE PASS_REGS);
return (TRUE);
}
2016-03-29 01:55:12 +01:00
/* low level voodoo to cut and then restore temporary registers after
* a
* call */
2015-10-20 08:10:39 +01:00
static Int restore_regs2(USES_REGS1) {
2017-04-08 11:29:29 +01:00
2015-10-20 08:10:39 +01:00
Term t = Deref(ARG1), d0;
choiceptr pt0;
Int d;
2017-04-08 11:29:29 +01:00
2015-10-20 08:10:39 +01:00
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, "support for coroutining");
return (FALSE);
}
d0 = Deref(ARG2);
if (!IsAtomTerm(t)) {
do_restore_regs(t, TRUE PASS_REGS);
}
if (IsVarTerm(d0)) {
Yap_Error(INSTANTIATION_ERROR, d0, "support for coroutining");
return (FALSE);
}
if (!IsIntegerTerm(d0)) {
return (FALSE);
}
d = IntegerOfTerm(d0);
if (!d)
return TRUE;
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
2015-10-20 08:10:39 +01:00
pt0 = (choiceptr)d;
#else
2015-10-20 08:10:39 +01:00
pt0 = (choiceptr)(LCL0 - d);
#endif
2015-10-20 08:10:39 +01:00
/* find where to cut to */
if ((CELL *)pt0 != LCL0 && pt0 > B) {
/* Wow, we're gonna cut!!! */
while (B->cp_b < pt0) {
while (POP_CHOICE_POINT(B->cp_b)) {
POP_EXECUTE();
}
HB = B->cp_h;
Yap_TrimTrail();
B = B->cp_b;
}
#ifdef TABLING
2015-10-20 08:10:39 +01:00
abolish_incomplete_subgoals(B);
#endif
#ifdef YAPOR
2015-10-20 08:10:39 +01:00
CUT_prune_to(pt0);
#endif /* YAPOR */
2015-10-20 08:10:39 +01:00
B = pt0;
}
return (TRUE);
}
static Int clean_ifcp(USES_REGS1) {
Term t = Deref(ARG1);
choiceptr pt0;
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, "cut_at/1");
return FALSE;
}
if (!IsIntegerTerm(t)) {
Yap_Error(TYPE_ERROR_INTEGER, t, "cut_at/1");
return FALSE;
}
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
2015-10-20 08:10:39 +01:00
pt0 = (choiceptr)IntegerOfTerm(t);
#else
2015-10-20 08:10:39 +01:00
pt0 = cp_from_integer(t PASS_REGS);
#endif
2015-10-20 08:10:39 +01:00
if (pt0 < B) {
/* this should never happen */
return TRUE;
2015-10-20 08:10:39 +01:00
} else if (pt0 == B) {
while (POP_CHOICE_POINT(B->cp_b)) {
POP_EXECUTE();
}
B = B->cp_b;
HB = B->cp_h;
} else {
pt0->cp_ap = (yamop *)TRUSTFAILCODE;
}
return TRUE;
}
static int disj_marker(yamop *apc) {
2015-10-20 08:10:39 +01:00
op_numbers opnum = Yap_op_from_opcode(apc->opc);
2015-07-23 01:05:06 +01:00
2015-10-20 08:10:39 +01:00
return opnum == _or_else || opnum == _or_last;
}
2015-10-20 08:10:39 +01:00
static Int cut_up_to_next_disjunction(USES_REGS1) {
choiceptr pt0 = B;
CELL *qenv = (CELL *)ENV[E_E];
2015-10-20 08:10:39 +01:00
while (pt0 && !(qenv == pt0->cp_env && disj_marker(pt0->cp_ap))) {
pt0 = pt0->cp_b;
}
if (!pt0)
return TRUE;
#ifdef YAPOR
2015-10-20 08:10:39 +01:00
CUT_prune_to(pt0);
#endif /* YAPOR */
2015-10-20 08:10:39 +01:00
/* find where to cut to */
if (SHOULD_CUT_UP_TO(B, pt0)) {
B = pt0;
#ifdef TABLING
2015-10-20 08:10:39 +01:00
abolish_incomplete_subgoals(B);
#endif /* TABLING */
2015-10-20 08:10:39 +01:00
}
HB = B->cp_h;
Yap_TrimTrail();
return TRUE;
}
2018-03-29 22:33:53 +01:00
/**
2018-01-18 14:47:27 +00:00
* Reset the Prolog engine . If _Hard_ resèt the global stack_el. If
* p_no_use_'soft_float keei
2018-03-29 22:33:53 +01:00
*
* @param mode
* @param hard
*
* @return
2018-01-18 14:47:27 +00:00
*/
bool Yap_Reset(yap_reset_t mode, bool hard) {
2015-10-20 08:10:39 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
int res = TRUE;
2015-10-20 08:10:39 +01:00
2016-03-29 01:55:12 +01:00
Yap_ResetException(worker_id);
2015-10-20 08:10:39 +01:00
/* first, backtrack to the root */
2018-01-18 14:47:27 +00:00
while (B) {
P = FAILCODE;
Yap_exec_absmi(true, mode);
2015-10-20 08:10:39 +01:00
B = B->cp_b;
}
2015-11-05 16:38:18 +00:00
/* reinitialize the engine */
2018-01-18 14:47:27 +00:00
Yap_InitYaamRegs(worker_id, false);
2015-10-20 08:10:39 +01:00
GLOBAL_Initialised = true;
ENV = LCL0;
ASP = (CELL *)B;
/* the first real choice-point will also have AP=FAIL */
/* always have an empty slots for people to use */
P = CP = YESCODE;
// ensure that we have slots where we need them
Yap_RebootSlots(worker_id);
return res;
}
bool is_cleanup_cp(choiceptr cp_b) {
PredEntry *pe;
if (cp_b->cp_ap->opc != ORLAST_OPCODE)
return FALSE;
#ifdef YAPOR
2015-10-20 08:10:39 +01:00
pe = cp_b->cp_ap->y_u.Osblp.p0;
#else
2015-10-20 08:10:39 +01:00
pe = cp_b->cp_ap->y_u.p.p;
#endif /* YAPOR */
/*
2016-03-29 01:55:12 +01:00
it has to be a cleanup and it has to be a completed goal,
otherwise the throw will be caught anyway.
*/
2015-10-20 08:10:39 +01:00
return pe == PredSafeCallCleanup;
}
2018-04-07 19:45:18 +01:00
static Int JumpToEnv(USES_REGS1) {
choiceptr handler = B;
2016-03-30 17:35:03 +01:00
/* just keep the throwm object away, we don't need to care about it
2016-03-29 01:55:12 +01:00
*/
2015-10-20 08:10:39 +01:00
/* careful, previous step may have caused a stack shift,
2016-03-29 01:55:12 +01:00
so get pointers here */
/* find the first choicepoint that may be a catch */
2016-03-30 17:35:03 +01:00
// DBTerm *dbt = Yap_RefToException();
2018-06-14 11:27:43 +01:00
while (handler && Yap_PredForChoicePt(handler, NULL) != PredDollarCatch &&
LOCAL_CBorder < LCL0 - (CELL *)handler && handler->cp_ap != NOCODE &&
handler->cp_b != NULL) {
2018-04-10 00:54:34 +01:00
handler->cp_ap = TRUSTFAILCODE;
2016-03-30 17:35:03 +01:00
handler = handler->cp_b;
2015-10-20 08:10:39 +01:00
}
if (LOCAL_PrologMode & AsyncIntMode) {
Yap_signal(YAP_FAIL_SIGNAL);
}
2018-03-29 22:33:53 +01:00
2018-04-07 19:45:18 +01:00
B = handler;
2016-03-29 01:55:12 +01:00
P = FAILCODE;
2018-06-25 13:44:09 +01:00
LOCAL_DoingUndefp = false;
2016-03-29 01:55:12 +01:00
return true;
2015-10-20 08:10:39 +01:00
}
2018-04-02 14:49:45 +01:00
bool Yap_JumpToEnv(void) {
2015-10-20 08:10:39 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
if (LOCAL_PrologMode & TopGoalMode)
return true;
2018-04-02 14:49:45 +01:00
return JumpToEnv(PASS_REGS1);
}
/* This does very nasty stuff!!!!! */
2016-03-29 01:55:12 +01:00
static Int jump_env(USES_REGS1) {
2018-04-09 02:00:51 +01:00
Term t = Deref(ARG1), t0 = t;
2018-04-16 14:54:53 +01:00
if (IsVarTerm(t)) {
2018-06-14 11:27:43 +01:00
Yap_ThrowError(INSTANTIATION_ERROR, t,
"throw/1 must be called instantiated");
2018-04-16 14:54:53 +01:00
}
2018-06-14 11:27:43 +01:00
// Yap_DebugPlWriteln(t);
2018-06-26 11:07:07 +01:00
// char *buf = Yap_TermToBuffer(t, ENC_ISO_UTF8,
2018-07-09 00:50:00 +01:00
// Quote_illegal_f | Ignore_ops_f |
// Unfold_cyclics_f);
2018-06-25 13:44:09 +01:00
// __android_log_print(ANDROID_LOG_INFO, "YAPDroid ", " throw(%s)", buf);
2018-06-14 11:27:43 +01:00
LOCAL_ActiveError = Yap_UserError(t0, LOCAL_ActiveError);
2018-04-07 19:45:18 +01:00
bool out = JumpToEnv(PASS_REGS1);
if (B != NULL && P == FAILCODE && B->cp_ap == NOCODE &&
LCL0 - (CELL *)B > LOCAL_CBorder) {
// we're failing up to the top layer
}
2018-07-09 00:50:00 +01:00
pop_text_stack(LOCAL_MallocDepth + 1);
2018-04-07 19:45:18 +01:00
return out;
}
2018-04-07 19:45:18 +01:00
/* set up a meta-call based on . context info */
static Int generate_pred_info(USES_REGS1) {
ARG1 = ARG3 = ENV[-EnvSizeInCells - 1];
ARG4 = ENV[-EnvSizeInCells - 3];
ARG2 = cp_as_integer((choiceptr)ENV[E_CB] PASS_REGS);
return TRUE;
}
2018-04-07 19:45:18 +01:00
void Yap_InitYaamRegs(int myworker_id, bool full_reset) {
Term h0var;
// getchar();
#if PUSH_REGS
2018-04-07 19:45:18 +01:00
/* Guarantee that after a longjmp we go back to the original abstract
machine registers */
#ifdef THREADS
2018-04-07 19:45:18 +01:00
if (myworker_id) {
REGSTORE *rs = REMOTE_ThreadHandle(myworker_id).default_yaam_regs;
pthread_setspecific(Yap_yaamregs_key, (const void *)rs);
REMOTE_ThreadHandle(myworker_id).current_yaam_regs = rs;
}
/* may be run by worker_id on behalf on myworker_id */
#else
2018-04-07 19:45:18 +01:00
Yap_regp = &Yap_standard_regs;
#endif
#endif /* PUSH_REGS */
2018-04-07 19:45:18 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
Yap_ResetException(LOCAL_ActiveError);
2018-04-07 19:45:18 +01:00
Yap_PutValue(AtomBreak, MkIntTerm(0));
TR = (tr_fr_ptr)REMOTE_TrailBase(myworker_id);
2018-06-14 11:27:43 +01:00
HR = H0 = ((CELL *)REMOTE_GlobalBase(myworker_id)) +
1; // +1: hack to ensure the gc does not try to mark mistakenly
2018-04-07 19:45:18 +01:00
LCL0 = ASP = (CELL *)REMOTE_LocalBase(myworker_id);
CurrentTrailTop = (tr_fr_ptr)(REMOTE_TrailTop(myworker_id) - MinTrailGap);
/* notice that an initial choice-point and environment
*must* be created for the garbage collector to work */
B = NULL;
ENV = NULL;
P = CP = YESCODE;
#ifdef DEPTH_LIMIT
2018-04-07 19:45:18 +01:00
DEPTH = RESET_DEPTH();
#endif
2018-04-07 19:45:18 +01:00
STATIC_PREDICATES_MARKED = FALSE;
if (full_reset) {
2019-01-09 09:32:09 +00:00
HB = HR = H0 + 1;
2018-04-07 19:45:18 +01:00
h0var = MkVarTerm();
REMOTE_GcGeneration(myworker_id) = Yap_NewTimedVar(h0var);
REMOTE_GcCurrentPhase(myworker_id) = 0L;
REMOTE_GcPhase(myworker_id) =
2018-06-14 11:27:43 +01:00
Yap_NewTimedVar(MkIntTerm(REMOTE_GcCurrentPhase(myworker_id)));
2018-01-18 14:47:27 +00:00
#if COROUTINING
2018-04-07 19:45:18 +01:00
REMOTE_WokenGoals(myworker_id) = Yap_NewTimedVar(TermNil);
h0var = MkVarTerm();
REMOTE_AttsMutableList(myworker_id) = Yap_NewTimedVar(h0var);
2018-01-18 14:47:27 +00:00
#endif
2019-01-09 09:32:09 +00:00
size_t defsz = 128*1024;
Yap_AllocateDefaultArena(defsz, myworker_id);
2018-04-07 19:45:18 +01:00
} else {
HR = Yap_ArenaLimit(REMOTE_GlobalArena(myworker_id));
}
Yap_InitPreAllocCodeSpace(myworker_id);
#ifdef FROZEN_STACKS
2018-04-07 19:45:18 +01:00
H_FZ = HR;
2011-03-30 15:32:59 +01:00
#ifdef YAPOR_SBA
2018-04-07 19:45:18 +01:00
BSEG =
2011-03-30 15:32:59 +01:00
#endif /* YAPOR_SBA */
2018-06-14 11:27:43 +01:00
BBREG = B_FZ = (choiceptr)REMOTE_LocalBase(myworker_id);
2018-04-07 19:45:18 +01:00
TR = TR_FZ = (tr_fr_ptr)REMOTE_TrailBase(myworker_id);
#endif /* FROZEN_STACKS */
2018-04-07 19:45:18 +01:00
CalculateStackGap(PASS_REGS1);
/* the first real choice-point will also have AP=FAIL */
/* always have an empty slots for people to use */
2012-12-14 22:54:00 +00:00
#if defined(YAPOR) || defined(THREADS)
2018-04-07 19:45:18 +01:00
LOCAL = REMOTE(myworker_id);
worker_id = myworker_id;
2012-12-14 22:54:00 +00:00
#endif /* THREADS */
2018-04-07 19:45:18 +01:00
Yap_RebootSlots(myworker_id);
#if defined(YAPOR) || defined(THREADS)
2018-04-07 19:45:18 +01:00
PP = NULL;
PREG_ADDR = NULL;
#endif
2018-04-07 19:45:18 +01:00
cut_c_initialize(myworker_id);
Yap_PrepGoal(0, NULL, NULL PASS_REGS);
#ifdef FROZEN_STACKS
2018-04-07 19:45:18 +01:00
H_FZ = HR;
#ifdef YAPOR_SBA
2018-04-07 19:45:18 +01:00
BSEG =
#endif /* YAPOR_SBA */
2018-06-14 11:27:43 +01:00
BBREG = B_FZ = (choiceptr)REMOTE_LocalBase(myworker_id);
2018-04-07 19:45:18 +01:00
TR = TR_FZ = (tr_fr_ptr)REMOTE_TrailBase(myworker_id);
#endif /* FROZEN_STACKS */
2018-04-07 19:45:18 +01:00
CalculateStackGap(PASS_REGS1);
2012-04-17 00:21:08 +01:00
#ifdef TABLING
2018-04-07 19:45:18 +01:00
/* ensure that LOCAL_top_dep_fr is always valid */
if (REMOTE_top_dep_fr(myworker_id))
DepFr_cons_cp(REMOTE_top_dep_fr(myworker_id)) = NORM_CP(B);
2012-04-17 00:21:08 +01:00
#endif
2018-04-07 19:45:18 +01:00
}
2018-04-07 19:45:18 +01:00
int Yap_dogc(int extra_args, Term *tp USES_REGS) {
UInt arity;
yamop *nextpc;
int i;
2015-10-20 08:10:39 +01:00
2018-04-07 19:45:18 +01:00
if (P && PREVOP(P, Osbpp)->opc == Yap_opcode(_call_usercpred)) {
arity = PREVOP(P, Osbpp)->y_u.Osbpp.p->ArityOfPE;
nextpc = P;
} else {
arity = 0;
nextpc = CP;
}
for (i = 0; i < extra_args; i++) {
XREGS[arity + i + 1] = tp[i];
2015-10-20 08:10:39 +01:00
}
2018-04-07 19:45:18 +01:00
if (!Yap_gc(arity + extra_args, ENV, nextpc)) {
return FALSE;
}
for (i = 0; i < extra_args; i++) {
tp[i] = XREGS[arity + i + 1];
}
return TRUE;
}
2015-10-20 08:10:39 +01:00
2018-04-07 19:45:18 +01:00
void Yap_InitExecFs(void) {
CACHE_REGS
2018-06-14 11:27:43 +01:00
YAP_opaque_handler_t catcher_ops;
2018-04-07 19:45:18 +01:00
memset(&catcher_ops, 0, sizeof(catcher_ops));
catcher_ops.cut_handler = watch_cut;
catcher_ops.fail_handler = watch_retry;
setup_call_catcher_cleanup_tag = YAP_NewOpaqueType(&catcher_ops);
Term cm = CurrentModule;
Yap_InitComma();
Yap_InitCPred("$execute", 1, execute, 0);
Yap_InitCPred("$execute", 2, execute2, 0);
Yap_InitCPred("$execute", 3, execute3, 0);
Yap_InitCPred("$execute", 4, execute4, 0);
Yap_InitCPred("$execute", 5, execute5, 0);
Yap_InitCPred("$execute", 6, execute6, 0);
Yap_InitCPred("$execute", 7, execute7, 0);
Yap_InitCPred("$execute", 8, execute8, 0);
Yap_InitCPred("$execute", 9, execute9, 0);
Yap_InitCPred("$execute", 10, execute10, 0);
Yap_InitCPred("$execute", 11, execute11, 0);
Yap_InitCPred("$execute", 12, execute12, 0);
Yap_InitCPred("$execute_in_mod", 2, execute_in_mod, 0);
Yap_InitCPred("$execute_wo_mod", 2, execute_in_mod, 0);
Yap_InitCPred("call_with_args", 1, execute_0, 0);
Yap_InitCPred("call_with_args", 2, execute_1, 0);
Yap_InitCPred("call_with_args", 3, execute_2, 0);
Yap_InitCPred("call_with_args", 4, execute_3, 0);
Yap_InitCPred("call_with_args", 5, execute_4, 0);
Yap_InitCPred("call_with_args", 6, execute_5, 0);
Yap_InitCPred("call_with_args", 7, execute_6, 0);
Yap_InitCPred("call_with_args", 8, execute_7, 0);
Yap_InitCPred("call_with_args", 9, execute_8, 0);
Yap_InitCPred("call_with_args", 10, execute_9, 0);
Yap_InitCPred("call_with_args", 11, execute_10, 0);
#ifdef DEPTH_LIMIT
2018-04-07 19:45:18 +01:00
Yap_InitCPred("$execute_under_depth_limit", 2, execute_depth_limit, 0);
#endif
2018-04-07 19:45:18 +01:00
Yap_InitCPred("$execute0", 2, execute0, NoTracePredFlag);
Yap_InitCPred("$execute_nonstop", 2, execute_nonstop, NoTracePredFlag);
2018-04-20 14:59:17 +01:00
Yap_InitCPred("$execute_nonstop", 1, execute_nonstop1, NoTracePredFlag);
2018-04-07 19:45:18 +01:00
Yap_InitCPred("$creep_step", 2, creep_step, NoTracePredFlag);
Yap_InitCPred("$execute_clause", 4, execute_clause, NoTracePredFlag);
Yap_InitCPred("$current_choice_point", 1, current_choice_point, 0);
2018-04-24 08:31:11 +01:00
Yap_InitCPred("$current_choicepoint", 1, current_choice_point, 0);
2018-04-07 19:45:18 +01:00
CurrentModule = HACKS_MODULE;
Yap_InitCPred("current_choice_point", 1, current_choice_point, 0);
Yap_InitCPred("current_choicepoint", 1, current_choice_point, 0);
Yap_InitCPred("env_choice_point", 1, save_env_b, 0);
2019-02-17 23:19:26 +00:00
Yap_InitCPred("parent_choice_point", 1, parent_choice_point1, 0);
Yap_InitCPred("parent_choice_point", 2, parent_choice_point, 0);
2018-04-07 19:45:18 +01:00
Yap_InitCPred("cut_at", 1, clean_ifcp, SafePredFlag);
CurrentModule = cm;
Yap_InitCPred("$restore_regs", 1, restore_regs,
2018-06-14 11:27:43 +01:00
NoTracePredFlag | SafePredFlag);
Yap_InitCPred("$restore_regs", 2, restore_regs2,
NoTracePredFlag | SafePredFlag);
2018-04-07 19:45:18 +01:00
Yap_InitCPred("$clean_ifcp", 1, clean_ifcp, SafePredFlag);
Yap_InitCPred("qpack_clean_up_to_disjunction", 0, cut_up_to_next_disjunction,
2018-06-14 11:27:43 +01:00
SafePredFlag);
2018-04-07 19:45:18 +01:00
Yap_InitCPred("throw", 1, jump_env, 0);
Yap_InitCPred("$generate_pred_info", 4, generate_pred_info, 0);
Yap_InitCPred("_user_expand_goal", 2, _user_expand_goal, 0);
Yap_InitCPred("$do_term_expansion", 2, do_term_expansion, 0);
Yap_InitCPred("$setup_call_catcher_cleanup", 1, setup_call_catcher_cleanup,
2018-06-14 11:27:43 +01:00
0);
2018-04-24 08:31:11 +01:00
Yap_InitCPred("$cleanup_on_exit", 2, cleanup_on_exit, NoTracePredFlag);
2018-04-07 19:45:18 +01:00
Yap_InitCPred("$tag_cleanup", 2, tag_cleanup, 0);
}