/**************************************************************/ /* ********************************************************** */ /* * * */ /* * 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: 21527 $ * */ /* $State$ * */ /* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ /* $Author: duraid $ * */ /* * * */ /* * 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"); }