/**************************************************** NAME : GenObjectLengthTest DESCRIPTION : Generates a test on the cardinality of a slot matching an object pattern INPUTS : The first lhsParseNode for a slot in an object pattern RETURNS : Nothing useful SIDE EFFECTS : The lhsParseNode network test is modified to include the length test NOTES : None ****************************************************/ globle void GenObjectLengthTest( void *theEnv, struct lhsParseNode *theNode) { struct ObjectMatchLength hack; EXPRESSION *theTest; if ((theNode->singleFieldsAfter == 0) && (theNode->type != SF_VARIABLE) && (theNode->type != SF_WILDCARD)) return; ClearBitString((void *) &hack,(int) sizeof(struct ObjectMatchLength)); if ((theNode->type != MF_VARIABLE) && (theNode->type != MF_WILDCARD) && (theNode->multiFieldsAfter == 0)) hack.exactly = 1; else hack.exactly = 0; if ((theNode->type == SF_VARIABLE) || (theNode->type == SF_WILDCARD)) hack.minLength = 1 + theNode->singleFieldsAfter; else hack.minLength = theNode->singleFieldsAfter; theTest = GenConstant(theEnv,OBJ_SLOT_LENGTH,EnvAddBitMap(theEnv,(void *) &hack, (int) sizeof(struct ObjectMatchLength))); if (theNode->constantSelector != NULL) { theNode->constantSelector->nextArg = CopyExpression(theEnv,theTest); } theNode->networkTest = CombineExpressions(theEnv,theTest,theNode->networkTest); }
static struct Instantiation * CopyInstantiation(struct Instantiation * inst) { struct Instantiation * copy; struct __ecereNameSpace__ecere__sys__OldList * list = MkList(); struct MembersInit * member; if(inst->members) { for(member = (*inst->members).first; member; member = member->next) ListAdd(list, CopyMembersInit(member)); } copy = MkInstantiation(CopySpecifier(inst->_class), CopyExpression(inst->exp), list); copy->data = inst->data; if(inst->data) { struct Symbol * classSym = FindClass(inst->_class->name); struct __ecereNameSpace__ecere__com__Class * _class = classSym ? classSym->registered : (((void *)0)); if(_class) { if(_class->type == 0) ((struct __ecereNameSpace__ecere__com__Instance *)(char *)((struct __ecereNameSpace__ecere__com__Instance *)copy->data))->_refCount++; } } copy->loc = inst->loc; copy->isConstant = inst->isConstant; return copy; }
/******************************************************************** NAME : ExpandFuncCall DESCRIPTION : This function is a wrap-around for a normal function call. It preexamines the argument expression list and expands any references to the sequence operator. It builds a copy of the function call expression with these new arguments inserted and evaluates the function call. INPUTS : A data object buffer RETURNS : Nothing useful SIDE EFFECTS : Expressions alloctaed/deallocated Function called and arguments evaluated EvaluationError set on errors NOTES : None *******************************************************************/ globle void ExpandFuncCall( void *theEnv, DATA_OBJECT *result) { EXPRESSION *newargexp,*fcallexp; struct FunctionDefinition *func; /* ====================================================================== Copy the original function call's argument expression list. Look for expand$ function callsexpressions and replace those with the equivalent expressions of the expansions of evaluations of the arguments. ====================================================================== */ newargexp = CopyExpression(theEnv,GetFirstArgument()->argList); ExpandFuncMultifield(theEnv,result,newargexp,&newargexp, (void *) FindFunction(theEnv,"expand$")); /* =================================================================== Build the new function call expression with the expanded arguments. Check the number of arguments, if necessary, and call the thing. =================================================================== */ fcallexp = get_struct(theEnv,expr); fcallexp->type = GetFirstArgument()->type; fcallexp->value = GetFirstArgument()->value; fcallexp->nextArg = NULL; fcallexp->argList = newargexp; if (fcallexp->type == FCALL) { func = (struct FunctionDefinition *) fcallexp->value; if (CheckFunctionArgCount(theEnv,ValueToString(func->callFunctionName), func->restrictions,CountArguments(newargexp)) == FALSE) { result->type = SYMBOL; result->value = EnvFalseSymbol(theEnv); ReturnExpression(theEnv,fcallexp); return; } } #if DEFFUNCTION_CONSTRUCT else if (fcallexp->type == PCALL) { if (CheckDeffunctionCall(theEnv,fcallexp->value, CountArguments(fcallexp->argList)) == FALSE) { result->type = SYMBOL; result->value = EnvFalseSymbol(theEnv); ReturnExpression(theEnv,fcallexp); SetEvaluationError(theEnv,TRUE); return; } } #endif EvaluateExpression(theEnv,fcallexp,result); ReturnExpression(theEnv,fcallexp); }
globle struct expr *CopyExpression( struct expr *original) { struct expr *topLevel, *next, *last; if (original == NULL) return(NULL); topLevel = GenConstant(original->type,original->value); topLevel->argList = CopyExpression(original->argList); last = topLevel; original = original->nextArg; while (original != NULL) { next = GenConstant(original->type,original->value); next->argList = CopyExpression(original->argList); last->nextArg = next; last = next; original = original->nextArg; } return(topLevel); }
static struct Initializer * CopyInitializer(struct Initializer * initializer) { struct Initializer * copy = (((void *)0)); ; if(initializer->type == 0) copy = MkInitializerAssignment(CopyExpression(initializer->exp)); else if(initializer->type == 1) copy = MkInitializerList(CopyList(initializer->list, CopyInitializer)); if(copy) { copy->loc = initializer->loc; copy->isConstant = initializer->isConstant; } return copy; }
globle struct constraintRecord *CopyConstraintRecord( void *theEnv, EXEC_STATUS, CONSTRAINT_RECORD *sourceConstraint) { CONSTRAINT_RECORD *theConstraint; if (sourceConstraint == NULL) return(NULL); theConstraint = get_struct(theEnv,execStatus,constraintRecord); theConstraint->anyAllowed = sourceConstraint->anyAllowed; theConstraint->symbolsAllowed = sourceConstraint->symbolsAllowed; theConstraint->stringsAllowed = sourceConstraint->stringsAllowed; theConstraint->floatsAllowed = sourceConstraint->floatsAllowed; theConstraint->integersAllowed = sourceConstraint->integersAllowed; theConstraint->instanceNamesAllowed = sourceConstraint->instanceNamesAllowed; theConstraint->instanceAddressesAllowed = sourceConstraint->instanceAddressesAllowed; theConstraint->externalAddressesAllowed = sourceConstraint->externalAddressesAllowed; theConstraint->voidAllowed = sourceConstraint->voidAllowed; theConstraint->multifieldsAllowed = sourceConstraint->multifieldsAllowed; theConstraint->singlefieldsAllowed = sourceConstraint->singlefieldsAllowed; theConstraint->factAddressesAllowed = sourceConstraint->factAddressesAllowed; theConstraint->anyRestriction = sourceConstraint->anyRestriction; theConstraint->symbolRestriction = sourceConstraint->symbolRestriction; theConstraint->stringRestriction = sourceConstraint->stringRestriction; theConstraint->floatRestriction = sourceConstraint->floatRestriction; theConstraint->integerRestriction = sourceConstraint->integerRestriction; theConstraint->classRestriction = sourceConstraint->classRestriction; theConstraint->instanceNameRestriction = sourceConstraint->instanceNameRestriction; theConstraint->classList = CopyExpression(theEnv,execStatus,sourceConstraint->classList); theConstraint->restrictionList = CopyExpression(theEnv,execStatus,sourceConstraint->restrictionList); theConstraint->minValue = CopyExpression(theEnv,execStatus,sourceConstraint->minValue); theConstraint->maxValue = CopyExpression(theEnv,execStatus,sourceConstraint->maxValue); theConstraint->minFields = CopyExpression(theEnv,execStatus,sourceConstraint->minFields); theConstraint->maxFields = CopyExpression(theEnv,execStatus,sourceConstraint->maxFields); theConstraint->bucket = -1; theConstraint->count = 0; theConstraint->multifield = CopyConstraintRecord(theEnv,execStatus,sourceConstraint->multifield); theConstraint->next = NULL; return(theConstraint); }
globle void OverlayConstraint( void *theEnv, CONSTRAINT_PARSE_RECORD *pc, CONSTRAINT_RECORD *cdst, CONSTRAINT_RECORD *csrc) { if (pc->type == 0) { cdst->anyAllowed = csrc->anyAllowed; cdst->symbolsAllowed = csrc->symbolsAllowed; cdst->stringsAllowed = csrc->stringsAllowed; cdst->floatsAllowed = csrc->floatsAllowed; cdst->integersAllowed = csrc->integersAllowed; cdst->instanceNamesAllowed = csrc->instanceNamesAllowed; cdst->instanceAddressesAllowed = csrc->instanceAddressesAllowed; cdst->externalAddressesAllowed = csrc->externalAddressesAllowed; cdst->voidAllowed = csrc->voidAllowed; cdst->factAddressesAllowed = csrc->factAddressesAllowed; } if (pc->range == 0) { ReturnExpression(theEnv,cdst->minValue); ReturnExpression(theEnv,cdst->maxValue); cdst->minValue = CopyExpression(theEnv,csrc->minValue); cdst->maxValue = CopyExpression(theEnv,csrc->maxValue); } if (pc->allowedClasses == 0) { ReturnExpression(theEnv,cdst->classList); cdst->classList = CopyExpression(theEnv,csrc->classList); } if (pc->allowedValues == 0) { if ((pc->allowedSymbols == 0) && (pc->allowedStrings == 0) && (pc->allowedLexemes == 0) && (pc->allowedIntegers == 0) && (pc->allowedFloats == 0) && (pc->allowedNumbers == 0) && (pc->allowedInstanceNames == 0)) { cdst->anyRestriction = csrc->anyRestriction; cdst->symbolRestriction = csrc->symbolRestriction; cdst->stringRestriction = csrc->stringRestriction; cdst->floatRestriction = csrc->floatRestriction; cdst->integerRestriction = csrc->integerRestriction; cdst->classRestriction = csrc->classRestriction; cdst->instanceNameRestriction = csrc->instanceNameRestriction; cdst->restrictionList = CopyExpression(theEnv,csrc->restrictionList); } else { if ((pc->allowedSymbols == 0) && csrc->symbolRestriction) { cdst->symbolRestriction = 1; AddToRestrictionList(theEnv,SYMBOL,cdst,csrc); } if ((pc->allowedStrings == 0) && csrc->stringRestriction) { cdst->stringRestriction = 1; AddToRestrictionList(theEnv,STRING,cdst,csrc); } if ((pc->allowedLexemes == 0) && csrc->symbolRestriction && csrc->stringRestriction) { cdst->symbolRestriction = 1; cdst->stringRestriction = 1; AddToRestrictionList(theEnv,SYMBOL,cdst,csrc); AddToRestrictionList(theEnv,STRING,cdst,csrc); } if ((pc->allowedIntegers == 0) && csrc->integerRestriction) { cdst->integerRestriction = 1; AddToRestrictionList(theEnv,INTEGER,cdst,csrc); } if ((pc->allowedFloats == 0) && csrc->floatRestriction) { cdst->floatRestriction = 1; AddToRestrictionList(theEnv,FLOAT,cdst,csrc); } if ((pc->allowedNumbers == 0) && csrc->integerRestriction && csrc->floatRestriction) { cdst->integerRestriction = 1; cdst->floatRestriction = 1; AddToRestrictionList(theEnv,INTEGER,cdst,csrc); AddToRestrictionList(theEnv,FLOAT,cdst,csrc); } if ((pc->allowedInstanceNames == 0) && csrc->instanceNameRestriction) { cdst->instanceNameRestriction = 1; AddToRestrictionList(theEnv,INSTANCE_NAME,cdst,csrc); } } } if (pc->cardinality == 0) { ReturnExpression(theEnv,cdst->minFields); ReturnExpression(theEnv,cdst->maxFields); cdst->minFields = CopyExpression(theEnv,csrc->minFields); cdst->maxFields = CopyExpression(theEnv,csrc->maxFields); } }
static struct expr *GetSlotAssertValues( struct templateSlot *slotPtr, struct expr *firstSlot, int *error) { struct expr *slotItem; struct expr *newArg, *tempArg; DATA_OBJECT theDefault; char *nullBitMap = "\0"; /*==================================================*/ /* Determine if the slot is assigned in the assert. */ /*==================================================*/ slotItem = FindAssertSlotItem(slotPtr,firstSlot); /*==========================================*/ /* If the slot is assigned, use that value. */ /*==========================================*/ if (slotItem != NULL) { newArg = slotItem->argList; slotItem->argList = NULL; } /*=================================*/ /* Otherwise, use a default value. */ /*=================================*/ else { /*================================================*/ /* If the (default ?NONE) attribute was specified */ /* for the slot, then a value must be supplied. */ /*================================================*/ if (slotPtr->noDefault) { PrintErrorID("TMPLTRHS",1,TRUE); PrintRouter(WERROR,"Slot "); PrintRouter(WERROR,slotPtr->slotName->contents); PrintRouter(WERROR," requires a value because of its (default ?NONE) attribute.\n"); *error = TRUE; return(NULL); } /*===================================================*/ /* If the (default ?DERIVE) attribute was specified */ /* (the default), then derive the default value from */ /* the slot's constraints. */ /*===================================================*/ else if ((slotPtr->defaultPresent == FALSE) && (slotPtr->defaultDynamic == FALSE)) { DeriveDefaultFromConstraints(slotPtr->constraints,&theDefault, (int) slotPtr->multislot); newArg = ConvertValueToExpression(&theDefault); } /*=========================================*/ /* Otherwise, use the expression contained */ /* in the default attribute. */ /*=========================================*/ else { newArg = CopyExpression(slotPtr->defaultList); } } /*=======================================================*/ /* Since a multifield slot default can contain a list of */ /* values, the values need to have a store-multifield */ /* function called wrapped around it to group all of the */ /* values into a single multifield value. */ /*=======================================================*/ if (slotPtr->multislot) { tempArg = GenConstant(FACT_STORE_MULTIFIELD,AddBitMap((void *) nullBitMap,1)); tempArg->argList = newArg; newArg = tempArg; } /*==============================================*/ /* Return the value to be asserted in the slot. */ /*==============================================*/ return(newArg); }
static struct defrule *ProcessRuleLHS( void *theEnv, struct lhsParseNode *theLHS, struct expr *actions, SYMBOL_HN *ruleName, int *error) { struct lhsParseNode *tempNode = NULL; struct defrule *topDisjunct = NULL, *currentDisjunct, *lastDisjunct = NULL; struct expr *newActions, *packPtr; int logicalJoin; int localVarCnt; int complexity; struct joinNode *lastJoin; intBool emptyLHS; /*================================================*/ /* Initially set the parsing error flag to FALSE. */ /*================================================*/ *error = FALSE; /*===========================================================*/ /* The top level of the construct representing the LHS of a */ /* rule is assumed to be an OR. If the implied OR is at the */ /* top level of the pattern construct, then remove it. */ /*===========================================================*/ if (theLHS == NULL) { emptyLHS = TRUE; } else { emptyLHS = FALSE; if (theLHS->type == OR_CE) theLHS = theLHS->right; } /*=========================================*/ /* Loop through each disjunct of the rule. */ /*=========================================*/ localVarCnt = CountParsedBindNames(theEnv); while ((theLHS != NULL) || (emptyLHS == TRUE)) { /*===================================*/ /* Analyze the LHS of this disjunct. */ /*===================================*/ if (emptyLHS) { tempNode = NULL; } else { if (theLHS->type == AND_CE) tempNode = theLHS->right; else if (theLHS->type == PATTERN_CE) tempNode = theLHS; } if (VariableAnalysis(theEnv,tempNode)) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); return(NULL); } /*=========================================*/ /* Perform entity dependent post analysis. */ /*=========================================*/ if (PostPatternAnalysis(theEnv,tempNode)) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); return(NULL); } /*========================================================*/ /* Print out developer information if it's being watched. */ /*========================================================*/ #if DEVELOPER && DEBUGGING_FUNCTIONS if (EnvGetWatchItem(theEnv,"rule-analysis")) { DumpRuleAnalysis(theEnv,tempNode); } #endif /*========================================*/ /* Check to see that logical CEs are used */ /* appropriately in the LHS of the rule. */ /*========================================*/ if ((logicalJoin = LogicalAnalysis(theEnv,tempNode)) < 0) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); return(NULL); } /*======================================================*/ /* Check to see if there are any RHS constraint errors. */ /*======================================================*/ if (CheckRHSForConstraintErrors(theEnv,actions,tempNode)) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); return(NULL); } /*=================================================*/ /* Replace variable references in the RHS with the */ /* appropriate variable retrieval functions. */ /*=================================================*/ newActions = CopyExpression(theEnv,actions); if (ReplaceProcVars(theEnv,"RHS of defrule",newActions,NULL,NULL, ReplaceRHSVariable,(void *) tempNode)) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); ReturnExpression(theEnv,newActions); return(NULL); } /*==================================*/ /* We're finished for this disjunct */ /* if we're only checking syntax. */ /*==================================*/ if (ConstructData(theEnv)->CheckSyntaxMode) { ReturnExpression(theEnv,newActions); if (emptyLHS) { emptyLHS = FALSE; } else { theLHS = theLHS->bottom; } continue; } /*=================================*/ /* Install the disjunct's actions. */ /*=================================*/ ExpressionInstall(theEnv,newActions); packPtr = PackExpression(theEnv,newActions); ReturnExpression(theEnv,newActions); /*===============================================================*/ /* Create the pattern and join data structures for the new rule. */ /*===============================================================*/ lastJoin = ConstructJoins(theEnv,logicalJoin,tempNode,1,NULL,TRUE,TRUE); /*===================================================================*/ /* Determine the rule's complexity for use with conflict resolution. */ /*===================================================================*/ complexity = RuleComplexity(theEnv,tempNode); /*=====================================================*/ /* Create the defrule data structure for this disjunct */ /* and put it in the list of disjuncts for this rule. */ /*=====================================================*/ currentDisjunct = CreateNewDisjunct(theEnv,ruleName,localVarCnt,packPtr,complexity, (unsigned) logicalJoin,lastJoin); /*============================================================*/ /* Place the disjunct in the list of disjuncts for this rule. */ /* If the disjunct is the first disjunct, then increment the */ /* reference counts for the dynamic salience (the expression */ /* for the dynamic salience is only stored with the first */ /* disjuncts and the other disjuncts refer back to the first */ /* disjunct for their dynamic salience value. */ /*============================================================*/ if (topDisjunct == NULL) { topDisjunct = currentDisjunct; ExpressionInstall(theEnv,topDisjunct->dynamicSalience); } else lastDisjunct->disjunct = currentDisjunct; /*===========================================*/ /* Move on to the next disjunct of the rule. */ /*===========================================*/ lastDisjunct = currentDisjunct; if (emptyLHS) { emptyLHS = FALSE; } else { theLHS = theLHS->bottom; } } return(topDisjunct); }
static struct Enumerator * CopyEnumerator(struct Enumerator * enumerator) { return MkEnumerator(CopyIdentifier(enumerator->id), CopyExpression(enumerator->exp)); }
struct Expression * CopyExpression(struct Expression * exp) { struct Expression * result = (((void *)0)); if(exp) switch(exp->type) { case 16: result = MkExpDummy(); break; case 0: result = MkExpIdentifier(CopyIdentifier(exp->identifier)); break; case 1: result = MkExpInstance(CopyInstantiation(exp->instance)); break; case 2: result = MkExpConstant(exp->string); break; case 3: result = MkExpString(exp->string); break; case 4: result = MkExpOp(CopyExpression(exp->op.exp1), exp->op.op, CopyExpression(exp->op.exp2)); break; case 5: { struct __ecereNameSpace__ecere__sys__OldList * list = MkList(); struct Expression * e; for(e = (*exp->list).first; e; e = e->next) ListAdd(list, CopyExpression(e)); result = MkExpBrackets(list); break; } case 6: { struct __ecereNameSpace__ecere__sys__OldList * list = MkList(); struct Expression * e; for(e = (*exp->index.index).first; e; e = e->next) ListAdd(list, CopyExpression(e)); result = MkExpIndex(CopyExpression(exp->index.exp), list); break; } case 7: { struct __ecereNameSpace__ecere__sys__OldList * list = MkList(); struct Expression * arg; if(exp->call.arguments) { for(arg = (*exp->call.arguments).first; arg; arg = arg->next) ListAdd(list, CopyExpression(arg)); } result = MkExpCall(CopyExpression(exp->call.exp), list); break; } case 8: result = MkExpMember(CopyExpression(exp->member.exp), CopyIdentifier(exp->member.member)); result->member.memberType = exp->member.memberType; result->member.thisPtr = exp->member.thisPtr; break; case 9: result = MkExpPointer(CopyExpression(exp->member.exp), CopyIdentifier(exp->member.member)); break; case 10: result = MkExpTypeSize(CopyTypeName(exp->typeName)); break; case 38: result = MkExpTypeAlign(CopyTypeName(exp->typeName)); break; case 11: result = MkExpCast(CopyTypeName(exp->cast.typeName), CopyExpression(exp->cast.exp)); break; case 12: { struct __ecereNameSpace__ecere__sys__OldList * list = MkList(); struct Expression * e; for(e = (*exp->cond.exp).first; e; e = e->next) ListAdd(list, CopyExpression(e)); result = MkExpCondition(CopyExpression(exp->cond.cond), list, CopyExpression(exp->cond.elseExp)); break; } case 36: result = MkExpVaArg(CopyExpression(exp->vaArg.exp), CopyTypeName(exp->vaArg.typeName)); break; case 25: result = MkExpExtensionCompound(CopyStatement(exp->compound)); break; } if(result) { result->expType = exp->expType; if(exp->expType) exp->expType->refCount++; result->destType = exp->destType; if(exp->destType) exp->destType->refCount++; result->loc = exp->loc; result->isConstant = exp->isConstant; result->byReference = exp->byReference; } return result; }
static struct defrule *ProcessRuleLHS( void *theEnv, struct lhsParseNode *theLHS, struct expr *actions, SYMBOL_HN *ruleName, int *error) { struct lhsParseNode *tempNode = NULL; struct defrule *topDisjunct = NULL, *currentDisjunct, *lastDisjunct = NULL; struct expr *newActions, *packPtr; int logicalJoin; int localVarCnt; int complexity; struct joinNode *lastJoin; intBool emptyLHS; /*================================================*/ /* Initially set the parsing error flag to FALSE. */ /*================================================*/ *error = FALSE; /*===========================================================*/ /* The top level of the construct representing the LHS of a */ /* rule is assumed to be an OR. If the implied OR is at the */ /* top level of the pattern construct, then remove it. */ /*===========================================================*/ if (theLHS == NULL) { emptyLHS = TRUE; } else { emptyLHS = FALSE; if (theLHS->type == OR_CE) theLHS = theLHS->right; } /*=========================================*/ /* Loop through each disjunct of the rule. */ /*=========================================*/ localVarCnt = CountParsedBindNames(theEnv); while ((theLHS != NULL) || (emptyLHS == TRUE)) { #if FUZZY_DEFTEMPLATES unsigned int LHSRuleType; /* LHSRuleType is set to FUZZY_LHS or CRISP_LHS */ unsigned int numFuzzySlots; int patternNum; #endif /*===================================*/ /* Analyze the LHS of this disjunct. */ /*===================================*/ if (emptyLHS) { tempNode = NULL; } else { if (theLHS->type == AND_CE) tempNode = theLHS->right; else if (theLHS->type == PATTERN_CE) tempNode = theLHS; } if (VariableAnalysis(theEnv,tempNode)) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); return(NULL); } /*=========================================*/ /* Perform entity dependent post analysis. */ /*=========================================*/ if (PostPatternAnalysis(theEnv,tempNode)) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); return(NULL); } #if FUZZY_DEFTEMPLATES /* calculate the number of fuzzy value slots in patterns with the rule disjunct and also determine LHS type of the rule -- if number of fuzzy slots in non-NOT patterns >0 then FUZZY LHS [if pattern is (not (xxx (fuzzySlot ...) ...)) then they don't count when considering the LHS type] */ if (emptyLHS) { tempNode = NULL; } else { if (theLHS->type == AND_CE) tempNode = theLHS->right; else if (theLHS->type == PATTERN_CE) tempNode = theLHS; } { int numFuzzySlotsInNonNotPatterns = 0; numFuzzySlots = FuzzySlotAnalysis(theEnv,tempNode, &numFuzzySlotsInNonNotPatterns); if (numFuzzySlotsInNonNotPatterns > 0) LHSRuleType = FUZZY_LHS; else LHSRuleType = CRISP_LHS; } #endif /*========================================================*/ /* Print out developer information if it's being watched. */ /*========================================================*/ #if DEVELOPER && DEBUGGING_FUNCTIONS if (EnvGetWatchItem(theEnv,"rule-analysis")) { DumpRuleAnalysis(theEnv,tempNode); } #endif /*======================================================*/ /* Check to see if there are any RHS constraint errors. */ /*======================================================*/ if (CheckRHSForConstraintErrors(theEnv,actions,tempNode)) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); return(NULL); } /*=================================================*/ /* Replace variable references in the RHS with the */ /* appropriate variable retrieval functions. */ /*=================================================*/ newActions = CopyExpression(theEnv,actions); if (ReplaceProcVars(theEnv,"RHS of defrule",newActions,NULL,NULL, ReplaceRHSVariable,(void *) tempNode)) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); ReturnExpression(theEnv,newActions); return(NULL); } /*===================================================*/ /* Remove any test CEs from the LHS and attach their */ /* expression to the closest preceeding non-negated */ /* join at the same not/and depth. */ /*===================================================*/ AttachTestCEsToPatternCEs(theEnv,tempNode); /*========================================*/ /* Check to see that logical CEs are used */ /* appropriately in the LHS of the rule. */ /*========================================*/ if ((logicalJoin = LogicalAnalysis(theEnv,tempNode)) < 0) { *error = TRUE; ReturnDefrule(theEnv,topDisjunct); ReturnExpression(theEnv,newActions); return(NULL); } /*==================================*/ /* We're finished for this disjunct */ /* if we're only checking syntax. */ /*==================================*/ if (ConstructData(theEnv)->CheckSyntaxMode) { ReturnExpression(theEnv,newActions); if (emptyLHS) { emptyLHS = FALSE; } else { theLHS = theLHS->bottom; } continue; } /*=================================*/ /* Install the disjunct's actions. */ /*=================================*/ ExpressionInstall(theEnv,newActions); packPtr = PackExpression(theEnv,newActions); ReturnExpression(theEnv,newActions); /*===============================================================*/ /* Create the pattern and join data structures for the new rule. */ /*===============================================================*/ lastJoin = ConstructJoins(theEnv,logicalJoin,tempNode,1,NULL,TRUE,TRUE); /*===================================================================*/ /* Determine the rule's complexity for use with conflict resolution. */ /*===================================================================*/ complexity = RuleComplexity(theEnv,tempNode); /*=====================================================*/ /* Create the defrule data structure for this disjunct */ /* and put it in the list of disjuncts for this rule. */ /*=====================================================*/ #if FUZZY_DEFTEMPLATES /* if not a FUZZY LHS then no need to allocate space to store ptrs to fuzzy slots of the patterns on the LHS since there won't be any -- numFuzzySlots will be 0. */ currentDisjunct = CreateNewDisjunct(theEnv,ruleName,localVarCnt,packPtr,complexity, logicalJoin,lastJoin,numFuzzySlots); /* set the type of LHS of Rule disjunct and also save fuzzy slot locator info for any fuzzy patterns */ currentDisjunct->lhsRuleType = LHSRuleType; if (numFuzzySlots > 0) { struct lhsParseNode *lhsPNPtr, *lhsSlotPtr; int i; /* get ptr to a pattern CE */ if (theLHS->type == AND_CE) lhsPNPtr = theLHS->right; else if (theLHS->type == PATTERN_CE) lhsPNPtr = theLHS; else lhsPNPtr = NULL; patternNum = 0; /* indexed from 0 */ i = 0; while (lhsPNPtr != NULL) { if (lhsPNPtr->type == PATTERN_CE) { lhsSlotPtr = lhsPNPtr->right; while (lhsSlotPtr != NULL) { /*==========================================================*/ /* If fuzzy template slot then save ptr to fuzzy value */ /* */ /* NOTE: when the pattern was added to the pattern net, the */ /* pattern node for the template name was removed (see */ /* PlaceFactPattern) and the pattern node of the FUZZY_VALUE*/ /* was changed a networkTest link in the SF_VARIABLE or */ /* SF_WILDCARD node as an SCALL_PN_FUZZY_VALUE expression. */ /* We need to search for that fuzzy value to put it in the */ /* rule (pattern_fv_arrayPtr points to an array of */ /* structures that holds the pattern number, slot number and*/ /* fuzzy value HN ptrs connected to the patterns of LHS). */ /*==========================================================*/ if (lhsSlotPtr->type == SF_WILDCARD || lhsSlotPtr->type == SF_VARIABLE) { FUZZY_VALUE_HN *fv_ptr; struct fzSlotLocator * fzSL_ptr; fv_ptr = findFuzzyValueInNetworktest(lhsSlotPtr->networkTest); if (fv_ptr != NULL) { fzSL_ptr = currentDisjunct->pattern_fv_arrayPtr + i; fzSL_ptr->patternNum = patternNum; fzSL_ptr->slotNum = (lhsSlotPtr->slotNumber)-1; fzSL_ptr->fvhnPtr = fv_ptr; i++; } } /*=====================================================*/ /* Move on to the next slot in the pattern. */ /*=====================================================*/ lhsSlotPtr = lhsSlotPtr->right; } } /*=====================================================*/ /* Move on to the next pattern in the LHS of the rule. */ /*=====================================================*/ lhsPNPtr = lhsPNPtr->bottom; patternNum++; } /* i should == numFuzzySlots OR something internal is screwed up -- OR this algorithm has a problem. */ if (i != numFuzzySlots) { EnvPrintRouter(theEnv,WERROR,"Internal ERROR *** Fuzzy structures -- routine ProcessRuleLHS\n"); EnvExitRouter(theEnv,EXIT_FAILURE); } } #else currentDisjunct = CreateNewDisjunct(theEnv,ruleName,localVarCnt,packPtr,complexity, (unsigned) logicalJoin,lastJoin); #endif /*============================================================*/ /* Place the disjunct in the list of disjuncts for this rule. */ /* If the disjunct is the first disjunct, then increment the */ /* reference counts for the dynamic salience (the expression */ /* for the dynamic salience is only stored with the first */ /* disjuncts and the other disjuncts refer back to the first */ /* disjunct for their dynamic salience value. */ /*============================================================*/ if (topDisjunct == NULL) { topDisjunct = currentDisjunct; ExpressionInstall(theEnv,topDisjunct->dynamicSalience); #if CERTAINTY_FACTORS ExpressionInstall(theEnv,topDisjunct->dynamicCF); #endif } else lastDisjunct->disjunct = currentDisjunct; /*===========================================*/ /* Move on to the next disjunct of the rule. */ /*===========================================*/ lastDisjunct = currentDisjunct; if (emptyLHS) { emptyLHS = FALSE; } else { theLHS = theLHS->bottom; } } return(topDisjunct); }