📄 factqury.c
字号:
QUERY_TEMPLATE *qtemplates;
unsigned rcnt;
register unsigned i,j;
result->type = MULTIFIELD;
result->begin = 0;
result->end = -1;
qtemplates = DetermineQueryTemplates(theEnv,GetFirstArgument()->nextArg,
"find-all-facts",&rcnt);
if (qtemplates == NULL)
{
result->value = (void *) EnvCreateMultifield(theEnv,0L);
return;
}
PushQueryCore(theEnv);
FactQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
FactQueryData(theEnv)->QueryCore->solns = (struct fact **) gm2(theEnv,(sizeof(struct fact *) * rcnt));
FactQueryData(theEnv)->QueryCore->query = GetFirstArgument();
FactQueryData(theEnv)->QueryCore->action = NULL;
FactQueryData(theEnv)->QueryCore->soln_set = NULL;
FactQueryData(theEnv)->QueryCore->soln_size = rcnt;
FactQueryData(theEnv)->QueryCore->soln_cnt = 0;
TestEntireChain(theEnv,qtemplates,0);
FactQueryData(theEnv)->AbortQuery = FALSE;
result->value = (void *) EnvCreateMultifield(theEnv,FactQueryData(theEnv)->QueryCore->soln_cnt * rcnt);
while (FactQueryData(theEnv)->QueryCore->soln_set != NULL)
{
for (i = 0 , j = (unsigned) (result->end + 2) ; i < rcnt ; i++ , j++)
{
SetMFType(result->value,j,FACT_ADDRESS);
SetMFValue(result->value,j,FactQueryData(theEnv)->QueryCore->soln_set->soln[i]);
}
result->end = (long) j-2;
PopQuerySoln(theEnv);
}
rm(theEnv,(void *) FactQueryData(theEnv)->QueryCore->solns,(sizeof(struct fact *) * rcnt));
rtn_struct(theEnv,query_core,FactQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryTemplates(theEnv,qtemplates);
}
/******************************************************************************
NAME : QueryDoForFact
DESCRIPTION : Finds the first set of facts which satisfy the query and
executes a user-action with that set
INPUTS : None
RETURNS : Caller's result buffer
SIDE EFFECTS : The query template-expressions are evaluated once,
and the query boolean-expression is evaluated
zero or more times (depending on fact restrictions
and how early the expression evaulates to TRUE - if at all).
Also the action expression is executed zero or once.
Caller's result buffer holds result of user-action
NOTES : H/L Syntax : See ParseQueryAction()
******************************************************************************/
globle void QueryDoForFact(
void *theEnv,
DATA_OBJECT *result)
{
QUERY_TEMPLATE *qtemplates;
unsigned rcnt;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
qtemplates = DetermineQueryTemplates(theEnv,GetFirstArgument()->nextArg->nextArg,
"do-for-fact",&rcnt);
if (qtemplates == NULL)
return;
PushQueryCore(theEnv);
FactQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
FactQueryData(theEnv)->QueryCore->solns = (struct fact **) gm2(theEnv,(sizeof(struct fact *) * rcnt));
FactQueryData(theEnv)->QueryCore->query = GetFirstArgument();
FactQueryData(theEnv)->QueryCore->action = GetFirstArgument()->nextArg;
if (TestForFirstInChain(theEnv,qtemplates,0) == TRUE)
EvaluateExpression(theEnv,FactQueryData(theEnv)->QueryCore->action,result);
FactQueryData(theEnv)->AbortQuery = FALSE;
ProcedureFunctionData(theEnv)->BreakFlag = FALSE;
rm(theEnv,(void *) FactQueryData(theEnv)->QueryCore->solns,(sizeof(struct fact *) * rcnt));
rtn_struct(theEnv,query_core,FactQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryTemplates(theEnv,qtemplates);
}
/******************************************************************************
NAME : QueryDoForAllFacts
DESCRIPTION : Finds all sets of facts which satisfy the query and
executes a user-function for each set as it is found
INPUTS : Caller's result buffer
RETURNS : Nothing useful
SIDE EFFECTS : The query template-expressions are evaluated once,
and the query boolean-expression is evaluated
once for every fact set. Also, the action is
executed for every fact set.
Caller's result buffer holds result of last action executed.
NOTES : H/L Syntax : See FactParseQueryAction()
******************************************************************************/
globle void QueryDoForAllFacts(
void *theEnv,
DATA_OBJECT *result)
{
QUERY_TEMPLATE *qtemplates;
unsigned rcnt;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
qtemplates = DetermineQueryTemplates(theEnv,GetFirstArgument()->nextArg->nextArg,
"do-for-all-facts",&rcnt);
if (qtemplates == NULL)
return;
PushQueryCore(theEnv);
FactQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
FactQueryData(theEnv)->QueryCore->solns = (struct fact **) gm2(theEnv,(sizeof(struct fact *) * rcnt));
FactQueryData(theEnv)->QueryCore->query = GetFirstArgument();
FactQueryData(theEnv)->QueryCore->action = GetFirstArgument()->nextArg;
FactQueryData(theEnv)->QueryCore->result = result;
ValueInstall(theEnv,FactQueryData(theEnv)->QueryCore->result);
TestEntireChain(theEnv,qtemplates,0);
ValueDeinstall(theEnv,FactQueryData(theEnv)->QueryCore->result);
PropagateReturnValue(theEnv,FactQueryData(theEnv)->QueryCore->result);
FactQueryData(theEnv)->AbortQuery = FALSE;
ProcedureFunctionData(theEnv)->BreakFlag = FALSE;
rm(theEnv,(void *) FactQueryData(theEnv)->QueryCore->solns,(sizeof(struct fact *) * rcnt));
rtn_struct(theEnv,query_core,FactQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryTemplates(theEnv,qtemplates);
}
/******************************************************************************
NAME : DelayedQueryDoForAllFacts
DESCRIPTION : Finds all sets of facts which satisfy the query and
and exceutes a user-action for each set
This function differs from QueryDoForAllFacts() in
that it forms the complete list of query satisfactions
BEFORE executing any actions.
INPUTS : Caller's result buffer
RETURNS : Nothing useful
SIDE EFFECTS : The query template-expressions are evaluated once,
and the query boolean-expression is evaluated
once for every fact set. The action is executed
for evry query satisfaction.
Caller's result buffer holds result of last action executed.
NOTES : H/L Syntax : See FactParseQueryNoAction()
******************************************************************************/
globle void DelayedQueryDoForAllFacts(
void *theEnv,
DATA_OBJECT *result)
{
QUERY_TEMPLATE *qtemplates;
unsigned rcnt;
register unsigned i;
result->type = SYMBOL;
result->value = EnvFalseSymbol(theEnv);
qtemplates = DetermineQueryTemplates(theEnv,GetFirstArgument()->nextArg->nextArg,
"delayed-do-for-all-facts",&rcnt);
if (qtemplates == NULL)
return;
PushQueryCore(theEnv);
FactQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
FactQueryData(theEnv)->QueryCore->solns = (struct fact **) gm2(theEnv,(sizeof(struct fact *) * rcnt));
FactQueryData(theEnv)->QueryCore->query = GetFirstArgument();
FactQueryData(theEnv)->QueryCore->action = NULL;
FactQueryData(theEnv)->QueryCore->soln_set = NULL;
FactQueryData(theEnv)->QueryCore->soln_size = rcnt;
FactQueryData(theEnv)->QueryCore->soln_cnt = 0;
TestEntireChain(theEnv,qtemplates,0);
FactQueryData(theEnv)->AbortQuery = FALSE;
FactQueryData(theEnv)->QueryCore->action = GetFirstArgument()->nextArg;
while (FactQueryData(theEnv)->QueryCore->soln_set != NULL)
{
for (i = 0 ; i < rcnt ; i++)
FactQueryData(theEnv)->QueryCore->solns[i] = FactQueryData(theEnv)->QueryCore->soln_set->soln[i];
PopQuerySoln(theEnv);
EvaluationData(theEnv)->CurrentEvaluationDepth++;
EvaluateExpression(theEnv,FactQueryData(theEnv)->QueryCore->action,result);
EvaluationData(theEnv)->CurrentEvaluationDepth--;
if (ProcedureFunctionData(theEnv)->ReturnFlag == TRUE)
{ PropagateReturnValue(theEnv,result); }
PeriodicCleanup(theEnv,FALSE,TRUE);
if (EvaluationData(theEnv)->HaltExecution || ProcedureFunctionData(theEnv)->BreakFlag || ProcedureFunctionData(theEnv)->ReturnFlag)
{
while (FactQueryData(theEnv)->QueryCore->soln_set != NULL)
PopQuerySoln(theEnv);
break;
}
}
ProcedureFunctionData(theEnv)->BreakFlag = FALSE;
rm(theEnv,(void *) FactQueryData(theEnv)->QueryCore->solns,(sizeof(struct fact *) * rcnt));
rtn_struct(theEnv,query_core,FactQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryTemplates(theEnv,qtemplates);
}
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/*******************************************************
NAME : PushQueryCore
DESCRIPTION : Pushes the current QueryCore onto stack
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Allocates new stack node and changes
QueryCoreStack
NOTES : None
*******************************************************/
static void PushQueryCore(
void *theEnv)
{
QUERY_STACK *qptr;
qptr = get_struct(theEnv,query_stack);
qptr->core = FactQueryData(theEnv)->QueryCore;
qptr->nxt = FactQueryData(theEnv)->QueryCoreStack;
FactQueryData(theEnv)->QueryCoreStack = qptr;
}
/******************************************************
NAME : PopQueryCore
DESCRIPTION : Pops top of QueryCore stack and
restores QueryCore to this core
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Stack node deallocated, QueryCoreStack
changed and QueryCore reset
NOTES : Assumes stack is not empty
******************************************************/
static void PopQueryCore(
void *theEnv)
{
QUERY_STACK *qptr;
FactQueryData(theEnv)->QueryCore = FactQueryData(theEnv)->QueryCoreStack->core;
qptr = FactQueryData(theEnv)->QueryCoreStack;
FactQueryData(theEnv)->QueryCoreStack = FactQueryData(theEnv)->QueryCoreStack->nxt;
rtn_struct(theEnv,query_stack,qptr);
}
/***************************************************
NAME : FindQueryCore
DESCRIPTION : Looks up a QueryCore Stack Frame
Depth 0 is current frame
1 is next deepest, etc.
INPUTS : Depth
RETURNS : Address of query core stack frame
SIDE EFFECTS : None
NOTES : None
***************************************************/
static QUERY_CORE *FindQueryCore(
void *theEnv,
int depth)
{
QUERY_STACK *qptr;
if (depth == 0)
return(FactQueryData(theEnv)->QueryCore);
qptr = FactQueryData(theEnv)->QueryCoreStack;
while (depth > 1)
{
qptr = qptr->nxt;
depth--;
}
return(qptr->core);
}
/**********************************************************
NAME : DetermineQueryTemplates
DESCRIPTION : Builds a list of templates to be used in
fact queries - uses parse form.
INPUTS : 1) The parse template expression chain
2) The name of the function being executed
3) Caller's buffer for restriction count
(# of separate lists)
RETURNS : The query list, or NULL on errors
SIDE EFFECTS : Memory allocated for list
Busy count incremented for all templates
NOTES : Each restriction is linked by nxt pointer,
multiple templates in a restriction are
linked by the chain pointer.
Rcnt caller's buffer is set to reflect the
total number of chains
Assumes classExp is not NULL and that each
restriction chain is terminated with
the QUERY_DELIMITER_SYMBOL "(QDS)"
**********************************************************/
static QUERY_TEMPLATE *DetermineQueryTemplates(
void *theEnv,
EXPRESSION *templateExp,
char *func,
unsigned *rcnt)
{
QUERY_TEMPLATE *clist = NULL,*cnxt = NULL,*cchain = NULL,*tmp;
int new_list = FALSE;
DATA_OBJECT temp;
*rcnt = 0;
while (templateExp != NULL)
{
if (EvaluateExpression(theEnv,templateExp,&temp))
{
DeleteQueryTemplates(theEnv,clist);
return(NULL);
}
if ((temp.type == SYMBOL) && (temp.value == (void *) FactQueryData(theEnv)->QUERY_DELIMETER_SYMBOL))
{
new_list = TRUE;
(*rcnt)++;
}
else if ((tmp = FormChain(theEnv,func,&temp)) != NULL)
{
if (clist == NULL)
clist = cnxt = cchain = tmp;
else if (new_list == TRUE)
{
new_list = FALSE;
cnxt->nxt = tmp;
cnxt = cchain = tmp;
}
else
cchain->chain = tmp;
while (cchain->chain != NULL)
cchain = cchain->chain;
}
else
{
SyntaxErrorMessage(theEnv,"fact-set query class restrictions");
DeleteQueryTemplates(theEnv,clist);
SetEvaluationError(theEnv,TRUE);
return(NULL);
}
templateExp = templateExp->nextArg;
}
return(clist);
}
/*************************************************************
NAME : FormChain
DESCRIPTION : Builds a list of classes to be used in
fact queries - uses parse form.
INPUTS : 1) Name of calling function for error msgs
2) Data object - must be a symbol or a
multifield value containing all symbols
The symbols must be names of existing templates
RETURNS : The query chain, or NULL on errors
SIDE EFFECTS : Memory allocated for chain
Busy count incremented for all templates
NOTES : None
*************************************************************/
static QUERY_TEMPLATE *FormChain(
void *theEnv,
char *func,
DATA_OBJECT *val)
{
struct deftemplate *templatePtr;
QUERY_TEMPLATE *head,*bot,*tmp;
register long i,end; /* 6.04 Bug Fix */
char *templateName;
int count;
if (val->type == DEFTEMPLATE_PTR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -