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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 708 - (show annotations) (download) (as text)
Tue Jun 27 07:34:31 2006 UTC (17 years, 11 months ago) by johnpye
File MIME type: text/x-csrc
File size: 16119 byte(s)
Replaced some references to ascmalloc with ASC_NEW_ARRAY
1 /*
2 * anoncopy.c
3 * by Benjamin Allan
4 * September 08, 1997
5 * Part of ASCEND
6 * Version: $Revision: 1.3 $
7 * Version control file: $RCSfile: anoncopy.c,v $
8 * Date last modified: $Date: 1998/06/16 16:38:34 $
9 * Last modified by: $Author: mthomas $
10 *
11 * This file is part of the Ascend Language Interpreter.
12 *
13 * Copyright (C) 1998 Carnegie Mellon University
14 *
15 * The Ascend Language Interpreter is free software; you can
16 * redistribute it and/or modify it under the terms of the GNU
17 * General Public License as published by the Free Software
18 * Foundation; either version 2 of the License, or (at your option)
19 * any later version.
20 *
21 * The Ascend Language Interpreter is distributed in hope that it
22 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
23 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 * See the GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with the program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check
29 * the file named COPYING.
30 */
31
32 /*
33 * we really need to ditch some of this crap.
34 */
35 #include <time.h>
36 #include <stdarg.h>
37
38 #include <utilities/ascConfig.h>
39 #include <utilities/ascMalloc.h>
40 #include <utilities/ascPanic.h>
41 #include <general/pool.h>
42 #include <general/list.h>
43 #include <general/dstring.h>
44 #include "compiler.h"
45 #include "bit.h"
46 #include "symtab.h"
47 #include "fractions.h"
48 #include "dimen.h"
49 #include "functype.h"
50 #include "expr_types.h"
51 #include "instance_enum.h"
52 #include "stattypes.h"
53 #include "statement.h"
54 #include "child.h"
55 #include "type_desc.h"
56 #include "module.h"
57 #include "library.h"
58 #include "sets.h"
59 #include "setio.h"
60 #include "extfunc.h"
61 #include "extcall.h"
62 #include "dimen.h"
63 #include "forvars.h"
64 #include "exprs.h"
65 #include "name.h"
66 #include "nameio.h"
67 #include "vlist.h"
68 #include "slist.h"
69 #include "evaluate.h"
70 #include "value_type.h"
71 #include "statio.h"
72 #include "pending.h"
73 #include "find.h"
74 #include "relation_type.h"
75 #include "relation.h"
76 #include "logical_relation.h"
77 #include "logrelation.h"
78 #include "relation_util.h"
79 #include "logrel_util.h"
80 #include "instance_types.h"
81 #include "cmpfunc.h"
82 #include "instance_io.h"
83 #include "when.h"
84 #include "case.h"
85 #include "when_util.h"
86 #include "select.h"
87 #include "atomvalue.h"
88 #include "arrayinst.h"
89 #include "copyinst.h"
90 #include "createinst.h"
91 #include "destroyinst.h"
92 #include "extinst.h"
93 #include "visitinst.h"
94 #include "instquery.h"
95 #include "mathinst.h"
96 #include "mergeinst.h"
97 #include "parentchild.h"
98 #include "refineinst.h"
99 #include "check.h"
100 #include "instance_name.h"
101 #include "setinstval.h"
102 #include "tmpnum.h"
103 #include "anontype.h"
104 #include "instmacro.h" /* some of this should move to relation.c */
105 #include "instantiate.h"
106
107 #ifndef lint
108 static CONST char anoncopyModuleId[] = "$Id: anoncopy.c,v 1.3 1998/06/16 16:38:34 mthomas Exp $";
109 #endif
110
111 #if ATDEBUG
112 #include "relation_io.h"
113 static struct Instance *g_Pass2AddAnonProtoVar_visit_root = 0;
114 #endif
115
116 /* forward declaration */
117 static struct Instance *
118 CopyAnonRelationArrayInstance(struct Instance *, struct Instance *,
119 unsigned long, struct gl_list_t *);
120
121 /*
122 * Create a new relation instance based on protorel,
123 * and attach it to newparent, copying details by reference.
124 * If newparent is NULL, no attachment done. This should only
125 * be the case when the newparent is an array and will be
126 * OTHERWISE established.
127 */
128 static
129 struct Instance *CopyAnonRelationInstance(struct Instance *newparent,
130 struct Instance *protorel,
131 unsigned long pos,
132 struct gl_list_t *copyvars)
133 {
134 register struct RelationInstance *src,*result;
135 struct relation *rel;
136 enum Expr_enum type;
137 register unsigned long size;
138
139 #if TIMECOMPILER
140 /* hack to get some statistics. BAA */
141 extern int g_CopyAnonRelation;
142 g_CopyAnonRelation++;
143 #endif
144
145 assert(InstanceKind(protorel) == REL_INST);
146 src = RELN_INST(protorel);
147 size = GetByteSize(src->desc);
148 result = RELN_INST(ascmalloc((unsigned)size));
149 AssertMemory(result);
150
151 ascbcopy((char *)src,(char *)result,(int)size);
152 result->parent[0] = NULL;
153 result->parent[1] = NULL;
154 result->whens = NULL;
155 result->logrels = NULL;
156 result->anon_flags = 0x0;
157 CopyTypeDesc(result->desc);
158 result->ptr = NULL;
159
160 RedoChildPointers(ChildListLen(GetChildList(result->desc)),
161 INST(result),REL_CHILD(result,0),
162 protorel,REL_CHILD(protorel,0));
163 CheckChildCopies(ChildListLen(GetChildList(result->desc)),
164 REL_CHILD(result,0));
165
166 rel = CopyAnonRelationByReference(protorel,INST(result),copyvars);
167 type = GetInstanceRelationType(protorel);
168 SetInstanceRelation(INST(result),rel,type);
169
170 if (newparent !=NULL) {
171 LinkToParentByPos(newparent,INST(result),pos);
172 }
173 return INST(result);
174 }
175
176 static
177 struct gl_list_t *CopyAnonArrayChildPtrs(struct Instance *newparent,
178 struct gl_list_t *list,
179 struct gl_list_t *copyvars)
180 {
181 register struct gl_list_t *result;
182 register unsigned long length,c;
183 register struct ArrayChild *new,*src;
184 if (list!=NULL){
185 length = gl_length(list);
186 if (length) {
187 result = gl_create(length);
188 for(c=1;c<=length;c++) {
189 src = (struct ArrayChild *)gl_fetch(list,c);
190 new = MALLOCPOOLAC;
191 *new = *src;
192 /* new->inst points to the proto of this array entry. need to fix */
193 if (new->inst !=NULL) {
194 switch (InstanceKind(new->inst)) {
195 /* should add an lrel case here */
196 case REL_INST:
197 new->inst = CopyAnonRelationInstance(NULL,new->inst,c,
198 copyvars);
199 AddParent(new->inst,newparent);
200 break;
201 case ARRAY_ENUM_INST:
202 case ARRAY_INT_INST:
203 new->inst = CopyAnonRelationArrayInstance(NULL, new->inst,
204 0, copyvars);
205 AddParent(new->inst,newparent);
206 break;
207 default:
208 Asc_Panic(2,"CopyAnonArrayChildPtrs","Non-relation array child!");
209 }
210 }
211 gl_append_ptr(result,(VOIDPTR)new);
212 }
213 gl_set_sorted(result, TRUE); /* because the originals were, by name */
214 return result;
215 } else {
216 return gl_create(0);
217 }
218 } else {
219 return NULL;
220 }
221 }
222
223 /*
224 * this function recurses, and probably belongs in arrayinst.c
225 * If newparent is not NULL, links result to it automatically.
226 */
227 static
228 struct Instance *
229 CopyAnonRelationArrayInstance(struct Instance *newparent,
230 struct Instance *proto,
231 unsigned long pos,
232 struct gl_list_t *copyvars)
233 {
234 register struct ArrayInstance *ary,*result;
235 AssertMemory(proto);
236 ary = ARY_INST(proto);
237 result = ARY_INST(ascmalloc(sizeof(struct ArrayInstance)));
238 AssertMemory(result);
239 result->t = ary->t;
240 result->pending_entry = NULL;
241 result->desc = ary->desc;
242 CopyTypeDesc(result->desc);
243 result->indirected = ary->indirected;
244 result->visited = 0;
245 result->tmp_num = 0;
246 result->parents = gl_create(AVG_PARENTS);
247 result->children = CopyAnonArrayChildPtrs(INST(result),
248 ary->children,
249 copyvars);
250 if (newparent != NULL) {
251 LinkToParentByPos(newparent,INST(result),pos);
252 }
253 return INST(result);
254 }
255
256 /* Collects the index path to any instance w/tmpnum != 0
257 * and resets the tmpnum of the index of the collected path in
258 * the index path list. Each collected path ends with a 0.
259 * Since we visit an instance exactly once,
260 * The memory needed here is freed all at once, so we can
261 * play a pooling game as needed. Then we will need to make
262 * a little struct that holds the buffer and indexpaths.
263 */
264 static
265 void Pass2AddAnonProtoVar(struct Instance *i,
266 unsigned long *llist,
267 int activelen,
268 struct gl_list_t *indexpaths)
269 {
270 unsigned long int *indices;
271 int j;
272 if (GetTmpNum(i)) {
273 assert(InstanceKind(i) == REAL_ATOM_INST);
274 indices = (unsigned long int *)
275 ascmalloc((activelen+1)*sizeof(unsigned long));
276 if (indices==NULL) {
277 FPRINTF(ASCERR,"Pass2AddAnonProtoVar: Insufficient memory.");
278 return;
279 }
280 for (j = 0; j < activelen ; j++) {
281 indices[j] = llist[j];
282 }
283 indices[activelen] = 0L;
284 gl_append_ptr(indexpaths,(void *)indices);
285 SetTmpNum(i,gl_length(indexpaths));
286 #if ATDEBUG
287 FPRINTF(ASCERR,"Pass2AddAnonProtoVar: found index path %lu for ", gl_length(indexpaths));
288 WriteInstanceName(ASCERR, i,g_Pass2AddAnonProtoVar_visit_root);
289 FPRINTF(ASCERR,"\n");
290 FPRINTF(ASCERR,"indices(0-terminated) =");
291 for (j = 0 ; j <= activelen; j++) {
292 FPRINTF(ASCERR,"%lu ", indices[j]);
293 }
294 FPRINTF(ASCERR,"\n");
295 #endif
296
297 }
298 }
299
300 /*
301 * sets to 1 the tmpnums of all vars occuring in any relation visited.
302 */
303 static
304 void Pass2LabelAnonProtoVars(struct Instance *i)
305 {
306 if (InstanceKind(i)==REL_INST) {
307 CONST struct relation *r;
308 r = GetInstanceRelationOnly(i);
309 if (r != NULL) {
310 unsigned long c,len;
311 len = NumberVariables(r);
312 for (c = 1; c <= len; c++) {
313 /* just as fast to set as it is to check whether already set */
314 SetTmpNum(RelationVariable(r,c),1);
315 }
316 }
317 }
318 }
319 /*
320 * i must be a MODEL.
321 * This function returns a gl_list of index paths through i
322 * to reach the vars occuring in relations (or relation arrays) of i.
323 * Each var will only occur once in the path list returned.
324 * An index path can be followed through any instance isomorphic to i
325 * and will end at a variable semantically equivalent to the one
326 * in i that generated the path.
327 * At the expense of a visit tree call (which we need anyway)
328 * this returns the list unsorted and never searched.
329 *
330 * At present the list returned should be destroyed with
331 * gl_free_and_destroy. This may change if we find ourselves
332 * in malloc/free hell from constructing index paths.
333 */
334 struct gl_list_t *Pass2CollectAnonProtoVars(struct Instance *i)
335 {
336 unsigned long c,len;
337 struct Instance *ch;
338 unsigned int indexlen = 40;
339 unsigned long *indices;
340 struct gl_list_t *result;
341
342 assert(InstanceKind(i)==MODEL_INST);
343 #if ATDEBUG
344 FPRINTF(ASCERR,"Pass2AddAnonProtoVar: Labeling vars for model:\n ");
345 WriteInstanceName(ASCERR,i,NULL);
346 FPRINTF(ASCERR,"\n");
347 #endif
348 len = NumberChildren(i);
349 result = gl_create(100);
350 indices = ASC_NEW_ARRAY(unsigned long,indexlen);
351 if (indices == NULL || result == NULL) {
352 FPRINTF(ASCERR,"Pass2CollectAnonProtoVars: Insufficient memory\n");
353 return result;
354 }
355 if (len==0) {
356 return result;
357 }
358 /* Don't visit whole tree of i to label relation vars, just local rels.
359 * Set tmpnums of vars in local relations to LONG_MAX-1 and of all other
360 * instances to 0.
361 */
362 ZeroTmpNums(i,0);
363 for (c=1; c<= len; c++) {
364 ch = InstanceChild(i,c);
365 switch (InstanceKind(ch)) {
366 case REL_INST:
367 #if ATDEBUG
368 FPRINTF(ASCERR,"Pass2AddAnonProtoVar: Labeling vars for equation:\n ");
369 WriteRelation(ASCERR,ch,i);
370 FPRINTF(ASCERR,"\n");
371 #endif
372 Pass2LabelAnonProtoVars(ch);
373 break;
374 case ARRAY_INT_INST:
375 case ARRAY_ENUM_INST:
376 if (GetBaseType(GetArrayBaseType(InstanceTypeDesc(ch)))
377 == relation_type) {
378 #if ATDEBUG
379 FPRINTF(ASCERR,"Pass2AddAnonProtoVar: Labeling vars for an eqn array: \n ");
380 WriteInstanceName(ASCERR,ch,i);
381 FPRINTF(ASCERR,"\n");
382 #endif
383 SilentVisitInstanceTree(ch,(VisitProc)Pass2LabelAnonProtoVars,0,0);
384 }
385 break;
386 default:
387 break;
388 }
389 }
390 /*
391 * Now do an indexed visit to collect the index paths to var with
392 * tmpnum != 0. Set the tmpnum of each collected var to the index
393 * in the path.
394 */
395 #if ATDEBUG
396 g_Pass2AddAnonProtoVar_visit_root = i;
397 #endif
398 IndexedVisitInstanceTree(i,(IndexedVisitProc)Pass2AddAnonProtoVar,
399 0,0,&indices,&indexlen,result);
400 ascfree(indices);
401 return result;
402 }
403
404 /*
405 * deallocate the indexpathlist collected by Pass2CollectAnonProtoVars.
406 */
407 void Pass2DestroyAnonProtoVars(struct gl_list_t *indexpathlist)
408 {
409 gl_free_and_destroy(indexpathlist);
410 }
411
412 /*
413 * This function takes the index paths from Pass2CollectAnonProtoVars(proto)
414 * and follows the indices through i which must be of the same anonymous
415 * type to build a gl_list of ATOM pointers indexed in the same way
416 * as the atoms in proto are tmpnum'd. The tmpnums of i are irrelevant.
417 */
418 static
419 struct gl_list_t *Pass2CollectAnonCopyVars(struct gl_list_t *protovars,
420 struct Instance *i)
421 {
422 struct gl_list_t *result;
423 struct Instance *ch;
424 unsigned long c,len;
425 unsigned long *indexpath;
426 int j;
427
428 #if ATDEBUG
429 FPRINTF(ASCERR,"Pass2CollectAnonCopyVars: collecting vars for model:\n ");
430 WriteInstanceName(ASCERR,i,NULL);
431 FPRINTF(ASCERR,"\n");
432 #endif
433 assert(InstanceKind(i)==MODEL_INST);
434 len = gl_length(protovars);
435 result = gl_create(len);
436 for (c=1; c <= len; c++) {
437 /* find var c in similar instance */
438 indexpath = ( unsigned long *)gl_fetch(protovars,c);
439 ch = i;
440 for (j = 0; indexpath[j] != 0; j++) {
441 ch = InstanceChild(ch,indexpath[j]);
442 assert(ch!=NULL);
443 #if ATDEBUG
444 FPRINTF(ASCERR,"Pass2CollectAnonCopyVars: child link %d = %lu to ",j,indexpath[j]);
445 WriteInstanceName(ASCERR,ch,i);
446 FPRINTF(ASCERR,"\n");
447 #endif
448 }
449 gl_append_ptr(result,ch);
450 assert(InstanceKind(ch) == REAL_ATOM_INST);
451 #if ATDEBUG
452 WriteInstanceName(ASCERR,ch,i);
453 FPRINTF(ASCERR,"\n");
454 #endif
455 }
456 return result;
457 }
458
459 static
460 void CopyAnonDummyInstance(struct Instance *parent,
461 unsigned long pos,
462 struct TypeDescription *def)
463 {
464 struct Instance *inst;
465 inst = ShortCutMakeUniversalInstance(def);
466 if (inst==NULL) {
467 inst = CreateDummyInstance(def);
468 }
469 LinkToParentByPos(parent,inst,pos);
470 }
471
472 /*
473 * Copies all the local relations (including those in arrays)
474 * of the MODEL instance proto to the instance i using only
475 * local information. No global information is needed, but
476 * we need to arrange that the tmpnums all start and end 0
477 * so we can avoid extra 0ing of them.
478 */
479 void Pass2CopyAnonProto(struct Instance *proto,
480 struct BitList *protoblist,
481 struct gl_list_t *protovarindices,
482 struct Instance *i)
483 {
484 struct BitList *blist;
485 struct gl_list_t *copyvars;
486 struct Instance *ch;
487 unsigned long nch,c;
488
489 blist = InstanceBitList(i);
490 /* copy bitlist from proto to i since they must be identical
491 * when we are done making them identical by copying newly
492 * made relations. Likewise, remove from pending list if needed.
493 */
494 OverwriteBList(protoblist,blist);
495 if (!InstanceInList(proto) && InstanceInList(i)) {
496 /* for now, this if will always pass */
497 RemoveInstance(i);
498 }
499 #if ATDEBUG
500 FPRINTF(ASCERR,"Pass2CollectAnonCopyVars: Collecting vars for ");
501 WriteInstanceName(ASCERR,i,NULL);
502 FPRINTF(ASCERR,"\n");
503 #endif
504 copyvars = Pass2CollectAnonCopyVars(protovarindices,i);
505 /* Now copy local relations, and wherever a var is needed
506 * in the copy, use the tmpnum of the original var in proto to
507 * look up the equivalent var in the copyvars found from i.
508 */
509 nch = NumberChildren(proto);
510 for (c = 1; c <= nch; c++) {
511 ch = InstanceChild(proto,c);
512 if (ch != NULL && InstanceChild(i,c) == NULL) {
513 switch (InstanceKind(ch)) {
514 case REL_INST:
515 CopyAnonRelationInstance(i,ch,c,copyvars);
516 break;
517 case ARRAY_ENUM_INST:
518 case ARRAY_INT_INST:
519 CopyAnonRelationArrayInstance(i,ch,c,copyvars);
520 break;
521 case DUMMY_INST:
522 CopyAnonDummyInstance(i,c,InstanceTypeDesc(ch));
523 break;
524 default:
525 break;
526 }
527 }
528 }
529 gl_destroy(copyvars);
530 }
531

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