#include "setup.h"
#if DEFGENERIC_CONSTRUCT
#include <string.h>
#include "argacces.h"
#if BLOAD || BLOAD_AND_BSAVE
#include "bload.h"
#endif
#if OBJECT_SYSTEM
#include "classcom.h"
#include "inscom.h"
#endif
#include "constrct.h"
#include "cstrccom.h"
#include "cstrcpsr.h"
#include "envrnmnt.h"
#include "evaluatn.h"
#include "extnfunc.h"
#if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE
#include "genrcbin.h"
#endif
#if CONSTRUCT_COMPILER
#include "genrccmp.h"
#endif
#include "genrcexe.h"
#if (! BLOAD_ONLY) && (! RUN_TIME)
#include "genrcpsr.h"
#endif
#include "memalloc.h"
#include "modulpsr.h"
#include "modulutl.h"
#include "multifld.h"
#include "router.h"
#include "strngrtr.h"
#if DEBUGGING_FUNCTIONS
#include "watch.h"
#endif
#include "prntutil.h"
#include "genrccom.h"
static void PrintGenericCall(Environment *,const char *,Defgeneric *);
static bool EvaluateGenericCall(Environment *,Defgeneric *,UDFValue *);
static void DecrementGenericBusyCount(Environment *,Defgeneric *);
static void IncrementGenericBusyCount(Environment *,Defgeneric *);
static void DeallocateDefgenericData(Environment *);
#if ! RUN_TIME
static void DestroyDefgenericAction(Environment *,ConstructHeader *,void *);
#endif
#if (! BLOAD_ONLY) && (! RUN_TIME)
static void SaveDefgenerics(Environment *,Defmodule *,const char *,void *);
static void SaveDefmethods(Environment *,Defmodule *,const char *,void *);
static void SaveDefmethodsForDefgeneric(Environment *,ConstructHeader *,void *);
static void RemoveDefgenericMethod(Environment *,Defgeneric *,unsigned short);
#endif
#if DEBUGGING_FUNCTIONS
static unsigned short ListMethodsForGeneric(Environment *,const char *,Defgeneric *);
static bool DefgenericWatchAccess(Environment *,int,bool,Expression *);
static bool DefgenericWatchPrint(Environment *,const char *,int,Expression *);
static bool DefmethodWatchAccess(Environment *,int,bool,Expression *);
static bool DefmethodWatchPrint(Environment *,const char *,int,Expression *);
static bool DefmethodWatchSupport(Environment *,const char *,const char *,bool,
void (*)(Environment *,const char *,Defgeneric *,unsigned short),
void (*)(Defgeneric *,unsigned short,bool),
Expression *);
static void PrintMethodWatchFlag(Environment *,const char *,Defgeneric *,unsigned short);
#endif
void SetupGenericFunctions(
Environment *theEnv)
{
EntityRecord genericEntityRecord =
{ "GCALL", GCALL,0,0,1,
(EntityPrintFunction *) PrintGenericCall,
(EntityPrintFunction *) PrintGenericCall,
NULL,
(EntityEvaluationFunction *) EvaluateGenericCall,
NULL,
(EntityBusyCountFunction *) DecrementGenericBusyCount,
(EntityBusyCountFunction *) IncrementGenericBusyCount,
NULL,NULL,NULL,NULL,NULL };
AllocateEnvironmentData(theEnv,DEFGENERIC_DATA,sizeof(struct defgenericData),DeallocateDefgenericData);
memcpy(&DefgenericData(theEnv)->GenericEntityRecord,&genericEntityRecord,sizeof(struct entityRecord));
InstallPrimitive(theEnv,&DefgenericData(theEnv)->GenericEntityRecord,GCALL);
DefgenericData(theEnv)->DefgenericModuleIndex =
RegisterModuleItem(theEnv,"defgeneric",
#if (! RUN_TIME)
AllocateDefgenericModule,
FreeDefgenericModule,
#else
NULL,NULL,
#endif
#if BLOAD_AND_BSAVE || BLOAD || BLOAD_ONLY
BloadDefgenericModuleReference,
#else
NULL,
#endif
#if CONSTRUCT_COMPILER && (! RUN_TIME)
DefgenericCModuleReference,
#else
NULL,
#endif
(FindConstructFunction *) FindDefgenericInModule);
DefgenericData(theEnv)->DefgenericConstruct = AddConstruct(theEnv,"defgeneric","defgenerics",
#if (! BLOAD_ONLY) && (! RUN_TIME)
ParseDefgeneric,
#else
NULL,
#endif
(FindConstructFunction *) FindDefgeneric,
GetConstructNamePointer,GetConstructPPForm,
GetConstructModuleItem,
(GetNextConstructFunction *) GetNextDefgeneric,
SetNextConstruct,
(IsConstructDeletableFunction *) DefgenericIsDeletable,
(DeleteConstructFunction *) Undefgeneric,
#if (! BLOAD_ONLY) && (! RUN_TIME)
(FreeConstructFunction *) RemoveDefgeneric
#else
NULL
#endif
);
#if ! RUN_TIME
AddClearReadyFunction(theEnv,"defgeneric",ClearDefgenericsReady,0,NULL);
#if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE
SetupGenericsBload(theEnv);
#endif
#if CONSTRUCT_COMPILER
SetupGenericsCompiler(theEnv);
#endif
#if ! BLOAD_ONLY
#if DEFMODULE_CONSTRUCT
AddPortConstructItem(theEnv,"defgeneric",SYMBOL_TOKEN);
#endif
AddConstruct(theEnv,"defmethod","defmethods",ParseDefmethod,
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
AddSaveFunction(theEnv,"defgeneric",SaveDefgenerics,1000,NULL);
AddSaveFunction(theEnv,"defmethod",SaveDefmethods,-1000,NULL);
AddUDF(theEnv,"undefgeneric","v",1,1,"y",UndefgenericCommand,"UndefgenericCommand",NULL);
AddUDF(theEnv,"undefmethod","v",2,2,"*;y;ly",UndefmethodCommand,"UndefmethodCommand",NULL);
#endif
AddUDF(theEnv,"call-next-method","*",0,0,NULL,CallNextMethod,"CallNextMethod",NULL);
FuncSeqOvlFlags(theEnv,"call-next-method",true,false);
AddUDF(theEnv,"call-specific-method","*",2,UNBOUNDED,"*;y;l",CallSpecificMethod,"CallSpecificMethod",NULL);
FuncSeqOvlFlags(theEnv,"call-specific-method",true,false);
AddUDF(theEnv,"override-next-method","*",0,UNBOUNDED,NULL,OverrideNextMethod,"OverrideNextMethod",NULL);
FuncSeqOvlFlags(theEnv,"override-next-method",true,false);
AddUDF(theEnv,"next-methodp","b",0,0,NULL,NextMethodPCommand,"NextMethodPCommand",NULL);
FuncSeqOvlFlags(theEnv,"next-methodp",true,false);
AddUDF(theEnv,"(gnrc-current-arg)","*",0,UNBOUNDED,NULL,GetGenericCurrentArgument,"GetGenericCurrentArgument",NULL);
#if DEBUGGING_FUNCTIONS
AddUDF(theEnv,"ppdefgeneric","vs",1,2,";y;ldsyn",PPDefgenericCommand,"PPDefgenericCommand",NULL);
AddUDF(theEnv,"list-defgenerics","v",0,1,"y",ListDefgenericsCommand,"ListDefgenericsCommand",NULL);
AddUDF(theEnv,"ppdefmethod","v",2,3,"*;y;l;ldsyn",PPDefmethodCommand,"PPDefmethodCommand",NULL);
AddUDF(theEnv,"list-defmethods","v",0,1,"y",ListDefmethodsCommand,"ListDefmethodsCommand",NULL);
AddUDF(theEnv,"preview-generic","v",1,UNBOUNDED,"*;y",PreviewGeneric,"PreviewGeneric",NULL);
#endif
AddUDF(theEnv,"get-defgeneric-list","m",0,1,"y",GetDefgenericListFunction,"GetDefgenericListFunction",NULL);
AddUDF(theEnv,"get-defmethod-list","m",0,1,"y",GetDefmethodListCommand,"GetDefmethodListCommand",NULL);
AddUDF(theEnv,"get-method-restrictions","m",2,2,"l;y",GetMethodRestrictionsCommand,"GetMethodRestrictionsCommand",NULL);
AddUDF(theEnv,"defgeneric-module","y",1,1,"y",GetDefgenericModuleCommand,"GetDefgenericModuleCommand",NULL);
#if OBJECT_SYSTEM
AddUDF(theEnv,"type","*",1,1,"*",ClassCommand,"ClassCommand",NULL);
#else
AddUDF(theEnv,"type","*",1,1,"*",TypeCommand,"TypeCommand",NULL);
#endif
#endif
#if DEBUGGING_FUNCTIONS
AddWatchItem(theEnv,"generic-functions",0,&DefgenericData(theEnv)->WatchGenerics,34,
DefgenericWatchAccess,DefgenericWatchPrint);
AddWatchItem(theEnv,"methods",0,&DefgenericData(theEnv)->WatchMethods,33,
DefmethodWatchAccess,DefmethodWatchPrint);
#endif
}
static void DeallocateDefgenericData(
Environment *theEnv)
{
#if ! RUN_TIME
struct defgenericModule *theModuleItem;
Defmodule *theModule;
#if BLOAD || BLOAD_AND_BSAVE
if (Bloaded(theEnv)) return;
#endif
DoForAllConstructs(theEnv,
DestroyDefgenericAction,
DefgenericData(theEnv)->DefgenericModuleIndex,false,NULL);
for (theModule = GetNextDefmodule(theEnv,NULL);
theModule != NULL;
theModule = GetNextDefmodule(theEnv,theModule))
{
theModuleItem = (struct defgenericModule *)
GetModuleItem(theEnv,theModule,
DefgenericData(theEnv)->DefgenericModuleIndex);
rtn_struct(theEnv,defgenericModule,theModuleItem);
}
#else
#if MAC_XCD
#pragma unused(theEnv)
#endif
#endif
}
#if ! RUN_TIME
static void DestroyDefgenericAction(
Environment *theEnv,
ConstructHeader *theConstruct,
void *buffer)
{
#if MAC_XCD
#pragma unused(buffer)
#endif
#if (! BLOAD_ONLY) && (! RUN_TIME)
Defgeneric *theDefgeneric = (Defgeneric *) theConstruct;
long i;
if (theDefgeneric == NULL) return;
for (i = 0 ; i < theDefgeneric->mcnt ; i++)
{ DestroyMethodInfo(theEnv,theDefgeneric,&theDefgeneric->methods[i]); }
if (theDefgeneric->mcnt != 0)
{ rm(theEnv,theDefgeneric->methods,(sizeof(Defmethod) * theDefgeneric->mcnt)); }
DestroyConstructHeader(theEnv,&theDefgeneric->header);
rtn_struct(theEnv,defgeneric,theDefgeneric);
#else
#if MAC_XCD
#pragma unused(theEnv,theConstruct)
#endif
#endif
}
#endif
Defgeneric *FindDefgeneric(
Environment *theEnv,
const char *genericModuleAndName)
{
return (Defgeneric *) FindNamedConstructInModuleOrImports(theEnv,genericModuleAndName,DefgenericData(theEnv)->DefgenericConstruct);
}
Defgeneric *FindDefgenericInModule(
Environment *theEnv,
const char *genericModuleAndName)
{
return (Defgeneric *) FindNamedConstructInModule(theEnv,genericModuleAndName,DefgenericData(theEnv)->DefgenericConstruct);
}
Defgeneric *LookupDefgenericByMdlOrScope(
Environment *theEnv,
const char *defgenericName)
{
return (Defgeneric *) LookupConstruct(theEnv,DefgenericData(theEnv)->DefgenericConstruct,defgenericName,true);
}
Defgeneric *LookupDefgenericInScope(
Environment *theEnv,
const char *defgenericName)
{
return (Defgeneric *) LookupConstruct(theEnv,DefgenericData(theEnv)->DefgenericConstruct,defgenericName,false);
}
Defgeneric *GetNextDefgeneric(
Environment *theEnv,
Defgeneric *theDefgeneric)
{
return (Defgeneric *) GetNextConstructItem(theEnv,&theDefgeneric->header,DefgenericData(theEnv)->DefgenericModuleIndex);
}
unsigned short GetNextDefmethod(
Defgeneric *theDefgeneric,
unsigned short theIndex)
{
unsigned short mi;
if (theIndex == 0)
{
if (theDefgeneric->methods != NULL)
{ return theDefgeneric->methods[0].index; }
return 0;
}
mi = FindMethodByIndex(theDefgeneric,theIndex);
if ((mi+1) == theDefgeneric->mcnt)
{ return 0; }
return theDefgeneric->methods[mi+1].index;
}
Defmethod *GetDefmethodPointer(
Defgeneric *theDefgeneric,
long theIndex)
{
return &theDefgeneric->methods[theIndex-1];
}
bool DefgenericIsDeletable(
Defgeneric *theDefgeneric)
{
Environment *theEnv = theDefgeneric->header.env;
if (! ConstructsDeletable(theEnv))
{ return false; }
return (theDefgeneric->busy == 0) ? true : false;
}
bool DefmethodIsDeletable(
Defgeneric *theDefgeneric,
unsigned short theIndex)
{
Environment *theEnv = theDefgeneric->header.env;
unsigned short mi;
if (! ConstructsDeletable(theEnv))
{ return false; }
mi = FindMethodByIndex(theDefgeneric,theIndex);
if (mi == METHOD_NOT_FOUND) return false;
if (theDefgeneric->methods[mi].system)
return false;
#if (! BLOAD_ONLY) && (! RUN_TIME)
return (MethodsExecuting(theDefgeneric) == false) ? true : false;
#else
return false;
#endif
}
void UndefgenericCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UndefconstructCommand(context,"undefgeneric",DefgenericData(theEnv)->DefgenericConstruct);
}
void GetDefgenericModuleCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
returnValue->value = GetConstructModuleCommand(context,"defgeneric-module",DefgenericData(theEnv)->DefgenericConstruct);
}
void UndefmethodCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UDFValue theArg;
Defgeneric *gfunc;
unsigned short mi;
if (! UDFFirstArgument(context,SYMBOL_BIT,&theArg)) return;
gfunc = LookupDefgenericByMdlOrScope(theEnv,theArg.lexemeValue->contents);
if ((gfunc == NULL) ? (strcmp(theArg.lexemeValue->contents,"*") != 0) : false)
{
PrintErrorID(theEnv,"GENRCCOM",1,false);
WriteString(theEnv,STDERR,"No such generic function '");
WriteString(theEnv,STDERR,theArg.lexemeValue->contents);
WriteString(theEnv,STDERR,"' in function undefmethod.\n");
return;
}
if (! UDFNextArgument(context,ANY_TYPE_BITS,&theArg)) return;
if (CVIsType(&theArg,SYMBOL_BIT))
{
if (strcmp(theArg.lexemeValue->contents,"*") != 0)
{
PrintErrorID(theEnv,"GENRCCOM",2,false);
WriteString(theEnv,STDERR,"Expected a valid method index in function undefmethod.\n");
return;
}
mi = 0;
}
else if (CVIsType(&theArg,INTEGER_BIT))
{
mi = (unsigned short) theArg.integerValue->contents;
if (mi == 0)
{
PrintErrorID(theEnv,"GENRCCOM",2,false);
WriteString(theEnv,STDERR,"Expected a valid method index in function undefmethod.\n");
return;
}
}
else
{
PrintErrorID(theEnv,"GENRCCOM",2,false);
WriteString(theEnv,STDERR,"Expected a valid method index in function undefmethod.\n");
return;
}
Undefmethod(gfunc,mi,theEnv);
}
bool Undefgeneric(
Defgeneric *theDefgeneric,
Environment *allEnv)
{
#if RUN_TIME || BLOAD_ONLY
return false;
#else
Environment *theEnv;
bool success = true;
GCBlock gcb;
if (theDefgeneric == NULL)
{ theEnv = allEnv; }
else
{ theEnv = theDefgeneric->header.env; }
GCBlockStart(theEnv,&gcb);
if (theDefgeneric == NULL)
{
if (ClearDefmethods(theEnv) == false)
success = false;
if (ClearDefgenerics(theEnv) == false)
success = false;
GCBlockEnd(theEnv,&gcb);
return success ;
}
if (DefgenericIsDeletable(theDefgeneric) == false)
{
GCBlockEnd(theEnv,&gcb);
return false;
}
RemoveConstructFromModule(theEnv,&theDefgeneric->header);
RemoveDefgeneric(theEnv,theDefgeneric);
GCBlockEnd(theEnv,&gcb);
return true;
#endif
}
bool Undefmethod(
Defgeneric *theDefgeneric,
unsigned short mi,
Environment *allEnv)
{
Environment *theEnv;
#if (! RUN_TIME) && (! BLOAD_ONLY)
GCBlock gcb;
#endif
if (theDefgeneric == NULL)
{ theEnv = allEnv; }
else
{ theEnv = theDefgeneric->header.env; }
#if RUN_TIME || BLOAD_ONLY
PrintErrorID(theEnv,"PRNTUTIL",4,false);
WriteString(theEnv,STDERR,"Unable to delete method ");
if (theDefgeneric != NULL)
{
WriteString(theEnv,STDERR,"'");
PrintGenericName(theEnv,STDERR,theDefgeneric);
WriteString(theEnv,STDERR,"'");
WriteString(theEnv,STDERR," #");
PrintUnsignedInteger(theEnv,STDERR,mi);
}
else
WriteString(theEnv,STDERR,"*");
WriteString(theEnv,STDERR,".\n");
return false;
#else
#if BLOAD || BLOAD_AND_BSAVE
if (Bloaded(theEnv) == true)
{
PrintErrorID(theEnv,"PRNTUTIL",4,false);
WriteString(theEnv,STDERR,"Unable to delete method ");
if (theDefgeneric != NULL)
{
WriteString(theEnv,STDERR,"'");
WriteString(theEnv,STDERR,DefgenericName(theDefgeneric));
WriteString(theEnv,STDERR,"'");
WriteString(theEnv,STDERR," #");
PrintUnsignedInteger(theEnv,STDERR,mi);
}
else
WriteString(theEnv,STDERR,"*");
WriteString(theEnv,STDERR,".\n");
return false;
}
#endif
GCBlockStart(theEnv,&gcb);
if (theDefgeneric == NULL)
{
bool success;
if (mi != 0)
{
PrintErrorID(theEnv,"GENRCCOM",3,false);
WriteString(theEnv,STDERR,"Incomplete method specification for deletion.\n");
GCBlockEnd(theEnv,&gcb);
return false;
}
success = ClearDefmethods(theEnv);
GCBlockEnd(theEnv,&gcb);
return success;
}
if (MethodsExecuting(theDefgeneric))
{
MethodAlterError(theEnv,theDefgeneric);
GCBlockEnd(theEnv,&gcb);
return false;
}
if (mi == 0)
{ RemoveAllExplicitMethods(theEnv,theDefgeneric); }
else
{
unsigned short nmi = CheckMethodExists(theEnv,"undefmethod",theDefgeneric,mi);
if (nmi == METHOD_NOT_FOUND)
{
GCBlockEnd(theEnv,&gcb);
return false;
}
RemoveDefgenericMethod(theEnv,theDefgeneric,nmi);
}
GCBlockEnd(theEnv,&gcb);
return true;
#endif
}
#if DEBUGGING_FUNCTIONS || PROFILING_FUNCTIONS
void DefmethodDescription(
Defgeneric *theDefgeneric,
unsigned short theIndex,
StringBuilder *theSB)
{
long mi;
Environment *theEnv = theDefgeneric->header.env;
mi = FindMethodByIndex(theDefgeneric,theIndex);
OpenStringBuilderDestination(theEnv,"MethodDescription",theSB);
if (mi != METHOD_NOT_FOUND)
{ PrintMethod(theEnv,&theDefgeneric->methods[mi],theSB); }
CloseStringBuilderDestination(theEnv,"MethodDescription");
}
#endif
#if DEBUGGING_FUNCTIONS
bool DefgenericGetWatch(
Defgeneric *theGeneric)
{
return theGeneric->trace;
}
void DefgenericSetWatch(
Defgeneric *theGeneric,
bool newState)
{
theGeneric->trace = newState;
}
bool DefmethodGetWatch(
Defgeneric *theGeneric,
unsigned short theIndex)
{
unsigned short mi;
mi = FindMethodByIndex(theGeneric,theIndex);
if (mi != METHOD_NOT_FOUND)
{ return theGeneric->methods[mi].trace; }
return false;
}
void DefmethodSetWatch(
Defgeneric *theGeneric,
unsigned short theIndex,
bool newState)
{
unsigned short mi;
mi = FindMethodByIndex(theGeneric,theIndex);
if (mi != METHOD_NOT_FOUND)
{ theGeneric->methods[mi].trace = newState; }
}
void PPDefgenericCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
PPConstructCommand(context,"ppdefgeneric",DefgenericData(theEnv)->DefgenericConstruct,returnValue);
}
void PPDefmethodCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UDFValue theArg;
const char *gname;
const char *logicalName;
Defgeneric *gfunc;
unsigned short gi;
if (! UDFFirstArgument(context,SYMBOL_BIT,&theArg)) return;
gname = theArg.lexemeValue->contents;
if (! UDFNextArgument(context,INTEGER_BIT,&theArg)) return;
if (UDFHasNextArgument(context))
{
logicalName = GetLogicalName(context,STDOUT);
if (logicalName == NULL)
{
IllegalLogicalNameMessage(theEnv,"ppdefmethod");
SetHaltExecution(theEnv,true);
SetEvaluationError(theEnv,true);
return;
}
}
else
{ logicalName = STDOUT; }
gfunc = CheckGenericExists(theEnv,"ppdefmethod",gname);
if (gfunc == NULL)
return;
gi = CheckMethodExists(theEnv,"ppdefmethod",gfunc,(unsigned short) theArg.integerValue->contents);
if (gi == METHOD_NOT_FOUND)
return;
if (strcmp(logicalName,"nil") == 0)
{
if (gfunc->methods[gi].header.ppForm != NULL)
{ returnValue->lexemeValue = CreateString(theEnv,gfunc->methods[gi].header.ppForm); }
else
{ returnValue->lexemeValue = CreateString(theEnv,""); }
}
else
{
if (gfunc->methods[gi].header.ppForm != NULL)
WriteString(theEnv,logicalName,gfunc->methods[gi].header.ppForm);
}
}
void ListDefmethodsCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UDFValue theArg;
Defgeneric *gfunc;
if (! UDFHasNextArgument(context))
{ ListDefmethods(theEnv,STDOUT,NULL); }
else
{
if (! UDFFirstArgument(context,SYMBOL_BIT,&theArg)) return;
gfunc = CheckGenericExists(theEnv,"list-defmethods",theArg.lexemeValue->contents);
if (gfunc != NULL)
{ ListDefmethods(theEnv,STDOUT,gfunc); }
}
}
const char *DefmethodPPForm(
Defgeneric *theDefgeneric,
unsigned short theIndex)
{
unsigned short mi;
mi = FindMethodByIndex(theDefgeneric,theIndex);
if (mi != METHOD_NOT_FOUND)
{ return theDefgeneric->methods[mi].header.ppForm; }
return "";
}
void ListDefgenericsCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
ListConstructCommand(context,DefgenericData(theEnv)->DefgenericConstruct);
}
void ListDefgenerics(
Environment *theEnv,
const char *logicalName,
Defmodule *theModule)
{
ListConstruct(theEnv,DefgenericData(theEnv)->DefgenericConstruct,logicalName,theModule);
}
void ListDefmethods(
Environment *theEnv,
const char *logicalName,
Defgeneric *theDefgeneric)
{
Defgeneric *gfunc;
unsigned long count;
if (theDefgeneric != NULL)
count = ListMethodsForGeneric(theEnv,logicalName,theDefgeneric);
else
{
count = 0;
for (gfunc = GetNextDefgeneric(theEnv,NULL) ;
gfunc != NULL ;
gfunc = GetNextDefgeneric(theEnv,gfunc))
{
count += ListMethodsForGeneric(theEnv,logicalName,gfunc);
if (GetNextDefgeneric(theEnv,gfunc) != NULL)
WriteString(theEnv,logicalName,"\n");
}
}
PrintTally(theEnv,logicalName,count,"method","methods");
}
#endif
void GetDefgenericListFunction(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
GetConstructListFunction(context,returnValue,DefgenericData(theEnv)->DefgenericConstruct);
}
void GetDefgenericList(
Environment *theEnv,
CLIPSValue *returnValue,
Defmodule *theModule)
{
UDFValue result;
GetConstructList(theEnv,&result,DefgenericData(theEnv)->DefgenericConstruct,theModule);
NormalizeMultifield(theEnv,&result);
returnValue->value = result.value;
}
void GetDefmethodListCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UDFValue theArg;
Defgeneric *gfunc;
CLIPSValue result;
if (! UDFHasNextArgument(context))
{
GetDefmethodList(theEnv,&result,NULL);
CLIPSToUDFValue(&result,returnValue);
}
else
{
if (! UDFFirstArgument(context,SYMBOL_BIT,&theArg))
{ return; }
gfunc = CheckGenericExists(theEnv,"get-defmethod-list",theArg.lexemeValue->contents);
if (gfunc != NULL)
{
GetDefmethodList(theEnv,&result,gfunc);
CLIPSToUDFValue(&result,returnValue);
}
else
{ SetMultifieldErrorValue(theEnv,returnValue); }
}
}
void GetDefmethodList(
Environment *theEnv,
CLIPSValue *returnValue,
Defgeneric *theDefgeneric)
{
Defgeneric *gfunc, *svg, *svnxt;
long i,j;
unsigned long count;
Multifield *theList;
if (theDefgeneric != NULL)
{
gfunc = theDefgeneric;
svnxt = GetNextDefgeneric(theEnv,theDefgeneric);
SetNextDefgeneric(theDefgeneric,NULL);
}
else
{
gfunc = GetNextDefgeneric(theEnv,NULL);
svnxt = (gfunc != NULL) ? GetNextDefgeneric(theEnv,gfunc) : NULL;
}
count = 0;
for (svg = gfunc ;
gfunc != NULL ;
gfunc = GetNextDefgeneric(theEnv,gfunc))
count += gfunc->mcnt;
count *= 2;
theList = CreateMultifield(theEnv,count);
returnValue->value = theList;
for (gfunc = svg , i = 0 ;
gfunc != NULL ;
gfunc = GetNextDefgeneric(theEnv,gfunc))
{
for (j = 0 ; j < gfunc->mcnt ; j++)
{
theList->contents[i++].value = GetDefgenericNamePointer(gfunc);
theList->contents[i++].integerValue = CreateInteger(theEnv,(long long) gfunc->methods[j].index);
}
}
if (svg != NULL)
SetNextDefgeneric(svg,svnxt);
}
void GetMethodRestrictionsCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UDFValue theArg;
Defgeneric *gfunc;
CLIPSValue result;
unsigned short mi;
if (! UDFFirstArgument(context,SYMBOL_BIT,&theArg))
{ return; }
gfunc = CheckGenericExists(theEnv,"get-method-restrictions",theArg.lexemeValue->contents);
if (gfunc == NULL)
{
SetMultifieldErrorValue(theEnv,returnValue);
return;
}
if (! UDFNextArgument(context,INTEGER_BIT,&theArg))
{ return; }
mi = (unsigned short) theArg.integerValue->contents;
if (CheckMethodExists(theEnv,"get-method-restrictions",gfunc,mi) == METHOD_NOT_FOUND)
{
SetMultifieldErrorValue(theEnv,returnValue);
return;
}
GetMethodRestrictions(gfunc,mi,&result);
CLIPSToUDFValue(&result,returnValue);
}
void GetMethodRestrictions(
Defgeneric *theDefgeneric,
unsigned short mi,
CLIPSValue *returnValue)
{
short i,j;
Defmethod *meth;
RESTRICTION *rptr;
size_t count;
int roffset,rstrctIndex;
Multifield *theList;
Environment *theEnv = theDefgeneric->header.env;
meth = theDefgeneric->methods + FindMethodByIndex(theDefgeneric,mi);
count = 3;
for (i = 0 ; i < meth->restrictionCount ; i++)
count += meth->restrictions[i].tcnt + 3;
theList = CreateMultifield(theEnv,count);
returnValue->value = theList;
if (meth->minRestrictions == RESTRICTIONS_UNBOUNDED)
{ theList->contents[0].integerValue = CreateInteger(theEnv,-1); }
else
{ theList->contents[0].integerValue = CreateInteger(theEnv,(long long) meth->minRestrictions); }
if (meth->maxRestrictions == RESTRICTIONS_UNBOUNDED)
{ theList->contents[1].integerValue = CreateInteger(theEnv,-1); }
else
{ theList->contents[1].integerValue = CreateInteger(theEnv,(long long) meth->maxRestrictions); }
theList->contents[2].integerValue = CreateInteger(theEnv,(long long) meth->restrictionCount);
roffset = 3 + meth->restrictionCount;
rstrctIndex = 3;
for (i = 0 ; i < meth->restrictionCount ; i++)
{
rptr = meth->restrictions + i;
theList->contents[rstrctIndex++].integerValue = CreateInteger(theEnv,(long long) roffset + 1);
theList->contents[roffset++].lexemeValue = (rptr->query != NULL) ? TrueSymbol(theEnv) : FalseSymbol(theEnv);
theList->contents[roffset++].integerValue = CreateInteger(theEnv,(long long) rptr->tcnt);
for (j = 0 ; j < rptr->tcnt ; j++)
{
#if OBJECT_SYSTEM
theList->contents[roffset++].lexemeValue = CreateSymbol(theEnv,DefclassName((Defclass *) rptr->types[j]));
#else
theList->contents[roffset++].lexemeValue = CreateSymbol(theEnv,TypeName(theEnv,((CLIPSInteger *) rptr->types[j])->contents));
#endif
}
}
}
static void PrintGenericCall(
Environment *theEnv,
const char *logName,
Defgeneric *theDefgeneric)
{
#if DEVELOPER
WriteString(theEnv,logName,"(");
WriteString(theEnv,logName,DefgenericName(theDefgeneric));
if (GetFirstArgument() != NULL)
{
WriteString(theEnv,logName," ");
PrintExpression(theEnv,logName,GetFirstArgument());
}
WriteString(theEnv,logName,")");
#else
#if MAC_XCD
#pragma unused(theEnv)
#pragma unused(logName)
#pragma unused(theDefgeneric)
#endif
#endif
}
static bool EvaluateGenericCall(
Environment *theEnv,
Defgeneric *theDefgeneric,
UDFValue *returnValue)
{
GenericDispatch(theEnv,theDefgeneric,NULL,NULL,GetFirstArgument(),returnValue);
if ((returnValue->header->type == SYMBOL_TYPE) &&
(returnValue->value == FalseSymbol(theEnv)))
return false;
return true;
}
static void DecrementGenericBusyCount(
Environment *theEnv,
Defgeneric *theDefgeneric)
{
if (! ConstructData(theEnv)->ClearInProgress)
{ theDefgeneric->busy--; }
}
static void IncrementGenericBusyCount(
Environment *theEnv,
Defgeneric *theDefgeneric)
{
#if MAC_XCD
#pragma unused(theEnv)
#endif
#if (! RUN_TIME) && (! BLOAD_ONLY)
if (! ConstructData(theEnv)->ParsingConstruct)
{ ConstructData(theEnv)->DanglingConstructs++; }
#endif
theDefgeneric->busy++;
}
#if (! BLOAD_ONLY) && (! RUN_TIME)
static void SaveDefgenerics(
Environment *theEnv,
Defmodule *theModule,
const char *logName,
void *context)
{
SaveConstruct(theEnv,theModule,logName,DefgenericData(theEnv)->DefgenericConstruct);
}
static void SaveDefmethods(
Environment *theEnv,
Defmodule *theModule,
const char *logName,
void *context)
{
DoForAllConstructsInModule(theEnv,theModule,
SaveDefmethodsForDefgeneric,
DefgenericData(theEnv)->DefgenericModuleIndex,
false,(void *) logName);
}
static void SaveDefmethodsForDefgeneric(
Environment *theEnv,
ConstructHeader *theDefgeneric,
void *userBuffer)
{
Defgeneric *gfunc = (Defgeneric *) theDefgeneric;
const char *logName = (const char *) userBuffer;
long i;
for (i = 0 ; i < gfunc->mcnt ; i++)
{
if (gfunc->methods[i].header.ppForm != NULL)
{
WriteString(theEnv,logName,gfunc->methods[i].header.ppForm);
WriteString(theEnv,logName,"\n");
}
}
}
static void RemoveDefgenericMethod(
Environment *theEnv,
Defgeneric *gfunc,
unsigned short gi)
{
Defmethod *narr;
unsigned short b,e;
if (gfunc->methods[gi].system)
{
SetEvaluationError(theEnv,true);
PrintErrorID(theEnv,"GENRCCOM",4,false);
WriteString(theEnv,STDERR,"Cannot remove implicit system function method for generic function '");
WriteString(theEnv,STDERR,DefgenericName(gfunc));
WriteString(theEnv,STDERR,"'.\n");
return;
}
DeleteMethodInfo(theEnv,gfunc,&gfunc->methods[gi]);
if (gfunc->mcnt == 1)
{
rm(theEnv,gfunc->methods,sizeof(Defmethod));
gfunc->mcnt = 0;
gfunc->methods = NULL;
}
else
{
gfunc->mcnt--;
narr = (Defmethod *) gm2(theEnv,(sizeof(Defmethod) * gfunc->mcnt));
for (b = e = 0 ; b < gfunc->mcnt ; b++ , e++)
{
if (b == gi)
e++;
GenCopyMemory(Defmethod,1,&narr[b],&gfunc->methods[e]);
}
rm(theEnv,gfunc->methods,(sizeof(Defmethod) * (gfunc->mcnt+1)));
gfunc->methods = narr;
}
}
#endif
#if DEBUGGING_FUNCTIONS
static unsigned short ListMethodsForGeneric(
Environment *theEnv,
const char *logicalName,
Defgeneric *gfunc)
{
unsigned short gi;
StringBuilder *theSB;
theSB = CreateStringBuilder(theEnv,256);
for (gi = 0 ; gi < gfunc->mcnt ; gi++)
{
WriteString(theEnv,logicalName,DefgenericName(gfunc));
WriteString(theEnv,logicalName," #");
PrintMethod(theEnv,&gfunc->methods[gi],theSB);
WriteString(theEnv,logicalName,theSB->contents);
WriteString(theEnv,logicalName,"\n");
}
SBDispose(theSB);
return gfunc->mcnt;
}
static bool DefgenericWatchAccess(
Environment *theEnv,
int code,
bool newState,
Expression *argExprs)
{
#if MAC_XCD
#pragma unused(code)
#endif
return(ConstructSetWatchAccess(theEnv,DefgenericData(theEnv)->DefgenericConstruct,newState,argExprs,
(ConstructGetWatchFunction *) DefgenericGetWatch,
(ConstructSetWatchFunction *) DefgenericSetWatch));
}
static bool DefgenericWatchPrint(
Environment *theEnv,
const char *logName,
int code,
Expression *argExprs)
{
#if MAC_XCD
#pragma unused(code)
#endif
return(ConstructPrintWatchAccess(theEnv,DefgenericData(theEnv)->DefgenericConstruct,logName,argExprs,
(ConstructGetWatchFunction *) DefgenericGetWatch,
(ConstructSetWatchFunction *) DefgenericSetWatch));
}
static bool DefmethodWatchAccess(
Environment *theEnv,
int code,
bool newState,
Expression *argExprs)
{
#if MAC_XCD
#pragma unused(code)
#endif
if (newState)
return(DefmethodWatchSupport(theEnv,"watch",NULL,newState,NULL,DefmethodSetWatch,argExprs));
else
return(DefmethodWatchSupport(theEnv,"unwatch",NULL,newState,NULL,DefmethodSetWatch,argExprs));
}
static bool DefmethodWatchPrint(
Environment *theEnv,
const char *logName,
int code,
Expression *argExprs)
{
#if MAC_XCD
#pragma unused(code)
#endif
return(DefmethodWatchSupport(theEnv,"list-watch-items",logName,0,
PrintMethodWatchFlag,NULL,argExprs));
}
static bool DefmethodWatchSupport(
Environment *theEnv,
const char *funcName,
const char *logName,
bool newState,
void (*printFunc)(Environment *,const char *,Defgeneric *,unsigned short),
void (*traceFunc)(Defgeneric *,unsigned short,bool),
Expression *argExprs)
{
Defgeneric *theGeneric = NULL;
unsigned short theMethod = 0;
unsigned int argIndex = 2;
UDFValue genericName, methodIndex;
Defmodule *theModule;
if (argExprs == NULL)
{
SaveCurrentModule(theEnv);
theModule = GetNextDefmodule(theEnv,NULL);
while (theModule != NULL)
{
SetCurrentModule(theEnv,theModule);
if (traceFunc == NULL)
{
WriteString(theEnv,logName,DefmoduleName(theModule));
WriteString(theEnv,logName,":\n");
}
theGeneric = GetNextDefgeneric(theEnv,NULL);
while (theGeneric != NULL)
{
theMethod = GetNextDefmethod(theGeneric,0);
while (theMethod != 0)
{
if (traceFunc != NULL)
(*traceFunc)(theGeneric,theMethod,newState);
else
{
WriteString(theEnv,logName," ");
(*printFunc)(theEnv,logName,theGeneric,theMethod);
}
theMethod = GetNextDefmethod(theGeneric,theMethod);
}
theGeneric = GetNextDefgeneric(theEnv,theGeneric);
}
theModule = GetNextDefmodule(theEnv,theModule);
}
RestoreCurrentModule(theEnv);
return true;
}
while (argExprs != NULL)
{
if (EvaluateExpression(theEnv,argExprs,&genericName))
return false;
if ((genericName.header->type != SYMBOL_TYPE) ? true :
((theGeneric =
LookupDefgenericByMdlOrScope(theEnv,genericName.lexemeValue->contents)) == NULL))
{
ExpectedTypeError1(theEnv,funcName,argIndex,"'generic function name'");
return false;
}
if (GetNextArgument(argExprs) == NULL)
theMethod = 0;
else
{
argExprs = GetNextArgument(argExprs);
argIndex++;
if (EvaluateExpression(theEnv,argExprs,&methodIndex))
return false;
if ((methodIndex.header->type != INTEGER_TYPE) ? false :
((methodIndex.integerValue->contents <= 0) ? false :
(FindMethodByIndex(theGeneric,theMethod) != METHOD_NOT_FOUND)))
theMethod = (unsigned short) methodIndex.integerValue->contents;
else
{
ExpectedTypeError1(theEnv,funcName,argIndex,"'method index'");
return false;
}
}
if (theMethod == 0)
{
theMethod = GetNextDefmethod(theGeneric,0);
while (theMethod != 0)
{
if (traceFunc != NULL)
(*traceFunc)(theGeneric,theMethod,newState);
else
(*printFunc)(theEnv,logName,theGeneric,theMethod);
theMethod = GetNextDefmethod(theGeneric,theMethod);
}
}
else
{
if (traceFunc != NULL)
(*traceFunc)(theGeneric,theMethod,newState);
else
(*printFunc)(theEnv,logName,theGeneric,theMethod);
}
argExprs = GetNextArgument(argExprs);
argIndex++;
}
return true;
}
static void PrintMethodWatchFlag(
Environment *theEnv,
const char *logName,
Defgeneric *theGeneric,
unsigned short theMethod)
{
StringBuilder *theSB = CreateStringBuilder(theEnv,60);
WriteString(theEnv,logName,DefgenericName(theGeneric));
WriteString(theEnv,logName," ");
DefmethodDescription(theGeneric,theMethod,theSB);
WriteString(theEnv,logName,theSB->contents);
if (DefmethodGetWatch(theGeneric,theMethod))
WriteString(theEnv,logName," = on\n");
else
WriteString(theEnv,logName," = off\n");
SBDispose(theSB);
}
#endif
#if ! OBJECT_SYSTEM
void TypeCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UDFValue result;
EvaluateExpression(theEnv,GetFirstArgument(),&result);
returnValue->lexemeValue = CreateSymbol(theEnv,TypeName(theEnv,result.header->type));
}
#endif
void SetNextDefgeneric(
Defgeneric *theDefgeneric,
Defgeneric *targetDefgeneric)
{
SetNextConstruct(&theDefgeneric->header,
&targetDefgeneric->header);
}
const char *DefgenericModule(
Defgeneric *theDefgeneric)
{
return GetConstructModuleName(&theDefgeneric->header);
}
const char *DefgenericName(
Defgeneric *theDefgeneric)
{
return GetConstructNameString(&theDefgeneric->header);
}
const char *DefgenericPPForm(
Defgeneric *theDefgeneric)
{
return GetConstructPPForm(&theDefgeneric->header);
}
CLIPSLexeme *GetDefgenericNamePointer(
Defgeneric *theDefgeneric)
{
return GetConstructNamePointer(&theDefgeneric->header);
}
void SetDefgenericPPForm(
Environment *theEnv,
Defgeneric *theDefgeneric,
const char *thePPForm)
{
SetConstructPPForm(theEnv,&theDefgeneric->header,thePPForm);
}
#endif