Exemple #1
0
globle void NetworkAssert(
  void *theEnv,
  struct partialMatch *binds,
  struct joinNode *join)
  {
   /*=========================================================*/
   /* If an incremental reset is being performed and the join */
   /* is not part of the network to be reset, then return.    */
   /*=========================================================*/

#if (! BLOAD_ONLY) && (! RUN_TIME)
   if (EngineData(theEnv)->IncrementalResetInProgress && (join->initialize == FALSE)) return;
#endif

   /*==================================================*/
   /* Use a special routine if this is the first join. */
   /*==================================================*/

   if (join->firstJoin)
     {
      EmptyDrive(theEnv,join,binds);
      return;
     }

   /*================================*/
   /* Enter the join from the right. */
   /*================================*/

   NetworkAssertRight(theEnv,binds,join);

   return;
  }
Exemple #2
0
globle void NetworkAssert(
  struct partialMatch *binds,
  struct joinNode *join,
  int enterDirection)
  {
   struct partialMatch *lhsBinds = NULL, *rhsBinds = NULL;
   struct partialMatch *comparePMs = NULL, *newBinds;
   int exprResult;

   /*=========================================================*/
   /* If an incremental reset is being performed and the join */
   /* is not part of the network to be reset, then return.    */
   /*=========================================================*/

#if INCREMENTAL_RESET && (! BLOAD_ONLY) && (! RUN_TIME)
   if (IncrementalResetInProgress && (join->initialize == FALSE)) return;
#endif

   /*=========================================================*/
   /* If the associated LHS pattern is a not CE or the join   */
   /* is a nand join, then we need an additional field in the */
   /* partial match to keep track of the pseudo fact if one   */
   /* is created. The partial match is automatically stored   */
   /* in the beta memory and the counterf slot is used to     */
   /* determine if it is an actual partial match. If counterf */
   /* is TRUE, there are one or more fact or instances        */
   /* keeping the not or nand join from being satisfied.      */
   /*=========================================================*/

   if ((enterDirection == LHS) &&
       ((join->patternIsNegated) || (join->joinFromTheRight)))
     {
      newBinds = AddSingleMatch(binds,NULL,
                                (join->ruleToActivate == NULL) ? 0 : 1,
                                (int) join->logicalJoin);
      newBinds->notOriginf = TRUE;
      newBinds->counterf = TRUE;
      binds = newBinds;
      binds->next = join->beta;
      join->beta = binds;
     }

   /*==================================================*/
   /* Use a special routine if this is the first join. */
   /*==================================================*/

   if (join->firstJoin)
     {
      EmptyDrive(join,binds);
      return;
     }

   /*==================================================*/
   /* Initialize some variables used to indicate which */
   /* side is being compared to the new partial match. */
   /*==================================================*/

   if (enterDirection == LHS)
     {
      if (join->joinFromTheRight)
        { comparePMs = ((struct joinNode *) join->rightSideEntryStructure)->beta;}
      else
        { comparePMs = ((struct patternNodeHeader *) join->rightSideEntryStructure)->alphaMemory; }
      lhsBinds = binds;
     }
   else if (enterDirection == RHS)
     {
      if (join->patternIsNegated || join->joinFromTheRight)
        { comparePMs = join->beta; }
      else
        { comparePMs = join->lastLevel->beta; }
      rhsBinds = binds;
     }
   else
     {
      SystemError("DRIVE",1);
      ExitRouter(EXIT_FAILURE);
     }

   /*===================================================*/
   /* Compare each set of binds on the opposite side of */
   /* the join with the set of binds that entered this  */
   /* join. If the binds don't mismatch, then perform   */
   /* the appropriate action for the logic of the join. */
   /*===================================================*/

   while (comparePMs != NULL)
     {
      /*===========================================================*/
      /* Initialize some variables pointing to the partial matches */
      /* in the LHS and RHS of the join. In addition, check for    */
      /* certain conditions under which the partial match can be   */
      /* skipped since it's not a "real" partial match.            */
      /*===========================================================*/

      if (enterDirection == RHS)
        {
         lhsBinds = comparePMs;

         /*=====================================================*/
         /* The partial matches entering from the LHS of a join */
         /* are stored in the beta memory of the previous join  */
         /* (unless the current join is a join from the right   */
         /* or is attached to a not CE). If the previous join   */
         /* is a join from the right or associated with a not   */
         /* CE, then some of its partial matches in its beta    */
         /* memory will not be "real" partial matches. That is, */
         /* there may be a partial match in the alpha memory    */
         /* that prevents the partial match from satisfying the */
         /* join's conditions. If this is the case, then the    */
         /* counterf flag in the partial match will be set to   */
         /* TRUE and in this case, we move on to the next       */
         /* partial match to be checked.                        */
         /*=====================================================*/

         if (lhsBinds->counterf &&
             (join->patternIsNegated == FALSE) &&
             (join->joinFromTheRight == FALSE))
           {
            comparePMs = comparePMs->next;
            continue;
           }

        /*==================================================*/
        /* If the join is associated with a not CE or has a */
        /* join from the right, then the LHS partial match  */
        /* currently being checked may already have a       */
        /* partial match from the alpha memory preventing   */
        /* it from being satisfied. If this is the case,    */
        /* then move on to the next partial match in the    */
        /* beta memory of the join.                         */
        /*==================================================*/

        if ((join->patternIsNegated || join->joinFromTheRight) &&
            (lhsBinds->counterf))
          {
           comparePMs = comparePMs->next;
           continue;
          }
        }
      else
        { rhsBinds = comparePMs; }

      /*========================================================*/
      /* If the join has no expression associated with it, then */
      /* the new partial match derived from the LHS and RHS     */
      /* partial matches is valid. In the event that the join   */
      /* is a join from the right, it must also be checked that */
      /* the RHS partial match is the same partial match that   */
      /* the LHS partial match was generated from. Each LHS     */
      /* partial match in a join from the right corresponds     */
      /* uniquely to a partial match from the RHS of the join.  */
      /* To determine whether the LHS partial match is the one  */
      /* associated with the RHS partial match, we compare the  */
      /* the entity addresses found in the partial matches to   */
      /* make sure they're equal.                               */
      /*========================================================*/

      if (join->networkTest == NULL)
        {
         exprResult = TRUE;
         if (join->joinFromTheRight)
           {
            int i;

            for (i = 0; i < (int) (lhsBinds->bcount - 1); i++)
              {
               if (lhsBinds->binds[i].gm.theMatch != rhsBinds->binds[i].gm.theMatch)
                 {
                  exprResult = FALSE;
                  break;
                 }
              }
           }
        }

      /*=========================================================*/
      /* If the join has an expression associated with it, then  */
      /* evaluate the expression to determine if the new partial */
      /* match derived from the LHS and RHS partial matches is   */
      /* valid (i.e. variable bindings are consistent and        */
      /* predicate expressions evaluate to TRUE).                */
      /*=========================================================*/

      else
        {
         exprResult = EvaluateJoinExpression(join->networkTest,lhsBinds,rhsBinds,join);
         if (EvaluationError)
           {
            if (join->patternIsNegated) exprResult = TRUE;
            SetEvaluationError(FALSE);
           }
        }

      /*====================================================*/
      /* If the join expression evaluated to TRUE (i.e.     */
      /* there were no conflicts between variable bindings, */
      /* all tests were satisfied, etc.), then perform the  */
      /* appropriate action given the logic of this join.   */
      /*====================================================*/

      if (exprResult != FALSE)
        {
         /*==============================================*/
         /* Use the PPDrive routine when the join isn't  */
         /* associated with a not CE and it doesn't have */
         /* a join from the right.                       */
         /*==============================================*/

         if ((join->patternIsNegated == FALSE) &&
             (join->joinFromTheRight == FALSE))
           { PPDrive(lhsBinds,rhsBinds,join); }

         /*=====================================================*/
         /* Use the PNRDrive routine when the new partial match */
         /* enters from the RHS of the join and the join either */
         /* is associated with a not CE or has a join from the  */
         /* right.                                              */
         /*=====================================================*/

         else if (enterDirection == RHS)
           { PNRDrive(join,comparePMs,rhsBinds); }

         /*===========================================================*/
         /* If the new partial match entered from the LHS of the join */
         /* and the join is either associated with a not CE or the    */
         /* join has a join from the right, then mark the LHS partial */
         /* match indicating that there is a RHS partial match        */
         /* preventing this join from being satisfied. Once this has  */
         /* happened, the other RHS partial matches don't have to be  */
         /* tested since it only takes one partial match to prevent   */
         /* the LHS from being satisfied.                             */
         /*===========================================================*/

         else if (enterDirection == LHS)
           {
            binds->binds[binds->bcount - 1].gm.theValue = (void *) rhsBinds;
            comparePMs = NULL;
            continue;
           }
        }

      /*====================================*/
      /* Move on to the next partial match. */
      /*====================================*/

      comparePMs = comparePMs->next;
     }

   /*==================================================================*/
   /* If a join with an associated not CE or join from the right was   */
   /* entered from the LHS side of the join, and the join expression   */
   /* failed for all sets of matches for the new bindings on the LHS   */
   /* side (there was no RHS partial match preventing the LHS partial  */
   /* match from being satisfied), then the LHS partial match appended */
   /* with an pseudo-fact that represents the instance of the not      */
   /* pattern or join from the right that was satisfied should be sent */
   /* to the joins below this join.                                    */
   /*==================================================================*/

   if ((join->patternIsNegated || join->joinFromTheRight) &&
       (enterDirection == LHS) &&
       (binds->binds[binds->bcount - 1].gm.theValue == NULL))
     { PNLDrive(join,binds); }

   return;
  }
Exemple #3
0
globle void NetworkAssertRight(
  void *theEnv,
  struct partialMatch *rhsBinds,
  struct joinNode *join)
  {
   struct partialMatch *lhsBinds, *nextBind;
   int exprResult, restore = FALSE;
   struct partialMatch *oldLHSBinds = NULL;
   struct partialMatch *oldRHSBinds = NULL;
   struct joinNode *oldJoin = NULL;

   /*=========================================================*/
   /* If an incremental reset is being performed and the join */
   /* is not part of the network to be reset, then return.    */
   /*=========================================================*/

#if (! BLOAD_ONLY) && (! RUN_TIME)
   if (EngineData(theEnv)->IncrementalResetInProgress && (join->initialize == FALSE)) return;
#endif

   if (join->firstJoin)
     {
      EmptyDrive(theEnv,join,rhsBinds);
      return;
     }
  
   /*=====================================================*/
   /* The partial matches entering from the LHS of a join */
   /* are stored in the left beta memory of the join.     */
   /*=====================================================*/

   lhsBinds = GetLeftBetaMemory(join,rhsBinds->hashValue);

#if DEVELOPER
   if (lhsBinds != NULL)
     { EngineData(theEnv)->rightToLeftLoops++; }
#endif

   /*====================================*/
   /* Set up the evaluation environment. */
   /*====================================*/
   
   if (lhsBinds != NULL)
     {
      oldLHSBinds = EngineData(theEnv)->GlobalLHSBinds;
      oldRHSBinds = EngineData(theEnv)->GlobalRHSBinds;
      oldJoin = EngineData(theEnv)->GlobalJoin;
      EngineData(theEnv)->GlobalRHSBinds = rhsBinds;
      EngineData(theEnv)->GlobalJoin = join;
      restore = TRUE;
     }
    
   /*===================================================*/
   /* Compare each set of binds on the opposite side of */
   /* the join with the set of binds that entered this  */
   /* join. If the binds don't mismatch, then perform   */
   /* the appropriate action for the logic of the join. */
   /*===================================================*/

   while (lhsBinds != NULL)
     {
      nextBind = lhsBinds->nextInMemory;
      join->memoryCompares++;
      
      /*===========================================================*/
      /* Initialize some variables pointing to the partial matches */
      /* in the LHS and RHS of the join.                           */
      /*===========================================================*/

      if (lhsBinds->hashValue != rhsBinds->hashValue)
        {
#if DEVELOPER
         if (join->leftMemory->size == 1)
           { EngineData(theEnv)->betaHashListSkips++; }
         else
           { EngineData(theEnv)->betaHashHTSkips++; }
           
         if (lhsBinds->marker != NULL)
           { EngineData(theEnv)->unneededMarkerCompare++; }
#endif
         lhsBinds = nextBind;
         continue;
        }
        
      /*===============================================================*/
      /* If there already is an associated RHS partial match stored in */
      /* the LHS partial match from the beta memory of this join, then */
      /* the exists/nand CE has already been satisfied and we can move */
      /* on to the next partial match found in the beta memory.        */
      /*===============================================================*/
        
      if (lhsBinds->marker != NULL)
        { 
#if DEVELOPER
         EngineData(theEnv)->unneededMarkerCompare++;
#endif
         lhsBinds = nextBind;
         continue;
        }

      /*===================================================*/
      /* If the join has no expression associated with it, */
      /* then the new partial match derived from the LHS   */
      /* and RHS partial matches is valid.                 */
      /*===================================================*/

      if (join->networkTest == NULL)
        { exprResult = TRUE; }

      /*=========================================================*/
      /* If the join has an expression associated with it, then  */
      /* evaluate the expression to determine if the new partial */
      /* match derived from the LHS and RHS partial matches is   */
      /* valid (i.e. variable bindings are consistent and        */
      /* predicate expressions evaluate to TRUE).                */
      /*=========================================================*/

      else
        {
#if DEVELOPER
         EngineData(theEnv)->rightToLeftComparisons++;
#endif
         EngineData(theEnv)->GlobalLHSBinds = lhsBinds;
         exprResult = EvaluateJoinExpression(theEnv,join->networkTest,join);
         if (EvaluationData(theEnv)->EvaluationError)
           {
            if (join->patternIsNegated) exprResult = TRUE;
            SetEvaluationError(theEnv,FALSE);
           }

#if DEVELOPER
         if (exprResult)
           { EngineData(theEnv)->rightToLeftSucceeds++; }
#endif
        }

      if ((join->secondaryNetworkTest != NULL) && exprResult)
        {
         EngineData(theEnv)->GlobalLHSBinds = lhsBinds;
         exprResult = EvaluateJoinExpression(theEnv,join->secondaryNetworkTest,join);
         if (EvaluationData(theEnv)->EvaluationError)
           { SetEvaluationError(theEnv,FALSE); }
        }

      /*====================================================*/
      /* If the join expression evaluated to TRUE (i.e.     */
      /* there were no conflicts between variable bindings, */
      /* all tests were satisfied, etc.), then perform the  */
      /* appropriate action given the logic of this join.   */
      /*====================================================*/

      if (exprResult != FALSE)
        {
         if (join->patternIsExists)
           {
            AddBlockedLink(lhsBinds,rhsBinds);
            PPDrive(theEnv,lhsBinds,NULL,join);
           }
         else if (join->patternIsNegated || join->joinFromTheRight)
           {
            AddBlockedLink(lhsBinds,rhsBinds);
            if (lhsBinds->children != NULL)
              { PosEntryRetractBeta(theEnv,lhsBinds,lhsBinds->children); }
            /*
            if (lhsBinds->dependents != NULL) 
              { RemoveLogicalSupport(theEnv,lhsBinds); }
            */
           } 
         else
           { PPDrive(theEnv,lhsBinds,rhsBinds,join); }
        }

      /*====================================*/
      /* Move on to the next partial match. */
      /*====================================*/

      lhsBinds = nextBind;
     }

   /*=========================================*/
   /* Restore the old evaluation environment. */
   /*=========================================*/

   if (restore)
     {
      EngineData(theEnv)->GlobalLHSBinds = oldLHSBinds;
      EngineData(theEnv)->GlobalRHSBinds = oldRHSBinds;
      EngineData(theEnv)->GlobalJoin = oldJoin;
     }
     
   return;
  }