示例#1
0
文件: clsltpsr.c 项目: DrItanium/maya
/**************************************************************
  NAME         : NewSlot
  DESCRIPTION  : Allocates and initalizes a new slot structure
  INPUTS       : The symbolic name of the new slot
  RETURNS      : The address of the new slot
  SIDE EFFECTS : None
  NOTES        : Also adds symbols of the form get-<name> and
                   put-<name> for slot accessors
 **************************************************************/
static SlotDescriptor *NewSlot(
  Environment *theEnv,
  CLIPSLexeme *name)
  {
   SlotDescriptor *slot;

   slot = get_struct(theEnv,slotDescriptor);
   slot->dynamicDefault = 1;
   slot->defaultSpecified = 0;
   slot->noDefault = 0;
#if DEFRULE_CONSTRUCT
   slot->reactive = 1;
#endif
   slot->noInherit = 0;
   slot->noWrite = 0;
   slot->initializeOnly = 0;
   slot->shared = 0;
   slot->multiple = 0;
   slot->composite = 0;
   slot->sharedCount = 0;
   slot->publicVisibility = 0;
   slot->createReadAccessor = false;
   slot->createWriteAccessor = false;
   slot->overrideMessageSpecified = 0;
   slot->cls = NULL;
   slot->defaultValue = NULL;
   slot->constraint = GetConstraintRecord(theEnv);
   slot->slotName = AddSlotName(theEnv,name,0,false);
   slot->overrideMessage = slot->slotName->putHandlerName;
   IncrementLexemeCount(slot->overrideMessage);
   return(slot);
  }
示例#2
0
文件: clsltpsr.c 项目: atrniv/CLIPS
/**************************************************************
  NAME         : NewSlot
  DESCRIPTION  : Allocates and initalizes a new slot structure
  INPUTS       : The symbolic name of the new slot
  RETURNS      : The address of the new slot
  SIDE EFFECTS : None
  NOTES        : Also adds symbols of the form get-<name> and
                   put-<name> for slot accessors
 **************************************************************/
static SLOT_DESC *NewSlot(
  void *theEnv,
  EXEC_STATUS,
  SYMBOL_HN *name)
  {
   SLOT_DESC *slot;

   slot = get_struct(theEnv,execStatus,slotDescriptor);
   slot->dynamicDefault = 1;
   slot->defaultSpecified = 0;
   slot->noDefault = 0;
#if DEFRULE_CONSTRUCT
   slot->reactive = 1;
#endif
   slot->noInherit = 0;
   slot->noWrite = 0;
   slot->initializeOnly = 0;
   slot->shared = 0;
   slot->multiple = 0;
   slot->composite = 0;
   slot->sharedCount = 0;
   slot->publicVisibility = 0;
   slot->createReadAccessor = FALSE;
   slot->createWriteAccessor = FALSE;
   slot->overrideMessageSpecified = 0;
   slot->cls = NULL;
   slot->defaultValue = NULL;
   slot->constraint = GetConstraintRecord(theEnv,execStatus);
   slot->slotName = AddSlotName(theEnv,execStatus,name,0,FALSE);
   slot->overrideMessage = slot->slotName->putHandlerName;
   IncrementSymbolCount(slot->overrideMessage);
   return(slot);
  }
示例#3
0
CONSTRAINT_RECORD *ArgumentTypeToConstraintRecord2(
  void *theEnv,
  unsigned bitTypes)
  {
   CONSTRAINT_RECORD *rv;

   rv = GetConstraintRecord(theEnv);
   rv->anyAllowed = false;

   if (bitTypes & VOID_TYPE)
     { rv->voidAllowed = true; }
   if (bitTypes & FLOAT_TYPE)
     { rv->floatsAllowed = true; }
   if (bitTypes & INTEGER_TYPE)
     { rv->integersAllowed = true; }
   if (bitTypes & SYMBOL_TYPE)
     { rv->symbolsAllowed = true; }
   if (bitTypes & STRING_TYPE)
     { rv->stringsAllowed = true; }
   if (bitTypes & MULTIFIELD_TYPE)
     { rv->multifieldsAllowed = true; }
   if (bitTypes & EXTERNAL_ADDRESS_TYPE)
     { rv->externalAddressesAllowed = true; }
   if (bitTypes & FACT_ADDRESS_TYPE)
     { rv->factAddressesAllowed = true; }
   if (bitTypes & INSTANCE_ADDRESS_TYPE)
     { rv->instanceAddressesAllowed = true; }
   if (bitTypes & INSTANCE_NAME_TYPE)
     { rv->instanceNamesAllowed = true; }
   if (bitTypes & BOOLEAN_TYPE)
     { rv->symbolsAllowed = true; }
     
   if (bitTypes == ANY_TYPE)
     { rv->anyAllowed = true; }

   return(rv);
  }
示例#4
0
struct lhsParseNode *RestrictionParse(
  char *readSource,
  struct token *theToken,
  int multifieldSlot,
  struct symbolHashNode *theSlot,
  int slotNumber,
  CONSTRAINT_RECORD *theConstraints,
  int position)
  {
   struct lhsParseNode *topNode = NULL, *lastNode = NULL, *nextNode;
   int numberOfSingleFields = 0;
   int numberOfMultifields = 0;
   int startPosition = position;
   int error = FALSE;
   CONSTRAINT_RECORD *tempConstraints;

   /*==================================================*/
   /* Keep parsing fields until a right parenthesis is */
   /* encountered. This will either indicate the end   */
   /* of an instance or deftemplate slot or the end of */
   /* an ordered fact.                                 */
   /*==================================================*/

   while (theToken->type != RPAREN)
     {
      /*========================================*/
      /* Look for either a single or multifield */
      /* wildcard or a conjuctive restriction.  */
      /*========================================*/

      if ((theToken->type == SF_WILDCARD) ||
          (theToken->type == MF_WILDCARD))
        {
         nextNode = GetLHSParseNode();
         nextNode->type = theToken->type;
         nextNode->negated = FALSE;
         GetToken(readSource,theToken);
        }
      else
        {
         nextNode = ConjuctiveRestrictionParse(readSource,theToken,&error);
         if (nextNode == NULL)
           {
            ReturnLHSParseNodes(topNode);
            return(NULL);
           }
        }

      /*========================================================*/
      /* Fix up the pretty print representation of a multifield */
      /* slot so that the fields don't run together.            */
      /*========================================================*/

      if ((theToken->type != RPAREN) && (multifieldSlot == TRUE))
        {
         PPBackup();
         SavePPBuffer(" ");
         SavePPBuffer(theToken->printForm);
        }

      /*========================================*/
      /* Keep track of the number of single and */
      /* multifield restrictions encountered.   */
      /*========================================*/

      if ((nextNode->type == SF_WILDCARD) || (nextNode->type == SF_VARIABLE))
        { numberOfSingleFields++; }
      else
        { numberOfMultifields++; }

      /*===================================*/
      /* Assign the slot name and indices. */
      /*===================================*/

      nextNode->slot = theSlot;
      nextNode->slotNumber = slotNumber;
      nextNode->index = position++;

      /*==============================================*/
      /* If we're not dealing with a multifield slot, */
      /* attach the constraints directly to the node  */
      /* and return.                                  */
      /*==============================================*/

      if (! multifieldSlot)
        {
         if (theConstraints == NULL)
           {
            if (nextNode->type == SF_VARIABLE)
              { nextNode->constraints = GetConstraintRecord(); }
            else nextNode->constraints = NULL;
           }
         else nextNode->constraints = theConstraints;
         return(nextNode);
        }

      /*====================================================*/
      /* Attach the restriction to the list of restrictions */
      /* already parsed for this slot or ordered fact.      */
      /*====================================================*/

      if (lastNode == NULL) topNode = nextNode;
      else lastNode->right = nextNode;

      lastNode = nextNode;
     }

   /*=====================================================*/
   /* Once we're through parsing, check to make sure that */
   /* a single field slot was given a restriction. If the */
   /* following test fails, then we know we're dealing    */
   /* with a multifield slot.                             */
   /*=====================================================*/

   if ((topNode == NULL) && (! multifieldSlot))
     {
      SyntaxErrorMessage("defrule");
      return(NULL);
     }

   /*===============================================*/
   /* Loop through each of the restrictions in the  */
   /* list of restrictions for the multifield slot. */
   /*===============================================*/

   for (nextNode = topNode; nextNode != NULL; nextNode = nextNode->right)
     {
      /*===================================================*/
      /* Assign a constraint record to each constraint. If */
      /* the slot has an explicit constraint, then copy    */
      /* this and store it with the constraint. Otherwise, */
      /* create a constraint record for a single field     */
      /* constraint and skip the constraint modifications  */
      /* for a multifield constraint.                      */
      /*===================================================*/

      if (theConstraints == NULL)
        {
         if (nextNode->type == SF_VARIABLE)
           { nextNode->constraints = GetConstraintRecord(); }
         else
           { continue; }
        }
      else
        { nextNode->constraints = CopyConstraintRecord(theConstraints); }

      /*==========================================*/
      /* Remove the min and max field constraints */
      /* for the entire slot from the constraint  */
      /* record for this single constraint.       */
      /*==========================================*/

      ReturnExpression(nextNode->constraints->minFields);
      ReturnExpression(nextNode->constraints->maxFields);
      nextNode->constraints->minFields = GenConstant(SYMBOL,NegativeInfinity);
      nextNode->constraints->maxFields = GenConstant(SYMBOL,PositiveInfinity);
      nextNode->derivedConstraints = TRUE;

      /*====================================================*/
      /* If we're not dealing with a multifield constraint, */
      /* then no further modifications are needed to the    */
      /* min and max constraints for this constraint.       */
      /*====================================================*/

      if ((nextNode->type != MF_WILDCARD) && (nextNode->type != MF_VARIABLE))
        { continue; }

      /*==========================================================*/
      /* Create a separate constraint record to keep track of the */
      /* cardinality information for this multifield constraint.  */
      /*==========================================================*/

      tempConstraints = GetConstraintRecord();
      SetConstraintType(MULTIFIELD,tempConstraints);
      tempConstraints->singlefieldsAllowed = FALSE;
      tempConstraints->multifield = nextNode->constraints;
      nextNode->constraints = tempConstraints;

      /*=====================================================*/
      /* Adjust the min and max field values for this single */
      /* multifield constraint based on the min and max      */
      /* fields for the entire slot and the number of single */
      /* field values contained in the slot.                 */
      /*=====================================================*/

      if (theConstraints->maxFields->value != PositiveInfinity)
        {
         ReturnExpression(tempConstraints->maxFields);
         tempConstraints->maxFields = GenConstant(INTEGER,AddLong(ValueToLong(theConstraints->maxFields->value) - numberOfSingleFields));
        }

      if ((numberOfMultifields == 1) && (theConstraints->minFields->value != NegativeInfinity))
        {
         ReturnExpression(tempConstraints->minFields);
         tempConstraints->minFields = GenConstant(INTEGER,AddLong(ValueToLong(theConstraints->minFields->value) - numberOfSingleFields));
        }
     }

   /*================================================*/
   /* If a multifield slot is being parsed, place a  */
   /* node on top of the list of constraints parsed. */
   /*================================================*/

   if (multifieldSlot)
     {
      nextNode = GetLHSParseNode();
      nextNode->type = MF_WILDCARD;
      nextNode->multifieldSlot = TRUE;
      nextNode->bottom = topNode;
      nextNode->slot = theSlot;
      nextNode->slotNumber = slotNumber;
      nextNode->index = startPosition;
      nextNode->constraints = theConstraints;
      topNode = nextNode;
      TallyFieldTypes(topNode->bottom);
     }

   /*=================================*/
   /* Return the list of constraints. */
   /*=================================*/

   return(topNode);
  }
示例#5
0
文件: cstrnutl.c 项目: atrniv/CLIPS
globle CONSTRAINT_RECORD *ArgumentTypeToConstraintRecord(
  void *theEnv,
  EXEC_STATUS,
  int theRestriction)
  {
   CONSTRAINT_RECORD *rv;

   rv = GetConstraintRecord(theEnv,execStatus);
   rv->anyAllowed = FALSE;

   switch (theRestriction)
     {
      case 'a':
        rv->externalAddressesAllowed = TRUE;
        break;

      case 'e':
        rv->symbolsAllowed = TRUE;
        rv->instanceNamesAllowed = TRUE;
        rv->instanceAddressesAllowed = TRUE;
        break;

      case 'd':
      case 'f':
        rv->floatsAllowed = TRUE;
        break;

      case 'g':
        rv->integersAllowed = TRUE;
        rv->floatsAllowed = TRUE;
        rv->symbolsAllowed = TRUE;
        break;

      case 'h':
        rv->factAddressesAllowed = TRUE;
        rv->integersAllowed = TRUE;
        rv->symbolsAllowed = TRUE;
        rv->instanceNamesAllowed = TRUE;
        rv->instanceAddressesAllowed = TRUE;
        break;

      case 'i':
      case 'l':
        rv->integersAllowed = TRUE;
        break;

      case 'j':
        rv->symbolsAllowed = TRUE;
        rv->stringsAllowed = TRUE;
        rv->instanceNamesAllowed = TRUE;
        break;

      case 'k':
        rv->symbolsAllowed = TRUE;
        rv->stringsAllowed = TRUE;
        break;

      case 'm':
        rv->singlefieldsAllowed = FALSE;
        rv->multifieldsAllowed = TRUE;
        break;

      case 'n':
        rv->floatsAllowed = TRUE;
        rv->integersAllowed = TRUE;
        break;

      case 'o':
        rv->instanceNamesAllowed = TRUE;
        break;

      case 'p':
        rv->instanceNamesAllowed = TRUE;
        rv->symbolsAllowed = TRUE;
        break;

      case 'q':
        rv->symbolsAllowed = TRUE;
        rv->stringsAllowed = TRUE;
        rv->multifieldsAllowed = TRUE;
        break;

      case 's':
        rv->stringsAllowed = TRUE;
        break;

      case 'w':
        rv->symbolsAllowed = TRUE;
        break;

      case 'x':
        rv->instanceAddressesAllowed = TRUE;
        break;

      case 'y':
        rv->factAddressesAllowed = TRUE;
        break;

      case 'z':
        rv->symbolsAllowed = TRUE;
        rv->factAddressesAllowed = TRUE;
        rv->integersAllowed = TRUE;
        break;

      case 'u':
        rv->anyAllowed = TRUE;
        rv->multifieldsAllowed = TRUE;
        break;

      case 'v':
        rv->voidAllowed = TRUE;
        break;
     }

   return(rv);
  }
示例#6
0
文件: cstrnutl.c 项目: atrniv/CLIPS
globle CONSTRAINT_RECORD *FunctionCallToConstraintRecord(
  void *theEnv,
  EXEC_STATUS,
  void *theFunction)
  {
   CONSTRAINT_RECORD *rv;

   rv = GetConstraintRecord(theEnv,execStatus);
   rv->anyAllowed = FALSE;

   switch ((char) ValueFunctionType(theFunction))
     {
      case 'a':
        rv->externalAddressesAllowed = TRUE;
        break;

      case 'f':
      case 'd':
        rv->floatsAllowed = TRUE;
        break;

      case 'i':
      case 'g':
      case 'l':
        rv->integersAllowed = TRUE;
        break;

      case 'j':
        rv->instanceNamesAllowed = TRUE;
        rv->symbolsAllowed = TRUE;
        rv->stringsAllowed = TRUE;
        break;

      case 'k':
        rv->symbolsAllowed = TRUE;
        rv->stringsAllowed = TRUE;
        break;

      case 'm':
        rv->singlefieldsAllowed = FALSE;
        rv->multifieldsAllowed = TRUE;
        break;

      case 'n':
        rv->floatsAllowed = TRUE;
        rv->integersAllowed = TRUE;
        break;

      case 'o':
        rv->instanceNamesAllowed = TRUE;
        break;

      case 's':
        rv->stringsAllowed = TRUE;
        break;

      case 'u':
        rv->anyAllowed = TRUE;
        rv->multifieldsAllowed = TRUE;
        break;

      case 'w':
      case 'c':
      case 'b':
        rv->symbolsAllowed = TRUE;
        break;

      case 'x':
        rv->instanceAddressesAllowed = TRUE;
        break;

      case 'v':
        rv->voidAllowed = TRUE;
        break;
     }

   return(rv);
  }
示例#7
0
文件: cstrnutl.c 项目: atrniv/CLIPS
globle CONSTRAINT_RECORD *ExpressionToConstraintRecord(
  void *theEnv,
  EXEC_STATUS,
  struct expr *theExpression)
  {
   CONSTRAINT_RECORD *rv;

   /*================================================*/
   /* A NULL expression is converted to a constraint */
   /* record with no values allowed.                 */
   /*================================================*/

   if (theExpression == NULL)
     {
      rv = GetConstraintRecord(theEnv,execStatus);
      rv->anyAllowed = FALSE;
      return(rv);
     }

   /*=============================================================*/
   /* Convert variables and function calls to constraint records. */
   /*=============================================================*/

   if ((theExpression->type == SF_VARIABLE) ||
       (theExpression->type == MF_VARIABLE) ||
#if DEFGENERIC_CONSTRUCT
       (theExpression->type == GCALL) ||
#endif
#if DEFFUNCTION_CONSTRUCT
       (theExpression->type == PCALL) ||
#endif
       (theExpression->type == GBL_VARIABLE) ||
       (theExpression->type == MF_GBL_VARIABLE))
     {
      rv = GetConstraintRecord(theEnv,execStatus);
      rv->multifieldsAllowed = TRUE;
      return(rv);
     }
   else if (theExpression->type == FCALL)
     { return(FunctionCallToConstraintRecord(theEnv,execStatus,theExpression->value)); }

   /*============================================*/
   /* Convert a constant to a constraint record. */
   /*============================================*/

   rv = GetConstraintRecord(theEnv,execStatus);
   rv->anyAllowed = FALSE;

   if (theExpression->type == FLOAT)
     {
      rv->floatRestriction = TRUE;
      rv->floatsAllowed = TRUE;
     }
   else if (theExpression->type == INTEGER)
     {
      rv->integerRestriction = TRUE;
      rv->integersAllowed = TRUE;
     }
   else if (theExpression->type == SYMBOL)
     {
      rv->symbolRestriction = TRUE;
      rv->symbolsAllowed = TRUE;
     }
   else if (theExpression->type == STRING)
     {
      rv->stringRestriction = TRUE;
      rv->stringsAllowed = TRUE;
     }
   else if (theExpression->type == INSTANCE_NAME)
     {
      rv->instanceNameRestriction = TRUE;
      rv->instanceNamesAllowed = TRUE;
     }
   else if (theExpression->type == INSTANCE_ADDRESS)
     { rv->instanceAddressesAllowed = TRUE; }

   if (rv->floatsAllowed || rv->integersAllowed || rv->symbolsAllowed ||
       rv->stringsAllowed || rv->instanceNamesAllowed)
     { rv->restrictionList = GenConstant(theEnv,execStatus,theExpression->type,theExpression->value); }

   return(rv);
  }
示例#8
0
static BOOLEAN CheckArgumentForConstraintError(
  struct expr *expressionList,
  struct expr *lastOne,
  int i,
  struct FunctionDefinition *theFunction,
  struct lhsParseNode *theLHS)
  {
   int theRestriction;
   CONSTRAINT_RECORD *constraint1, *constraint2, *constraint3, *constraint4;
   struct lhsParseNode *theVariable;
   struct expr *tmpPtr;
   int rv = FALSE;

   /*=============================================================*/
   /* Skip anything that isn't a variable or isn't an argument to */
   /* a user defined function (i.e. deffunctions and generic have */
   /* no constraint information so they aren't checked).          */
   /*=============================================================*/

   if ((expressionList->type != SF_VARIABLE) || (theFunction == NULL))
     { return (rv); }

   /*===========================================*/
   /* Get the restrictions for the argument and */
   /* convert them to a constraint record.      */
   /*===========================================*/

   theRestriction = GetNthRestriction(theFunction,i);
   constraint1 = ArgumentTypeToConstraintRecord(theRestriction);

   /*================================================*/
   /* Look for the constraint record associated with */
   /* binding the variable in the LHS of the rule.   */
   /*================================================*/

   theVariable = FindVariable((SYMBOL_HN *) expressionList->value,theLHS);
   if (theVariable != NULL)
     {
      if (theVariable->type == MF_VARIABLE)
        {
         constraint2 = GetConstraintRecord();
         SetConstraintType(MULTIFIELD,constraint2);
        }
      else if (theVariable->constraints == NULL)
        { constraint2 = GetConstraintRecord(); }
      else
        { constraint2 = CopyConstraintRecord(theVariable->constraints); }
     }
   else
     { constraint2 = NULL; }

   /*================================================*/
   /* Look for the constraint record associated with */
   /* binding the variable on the RHS of the rule.   */
   /*================================================*/

   constraint3 = FindBindConstraints((SYMBOL_HN *) expressionList->value);

   /*====================================================*/
   /* Union the LHS and RHS variable binding constraints */
   /* (the variable must satisfy one or the other).      */
   /*====================================================*/

   constraint3 = UnionConstraints(constraint3,constraint2);

   /*====================================================*/
   /* Intersect the LHS/RHS variable binding constraints */
   /* with the function argument restriction constraints */
   /* (the variable must satisfy both).                  */
   /*====================================================*/

   constraint4 = IntersectConstraints(constraint3,constraint1);

   /*====================================*/
   /* Check for unmatchable constraints. */
   /*====================================*/

   if (UnmatchableConstraint(constraint4) && GetStaticConstraintChecking())
     {
      PrintErrorID("RULECSTR",3,TRUE);
      PrintRouter(WERROR,"Previous variable bindings of ?");
      PrintRouter(WERROR,ValueToString((SYMBOL_HN *) expressionList->value));
      PrintRouter(WERROR," caused the type restrictions");
      PrintRouter(WERROR,"\nfor argument #");
      PrintLongInteger(WERROR,(long int) i);
      PrintRouter(WERROR," of the expression ");
      tmpPtr = lastOne->nextArg;
      lastOne->nextArg = NULL;
      PrintExpression(WERROR,lastOne);
      lastOne->nextArg = tmpPtr;
      PrintRouter(WERROR,"\nfound in the rule's RHS to be violated.\n");

      rv = TRUE;
     }

   /*===========================================*/
   /* Free the temporarily created constraints. */
   /*===========================================*/

   RemoveConstraint(constraint1);
   RemoveConstraint(constraint2);
   RemoveConstraint(constraint3);
   RemoveConstraint(constraint4);

   /*========================================*/
   /* Return TRUE if unmatchable constraints */
   /* were detected, otherwise FALSE.        */
   /*========================================*/

   return(rv);
  }
示例#9
0
static BOOLEAN MultifieldCardinalityViolation(
  struct lhsParseNode *theNode)
  {
   struct lhsParseNode *tmpNode;
   struct expr *tmpMax;
   long minFields = 0;
   long maxFields = 0;
   int posInfinity = FALSE;
   CONSTRAINT_RECORD *newConstraint, *tempConstraint;

   /*================================*/
   /* A single field slot can't have */
   /* a cardinality violation.       */
   /*================================*/

   if (theNode->multifieldSlot == FALSE) return(FALSE);

   /*=============================================*/
   /* Determine the minimum and maximum number of */
   /* fields the slot could contain based on the  */
   /* slot constraints found in the pattern.      */
   /*=============================================*/

   for (tmpNode = theNode->bottom;
        tmpNode != NULL;
        tmpNode = tmpNode->right)
     {
      /*====================================================*/
      /* A single field variable increases both the minimum */
      /* and maximum number of fields by one.               */
      /*====================================================*/

      if ((tmpNode->type == SF_VARIABLE) ||
          (tmpNode->type == SF_WILDCARD))
        {
         minFields++;
         maxFields++;
        }

      /*=================================================*/
      /* Otherwise a multifield wildcard or variable has */
      /* been encountered. If it is constrained then use */
      /* minimum and maximum number of fields constraint */
      /* associated with this LHS node.                  */
      /*=================================================*/

      else if (tmpNode->constraints != NULL)
        {
         /*=======================================*/
         /* The lowest minimum of all the min/max */
         /* pairs will be the first in the list.  */
         /*=======================================*/

         if (tmpNode->constraints->minFields->value != NegativeInfinity)
           { minFields += ValueToLong(tmpNode->constraints->minFields->value); }

         /*=========================================*/
         /* The greatest maximum of all the min/max */
         /* pairs will be the last in the list.     */
         /*=========================================*/

         tmpMax = tmpNode->constraints->maxFields;
         while (tmpMax->nextArg != NULL) tmpMax = tmpMax->nextArg;
         if (tmpMax->value == PositiveInfinity)
           { posInfinity = TRUE; }
         else
           { maxFields += ValueToLong(tmpMax->value); }
        }

      /*================================================*/
      /* Otherwise an unconstrained multifield wildcard */
      /* or variable increases the maximum number of    */
      /* fields to positive infinity.                   */
      /*================================================*/

      else
        { posInfinity = TRUE; }
     }

   /*==================================================================*/
   /* Create a constraint record for the cardinality of the sum of the */
   /* cardinalities of the restrictions inside the multifield slot.    */
   /*==================================================================*/

   if (theNode->constraints == NULL) tempConstraint = GetConstraintRecord();
   else tempConstraint = CopyConstraintRecord(theNode->constraints);
   ReturnExpression(tempConstraint->minFields);
   ReturnExpression(tempConstraint->maxFields);
   tempConstraint->minFields = GenConstant(INTEGER,AddLong((long) minFields));
   if (posInfinity) tempConstraint->maxFields = GenConstant(SYMBOL,PositiveInfinity);
   else tempConstraint->maxFields = GenConstant(INTEGER,AddLong((long) maxFields));

   /*================================================================*/
   /* Determine the final cardinality for the multifield slot by     */
   /* intersecting the cardinality sum of the restrictions within    */
   /* the multifield slot with the original cardinality of the slot. */
   /*================================================================*/

   newConstraint = IntersectConstraints(theNode->constraints,tempConstraint);
   if (theNode->derivedConstraints) RemoveConstraint(theNode->constraints);
   RemoveConstraint(tempConstraint);
   theNode->constraints = newConstraint;
   theNode->derivedConstraints = TRUE;

   /*===================================================================*/
   /* Determine if the final cardinality for the slot can be satisfied. */
   /*===================================================================*/

   if (GetStaticConstraintChecking() == FALSE) return(FALSE);
   if (UnmatchableConstraint(newConstraint)) return(TRUE);

   return(FALSE);
  }
示例#10
0
static struct templateSlot *DefinedSlots(
  void *theEnv,
  char *readSource,
  SYMBOL_HN *slotName,
  int multifieldSlot,
  struct token *inputToken)
  {
   struct templateSlot *newSlot;
   struct expr *defaultList;
   int defaultFound = FALSE;
   int noneSpecified, deriveSpecified;
   CONSTRAINT_PARSE_RECORD parsedConstraints;

   /*===========================*/
   /* Build the slot container. */
   /*===========================*/

   newSlot = get_struct(theEnv,templateSlot);
   newSlot->slotName = slotName;
   newSlot->defaultList = NULL;
   newSlot->constraints = GetConstraintRecord(theEnv);
   if (multifieldSlot)
     { newSlot->constraints->multifieldsAllowed = TRUE; }
   newSlot->multislot = multifieldSlot;
   newSlot->noDefault = FALSE;
   newSlot->defaultPresent = FALSE;
   newSlot->defaultDynamic = FALSE;
   newSlot->next = NULL;

   /*========================================*/
   /* Parse the primitive slot if it exists. */
   /*========================================*/

   InitializeConstraintParseRecord(&parsedConstraints);
   GetToken(theEnv,readSource,inputToken);

   while (inputToken->type != RPAREN)
     {
      PPBackup(theEnv);
      SavePPBuffer(theEnv," ");
      SavePPBuffer(theEnv,inputToken->printForm);

      /*================================================*/
      /* Slot attributes begin with a left parenthesis. */
      /*================================================*/

      if (inputToken->type != LPAREN)
        {
         SyntaxErrorMessage(theEnv,"deftemplate");
         ReturnSlots(theEnv,newSlot);
         DeftemplateData(theEnv)->DeftemplateError = TRUE;
         return(NULL);
        }

      /*=============================================*/
      /* The name of the attribute must be a symbol. */
      /*=============================================*/

      GetToken(theEnv,readSource,inputToken);
      if (inputToken->type != SYMBOL)
        {
         SyntaxErrorMessage(theEnv,"deftemplate");
         ReturnSlots(theEnv,newSlot);
         DeftemplateData(theEnv)->DeftemplateError = TRUE;
         return(NULL);
        }

      /*================================================================*/
      /* Determine if the attribute is one of the standard constraints. */
      /*================================================================*/

      if (StandardConstraint(ValueToString(inputToken->value)))
        {
         if (ParseStandardConstraint(theEnv,readSource,(ValueToString(inputToken->value)),
                                     newSlot->constraints,&parsedConstraints,
                                     multifieldSlot) == FALSE)
           {
            DeftemplateData(theEnv)->DeftemplateError = TRUE;
            ReturnSlots(theEnv,newSlot);
            return(NULL);
           }
        }

      /*=================================================*/
      /* else if the attribute is the default attribute, */
      /* then get the default list for this slot.        */
      /*=================================================*/

      else if ((strcmp(ValueToString(inputToken->value),"default") == 0) ||
               (strcmp(ValueToString(inputToken->value),"default-dynamic") == 0))
        {
         /*======================================================*/
         /* Check to see if the default has already been parsed. */
         /*======================================================*/

         if (defaultFound)
           {
            AlreadyParsedErrorMessage(theEnv,"default attribute",NULL);
            DeftemplateData(theEnv)->DeftemplateError = TRUE;
            ReturnSlots(theEnv,newSlot);
            return(NULL);
           }

         newSlot->noDefault = FALSE;

         /*=====================================================*/
         /* Determine whether the default is dynamic or static. */
         /*=====================================================*/

         if (strcmp(ValueToString(inputToken->value),"default") == 0)
           {
            newSlot->defaultPresent = TRUE;
            newSlot->defaultDynamic = FALSE;
           }
         else
           {
            newSlot->defaultPresent = FALSE;
            newSlot->defaultDynamic = TRUE;
           }

         /*===================================*/
         /* Parse the list of default values. */
         /*===================================*/

         defaultList = ParseDefault(theEnv,readSource,multifieldSlot,(int) newSlot->defaultDynamic,
                                  TRUE,&noneSpecified,&deriveSpecified,&DeftemplateData(theEnv)->DeftemplateError);
         if (DeftemplateData(theEnv)->DeftemplateError == TRUE)
           {
            ReturnSlots(theEnv,newSlot);
            return(NULL);
           }

         /*==================================*/
         /* Store the default with the slot. */
         /*==================================*/

         defaultFound = TRUE;
         if (deriveSpecified) newSlot->defaultPresent = FALSE;
         else if (noneSpecified)
           {
            newSlot->noDefault = TRUE;
            newSlot->defaultPresent = FALSE;
           }
         newSlot->defaultList = defaultList;
        }

      /*============================================*/
      /* Otherwise the attribute is an invalid one. */
      /*============================================*/

      else
        {
         SyntaxErrorMessage(theEnv,"slot attributes");
         ReturnSlots(theEnv,newSlot);
         DeftemplateData(theEnv)->DeftemplateError = TRUE;
         return(NULL);
        }

      /*===================================*/
      /* Begin parsing the next attribute. */
      /*===================================*/

      GetToken(theEnv,readSource,inputToken);
     }

   /*============================*/
   /* Return the attribute list. */
   /*============================*/

   return(newSlot);
  }
示例#11
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);
  }
示例#12
0
globle struct constraintRecord *UnionConstraints(
  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)) return(GetConstraintRecord(theEnv));

   /*=====================================================*/
   /* If one of the constraint records is NULL, then the  */
   /* union is the other constraint record. Note that     */
   /* this is different from the way that intersections   */
   /* were handled (a NULL constraint record implied that */
   /*  any value was legal which in turn would imply that */
   /* the union would allow any value as well).           */
   /*=====================================================*/

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

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

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

   rv = GetConstraintRecord(theEnv);

   /*==========================*/
   /* Union the allowed types. */
   /*==========================*/

   if (c1->multifieldsAllowed || c2->multifieldsAllowed)
     { rv->multifieldsAllowed = TRUE; }

   if (c1->singlefieldsAllowed || c2->singlefieldsAllowed)
     { rv->singlefieldsAllowed = TRUE; }

   if (c1->anyAllowed || c2->anyAllowed) rv->anyAllowed = TRUE;
   else
     {
      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->factAddressesAllowed = (c1->factAddressesAllowed || c2->factAddressesAllowed);
#if FUZZY_DEFTEMPLATES
      rv->fuzzyValuesAllowed = (c1->fuzzyValuesAllowed || c2->factAddressesAllowed);
#endif
     }

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

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

      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

      if (c1Changed) SetAnyRestrictionFlags(c1,FALSE);
      else if (c2Changed) SetAnyRestrictionFlags(c2,FALSE);
     }

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

   UnionAllowedValueExpressions(theEnv,c1,c2,rv);
   UnionAllowedClassExpressions(theEnv,c1,c2,rv);
   UnionNumericExpressions(theEnv,c1,c2,rv,TRUE);
   UnionNumericExpressions(theEnv,c1,c2,rv,FALSE);

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

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

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

   return(rv);
  }
示例#13
0
static int ProcessVariable(
  void *theEnv,
  struct lhsParseNode *thePattern,
  struct lhsParseNode *multifieldHeader,
  struct lhsParseNode *patternHead,
  int patternHeadType,
  struct nandFrame *theNandFrames)
  {
   int theType;
   struct symbolHashNode *theVariable;
   struct constraintRecord *theConstraints;

   /*=============================================================*/
   /* If a pattern address is being propagated, then treat it as  */
   /* a single field pattern variable and create a constraint     */
   /* which indicates that is must be a fact or instance address. */
   /* This code will have to be modified for new data types which */
   /* can match patterns.                                         */
   /*=============================================================*/

   if (thePattern->type == PATTERN_CE)
     {
      theType = SF_VARIABLE;
      theVariable = (struct symbolHashNode *) thePattern->value;
      if (thePattern->derivedConstraints) RemoveConstraint(theEnv,thePattern->constraints);
      theConstraints = GetConstraintRecord(theEnv);
      thePattern->constraints = theConstraints;
      thePattern->constraints->anyAllowed = FALSE;
      thePattern->constraints->instanceAddressesAllowed = TRUE;
      thePattern->constraints->factAddressesAllowed = TRUE;
      thePattern->derivedConstraints = TRUE;
     }

   /*===================================================*/
   /* Otherwise a pattern variable is being propagated. */
   /*===================================================*/

   else
     {
      theType = thePattern->type;
      theVariable = (struct symbolHashNode *) thePattern->value;
     }

   /*===================================================*/
   /* Propagate the variable location to any additional */
   /* fields associated with the binding variable.      */
   /*===================================================*/

   if (thePattern->type != PATTERN_CE)
     {
      PropagateVariableToNodes(theEnv,thePattern->bottom,theType,theVariable,
                               thePattern,patternHead->beginNandDepth,
                               TRUE,FALSE);

      if (ProcessField(theEnv,thePattern,multifieldHeader,patternHead,patternHeadType,theNandFrames))
        { return(TRUE); }
     }

   /*=================================================================*/
   /* Propagate the constraints to other fields, slots, and patterns. */
   /*=================================================================*/

   return(PropagateVariableDriver(theEnv,patternHead,thePattern,multifieldHeader,theType,
                                  theVariable,thePattern,TRUE,patternHeadType));
  }
示例#14
0
CONSTRAINT_RECORD *FunctionCallToConstraintRecord(
  void *theEnv,
  void *theFunction)
  {
   CONSTRAINT_RECORD *rv;

   if (ValueFunctionType(theFunction) == 'z')
     { return ArgumentTypeToConstraintRecord2(theEnv,UnknownFunctionType(theFunction)); }
     
   rv = GetConstraintRecord(theEnv);
   rv->anyAllowed = false;

   switch ((char) ValueFunctionType(theFunction))
     {
      case 'a':
        rv->externalAddressesAllowed = true;
        break;

      case 'f':
      case 'd':
        rv->floatsAllowed = true;
        break;

      case 'i':
      case 'g':
      case 'l':
        rv->integersAllowed = true;
        break;

      case 'j':
        rv->instanceNamesAllowed = true;
        rv->symbolsAllowed = true;
        rv->stringsAllowed = true;
        break;

      case 'k':
        rv->symbolsAllowed = true;
        rv->stringsAllowed = true;
        break;

      case 'm':
        rv->singlefieldsAllowed = false;
        rv->multifieldsAllowed = true;
        break;

      case 'n':
        rv->floatsAllowed = true;
        rv->integersAllowed = true;
        break;

      case 'o':
        rv->instanceNamesAllowed = true;
        break;

      case 's':
        rv->stringsAllowed = true;
        break;

      case 'u':
        rv->anyAllowed = true;
        rv->multifieldsAllowed = true;
        break;

      case 'w':
      case 'c':
      case 'b':
        rv->symbolsAllowed = true;
        break;

      case 'x':
        rv->instanceAddressesAllowed = true;
        break;

      case 'y':
        rv->factAddressesAllowed = true;
        break;

      case 'v':
        rv->voidAllowed = true;
        break;
     }

   return(rv);
  }