Пример #1
0
static void UpdateRestrictionFlags(
  CONSTRAINT_RECORD *rv)
  {
   if ((rv->anyRestriction) && (rv->restrictionList == NULL))
     {
      SetAnyAllowedFlags(rv,TRUE);
      rv->anyAllowed = FALSE;
     }

   if ((rv->symbolRestriction) && (rv->symbolsAllowed))
     { rv->symbolsAllowed = FindItemInExpression(SYMBOL,NULL,FALSE,rv->restrictionList); }

   if ((rv->stringRestriction)  && (rv->stringsAllowed))
     { rv->stringsAllowed = FindItemInExpression(STRING,NULL,FALSE,rv->restrictionList); }

   if ((rv->floatRestriction) && (rv->floatsAllowed))
     { rv->floatsAllowed = FindItemInExpression(FLOAT,NULL,FALSE,rv->restrictionList); }

   if ((rv->integerRestriction) && (rv->integersAllowed))
     { rv->integersAllowed = FindItemInExpression(INTEGER,NULL,FALSE,rv->restrictionList); }

   if ((rv->instanceNameRestriction) && (rv->instanceNamesAllowed))
     { rv->instanceNamesAllowed = FindItemInExpression(INSTANCE_NAME,NULL,FALSE,rv->restrictionList); }

#if FUZZY_DEFTEMPLATES
   if ((rv->fuzzyValueRestriction) && (rv->fuzzyValuesAllowed))
     { rv->fuzzyValuesAllowed = FindItemInExpression(DEFTEMPLATE_PTR,NULL,FALSE,rv->restrictionList); }
#endif
  }
Пример #2
0
globle struct constraintRecord *GetConstraintRecord(
  void *theEnv,
  EXEC_STATUS)
  {
   CONSTRAINT_RECORD *constraints;
   unsigned i;

   constraints = get_struct(theEnv,execStatus,constraintRecord);

   for (i = 0 ; i < sizeof(CONSTRAINT_RECORD) ; i++)
     { ((char *) constraints)[i] = '\0'; }

   SetAnyAllowedFlags(constraints,TRUE);

   constraints->multifieldsAllowed = FALSE;
   constraints->singlefieldsAllowed = TRUE;

   constraints->anyRestriction = FALSE;
   constraints->symbolRestriction = FALSE;
   constraints->stringRestriction = FALSE;
   constraints->floatRestriction = FALSE;
   constraints->integerRestriction = FALSE;
   constraints->classRestriction = FALSE;
   constraints->instanceNameRestriction = FALSE;
   constraints->classList = NULL;
   constraints->restrictionList = NULL;
   constraints->minValue = GenConstant(theEnv,execStatus,SYMBOL,SymbolData(theEnv,execStatus)->NegativeInfinity);
   constraints->maxValue = GenConstant(theEnv,execStatus,SYMBOL,SymbolData(theEnv,execStatus)->PositiveInfinity);
   constraints->minFields = GenConstant(theEnv,execStatus,INTEGER,SymbolData(theEnv,execStatus)->Zero);
   constraints->maxFields = GenConstant(theEnv,execStatus,SYMBOL,SymbolData(theEnv,execStatus)->PositiveInfinity);
   constraints->bucket = -1;
   constraints->count = 0;
   constraints->multifield = NULL;
   constraints->next = NULL;

   return(constraints);
  }
Пример #3
0
globle struct constraintRecord *IntersectConstraints(
  void *theEnv,
  CONSTRAINT_RECORD *c1,
  CONSTRAINT_RECORD *c2)
  {
   struct constraintRecord *rv;
   int c1Changed = FALSE, c2Changed = FALSE;

   /*=================================================*/
   /* If both constraint records are NULL,then create */
   /* a constraint record that allows any value.      */
   /*=================================================*/

   if ((c1 == NULL) && (c2 == NULL))
     {
      rv = GetConstraintRecord(theEnv);
      rv->multifieldsAllowed = TRUE;
      return(rv);
     }

   /*=================================================*/
   /* If one of the constraint records is NULL, then  */
   /* the intersection is the other constraint record */
   /* (a NULL value means no constraints).            */
   /*=================================================*/

   if (c1 == NULL) return(CopyConstraintRecord(theEnv,c2));

   if (c2 == NULL) return(CopyConstraintRecord(theEnv,c1));

   /*=================================*/
   /* Create a new constraint record. */
   /*=================================*/

   rv = GetConstraintRecord(theEnv);

   /*==============================*/
   /* Intersect the allowed types. */
   /*==============================*/

   if ((c1->multifieldsAllowed != c2->multifieldsAllowed) &&
       (c1->singlefieldsAllowed != c2->singlefieldsAllowed))
     {
      rv->anyAllowed = FALSE;
      return(rv);
     }

   if (c1->multifieldsAllowed && c2->multifieldsAllowed)
     { rv->multifieldsAllowed = TRUE; }
   else
     { rv->multifieldsAllowed = FALSE; }

   if (c1->singlefieldsAllowed && c2->singlefieldsAllowed)
     { rv->singlefieldsAllowed = TRUE; }
   else
     { rv->singlefieldsAllowed = FALSE; }

   if (c1->anyAllowed && c2->anyAllowed) rv->anyAllowed = TRUE;
   else
     {
      if (c1->anyAllowed)
        {
         c1Changed = TRUE;
         SetAnyAllowedFlags(c1,FALSE);
        }
      else if (c2->anyAllowed)
        {
         c2Changed = TRUE;
         SetAnyAllowedFlags(c2,FALSE);
        }

      rv->anyAllowed = FALSE;
      rv->symbolsAllowed = (c1->symbolsAllowed && c2->symbolsAllowed);
      rv->stringsAllowed = (c1->stringsAllowed && c2->stringsAllowed);
      rv->floatsAllowed = (c1->floatsAllowed && c2->floatsAllowed);
      rv->integersAllowed = (c1->integersAllowed && c2->integersAllowed);
      rv->instanceNamesAllowed = (c1->instanceNamesAllowed && c2->instanceNamesAllowed);
      rv->instanceAddressesAllowed = (c1->instanceAddressesAllowed && c2->instanceAddressesAllowed);
      rv->externalAddressesAllowed = (c1->externalAddressesAllowed && c2->externalAddressesAllowed);
      rv->voidAllowed = (c1->voidAllowed && c2->voidAllowed);
      rv->multifieldsAllowed = (c1->multifieldsAllowed && c2->multifieldsAllowed);
      rv->factAddressesAllowed = (c1->factAddressesAllowed && c2->factAddressesAllowed);
#if FUZZY_DEFTEMPLATES
      rv->fuzzyValuesAllowed = (c1->fuzzyValuesAllowed && c2->fuzzyValuesAllowed);
#endif

      if (c1Changed) SetAnyAllowedFlags(c1,TRUE);
      if (c2Changed) SetAnyAllowedFlags(c2,TRUE);
     }

   /*=====================================*/
   /* Intersect the allowed-values flags. */
   /*=====================================*/

   if (c1->anyRestriction || c2->anyRestriction) rv->anyRestriction = TRUE;
   else
     {
      rv->anyRestriction = FALSE;
      rv->symbolRestriction = (c1->symbolRestriction || c2->symbolRestriction);
      rv->stringRestriction = (c1->stringRestriction || c2->stringRestriction);
      rv->floatRestriction = (c1->floatRestriction || c2->floatRestriction);
      rv->integerRestriction = (c1->integerRestriction || c2->integerRestriction);
      rv->classRestriction = (c1->classRestriction || c2->classRestriction);
      rv->instanceNameRestriction = (c1->instanceNameRestriction || c2->instanceNameRestriction);
#if FUZZY_DEFTEMPLATES
      rv->fuzzyValueRestriction = (c1->fuzzyValueRestriction || c2->fuzzyValueRestriction);
#endif
     }

   /*==================================================*/
   /* Intersect the allowed values list, allowed class */
   /* list, min and max values, and the range values.  */
   /*==================================================*/

   IntersectAllowedValueExpressions(theEnv,c1,c2,rv);
   IntersectAllowedClassExpressions(theEnv,c1,c2,rv);
   IntersectNumericExpressions(theEnv,c1,c2,rv,TRUE);
   IntersectNumericExpressions(theEnv,c1,c2,rv,FALSE);

   /*==========================================*/
   /* Update the allowed-values flags based on */
   /* the previous intersection for allowed,   */
   /* min and max, and range values.           */
   /*==========================================*/

   UpdateRestrictionFlags(rv);

   /*============================================*/
   /* If multifields are allowed, then intersect */
   /* the constraint record for them.            */
   /*============================================*/

   if (rv->multifieldsAllowed)
     {
      rv->multifield = IntersectConstraints(theEnv,c1->multifield,c2->multifield);
      if (UnmatchableConstraint(rv->multifield))
        { rv->multifieldsAllowed = FALSE; }
     }

   /*========================*/
   /* Return the intersected */
   /* constraint record.     */
   /*========================*/

   return(rv);
  }
Пример #4
0
static void UnionNumericExpressions(
  void *theEnv,
  CONSTRAINT_RECORD *constraint1,
  CONSTRAINT_RECORD *constraint2,
  CONSTRAINT_RECORD *newConstraint,
  int range)
  {
   struct expr *tmpmin, *tmpmax;
   struct expr *theMinList, *theMaxList;

   /*=========================================*/
   /* Initialize the new range/min/max values */
   /* for the union of the constraints.       */
   /*=========================================*/

   theMinList = NULL;
   theMaxList = NULL;

   /*=================================*/
   /* Determine the min/max values of */
   /* the first constraint record.    */
   /*=================================*/

   if (range)
     {
      tmpmin = constraint1->minValue;
      tmpmax = constraint1->maxValue;
     }
   else
     {
      tmpmin = constraint1->minFields;
      tmpmax = constraint1->maxFields;
     }

   /*============================================*/
   /* Add each range/min/max pair from the first */
   /* constraint record to the union list.       */
   /*============================================*/

   for (;
        tmpmin != NULL;
        tmpmin = tmpmin->nextArg,tmpmax = tmpmax->nextArg)
     { UnionRangeMinMaxValueWithList(theEnv,tmpmin,tmpmax,&theMinList,&theMaxList); }

   /*=================================*/
   /* Determine the min/max values of */
   /* the second constraint record.   */
   /*=================================*/

   if (range)
     {
      tmpmin = constraint2->minValue;
      tmpmax = constraint2->maxValue;
     }
   else
     {
      tmpmin = constraint2->minFields;
      tmpmax = constraint2->maxFields;
     }

   /*=============================================*/
   /* Add each range/min/max pair from the second */
   /* constraint record to the union list.        */
   /*=============================================*/

   for (;
        tmpmin != NULL;
        tmpmin = tmpmin->nextArg,tmpmax = tmpmax->nextArg)
     { UnionRangeMinMaxValueWithList(theEnv,tmpmin,tmpmax,&theMinList,&theMaxList); }

   /*=====================================================*/
   /* If the union produced a pair of valid range/min/max */
   /* values, then replace the previous values of the     */
   /* constraint record to the new unioned values.        */
   /*=====================================================*/

   if (theMinList != NULL)
     {
      if (range)
        {
         ReturnExpression(theEnv,newConstraint->minValue);
         ReturnExpression(theEnv,newConstraint->maxValue);
         newConstraint->minValue = theMinList;
         newConstraint->maxValue = theMaxList;
        }
      else
        {
         ReturnExpression(theEnv,newConstraint->minFields);
         ReturnExpression(theEnv,newConstraint->maxFields);
         newConstraint->minFields = theMinList;
         newConstraint->maxFields = theMaxList;
        }
     }

   /*==============================================================*/
   /* Otherwise, the union produced no valid range/min/max values. */
   /* For the range attribute, this means that no numbers can      */
   /* satisfy the constraint. For the min/max fields attribute, it */
   /* means that no value can satisfy the constraint.              */
   /*==============================================================*/

   else
     {
      if (range)
        {
         if (newConstraint->anyAllowed) SetAnyAllowedFlags(newConstraint,FALSE);
         newConstraint->integersAllowed = FALSE;
         newConstraint->floatsAllowed = FALSE;
        }
      else
        {
         SetAnyAllowedFlags(newConstraint,TRUE);
         newConstraint->anyAllowed = TRUE;
        }
     }
  }
Пример #5
0
static void IntersectNumericExpressions(
  void *theEnv,
  CONSTRAINT_RECORD *constraint1,
  CONSTRAINT_RECORD *constraint2,
  CONSTRAINT_RECORD *newConstraint,
  int range)
  {
   struct expr *tmpmin1, *tmpmax1, *tmpmin2, *tmpmax2, *theMin, *theMax;
   struct expr *theMinList, *theMaxList, *lastMin = NULL, *lastMax = NULL;
   int cmaxmax, cminmin, cmaxmin, cminmax;

   /*==========================================*/
   /* Initialize the new range/min/max values  */
   /* for the intersection of the constraints. */
   /*==========================================*/

   theMinList = NULL;
   theMaxList = NULL;

   /*=================================*/
   /* Determine the min/max values of */
   /* the first constraint record.    */
   /*=================================*/

   if (range)
     {
      tmpmin1 = constraint1->minValue;
      tmpmax1 = constraint1->maxValue;
     }
   else
     {
      tmpmin1 = constraint1->minFields;
      tmpmax1 = constraint1->maxFields;
     }

   /*===========================================*/
   /* Loop through each of range/min/max values */
   /* from the first constraint record.         */
   /*===========================================*/

   for (;
        tmpmin1 != NULL;
        tmpmin1 = tmpmin1->nextArg, tmpmax1 = tmpmax1->nextArg)
     {
      /*============================================*/
      /* Get the appropriate values from the second */
      /* constraint record for comparison.          */
      /*============================================*/

      if (range)
        {
         tmpmin2 = constraint2->minValue;
         tmpmax2 = constraint2->maxValue;
        }
      else
        {
         tmpmin2 = constraint2->minFields;
         tmpmax2 = constraint2->maxFields;
        }

      /*================================================*/
      /* Loop through each of range/min/max values from */
      /* the second constraint record comparing it to   */
      /* the values from the first constraint record.   */
      /*================================================*/

      for (;
           tmpmin2 != NULL;
           tmpmin2 = tmpmin2->nextArg, tmpmax2 = tmpmax2->nextArg)
        {
         /*==============================================*/
         /* Determine the relationship between the four  */
         /* combinations of min/max values (>, <, or =). */
         /*==============================================*/

         cmaxmax = CompareNumbers(theEnv,tmpmax1->type,tmpmax1->value,
                                  tmpmax2->type,tmpmax2->value);

         cminmin = CompareNumbers(theEnv,tmpmin1->type,tmpmin1->value,
                                  tmpmin2->type,tmpmin2->value);

         cmaxmin = CompareNumbers(theEnv,tmpmax1->type,tmpmax1->value,
                                  tmpmin2->type,tmpmin2->value);

         cminmax = CompareNumbers(theEnv,tmpmin1->type,tmpmin1->value,
                                  tmpmax2->type,tmpmax2->value);

         /*============================================*/
         /* If the range/min/max values don't overlap, */
         /* then proceed to the next pair of numbers   */
         /* to see if they overlap.                    */
         /*============================================*/

         if ((cmaxmin == LESS_THAN) || (cminmax == GREATER_THAN))
           { continue; }

         /*=======================================*/
         /* Compute the new minimum value for the */
         /* intersected range/min/max values.     */
         /*=======================================*/

         if (cminmin == GREATER_THAN)
           { theMin = GenConstant(theEnv,tmpmin1->type,tmpmin1->value); }
         else
           { theMin = GenConstant(theEnv,tmpmin2->type,tmpmin2->value); }

         /*=======================================*/
         /* Compute the new maximum value for the */
         /* intersected range/min/max values.     */
         /*=======================================*/

         if (cmaxmax == LESS_THAN)
           { theMax = GenConstant(theEnv,tmpmax1->type,tmpmax1->value); }
         else
           { theMax = GenConstant(theEnv,tmpmax2->type,tmpmax2->value); }

         /*==================================*/
         /* Add the new range/min/max values */
         /* to the intersection list.        */
         /*==================================*/

         if (lastMin == NULL)
           {
            theMinList = theMin;
            theMaxList = theMax;
           }
         else
           {
            lastMin->nextArg = theMin;
            lastMax->nextArg = theMax;
           }

         lastMin = theMin;
         lastMax = theMax;
        }
     }

   /*============================================================*/
   /* If the intersection produced a pair of valid range/min/max */
   /* values, then replace the previous values of the constraint */
   /* record to the new intersected values.                      */
   /*============================================================*/

   if (theMinList != NULL)
     {
      if (range)
        {
         ReturnExpression(theEnv,newConstraint->minValue);
         ReturnExpression(theEnv,newConstraint->maxValue);
         newConstraint->minValue = theMinList;
         newConstraint->maxValue = theMaxList;
        }
      else
        {
         ReturnExpression(theEnv,newConstraint->minFields);
         ReturnExpression(theEnv,newConstraint->maxFields);
         newConstraint->minFields = theMinList;
         newConstraint->maxFields = theMaxList;
        }
     }

   /*===============================================================*/
   /* Otherwise, the intersection produced no valid range/min/max   */
   /* values. For the range attribute, this means that no numbers   */
   /* can satisfy the constraint. For the min/max fields attribute, */
   /* it means that no value can satisfy the constraint.            */
   /*===============================================================*/

   else
     {
      if (range)
        {
         if (newConstraint->anyAllowed) SetAnyAllowedFlags(newConstraint,FALSE);
         newConstraint->integersAllowed = FALSE;
         newConstraint->floatsAllowed = FALSE;
        }
      else
        {
         SetAnyAllowedFlags(newConstraint,TRUE);
         newConstraint->singlefieldsAllowed = FALSE;
         newConstraint->multifieldsAllowed = FALSE;
         newConstraint->anyAllowed = FALSE;
        }
     }
  }