/[ascend]/trunk/base/generic/compiler/proc.c
ViewVC logotype

Contents of /trunk/base/generic/compiler/proc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 669 - (show annotations) (download) (as text)
Wed Jun 21 07:00:45 2006 UTC (13 years, 8 months ago) by johnpye
File MIME type: text/x-csrc
File size: 8169 byte(s)
Merged changes from DAE branch (revisions 702 to 819) back into trunk.
This adds the Integration API to the ASCEND solver (in base/generic).
Also provides pre-alpha support for 'IDA' from the SUNDIALS suite, a DAE solver.
Many other minor code clean-ups, including adoption of new 'ASC_NEW' and friends (to replace 'ascmalloc')
Added some very sketchy stuff providing 'DIFF(...)' syntax, although it is anticipated that this will be removed.
1 /*
2 * Procedure Data Structure Implementation
3 * by Tom Epperly
4 * Created: 1/10/90
5 * Version: $Revision: 1.18 $
6 * Version control file: $RCSfile: proc.c,v $
7 * Date last modified: $Date: 1998/04/11 01:31:21 $
8 * Last modified by: $Author: ballan $
9 *
10 * This file is part of the Ascend Language Interpreter.
11 *
12 * Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
13 * Copyright (C) 1998 Carnegie Mellon University
14 *
15 * The Ascend Language Interpreter is free software; you can redistribute
16 * it and/or modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of the
18 * License, or (at your option) any later version.
19 *
20 * The Ascend Language Interpreter is distributed in hope that it will be
21 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with the program; if not, write to the Free Software Foundation,
27 * Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named
28 * COPYING.
29 *
30 */
31
32 #include <utilities/ascConfig.h>
33 #include <utilities/ascMalloc.h>
34 #include "compiler.h"
35 #include "symtab.h"
36 #include "instance_enum.h"
37 #include "cmpfunc.h"
38 #include <general/list.h>
39 #include "fractions.h"
40 #include "dimen.h"
41 #include "functype.h"
42 #include "expr_types.h"
43 #include "stattypes.h"
44 #include "statement.h"
45 #include "slist.h"
46 #include "proc.h"
47
48 #define PMALLOC(x) \
49 x = (struct InitProcedure *)ascmalloc(sizeof(struct InitProcedure))
50 #ifndef lint
51 static CONST char ProcedureRCSid[] = "$Id: proc.c,v 1.18 1998/04/11 01:31:21 ballan Exp $";
52 #endif
53
54 /*
55 * UNIVERSAL method list for all models.
56 * If a method lookup fails, this list is consulted.
57 * more or less this exists because there isn't an
58 * explicit root MODEL in the implementation.
59 */
60 static struct gl_list_t *g_model_definition_methods = NULL;
61 #define GMDM g_model_definition_methods
62
63 struct InitProcedure *CreateProcedure(symchar *name,
64 struct StatementList *stats)
65 {
66 register struct InitProcedure *result;
67 assert(AscFindSymbol(name)!=NULL);
68 PMALLOC(result);
69 assert(result!=NULL);
70 result->name = name;
71 result->slist = stats;
72 result->parse_id = 0;
73 if (stats!=NULL) AddContext(stats,context_METH);
74 return result;
75 }
76
77 struct InitProcedure *CopyProcedure(struct InitProcedure *p)
78 {
79 register struct InitProcedure *result;
80 assert(p!=NULL);
81 PMALLOC(result);
82 assert(result!=NULL);
83 result->name = p->name;
84 result->parse_id = p->parse_id;
85 result->slist = CopyStatementList(p->slist);
86 return result;
87 }
88
89 struct InitProcedure *CopyProcToModify(struct InitProcedure *p)
90 {
91 register struct InitProcedure *result;
92 assert(p!=NULL);
93 PMALLOC(result);
94 assert(result!=NULL);
95 result->name = p->name;
96 result->parse_id = 0;
97 result->slist = CopyListToModify(p->slist);
98 return result;
99 }
100
101 struct gl_list_t *MergeProcedureLists(struct gl_list_t *old,
102 struct gl_list_t *new)
103 {
104 register struct gl_list_t *result;
105 register struct InitProcedure *proc;
106 register unsigned long c,len;
107 register unsigned long refproc;
108 if (old==NULL) {
109 return new;
110 }
111 result = gl_create(gl_length(old)+gl_safe_length(new));
112 if (new!=NULL){
113 len = gl_length(new);
114 for(c=1;c<=len;c++){
115 proc = (struct InitProcedure *)gl_fetch(new,c);
116 gl_append_ptr(result,(VOIDPTR)proc);
117 } /* dont destroy the list yet */
118 }
119 len = gl_length(old);
120 /* this is where method inheritance rules occur. We keep all the
121 * methods from the new in result, then we search for any method in
122 * the old list which does not have an identically named
123 * counterpart in the new list and add it to the result.
124 * Methods in the old result which have be redefined in the new
125 * list given are ignored.
126 *
127 * Once a result list is achieved the new list (but not the methods
128 * in it) may be destroyed since the methods are all stored in result.
129 */
130 if (new!=NULL) {
131 for(c=1;c<=len;c++) {
132 proc = (struct InitProcedure *)gl_fetch(old,c);
133 refproc = gl_search(new,proc,(CmpFunc)CmpProcs);
134 /* refproc will be 0 if no match */
135 if (refproc==0) {
136 /* hence append to result */
137 gl_append_ptr(result,(VOIDPTR)CopyProcedure(proc));
138 }
139 }
140 gl_destroy(new);
141 } else {
142 for(c=1;c<=len;c++){
143 proc = (struct InitProcedure *)gl_fetch(old,c);
144 gl_append_ptr(result,(VOIDPTR)CopyProcedure(proc));
145 }
146 }
147 gl_sort(result,(CmpFunc)CmpProcs);
148 return result;
149 }
150
151 void DestroyProcedure(struct InitProcedure *p)
152 {
153 if (p!=NULL){
154 /* the following only destroys a reference to p->slist
155 * unless of course it is the last reference to p->slist.
156 * The name of the method belongs to the symbol table so must
157 * not be destroyed here.
158 */
159 DestroyStatementList(p->slist);
160 p->parse_id = -1;
161 ascfree((char *)p);
162 }
163 }
164
165 void DestroyProcedureList(struct gl_list_t *pl)
166 {
167 if (pl!=NULL){
168 gl_iterate(pl,(void (*)(VOIDPTR))DestroyProcedure);
169 gl_destroy(pl);
170 }
171 }
172
173 /*
174 * Returns the list of methods defined for all MODELs
175 * unless they redefine the methods themselves.
176 */
177 struct gl_list_t *GetUniversalProcedureList(void)
178 {
179 return GMDM;
180 }
181
182 /*
183 * Sets the list of procedures defined for all MODELs.
184 * If a UPL already exists, it will be destroyed unless it
185 * is the same. If the same, it is resorted.
186 */
187 void SetUniversalProcedureList(struct gl_list_t *upl)
188 {
189 if (GMDM != upl) {
190 DestroyProcedureList(GMDM);
191 GMDM = upl;
192 }
193 if (GMDM != NULL) {
194 gl_sort(GMDM,(CmpFunc)CmpProcs);
195 }
196 return;
197 }
198
199 symchar *ProcNameF(CONST struct InitProcedure *p)
200 {
201 assert(p!=NULL);
202 return p->name;
203 }
204
205 struct StatementList *ProcStatementListF(CONST struct InitProcedure *p)
206 {
207 assert(p!=NULL);
208 return p->slist;
209 }
210
211 long GetProcParseIdF(CONST struct InitProcedure *p)
212 {
213 assert(p!=NULL);
214 return p->parse_id;
215 }
216
217 void SetProcParseIdF(struct InitProcedure *p, long id)
218 {
219 assert(p!=NULL);
220 p->parse_id = id;
221 }
222
223 int CmpProcs(CONST struct InitProcedure *p1, CONST struct InitProcedure *p2)
224 {
225 assert(p1 && p2);
226 return CmpSymchar(p1->name,p2->name);
227 }
228
229
230 int CompareProcedureLists(struct gl_list_t *pl1, struct gl_list_t *pl2,
231 unsigned long *n)
232 {
233 CONST struct InitProcedure *proc1, *proc2;
234 CONST struct StatementList *sl1, *sl2;
235 unsigned long c,len, len1, len2, diff;
236
237 assert (n != NULL);
238
239 /* compare ptrs */
240 if (pl1==pl2) {
241 return 0;
242 }
243
244 /* check for nulls */
245 if ( (pl1==NULL) || (pl2==NULL) ) {
246 *n = 1;
247 return 1;
248 }
249
250 /* length of each procedure list */
251 len1 = gl_length(pl1);
252 len2 = gl_length(pl2);
253
254 /*
255 * if len1 and len2 are different from each other , we will return 1,
256 * but we still need to find the index of the first different procedure.
257 * So, get the number of elements of the shorthest list and compare
258 * that number of procedures in the lists
259 */
260 if (len1 == len2) {
261 len = len1;
262 } else {
263 if (len1 < len2) {
264 len = len1;
265 } else {
266 len = len2;
267 }
268 }
269
270 /* analyze the list of procedures */
271 for(c=1;c<=len;c++){
272 proc1 = (struct InitProcedure *)gl_fetch(pl1,c);
273 proc2 = (struct InitProcedure *)gl_fetch(pl2,c);
274
275 /*
276 * compare names
277 */
278 if (CmpProcs(proc1,proc2)) {
279 *n = c;
280 return 1;
281 }
282 /*
283 * compare statement lists
284 * if lists are different, diff will contain the index of the first
285 * different statement. Use it if necessary
286 */
287 sl1 = ProcStatementList(proc1);
288 sl2 = ProcStatementList(proc2);
289 if (CompareStatementLists(sl1,sl2,&diff)) {
290 *n = c;
291 return 1;
292 }
293 }
294
295 /*
296 * If we get here and the number of elements in the list are equal,
297 * then the procedures are equal,
298 * else the index of the first different procedure is len + 1
299 */
300 if (len1 == len2) {
301 return 0;
302 } else {
303 *n = len+1;
304 return 1;
305 }
306
307 /* parse_id are not for comparison */
308 }

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22