📄 genrcpsr.c
字号:
SIDE EFFECTS : Expression type chain allocated
one or more nodes holding codes for types
(or class addresses)
NOTES : None
*************************************************************/
static EXPRESSION *ValidType(
void *theEnv,
SYMBOL_HN *tname)
{
#if OBJECT_SYSTEM
DEFCLASS *cls;
if (FindModuleSeparator(ValueToString(tname)))
IllegalModuleSpecifierMessage(theEnv);
else
{
cls = LookupDefclassInScope(theEnv,ValueToString(tname));
if (cls == NULL)
{
PrintErrorID(theEnv,"GENRCPSR",14,FALSE);
EnvPrintRouter(theEnv,WERROR,"Unknown class in method.\n");
return(NULL);
}
return(GenConstant(theEnv,EXTERNAL_ADDRESS,(void *) cls));
}
#else
if (strcmp(ValueToString(tname),INTEGER_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) INTEGER)));
if (strcmp(ValueToString(tname),FLOAT_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) FLOAT)));
if (strcmp(ValueToString(tname),SYMBOL_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) SYMBOL)));
if (strcmp(ValueToString(tname),STRING_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) STRING)));
if (strcmp(ValueToString(tname),MULTIFIELD_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) MULTIFIELD)));
if (strcmp(ValueToString(tname),EXTERNAL_ADDRESS_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) EXTERNAL_ADDRESS)));
if (strcmp(ValueToString(tname),FACT_ADDRESS_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) FACT_ADDRESS)));
if (strcmp(ValueToString(tname),NUMBER_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) NUMBER_TYPE_CODE)));
if (strcmp(ValueToString(tname),LEXEME_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) LEXEME_TYPE_CODE)));
if (strcmp(ValueToString(tname),ADDRESS_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) ADDRESS_TYPE_CODE)));
if (strcmp(ValueToString(tname),PRIMITIVE_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) PRIMITIVE_TYPE_CODE)));
if (strcmp(ValueToString(tname),OBJECT_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) OBJECT_TYPE_CODE)));
if (strcmp(ValueToString(tname),INSTANCE_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) INSTANCE_TYPE_CODE)));
if (strcmp(ValueToString(tname),INSTANCE_NAME_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) INSTANCE_NAME)));
if (strcmp(ValueToString(tname),INSTANCE_ADDRESS_TYPE_NAME) == 0)
return(GenConstant(theEnv,INTEGER,(void *) EnvAddLong(theEnv,(long) INSTANCE_ADDRESS)));
PrintErrorID(theEnv,"GENRCPSR",14,FALSE);
EnvPrintRouter(theEnv,WERROR,"Unknown type in method.\n");
#endif
return(NULL);
}
/*************************************************************
NAME : RedundantClasses
DESCRIPTION : Determines if one class (type) is
subsumes (or is subsumed by) another.
INPUTS : Two void pointers which are class pointers
if COOL is installed or integer hash nodes
for type codes otherwise.
RETURNS : TRUE if there is subsumption, FALSE otherwise
SIDE EFFECTS : An error message is printed, if appropriate.
NOTES : None
*************************************************************/
static intBool RedundantClasses(
void *theEnv,
void *c1,
void *c2)
{
char *tname;
#if OBJECT_SYSTEM
if (HasSuperclass((DEFCLASS *) c1,(DEFCLASS *) c2))
tname = EnvGetDefclassName(theEnv,c1);
else if (HasSuperclass((DEFCLASS *) c2,(DEFCLASS *) c1))
tname = EnvGetDefclassName(theEnv,c2);
#else
if (SubsumeType(ValueToInteger(c1),ValueToInteger(c2)))
tname = TypeName(theEnv,ValueToInteger(c1));
else if (SubsumeType(ValueToInteger(c2),ValueToInteger(c1)))
tname = TypeName(theEnv,ValueToInteger(c2));
#endif
else
return(FALSE);
PrintErrorID(theEnv,"GENRCPSR",15,FALSE);
EnvPrintRouter(theEnv,WERROR,tname);
EnvPrintRouter(theEnv,WERROR," class is redundant.\n");
return(TRUE);
}
/*********************************************************
NAME : AddGeneric
DESCRIPTION : Inserts a new generic function
header into the generic list
INPUTS : 1) Symbolic name of the new generic
2) Caller's input buffer for flag
if added generic is new or not
RETURNS : The address of the new node, or
address of old node if already present
SIDE EFFECTS : Generic header inserted
If the node is already present, it is
moved to the end of the list, otherwise
the new node is inserted at the end
NOTES : None
*********************************************************/
static DEFGENERIC *AddGeneric(
void *theEnv,
SYMBOL_HN *name,
int *newGeneric)
{
DEFGENERIC *gfunc;
gfunc = (DEFGENERIC *) EnvFindDefgeneric(theEnv,ValueToString(name));
if (gfunc != NULL)
{
*newGeneric = FALSE;
if (ConstructData(theEnv)->CheckSyntaxMode)
{ return(gfunc); }
/* ================================
The old trace state is preserved
================================ */
RemoveConstructFromModule(theEnv,(struct constructHeader *) gfunc);
}
else
{
*newGeneric = TRUE;
gfunc = NewGeneric(theEnv,name);
IncrementSymbolCount(name);
AddImplicitMethods(theEnv,gfunc);
}
AddConstructToModule((struct constructHeader *) gfunc);
return(gfunc);
}
/**********************************************************************
NAME : AddGenericMethod
DESCRIPTION : Inserts a blank method (with the method-index set)
into the specified position of the generic
method array
INPUTS : 1) The generic function
2) The index where to add the method in the array
3) The method user-index (0 if don't care)
RETURNS : The address of the new method
SIDE EFFECTS : Fields initialized (index set) and new method inserted
Generic function new method-index set to specified
by user-index if > current new method-index
NOTES : None
**********************************************************************/
static DEFMETHOD *AddGenericMethod(
void *theEnv,
DEFGENERIC *gfunc,
int mposn,
unsigned mi)
{
DEFMETHOD *narr;
register unsigned b, e;
narr = (DEFMETHOD *) gm2(theEnv,(sizeof(DEFMETHOD) * (gfunc->mcnt+1)));
for (b = e = 0 ; b < gfunc->mcnt ; b++ , e++)
{
if (b == (unsigned) mposn)
e++;
GenCopyMemory(DEFMETHOD,1,&narr[e],&gfunc->methods[b]);
}
if (mi == 0)
narr[mposn].index = gfunc->new_index++;
else
{
narr[mposn].index = mi;
if (mi >= gfunc->new_index)
gfunc->new_index = mi+1;
}
narr[mposn].busy = 0;
#if DEBUGGING_FUNCTIONS
narr[mposn].trace = DefgenericData(theEnv)->WatchMethods;
#endif
narr[mposn].minRestrictions = 0;
narr[mposn].maxRestrictions = 0;
narr[mposn].restrictionCount = 0;
narr[mposn].localVarCount = 0;
narr[mposn].system = 0;
narr[mposn].restrictions = NULL;
narr[mposn].actions = NULL;
narr[mposn].ppForm = NULL;
narr[mposn].usrData = NULL;
if (gfunc->mcnt != 0)
rm(theEnv,(void *) gfunc->methods,(sizeof(DEFMETHOD) * gfunc->mcnt));
gfunc->mcnt++;
gfunc->methods = narr;
return(&narr[mposn]);
}
/****************************************************************
NAME : RestrictionsCompare
DESCRIPTION : Compares the restriction-expression list
with an existing methods restrictions to
determine an ordering
INPUTS : 1) The parameter/restriction expression list
2) The total number of restrictions
3) The number of minimum restrictions
4) The number of maximum restrictions (-1
if unlimited)
5) The method with which to compare restrictions
RETURNS : A code representing how the method restrictions
-1 : New restrictions have higher precedence
0 : New restrictions are identical
1 : New restrictions have lower precedence
SIDE EFFECTS : None
NOTES : The new restrictions are stored in the argList
pointers of the parameter expressions
****************************************************************/
static int RestrictionsCompare(
EXPRESSION *params,
int rcnt,
int min,
int max,
DEFMETHOD *meth)
{
register int i;
register RESTRICTION *r1,*r2;
int diff = FALSE,rtn;
for (i = 0 ; (i < rcnt) && (i < meth->restrictionCount) ; i++)
{
/* =============================================================
A wildcard parameter always has lower precedence than
a regular parameter, regardless of the class restriction list
============================================================= */
if ((i == rcnt-1) && (max == -1) &&
(meth->maxRestrictions != -1))
return(LOWER_PRECEDENCE);
if ((i == meth->restrictionCount-1) && (max != -1) &&
(meth->maxRestrictions == -1))
return(HIGHER_PRECEDENCE);
/* =============================================================
The parameter with the most specific type list has precedence
============================================================= */
r1 = (RESTRICTION *) params->argList;
r2 = &meth->restrictions[i];
rtn = TypeListCompare(r1,r2);
if (rtn != IDENTICAL)
return(rtn);
/* =====================================================
The parameter with a query restriction has precedence
===================================================== */
if ((r1->query == NULL) && (r2->query != NULL))
return(LOWER_PRECEDENCE);
if ((r1->query != NULL) && (r2->query == NULL))
return(HIGHER_PRECEDENCE);
/* ==========================================================
Remember if the method restrictions differ at all - query
expressions must be identical as well for the restrictions
to be the same
========================================================== */
if (IdenticalExpression(r1->query,r2->query) == FALSE)
diff = TRUE;
params = params->nextArg;
}
/* =============================================================
If the methods have the same number of parameters here, they
are either the same restrictions, or they differ only in
the query restrictions
============================================================= */
if (rcnt == meth->restrictionCount)
return(diff ? LOWER_PRECEDENCE : IDENTICAL);
/* =============================================
The method with the greater number of regular
parameters has precedence
If they require the smae # of reg params,
then one without a wildcard has precedence
============================================= */
if (min > meth->minRestrictions)
return(HIGHER_PRECEDENCE);
if (meth->minRestrictions < min)
return(LOWER_PRECEDENCE);
return((max == - 1) ? LOWER_PRECEDENCE : HIGHER_PRECEDENCE);
}
/*****************************************************
NAME : TypeListCompare
DESCRIPTION : Determines the precedence between
the class lists on two restrictions
INPUTS : 1) Restriction address #1
2) Restriction address #2
RETURNS : -1 : r1 precedes r2
0 : Identical classes
1 : r2 precedes r1
SIDE EFFECTS : None
NOTES : None
*****************************************************/
static int TypeListCompare(
RESTRICTION *r1,
RESTRICTION *r2)
{
register int i,diff = FALSE;
if ((r1->tcnt == 0) && (r2->tcnt == 0))
return(IDENTICAL);
if (r1->tcnt == 0)
return(LOWER_PRECEDENCE);
if (r2->tcnt == 0)
return(HIGHER_PRECEDENCE);
for (i = 0 ; ((unsigned) i < r1->tcnt) && ((unsigned) i < r2->tcnt) ; i++)
{
if (r1->types[i] != r2->types[i])
{
diff = TRUE;
#if OBJECT_SYSTEM
if (HasSuperclass((DEFCLASS *) r1->types[i],(DEFCLASS *) r2->types[i]))
return(HIGHER_PRECEDENCE);
if (HasSuperclass((DEFCLASS *) r2->types[i],(DEFCLASS *) r1->types[i]))
return(LOWER_PRECEDENCE);
#else
if (SubsumeType(ValueToInteger(r1->types[i]),ValueToInteger(r2->types[i])))
return(HIGHER_PRECEDENCE);
if (SubsumeType(ValueToInteger(r2->types[i]),ValueToInteger(r1->types[i])))
return(LOWER_PRECEDENCE);
#endif
}
}
if (r1->tcnt < r2->tcnt)
return(HIGHER_PRECEDENCE);
if (r1->tcnt > r2->tcnt)
return(LOWER_PRECEDENCE);
if (diff)
return(LOWER_PRECEDENCE);
return(IDENTICAL);
}
/***************************************************
NAME : NewGeneric
DESCRIPTION : Allocates and initializes a new
generic function header
INPUTS : The name of the new generic
RETURNS : The address of the new generic
SIDE EFFECTS : Generic function header created
NOTES : None
***************************************************/
static DEFGENERIC *NewGeneric(
void *theEnv,
SYMBOL_HN *gname)
{
DEFGENERIC *ngen;
ngen = get_struct(theEnv,defgeneric);
InitializeConstructHeader(theEnv,"defgeneric",(struct constructHeader *) ngen,gname);
ngen->busy = 0;
ngen->new_index = 1;
ngen->methods = NULL;
ngen->mcnt = 0;
#if DEBUGGING_FUNCTIONS
ngen->trace = DefgenericData(theEnv)->WatchGenerics;
#endif
return(ngen);
}
#endif /* DEFGENERIC_CONSTRUCT && (! BLOAD_ONLY) && (! RUN_TIME) */
/***************************************************
NAME :
DESCRIPTION :
INPUTS :
RETURNS :
SIDE EFFECTS :
NOTES :
***************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -