/* ASCEND modelling environment Copyright (C) 2006 Carnegie Mellon University Copyright (C) 1996 Ben Allan Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *//* @file Ascend Instance Tree Link Management *//* based in instance.c by Tom Epperly 9/3/89 Last in CVS: $Revision: 1.13 $ $Date: 1998/02/05 16:36:59 $ $Author: ballan $ */ #include #include #include #include #include #include #include "symtab.h" #include "functype.h" #include "expr_types.h" #include "instance_name.h" #include "instance_io.h" #include "check.h" #include "dump.h" #include "child.h" #include "type_desc.h" #include "prototype.h" #include "pending.h" #include "find.h" #include "rel_blackbox.h" #include "vlist.h" #include "relation.h" #include "logical_relation.h" #include "logrelation.h" #include "relation_util.h" #include "logrel_util.h" #include "rel_common.h" #include "case.h" #include "when_util.h" #include "universal.h" #include #include "instance_types.h" /* new */ #include "atomsize.h" #include "atomvalue.h" #include "cmpfunc.h" #include "destroyinst.h" #include "instmacro.h" #include "instquery.h" #include "linkinst.h" #include "mathinst.h" #include "parentchild.h" #define PANIC_ILLEGAL_INSTANCE Asc_Panic(2, __FUNCTION__, "invalid instance type") /** this gets used in interactive merge/refinement and destruction. */ void ChangeRelationPointers(struct Instance *rel, struct Instance *old, struct Instance *new ){ //if(NULL==new)CONSOLE_DEBUG("Want to remove reference to var %p in relation %p",old,rel); assert(rel!=NULL); assert(rel->t==REL_INST); AssertMemory(rel); if (RELN_INST(rel)->ptr!=NULL) { /* FIXME: ChangeRelationPointers needs verification. all rel types have the rel->varlist that needs repair, then each rel type has specifics to fix up. */ switch (RELN_INST(rel)->type) { case e_token: ModifyTokenRelationPointers(rel,RELN_INST(rel)->ptr,old,new); return; #if 0 case e_glassbox: ModifyGlassBoxRelPointers(rel,RELN_INST(rel)->ptr,old,new); return; #endif case e_blackbox: ModifyBlackBoxRelPointers(rel,RELN_INST(rel)->ptr,old,new); return; case e_undefined: default: PANIC_ILLEGAL_INSTANCE; } } } void ChangeLogRelPointers(struct Instance *lrel, struct Instance *old, struct Instance *new ){ struct gl_list_t *varlist,*rellist; struct Instance *inst; struct logrelation *logrel; logrel = LRELN_INST(lrel)->ptr; varlist = logrel->bvars; rellist = logrel->satrels; if (new == NULL) { inst = old; } else { inst = new; } assert(lrel->t==LREL_INST); AssertMemory(lrel); switch(inst->t){ case BOOLEAN_ATOM_INST: if (logrel!=NULL){ ModifyLogRelPointers(varlist,logrel,old,new); return; } break; case REL_INST: case LREL_INST: if (logrel!=NULL){ ModifyLogRelPointers(rellist,logrel,old,new); return; } break; default: PANIC_ILLEGAL_INSTANCE; } } void ChangeWhenPointers(struct Instance *when, struct Instance *old, struct Instance *new ){ struct gl_list_t *varlist,*caselist,*reflist; struct Instance *scratch; struct Case *cur_case; unsigned long c,len,pos; varlist = W_INST(when)->bvar; caselist = W_INST(when)->cases; len = gl_length(caselist); if (new == NULL) { scratch = old; } else { scratch = new; } assert(when->t==WHEN_INST); AssertMemory(when); switch(scratch->t){ case BOOLEAN_ATOM_INST: case INTEGER_ATOM_INST: case SYMBOL_ATOM_INST: case BOOLEAN_CONSTANT_INST: case INTEGER_CONSTANT_INST: case SYMBOL_CONSTANT_INST: if (varlist!=NULL){ ModifyWhenPointers(varlist,old,new); return; } case MODEL_INST: case WHEN_INST: case REL_INST: case LREL_INST: for(c=1;c<=len;c++) { cur_case = (struct Case *)gl_fetch(caselist,c); reflist = GetCaseReferences(cur_case); if (reflist != NULL) { if (0 != (pos = gl_search(reflist,old,(CmpFunc)CmpP))) ModifyWhenPointers(reflist,old,new); } } return; default: PANIC_ILLEGAL_INSTANCE; } } /** Tell parent to change pointers to oldchild to pointers to newchild. */ void ChangeParent(struct Instance *parent, struct Instance *oldchild, struct Instance *newchild ){ register unsigned long c,length; AssertMemory(parent); length = NumberChildren(parent); for(c=1;c<=length;c++){ if (InstanceChild(parent,c)==oldchild) { StoreChildPtr(parent,c,newchild); } } } void ReDirectParents(struct Instance *old, struct Instance *new){ register struct Instance *parent; register unsigned long index1,length; length = NumberParents(new); for(index1=1;index1<=length;index1++) { parent = InstanceParent(new,index1); ChangeParent(parent,old,new); } } void ReDirectChildren(struct Instance *old, struct Instance *new){ register struct Instance *child; register unsigned long c,length,pos; length = NumberChildren(new); for(c=1;c<=length;c++){ if ((child = InstanceChild(new,c))!=NULL){ if ((pos = SearchForParent(child,old))!=0){ DeleteParent(child,pos); AddParent(child,new); } } } } void ReorderChildrenPtrs(register struct Instance **c, register CONST ChildListPtr old, register CONST ChildListPtr new, register unsigned long int olen, register unsigned long int nlen ){ register unsigned nzero; if (olen==0) return; nzero = nlen-olen; while (nlen > 0) { if (ChildStrPtr(new,nlen) == ChildStrPtr(old,olen)) { /* move pointer at olen-1 to nlen-1 and put NULL in olen-1 */ c[--nlen] = c[--olen]; c[olen] = NULL; if (olen==0)return; } else { nlen--; if (--nzero==0) return; } } } /** Remove old from the clique put new in its place. */ void FixCliques(struct Instance *old, struct Instance *new){ register struct Instance *ptr,*next; ptr = new; /* SetNextCliqueMember(ptr,NextCliqueMember(old)); not needed */ while((next=NextCliqueMember(ptr))!=old) ptr = next; SetNextCliqueMember(ptr,new); /* SetNextCliqueMember(old,old); illegal since old is no longer allocated */ } /* this is called to tell relations about a change in variable location * e.g. If two atoms are merged, point all the relations that know about * ATOM old to ATOM new. */ void FixRelations(struct RealAtomInstance *old, struct RealAtomInstance *new) { register unsigned long c,len; AssertMemory(old); AssertMemory(new); if ((new->relations==NULL)||(new->relations==old->relations)){ /* new had no relations or new has the identical relation list */ new->relations = old->relations; if ((len=RelationsCount(INST(new)))>0){ for(c=1;c<=len;c++) { ChangeRelationPointers(RelationsForAtom(INST(new),c), INST(old),INST(new)); } } } else { len=RelationsCount(INST(old)); if (len>0) { for(c=1;c<=len;c++){ ChangeRelationPointers(RelationsForAtom(INST(old),c), INST(old),INST(new)); AddRelation(INST(new),RelationsForAtom(INST(old),c)); } } if (old->relations) { gl_destroy(old->relations); } } old->relations=NULL; } static void FixLogRelationsIf(struct Instance *old, struct Instance *new){ register unsigned long c,len; if ((len=LogRelationsCount(new))>0){ for(c=1;c<=len;c++) { ChangeLogRelPointers(LogRelationsForInstance(new,c),old,new); } } } static void FixLogRelationsElse(struct Instance *old, struct Instance *new){ register unsigned long c,len; if ((len=LogRelationsCount(INST(old)))>0){ for(c=1;c<=len;c++){ ChangeLogRelPointers(LogRelationsForInstance(old,c),old,new); AddLogRel(new,LogRelationsForInstance(old,c)); } } } void FixLogRelations(struct Instance *old, struct Instance *new ){ switch(old->t){ case BOOLEAN_ATOM_INST: AssertMemory(BA_INST(old)); AssertMemory(BA_INST(new)); if((BA_INST(new)->logrelations==NULL) || (BA_INST(new)->logrelations==BA_INST(old)->logrelations)) { BA_INST(new)->logrelations = BA_INST(old)->logrelations; FixLogRelationsIf(old,new); } else { FixLogRelationsElse(old,new); if (BA_INST(old)->logrelations) gl_destroy(BA_INST(old)->logrelations); } BA_INST(old)->logrelations=NULL; break; case REL_INST: AssertMemory(RELN_INST(old)); AssertMemory(RELN_INST(new)); if((RELN_INST(new)->logrels==NULL) || (RELN_INST(new)->logrels==RELN_INST(old)->logrels)) { RELN_INST(new)->logrels = RELN_INST(old)->logrels; FixLogRelationsIf(old,new); } else { FixLogRelationsElse(old,new); if (RELN_INST(old)->logrels) gl_destroy(RELN_INST(old)->logrels); } RELN_INST(old)->logrels=NULL; break; case LREL_INST: AssertMemory(LRELN_INST(old)); AssertMemory(LRELN_INST(new)); if((LRELN_INST(new)->logrels==NULL) || (LRELN_INST(new)->logrels==LRELN_INST(old)->logrels)) { LRELN_INST(new)->logrels = LRELN_INST(old)->logrels; FixLogRelationsIf(old,new); } else { FixLogRelationsElse(old,new); if (LRELN_INST(old)->logrels) gl_destroy(LRELN_INST(old)->logrels); } LRELN_INST(old)->logrels=NULL; break; default: PANIC_ILLEGAL_INSTANCE; } } static void FixWhensIf(struct Instance *old, struct Instance *new){ register unsigned long c,len; if ((len=WhensCount(new))>0){ for(c=1;c<=len;c++) { ChangeWhenPointers(WhensForInstance(new,c),old,new); } } } static void FixWhensElse(struct Instance *old, struct Instance *new){ register unsigned long c,len; if ((len=WhensCount(INST(old)))>0){ for(c=1;c<=len;c++){ ChangeWhenPointers(WhensForInstance(old,c),old,new); AddWhen(new,WhensForInstance(old,c)); } } } void FixWhens(struct Instance *old, struct Instance *new){ switch(old->t){ case BOOLEAN_ATOM_INST: AssertMemory(BA_INST(old)); AssertMemory(BA_INST(new)); if((BA_INST(new)->whens==NULL) || (BA_INST(new)->whens==BA_INST(old)->whens)) { BA_INST(new)->whens = BA_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (BA_INST(old)->whens) gl_destroy(BA_INST(old)->whens); } BA_INST(old)->whens=NULL; break; case INTEGER_ATOM_INST: AssertMemory(IA_INST(old)); AssertMemory(IA_INST(new)); if((IA_INST(new)->whens==NULL) || (IA_INST(new)->whens==IA_INST(old)->whens)) { IA_INST(new)->whens = IA_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (IA_INST(old)->whens) gl_destroy(IA_INST(old)->whens); } IA_INST(old)->whens=NULL; break; case SYMBOL_ATOM_INST: AssertMemory(SYMA_INST(old)); AssertMemory(SYMA_INST(new)); if((SYMA_INST(new)->whens==NULL) || (SYMA_INST(new)->whens==SYMA_INST(old)->whens)) { SYMA_INST(new)->whens = SYMA_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (SYMA_INST(old)->whens) gl_destroy(SYMA_INST(old)->whens); } SYMA_INST(old)->whens=NULL; break; case BOOLEAN_CONSTANT_INST: AssertMemory(BC_INST(old)); AssertMemory(BC_INST(new)); if((BC_INST(new)->whens==NULL) || (BC_INST(new)->whens==BC_INST(old)->whens)) { BC_INST(new)->whens = BC_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (BC_INST(old)->whens) gl_destroy(BC_INST(old)->whens); } BC_INST(old)->whens=NULL; break; case INTEGER_CONSTANT_INST: AssertMemory(IC_INST(old)); AssertMemory(IC_INST(new)); if((IC_INST(new)->whens==NULL) || (IC_INST(new)->whens==IC_INST(old)->whens)) { IC_INST(new)->whens = IC_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (IC_INST(old)->whens) gl_destroy(IC_INST(old)->whens); } IC_INST(old)->whens=NULL; break; case SYMBOL_CONSTANT_INST: AssertMemory(SYMC_INST(old)); AssertMemory(SYMC_INST(new)); if((SYMC_INST(new)->whens==NULL) || (SYMC_INST(new)->whens==SYMC_INST(old)->whens)) { SYMC_INST(new)->whens = SYMC_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (SYMC_INST(old)->whens) gl_destroy(SYMC_INST(old)->whens); } SYMC_INST(old)->whens=NULL; break; case MODEL_INST: AssertMemory(MOD_INST(old)); AssertMemory(MOD_INST(new)); if((MOD_INST(new)->whens==NULL) || (MOD_INST(new)->whens==MOD_INST(old)->whens)) { MOD_INST(new)->whens = MOD_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (MOD_INST(old)->whens) gl_destroy(MOD_INST(old)->whens); } MOD_INST(old)->whens=NULL; break; case REL_INST: AssertMemory(RELN_INST(old)); AssertMemory(RELN_INST(new)); if((RELN_INST(new)->whens==NULL) || (RELN_INST(new)->whens==RELN_INST(old)->whens)) { RELN_INST(new)->whens = RELN_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (RELN_INST(old)->whens) gl_destroy(RELN_INST(old)->whens); } RELN_INST(old)->whens=NULL; break; case LREL_INST: AssertMemory(LRELN_INST(old)); AssertMemory(LRELN_INST(new)); if((LRELN_INST(new)->whens==NULL) || (LRELN_INST(new)->whens==LRELN_INST(old)->whens)) { LRELN_INST(new)->whens = LRELN_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (LRELN_INST(old)->whens) gl_destroy(LRELN_INST(old)->whens); } LRELN_INST(old)->whens=NULL; break; case WHEN_INST: AssertMemory(W_INST(old)); AssertMemory(W_INST(new)); if((W_INST(new)->whens==NULL) || (W_INST(new)->whens==W_INST(old)->whens)) { W_INST(new)->whens = W_INST(old)->whens; FixWhensIf(old,new); } else{ FixWhensElse(old,new); if (W_INST(old)->whens) gl_destroy(W_INST(old)->whens); } W_INST(old)->whens=NULL; break; default: PANIC_ILLEGAL_INSTANCE; } } void FixWhensForRefinement(struct Instance *old, struct Instance *new){ switch(new->t){ case BOOLEAN_ATOM_INST: AssertMemory(BA_INST(new)); if(BA_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; case INTEGER_ATOM_INST: AssertMemory(IA_INST(new)); if(IA_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; case SYMBOL_ATOM_INST: AssertMemory(SYMA_INST(new)); if(SYMA_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; case BOOLEAN_CONSTANT_INST: AssertMemory(BC_INST(new)); if(BC_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; case INTEGER_CONSTANT_INST: AssertMemory(IC_INST(new)); if(IC_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; case SYMBOL_CONSTANT_INST: AssertMemory(SYMC_INST(new)); if(SYMC_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; case MODEL_INST: AssertMemory(MOD_INST(new)); if(MOD_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; case REL_INST: AssertMemory(RELN_INST(new)); if(RELN_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; case LREL_INST: AssertMemory(LRELN_INST(new)); if(LRELN_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; case WHEN_INST: AssertMemory(W_INST(new)); if(W_INST(new)->whens!=NULL) { FixWhensIf(old,new); } break; default: PANIC_ILLEGAL_INSTANCE; } }