/* * Procedure Data Structure Implementation * by Tom Epperly * Created: 1/10/90 * Version: $Revision: 1.18 $ * Version control file: $RCSfile: proc.c,v $ * Date last modified: $Date: 1998/04/11 01:31:21 $ * Last modified by: $Author: ballan $ * * This file is part of the Ascend Language Interpreter. * * Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly * Copyright (C) 1998 Carnegie Mellon University * * The Ascend Language Interpreter 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 of the * License, or (at your option) any later version. * * The Ascend Language Interpreter is distributed in 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 . */ #include "proc.h" #include #include #include "symtab.h" #include "instance_enum.h" #include "cmpfunc.h" #include #include "functype.h" #include "expr_types.h" #include "stattypes.h" #include "statement.h" #define PMALLOC(x) x = ASC_NEW(struct InitProcedure) /* * UNIVERSAL method list for all models. * If a method lookup fails, this list is consulted. * more or less this exists because there isn't an * explicit root MODEL in the implementation. */ static struct gl_list_t *g_model_definition_methods = NULL; #define GMDM g_model_definition_methods struct InitProcedure *CreateProcedure(symchar *name, struct StatementList *stats) { register struct InitProcedure *result; assert(AscFindSymbol(name)!=NULL); PMALLOC(result); assert(result!=NULL); result->name = name; result->slist = stats; result->parse_id = 0; if (stats!=NULL) AddContext(stats,context_METH); return result; } struct InitProcedure *CopyProcedure(struct InitProcedure *p) { register struct InitProcedure *result; assert(p!=NULL); PMALLOC(result); assert(result!=NULL); result->name = p->name; result->parse_id = p->parse_id; result->slist = CopyStatementList(p->slist); return result; } struct InitProcedure *CopyProcToModify(struct InitProcedure *p) { register struct InitProcedure *result; assert(p!=NULL); PMALLOC(result); assert(result!=NULL); result->name = p->name; result->parse_id = 0; result->slist = CopyListToModify(p->slist); return result; } struct gl_list_t *MergeProcedureLists(struct gl_list_t *old, struct gl_list_t *new) { register struct gl_list_t *result; register struct InitProcedure *proc; register unsigned long c,len; register unsigned long refproc; if (old==NULL) { return new; } result = gl_create(gl_length(old)+gl_safe_length(new)); if (new!=NULL){ len = gl_length(new); for(c=1;c<=len;c++){ proc = (struct InitProcedure *)gl_fetch(new,c); gl_append_ptr(result,(VOIDPTR)proc); } /* dont destroy the list yet */ } len = gl_length(old); /* this is where method inheritance rules occur. We keep all the * methods from the new in result, then we search for any method in * the old list which does not have an identically named * counterpart in the new list and add it to the result. * Methods in the old result which have be redefined in the new * list given are ignored. * * Once a result list is achieved the new list (but not the methods * in it) may be destroyed since the methods are all stored in result. */ if (new!=NULL) { for(c=1;c<=len;c++) { proc = (struct InitProcedure *)gl_fetch(old,c); refproc = gl_search(new,proc,(CmpFunc)CmpProcs); /* refproc will be 0 if no match */ if (refproc==0) { /* hence append to result */ gl_append_ptr(result,(VOIDPTR)CopyProcedure(proc)); } } gl_destroy(new); } else { for(c=1;c<=len;c++){ proc = (struct InitProcedure *)gl_fetch(old,c); gl_append_ptr(result,(VOIDPTR)CopyProcedure(proc)); } } gl_sort(result,(CmpFunc)CmpProcs); return result; } void DestroyProcedure(struct InitProcedure *p) { if (p!=NULL){ /* the following only destroys a reference to p->slist * unless of course it is the last reference to p->slist. * The name of the method belongs to the symbol table so must * not be destroyed here. */ DestroyStatementList(p->slist); p->parse_id = -1; ascfree((char *)p); } } void DestroyProcedureList(struct gl_list_t *pl) { if (pl!=NULL){ gl_iterate(pl,(void (*)(VOIDPTR))DestroyProcedure); gl_destroy(pl); } } /* * Returns the list of methods defined for all MODELs * unless they redefine the methods themselves. */ struct gl_list_t *GetUniversalProcedureList(void) { return GMDM; } /* * Sets the list of procedures defined for all MODELs. * If a UPL already exists, it will be destroyed unless it * is the same. If the same, it is resorted. */ void SetUniversalProcedureList(struct gl_list_t *upl) { if (GMDM != upl) { DestroyProcedureList(GMDM); GMDM = upl; } if (GMDM != NULL) { gl_sort(GMDM,(CmpFunc)CmpProcs); } return; } symchar *ProcNameF(CONST struct InitProcedure *p) { assert(p!=NULL); return p->name; } struct StatementList *ProcStatementListF(CONST struct InitProcedure *p) { assert(p!=NULL); return p->slist; } long GetProcParseIdF(CONST struct InitProcedure *p) { assert(p!=NULL); return p->parse_id; } void SetProcParseIdF(struct InitProcedure *p, long id) { assert(p!=NULL); p->parse_id = id; } int CmpProcs(CONST struct InitProcedure *p1, CONST struct InitProcedure *p2) { assert(p1 && p2); return CmpSymchar(p1->name,p2->name); } int CompareProcedureLists(struct gl_list_t *pl1, struct gl_list_t *pl2, unsigned long *n) { CONST struct InitProcedure *proc1, *proc2; CONST struct StatementList *sl1, *sl2; unsigned long c,len, len1, len2, diff; assert (n != NULL); /* compare ptrs */ if (pl1==pl2) { return 0; } /* check for nulls */ if ( (pl1==NULL) || (pl2==NULL) ) { *n = 1; return 1; } /* length of each procedure list */ len1 = gl_length(pl1); len2 = gl_length(pl2); /* * if len1 and len2 are different from each other , we will return 1, * but we still need to find the index of the first different procedure. * So, get the number of elements of the shorthest list and compare * that number of procedures in the lists */ if (len1 == len2) { len = len1; } else { if (len1 < len2) { len = len1; } else { len = len2; } } /* analyze the list of procedures */ for(c=1;c<=len;c++){ proc1 = (struct InitProcedure *)gl_fetch(pl1,c); proc2 = (struct InitProcedure *)gl_fetch(pl2,c); /* * compare names */ if (CmpProcs(proc1,proc2)) { *n = c; return 1; } /* * compare statement lists * if lists are different, diff will contain the index of the first * different statement. Use it if necessary */ sl1 = ProcStatementList(proc1); sl2 = ProcStatementList(proc2); if (CompareStatementLists(sl1,sl2,&diff)) { *n = c; return 1; } } /* * If we get here and the number of elements in the list are equal, * then the procedures are equal, * else the index of the first different procedure is len + 1 */ if (len1 == len2) { return 0; } else { *n = len+1; return 1; } /* parse_id are not for comparison */ }