/*********************************************************************** NAME : ParseQueryNoAction DESCRIPTION : Parses the following functions : (any-instancep) (find-first-instance) (find-all-instances) INPUTS : 1) The address of the top node of the query function 2) The logical name of the input RETURNS : The completed expression chain, or NULL on errors SIDE EFFECTS : The expression chain is extended, or the "top" node is deleted on errors NOTES : H/L Syntax : (<function> <query-block>) <query-block> :== (<instance-var>+) <query-expression> <instance-var> :== (<var-name> <class-name>+) Parses into following form : <query-function> | V <query-expression> -> <class-1a> -> <class-1b> -> (QDS) -> <class-2a> -> <class-2b> -> (QDS) -> ... ***********************************************************************/ globle EXPRESSION *ParseQueryNoAction( void *theEnv, EXPRESSION *top, char *readSource) { EXPRESSION *insQuerySetVars; struct token queryInputToken; insQuerySetVars = ParseQueryRestrictions(theEnv,top,readSource,&queryInputToken); if (insQuerySetVars == NULL) return(NULL); IncrementIndentDepth(theEnv,3); PPCRAndIndent(theEnv); if (ParseQueryTestExpression(theEnv,top,readSource) == FALSE) { DecrementIndentDepth(theEnv,3); ReturnExpression(theEnv,insQuerySetVars); return(NULL); } DecrementIndentDepth(theEnv,3); GetToken(theEnv,readSource,&queryInputToken); if (GetType(queryInputToken) != RPAREN) { SyntaxErrorMessage(theEnv,"instance-set query function"); ReturnExpression(theEnv,top); ReturnExpression(theEnv,insQuerySetVars); return(NULL); } ReplaceInstanceVariables(theEnv,insQuerySetVars,top->argList,TRUE,0); ReturnExpression(theEnv,insQuerySetVars); return(top); }
/*********************************************************************************** NAME : ReplaceInstanceVariables DESCRIPTION : Replaces all references to instance-variables within an instance query-function with function calls to query-instance (which references the instance array at run-time) INPUTS : 1) The instance-variable list 2) A boolean expression containing variable references 3) A flag indicating whether to allow slot references of the type <instance-query-variable>:<slot-name> for direct slot access or not 4) Nesting depth of query functions RETURNS : Nothing useful SIDE EFFECTS : If a SF_VARIABLE node is found and is on the list of instance variables, it is replaced with a query-instance function call. NOTES : Other SF_VARIABLE(S) are left alone for replacement by other parsers. This implies that a user may use defgeneric, defrule, and defmessage-handler variables within a query-function where they do not conflict with instance-variable names. ***********************************************************************************/ static void ReplaceInstanceVariables( void *theEnv, EXEC_STATUS, EXPRESSION *vlist, EXPRESSION *bexp, int sdirect, int ndepth) { EXPRESSION *eptr; struct FunctionDefinition *rindx_func,*rslot_func; int posn; rindx_func = FindFunction(theEnv,execStatus,"(query-instance)"); rslot_func = FindFunction(theEnv,execStatus,"(query-instance-slot)"); while (bexp != NULL) { if (bexp->type == SF_VARIABLE) { eptr = vlist; posn = 0; while ((eptr != NULL) ? (eptr->value != bexp->value) : FALSE) { eptr = eptr->nextArg; posn++; } if (eptr != NULL) { bexp->type = FCALL; bexp->value = (void *) rindx_func; eptr = GenConstant(theEnv,execStatus,INTEGER,(void *) EnvAddLong(theEnv,execStatus,(long long) ndepth)); eptr->nextArg = GenConstant(theEnv,execStatus,INTEGER,(void *) EnvAddLong(theEnv,execStatus,(long long) posn)); bexp->argList = eptr; } else if (sdirect == TRUE) ReplaceSlotReference(theEnv,execStatus,vlist,bexp,rslot_func,ndepth); } if (bexp->argList != NULL) { if (IsQueryFunction(bexp)) ReplaceInstanceVariables(theEnv,execStatus,vlist,bexp->argList,sdirect,ndepth+1); else ReplaceInstanceVariables(theEnv,execStatus,vlist,bexp->argList,sdirect,ndepth); } bexp = bexp->nextArg; } }