📄 generate.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.20 01/31/02 */
/* */
/* GENERATE MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Provides routines for converting field */
/* constraints to expressions which can be used */
/* in the pattern and join networks. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* */
/*************************************************************/
#define _GENERATE_SOURCE_
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <stdlib.h>
#include "setup.h"
#if (! RUN_TIME) && (! BLOAD_ONLY) && DEFRULE_CONSTRUCT
#include "constant.h"
#include "envrnmnt.h"
#include "memalloc.h"
#include "symbol.h"
#include "exprnpsr.h"
#include "argacces.h"
#include "extnfunc.h"
#include "router.h"
#include "ruledef.h"
#include "pattern.h"
#include "generate.h"
#if DEFGLOBAL_CONSTRUCT
#include "globlpsr.h"
#endif
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static void ExtractAnds(void *,struct lhsParseNode *,int,
struct expr **,struct expr **);
static void ExtractFieldTest(void *,struct lhsParseNode *,int,
struct expr **,struct expr **);
static struct expr *GetfieldReplace(void *,struct lhsParseNode *);
static struct expr *GenPNConstant(void *,struct lhsParseNode *);
static struct expr *GenJNConstant(void *,struct lhsParseNode *);
static struct expr *GenJNColon(void *,struct lhsParseNode *);
static struct expr *GenPNColon(void *,struct lhsParseNode *);
static struct expr *GenJNEq(void *,struct lhsParseNode *);
static struct expr *GenPNEq(void *,struct lhsParseNode *);
static struct expr *GenJNVariableComparison(void *,struct lhsParseNode *,
struct lhsParseNode *);
static struct expr *GenPNVariableComparison(void *,struct lhsParseNode *,
struct lhsParseNode *);
static int AllVariablesInPattern(struct lhsParseNode *,
int);
static int AllVariablesInExpression(struct lhsParseNode *,
int);
/*******************************************************/
/* FieldConversion: Generates join and pattern network */
/* expressions for a field constraint. */
/*******************************************************/
globle void FieldConversion(
void *theEnv,
struct lhsParseNode *theField,
struct lhsParseNode *thePattern)
{
int testInPatternNetwork = TRUE;
struct lhsParseNode *patternPtr;
struct expr *headOfPNExpression, *headOfJNExpression;
struct expr *lastPNExpression, *lastJNExpression;
struct expr *tempExpression;
struct expr *patternNetTest = NULL;
struct expr *joinNetTest = NULL;
/*==================================================*/
/* Consider a NULL pointer to be an internal error. */
/*==================================================*/
if (theField == NULL)
{
SystemError(theEnv,"ANALYSIS",3);
EnvExitRouter(theEnv,EXIT_FAILURE);
}
/*========================================================*/
/* Determine if constant testing must be performed in the */
/* join network. Only possible when a field contains an */
/* or ('|') and references are made to variables outside */
/* the pattern. */
/*========================================================*/
if (theField->bottom != NULL)
{
if (theField->bottom->bottom != NULL)
{ testInPatternNetwork = AllVariablesInPattern(theField->bottom,theField->pattern); }
}
/*=============================================================*/
/* Extract pattern and join network expressions. Loop through */
/* the or'ed constraints of the field, extracting pattern and */
/* join network expressions and adding them to a running list. */
/*=============================================================*/
headOfPNExpression = lastPNExpression = NULL;
headOfJNExpression = lastJNExpression = NULL;
for (patternPtr = theField->bottom;
patternPtr != NULL;
patternPtr = patternPtr->bottom)
{
/*=============================================*/
/* Extract pattern and join network tests from */
/* the or'ed constraint being examined. */
/*=============================================*/
ExtractAnds(theEnv,patternPtr,testInPatternNetwork,&patternNetTest,&joinNetTest);
/*=====================================================*/
/* Add the new pattern network expressions to the list */
/* of pattern network expressions being constructed. */
/*=====================================================*/
if (patternNetTest != NULL)
{
if (lastPNExpression == NULL)
{ headOfPNExpression = patternNetTest; }
else
{ lastPNExpression->nextArg = patternNetTest; }
lastPNExpression = patternNetTest;
}
/*==================================================*/
/* Add the new join network expressions to the list */
/* of join network expressions being constructed. */
/*==================================================*/
if (joinNetTest != NULL)
{
if (lastJNExpression == NULL)
{ headOfJNExpression = joinNetTest; }
else
{ lastJNExpression->nextArg = joinNetTest; }
lastJNExpression = joinNetTest;
}
}
/*==========================================================*/
/* If there was more than one expression generated from the */
/* or'ed field constraints for the pattern network, then */
/* enclose the expressions within an "or" function call. */
/*==========================================================*/
if ((headOfPNExpression != NULL) ? (headOfPNExpression->nextArg != NULL) : FALSE)
{
tempExpression = GenConstant(theEnv,FCALL,ExpressionData(theEnv)->PTR_OR);
tempExpression->argList = headOfPNExpression;
headOfPNExpression = tempExpression;
}
/*==========================================================*/
/* If there was more than one expression generated from the */
/* or'ed field constraints for the join network, then */
/* enclose the expressions within an "or" function call. */
/*==========================================================*/
if ((headOfJNExpression != NULL) ? (headOfJNExpression->nextArg != NULL) : FALSE)
{
tempExpression = GenConstant(theEnv,FCALL,ExpressionData(theEnv)->PTR_OR);
tempExpression->argList = headOfJNExpression;
headOfJNExpression = tempExpression;
}
/*===============================================================*/
/* If the field constraint binds a variable that was previously */
/* bound somewhere in the LHS of the rule, then generate an */
/* expression to compare this binding occurrence of the variable */
/* to the previous binding occurrence. */
/*===============================================================*/
if (((theField->type == MF_VARIABLE) || (theField->type == SF_VARIABLE)) &&
(theField->referringNode != NULL))
{
/*================================================================*/
/* If the previous variable reference is within the same pattern, */
/* then the variable comparison can occur in the pattern network. */
/*================================================================*/
if (theField->referringNode->pattern == theField->pattern)
{
tempExpression = GenPNVariableComparison(theEnv,theField,theField->referringNode);
headOfPNExpression = CombineExpressions(theEnv,tempExpression,headOfPNExpression);
}
/*====================================*/
/* Otherwise, the variable comparison */
/* must occur in the join network. */
/*====================================*/
else if (theField->referringNode->pattern > 0)
{
tempExpression = GenJNVariableComparison(theEnv,theField,theField->referringNode);
headOfJNExpression = CombineExpressions(theEnv,tempExpression,headOfJNExpression);
}
}
/*======================================================*/
/* Attach the pattern network expressions to the field. */
/*======================================================*/
theField->networkTest = headOfPNExpression;
/*=====================================================*/
/* Attach the join network expressions to the pattern. */
/*=====================================================*/
thePattern->networkTest = CombineExpressions(theEnv,thePattern->networkTest,headOfJNExpression);
}
/****************************************************************************/
/* ExtractAnds: Loops through a single set of subfields bound together by */
/* an & connective constraint in a field and generates expressions needed */
/* for testing conditions in the pattern and join network. */
/****************************************************************************/
static void ExtractAnds(
void *theEnv,
struct lhsParseNode *andField,
int testInPatternNetwork,
struct expr **patternNetTest,
struct expr **joinNetTest)
{
struct expr *newPNTest, *newJNTest;
/*=================================================*/
/* Before starting, the subfield has no pattern or */
/* join network expressions associated with it. */
/*=================================================*/
*patternNetTest = NULL;
*joinNetTest = NULL;
/*=========================================*/
/* Loop through each of the subfields tied */
/* together by the & constraint. */
/*=========================================*/
for (;
andField != NULL;
andField = andField->right)
{
/*======================================*/
/* Extract the pattern and join network */
/* expressions from the subfield. */
/*======================================*/
ExtractFieldTest(theEnv,andField,testInPatternNetwork,&newPNTest,&newJNTest);
/*=================================================*/
/* Add the new expressions to the list of pattern */
/* and join network expressions being constructed. */
/*=================================================*/
*patternNetTest = CombineExpressions(theEnv,*patternNetTest,newPNTest);
*joinNetTest = CombineExpressions(theEnv,*joinNetTest,newJNTest);
}
}
/************************************************************************/
/* ExtractFieldTest: Generates the pattern or join network expression */
/* associated with the basic field constraints: constants, predicate, */
/* return value, and variable constraints. Based on the context in */
/* which a constraint is used, some constraints may be tested in the */
/* pattern network while other constraints must be tested in the join */
/* network. Constraints which refer to variables in other patterns */
/* must be tested in the join network. The predicate constraint */
/* associated with a test CE is tested in the join network (even if */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -