?? analysis.c
字號:
/*===================================================*/ /* 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)) { return(TRUE); } } /*=================================================================*/ /* Propagate the constraints to other fields, slots, and patterns. */ /*=================================================================*/ return(PropagateVariableDriver(theEnv,patternHead,thePattern,multifieldHeader,theType, theVariable,thePattern,TRUE)); }/*******************************************//* PropagateVariableDriver: Driver routine *//* for propagating variable references. *//*******************************************/static int PropagateVariableDriver( void *theEnv, struct lhsParseNode *patternHead, struct lhsParseNode *theNode, struct lhsParseNode *multifieldHeader, int theType, struct symbolHashNode *variableName, struct lhsParseNode *theReference, int assignReference) { /*===================================================*/ /* Propagate the variable location to any additional */ /* constraints associated with the binding variable. */ /*===================================================*/ if (multifieldHeader != NULL) { if (PropagateVariableToNodes(theEnv,multifieldHeader->right,theType,variableName, theReference,patternHead->beginNandDepth,assignReference,FALSE)) { VariableMixingErrorMessage(theEnv,variableName); return(TRUE); } } /*========================================================*/ /* Propagate the variable location to fields/slots in the */ /* same pattern which appear after the binding variable. */ /*========================================================*/ if (PropagateVariableToNodes(theEnv,theNode->right,theType,variableName,theReference, patternHead->beginNandDepth,assignReference,FALSE)) { VariableMixingErrorMessage(theEnv,variableName); return(TRUE); } /*======================================================*/ /* Propagate values to other patterns if the pattern in */ /* which the variable is found is not a "not" CE or the */ /* last pattern within a nand CE. */ /*======================================================*/ if (((patternHead->type == PATTERN_CE) || (patternHead->type == TEST_CE)) && (patternHead->negated == FALSE) && (patternHead->exists == FALSE) && (patternHead->beginNandDepth <= patternHead->endNandDepth)) { int ignoreVariableMixing; /*============================================================*/ /* If the variables are propagated from a test CE, then don't */ /* check for mixing of single and multifield variables (since */ /* previously bound multifield variables typically have the $ */ /* removed when passed as an argument to a function unless */ /* sequence expansion is desired). */ /*============================================================*/ if (patternHead->type == TEST_CE) ignoreVariableMixing = TRUE; else ignoreVariableMixing = FALSE; /*==========================*/ /* Propagate the reference. */ /*==========================*/ if (PropagateVariableToNodes(theEnv,patternHead->bottom,theType,variableName,theReference, patternHead->beginNandDepth,assignReference, ignoreVariableMixing)) { VariableMixingErrorMessage(theEnv,variableName); return(TRUE); } } /*==============================================*/ /* Return FALSE to indicate that no errors were */ /* generated by the variable propagation. */ /*==============================================*/ return(FALSE); }/********************************************************//* ProcessField: Processes a field or slot of a pattern *//* which does not contain a binding variable. *//********************************************************/static int ProcessField( void *theEnv, struct lhsParseNode *thePattern, struct lhsParseNode *multifieldHeader, struct lhsParseNode *patternHead) { struct lhsParseNode *theList, *tempList; /*====================================================*/ /* Nothing needs to be done for the node representing */ /* the entire pattern. Return FALSE to indicate that */ /* no errors were generated. */ /*====================================================*/ if (thePattern->type == PATTERN_CE) return(FALSE); /*====================================================================*/ /* Derive a set of constraints based on values found in the slot or */ /* field. For example, if a slot can only contain the values 1, 2, or */ /* 3, the field constraint ~2 would generate a constraint record that */ /* only allows the value 1 or 3. Once generated, the constraints are */ /* propagated to other slots and fields. */ /*====================================================================*/ theList = DeriveVariableConstraints(theEnv,thePattern); for (tempList = theList; tempList != NULL; tempList = tempList->right) { if (PropagateVariableDriver(theEnv,patternHead,thePattern,multifieldHeader,tempList->type, (SYMBOL_HN *) tempList->value,tempList,FALSE)) { ReturnLHSParseNodes(theEnv,theList); return(TRUE); } } ReturnLHSParseNodes(theEnv,theList); /*===========================================================*/ /* Check for "variable referenced, but not previously bound" */ /* errors. Return TRUE if this type of error is detected. */ /*===========================================================*/ if (UnboundVariablesInPattern(theEnv,thePattern,(int) patternHead->whichCE)) { return(TRUE); } /*==================================================*/ /* Check for constraint errors for this slot/field. */ /* If the slot/field has unmatchable constraints */ /* then return TRUE to indicate a semantic error. */ /*==================================================*/ if (ProcessConnectedConstraints(theEnv,thePattern,multifieldHeader,patternHead)) { return(TRUE); } /*==============================================================*/ /* Convert the slot/field constraint to a series of expressions */ /* that will be used in the pattern and join networks. */ /*==============================================================*/ FieldConversion(theEnv,thePattern,patternHead); /*=========================================================*/ /* Return FALSE to indicate that no errors were generated. */ /*=========================================================*/ return(FALSE); }/*************************************************************//* PropagateVariableToNodes: Propagates variable references *//* to all other variables within the semantic scope of the *//* bound variable. That is, a variable reference cannot be *//* beyond an enclosing not/and CE combination. The *//* restriction of propagating variables beyond an enclosing *//* not CE is handled within the GetVariables function. *//*************************************************************/static int PropagateVariableToNodes( void *theEnv, struct lhsParseNode *theNode, int theType, struct symbolHashNode *variableName, struct lhsParseNode *theReference, int startDepth, int assignReference, int ignoreVariableTypes) { struct constraintRecord *tempConstraints; /*===========================================*/ /* Traverse the nodes using the bottom link. */ /*===========================================*/ while (theNode != NULL) { /*==================================================*/ /* If the field/slot contains a predicate or return */ /* value constraint, then propagate the variable to */ /* the expression associated with that constraint. */ /*==================================================*/ if (theNode->expression != NULL) { PropagateVariableToNodes(theEnv,theNode->expression,theType,variableName, theReference,startDepth,assignReference,TRUE); } /*======================================================*/ /* If the field/slot is a single or multifield variable */ /* with the same name as the propagated variable, */ /* then propagate the variable location to this node. */ /*======================================================*/ else if (((theNode->type == SF_VARIABLE) || (theNode->type == MF_VARIABLE)) && (theNode->value == (void *) variableName)) { /*======================================================*/ /* Check for mixing of single and multifield variables. */ /*======================================================*/ if (ignoreVariableTypes == FALSE) { if (((theType == SF_VARIABLE) && (theNode->type == MF_VARIABLE)) || ((theType == MF_VARIABLE) && (theNode->type == SF_VARIABLE))) { return(TRUE); } } /*======================================================*/ /* Intersect the propagated variable's constraints with */ /* the current constraints for this field/slot. */ /*======================================================*/ if ((theReference->constraints != NULL) && (! theNode->negated)) { tempConstraints = theNode->constraints; theNode->constraints = IntersectConstraints(theEnv,theReference->constraints, tempConstraints); if (theNode->derivedConstraints) { RemoveConstraint(theEnv,tempConstraints); } theNode->derivedConstraints = TRUE; } /*=====================================================*/ /* Don't propagate the variable if it originates from */ /* a different type of pattern object and the variable */ /* reference has already been resolved. */ /*=====================================================*/ if (assignReference) { if (theNode->referringNode == NULL) { theNode->referringNode = theReference; } else if (theReference->pattern == theNode->pattern) { theNode->referringNode = theReference; } else if (theReference->patternType == theNode->patternType) { theNode->referringNode = theReference; } } } /*========================================================*/ /* If the field/slot is the node representing the entire */ /* pattern, then propagate the variable location to the */ /* fact address associated with the pattern (if it is the */ /* same variable name). */ /*========================================================*/ else if ((theNode->type == PATTERN_CE) && (theNode->value == (void *) variableName) && (assignReference == TRUE)) { if (theType == MF_VARIABLE) return(TRUE); theNode->referringNode = theReference; } /*=====================================================*/ /* Propagate the variable to other fields contained */ /* within the same & field constraint or same pattern. */ /*=====================================================*/ if (theNode->right != NULL) { if (PropagateVariableToNodes(theEnv,theNode->right,theType,variableName, theReference,startDepth,assignReference,ignoreVariableTypes)) { return(TRUE); } } /*============================================================*/ /* Propagate the variable to other patterns within the same */ /* semantic scope (if dealing with the node for an entire */ /* pattern) or to the next | field constraint within a field. */ /*============================================================*/ if ((theNode->type == PATTERN_CE) || (theNode->type == TEST_CE)) { if (theNode->endNandDepth < startDepth) theNode = NULL; else theNode = theNode->bottom; } else { theNode = theNode->bottom; } } /*========================================================*/ /* Return FALSE to indicate that no errors were detected. */ /*========================================================*/ return(FALSE); }/*************************************************************//* UnboundVariablesInPattern: Verifies that variables within *//* a slot/field have been referenced properly (i.e. that *//* variables have been previously bound if they are not a *//* binding occurrence). *//*************************************************************/static intBool UnboundVariablesInPattern( void *theEnv, struct lhsParseNode *theSlot, int pattern) { struct lhsParseNode *andField; struct lhsParseNode *rv; int result; struct lhsParseNode *orField; struct symbolHashNode *slotName; CONSTRAINT_RECORD *theConstraints; int theField; /*===================================================*/ /* If a multifield slot is being checked, then check */ /* each of the fields grouped with the multifield. */ /*===================================================*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -