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

1988 lines
50 KiB
C
Raw Normal View History

/*************************************************************************
* *
* YAP Prolog *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* *
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
* *
**************************************************************************
* *
* File: exec.c *
* Last rev: 8/2/88 *
* mods: *
* comments: Execute Prolog code *
* *
*************************************************************************/
#ifdef SCCS
static char SccsId[] = "@(#)cdmgr.c 1.1 05/02/98";
#endif
#include "absmi.h"
2013-11-15 01:10:25 +00:00
#include "pl-shared.h"
#include "yapio.h"
#include "attvar.h"
#include "cut_c.h"
2013-04-25 23:15:04 +01:00
static Int CallPredicate(PredEntry *, choiceptr, yamop * CACHE_TYPE);
// must hold thread worker comm lock at call.
2013-04-25 23:15:04 +01:00
static Int EnterCreepMode(Term, Term CACHE_TYPE);
static Int p_save_cp( USES_REGS1 );
static Int p_execute( USES_REGS1 );
static Int p_execute0( USES_REGS1 );
static Term
cp_as_integer(choiceptr cp USES_REGS)
{
return(MkIntegerTerm(LCL0-(CELL *)cp));
}
static choiceptr
cp_from_integer(Term cpt USES_REGS)
{
return (choiceptr)(LCL0-IntegerOfTerm(cpt));
}
Term
Yap_cp_as_integer(choiceptr cp)
{
CACHE_REGS
return cp_as_integer(cp PASS_REGS);
}
static inline Int
CallPredicate(PredEntry *pen, choiceptr cut_pt, yamop *code USES_REGS) {
#ifdef LOW_LEVEL_TRACER
if (Yap_do_low_level_trace)
low_level_trace(enter_pred,pen,XREGS+1);
#endif /* LOW_LEVEL_TRACE */
#ifdef DEPTH_LIMIT
if (DEPTH <= MkIntTerm(1)) {/* I assume Module==0 is prolog */
if (pen->ModuleOfPred) {
if (DEPTH == MkIntTerm(0)) {
UNLOCK(pen->PELock);
return FALSE;
}
else DEPTH = RESET_DEPTH();
}
} else if (pen->ModuleOfPred)
DEPTH -= MkIntConstant(2);
#endif /* DEPTH_LIMIT */
2008-09-01 16:48:05 +01:00
if (P->opc != EXECUTE_CPRED_OP_CODE) {
CP = P;
ENV = YENV;
YENV = ASP;
}
/* make sure we have access to the user given cut */
YENV[E_CB] = (CELL) cut_pt;
P = code;
return TRUE;
}
inline static Int
2012-02-06 11:41:58 +00:00
CallMetaCall(Term t, Term mod USES_REGS) {
ARG1 = t;
ARG2 = cp_as_integer(B PASS_REGS); /* p_save_cp */
2012-02-06 11:41:58 +00:00
ARG3 = t;
if (mod) {
ARG4 = mod;
} else {
ARG4 = TermProlog;
}
return (CallPredicate(PredMetaCall, B, PredMetaCall->CodeOfPred PASS_REGS));
}
Term
Yap_ExecuteCallMetaCall(Term mod) {
CACHE_REGS
Term ts[4];
ts[0] = ARG1;
ts[1] = cp_as_integer(B PASS_REGS); /* p_save_cp */
ts[2] = ARG1;
ts[3] = mod;
return(Yap_MkApplTerm(PredMetaCall->FunctorOfPred,4,ts));
}
static Int
2012-02-06 11:41:58 +00:00
CallError(yap_error_number err, Term t, Term mod USES_REGS)
{
if (yap_flags[LANGUAGE_MODE_FLAG] == 1) {
2012-02-06 11:41:58 +00:00
return(CallMetaCall(t, mod PASS_REGS));
} else {
2012-02-06 11:41:58 +00:00
Yap_Error(err, t, "call/1");
return(FALSE);
}
}
static Int
p_save_cp( USES_REGS1 )
{
Term t = Deref(ARG1);
Term td;
#if SHADOW_HB
register CELL *HBREG = HB;
#endif
if (!IsVarTerm(t)) return(FALSE);
td = cp_as_integer(B PASS_REGS);
YapBind((CELL *)t,td);
return(TRUE);
}
static Int
p_save_env_b( USES_REGS1 )
{
Term t = Deref(ARG1);
Term td;
#if SHADOW_HB
register CELL *HBREG = HB;
#endif
if (!IsVarTerm(t)) return(FALSE);
td = cp_as_integer((choiceptr)YENV[E_CB] PASS_REGS);
YapBind((CELL *)t,td);
return(TRUE);
}
static Int
p_trail_suspension_marker( USES_REGS1 )
{
Term t = Deref(ARG1);
TrailTerm(TR) = AbsPair((CELL*)t);
TR++;
return TRUE;
}
inline static Int
do_execute(Term t, Term mod USES_REGS)
{
2012-02-06 11:41:58 +00:00
Term t0 = t;
/* first do predicate expansion, even before you process signals.
This way you don't get to spy goal_expansion(). */
LOCK(LOCAL_SignalLock);
if (PRED_GOAL_EXPANSION_ALL) {
/* disable creeping when we do goal expansion */
2014-03-06 02:09:48 +00:00
if (!LOCAL_InterruptsDisabled &&
Yap_undo_signal( YAP_CREEP_SIGNAL ) ) {
2013-12-12 14:24:40 +00:00
CalculateStackGap( PASS_REGS1 );
}
UNLOCK(LOCAL_SignalLock);
2012-02-06 11:41:58 +00:00
return CallMetaCall(ARG1, mod PASS_REGS);
2014-03-06 02:09:48 +00:00
} else if (Yap_has_a_signal() &&
!LOCAL_InterruptsDisabled &&
!(LOCAL_PrologMode & (AbortMode|InterruptMode|SystemMode))) {
return EnterCreepMode(t, mod PASS_REGS);
}
UNLOCK(LOCAL_SignalLock);
restart_exec:
if (IsVarTerm(t)) {
2012-02-06 11:41:58 +00:00
return CallError(INSTANTIATION_ERROR, t0, mod PASS_REGS);
} else if (IsApplTerm(t)) {
register Functor f = FunctorOfTerm(t);
register CELL *pt;
PredEntry *pen;
unsigned int i, arity;
f = FunctorOfTerm(t);
if (IsExtensionFunctor(f)) {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod PASS_REGS);
}
arity = ArityOfFunctor(f);
if (arity > MaxTemps) {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod PASS_REGS);
}
pen = RepPredProp(PredPropByFunc(f, mod));
/* You thought we would be over by now */
/* but no meta calls require special preprocessing */
if (pen->PredFlags & (GoalExPredFlag|MetaPredFlag)) {
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)) {
2012-02-06 11:41:58 +00:00
return CallError(INSTANTIATION_ERROR, t0, mod PASS_REGS);
} else {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_ATOM, t0, mod PASS_REGS);
}
}
} else {
2012-02-06 11:41:58 +00:00
return CallMetaCall(t, mod PASS_REGS);
}
}
/* now let us do what we wanted to do from the beginning !! */
/* 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++) {
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
Term d0 = *pt++;
if (d0 == 0)
` XREGS[i] = (CELL)(pt-1);
else
XREGS[i] = d0;
#else
XREGS[i] = *pt++;
#endif
}
return (CallPredicate(pen, B, pen->CodeOfPred PASS_REGS));
} else if (IsAtomTerm(t)) {
PredEntry *pe;
Atom a = AtomOfTerm(t);
if (a == AtomTrue || a == AtomOtherwise || a == AtomCut)
return(TRUE);
2012-10-19 18:10:48 +01:00
else if (a == AtomFail || (a == AtomFalse && !RepPredProp(PredPropByAtom(a, mod))->ModuleOfPred) )
return(FALSE);
/* call may not define new system predicates!! */
pe = RepPredProp(PredPropByAtom(a, mod));
return (CallPredicate(pe, B, pe->CodeOfPred PASS_REGS));
} else if (IsIntTerm(t)) {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod PASS_REGS);
} else {
/* Is Pair Term */
2012-02-06 11:41:58 +00:00
return(CallMetaCall(t, mod PASS_REGS));
}
}
static Term
copy_execn_to_heap(Functor f, CELL *pt, unsigned int n, unsigned int arity, Term mod USES_REGS)
{
2014-01-19 21:15:05 +00:00
CELL *h0 = HR;
Term tf;
unsigned int i;
if (arity == 2 &&
NameOfFunctor(f) == AtomDot) {
for (i = 0; i<arity-n;i++) {
2014-01-19 21:15:05 +00:00
*HR++ = pt[i];
}
for (i=0; i< n; i++) {
2014-01-19 21:15:05 +00:00
*HR++ = h0[(int)(i-n)];
}
tf = AbsPair(h0);
} else {
2014-01-19 21:15:05 +00:00
*HR++ = (CELL)f;
for (i = 0; i<arity-n;i++) {
2014-01-19 21:15:05 +00:00
*HR++ = pt[i];
}
for (i=0; i< n; i++) {
2014-01-19 21:15:05 +00:00
*HR++ = h0[(int)(i-n)];
}
tf = AbsAppl(h0);
}
if (mod != CurrentModule) {
2014-01-19 21:15:05 +00:00
CELL *h0 = HR;
*HR++ = (CELL)FunctorModule;
*HR++ = mod;
*HR++ = tf;
tf = AbsAppl(h0);
}
return tf;
}
inline static Int
do_execute_n(Term t, Term mod, unsigned int n USES_REGS)
{
Functor f;
Atom Name;
register CELL *pt;
PredEntry *pen;
unsigned int i, arity;
int j = -n;
2012-02-06 11:41:58 +00:00
Term t0 = t;
restart_exec:
if (IsVarTerm(t)) {
2012-02-06 11:41:58 +00:00
return CallError(INSTANTIATION_ERROR, t0, mod PASS_REGS);
} else if (IsAtomTerm(t)) {
arity = n;
Name = AtomOfTerm(t);
pt = NULL;
} else if (IsIntTerm(t)) {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod PASS_REGS);
} 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)) {
2012-02-06 11:41:58 +00:00
return CallError(INSTANTIATION_ERROR, t0, tmod PASS_REGS);
} else {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_ATOM, t0, tmod PASS_REGS);
}
}
}
arity = ArityOfFunctor(f)+n;
Name = NameOfFunctor(f);
pt = RepAppl(t)+1;
}
f = Yap_MkFunctor(Name,arity);
if (IsExtensionFunctor(f)) {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod PASS_REGS);
}
LOCK(LOCAL_SignalLock);
if (PRED_GOAL_EXPANSION_ALL) {
/* disable creeping when we do goal expansion */
2014-03-06 02:09:48 +00:00
if (Yap_has_signal( YAP_CREEP_SIGNAL ) &&
!LOCAL_InterruptsDisabled) {
Yap_undo_signal( YAP_CREEP_SIGNAL );
2013-12-12 14:24:40 +00:00
CalculateStackGap( PASS_REGS1 );
}
2012-02-06 11:41:58 +00:00
t = copy_execn_to_heap(f, pt, n, arity, mod PASS_REGS);
UNLOCK(LOCAL_SignalLock);
return CallMetaCall(t, mod PASS_REGS);
2014-03-06 02:09:48 +00:00
} else if (Yap_has_a_signal() &&
!LOCAL_InterruptsDisabled) {
return EnterCreepMode(copy_execn_to_heap(f, pt, n, arity, CurrentModule PASS_REGS), mod PASS_REGS);
}
UNLOCK(LOCAL_SignalLock);
if (arity > MaxTemps) {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, mod PASS_REGS);
}
pen = RepPredProp(PredPropByFunc(f, mod));
/* You thought we would be over by now */
/* but no meta calls require special preprocessing */
if (pen->PredFlags & (GoalExPredFlag|MetaPredFlag)) {
2012-02-06 11:41:58 +00:00
Term t = copy_execn_to_heap(f, pt, n, arity, mod PASS_REGS);
return(CallMetaCall(t, mod PASS_REGS));
}
/* now let us do what we wanted to do from the beginning !! */
/* I cannot use the standard macro here because
otherwise I would dereference the argument and
might skip a svar */
for (i = 1; i <= arity-n; i++) {
2011-03-30 15:32:59 +01:00
#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++) {
2014-01-19 21:15:05 +00:00
XREGS[i] = HR[j];
}
return CallPredicate(pen, B, pen->CodeOfPred PASS_REGS);
}
// enter locked
static Int
EnterCreepMode(Term t, Term mod USES_REGS) {
PredEntry *PredCreep;
2014-03-06 02:09:48 +00:00
if (Yap_has_signal( YAP_CDOVF_SIGNAL ) ) {
ARG1 = t;
if (!Yap_locked_growheap(FALSE, 0, NULL)) {
Yap_Error(OUT_OF_HEAP_ERROR, TermNil, "YAP failed to grow heap at meta-call");
}
2014-03-06 02:09:48 +00:00
if (!Yap_has_a_signal()) {
UNLOCK(LOCAL_SignalLock);
return do_execute(ARG1, mod PASS_REGS);
}
}
PredCreep = RepPredProp(PredPropByFunc(FunctorCreep,1));
2013-02-08 16:36:45 +00:00
PP = PredCreep;
if (!IsVarTerm(t) && IsApplTerm(t) && FunctorOfTerm(t) == FunctorModule) {
ARG1 = MkPairTerm(ArgOfTerm(1,t),ArgOfTerm(2,t));
} else {
2013-02-08 16:36:45 +00:00
if (mod) {
ARG1 = MkPairTerm(mod,t);
} else {
ARG1 = MkPairTerm(TermProlog,t);
}
}
2013-12-12 14:24:40 +00:00
CalculateStackGap( PASS_REGS1 );
2011-05-04 10:11:41 +01:00
UNLOCK(LOCAL_SignalLock);
P_before_spy = P;
return CallPredicate(PredCreep, B, PredCreep->CodeOfPred PASS_REGS);
}
static Int
p_execute( USES_REGS1 )
{ /* '$execute'(Goal) */
Term t = Deref(ARG1);
return do_execute(t, CurrentModule PASS_REGS);
}
static void
heap_store(Term t USES_REGS)
{
if (IsVarTerm(t)) {
2014-01-19 21:15:05 +00:00
if (VarOfTerm(t) < HR) {
*HR++ = t;
} else {
2014-01-19 21:15:05 +00:00
RESET_VARIABLE(HR);
Bind_Local(VarOfTerm(t), (CELL)HR);
HR++;
}
} else {
2014-01-19 21:15:05 +00:00
*HR++ = t;
}
}
static Int
p_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
p_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
p_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
p_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
p_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
p_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
p_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
p_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
p_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
p_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
p_execute12( 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);
heap_store(Deref(ARG12) PASS_REGS);
return(do_execute_n(t, CurrentModule, 11 PASS_REGS));
}
static Int
p_execute_clause( USES_REGS1 )
{ /* '$execute_clause'(Goal) */
2012-02-06 11:41:58 +00:00
Term t = Deref(ARG1), t0 = t;
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);
restart_exec:
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) {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, 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) {
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
Term d0 = *pt++;
if (d0 == 0)
XREGS[i] = (CELL)(pt-1);
else
XREGS[i] = d0;
#else
XREGS[i] = *pt++;
#endif
}
} else {
Yap_Error(TYPE_ERROR_CALLABLE,ARG3,"call/1");
return FALSE;
}
/* N = arity; */
/* call may not define new system predicates!! */
if (RepPredProp(pe)->PredFlags & MegaClausePredFlag) {
code = Yap_MegaClauseFromTerm(clt);
} else {
code = Yap_ClauseFromTerm(clt)->ClCode;
}
LOCK(LOCAL_SignalLock);
2014-03-06 02:09:48 +00:00
if (Yap_undo_signal(YAP_CREEP_SIGNAL)) {
Yap_signal(YAP_CREEP_SIGNAL);
}
UNLOCK(LOCAL_SignalLock);
return CallPredicate(RepPredProp(pe), cut_cp, code PASS_REGS);
}
static Int
p_execute_in_mod( USES_REGS1 )
{ /* '$execute'(Goal) */
return(do_execute(Deref(ARG1), Deref(ARG2) PASS_REGS));
}
static Int
p_do_goal_expansion( USES_REGS1 )
{
2014-03-06 02:09:48 +00:00
Int creeping = Yap_has_signal(YAP_CREEP_SIGNAL);
Int out = FALSE;
PredEntry *pe;
Term cmod = Deref(ARG2);
ARG2 = ARG3;
if (creeping) {
LOCK(LOCAL_SignalLock);
2014-03-06 02:09:48 +00:00
Yap_undo_signal(YAP_CREEP_SIGNAL);
UNLOCK(LOCAL_SignalLock);
}
/* CurMod:goal_expansion(A,B) */
if ( (pe = RepPredProp(Yap_GetPredPropByFunc(FunctorGoalExpansion2, cmod) ) ) &&
pe->OpcodeOfPred != FAIL_OPCODE &&
pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL PASS_REGS) ) {
out = TRUE;
ARG3 = ARG2;
goto complete;
}
/* system:goal_expansion(A,B) */
if ( (pe = RepPredProp(Yap_GetPredPropByFunc(FunctorGoalExpansion2, SYSTEM_MODULE ) ) ) &&
pe->OpcodeOfPred != FAIL_OPCODE &&
pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL PASS_REGS) ) {
out = TRUE;
ARG3 = ARG2;
goto complete;
}
ARG3 = ARG2;
ARG2 = cmod;
/* user:goal_expansion(A,CurMod,B) */
if ( (pe = RepPredProp(Yap_GetPredPropByFunc(FunctorGoalExpansion, USER_MODULE ) ) ) &&
pe->OpcodeOfPred != FAIL_OPCODE &&
pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL PASS_REGS) ) {
out = TRUE;
goto complete;
}
ARG2 = ARG3;
/* user:goal_expansion(A,B) */
if ( cmod != USER_MODULE && /* we have tried this before */
(pe = RepPredProp(Yap_GetPredPropByFunc(FunctorGoalExpansion2, USER_MODULE ) ) ) &&
pe->OpcodeOfPred != FAIL_OPCODE &&
pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL PASS_REGS) ) {
ARG3 = ARG2;
out = TRUE;
}
complete:
LOCK(LOCAL_SignalLock);
if (creeping) {
2014-03-06 02:09:48 +00:00
Yap_signal( YAP_CREEP_SIGNAL );
}
UNLOCK(LOCAL_SignalLock);
return out;
}
static Int
p_do_term_expansion( USES_REGS1 )
{
LOCK(LOCAL_SignalLock);
2014-03-06 02:09:48 +00:00
Int creeping = Yap_has_signal(YAP_CREEP_SIGNAL);
Int out = FALSE;
PredEntry *pe;
Term cmod = CurrentModule;
/* disable creeping */
2014-03-06 02:09:48 +00:00
if (creeping)
Yap_undo_signal(YAP_CREEP_SIGNAL);
UNLOCK(LOCAL_SignalLock);
/* CurMod:term_expansion(A,B) */
if ( (pe = RepPredProp(Yap_GetPredPropByFunc(FunctorTermExpansion, cmod) ) ) &&
pe->OpcodeOfPred != FAIL_OPCODE &&
pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL PASS_REGS) ) {
out = TRUE;
goto complete;
}
/* system:term_expansion(A,B) */
if ( (pe = RepPredProp(Yap_GetPredPropByFunc(FunctorTermExpansion, SYSTEM_MODULE ) ) ) &&
pe->OpcodeOfPred != FAIL_OPCODE &&
pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL PASS_REGS) ) {
out = TRUE;
goto complete;
}
/* user:term_expansion(A,B) */
if ( cmod != USER_MODULE && /* we have tried this before */
(pe = RepPredProp(Yap_GetPredPropByFunc(FunctorTermExpansion, USER_MODULE ) ) ) &&
pe->OpcodeOfPred != FAIL_OPCODE &&
pe->OpcodeOfPred != UNDEF_OPCODE &&
Yap_execute_pred(pe, NULL PASS_REGS) ) {
out = TRUE;
}
complete:
LOCK(LOCAL_SignalLock);
if (creeping) {
2014-03-06 02:09:48 +00:00
Yap_signal(YAP_CREEP_SIGNAL);
}
UNLOCK(LOCAL_SignalLock);
return out;
}
static Int
p_execute0( USES_REGS1 )
{ /* '$execute0'(Goal,Mod) */
2012-02-06 11:41:58 +00:00
Term t = Deref(ARG1), t0 = t;
Term mod = Deref(ARG2);
unsigned int arity;
Prop pe;
LOCK(LOCAL_SignalLock);
2014-03-06 02:09:48 +00:00
if (Yap_has_a_signal() &&
!LOCAL_InterruptsDisabled) {
return EnterCreepMode(t, mod PASS_REGS);
}
UNLOCK(LOCAL_SignalLock);
restart_exec:
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;
} else {
if (IsVarTerm(tmod)) {
2012-02-06 11:41:58 +00:00
return CallError(INSTANTIATION_ERROR, t0, mod PASS_REGS);
} else {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_ATOM, t0, mod PASS_REGS);
}
}
}
pe = PredPropByFunc(f, mod);
// Yap_DebugPlWrite(mod);fprintf(stderr,"\n");
arity = ArityOfFunctor(f);
if (arity > MaxTemps) {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, 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) {
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
Term d0 = *pt++;
if (d0 == 0)
XREGS[i] = (CELL)(pt-1);
else
XREGS[i] = d0;
#else
XREGS[i] = *pt++;
#endif
}
} else {
Yap_Error(TYPE_ERROR_CALLABLE,ARG1,"call/1");
return FALSE;
}
/* N = arity; */
/* call may not define new system predicates!! */
return CallPredicate(RepPredProp(pe), B, RepPredProp(pe)->CodeOfPred PASS_REGS);
}
static Int
p_execute_nonstop( USES_REGS1 )
{ /* '$execute_nonstop'(Goal,Mod) */
2012-02-06 11:41:58 +00:00
Term t = Deref(ARG1), t0 = t;
Term mod = Deref(ARG2);
unsigned int arity;
Prop pe;
restart_exec:
2010-02-25 17:52:11 +00:00
if (IsVarTerm(mod)) {
mod = CurrentModule;
} else if (!IsAtomTerm(mod)) {
Yap_Error(TYPE_ERROR_ATOM, ARG2, "call/1");
return FALSE;
}
if (IsVarTerm(t)) {
2010-02-25 17:52:11 +00:00
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);
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)) {
2012-02-06 11:41:58 +00:00
return CallError(INSTANTIATION_ERROR, t0, mod PASS_REGS);
} else {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_ATOM, t0, mod PASS_REGS);
}
}
}
pe = PredPropByFunc(f, mod);
arity = ArityOfFunctor(f);
if (arity > MaxTemps) {
2012-02-06 11:41:58 +00:00
return CallError(TYPE_ERROR_CALLABLE, t0, 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) {
2011-03-30 15:32:59 +01:00
#if YAPOR_SBA
Term d0 = *pt++;
if (d0 == 0)
XREGS[i] = (CELL)(pt-1);
else
XREGS[i] = d0;
#else
XREGS[i] = *pt++;
#endif
}
} else {
Yap_Error(TYPE_ERROR_CALLABLE,ARG3,"call/1");
return FALSE;
}
/* N = arity; */
/* call may not define new system predicates!! */
LOCK(LOCAL_SignalLock);
if (RepPredProp(pe)->PredFlags & SpiedPredFlag) {
2014-03-06 02:09:48 +00:00
if (!LOCAL_InterruptsDisabled &&
Yap_undo_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);
}
UNLOCK(LOCAL_SignalLock);
#endif
return CallPredicate(RepPredProp(pe), B, RepPredProp(pe)->cs.p_code.TrueCodeOfPred PASS_REGS);
2014-03-06 02:09:48 +00:00
} else { if (Yap_has_signal( YAP_CREEP_SIGNAL ) &&
2011-05-04 10:11:41 +01:00
!LOCAL_InterruptsDisabled &&
(!(RepPredProp(pe)->PredFlags & (AsmPredFlag|CPredFlag)) ||
RepPredProp(pe)->OpcodeOfPred == Yap_opcode(_call_bfunc_xx))) {
Yap_signal(YAP_CREEP_SIGNAL);
}
UNLOCK(LOCAL_SignalLock);
return CallPredicate(RepPredProp(pe), B, RepPredProp(pe)->CodeOfPred PASS_REGS);
}
}
static Term
slice_module_for_call_with_args(Term tin, Term *modp, int arity)
{
if (IsVarTerm(tin)) {
Yap_Error(INSTANTIATION_ERROR,tin,"call_with_args/%d", arity);
return 0L;
}
while (IsApplTerm(tin)) {
Functor f = FunctorOfTerm(tin);
Term newmod;
if (f != FunctorModule) {
Yap_Error(TYPE_ERROR_ATOM,tin,"call_with_args/%d", arity);
return 0L;
}
newmod = ArgOfTerm(1,tin);
if (IsVarTerm(newmod)) {
Yap_Error(INSTANTIATION_ERROR,tin,"call_with_args/%d",arity);
return 0L;
} else if (!IsAtomTerm(newmod)) {
Yap_Error(TYPE_ERROR_ATOM,newmod,"call_with_args/%d",arity);
return 0L;
}
*modp = newmod;
tin = ArgOfTerm(2,tin);
}
if (!IsAtomTerm(tin)) {
Yap_Error(TYPE_ERROR_ATOM,tin,"call_with_args/%d",arity);
return 0L;
}
return tin;
}
static Int
p_execute_0( USES_REGS1 )
{ /* '$execute_0'(Goal) */
Term mod = CurrentModule;
Term t = slice_module_for_call_with_args(Deref(ARG1),&mod,0);
if (!t)
return FALSE;
return do_execute(t, mod PASS_REGS);
}
static Int
call_with_args(int i USES_REGS)
{
Term mod = CurrentModule, t;
int j;
t = slice_module_for_call_with_args(Deref(ARG1),&mod,i);
if (!t)
return FALSE;
for (j=0;j<i;j++)
heap_store(Deref(XREGS[j+2]) PASS_REGS);
return(do_execute_n(t, mod, i PASS_REGS));
}
static Int
p_execute_1( USES_REGS1 )
{ /* '$execute_0'(Goal) */
return call_with_args(1 PASS_REGS);
}
static Int
p_execute_2( USES_REGS1 )
{ /* '$execute_2'(Goal) */
return call_with_args(2 PASS_REGS);
}
static Int
p_execute_3( USES_REGS1 )
{ /* '$execute_3'(Goal) */
return call_with_args(3 PASS_REGS);
}
static Int
p_execute_4( USES_REGS1 )
{ /* '$execute_4'(Goal) */
return call_with_args(4 PASS_REGS);
}
static Int
p_execute_5( USES_REGS1 )
{ /* '$execute_5'(Goal) */
return call_with_args(5 PASS_REGS);
}
static Int
p_execute_6( USES_REGS1 )
{ /* '$execute_6'(Goal) */
return call_with_args(6 PASS_REGS);
}
static Int
p_execute_7( USES_REGS1 )
{ /* '$execute_7'(Goal) */
return call_with_args(7 PASS_REGS);
}
static Int
p_execute_8( USES_REGS1 )
{ /* '$execute_8'(Goal) */
return call_with_args(8 PASS_REGS);
}
static Int
p_execute_9( USES_REGS1 )
{ /* '$execute_9'(Goal) */
return call_with_args(9 PASS_REGS);
}
static Int
p_execute_10( USES_REGS1 )
{ /* '$execute_10'(Goal) */
return call_with_args(10 PASS_REGS);
}
#ifdef DEPTH_LIMIT
static Int
p_execute_depth_limit( USES_REGS1 ) {
Term d = Deref(ARG2);
if (IsVarTerm(d)) {
Yap_Error(INSTANTIATION_ERROR,d,"depth_bound_call/2");
2013-01-28 23:21:54 +00:00
return FALSE;
} else if (!IsIntegerTerm(d)) {
if (IsFloatTerm(d) && isinf(FloatOfTerm(d))) {
DEPTH = RESET_DEPTH();
} else {
Yap_Error(TYPE_ERROR_INTEGER, d, "depth_bound_call/2");
return FALSE;
}
} else {
DEPTH = MkIntTerm(IntegerOfTerm(d)*2);
}
2013-01-28 23:21:54 +00:00
return p_execute( PASS_REGS1 );
}
#endif
static Int
p_pred_goal_expansion_on( USES_REGS1 ) {
/* a goal needs expansion if we have goal_expansion defined or
if the goal is a meta-call */
return PRED_GOAL_EXPANSION_ON;
}
static Int
exec_absmi(int top USES_REGS)
{
int lval, out;
if (top && (lval = sigsetjmp (LOCAL_RestartEnv, 1)) != 0) {
switch(lval) {
case 1:
{ /* restart */
/* otherwise, SetDBForThrow will fail entering critical mode */
LOCAL_PrologMode = UserMode;
/* 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 */
ASP = (CELL *)PROTECT_FROZEN_B(B);
2011-05-04 10:11:41 +01:00
LOCK(LOCAL_SignalLock);
/* forget any signals active, we're reborne */
2014-03-06 02:09:48 +00:00
LOCAL_FirstActiveSignal = LOCAL_LastActiveSignal;
2013-12-12 14:24:40 +00:00
CalculateStackGap( PASS_REGS1 );
LOCAL_PrologMode = UserMode;
2011-05-04 10:11:41 +01:00
UNLOCK(LOCAL_SignalLock);
P = (yamop *)FAILCODE;
}
break;
case 2:
{
/* arithmetic exception */
/* must be done here, otherwise siglongjmp will clobber all the registers */
Yap_Error(LOCAL_matherror ,TermNil,NULL);
/* reset the registers so that we don't have trash in abstract machine */
Yap_set_fpu_exceptions(yap_flags[LANGUAGE_MODE_FLAG] == 1);
P = (yamop *)FAILCODE;
LOCAL_PrologMode = UserMode;
}
break;
case 3:
{ /* saved state */
2011-08-31 21:54:19 +01:00
return FALSE;
}
default:
/* do nothing */
LOCAL_PrologMode = UserMode;
}
} else {
LOCAL_PrologMode = UserMode;
}
2010-12-13 20:39:12 +00:00
YENV = ASP;
YENV[E_CB] = Unsigned (B);
out = Yap_absmi(0);
/* make sure we don't leave a FAIL signal hanging around */
LOCK(LOCAL_SignalLock);
2014-03-06 02:09:48 +00:00
Yap_undo_signal( YAP_FAIL_SIGNAL );
if (!Yap_has_a_signal())
2013-12-12 14:24:40 +00:00
CalculateStackGap( PASS_REGS1 );
UNLOCK(LOCAL_SignalLock);
return out;
}
void
Yap_PrepGoal(UInt arity, CELL *pt, choiceptr saved_b USES_REGS)
{
/* create an initial pseudo environment so that when garbage
collection is going up in the environment chain it doesn't get
confused */
EX = NULL;
// sl = Yap_InitSlot(t);
YENV = ASP;
YENV[E_CP] = (CELL)P;
YENV[E_CB] = (CELL)B;
YENV[E_E] = (CELL)ENV;
2011-04-15 23:05:03 +01:00
#ifdef TABLING
YENV[E_B] = (CELL)B;
#endif
#ifdef DEPTH_LIMIT
YENV[E_DEPTH] = DEPTH;
#endif
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--;
2014-01-19 21:15:05 +00:00
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
B->cp_depth = DEPTH;
#endif /* DEPTH_LIMIT */
YENV = ASP = (CELL *)B;
YENV[E_CB] = (CELL)B;
2014-01-19 21:15:05 +00:00
HB = HR;
2010-12-13 20:39:12 +00:00
CP = YESCODE;
}
static Int
do_goal(yamop *CodeAdr, int arity, CELL *pt, int top USES_REGS)
{
choiceptr saved_b = B;
Int out;
Yap_PrepGoal(arity, pt, saved_b PASS_REGS);
P = (yamop *) CodeAdr;
S = CellPtr (RepPredProp (PredPropByFunc (Yap_MkFunctor(AtomCall, 1),0))); /* A1 mishaps */
out = exec_absmi(top PASS_REGS);
2012-04-12 23:52:25 +01:00
Yap_flush();
// if (out) {
// out = Yap_GetFromSlot(sl);
// }
// Yap_RecoverSlots(1);
return out;
}
Int
Yap_exec_absmi(int top)
{
CACHE_REGS
return exec_absmi(top PASS_REGS);
}
int
Yap_execute_pred(PredEntry *ppe, CELL *pt USES_REGS)
{
yamop *saved_p, *saved_cp;
yamop *CodeAdr;
Int out;
saved_p = P;
saved_cp = CP;
PELOCK(81,ppe);
CodeAdr = ppe->CodeOfPred;
UNLOCK(ppe->PELock);
out = do_goal(CodeAdr, ppe->ArityOfPE, pt, FALSE PASS_REGS);
if (out == 1) {
2011-12-22 10:27:56 +00:00
choiceptr cut_B;
/* we succeeded, let's prune */
/* restore the old environment */
/* get to previous environment */
cut_B = (choiceptr)ENV[E_CB];
{
/* Note that
cut_B == (choiceptr)ENV[E_CB] */
while (POP_CHOICE_POINT(ENV[E_CB]))
{
POP_EXECUTE();
}
}
#ifdef YAPOR
CUT_prune_to(cut_B);
#endif /* YAPOR */
#ifdef TABLING
if (B != cut_B) {
while (B->cp_b < cut_B) {
B = B->cp_b;
}
#ifdef TABLING
abolish_incomplete_subgoals(B);
#endif
}
#endif /* TABLING */
B = cut_B;
CP = saved_cp;
P = saved_p;
ASP = ENV;
#ifdef DEPTH_LIMIT
DEPTH= ENV[E_DEPTH];
#endif
ENV = (CELL *)(ENV[E_E]);
/* we have failed, and usually we would backtrack to this B,
trouble is, we may also have a delayed cut to do */
if (B != NULL)
HB = B->cp_h;
YENV = ENV;
2013-01-19 22:13:43 +00:00
return TRUE;
} else if (out == 0) {
P = saved_p;
CP = saved_cp;
2014-01-19 21:15:05 +00:00
HR = B->cp_h;
#ifdef DEPTH_LIMIT
DEPTH= B->cp_depth;
#endif
/* ASP should be set to the top of the local stack when we
did the call */
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);
return(FALSE);
} else {
Yap_Error(SYSTEM_ERROR,TermNil,"emulator crashed");
return(FALSE);
}
}
Int
Yap_execute_goal(Term t, int nargs, Term mod)
{
CACHE_REGS
Prop pe;
PredEntry *ppe;
CELL *pt;
/* preserve the current restart environment */
/* visualc*/
/* just keep the difference because of possible garbage collections */
if (IsAtomTerm(t)) {
Atom a = AtomOfTerm(t);
pt = NULL;
pe = PredPropByAtom(a, mod);
} else if (IsApplTerm(t)) {
Functor f = FunctorOfTerm(t);
if (IsBlobFunctor(f)) {
Yap_Error(TYPE_ERROR_CALLABLE,t,"call/1");
return(FALSE);
}
/* I cannot use the standard macro here because
otherwise I would dereference the argument and
might skip a svar */
pt = RepAppl(t)+1;
pe = PredPropByFunc(f, mod);
} else {
Yap_Error(TYPE_ERROR_CALLABLE,t,"call/1");
return(FALSE);
}
ppe = RepPredProp(pe);
if (pe == NIL) {
return CallMetaCall(t, mod PASS_REGS);
}
return Yap_execute_pred(ppe, pt PASS_REGS);
}
void
Yap_trust_last(void)
{
CACHE_REGS
ASP = B->cp_env;
CP = B->cp_cp;
2014-01-19 21:15:05 +00:00
HR = B->cp_h;
#ifdef DEPTH_LIMIT
DEPTH= B->cp_depth;
#endif
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);
}
}
Term
Yap_RunTopGoal(Term t)
{
CACHE_REGS
yamop *CodeAdr;
Prop pe;
PredEntry *ppe;
CELL *pt;
UInt arity;
Term mod = CurrentModule;
Term goal_out = 0;
restart_runtopgoal:
if (IsAtomTerm(t)) {
Atom a = AtomOfTerm(t);
pt = NULL;
pe = PredPropByAtom(a, CurrentModule);
arity = 0;
} else if (IsApplTerm(t)) {
Functor f = FunctorOfTerm(t);
if (IsBlobFunctor(f)) {
Yap_Error(TYPE_ERROR_CALLABLE,t,"call/1");
return(FALSE);
}
if (f == FunctorModule) {
Term tmod = ArgOfTerm(1,t);
if (!IsVarTerm(tmod) && IsAtomTerm(tmod)) {
mod = tmod;
t = ArgOfTerm(2,t);
goto restart_runtopgoal;
} else {
if (IsVarTerm(tmod)) {
Yap_Error(INSTANTIATION_ERROR,t,"call/1");
} else {
Yap_Error(TYPE_ERROR_ATOM,t,"call/1");
}
return FALSE;
}
}
/* I cannot use the standard macro here because
otherwise I would dereference the argument and
might skip a svar */
2011-12-13 22:20:28 +00:00
pe = PredPropByFunc(f, mod);
pt = RepAppl(t)+1;
arity = ArityOfFunctor(f);
} else {
Yap_Error(TYPE_ERROR_CALLABLE,t,"call/1");
return(FALSE);
}
ppe = RepPredProp(pe);
if (pe == NIL) {
/* we must always start the emulator with Prolog code */
return FALSE;
}
PELOCK(82,ppe);
CodeAdr = ppe->CodeOfPred;
UNLOCK(ppe->PELock);
#if !USE_SYSTEM_MALLOC
if (LOCAL_TrailTop - HeapTop < 2048) {
LOCAL_PrologMode = BootMode;
Yap_Error(OUT_OF_TRAIL_ERROR,TermNil,
"unable to boot because of too little Trail space");
}
#endif
goal_out = do_goal(CodeAdr, arity, pt, TRUE PASS_REGS);
return goal_out;
}
static void
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;
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;
}
}
}
/* low level voodoo to restore temporary registers after a call */
static Int
p_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);
restore_regs(t, FALSE PASS_REGS);
return(TRUE);
}
/* low level voodoo to cut and then restore temporary registers after a call */
static Int
p_restore_regs2( USES_REGS1 )
{
Term t = Deref(ARG1), d0;
choiceptr pt0;
Int d;
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR,t,"support for coroutining");
return(FALSE);
}
d0 = Deref(ARG2);
if (!IsAtomTerm(t)) {
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
pt0 = (choiceptr)d;
#else
pt0 = (choiceptr)(LCL0-d);
#endif
/* 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
abolish_incomplete_subgoals(B);
#endif
#ifdef YAPOR
CUT_prune_to(pt0);
#endif /* YAPOR */
B = pt0;
}
return(TRUE);
}
static Int
p_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
pt0 = (choiceptr)IntegerOfTerm(t);
#else
pt0 = cp_from_integer(t PASS_REGS);
#endif
if (pt0 < B) {
/* this should never happen */
return TRUE;
} 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) {
op_numbers opnum = Yap_op_from_opcode(apc->opc);
return opnum == _or_else || opnum == _or_last;
}
static Int
p_cut_up_to_next_disjunction( USES_REGS1 ) {
choiceptr pt0 = B;
CELL *qenv = (CELL *)ENV[E_E];
while (pt0 &&
!( qenv == pt0->cp_env && disj_marker(pt0->cp_ap))) {
pt0 = pt0->cp_b;
}
if (!pt0)
return TRUE;
#ifdef YAPOR
CUT_prune_to(pt0);
#endif /* YAPOR */
/* find where to cut to */
if (SHOULD_CUT_UP_TO(B,pt0)) {
B = pt0;
#ifdef TABLING
abolish_incomplete_subgoals(B);
#endif /* TABLING */
}
HB = B->cp_h;
Yap_TrimTrail();
return TRUE;
}
static int is_cleanup_cp(choiceptr cp_b)
{
PredEntry *pe;
if (cp_b->cp_ap->opc != ORLAST_OPCODE)
return FALSE;
#ifdef YAPOR
2014-05-30 01:06:09 +01:00
pe = cp_b->cp_ap->y_u.Osblp.p0;
#else
2014-05-30 01:06:09 +01:00
pe = cp_b->cp_ap->y_u.p.p;
#endif /* YAPOR */
2009-12-03 02:13:22 +00:00
/*
it has to be a cleanup and it has to be a completed goal,
otherwise the throw will be caught anyway.
*/
return pe == PredSafeCallCleanup;
}
static Int
JumpToEnv(Term t USES_REGS) {
2011-03-18 19:34:58 +00:00
#ifndef YAPOR
yamop *pos = NEXTOP(PredDollarCatch->cs.p_code.TrueCodeOfPred,l),
*catchpos = NEXTOP(PredHandleThrow->cs.p_code.TrueCodeOfPred,l);
#else
yamop *pos = NEXTOP(PredDollarCatch->cs.p_code.TrueCodeOfPred,Otapl),
*catchpos = NEXTOP(PredHandleThrow->cs.p_code.TrueCodeOfPred,Otapl);
2011-03-18 19:34:58 +00:00
#endif
CELL *env, *env1;
choiceptr handler, previous = NULL;
/* throws cannot interrupt throws */
if (EX)
return FALSE;
/* just keep the throwed object away, we don't need to care about it */
2011-05-04 10:11:41 +01:00
if (!(LOCAL_BallTerm = Yap_StoreTermInDB(t, 0))) {
Yap_RestartYap( 1 );
}
/* careful, previous step may have caused a stack shift,
so get pointers here */
handler = B;
env1 = ENV;
do {
/* find the first choicepoint that may be a catch */
while (handler != NULL && handler->cp_ap != pos) {
/* we are already doing a catch */
if (handler->cp_ap == catchpos) {
P = (yamop *)FAILCODE;
return TRUE;
}
/* we have a cleanup handler in the middle */
if (is_cleanup_cp(handler)) {
/* keep it around */
if (previous == NULL) {
B = handler;
} else {
previous->cp_b = handler;
}
previous = handler;
#ifdef TABLING
} else {
if (handler->cp_ap != NOCODE) {
abolish_incomplete_subgoals(handler);
}
#endif /* TABLING */
}
/* we reached C-Code */
if (handler->cp_ap == NOCODE) {
/* up to the C-code to deal with this! */
2011-05-04 10:11:41 +01:00
LOCAL_UncaughtThrow = TRUE;
if (previous == NULL)
B = handler;
else
previous->cp_b = handler;
2011-05-04 10:11:41 +01:00
EX = LOCAL_BallTerm;
LOCAL_BallTerm = NULL;
P = (yamop *)FAILCODE;
/* make sure failure will be seen at next port */
LOCK(LOCAL_SignalLock);
if (LOCAL_PrologMode & AsyncIntMode) {
Yap_signal(YAP_FAIL_SIGNAL);
}
UNLOCK(LOCAL_SignalLock);
HB = B->cp_h;
return TRUE;
}
/* make sure we prune C-choicepoints */
while (POP_CHOICE_POINT(handler->cp_b))
{
POP_EXECUTE();
}
handler = handler->cp_b;
}
/* uncaught throw */
if (handler == NULL) {
2011-05-04 10:11:41 +01:00
LOCAL_UncaughtThrow = TRUE;
Yap_RestartYap( 1 );
}
/* is it a continuation? */
env = handler->cp_env;
while (env > env1) {
env1 = ENV_Parent(env1);
}
/* yes, we found it ! */
// while (env < ENV)
// env = ENV_Parent(env);
if (env == env1) {
break;
}
/* oops, try next */
handler = handler->cp_b;
} while (TRUE);
/* step one environment above, otherwise we'll redo the original goal */
if (previous == NULL) {
B = handler;
} else {
// EX = t;
previous->cp_b = handler;
}
/* make sure we get rid of trash in the trail */
handler->cp_cp = (yamop *)env[E_CP];
handler->cp_env = (CELL *)env[E_E];
2011-03-18 19:34:58 +00:00
handler->cp_ap = catchpos;
/* can recover Heap thanks to copy term :-( */
/* B->cp_h = H; */
/* I could backtrack here, but it is easier to leave the unwinding
to the emulator */
LOCK(LOCAL_SignalLock);
if (LOCAL_PrologMode & AsyncIntMode) {
Yap_signal(YAP_FAIL_SIGNAL);
}
UNLOCK(LOCAL_SignalLock);
P = (yamop *)FAILCODE;
HB = B->cp_h;
/* try to recover space */
/* can only do that when we recover space */
/* first, simulate backtracking */
/* so that I will execute op_fail */
return TRUE;
}
Int
Yap_JumpToEnv(Term t) {
CACHE_REGS
if (LOCAL_PrologMode & BootMode) {
return FALSE;
}
return JumpToEnv(t PASS_REGS);
}
/* This does very nasty stuff!!!!! */
static Int
p_jump_env( USES_REGS1 ) {
return(JumpToEnv(Deref(ARG1) PASS_REGS));
}
/* set up a meta-call based on . context info */
static Int
p_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;
}
void
Yap_InitYaamRegs( int myworker_id )
{
Term h0var;
// getchar();
#if PUSH_REGS
/* Guarantee that after a longjmp we go back to the original abstract
machine registers */
#ifdef THREADS
CACHE_REGS
2012-12-13 18:12:50 +00:00
if (myworker_id) {
2013-11-15 01:10:25 +00:00
REGSTORE *rs = REMOTE_ThreadHandle(myworker_id).default_yaam_regs;
pthread_setspecific(Yap_yaamregs_key, (const void *)rs);
REMOTE_PL_local_data_p(myworker_id)->reg_cache = rs;
REMOTE_ThreadHandle(myworker_id).current_yaam_regs = rs;
REFRESH_CACHE_REGS
}
/* may be run by worker_id on behalf on myworker_id */
#else
Yap_regp = &Yap_standard_regs;
#endif
#endif /* PUSH_REGS */
2012-12-13 18:12:50 +00:00
Yap_ResetExceptionTerm ( myworker_id );
Yap_PutValue (AtomBreak, MkIntTerm (0));
2012-12-13 18:12:50 +00:00
TR = (tr_fr_ptr)REMOTE_TrailBase(myworker_id);
2014-01-19 21:15:05 +00:00
HR = H0 = ((CELL *) REMOTE_GlobalBase(myworker_id))+1; // +1: hack to ensure the gc does not try to mark mistakenly
2012-12-13 18:12:50 +00: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 since for the garbage collector to work */
B = NULL;
ENV = NULL;
P = CP = YESCODE;
#ifdef DEPTH_LIMIT
DEPTH = RESET_DEPTH();
#endif
STATIC_PREDICATES_MARKED = FALSE;
#ifdef FROZEN_STACKS
2014-01-19 21:15:05 +00:00
H_FZ = HR;
2011-03-30 15:32:59 +01:00
#ifdef YAPOR_SBA
BSEG =
2011-03-30 15:32:59 +01:00
#endif /* YAPOR_SBA */
2012-12-13 18:12:50 +00:00
BBREG = B_FZ = (choiceptr) REMOTE_LocalBase(myworker_id);
TR = TR_FZ = (tr_fr_ptr) REMOTE_TrailBase(myworker_id);
#endif /* FROZEN_STACKS */
2012-12-13 18:12:50 +00:00
LOCK(REMOTE_SignalLock(myworker_id));
2013-12-12 14:24:40 +00: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)
2012-12-13 18:12:50 +00:00
LOCAL = REMOTE(myworker_id);
2012-12-14 19:58:07 +00:00
worker_id = myworker_id;
2012-12-14 22:54:00 +00:00
#endif /* THREADS */
#if COROUTINING
2012-12-13 18:12:50 +00:00
REMOTE_WokenGoals(myworker_id) = Yap_NewTimedVar(TermNil);
h0var = MkVarTerm();
2012-12-13 18:12:50 +00:00
REMOTE_AttsMutableList(myworker_id) = Yap_NewTimedVar(h0var);
#endif
REMOTE_CurSlot(myworker_id) = 0;
h0var = MkVarTerm();
2012-12-13 18:12:50 +00:00
REMOTE_GcGeneration(myworker_id) = Yap_NewTimedVar(h0var);
REMOTE_GcCurrentPhase(myworker_id) = 0L;
REMOTE_GcPhase(myworker_id) = Yap_NewTimedVar(MkIntTerm(REMOTE_GcCurrentPhase(myworker_id)));
#if defined(YAPOR) || defined(THREADS)
PP = NULL;
PREG_ADDR = NULL;
#endif
if (REMOTE_GlobalArena(myworker_id) == 0L ||
REMOTE_GlobalArena(myworker_id) == TermNil) {
REMOTE_GlobalArena(myworker_id) = TermNil;
Yap_AllocateDefaultArena(128*1024, 2, myworker_id);
Yap_InitPreAllocCodeSpace( myworker_id );
}
2012-12-13 18:12:50 +00:00
cut_c_initialize( myworker_id );
2013-02-08 16:36:45 +00:00
Yap_PrepGoal(0, NULL, NULL PASS_REGS);
2012-04-17 00:21:08 +01:00
#ifdef TABLING
/* ensure that LOCAL_top_dep_fr is always valid */
2012-12-13 18:12:50 +00:00
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
2013-02-08 16:36:45 +00:00
UNLOCK(REMOTE_SignalLock(myworker_id));
2013-12-16 12:34:41 +00:00
// make sure we have slots in case we don go through the top-level */
Yap_StartSlots( PASS_REGS1 );
}
static Int
p_uncaught_throw( USES_REGS1 )
{
2011-05-04 10:11:41 +01:00
Int out = LOCAL_UncaughtThrow;
LOCAL_UncaughtThrow = FALSE; /* just caught it */
return out;
}
Term
Yap_GetException(void)
{
CACHE_REGS
Term t = 0L;
2011-05-04 10:11:41 +01:00
if (LOCAL_BallTerm) {
do {
2011-05-04 10:11:41 +01:00
t = Yap_PopTermFromDB(LOCAL_BallTerm);
if (t == 0) {
if (LOCAL_Error_TYPE == OUT_OF_ATTVARS_ERROR) {
LOCAL_Error_TYPE = YAP_NO_ERROR;
if (!Yap_growglobal(NULL)) {
Yap_Error(OUT_OF_ATTVARS_ERROR, TermNil, LOCAL_ErrorMessage);
return FALSE;
}
} else {
LOCAL_Error_TYPE = YAP_NO_ERROR;
2011-05-04 10:11:41 +01:00
if (!Yap_growstack(LOCAL_BallTerm->NOfCells*CellSize)) {
Yap_Error(OUT_OF_STACK_ERROR, TermNil, LOCAL_ErrorMessage);
return FALSE;
}
}
}
} while (t == 0);
2011-05-04 10:11:41 +01:00
LOCAL_BallTerm = NULL;
}
return t;
}
static Int
p_reset_exception( USES_REGS1 )
{
Term t;
EX = NULL;
t = Yap_GetException();
if (!t)
return FALSE;
return Yap_unify(t, ARG1);
}
void
2012-12-13 18:12:50 +00:00
Yap_ResetExceptionTerm(int wid)
{
2012-12-13 18:12:50 +00:00
Yap_ReleaseTermFromDB(REMOTE_BallTerm(wid));
REMOTE_BallTerm(wid) = NULL;
}
static Int
p_get_exception( USES_REGS1 )
{
Term t = Yap_GetException();
if (!t)
return FALSE;
return Yap_unify(t, ARG1);
}
2013-11-16 00:27:02 +00:00
int
Yap_dogc( int extra_args, Term *tp USES_REGS )
{
UInt arity;
yamop *nextpc;
int i;
if (P && PREVOP(P,Osbpp)->opc == Yap_opcode(_call_usercpred)) {
2014-05-30 01:06:09 +01:00
arity = PREVOP(P,Osbpp)->y_u.Osbpp.p->ArityOfPE;
2013-11-16 00:27:02 +00:00
nextpc = P;
} else {
arity = 0;
nextpc = CP;
}
for (i=0; i < extra_args; i++) {
XREGS[arity+i+1] = tp[i];
}
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;
}
void
Yap_InitExecFs(void)
{
CACHE_REGS
Term cm = CurrentModule;
Yap_InitComma();
2012-10-19 18:10:48 +01:00
Yap_InitCPred("$execute", 1, p_execute, 0);
Yap_InitCPred("$execute", 2, p_execute2, 0);
Yap_InitCPred("$execute", 3, p_execute3, 0);
Yap_InitCPred("$execute", 4, p_execute4, 0);
Yap_InitCPred("$execute", 5, p_execute5, 0);
Yap_InitCPred("$execute", 6, p_execute6, 0);
Yap_InitCPred("$execute", 7, p_execute7, 0);
Yap_InitCPred("$execute", 8, p_execute8, 0);
Yap_InitCPred("$execute", 9, p_execute9, 0);
Yap_InitCPred("$execute", 10, p_execute10, 0);
Yap_InitCPred("$execute", 11, p_execute11, 0);
Yap_InitCPred("$execute", 12, p_execute12, 0);
Yap_InitCPred("$execute_in_mod", 2, p_execute_in_mod, 0);
Yap_InitCPred("$execute_wo_mod", 2, p_execute_in_mod, 0);
Yap_InitCPred("call_with_args", 1, p_execute_0, 0);
Yap_InitCPred("call_with_args", 2, p_execute_1, 0);
Yap_InitCPred("call_with_args", 3, p_execute_2, 0);
Yap_InitCPred("call_with_args", 4, p_execute_3, 0);
Yap_InitCPred("call_with_args", 5, p_execute_4, 0);
Yap_InitCPred("call_with_args", 6, p_execute_5, 0);
Yap_InitCPred("call_with_args", 7, p_execute_6, 0);
Yap_InitCPred("call_with_args", 8, p_execute_7, 0);
Yap_InitCPred("call_with_args", 9, p_execute_8, 0);
Yap_InitCPred("call_with_args", 10, p_execute_9, 0);
Yap_InitCPred("call_with_args", 11, p_execute_10, 0);
#ifdef DEPTH_LIMIT
2012-10-19 18:10:48 +01:00
Yap_InitCPred("$execute_under_depth_limit", 2, p_execute_depth_limit, 0);
#endif
2012-10-19 18:10:48 +01:00
Yap_InitCPred("$execute0", 2, p_execute0, 0);
Yap_InitCPred("$execute_nonstop", 2, p_execute_nonstop, 0);
Yap_InitCPred("$execute_clause", 4, p_execute_clause, 0);
2013-02-17 13:02:03 +00:00
Yap_InitCPred("$current_choice_point", 1, p_save_cp, 0);
Yap_InitCPred("$current_choicepoint", 1, p_save_cp, 0);
CurrentModule = HACKS_MODULE;
2012-10-19 18:10:48 +01:00
Yap_InitCPred("current_choice_point", 1, p_save_cp, 0);
Yap_InitCPred("current_choicepoint", 1, p_save_cp, 0);
Yap_InitCPred("env_choice_point", 1, p_save_env_b, 0);
Yap_InitCPred("trail_suspension_marker", 1, p_trail_suspension_marker, 0);
Yap_InitCPred("cut_at", 1, p_clean_ifcp, SafePredFlag);
CurrentModule = cm;
2012-10-19 18:10:48 +01:00
Yap_InitCPred("$pred_goal_expansion_on", 0, p_pred_goal_expansion_on, SafePredFlag);
Yap_InitCPred("$restore_regs", 1, p_restore_regs, SafePredFlag);
Yap_InitCPred("$restore_regs", 2, p_restore_regs2, SafePredFlag);
Yap_InitCPred("$clean_ifcp", 1, p_clean_ifcp, SafePredFlag);
Yap_InitCPred("qpack_clean_up_to_disjunction", 0, p_cut_up_to_next_disjunction, SafePredFlag);
2012-10-19 18:10:48 +01:00
Yap_InitCPred("$jump_env_and_store_ball", 1, p_jump_env, 0);
Yap_InitCPred("$generate_pred_info", 4, p_generate_pred_info, 0);
Yap_InitCPred("$uncaught_throw", 0, p_uncaught_throw, 0);
Yap_InitCPred("$reset_exception", 1, p_reset_exception, 0);
Yap_InitCPred("$do_goal_expansion", 3, p_do_goal_expansion, 0);
Yap_InitCPred("$do_term_expansion", 2, p_do_term_expansion, 0);
2012-10-19 18:10:48 +01:00
Yap_InitCPred("$get_exception", 1, p_get_exception, 0);
}