globle struct fact *CreateFact( void *vTheDeftemplate) { struct deftemplate *theDeftemplate = (struct deftemplate *) vTheDeftemplate; struct fact *newFact; int i; /*=================================*/ /* A deftemplate must be specified */ /* in order to create a fact. */ /*=================================*/ if (theDeftemplate == NULL) return(NULL); /*============================================*/ /* Create a fact for an explicit deftemplate. */ /*============================================*/ if (theDeftemplate->implied == FALSE) { newFact = CreateFactBySize((int) theDeftemplate->numberOfSlots); for (i = 0; i < (int) theDeftemplate->numberOfSlots; i++) { newFact->theProposition.theFields[i].type = RVOID; } } /*===========================================*/ /* Create a fact for an implied deftemplate. */ /*===========================================*/ else { newFact = CreateFactBySize(1); newFact->theProposition.theFields[0].type = MULTIFIELD; newFact->theProposition.theFields[0].value = CreateMultifield2(0L); } /*===============================*/ /* Return a pointer to the fact. */ /*===============================*/ newFact->whichDeftemplate = theDeftemplate; return(newFact); }
globle struct fact *StringToFact( char *str) { struct token theToken; struct fact *factPtr; int numberOfFields = 0, whichField; struct expr *assertArgs, *tempPtr; int error = FALSE; DATA_OBJECT theResult; /*=========================================*/ /* Open a string router and parse the fact */ /* using the router as an input source. */ /*=========================================*/ OpenStringSource("assert_str",str,0); assertArgs = GetRHSPattern("assert_str",&theToken, &error,FALSE,TRUE, TRUE,RPAREN); CloseStringSource("assert_str"); /*===========================================*/ /* Check for errors or the use of variables. */ /*===========================================*/ if (error) { ReturnExpression(assertArgs); return(NULL); } if (ExpressionContainsVariables(assertArgs,FALSE)) { LocalVariableErrorMessage("the assert-string function"); SetEvaluationError(TRUE); ReturnExpression(assertArgs); return(NULL); } /*=======================================================*/ /* Count the number of fields needed for the fact and */ /* create a fact data structure of the appropriate size. */ /*=======================================================*/ for (tempPtr = assertArgs->nextArg; tempPtr != NULL; tempPtr = tempPtr->nextArg) { numberOfFields++; } factPtr = (struct fact *) CreateFactBySize(numberOfFields); factPtr->whichDeftemplate = (struct deftemplate *) assertArgs->value; /*=============================================*/ /* Copy the fields to the fact data structure. */ /*=============================================*/ whichField = 0; for (tempPtr = assertArgs->nextArg; tempPtr != NULL; tempPtr = tempPtr->nextArg) { EvaluateExpression(tempPtr,&theResult); factPtr->theProposition.theFields[whichField].type = (short) theResult.type; factPtr->theProposition.theFields[whichField].value = theResult.value; whichField++; } ReturnExpression(assertArgs); /*==================*/ /* Return the fact. */ /*==================*/ return(factPtr); }
globle void AssertCommand( void *theEnv, DATA_OBJECT_PTR rv) { struct deftemplate *theDeftemplate; struct field *theField; DATA_OBJECT theValue; struct expr *theExpression; struct templateSlot *slotPtr; struct fact *newFact; int error = FALSE; int i; struct fact *theFact; /*===================================================*/ /* Set the default return value to the symbol FALSE. */ /*===================================================*/ SetpType(rv,SYMBOL); SetpValue(rv,EnvFalseSymbol(theEnv)); /*================================*/ /* Get the deftemplate associated */ /* with the fact being asserted. */ /*================================*/ theExpression = GetFirstArgument(); theDeftemplate = (struct deftemplate *) theExpression->value; /*=======================================*/ /* Create the fact and store the name of */ /* the deftemplate as the 1st field. */ /*=======================================*/ if (theDeftemplate->implied == FALSE) { newFact = CreateFactBySize(theEnv,theDeftemplate->numberOfSlots); slotPtr = theDeftemplate->slotList; } else { newFact = CreateFactBySize(theEnv,1); if (theExpression->nextArg == NULL) { newFact->theProposition.theFields[0].type = MULTIFIELD; newFact->theProposition.theFields[0].value = CreateMultifield2(theEnv,0L); } slotPtr = NULL; } newFact->whichDeftemplate = theDeftemplate; /*===================================================*/ /* Evaluate the expression associated with each slot */ /* and store the result in the appropriate slot of */ /* the newly created fact. */ /*===================================================*/ theField = newFact->theProposition.theFields; for (theExpression = theExpression->nextArg, i = 0; theExpression != NULL; theExpression = theExpression->nextArg, i++) { /*===================================================*/ /* Evaluate the expression to be stored in the slot. */ /*===================================================*/ EvaluateExpression(theEnv,theExpression,&theValue); /*============================================================*/ /* A multifield value can't be stored in a single field slot. */ /*============================================================*/ if ((slotPtr != NULL) ? (slotPtr->multislot == FALSE) && (theValue.type == MULTIFIELD) : FALSE) { MultiIntoSingleFieldSlotError(theEnv,slotPtr,theDeftemplate); theValue.type = SYMBOL; theValue.value = EnvFalseSymbol(theEnv); error = TRUE; } /*==============================*/ /* Store the value in the slot. */ /*==============================*/ theField[i].type = theValue.type; theField[i].value = theValue.value; /*========================================*/ /* Get the information for the next slot. */ /*========================================*/ if (slotPtr != NULL) slotPtr = slotPtr->next; } /*============================================*/ /* If an error occured while generating the */ /* fact's slot values, then abort the assert. */ /*============================================*/ if (error) { ReturnFact(theEnv,newFact); return; } /*================================*/ /* Add the fact to the fact-list. */ /*================================*/ theFact = (struct fact *) EnvAssert(theEnv,(void *) newFact); /*========================================*/ /* The asserted fact is the return value. */ /*========================================*/ if (theFact != NULL) { SetpType(rv,FACT_ADDRESS); SetpValue(rv,(void *) theFact); } return; }
static void DuplicateModifyCommand( void *theEnv, int retractIt, DATA_OBJECT_PTR returnValue) { long int factNum; struct fact *oldFact, *newFact, *theFact; struct expr *testPtr; DATA_OBJECT computeResult; struct deftemplate *templatePtr; struct templateSlot *slotPtr; int i, position, found; /*===================================================*/ /* Set the default return value to the symbol FALSE. */ /*===================================================*/ SetpType(returnValue,SYMBOL); SetpValue(returnValue,SymbolData(theEnv)->FalseSymbol); /*==================================================*/ /* Evaluate the first argument which is used to get */ /* a pointer to the fact to be modified/duplicated. */ /*==================================================*/ testPtr = GetFirstArgument(); EvaluateExpression(theEnv,testPtr,&computeResult); /*==============================================================*/ /* If an integer is supplied, then treat it as a fact-index and */ /* search the fact-list for the fact with that fact-index. */ /*==============================================================*/ if (computeResult.type == INTEGER) { factNum = ValueToLong(computeResult.value); if (factNum < 0) { if (retractIt) ExpectedTypeError2(theEnv,"modify",1); else ExpectedTypeError2(theEnv,"duplicate",1); SetEvaluationError(theEnv,TRUE); return; } oldFact = (struct fact *) EnvGetNextFact(theEnv,NULL); while (oldFact != NULL) { if (oldFact->factIndex == factNum) { break; } else { oldFact = oldFact->nextFact; } } if (oldFact == NULL) { char tempBuffer[20]; sprintf(tempBuffer,"f-%ld",factNum); CantFindItemErrorMessage(theEnv,"fact",tempBuffer); return; } } /*==========================================*/ /* Otherwise, if a pointer is supplied then */ /* no lookup is required. */ /*==========================================*/ else if (computeResult.type == FACT_ADDRESS) { oldFact = (struct fact *) computeResult.value; } /*===========================================*/ /* Otherwise, the first argument is invalid. */ /*===========================================*/ else { if (retractIt) ExpectedTypeError2(theEnv,"modify",1); else ExpectedTypeError2(theEnv,"duplicate",1); SetEvaluationError(theEnv,TRUE); return; } /*==================================*/ /* See if it is a deftemplate fact. */ /*==================================*/ templatePtr = oldFact->whichDeftemplate; if (templatePtr->implied) return; /*================================================================*/ /* Duplicate the values from the old fact (skipping multifields). */ /*================================================================*/ newFact = (struct fact *) CreateFactBySize(theEnv,oldFact->theProposition.multifieldLength); newFact->whichDeftemplate = templatePtr; for (i = 0; i < (int) oldFact->theProposition.multifieldLength; i++) { newFact->theProposition.theFields[i].type = oldFact->theProposition.theFields[i].type; if (newFact->theProposition.theFields[i].type != MULTIFIELD) { newFact->theProposition.theFields[i].value = oldFact->theProposition.theFields[i].value; } else { newFact->theProposition.theFields[i].value = NULL; } } /*========================*/ /* Start replacing slots. */ /*========================*/ testPtr = testPtr->nextArg; while (testPtr != NULL) { /*============================================================*/ /* If the slot identifier is an integer, then the slot was */ /* previously identified and its position within the template */ /* was stored. Otherwise, the position of the slot within the */ /* deftemplate has to be determined by comparing the name of */ /* the slot against the list of slots for the deftemplate. */ /*============================================================*/ if (testPtr->type == INTEGER) { position = (int) ValueToLong(testPtr->value); } else { found = FALSE; position = 0; slotPtr = templatePtr->slotList; while (slotPtr != NULL) { if (slotPtr->slotName == (SYMBOL_HN *) testPtr->value) { found = TRUE; slotPtr = NULL; } else { slotPtr = slotPtr->next; position++; } } if (! found) { InvalidDeftemplateSlotMessage(theEnv,ValueToString(testPtr->value), ValueToString(templatePtr->header.name)); SetEvaluationError(theEnv,TRUE); ReturnFact(theEnv,newFact); return; } } /*===================================================*/ /* If a single field slot is being replaced, then... */ /*===================================================*/ if (newFact->theProposition.theFields[position].type != MULTIFIELD) { /*======================================================*/ /* If the list of values to store in the slot is empty */ /* or contains more than one member than an error has */ /* occured because a single field slot can only contain */ /* a single value. */ /*======================================================*/ if ((testPtr->argList == NULL) ? TRUE : (testPtr->argList->nextArg != NULL)) { MultiIntoSingleFieldSlotError(theEnv,GetNthSlot(templatePtr,position),templatePtr); ReturnFact(theEnv,newFact); return; } /*===================================================*/ /* Evaluate the expression to be stored in the slot. */ /*===================================================*/ EvaluateExpression(theEnv,testPtr->argList,&computeResult); SetEvaluationError(theEnv,FALSE); /*====================================================*/ /* If the expression evaluated to a multifield value, */ /* then an error occured since a multifield value can */ /* not be stored in a single field slot. */ /*====================================================*/ if (computeResult.type == MULTIFIELD) { ReturnFact(theEnv,newFact); MultiIntoSingleFieldSlotError(theEnv,GetNthSlot(templatePtr,position),templatePtr); return; } /*=============================*/ /* Store the value in the slot */ /*=============================*/ newFact->theProposition.theFields[position].type = computeResult.type; newFact->theProposition.theFields[position].value = computeResult.value; } /*=================================*/ /* Else replace a multifield slot. */ /*=================================*/ else { /*======================================*/ /* Determine the new value of the slot. */ /*======================================*/ StoreInMultifield(theEnv,&computeResult,testPtr->argList,FALSE); SetEvaluationError(theEnv,FALSE); /*=============================*/ /* Store the value in the slot */ /*=============================*/ newFact->theProposition.theFields[position].type = computeResult.type; newFact->theProposition.theFields[position].value = computeResult.value; } testPtr = testPtr->nextArg; } /*=====================================*/ /* Copy the multifield values from the */ /* old fact that were not replaced. */ /*=====================================*/ for (i = 0; i < (int) oldFact->theProposition.multifieldLength; i++) { if ((newFact->theProposition.theFields[i].type == MULTIFIELD) && (newFact->theProposition.theFields[i].value == NULL)) { newFact->theProposition.theFields[i].value = CopyMultifield(theEnv,(struct multifield *) oldFact->theProposition.theFields[i].value); } } /*======================================*/ /* Perform the duplicate/modify action. */ /*======================================*/ if (retractIt) EnvRetract(theEnv,oldFact); theFact = (struct fact *) EnvAssert(theEnv,newFact); /*========================================*/ /* The asserted fact is the return value. */ /*========================================*/ if (theFact != NULL) { SetpDOBegin(returnValue,1); SetpDOEnd(returnValue,theFact->theProposition.multifieldLength); SetpType(returnValue,FACT_ADDRESS); SetpValue(returnValue,(void *) theFact); } return; }
globle struct fact *StringToFact( char *str) { struct token theToken; struct fact *factPtr; int numberOfFields = 0, whichField; struct expr *assertArgs, *tempPtr; int error = FALSE; DATA_OBJECT theResult; /*=========================================*/ /* Open a string router and parse the fact */ /* using the router as an input source. */ /*=========================================*/ OpenStringSource("assert_str",str,0); assertArgs = GetRHSPattern("assert_str",&theToken, &error,FALSE,TRUE, TRUE,RPAREN); CloseStringSource("assert_str"); #if CERTAINTY_FACTORS /* GetRHSPattern called above may have left a token in the lookahead Token (theUnToken) -- see GetRHSPattern and Scanner.c -- clear it since we are closing the string source and it should not be read when next token requested NOTE: this may not be needed now that am not unGetting STOP tokens? */ ClearTheUnToken(); #endif /*===========================================*/ /* Check for errors or the use of variables. */ /*===========================================*/ if (error) { ReturnExpression(assertArgs); return(NULL); } if (ExpressionContainsVariables(assertArgs,FALSE)) { LocalVariableErrorMessage("the assert-string function"); SetEvaluationError(TRUE); ReturnExpression(assertArgs); return(NULL); } /*=======================================================*/ /* Count the number of fields needed for the fact and */ /* create a fact data structure of the appropriate size. */ /*=======================================================*/ for (tempPtr = assertArgs->nextArg; tempPtr != NULL; tempPtr = tempPtr->nextArg) { numberOfFields++; } factPtr = (struct fact *) CreateFactBySize(numberOfFields); factPtr->whichDeftemplate = (struct deftemplate *) assertArgs->value; #if CERTAINTY_FACTORS /* get the CF from the argList of the DEFTEMPLATE_PTR expr struct currently pointed at be assertArgs */ if (assertArgs->argList == NULL) factPtr->factCF = 1.0; else { EvaluateExpression(assertArgs->argList,&theResult); if (theResult.type != FLOAT && theResult.type != INTEGER) { cfNonNumberError(); factPtr->factCF = 1.0; } else factPtr->factCF = (theResult.type == FLOAT) ? ValueToDouble(theResult.value) : (double)ValueToLong(theResult.value); } #endif /*=============================================*/ /* Copy the fields to the fact data structure. */ /*=============================================*/ ExpressionInstall(assertArgs); /* DR0836 */ whichField = 0; for (tempPtr = assertArgs->nextArg; tempPtr != NULL; tempPtr = tempPtr->nextArg) { #if FUZZY_DEFTEMPLATES /* 03-07-96 */ /* NOTE: a fuzzy fact should have been parsed to give a single constant arg of type FUZZY_VALUE */ #endif EvaluateExpression(tempPtr,&theResult); factPtr->theProposition.theFields[whichField].type = (short) theResult.type; factPtr->theProposition.theFields[whichField].value = theResult.value; whichField++; } ExpressionDeinstall(assertArgs); /* DR0836 */ ReturnExpression(assertArgs); /*==================*/ /* Return the fact. */ /*==================*/ return(factPtr); }