blob: 5bae7932ec6753bf924a68cbe65558c4f942653b [file] [log] [blame]
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * ST INDEXING * */
/* * * */
/* * $Module: ST * */
/* * * */
/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */
/* * MPI fuer Informatik * */
/* * * */
/* * This program is free software; you can redistribute * */
/* * it and/or modify it under the terms of the GNU * */
/* * General Public License as published by the Free * */
/* * Software Foundation; either version 2 of the License, * */
/* * or (at your option) any later version. * */
/* * * */
/* * This program is distributed in the hope that it will * */
/* * be useful, but WITHOUT ANY WARRANTY; without even * */
/* * the implied warranty of MERCHANTABILITY or FITNESS * */
/* * FOR A PARTICULAR PURPOSE. See the GNU General Public * */
/* * License for more details. * */
/* * * */
/* * You should have received a copy of the GNU General * */
/* * Public License along with this program; if not, write * */
/* * to the Free Software Foundation, Inc., 59 Temple * */
/* * Place, Suite 330, Boston, MA 02111-1307 USA * */
/* * * */
/* * * */
/* $Revision$ * */
/* $State$ * */
/* $Date$ * */
/* $Author$ * */
/* * * */
/* * Contact: * */
/* * Christoph Weidenbach * */
/* * MPI fuer Informatik * */
/* * Stuhlsatzenhausweg 85 * */
/* * 66123 Saarbruecken * */
/* * Email: weidenb@mpi-sb.mpg.de * */
/* * Germany * */
/* * * */
/* ********************************************************** */
/**************************************************************/
/* $RCSfile$ */
#include "st.h"
/**************************************************************/
/* Local Variables */
/**************************************************************/
static st_RETRIEVAL_TYPE st_CURRENT_RETRIEVAL;
static st_WHERE_TYPE st_WHICH_CONTEXTS;
static CONTEXT st_INDEX_CONTEXT;
static st_MINMAX st_EXIST_MINMAX;
/**************************************************************/
/* Global Variables */
/**************************************************************/
ST_STACK st_STACK;
int st_STACKPOINTER;
int st_STACKSAVE;
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * CREATION OF INDEX * */
/* * * */
/* ********************************************************** */
/**************************************************************/
st_INDEX st_IndexCreate(void)
/**************************************************************
INPUT: None.
RETURNS: A pointer to a new St-Index.
SUMMARY: Creates a new St-index.
***************************************************************/
{
st_INDEX StIndex;
StIndex = st_Get();
StIndex->subnodes = list_Nil();
StIndex->entries = list_Nil();
StIndex->subst = subst_Nil();
st_SetMax(StIndex, 0);
st_SetMin(StIndex, 0);
return StIndex;
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * CREATION OF INDEX NODES * */
/* * * */
/* ********************************************************** */
/**************************************************************/
static st_INDEX st_NodeAddLeaf(SUBST Subst, st_MINMAX MinMax, POINTER Pointer)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
st_INDEX NewLeaf;
NewLeaf = st_Get();
NewLeaf->subnodes = list_Nil();
NewLeaf->entries = list_List(Pointer);
NewLeaf->subst = Subst;
st_SetMax(NewLeaf, MinMax);
st_SetMin(NewLeaf, MinMax);
return NewLeaf;
}
static void st_NodeAddInner(st_INDEX StIndex, SUBST SubstOld, SUBST SubstNew,
SUBST ComGen, st_MINMAX MinMax, POINTER Pointer)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
st_INDEX OldIndexNode;
OldIndexNode = st_Get();
OldIndexNode->subst = SubstOld;
OldIndexNode->entries = StIndex->entries;
OldIndexNode->subnodes = StIndex->subnodes;
st_SetMax(OldIndexNode, st_Max(StIndex));
st_SetMin(OldIndexNode, st_Min(StIndex));
subst_Delete(StIndex->subst);
StIndex->subst = ComGen;
StIndex->entries = list_Nil();
StIndex->subnodes = list_Cons(st_NodeAddLeaf(SubstNew, MinMax, Pointer),
list_List(OldIndexNode));
if (st_Max(StIndex) < MinMax)
st_SetMax(StIndex, MinMax);
else if (st_Min(StIndex) > MinMax)
st_SetMin(StIndex, MinMax);
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * MERGING OF INDEX NODES * */
/* * * */
/* ********************************************************** */
/**************************************************************/
static void st_NodeMergeWithSon(st_INDEX StIndex)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
st_INDEX SubNode;
SubNode = (st_INDEX)list_Car(StIndex->subnodes);
list_Delete(StIndex->subnodes);
StIndex->subst = subst_Merge(SubNode->subst, StIndex->subst);
StIndex->entries = SubNode->entries;
StIndex->subnodes = SubNode->subnodes;
st_SetMax(StIndex, st_Max(SubNode));
st_SetMin(StIndex, st_Min(SubNode));
subst_Delete(SubNode->subst);
st_Free(SubNode);
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * VARIABLE HANDLING FOR TERMS AND SUBSTS. * */
/* * * */
/* ********************************************************** */
/**************************************************************/
static void st_CloseUsedVariables(const CONTEXT Context, LIST NodeList)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
for (; list_Exist(NodeList); NodeList = list_Cdr(NodeList)) {
SUBST Subst;
for (Subst = ((st_INDEX)list_Car(NodeList))->subst;
subst_Exist(Subst);
Subst = subst_Next(Subst))
if (!cont_VarIsUsed(Context, subst_Dom(Subst)))
cont_CreateClosedBinding(Context, subst_Dom(Subst));
if (!st_IsLeaf((st_INDEX)list_Car(NodeList)))
st_CloseUsedVariables(Context, ((st_INDEX)list_Car(NodeList))->subnodes);
}
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * HEURISTICS FOR INSERTION OF TERMS AND SUBSTS. * */
/* * * */
/* ********************************************************** */
/**************************************************************/
static st_INDEX st_FirstVariant(const CONTEXT Context, LIST Subnodes, st_INDEX* BestNonVariant)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
st_INDEX EmptyVariant;
for (EmptyVariant = NULL, *BestNonVariant = NULL;
list_Exist(Subnodes);
Subnodes = list_Cdr(Subnodes)) {
st_INDEX CurrentNode;
CurrentNode = (st_INDEX)list_Car(Subnodes);
cont_StartBinding();
if (subst_Variation(Context, CurrentNode->subst)) {
if (subst_Exist(CurrentNode->subst)) {
subst_CloseVariables(Context, CurrentNode->subst);
return CurrentNode;
} else
EmptyVariant = CurrentNode;
} else if (*BestNonVariant == NULL)
if (subst_MatchTops(Context, CurrentNode->subst))
*BestNonVariant = CurrentNode;
cont_BackTrack();
}
return EmptyVariant;
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * INSERTION OF TERMS * */
/* * * */
/* ********************************************************** */
/**************************************************************/
void st_EntryCreate(st_INDEX StIndex, POINTER Pointer, TERM Term, const CONTEXT Context)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
st_INDEX Current;
st_INDEX BestNonVariant;
SYMBOL FirstDomain;
st_MINMAX MinMax;
cont_Check();
MinMax = term_ComputeSize(Term);
/* CREATE INITIAL BINDING AND INITIALIZE LOCAL VARIABLES */
FirstDomain = cont_NextIndexVariable(Context);
cont_CreateBinding(Context, FirstDomain, Context, Term);
Current = StIndex;
if (st_Max(Current) < MinMax)
st_SetMax(Current, MinMax);
else if (st_Min(Current) > MinMax)
st_SetMin(Current, MinMax);
/* FIND "LAST" VARIATION */
while (!st_IsLeaf(Current) &&
(Current = st_FirstVariant(Context, Current->subnodes, &BestNonVariant))) {
if (st_Max(Current) < MinMax)
st_SetMax(Current, MinMax);
else if (st_Min(Current) > MinMax)
st_SetMin(Current, MinMax);
StIndex = Current;
}
if (cont_BindingsSinceLastStart()==0 && Current && st_IsLeaf(Current)) {
/* INSERT ENTRY EQUAL MODULO RENAMING */
Current->entries = list_Cons(Pointer, Current->entries);
} else if (BestNonVariant) {
/* CREATE INNER NODE AND A NEW LEAF */
SUBST ComGen, SubstOld, SubstNew;
if (!st_IsLeaf(BestNonVariant))
st_CloseUsedVariables(Context, BestNonVariant->subnodes);
ComGen = subst_ComGen(Context, BestNonVariant->subst, &SubstOld, &SubstNew);
st_NodeAddInner(BestNonVariant,
SubstOld,
subst_CloseOpenVariables(SubstNew),
ComGen,
MinMax,
Pointer);
} else
/* ADD A SINGLE LEAF NODE TO FATHER */
StIndex->subnodes =
list_Cons(st_NodeAddLeaf(subst_CloseOpenVariables(subst_Nil()), MinMax,
Pointer),
StIndex->subnodes);
cont_Reset();
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * DELETION OF INDEX * */
/* * * */
/* ********************************************************** */
/**************************************************************/
void st_IndexDelete(st_INDEX StIndex)
/**************************************************************
INPUT: A pointer to an existing St-Index.
SUMMARY: Deletes the whole index structure.
***************************************************************/
{
if (StIndex == NULL)
return;
else if (st_IsLeaf(StIndex))
list_Delete(StIndex->entries);
else
/* Recursion */
list_DeleteWithElement(StIndex->subnodes, (void (*)(POINTER))st_IndexDelete);
subst_Delete(StIndex->subst);
st_Free(StIndex);
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * DELETION OF ENTRY FOR TERMS * */
/* * * */
/* ********************************************************** */
/**************************************************************/
static st_INDEX st_EntryDeleteHelp(const CONTEXT Context, st_INDEX StIndex, POINTER Pointer,
BOOL* Found)
/**************************************************************
INPUT: The root of an abstraction tree (StIndex), a
pointer to a specific entry of the tree and
a query term.
RETURNS: Nothing.
SUMMARY: Uses Term in order to find Pointer in the tree.
EFFECTS: Will delete nodes of StIndex.
***************************************************************/
{
if (st_IsLeaf(StIndex)) {
*Found = list_DeleteFromList(&(StIndex->entries), Pointer);
if (list_Exist(StIndex->entries))
return StIndex;
else {
subst_Delete(StIndex->subst);
st_Free(StIndex);
return NULL;
}
} else {
LIST Subnodes;
for (Subnodes = StIndex->subnodes;
list_Exist(Subnodes);
Subnodes = list_Cdr(Subnodes)) {
st_INDEX CurrentNode;
CurrentNode = (st_INDEX)list_Car(Subnodes);
cont_StartBinding();
if (subst_Variation(Context, CurrentNode->subst)) {
list_Rplaca(Subnodes, st_EntryDeleteHelp(Context,
CurrentNode,
Pointer,
Found));
if (*Found) {
if (list_DeleteFromList(&(StIndex->subnodes), NULL))
if (list_Empty(list_Cdr(StIndex->subnodes))) {
/* 'StIndex' has one subnode only. */
st_NodeMergeWithSon(StIndex);
return StIndex;
}
/* Assertion: 'StIndex' is an inner node. */
CurrentNode = (st_INDEX)list_Car(StIndex->subnodes);
st_SetMax(StIndex, st_Max(CurrentNode));
st_SetMin(StIndex, st_Min(CurrentNode));
for (Subnodes = list_Cdr(StIndex->subnodes);
list_Exist(Subnodes);
Subnodes = list_Cdr(Subnodes)) {
CurrentNode = (st_INDEX)list_Car(Subnodes);
if (st_Max(CurrentNode) > st_Max(StIndex))
st_SetMax(StIndex, st_Max(CurrentNode));
if (st_Min(CurrentNode) < st_Min(StIndex))
st_SetMin(StIndex, st_Min(CurrentNode));
}
return StIndex;
}
}
cont_BackTrack();
}
return StIndex;
}
}
BOOL st_EntryDelete(st_INDEX StIndex, POINTER Pointer, TERM Term, const CONTEXT Context)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
BOOL Found;
LIST Subnodes;
SYMBOL FirstDomain;
cont_Check();
FirstDomain = symbol_FirstIndexVariable();
cont_CreateBinding(Context, FirstDomain, Context, Term);
for (Found = FALSE, Subnodes = StIndex->subnodes;
list_Exist(Subnodes);
Subnodes = list_Cdr(Subnodes)) {
st_INDEX CurrentNode;
CurrentNode = (st_INDEX)list_Car(Subnodes);
cont_StartBinding();
if (subst_Variation(Context, CurrentNode->subst)) {
list_Rplaca(Subnodes, st_EntryDeleteHelp(Context, CurrentNode, Pointer, &Found));
if (Found) {
StIndex->subnodes = list_PointerDeleteElement(StIndex->subnodes, NULL);
if (list_Exist(StIndex->subnodes)) {
CurrentNode = (st_INDEX)list_Car(StIndex->subnodes);
st_SetMax(StIndex, st_Max(CurrentNode));
st_SetMin(StIndex, st_Min(CurrentNode));
for (Subnodes = list_Cdr(StIndex->subnodes);
list_Exist(Subnodes);
Subnodes = list_Cdr(Subnodes)) {
CurrentNode = (st_INDEX)list_Car(Subnodes);
if (st_Max(CurrentNode) > st_Max(StIndex))
st_SetMax(StIndex, st_Max(CurrentNode));
if (st_Min(CurrentNode) < st_Min(StIndex))
st_SetMin(StIndex, st_Min(CurrentNode));
}
} else {
st_SetMax(StIndex, 0);
st_SetMin(StIndex, 0);
}
break;
}
}
cont_BackTrack();
}
cont_Reset();
return Found;
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * RETRIEVAL FOR TERMS * */
/* * * */
/* ********************************************************** */
/**************************************************************/
static LIST st_TraverseTreeUnifier(CONTEXT IndexContext, st_INDEX StIndex)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
int Save;
LIST Result, CurrentList;
st_INDEX CurrentNode;
/* PREPARE TRAVERSAL */
Save = stack_Bottom();
Result = list_Nil();
CurrentList = StIndex->subnodes;
cont_StartBinding();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (stack_Empty(Save))
return Result;
CurrentList = stack_PopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
subst_Unify(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList))
if (st_IsLeaf(CurrentNode)) {
Result = list_Append(CurrentNode->entries, Result);
break;
} else if (list_Exist(list_Cdr(CurrentList))) {
stack_Push(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
static LIST st_TraverseTreeGen(CONTEXT IndexContext, st_INDEX StIndex)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
int Save;
LIST Result, CurrentList;
st_INDEX CurrentNode;
/* PREPARE TRAVERSAL */
Save = stack_Bottom();
Result = list_Nil();
CurrentList = StIndex->subnodes;
cont_StartBinding();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (stack_Empty(Save))
return Result;
CurrentList = stack_PopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
subst_Match(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList))
if (st_IsLeaf(CurrentNode)) {
Result = list_Append(CurrentNode->entries, Result);
break;
} else if (list_Cdr(CurrentList)) {
stack_Push(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
static LIST st_TraverseTreeInstance(CONTEXT IndexContext, st_INDEX StIndex)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
int Save;
LIST Result, CurrentList;
st_INDEX CurrentNode;
/* PREPARE TRAVERSAL */
Save = stack_Bottom();
Result = list_Nil();
CurrentList = StIndex->subnodes;
cont_StartBinding();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (stack_Empty(Save))
return Result;
CurrentList = stack_PopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
subst_MatchReverse(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList))
if (st_IsLeaf(CurrentNode)) {
Result = list_Append(CurrentNode->entries, Result);
break;
} else if (list_Cdr(CurrentList)) {
stack_Push(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
static LIST st_TraverseTreeGenPreTest(CONTEXT IndexContext,
st_INDEX StIndex,
st_MINMAX MinMax)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
int Save;
LIST Result, CurrentList;
st_INDEX CurrentNode;
/* PREPARE TRAVERSAL */
Save = stack_Bottom();
Result = list_Nil();
CurrentList = StIndex->subnodes;
cont_StartBinding();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (stack_Empty(Save))
return Result;
CurrentList = stack_PopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
(MinMax >= st_Min(CurrentNode)) &&
subst_Match(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList))
if (st_IsLeaf(CurrentNode)) {
Result = list_Append(CurrentNode->entries, Result);
break;
} else if (list_Cdr(CurrentList)) {
stack_Push(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
static LIST st_TraverseTreeInstancePreTest(CONTEXT IndexContext, st_INDEX StIndex, st_MINMAX MinMax)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
int Save;
LIST Result, CurrentList;
st_INDEX CurrentNode;
/* PREPARE TRAVERSAL */
Save = stack_Bottom();
Result = list_Nil();
CurrentList = StIndex->subnodes;
cont_StartBinding();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (stack_Empty(Save))
return Result;
CurrentList = stack_PopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
(MinMax <= st_Max(CurrentNode)) &&
subst_MatchReverse(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList))
if (st_IsLeaf(CurrentNode)) {
Result = list_Append(CurrentNode->entries, Result);
break;
} else if (list_Cdr(CurrentList)) {
stack_Push(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
LIST st_GetUnifier(CONTEXT IndexContext, st_INDEX StIndex, CONTEXT TermContext, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST Result;
SYMBOL FirstDomain;
cont_Check();
FirstDomain = symbol_FirstIndexVariable();
cont_CreateBinding(IndexContext, FirstDomain, TermContext, Term);
Result = st_TraverseTreeUnifier(IndexContext, StIndex);
cont_Reset();
return Result;
}
LIST st_GetGen(CONTEXT IndexContext, st_INDEX StIndex, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST Result;
SYMBOL FirstDomain;
cont_Check();
FirstDomain = symbol_FirstIndexVariable();
cont_CreateBinding(IndexContext, FirstDomain, cont_InstanceContext(), Term);
Result = st_TraverseTreeGen(IndexContext, StIndex);
cont_Reset();
return Result;
}
LIST st_GetGenPreTest(CONTEXT IndexContext, st_INDEX StIndex, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST Result;
SYMBOL FirstDomain;
cont_Check();
FirstDomain = symbol_FirstIndexVariable();
cont_CreateBinding(IndexContext, FirstDomain, cont_InstanceContext(), Term);
Result = st_TraverseTreeGenPreTest(IndexContext, StIndex, term_ComputeSize(Term));
cont_Reset();
return Result;
}
LIST st_GetInstance(CONTEXT IndexContext, st_INDEX StIndex, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST Result;
SYMBOL FirstDomain;
cont_Check();
FirstDomain = symbol_FirstIndexVariable();
cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term);
Result = st_TraverseTreeInstance(IndexContext, StIndex);
cont_Reset();
return Result;
}
LIST st_GetInstancePreTest(CONTEXT IndexContext, st_INDEX StIndex, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST Result;
SYMBOL FirstDomain;
cont_Check();
FirstDomain = symbol_FirstIndexVariable();
cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term);
Result = st_TraverseTreeInstancePreTest(IndexContext, StIndex, term_ComputeSize(Term));
cont_Reset();
return Result;
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * INCREMENTAL RETRIEVAL * */
/* * * */
/* ********************************************************** */
/**************************************************************/
static POINTER st_TraverseForExistUnifier(CONTEXT IndexContext)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST CurrentList;
st_INDEX CurrentNode;
/* Caution: In case an entry is found
the procedure returns immediately
without backtracking the current bindings. */
CurrentList = list_Nil();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (st_StackEmpty(st_STACKSAVE))
return NULL;
CurrentList = st_StackPopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
subst_Unify(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList)) {
if (list_Exist(list_Cdr(CurrentList))) {
st_StackPush(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
if (st_IsLeaf(CurrentNode)) {
st_StackPush(list_Cdr(CurrentNode->entries));
return list_Car(CurrentNode->entries);
}
}
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
static POINTER st_TraverseForExistGen(CONTEXT IndexContext)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST CurrentList;
st_INDEX CurrentNode;
/* Caution: In case an entry is found
the procedure returns immediately
without backtracking the current bindings. */
CurrentList = list_Nil();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (st_StackEmpty(st_STACKSAVE))
return NULL;
CurrentList = st_StackPopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
subst_Match(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList)) {
if (list_Exist(list_Cdr(CurrentList))) {
st_StackPush(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
if (st_IsLeaf(CurrentNode)) {
st_StackPush(list_Cdr(CurrentNode->entries));
return list_Car(CurrentNode->entries);
}
}
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
static POINTER st_TraverseForExistGenPreTest(CONTEXT IndexContext)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST CurrentList;
st_INDEX CurrentNode;
/* Caution: In case an entry is found
the procedure returns immediately
without backtracking the current bindings. */
CurrentList = list_Nil();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (st_StackEmpty(st_STACKSAVE))
return NULL;
CurrentList = st_StackPopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
(st_EXIST_MINMAX >= st_Min(CurrentNode)) &&
subst_Match(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList)) {
if (list_Exist(list_Cdr(CurrentList))) {
st_StackPush(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
if (st_IsLeaf(CurrentNode)) {
st_StackPush(list_Cdr(CurrentNode->entries));
return list_Car(CurrentNode->entries);
}
}
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
static POINTER st_TraverseForExistInstance(CONTEXT IndexContext)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST CurrentList;
st_INDEX CurrentNode;
/* Caution: In case an entry is found
the procedure returns immediately
without backtracking the current bindings. */
CurrentList = list_Nil();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (st_StackEmpty(st_STACKSAVE))
return NULL;
CurrentList = st_StackPopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
subst_MatchReverse(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList)) {
if (list_Exist(list_Cdr(CurrentList))) {
st_StackPush(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
if (st_IsLeaf(CurrentNode)) {
st_StackPush(list_Cdr(CurrentNode->entries));
return list_Car(CurrentNode->entries);
}
}
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
static POINTER st_TraverseForExistInstancePreTest(CONTEXT IndexContext)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST CurrentList;
st_INDEX CurrentNode;
/* Caution: In case an entry is found
the procedure returns immediately
without backtracking the current bindings. */
CurrentList = list_Nil();
for (;;) {
/* BACKTRACK A BIG STEP */
if (list_Empty(CurrentList)) {
cont_StopAndBackTrack();
if (st_StackEmpty(st_STACKSAVE))
return NULL;
CurrentList = st_StackPopResult();
}
/* DESCENDING */
for (CurrentNode = (st_INDEX)list_Car(CurrentList);
(st_EXIST_MINMAX <= st_Max(CurrentNode)) &&
subst_MatchReverse(IndexContext, CurrentNode->subst);
CurrentList = CurrentNode->subnodes,
CurrentNode = (st_INDEX)list_Car(CurrentList)) {
if (list_Exist(list_Cdr(CurrentList))) {
st_StackPush(list_Cdr(CurrentList));
cont_StartBinding();
} else
cont_StopAndStartBinding();
if (st_IsLeaf(CurrentNode)) {
st_StackPush(list_Cdr(CurrentNode->entries));
return list_Car(CurrentNode->entries);
}
}
/* BACKTRACK LEAF OR INNER NODE */
CurrentList = list_Cdr(CurrentList);
cont_BackTrackAndStart();
}
}
void st_CancelExistRetrieval(void)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
if (st_CURRENT_RETRIEVAL != st_NOP) {
#ifdef CHECK
cont_CheckState();
#endif
st_StackSetBottom(st_STACKSAVE);
switch (st_WHICH_CONTEXTS) {
case st_STANDARD:
cont_Reset();
break;
case st_NOC:
break;
default:
misc_StartErrorReport();
misc_ErrorReport("\n In st_CancelExistRetrieval: Unknown context type.\n");
misc_FinishErrorReport();
}
st_CURRENT_RETRIEVAL = st_NOP;
st_WHICH_CONTEXTS = st_NOC;
st_INDEX_CONTEXT = NULL;
st_EXIST_MINMAX = 0;
}
}
POINTER st_ExistUnifier(CONTEXT IndexContext, st_INDEX StIndex, CONTEXT TermContext, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
SYMBOL FirstDomain;
POINTER Result;
#ifdef CHECK
if (!st_StackEmpty(st_STACKSAVE)) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistUnifier: ST-Stack not empty.\n");
misc_FinishErrorReport();
} else if (st_CURRENT_RETRIEVAL != st_NOP) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistUnifier: %d Retrieval already in progress.\n",
st_CURRENT_RETRIEVAL);
misc_FinishErrorReport();
}
#endif
cont_Check();
if (st_Exist(StIndex)) {
st_CURRENT_RETRIEVAL = st_UNIFIER;
st_WHICH_CONTEXTS = st_STANDARD;
st_INDEX_CONTEXT = IndexContext;
st_STACKSAVE = st_StackBottom();
FirstDomain = symbol_FirstIndexVariable();
cont_CreateBinding(IndexContext, FirstDomain, TermContext, Term);
cont_StartBinding();
st_StackPush(StIndex->subnodes);
cont_StartBinding();
Result = st_TraverseForExistUnifier(IndexContext);
#ifdef CHECK
cont_SaveState();
#endif
if (Result == NULL)
st_CancelExistRetrieval();
return Result;
} else
return NULL;
}
POINTER st_ExistGen(CONTEXT IndexContext, st_INDEX StIndex, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
SYMBOL FirstDomain;
POINTER Result;
#ifdef CHECK
if (!st_StackEmpty(st_STACKSAVE)) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistGen: ST-Stack not empty.\n");
misc_FinishErrorReport();
}
else
if (st_CURRENT_RETRIEVAL != st_NOP) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistGen: %d Retrieval already in progress.\n",
st_CURRENT_RETRIEVAL);
misc_FinishErrorReport();
}
#endif
cont_Check();
if (st_Exist(StIndex)) {
st_CURRENT_RETRIEVAL = st_GEN;
st_WHICH_CONTEXTS = st_STANDARD;
st_INDEX_CONTEXT = IndexContext;
st_STACKSAVE = st_StackBottom();
FirstDomain = symbol_FirstIndexVariable();
cont_CreateBinding(IndexContext, FirstDomain, cont_InstanceContext(), Term);
cont_StartBinding();
st_StackPush(StIndex->subnodes);
cont_StartBinding();
Result = st_TraverseForExistGen(IndexContext);
#ifdef CHECK
cont_SaveState();
#endif
if (Result == NULL)
st_CancelExistRetrieval();
return Result;
} else
return NULL;
}
POINTER st_ExistGenPreTest(CONTEXT IndexContext, st_INDEX StIndex, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
SYMBOL FirstDomain;
POINTER Result;
#ifdef CHECK
if (!st_StackEmpty(st_STACKSAVE)) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistGenPreTest: ST-Stack not empty.\n");
misc_FinishErrorReport();
}
else
if (st_CURRENT_RETRIEVAL != st_NOP) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistGenPreTest: %d Retrieval already in progress.\n",
st_CURRENT_RETRIEVAL);
misc_FinishErrorReport();
}
#endif
cont_Check();
if (st_Exist(StIndex)) {
st_CURRENT_RETRIEVAL = st_GENPRETEST;
st_WHICH_CONTEXTS = st_STANDARD;
st_INDEX_CONTEXT = IndexContext;
st_STACKSAVE = st_StackBottom();
FirstDomain = symbol_FirstIndexVariable();
st_EXIST_MINMAX = term_ComputeSize(Term);
cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term);
cont_StartBinding();
st_StackPush(StIndex->subnodes);
cont_StartBinding();
Result = st_TraverseForExistGenPreTest(IndexContext);
#ifdef CHECK
cont_SaveState();
#endif
if (Result == NULL)
st_CancelExistRetrieval();
return Result;
} else
return NULL;
}
POINTER st_ExistInstance(CONTEXT IndexContext, st_INDEX StIndex, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
SYMBOL FirstDomain;
POINTER Result;
#ifdef CHECK
if (!st_StackEmpty(st_STACKSAVE)) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistInstance: ST-Stack not empty.\n");
misc_FinishErrorReport();
}
else
if (st_CURRENT_RETRIEVAL != st_NOP) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistInstance: %d Retrieval already in progress.\n",
st_CURRENT_RETRIEVAL);
misc_FinishErrorReport();
}
#endif
cont_Check();
if (st_Exist(StIndex)) {
st_CURRENT_RETRIEVAL = st_INSTANCE;
st_WHICH_CONTEXTS = st_STANDARD;
st_INDEX_CONTEXT = IndexContext;
st_STACKSAVE = st_StackBottom();
FirstDomain = symbol_FirstIndexVariable();
cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term);
cont_StartBinding();
st_StackPush(StIndex->subnodes);
cont_StartBinding();
Result = st_TraverseForExistInstance(IndexContext);
#ifdef CHECK
cont_SaveState();
#endif
if (Result == NULL)
st_CancelExistRetrieval();
return Result;
} else
return NULL;
}
POINTER st_ExistInstancePreTest(CONTEXT IndexContext, st_INDEX StIndex, TERM Term)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
SYMBOL FirstDomain;
POINTER Result;
#ifdef CHECK
if (!st_StackEmpty(st_STACKSAVE)) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistInstancePreTest: ST-Stack not empty.\n");
misc_FinishErrorReport();
}
else
if (st_CURRENT_RETRIEVAL != st_NOP) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_ExistInstancePreTest: %d Retrieval already in progress.\n",
st_CURRENT_RETRIEVAL);
misc_FinishErrorReport();
}
#endif
cont_Check();
if (st_Exist(StIndex)) {
st_CURRENT_RETRIEVAL = st_INSTANCEPRETEST;
st_WHICH_CONTEXTS = st_STANDARD;
st_INDEX_CONTEXT = IndexContext;
st_STACKSAVE = st_StackBottom();
FirstDomain = symbol_FirstIndexVariable();
st_EXIST_MINMAX = term_ComputeSize(Term);
cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term);
cont_StartBinding();
st_StackPush(StIndex->subnodes);
cont_StartBinding();
Result = st_TraverseForExistInstancePreTest(IndexContext);
#ifdef CHECK
cont_SaveState();
#endif
if (Result == NULL)
st_CancelExistRetrieval();
return Result;
} else
return NULL;
}
POINTER st_NextCandidate(void)
/**************************************************************
INPUT:
RETURNS:
EFFECTS:
***************************************************************/
{
LIST Result;
#ifdef CHECK
if (st_StackEmpty(st_STACKSAVE)) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_NextCandidate: ST-Stack empty.\n");
misc_FinishErrorReport();
}
else
if (st_CURRENT_RETRIEVAL == st_NOP) {
misc_StartErrorReport();
misc_ErrorReport("\n In st_NextCandidate: No retrieval in progress.\n");
misc_FinishErrorReport();
}
cont_CheckState();
#endif
Result = st_StackPopResult();
if (list_Exist(Result)) {
st_StackPush(list_Cdr(Result));
#ifdef CHECK
cont_SaveState();
#endif
return list_Car(Result);
} else {
POINTER NewResult;
NewResult = NULL;
if (st_WHICH_CONTEXTS == st_STANDARD)
switch (st_CURRENT_RETRIEVAL) {
case st_UNIFIER:
NewResult = st_TraverseForExistUnifier(st_INDEX_CONTEXT);
break;
case st_GEN:
NewResult = st_TraverseForExistGen(st_INDEX_CONTEXT);
break;
case st_GENPRETEST:
NewResult = st_TraverseForExistGenPreTest(st_INDEX_CONTEXT);
break;
case st_INSTANCE:
NewResult = st_TraverseForExistInstance(st_INDEX_CONTEXT);
break;
case st_INSTANCEPRETEST:
NewResult = st_TraverseForExistInstancePreTest(st_INDEX_CONTEXT);
default:
misc_StartErrorReport();
misc_ErrorReport("\n In st_NextCandidate: Unknown retrieval type.\n");
misc_FinishErrorReport();
}
else {
misc_StartErrorReport();
misc_ErrorReport("\n In st_NextCandidate: Unknown context type.\n");
misc_FinishErrorReport();
}
#ifdef CHECK
cont_SaveState();
#endif
if (NewResult == NULL)
st_CancelExistRetrieval();
return NewResult;
}
}
/**************************************************************/
/* ********************************************************** */
/* * * */
/* * OUTPUT * */
/* * * */
/* ********************************************************** */
/**************************************************************/
static void st_PrintHelp(st_INDEX St, int Position, void (*Print)(POINTER))
/**************************************************************
INPUT: A node of an St, an indention and a print
function for the entries.
SUMMARY: Prints an St starting at node St.
***************************************************************/
{
int i;
if (St == (st_INDEX)NULL)
return;
for (i = 0; i < Position; i++)
putchar(' ');
puts("|");
for (i = 0; i < Position; i++)
putchar(' ');
fputs("+-", stdout);
printf(" Max: %d, Min: %d, ", st_Max(St), st_Min(St));
subst_Print(St->subst);
putchar('\n');
if (st_IsLeaf(St)) {
LIST Scan;
for (i = 0; i < Position; i++)
putchar(' ');
fputs(" =>", stdout);
if (Print)
for (Scan = St->entries; Scan != NULL; Scan = list_Cdr(Scan)) {
putchar(' ');
Print(list_Car(Scan));
}
else
printf(" %d Entries", list_Length(St->entries));
putchar('\n');
} else {
LIST Scan;
for (Scan = St->subnodes; Scan != NULL; Scan = list_Cdr(Scan))
st_PrintHelp(list_Car(Scan), Position + 2, Print);
}
}
void st_Print(st_INDEX StIndex, void (*Print)(POINTER))
/**************************************************************
INPUT: The root of an St.
SUMMARY: Prints a whole St.
***************************************************************/
{
LIST Scan;
if (st_Empty(StIndex)) {
puts("\n\nIndex empty.");
return;
}
fputs("\n\nroot: ", stdout);
printf(" Max: %d, Min: %d, ", st_Max(StIndex), st_Min(StIndex));
subst_Print(StIndex->subst);
putchar('\n');
if (st_IsLeaf(StIndex)) {
fputs(" =>", stdout);
if (Print)
for (Scan = StIndex->entries; Scan != NULL; Scan = list_Cdr(Scan)) {
putchar(' ');
Print(list_Car(Scan));
}
else
printf(" %d Entries", list_Length(StIndex->entries));
} else
for (Scan = StIndex->subnodes; Scan != NULL; Scan = list_Cdr(Scan))
st_PrintHelp(list_Car(Scan),2, Print);
puts("\n");
}