static void DetachJoins( void *theEnv, struct joinNode *join, intBool destroy) { struct joinNode *prevJoin, *rightJoin; struct joinLink *lastLink, *theLink; int lastMark; /*===========================*/ /* Begin removing the joins. */ /*===========================*/ while (join != NULL) { if (join->marked) return; /*==========================================================*/ /* Remember the join "above" this join (the one that enters */ /* from the left). If the join is entered from the right by */ /* another join, remember the right entering join as well. */ /*==========================================================*/ prevJoin = join->lastLevel; if (join->joinFromTheRight) { rightJoin = (struct joinNode *) join->rightSideEntryStructure; } else { rightJoin = NULL; } /*=================================================*/ /* If the join was attached to a pattern, remove */ /* any structures associated with the pattern that */ /* are no longer needed. */ /*=================================================*/ #if (! RUN_TIME) && (! BLOAD_ONLY) if (! destroy) { if ((join->rightSideEntryStructure != NULL) && (join->joinFromTheRight == FALSE)) { RemoveIntranetworkLink(theEnv,join); } } #endif /*======================================*/ /* Remove any partial matches contained */ /* in the beta memory of the join. */ /*======================================*/ if (destroy) { DestroyBetaMemory(theEnv,join,LHS); DestroyBetaMemory(theEnv,join,RHS); } else { FlushBetaMemory(theEnv,join,LHS); FlushBetaMemory(theEnv,join,RHS); } ReturnLeftMemory(theEnv,join); ReturnRightMemory(theEnv,join); /*===================================*/ /* Remove the expressions associated */ /* with the join. */ /*===================================*/ #if (! RUN_TIME) && (! BLOAD_ONLY) if (! destroy) { RemoveHashedExpression(theEnv,join->networkTest); RemoveHashedExpression(theEnv,join->secondaryNetworkTest); RemoveHashedExpression(theEnv,join->leftHash); RemoveHashedExpression(theEnv,join->rightHash); } #endif /*============================*/ /* Fix the right prime links. */ /*============================*/ if (join->firstJoin && (join->rightSideEntryStructure == NULL)) { lastLink = NULL; theLink = DefruleData(theEnv)->RightPrimeJoins; while (theLink != NULL) { if (theLink->join == join) { if (lastLink == NULL) { DefruleData(theEnv)->RightPrimeJoins = theLink->next; } else { lastLink->next = theLink->next; } #if (! RUN_TIME) && (! BLOAD_ONLY) rtn_struct(theEnv,joinLink,theLink); #endif theLink = NULL; } else { lastLink = theLink; theLink = lastLink->next; } } } /*===========================*/ /* Fix the left prime links. */ /*===========================*/ if (join->firstJoin && (join->patternIsNegated || join->joinFromTheRight) && (! join->patternIsExists)) { lastLink = NULL; theLink = DefruleData(theEnv)->LeftPrimeJoins; while (theLink != NULL) { if (theLink->join == join) { if (lastLink == NULL) { DefruleData(theEnv)->LeftPrimeJoins = theLink->next; } else { lastLink->next = theLink->next; } #if (! RUN_TIME) && (! BLOAD_ONLY) rtn_struct(theEnv,joinLink,theLink); #endif theLink = NULL; } else { lastLink = theLink; theLink = theLink->next; } } } /*==================================================*/ /* Remove the link to the join from the join above. */ /*==================================================*/ if (prevJoin != NULL) { lastLink = NULL; theLink = prevJoin->nextLinks; while (theLink != NULL) { if (theLink->join == join) { if (lastLink == NULL) { prevJoin->nextLinks = theLink->next; } else { lastLink->next = theLink->next; } #if (! RUN_TIME) && (! BLOAD_ONLY) rtn_struct(theEnv,joinLink,theLink); #endif theLink = NULL; } else { lastLink = theLink; theLink = theLink->next; } } } /*==========================================*/ /* Remove the right join link if it exists. */ /*==========================================*/ if (rightJoin != NULL) { lastLink = NULL; theLink = rightJoin->nextLinks; while (theLink != NULL) { if (theLink->join == join) { if (lastLink == NULL) { rightJoin->nextLinks = theLink->next; } else { lastLink->next = theLink->next; } #if (! RUN_TIME) && (! BLOAD_ONLY) rtn_struct(theEnv,joinLink,theLink); #endif theLink = NULL; } else { lastLink = theLink; theLink = theLink->next; } } if ((rightJoin->nextLinks == NULL) && (rightJoin->ruleToActivate == NULL)) { if (prevJoin != NULL) { lastMark = prevJoin->marked; prevJoin->marked = TRUE; DetachJoins(theEnv,rightJoin,destroy); prevJoin->marked = lastMark; } else { DetachJoins(theEnv,rightJoin,destroy); } } } /*==================*/ /* Delete the join. */ /*==================*/ #if (! RUN_TIME) && (! BLOAD_ONLY) rtn_struct(theEnv,joinNode,join); #endif /*===========================================================*/ /* Move on to the next join to be removed. All the joins of */ /* a rule can be deleted by following the right joins links */ /* (when these links exist) and then following the left join */ /* links. This works because if join A enters join B from */ /* the right, the right/left links of join A eventually lead */ /* to the join which enters join B from the left. */ /*===========================================================*/ if (prevJoin == NULL) { return; } else if (prevJoin->ruleToActivate != NULL) { return; } else if (prevJoin->nextLinks == NULL) { join = prevJoin; } else { return; } } }
static void DetachJoins( struct defrule *theRule) { struct joinNode *join; struct joinNode *prevJoin; struct joinNode *joinPtr, *lastJoin, *rightJoin; /*==================================*/ /* Find the last join for the rule. */ /*==================================*/ join = theRule->lastJoin; theRule->lastJoin = NULL; if (join == NULL) return; /*===================================================*/ /* Remove the activation link from the last join. If */ /* there are joins below this join, then all of the */ /* joins for this rule were shared with another rule */ /* and thus no joins can be deleted. */ /*===================================================*/ join->ruleToActivate = NULL; if (join->nextLevel != NULL) return; /*===========================*/ /* Begin removing the joins. */ /*===========================*/ while (join != NULL) { /*==========================================================*/ /* Remember the join "above" this join (the one that enters */ /* from the left). If the join is entered from the right by */ /* another join, remember the right entering join as well. */ /*==========================================================*/ prevJoin = join->lastLevel; if (join->joinFromTheRight) { rightJoin = (struct joinNode *) join->rightSideEntryStructure; } else { rightJoin = NULL; } /*=================================================*/ /* If the join was attached to a pattern, remove */ /* any structures associated with the pattern that */ /* are no longer needed. */ /*=================================================*/ if ((join->rightSideEntryStructure != NULL) && (join->joinFromTheRight == FALSE)) { RemoveIntranetworkLink(join); } /*======================================*/ /* Remove any partial matches contained */ /* in the beta memory of the join. */ /*======================================*/ FlushAlphaBetaMemory(join->beta); join->beta = NULL; /*===================================*/ /* Remove the expressions associated */ /* with the join. */ /*===================================*/ RemoveHashedExpression(join->networkTest); /*==================================================*/ /* Remove the link to the join from the join above. */ /*==================================================*/ if (prevJoin == NULL) { rtn_struct(joinNode,join); return; } lastJoin = NULL; joinPtr = prevJoin->nextLevel; while (joinPtr != NULL) { if (joinPtr == join) { if (lastJoin == NULL) { prevJoin->nextLevel = joinPtr->rightDriveNode; } else { lastJoin->rightDriveNode = joinPtr->rightDriveNode; } joinPtr = NULL; } else { lastJoin = joinPtr; joinPtr = joinPtr->rightDriveNode; } } /*==================*/ /* Delete the join. */ /*==================*/ rtn_struct(joinNode,join); /*==========================================*/ /* Remove the right join link if it exists. */ /*==========================================*/ if (rightJoin != NULL) { rightJoin->nextLevel = NULL; prevJoin = rightJoin; } /*===========================================================*/ /* Move on to the next join to be removed. All the joins of */ /* a rule can be deleted by following the right joins links */ /* (when these links exist) and then following the left join */ /* links. This works because if join A enters join B from */ /* the right, the right/left links of join A eventually lead */ /* to the join which enters join B from the left. */ /*===========================================================*/ if (prevJoin->ruleToActivate != NULL) { join = NULL; } else if (prevJoin->nextLevel == NULL) { join = prevJoin; } else { join = NULL; } } }