home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Vectronix 2
/
VECTRONIX2.iso
/
FILES_01
/
X_PROLOG.LZH
/
X_PROLOG
/
SOURCES
/
MACHINE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-13
|
8KB
|
281 lines
/*
* X PROLOG Vers. 2.0
*
*
* Written by : Andreas Toenne
* CS Dept. , IRB
* University of Dortmund, W-Germany
* <at@unido.uucp>
* <....!seismo!unido!at>
* <at@unido.bitnet>
*
* Copyright : This software is copyrighted by Andreas Toenne.
* Permission is granted hereby to copy the entire
* package including this copyright notice without fee.
*
*/
#include <setjmp.h>
#include "prolog.h"
#include "error.h"
#include "extern.h"
extern functor *get_functor(); /* functor */
extern term *nil_proto(); /* terms */
extern term *argument(); /* terms */
extern term *deref(); /* terms */
extern short term_unify(); /* terms */
extern term *term_instance(); /* terms */
extern void pop_copies(); /* memory */
extern void push_back(); /* memory */
extern void push_env(); /* memory */
extern void push_frame(); /* memory */
extern void pop_trails(); /* memory */
extern void panic(); /* error */
extern term *error(); /* error */
extern short call_builtin(); /* builtin */
extern void init_stacks(); /* init */
term *ocopytop, *ocopynext; /* copystack */
/* This is the prolog machine */
void machine(goal)
term *goal; /* the goal to start with */
{
register term *c_term; /* the current term */
register clause *c_clause; /* the current clause */
register short success;
if (FUNC(goal) == NILFUNCTOR) /* no main goal ?? */
panic(NOGOAL);
ocopytop = copytop; /* save the size of the copystack */
ocopynext = copynext;
if (setjmp(&abortpoint)) /* returned from longjmp */
{
copytop = ocopytop;
copynext = ocopynext;
trailtop= 0L;
Preenv = Topenv = (env *)0L;
Backpoint = (backlog *)0L;
stacktop = stack;
}
c_errno = 0; /* clear error number */
/* we first set the logs for the main goal */
push_env(0L, goal); /* no ancestor, no vars */
push_frame(Topenv, 0);
if (FUNC(goal) == COMMAFUNCTOR)
c_term = argument(goal, Topenv, 1);
else
c_term = deref(goal, Topenv);
success = TRUE;
do /* forever */
{
/* upon start of the loop c_term points to the current */
/* 'program' term in the current enviroment. */
/* if !success then backtracking has set c_clause, */
/* otherwise we must set c_clause */
if (success) /* set c_clause */
{
if (!ISSTRUCT(c_term) /* must be compound term */
|| ! (c_clause = (clause *)FUNC(c_term)->cp))
{
/* replace the faulty call by error */
push_env(Topenv, NULL);
push_frame(Topenv, MAXVARS);
Topenv->current = error(ENOCLAUSE, c_term);
c_term=ARG(Topenv->current,1);
continue; /* try again with error */
}
/* if our current clause offers some more alternatives*/
/* we must set a backtrack log for the current call */
if (c_clause->next)
push_back(c_clause);
}
/* build preliminary enviroment for goal */
if (! ISBUILTIN(c_clause))
{
push_env(Topenv, c_clause->body);
push_frame(Topenv, c_clause->nvars);
}
/* now do the true work */
if (dodebug) debug();
if (ISBUILTIN(c_clause)) /* call a builtin */
{
switch((short)c_clause->head)
{
case 0: /* abort */
longjmp(&abortpoint, TRUE);
case 1: /* call */
push_env(Topenv,
argument(c_term,Topenv,1));
push_frame(Topenv, 0);
if (FUNC(Topenv->current) == COMMAFUNCTOR)
c_term = ARG(Topenv->current, 1);
else
c_term = Topenv->current;
success = TRUE;
continue;
}
success = call_builtin((short)c_clause->head,
c_term,Topenv);
}
else /* unify c_term and head */
success = term_unify(c_term, Preenv,
c_clause->head, Topenv);
if (c_errno) /* an bi error has occured */
{
if (c_errno == ESYNTAX)
{
c_errno = 0;
goto fail;
}
if (c_errno == EIO && !io_errors)
{
c_errno = 0;
goto fail;
}
push_env(Topenv, NULL);
push_frame(Topenv, MAXVARS);
Topenv->current = error(c_errno, c_term);
c_term=ARG(Topenv->current,1);
if (c_errno != ESYNTAX)
{
biseen();
bitold();
}
c_errno = 0;
success = TRUE;
continue; /* again with new error goal */
}
if (success) /* the head matches the current term */
{
/* try to enter the body of the clause */
if (! ISBUILTIN(c_clause) &&
FUNC(c_clause->body) != TRUEFUNCTOR)
{
if (FUNC(Topenv->current) == COMMAFUNCTOR)
c_term = ARG(Topenv->current, 1);
else
c_term = Topenv->current;
}
else
/* assume c_clause is done. */
/* we now descend in the enviroments until a not */
/* done enviroment is found. */
/* the skipped enviroments are finished and must be */
/* removed. */
/* if we move past a 'locked' enviroment, we */
/* must duplicate it for sake of backtracking */
/* this is done by creating a new enviroment */
/* an its frame beeing the old frame */
{
register env *e = Topenv;
/* search for an proper enviroment */
do
{
if (FUNC(e->current)
== COMMAFUNCTOR)
break;
else
if (!(e=e->pre)) /* oops */
panic(EXITUS);
} while (TRUE);
/* clean up the stack */
/* easy if e is not frozen */
if ((long)e > (long)Backpoint)
{
Topenv = e; /* reduce env stack */
Preenv = Topenv->pre;
stacktop = (char *)((long)Topenv +
sizeof(env) + Topenv->nvars *
sizeof(term));
}
else
{
/* cut stack upto choice point */
stacktop = (char *)((long)Backpoint +
sizeof(backlog));
/* duplicate e, but not it's vars */
push_env(e->pre, 0L);
Topenv->frame = e->frame;
Topenv->nvars = e->nvars;
}
/* setup c_term and c_clause */
Topenv->current = ARG(e->current,2);
if (FUNC(Topenv->current) == COMMAFUNCTOR)
c_term = ARG(Topenv->current, 1);
else
c_term = Topenv->current;
} /* else */
} /* success */
else /* !success */
{
fail:
/* the builtin has failed or the current clauses */
/* head didn't match. */
/* remove new term copies */
pop_copies(Backpoint->copylev);
/* unbind frozen vars */
pop_trails(Backpoint->traillev);
/* remove enviroments without alternatives */
/* and restore the old c_term */
stacktop = (char *)((long)Backpoint+sizeof(backlog));
Topenv = Backpoint->frozen_env;
Preenv = Topenv->pre;
if (FUNC(Topenv->current) == COMMAFUNCTOR)
c_term = ARG(Topenv->current, 1);
else
c_term = Topenv->current;
while (FUNC(c_term) == CALLFUNCTOR)
c_term = argument(c_term, Topenv, 1);
/* setup the new current clause */
c_clause = ((clause *)(Backpoint->resume))->next;
/* if we got no further alternative, we must */
/* remove this backtrack log */
/* otherwise we must update the log */
if (!c_clause || !c_clause->next)
{
stacktop = (char *)Backpoint;
Backpoint = Backpoint->pre;
}
else
Backpoint->resume = (char *)c_clause;
} /* !success */
} while (TRUE);
}