#include "setup.h"
#if INSTANCE_SET_QUERIES
#include "argacces.h"
#include "classcom.h"
#include "classfun.h"
#include "envrnmnt.h"
#include "exprnpsr.h"
#include "insfun.h"
#include "insmngr.h"
#include "insqypsr.h"
#include "memalloc.h"
#include "prcdrfun.h"
#include "prntutil.h"
#include "router.h"
#include "utility.h"
#include "insquery.h"
static void PushQueryCore(Environment *);
static void PopQueryCore(Environment *);
static QUERY_CORE *FindQueryCore(Environment *,long long);
static QUERY_CLASS *DetermineQueryClasses(Environment *,Expression *,const char *,unsigned *);
static QUERY_CLASS *FormChain(Environment *,const char *,Defclass *,UDFValue *);
static void DeleteQueryClasses(Environment *,QUERY_CLASS *);
static bool TestForFirstInChain(Environment *,QUERY_CLASS *,unsigned);
static bool TestForFirstInstanceInClass(Environment *,Defmodule *,int,Defclass *,QUERY_CLASS *,unsigned);
static void TestEntireChain(Environment *,QUERY_CLASS *,unsigned);
static void TestEntireClass(Environment *,Defmodule *,int,Defclass *,QUERY_CLASS *,unsigned);
static void AddSolution(Environment *);
static void PopQuerySoln(Environment *);
void SetupQuery(
Environment *theEnv)
{
AllocateEnvironmentData(theEnv,INSTANCE_QUERY_DATA,sizeof(struct instanceQueryData),NULL);
#if ! RUN_TIME
InstanceQueryData(theEnv)->QUERY_DELIMITER_SYMBOL = CreateSymbol(theEnv,QUERY_DELIMITER_STRING);
IncrementLexemeCount(InstanceQueryData(theEnv)->QUERY_DELIMITER_SYMBOL);
AddUDF(theEnv,"(query-instance)","n",0,UNBOUNDED,NULL,GetQueryInstance,"GetQueryInstance",NULL);
AddUDF(theEnv,"(query-instance-slot)","*",0,UNBOUNDED,NULL,GetQueryInstanceSlot,"GetQueryInstanceSlot",NULL);
AddUDF(theEnv,"any-instancep","b",0,UNBOUNDED,NULL,AnyInstances,"AnyInstances",NULL);
AddUDF(theEnv,"find-instance","m",0,UNBOUNDED,NULL,QueryFindInstance,"QueryFindInstance",NULL);
AddUDF(theEnv,"find-all-instances","m",0,UNBOUNDED,NULL,QueryFindAllInstances,"QueryFindAllInstances",NULL);
AddUDF(theEnv,"do-for-instance","*",0,UNBOUNDED,NULL,QueryDoForInstance,"QueryDoForInstance",NULL);
AddUDF(theEnv,"do-for-all-instances","*",0,UNBOUNDED,NULL,QueryDoForAllInstances,"QueryDoForAllInstances",NULL);
AddUDF(theEnv,"delayed-do-for-all-instances","*",0,UNBOUNDED,NULL,DelayedQueryDoForAllInstances,"DelayedQueryDoForAllInstances",NULL);
#endif
AddFunctionParser(theEnv,"any-instancep",ParseQueryNoAction);
AddFunctionParser(theEnv,"find-instance",ParseQueryNoAction);
AddFunctionParser(theEnv,"find-all-instances",ParseQueryNoAction);
AddFunctionParser(theEnv,"do-for-instance",ParseQueryAction);
AddFunctionParser(theEnv,"do-for-all-instances",ParseQueryAction);
AddFunctionParser(theEnv,"delayed-do-for-all-instances",ParseQueryAction);
}
void GetQueryInstance(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
QUERY_CORE *core;
core = FindQueryCore(theEnv,GetFirstArgument()->integerValue->contents);
returnValue->value = GetFullInstanceName(theEnv,core->solns[GetFirstArgument()->nextArg->integerValue->contents]);
}
void GetQueryInstanceSlot(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
Instance *ins;
InstanceSlot *sp;
UDFValue temp;
QUERY_CORE *core;
const char *varSlot;
returnValue->lexemeValue = FalseSymbol(theEnv);
core = FindQueryCore(theEnv,GetFirstArgument()->integerValue->contents);
ins = core->solns[GetFirstArgument()->nextArg->integerValue->contents];
varSlot = GetFirstArgument()->nextArg->nextArg->nextArg->lexemeValue->contents;
if (ins->garbage)
{
InstanceVarSlotErrorMessage1(theEnv,ins,varSlot);
SetEvaluationError(theEnv,true);
return;
}
EvaluateExpression(theEnv,GetFirstArgument()->nextArg->nextArg,&temp);
if (temp.header->type != SYMBOL_TYPE)
{
InvalidVarSlotErrorMessage(theEnv,varSlot);
SetEvaluationError(theEnv,true);
return;
}
sp = FindInstanceSlot(theEnv,ins,temp.lexemeValue);
if (sp == NULL)
{
InstanceVarSlotErrorMessage2(theEnv,ins,varSlot);
SetEvaluationError(theEnv,true);
return;
}
returnValue->value = sp->value;
if (sp->type == MULTIFIELD_TYPE)
{
returnValue->begin = 0;
returnValue->range = sp->multifieldValue->length;
}
}
void AnyInstances(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
QUERY_CLASS *qclasses;
unsigned rcnt;
bool testResult;
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg,
"any-instancep",&rcnt);
if (qclasses == NULL)
{
returnValue->lexemeValue = FalseSymbol(theEnv);
return;
}
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (Instance **) gm2(theEnv,(sizeof(Instance *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
testResult = TestForFirstInChain(theEnv,qclasses,0);
InstanceQueryData(theEnv)->AbortQuery = false;
rm(theEnv,InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(Instance *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
returnValue->lexemeValue = CreateBoolean(theEnv,testResult);
}
void QueryFindInstance(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
QUERY_CLASS *qclasses;
unsigned rcnt,i;
returnValue->begin = 0;
returnValue->range = 0;
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg,
"find-instance",&rcnt);
if (qclasses == NULL)
{
returnValue->value = CreateMultifield(theEnv,0L);
return;
}
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (Instance **)
gm2(theEnv,(sizeof(Instance *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
if (TestForFirstInChain(theEnv,qclasses,0) == true)
{
returnValue->value = CreateMultifield(theEnv,rcnt);
returnValue->range = rcnt;
for (i = 0 ; i < rcnt ; i++)
{
returnValue->multifieldValue->contents[i].lexemeValue =
GetFullInstanceName(theEnv,InstanceQueryData(theEnv)->QueryCore->solns[i]);
}
}
else
returnValue->value = CreateMultifield(theEnv,0L);
InstanceQueryData(theEnv)->AbortQuery = false;
rm(theEnv,InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(Instance *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
void QueryFindAllInstances(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
QUERY_CLASS *qclasses;
unsigned rcnt;
size_t i, j;
returnValue->begin = 0;
returnValue->range = 0;
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg,
"find-all-instances",&rcnt);
if (qclasses == NULL)
{
returnValue->value = CreateMultifield(theEnv,0L);
return;
}
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (Instance **) gm2(theEnv,(sizeof(Instance *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
InstanceQueryData(theEnv)->QueryCore->action = NULL;
InstanceQueryData(theEnv)->QueryCore->soln_set = NULL;
InstanceQueryData(theEnv)->QueryCore->soln_size = rcnt;
InstanceQueryData(theEnv)->QueryCore->soln_cnt = 0;
TestEntireChain(theEnv,qclasses,0);
InstanceQueryData(theEnv)->AbortQuery = false;
returnValue->value = CreateMultifield(theEnv,InstanceQueryData(theEnv)->QueryCore->soln_cnt * rcnt);
while (InstanceQueryData(theEnv)->QueryCore->soln_set != NULL)
{
for (i = 0 , j = returnValue->range ; i < rcnt ; i++ , j++)
{
returnValue->multifieldValue->contents[j].lexemeValue =
GetFullInstanceName(theEnv,InstanceQueryData(theEnv)->QueryCore->soln_set->soln[i]);
}
returnValue->range = j;
PopQuerySoln(theEnv);
}
rm(theEnv,InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(Instance *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
void QueryDoForInstance(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
QUERY_CLASS *qclasses;
unsigned i, rcnt;
returnValue->lexemeValue = FalseSymbol(theEnv);
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg->nextArg,
"do-for-instance",&rcnt);
if (qclasses == NULL)
return;
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (Instance **) gm2(theEnv,(sizeof(Instance *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
InstanceQueryData(theEnv)->QueryCore->action = GetFirstArgument()->nextArg;
if (TestForFirstInChain(theEnv,qclasses,0) == true)
{
for (i = 0; i < rcnt; i++)
{ InstanceQueryData(theEnv)->QueryCore->solns[i]->busy++; }
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->action,returnValue);
for (i = 0; i < rcnt; i++)
{ InstanceQueryData(theEnv)->QueryCore->solns[i]->busy--; }
}
InstanceQueryData(theEnv)->AbortQuery = false;
ProcedureFunctionData(theEnv)->BreakFlag = false;
rm(theEnv,InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(Instance *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
void QueryDoForAllInstances(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
QUERY_CLASS *qclasses;
unsigned rcnt;
returnValue->lexemeValue = FalseSymbol(theEnv);
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg->nextArg,
"do-for-all-instances",&rcnt);
if (qclasses == NULL)
return;
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (Instance **) gm2(theEnv,(sizeof(Instance *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
InstanceQueryData(theEnv)->QueryCore->action = GetFirstArgument()->nextArg;
InstanceQueryData(theEnv)->QueryCore->result = returnValue;
RetainUDFV(theEnv,InstanceQueryData(theEnv)->QueryCore->result);
TestEntireChain(theEnv,qclasses,0);
ReleaseUDFV(theEnv,InstanceQueryData(theEnv)->QueryCore->result);
InstanceQueryData(theEnv)->AbortQuery = false;
ProcedureFunctionData(theEnv)->BreakFlag = false;
rm(theEnv,InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(Instance *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
void DelayedQueryDoForAllInstances(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
QUERY_CLASS *qclasses;
unsigned rcnt;
unsigned i;
GCBlock gcb;
QUERY_SOLN *theSet;
returnValue->lexemeValue = FalseSymbol(theEnv);
qclasses = DetermineQueryClasses(theEnv,GetFirstArgument()->nextArg->nextArg,
"delayed-do-for-all-instances",&rcnt);
if (qclasses == NULL)
return;
PushQueryCore(theEnv);
InstanceQueryData(theEnv)->QueryCore = get_struct(theEnv,query_core);
InstanceQueryData(theEnv)->QueryCore->solns = (Instance **) gm2(theEnv,(sizeof(Instance *) * rcnt));
InstanceQueryData(theEnv)->QueryCore->query = GetFirstArgument();
InstanceQueryData(theEnv)->QueryCore->action = NULL;
InstanceQueryData(theEnv)->QueryCore->soln_set = NULL;
InstanceQueryData(theEnv)->QueryCore->soln_size = rcnt;
InstanceQueryData(theEnv)->QueryCore->soln_cnt = 0;
TestEntireChain(theEnv,qclasses,0);
InstanceQueryData(theEnv)->AbortQuery = false;
InstanceQueryData(theEnv)->QueryCore->action = GetFirstArgument()->nextArg;
GCBlockStart(theEnv,&gcb);
for (theSet = InstanceQueryData(theEnv)->QueryCore->soln_set;
theSet != NULL;
theSet = theSet->nxt)
{
for (i = 0; i < rcnt; i++)
{ theSet->soln[i]->busy++; }
}
for (theSet = InstanceQueryData(theEnv)->QueryCore->soln_set;
theSet != NULL; )
{
for (i = 0 ; i < rcnt ; i++)
{
if (theSet->soln[i]->garbage)
{ goto nextSet; }
InstanceQueryData(theEnv)->QueryCore->solns[i] = theSet->soln[i];
}
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->action,returnValue);
if (EvaluationData(theEnv)->HaltExecution || ProcedureFunctionData(theEnv)->BreakFlag || ProcedureFunctionData(theEnv)->ReturnFlag)
{ break; }
CleanCurrentGarbageFrame(theEnv,NULL);
CallPeriodicTasks(theEnv);
nextSet: theSet = theSet->nxt;
}
for (theSet = InstanceQueryData(theEnv)->QueryCore->soln_set;
theSet != NULL;
theSet = theSet->nxt)
{
for (i = 0; i < rcnt; i++)
{ theSet->soln[i]->busy--; }
}
GCBlockEndUDF(theEnv,&gcb,returnValue);
CallPeriodicTasks(theEnv);
while (InstanceQueryData(theEnv)->QueryCore->soln_set != NULL)
{ PopQuerySoln(theEnv); }
ProcedureFunctionData(theEnv)->BreakFlag = false;
rm(theEnv,InstanceQueryData(theEnv)->QueryCore->solns,(sizeof(Instance *) * rcnt));
rtn_struct(theEnv,query_core,InstanceQueryData(theEnv)->QueryCore);
PopQueryCore(theEnv);
DeleteQueryClasses(theEnv,qclasses);
}
static void PushQueryCore(
Environment *theEnv)
{
QUERY_STACK *qptr;
qptr = get_struct(theEnv,query_stack);
qptr->core = InstanceQueryData(theEnv)->QueryCore;
qptr->nxt = InstanceQueryData(theEnv)->QueryCoreStack;
InstanceQueryData(theEnv)->QueryCoreStack = qptr;
}
static void PopQueryCore(
Environment *theEnv)
{
QUERY_STACK *qptr;
InstanceQueryData(theEnv)->QueryCore = InstanceQueryData(theEnv)->QueryCoreStack->core;
qptr = InstanceQueryData(theEnv)->QueryCoreStack;
InstanceQueryData(theEnv)->QueryCoreStack = InstanceQueryData(theEnv)->QueryCoreStack->nxt;
rtn_struct(theEnv,query_stack,qptr);
}
static QUERY_CORE *FindQueryCore(
Environment *theEnv,
long long depth)
{
QUERY_STACK *qptr;
if (depth == 0)
return InstanceQueryData(theEnv)->QueryCore;
qptr = InstanceQueryData(theEnv)->QueryCoreStack;
while (depth > 1)
{
qptr = qptr->nxt;
depth--;
}
return qptr->core;
}
static QUERY_CLASS *DetermineQueryClasses(
Environment *theEnv,
Expression *classExp,
const char *func,
unsigned *rcnt)
{
QUERY_CLASS *clist = NULL,*cnxt = NULL,*cchain = NULL,*tmp;
bool new_list = false;
UDFValue temp;
Defclass *theClass;
*rcnt = 0;
while (classExp != NULL)
{
theClass = NULL;
if (classExp->type == DEFCLASS_PTR)
{
theClass = (Defclass *) classExp->value;
}
else if (EvaluateExpression(theEnv,classExp,&temp))
{
DeleteQueryClasses(theEnv,clist);
return NULL;
}
if ((theClass == NULL) &&
(temp.value == (void *) InstanceQueryData(theEnv)->QUERY_DELIMITER_SYMBOL))
{
new_list = true;
(*rcnt)++;
}
else if ((tmp = FormChain(theEnv,func,theClass,&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,"instance-set query class restrictions");
DeleteQueryClasses(theEnv,clist);
SetEvaluationError(theEnv,true);
return NULL;
}
classExp = classExp->nextArg;
}
return(clist);
}
static QUERY_CLASS *FormChain(
Environment *theEnv,
const char *func,
Defclass *theClass,
UDFValue *val)
{
Defclass *cls;
QUERY_CLASS *head,*bot,*tmp;
size_t i;
const char *className;
Defmodule *currentModule;
currentModule = GetCurrentModule(theEnv);
if (theClass != NULL)
{
IncrementDefclassBusyCount(theEnv,theClass);
head = get_struct(theEnv,query_class);
head->cls = theClass;
if (DefclassInScope(theEnv,head->cls,currentModule))
head->theModule = currentModule;
else
head->theModule = head->cls->header.whichModule->theModule;
head->chain = NULL;
head->nxt = NULL;
return(head);
}
if (val->header->type == SYMBOL_TYPE)
{
cls = LookupDefclassByMdlOrScope(theEnv,val->lexemeValue->contents);
if (cls == NULL)
{
ClassExistError(theEnv,func,val->lexemeValue->contents);
return NULL;
}
IncrementDefclassBusyCount(theEnv,(Defclass *) cls);
head = get_struct(theEnv,query_class);
head->cls = cls;
if (DefclassInScope(theEnv,head->cls,currentModule))
head->theModule = currentModule;
else
head->theModule = head->cls->header.whichModule->theModule;
head->chain = NULL;
head->nxt = NULL;
return(head);
}
if (val->header->type == MULTIFIELD_TYPE)
{
head = bot = NULL;
for (i = val->begin ; i < (val->begin + val->range) ; i++)
{
if (val->multifieldValue->contents[i].header->type == SYMBOL_TYPE)
{
className = val->multifieldValue->contents[i].lexemeValue->contents;
cls = LookupDefclassByMdlOrScope(theEnv,className);
if (cls == NULL)
{
ClassExistError(theEnv,func,className);
DeleteQueryClasses(theEnv,head);
return NULL;
}
}
else
{
DeleteQueryClasses(theEnv,head);
return NULL;
}
IncrementDefclassBusyCount(theEnv,(Defclass *) cls);
tmp = get_struct(theEnv,query_class);
tmp->cls = cls;
if (DefclassInScope(theEnv,tmp->cls,currentModule))
tmp->theModule = currentModule;
else
tmp->theModule = tmp->cls->header.whichModule->theModule;
tmp->chain = NULL;
tmp->nxt = NULL;
if (head == NULL)
head = tmp;
else
bot->chain = tmp;
bot = tmp;
}
return(head);
}
return NULL;
}
static void DeleteQueryClasses(
Environment *theEnv,
QUERY_CLASS *qlist)
{
QUERY_CLASS *tmp;
while (qlist != NULL)
{
while (qlist->chain != NULL)
{
tmp = qlist->chain;
qlist->chain = qlist->chain->chain;
DecrementDefclassBusyCount(theEnv,(Defclass *) tmp->cls);
rtn_struct(theEnv,query_class,tmp);
}
tmp = qlist;
qlist = qlist->nxt;
DecrementDefclassBusyCount(theEnv,(Defclass *) tmp->cls);
rtn_struct(theEnv,query_class,tmp);
}
}
static bool TestForFirstInChain(
Environment *theEnv,
QUERY_CLASS *qchain,
unsigned indx)
{
QUERY_CLASS *qptr;
int id;
InstanceQueryData(theEnv)->AbortQuery = true;
for (qptr = qchain ; qptr != NULL ; qptr = qptr->chain)
{
InstanceQueryData(theEnv)->AbortQuery = false;
if ((id = GetTraversalID(theEnv)) == -1)
return false;
if (TestForFirstInstanceInClass(theEnv,qptr->theModule,id,qptr->cls,qchain,indx))
{
ReleaseTraversalID(theEnv);
return true;
}
ReleaseTraversalID(theEnv);
if ((EvaluationData(theEnv)->HaltExecution == true) || (InstanceQueryData(theEnv)->AbortQuery == true))
return false;
}
return false;
}
static bool TestForFirstInstanceInClass(
Environment *theEnv,
Defmodule *theModule,
int id,
Defclass *cls,
QUERY_CLASS *qchain,
unsigned indx)
{
unsigned long i;
Instance *ins;
UDFValue temp;
GCBlock gcb;
unsigned j;
if (TestTraversalID(cls->traversalRecord,id))
return false;
SetTraversalID(cls->traversalRecord,id);
if (DefclassInScope(theEnv,cls,theModule) == false)
return false;
GCBlockStart(theEnv,&gcb);
ins = cls->instanceList;
while (ins != NULL)
{
InstanceQueryData(theEnv)->QueryCore->solns[indx] = ins;
if (qchain->nxt != NULL)
{
ins->busy++;
if (TestForFirstInChain(theEnv,qchain->nxt,indx+1) == true)
{
ins->busy--;
break;
}
ins->busy--;
if ((EvaluationData(theEnv)->HaltExecution == true) || (InstanceQueryData(theEnv)->AbortQuery == true))
break;
}
else
{
for (j = 0; j < indx; j++)
{
if (InstanceQueryData(theEnv)->QueryCore->solns[j]->garbage)
{
ins = NULL;
goto endTest;
}
}
ins->busy++;
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->query,&temp);
ins->busy--;
if (EvaluationData(theEnv)->HaltExecution == true)
break;
if (temp.value != FalseSymbol(theEnv))
break;
}
CleanCurrentGarbageFrame(theEnv,NULL);
CallPeriodicTasks(theEnv);
ins = ins->nxtClass;
while ((ins != NULL) ? (ins->garbage == 1) : false)
ins = ins->nxtClass;
}
endTest:
GCBlockEnd(theEnv,&gcb);
CallPeriodicTasks(theEnv);
if (ins != NULL)
return(((EvaluationData(theEnv)->HaltExecution == true) || (InstanceQueryData(theEnv)->AbortQuery == true))
? false : true);
for (i = 0 ; i < cls->directSubclasses.classCount ; i++)
{
if (TestForFirstInstanceInClass(theEnv,theModule,id,cls->directSubclasses.classArray[i],
qchain,indx))
return true;
if ((EvaluationData(theEnv)->HaltExecution == true) || (InstanceQueryData(theEnv)->AbortQuery == true))
return false;
}
return false;
}
static void TestEntireChain(
Environment *theEnv,
QUERY_CLASS *qchain,
unsigned indx)
{
QUERY_CLASS *qptr;
int id;
InstanceQueryData(theEnv)->AbortQuery = true;
for (qptr = qchain ; qptr != NULL ; qptr = qptr->chain)
{
InstanceQueryData(theEnv)->AbortQuery = false;
if ((id = GetTraversalID(theEnv)) == -1)
return;
TestEntireClass(theEnv,qptr->theModule,id,qptr->cls,qchain,indx);
ReleaseTraversalID(theEnv);
if ((EvaluationData(theEnv)->HaltExecution == true) || (InstanceQueryData(theEnv)->AbortQuery == true))
return;
}
}
static void TestEntireClass(
Environment *theEnv,
Defmodule *theModule,
int id,
Defclass *cls,
QUERY_CLASS *qchain,
unsigned indx)
{
unsigned long i;
Instance *ins;
UDFValue temp;
GCBlock gcb;
unsigned j;
if (TestTraversalID(cls->traversalRecord,id))
return;
SetTraversalID(cls->traversalRecord,id);
if (DefclassInScope(theEnv,cls,theModule) == false)
return;
GCBlockStart(theEnv,&gcb);
ins = cls->instanceList;
while (ins != NULL)
{
InstanceQueryData(theEnv)->QueryCore->solns[indx] = ins;
if (qchain->nxt != NULL)
{
ins->busy++;
TestEntireChain(theEnv,qchain->nxt,indx+1);
ins->busy--;
if ((EvaluationData(theEnv)->HaltExecution == true) || (InstanceQueryData(theEnv)->AbortQuery == true))
break;
}
else
{
for (j = 0; j < indx; j++)
{
if (InstanceQueryData(theEnv)->QueryCore->solns[j]->garbage)
{ goto endTest; }
}
ins->busy++;
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->query,&temp);
ins->busy--;
if (EvaluationData(theEnv)->HaltExecution == true)
break;
if (temp.value != FalseSymbol(theEnv))
{
if (InstanceQueryData(theEnv)->QueryCore->action != NULL)
{
ins->busy++;
ReleaseUDFV(theEnv,InstanceQueryData(theEnv)->QueryCore->result);
EvaluateExpression(theEnv,InstanceQueryData(theEnv)->QueryCore->action,InstanceQueryData(theEnv)->QueryCore->result);
RetainUDFV(theEnv,InstanceQueryData(theEnv)->QueryCore->result);
ins->busy--;
if (ProcedureFunctionData(theEnv)->BreakFlag || ProcedureFunctionData(theEnv)->ReturnFlag)
{
InstanceQueryData(theEnv)->AbortQuery = true;
break;
}
if (EvaluationData(theEnv)->HaltExecution == true)
break;
}
else
AddSolution(theEnv);
}
}
ins = ins->nxtClass;
while ((ins != NULL) ? (ins->garbage == 1) : false)
ins = ins->nxtClass;
CleanCurrentGarbageFrame(theEnv,NULL);
CallPeriodicTasks(theEnv);
}
endTest:
GCBlockEnd(theEnv,&gcb);
CallPeriodicTasks(theEnv);
if (ins != NULL)
return;
for (i = 0 ; i < cls->directSubclasses.classCount ; i++)
{
TestEntireClass(theEnv,theModule,id,cls->directSubclasses.classArray[i],qchain,indx);
if ((EvaluationData(theEnv)->HaltExecution == true) || (InstanceQueryData(theEnv)->AbortQuery == true))
return;
}
}
static void AddSolution(
Environment *theEnv)
{
QUERY_SOLN *new_soln;
unsigned i;
new_soln = (QUERY_SOLN *) gm2(theEnv,sizeof(QUERY_SOLN));
new_soln->soln = (Instance **)
gm2(theEnv,(sizeof(Instance *) * (InstanceQueryData(theEnv)->QueryCore->soln_size)));
for (i = 0 ; i < InstanceQueryData(theEnv)->QueryCore->soln_size ; i++)
new_soln->soln[i] = InstanceQueryData(theEnv)->QueryCore->solns[i];
new_soln->nxt = NULL;
if (InstanceQueryData(theEnv)->QueryCore->soln_set == NULL)
InstanceQueryData(theEnv)->QueryCore->soln_set = new_soln;
else
InstanceQueryData(theEnv)->QueryCore->soln_bottom->nxt = new_soln;
InstanceQueryData(theEnv)->QueryCore->soln_bottom = new_soln;
InstanceQueryData(theEnv)->QueryCore->soln_cnt++;
}
static void PopQuerySoln(
Environment *theEnv)
{
InstanceQueryData(theEnv)->QueryCore->soln_bottom = InstanceQueryData(theEnv)->QueryCore->soln_set;
InstanceQueryData(theEnv)->QueryCore->soln_set = InstanceQueryData(theEnv)->QueryCore->soln_set->nxt;
rm(theEnv,InstanceQueryData(theEnv)->QueryCore->soln_bottom->soln,
(sizeof(Instance *) * InstanceQueryData(theEnv)->QueryCore->soln_size));
rm(theEnv,InstanceQueryData(theEnv)->QueryCore->soln_bottom,sizeof(QUERY_SOLN));
}
#endif