📄 analysis.c
字号:
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))
{ 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->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; }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -