📄 genrcpsr.c
字号:
(or a Class address if COOL is installed) INPUTS : The type name RETURNS : The expression chain (NULL on errors) SIDE EFFECTS : Expression type chain allocated one or more nodes holding codes for types (or class addresses) NOTES : None *************************************************************/static EXPRESSION *ValidType(tname) SYMBOL_HN *tname; {#if OBJECT_SYSTEM DEFCLASS *cls; if (FindModuleSeparator(ValueToString(tname))) IllegalModuleSpecifierMessage(); else { cls = LookupDefclassInScope(ValueToString(tname)); if (cls == NULL) { PrintErrorID("GENRCPSR",14,CLIPS_FALSE); PrintCLIPS(WERROR,"Unknown class in method.\n"); return(NULL); } return(GenConstant(EXTERNAL_ADDRESS,(VOID *) cls)); }#else if (strcmp(ValueToString(tname),INTEGER_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) INTEGER))); if (strcmp(ValueToString(tname),FLOAT_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) FLOAT))); if (strcmp(ValueToString(tname),SYMBOL_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) SYMBOL))); if (strcmp(ValueToString(tname),STRING_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) STRING))); if (strcmp(ValueToString(tname),MULTIFIELD_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) MULTIFIELD))); if (strcmp(ValueToString(tname),EXTERNAL_ADDRESS_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) EXTERNAL_ADDRESS))); if (strcmp(ValueToString(tname),FACT_ADDRESS_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) FACT_ADDRESS))); if (strcmp(ValueToString(tname),NUMBER_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) NUMBER_TYPE_CODE))); if (strcmp(ValueToString(tname),LEXEME_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) LEXEME_TYPE_CODE))); if (strcmp(ValueToString(tname),ADDRESS_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) ADDRESS_TYPE_CODE))); if (strcmp(ValueToString(tname),PRIMITIVE_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) PRIMITIVE_TYPE_CODE))); if (strcmp(ValueToString(tname),OBJECT_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) OBJECT_TYPE_CODE))); if (strcmp(ValueToString(tname),INSTANCE_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) INSTANCE_TYPE_CODE))); if (strcmp(ValueToString(tname),INSTANCE_NAME_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) INSTANCE_NAME))); if (strcmp(ValueToString(tname),INSTANCE_ADDRESS_TYPE_NAME) == 0) return(GenConstant(INTEGER,(VOID *) AddLong((long) INSTANCE_ADDRESS))); PrintErrorID("GENRCPSR",14,CLIPS_FALSE); PrintCLIPS(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 : CLIPS_TRUE if there is subsumption, CLIPS_FALSE otherwise SIDE EFFECTS : An error message is printed, if appropriate. NOTES : None *************************************************************/static BOOLEAN RedundantClasses(c1,c2) VOID *c1,*c2; { char *tname;#if OBJECT_SYSTEM if (HasSuperclass((DEFCLASS *) c1,(DEFCLASS *) c2)) tname = GetDefclassName(c1); else if (HasSuperclass((DEFCLASS *) c2,(DEFCLASS *) c1)) tname = GetDefclassName(c2);#else if (SubsumeType(ValueToInteger(c1),ValueToInteger(c2))) tname = TypeName(ValueToInteger(c1)); else if (SubsumeType(ValueToInteger(c2),ValueToInteger(c1))) tname = TypeName(ValueToInteger(c2));#endif else return(CLIPS_FALSE); PrintErrorID("GENRCPSR",15,CLIPS_FALSE); PrintCLIPS(WERROR,tname); PrintCLIPS(WERROR," class is redundant.\n"); return(CLIPS_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(name,new) SYMBOL_HN *name; int *new; { DEFGENERIC *gfunc; gfunc = (DEFGENERIC *) FindDefgeneric(ValueToString(name)); if (gfunc != NULL) { *new = CLIPS_FALSE; /* ================================ The old trace state is preserved ================================ */ RemoveConstructFromModule((struct constructHeader *) gfunc); } else { *new = CLIPS_TRUE; gfunc = NewGeneric(name); IncrementSymbolCount(name); AddImplicitMethods(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(gfunc,mposn,mi) DEFGENERIC *gfunc; int mposn; unsigned mi; { DEFMETHOD *narr; register int b,e; narr = (DEFMETHOD *) gm2((int) (sizeof(DEFMETHOD) * (gfunc->mcnt+1))); for (b = e = 0 ; b < gfunc->mcnt ; b++ , e++) { if (b == mposn) e++; CopyMemory(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 = 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; if (gfunc->mcnt != 0) rm((VOID *) gfunc->methods,(int) (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(params,rcnt,min,max,meth) EXPRESSION *params; int rcnt,min,max; DEFMETHOD *meth; { register int i; register RESTRICTION *r1,*r2; int diff = CLIPS_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) == CLIPS_FALSE) diff = CLIPS_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(r1,r2) RESTRICTION *r1,*r2; { register int i,diff = CLIPS_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 ; (i < r1->tcnt) && (i < r2->tcnt) ; i++) { if (r1->types[i] != r2->types[i]) { diff = CLIPS_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(gname) SYMBOL_HN *gname; { DEFGENERIC *ngen; ngen = get_struct(defgeneric); InitializeConstructHeader("defgeneric",(struct constructHeader *) ngen,gname); ngen->busy = 0; ngen->new_index = 1; ngen->methods = NULL; ngen->mcnt = 0;#if DEBUGGING_FUNCTIONS ngen->trace = 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 + -