/[ascend]/trunk/ascend/compiler/link.c
ViewVC logotype

Contents of /trunk/ascend/compiler/link.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2565 - (show annotations) (download) (as text)
Fri Feb 3 23:25:40 2012 UTC (10 years, 5 months ago) by jpye
File MIME type: text/x-csrc
File size: 26679 byte(s)
cleanup
1 /* ASCEND modelling environment
2 Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
3 Copyright (C) 2006 Carnegie Mellon University
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 *//**
20 @file
21 Link Routines.
22
23 *//*
24 by Dante Stroe
25 Created: 07/07/2009
26 */
27
28
29
30 #include "link.h"
31 #include <stdarg.h>
32 #include <ascend/general/list.h>
33 #include <ascend/general/ascMalloc.h>
34 #include <ascend/general/panic.h>
35 #include <ascend/utilities/error.h>
36
37 #include "cmpfunc.h"
38 #include "find.h"
39 #include "forvars.h"
40 #include "instance_types.h"
41 #include "instance_enum.h"
42 #include "instmacro.h"
43 #include "instquery.h"
44 #include "statement.h"
45 #include "stattypes.h"
46 #include "stdio.h"
47 #include "symtab.h"
48 #include "visitinst.h"
49 #include "vlist.h"
50 #include "name.h"
51 #include "instance_io.h"
52
53
54
55 /**< DS: beginning of LINK functions *******/
56 /* implemented functions related to the LINK statements, probably they shouldn't be here*/
57
58 /**
59 Find instances: Make sure at least one thing is found for each name item
60 on list (else returned list will be NULL) and return the collected instances.
61 DS: it returns a non-flattened list of the instances
62 */
63 static struct gl_list_t *FindInstsNonFlat(
64 struct Instance *inst,CONST struct VariableList *list,enum find_errors *err
65 ){
66 struct gl_list_t *result,*temp;
67
68 result = gl_create(AVG_LINKS_INST);
69 while(list!=NULL){
70 temp = FindInstances(inst,NamePointer(list),err);
71 if (temp==NULL){
72 gl_destroy(result);
73 return NULL;
74 }
75 gl_append_ptr(result,temp);
76 list = NextVariableNode(list);
77 }
78 return result;
79 }
80
81 /**
82 Find instances: Make sure at least one thing is found for each name item
83 on list (else returned list will be NULL) and return the collected instances.
84 DS: it returns a flattened list of the instances
85 */
86 static struct gl_list_t *FindInsts(
87 struct Instance *inst, CONST struct VariableList *list, enum find_errors *err
88 ){
89 struct gl_list_t *result,*temp;
90 unsigned c,len;
91 result = gl_create(AVG_LINKS_INST);
92 while(list!=NULL){
93 temp = FindInstances(inst,NamePointer(list),err);
94 if (temp==NULL){
95 gl_destroy(result);
96 return NULL;
97 }
98 len = gl_length(temp);
99 for(c=1;c<=len;c++) {
100 gl_append_ptr(result,gl_fetch(temp,c));
101 }
102 gl_destroy(temp);
103 list = NextVariableNode(list);
104 }
105 return result;
106 }
107
108
109 /**
110 DS: Helper function that compares a key and a list of instances with a link_entry
111 @return 0 if the tuple (key, instances) is the same as the link entry,
112 otherwise return 1.
113 */
114 static int CmpLinkEntry(symchar *key, struct VariableList *vlist,struct link_entry_t *linkEntry){
115 /* DS: Note: the key_cache and the u.vl were used instead of
116 LINKStatKey(linkEntry->u.statptr) and LINKStatVlist(linkEntry->u.statptr),
117 because for some reason the pointer to the statement becomes NULL after the
118 statement is executed */
119
120 struct VariableList *linkEntry_vlist;
121
122 if(CmpSymchar(key,linkEntry->key_cache) != 0) {
123 /* if the keys are different, the LINKs are different */
124 return 1;
125 }
126
127 linkEntry_vlist = linkEntry->u.vl;
128 if(VariableListLength(vlist) != VariableListLength(linkEntry_vlist)) {
129 /* if the number of variables linked are different, the LINKs are different */
130 return 1;
131 }
132
133 if(CompareVariableLists(vlist,linkEntry_vlist) != 0) { /* if the variables linked are different, the LINKs are different */
134 return 1; /* DS Note: it is ordered biased */
135 }
136
137 return 0; /* (key, instances) is the same as linkEntry */
138 }
139
140
141 void CollectLinkTypes(struct Instance *model, struct gl_list_t *result)
142 {
143 struct TypeDescription *modelType;
144 struct link_entry_t *link_entry;
145 symchar *key, *key_result;
146 int c1, c2, len_table, len_result, existent;
147
148 modelType = InstanceTypeDesc(model);
149 if(modelType->t == model_type) {
150
151 /* probe instance given (if appropriate kind) to get link info needed
152 from the TypeDescription link_table */
153 len_table = gl_length(modelType->u.modarg.link_table);
154
155 for(c1=1;c1<=len_table;c1++){
156 link_entry = (struct link_entry_t *)gl_fetch(modelType->u.modarg.link_table,c1);
157 if(link_entry->key_cache == NULL){ /**< in case the cache is empty we need to find keys from the statements */
158 key = LINKStatKey(link_entry->u.statptr);
159 }else{
160 key = link_entry->key_cache;
161 }
162 // verify that any new info obtained is kept uniquely in the result list.(not efficient at all DS TODO)
163 len_result = gl_length(result);
164 existent = 0;
165 for(c2=1;c2<=len_result;c2++){
166 key_result = (symchar *)gl_fetch(result,c2);
167 if(CmpSymchar(key,key_result) == 0){
168 existent = 1;
169 }
170 }
171 if(!existent){
172 gl_append_ptr(result,(VOIDPTR)key);
173 }
174 }
175
176 /* probe instance given (if appropriate kind) to get link info needed
177 from the ModelInstances link_table */
178 len_table = gl_length(MOD_INST(model)->link_table);
179 for(c1=1;c1<=len_table;c1++){
180 link_entry = (struct link_entry_t *)gl_fetch(MOD_INST(model)->link_table,c1);
181 if(link_entry->key_cache == NULL){ /**< in case the cache is empty we need to find keys from the statements */
182 key = LINKStatKey(link_entry->u.statptr);
183 }else{
184 key = link_entry->key_cache;
185 }
186 /* verify that any new info obtained is kept uniquely in the result
187 list.(not efficient at all DS TODO) */
188 len_result = gl_length(result);
189 existent = 0;
190 for(c2=1;c2<=len_result;c2++){
191 key_result = (symchar *)gl_fetch(result,c2);
192 if(CmpSymchar(key,key_result) == 0){
193 existent = 1;
194 }
195 }
196 if(!existent){
197 gl_append_ptr(result,(VOIDPTR)key);
198 }
199 }
200 }
201 /*DS:If the instance or the child instance is not a model we do nothing
202 since a "link_table" is only present in the typedescription of a model (modarg) */
203 }
204
205
206 /** find all the keys in link table(s), optionally recursive. */
207 extern struct gl_list_t *getLinkTypes (struct Instance *model, int recursive){
208 struct gl_list_t *result = gl_create(AVG_LINKS);
209
210 if (recursive) {
211 VisitInstanceTreeTwo(model, (VisitTwoProc)CollectLinkTypes, 0,0, result);
212 }else{
213 CollectLinkTypes(model, result);
214 }
215 return result;
216 }
217
218
219 void CollectLinks(struct Instance *model, struct gl_list_t *result){
220 struct TypeDescription *modelType;
221 struct link_entry_t *link_entry, *link_entry_result;
222 int c1, c2, len_table, len_result, existent;
223
224 modelType = InstanceTypeDesc(model);
225 if(modelType->t == model_type) {
226
227 /* probe instance given (if appropriate kind) to get link info needed
228 from the TypeDescription link_table */
229 len_table = gl_length(modelType->u.modarg.link_table);
230 for(c1=1;c1<=len_table;c1++){
231 link_entry = (struct link_entry_t *)gl_fetch(modelType->u.modarg.link_table,c1);
232 // verify if the LINK is unique in the result list
233 len_result = gl_length(result);
234 existent = 0;
235
236 for(c2=1;c2<=len_result;c2++){
237 link_entry_result = (struct link_entry_t *)gl_fetch(result,c2);
238 if(CmpLinkEntry(link_entry->key_cache,link_entry->u.vl,link_entry_result) == 0){
239 existent = 1;
240 }
241 }
242 if(!existent){
243 gl_append_ptr(result,(VOIDPTR)link_entry);
244 }
245 }
246
247 /* probe instance given (if appropriate kind) to get link info needed
248 from the ModelInstance link_table */
249 len_table = gl_length(MOD_INST(model)->link_table);
250 for(c1=1;c1<=len_table;c1++){
251 link_entry = (struct link_entry_t *)gl_fetch(MOD_INST(model)->link_table,c1);
252 existent = 0;
253 // verify if the LINK is unique in the result list
254 len_result = gl_length(result);
255
256 for(c2=1;c2<=len_result;c2++){
257 link_entry_result = (struct link_entry_t *)gl_fetch(result,c2);
258 if(CmpLinkEntry(link_entry->key_cache,link_entry->u.vl,link_entry_result) == 0){
259 existent = 1;
260 }
261 }
262 if(!existent){
263 gl_append_ptr(result,(VOIDPTR)link_entry);
264 }
265 }
266 }
267 /*DS:If the instance or the child instance is not a model we do nothing since
268 a "link_table" is only present in the typedescription of a model (modarg) */
269 }
270
271
272 extern struct gl_list_t *getLinks(struct Instance *model
273 , symchar *target_key, int recursive
274 ){
275 struct gl_list_t *result = gl_create(AVG_LINKS); /**< DS: hardcoded for now but will eventually be a constant */
276 int c1, len_result;
277 struct link_entry_t *link_entry;
278
279 if(recursive){
280 VisitInstanceTreeTwo(model, (VisitTwoProc)CollectLinks, 0,0, result);
281 }else{
282 CollectLinks(model, result);
283 }
284
285 len_result = gl_length(result);
286
287 for(c1=1;c1<=len_result;c1++) {
288 link_entry = (struct link_entry_t *)gl_fetch(result,c1);
289 if(CmpSymchar(link_entry->key_cache,target_key) !=0 ){
290 gl_delete(result,c1,0); /* if the link entry does not have sought key we delete it from the result list */
291 len_result--;
292 }
293 }
294 return result;
295 }
296
297
298 /**<DS: get all links matching key, optionally recursive. */
299 extern struct gl_list_t *getLinksReferencing (struct Instance *model
300 , symchar* key, struct Instance *targetInstance, int recursive
301 ){
302 struct gl_list_t *link_instances,*result = gl_create(AVG_LINKS);
303 struct link_entry_t *link_entry;
304 struct Instance *inst;
305 enum find_errors err;
306 int c1, c2, len_result, len_inst, containsInst;
307
308 if(recursive){
309 VisitInstanceTreeTwo(model, (VisitTwoProc)CollectLinks, 0,0, result);
310 }else{
311 CollectLinks(model, result);
312 }
313
314 /* DS: get all the links that contain the target instance */
315 len_result = gl_length(result);
316 for(c1=1;c1<=len_result;c1++){
317 link_entry = (struct link_entry_t *)gl_fetch(result,c1);
318 if(link_entry->instances_cache == NULL ) {
319 link_instances = FindInsts(model,link_entry->u.vl,&err);
320 }else{
321 link_instances = link_entry->instances_cache;
322 }
323
324 len_inst = gl_length(link_instances);
325 containsInst = 0;
326 if(CmpSymchar(link_entry->key_cache,key) == 0){
327 for(c2=1;c2<=len_inst;c2++){
328 inst = (struct Instance *)gl_fetch(link_instances,c2);
329 if(inst == targetInstance){
330 containsInst = 1;
331 }
332 }
333 }
334 if(!containsInst){
335 gl_delete(result,c1,0); /* if the link entry does not have sought key we delete it from the result list */
336 len_result--;
337 }
338 }
339 return result;
340 }
341
342 /** DS: called by the ASCEND LINK command, both in the declarative and the non-declarative section */
343 extern void addLinkEntry(struct Instance *model, symchar *key
344 , struct gl_list_t *instances, struct Statement *stat, unsigned int declarative
345 ){
346 struct TypeDescription *modelType;
347 struct link_entry_t *link_entry, *old_link_entry;
348 struct for_var_t *ptr;
349 int c,len,exist = 0;
350
351 if(strcmp("TestingRoutine",SCP(key)) == 0) {
352 TestingRoutine(model);
353 return;
354 }
355
356 /* in case the LINK key is in fact the index of a for loop, the value of the
357 index at the current iteration is turned into a symchar and stored as a key*/
358 if(GetEvaluationForTable() && (ptr = FindForVar((struct gl_list_t *)GetEvaluationForTable(),key)) != NULL) {
359 char index_key[10];
360 sprintf(index_key,"%ld",GetForInteger(ptr));
361 key = AddSymbol(index_key);
362 }
363
364 if(declarative == 0) {
365 /* we first check if the LINK we are about to add isn't already present in the declartive LINK table */
366 len = gl_length(MOD_INST(model)->link_table);
367 for(c=1;c<=len;c++){
368 old_link_entry = (struct link_entry_t *)gl_fetch(MOD_INST(model)->link_table,c);
369 if(CmpLinkEntry(key,LINKStatVlist(stat),old_link_entry) == 0){
370 exist = 1;
371 }
372 }
373
374 if(!exist){
375
376 link_entry = (struct link_entry_t *)ascmalloc(sizeof(struct link_entry_t));
377 link_entry->key_cache = key;
378 link_entry->u.statptr = stat;
379 link_entry->link_type = stat->v.lnk.key_type;
380 link_entry->u.vl = LINKStatVlist(stat);
381 link_entry->instances_cache = instances;
382 link_entry->flags = 1;
383 link_entry->length = gl_length(instances);
384
385 /**< DS: in case the link entry is non-declartive, it is appended to the linktable in the model instance */
386 gl_append_ptr(MOD_INST(model)->link_table,(VOIDPTR)link_entry);
387 printf("\n non-declarative LINK no of instances in cache: %ld \n", gl_length(link_entry->instances_cache));
388 printf("\n non-declarative LINK key %s \n", SCP(key));
389 }else{
390 ERROR_REPORTER_HERE(ASC_USER_WARNING,"The LINK entry to-be added is already present in the non-declarative LINK table.");
391 }
392 }else{
393 if(link_entry->link_type == link_ignore) {
394 ignoreDeclLinkEntry(model,key,LINKStatVlist(stat));
395 }else {
396 modelType = InstanceTypeDesc(model);
397 len = gl_length(modelType->u.modarg.link_table);
398
399 for(c=1;c<=len;c++){
400 old_link_entry = (struct link_entry_t *)gl_fetch(modelType->u.modarg.link_table,c);
401 if(CmpLinkEntry(key,LINKStatVlist(stat),old_link_entry) == 0){
402 exist = 1;
403 }
404 }
405
406 if(!exist){
407 link_entry = (struct link_entry_t *)ascmalloc(sizeof(struct link_entry_t));
408 link_entry->key_cache = key;
409 link_entry->u.statptr = stat;
410 link_entry->link_type = stat->v.lnk.key_type;
411 link_entry->u.vl = LINKStatVlist(stat);
412 link_entry->instances_cache = instances;
413 link_entry->flags = 1;
414 link_entry->length = gl_length(instances);
415
416 /**< DS: in case the link entry is declarative, it is appeneded to the linktable in the model type description */
417 gl_append_ptr(modelType->u.modarg.link_table,(VOIDPTR)link_entry);
418
419 /* DS: testing purposes: */
420 printf("\n declarative LINK no of instances in cache: %ld \n", gl_length(link_entry->instances_cache));
421 printf("\n declarative LINK key %s \n", SCP(key));
422 }else{
423 ERROR_REPORTER_HERE(ASC_USER_WARNING,"The LINK entry to-be added is already present in the declarative LINK table.");
424 }
425 }
426 }
427 }
428
429 extern void ignoreDeclLinkEntry(struct Instance *model
430 , symchar *key, struct VariableList *vlist
431 ){
432 /*DS: used in case the 'ignore' key is used for a declarative link */
433 struct TypeDescription *modelType;
434 struct link_entry_t *link_entry;
435 modelType = InstanceTypeDesc(model);
436 int c, len, exist = 0;
437
438 len = gl_length(modelType->u.modarg.link_table);
439 printf("\n declarative link_table size %d\n",len);
440 for(c=1;c<=len;c++){
441 link_entry = (struct link_entry_t *)gl_fetch(modelType->u.modarg.link_table,c);
442 if (CmpLinkEntry(key,vlist,link_entry) == 0) {
443 exist = 1;
444 printf("\n ignored LinkEntry from declarative link_table \n");
445 gl_delete(modelType->u.modarg.link_table,c,1);
446 len--;
447 }
448 }
449 len = gl_length(modelType->u.modarg.link_table);
450 printf("\n new declarative link_table size %d\n",len);
451
452 if(!exist){
453 ERROR_REPORTER_HERE(ASC_USER_ERROR,"The LINK entry to-be ignored does not exist.");
454 }
455 }
456
457 /**
458 DS: (current Implementation) check if the the non-declarative or declarative
459 link table contains any of the instances in the list under the given key, if
460 so remove them from the entries
461 */
462 extern void removeLinkEntry(struct Instance *model
463 , symchar *key, struct VariableList *vlist
464 ){
465 /* used when called by the UNLINK command in the METHODS section by ASCEND */
466 struct link_entry_t *link_entry;
467 struct for_var_t *ptr;
468 int c, len, exist = 0;
469
470
471 printf("\n execute removeLinkEntry \n");
472
473 /* in case the LINK key is in fact the index of a for loop, the value of
474 the index at the current iteration is turned into a symchar and stored as a key*/
475 if(GetEvaluationForTable() && (ptr = FindForVar((struct gl_list_t *)GetEvaluationForTable(),key)) != NULL) {
476 char index_key[10];
477 sprintf(index_key,"%ld",GetForInteger(ptr));
478 key = AddSymbol(index_key);
479 }
480
481 len = gl_length(MOD_INST(model)->link_table);
482 printf("\n non-declarative link_table size %d\n",len);
483 for(c=1;c<=len;c++){
484 link_entry = (struct link_entry_t *)gl_fetch(MOD_INST(model)->link_table,c);
485 if(CmpLinkEntry(key,vlist,link_entry) == 0) {
486 exist = 1;
487 printf("\n removed LinkEntry from non-declarative link_table\n");
488 gl_delete(MOD_INST(model)->link_table,c,1); /* we also deallocate the memory allocated for the link_entry */
489 len--;
490 }
491 }
492
493 len = gl_length(MOD_INST(model)->link_table);
494 printf("\n new non-declarative link_table size %d\n",len);
495
496
497 if(!exist){
498 ERROR_REPORTER_HERE(ASC_USER_ERROR,"The LINK entry to-be removed does not exist.");
499 }
500 }
501
502
503 /** DS: (current Implementation) check if the the non-declarative link table contains any of the instances in the list under the given key, if so remove them from the entries */
504 extern void removeNonDeclarativeLinkEntry(struct Instance *model
505 , symchar *key, int recursive
506 ){
507 struct gl_list_t *result=gl_create(AVG_LINKS);
508 struct link_entry_t *link_entry;
509 int c=1, len;
510
511
512 if (recursive) {
513 VisitInstanceTreeTwo(model, (VisitTwoProc)CollectLinks, 0,0, result);
514 }else{
515 CollectLinks(model, result);
516 }
517
518 printf("\n execute removeNonDeclarativeLinkEntry \n");
519 len = gl_length(MOD_INST(model)->link_table);
520 printf("\n non-declarative link_table size: %d\n",len);
521 while(len != 0 || c<=len) {
522 link_entry = (struct link_entry_t *)gl_fetch( MOD_INST(model)->link_table,c);
523
524 if ((key == NULL || CmpSymchar(key,link_entry->key_cache) == 0) && isDeclarative(model,link_entry) == 0 ) { /*DS: if the key is NULL then remove all entries from the link_table */
525 printf("\n execute removed LinkEntry \n");
526 gl_delete(MOD_INST(model)->link_table,c,1);
527 len--;
528 }else{
529 c++;
530 }
531 }
532
533 len = gl_length(MOD_INST(model)->link_table);
534 printf("\n non-declarative link_table size: %d\n",len);
535 }
536
537
538 const struct gl_list_t *getLinkInstances(struct Instance *inst
539 , struct link_entry_t *link_entry,int status
540 ){
541 struct gl_list_t *result = gl_create(AVG_LINKS_INST);
542 enum find_errors err;
543
544 result = FindInstsNonFlat(inst,link_entry->u.vl,&err);
545
546 if (result==NULL) {
547 switch(err){
548 case impossible_instance:
549 ERROR_REPORTER_HERE(ASC_USER_ERROR,"LINK entry contains imposible instance name");
550 default:
551 ERROR_REPORTER_HERE(ASC_USER_ERROR,"incomplete instances in LINK entry");
552 }
553 }
554 return result;
555 }
556
557
558 const struct gl_list_t *getLinkInstancesFlat(struct Instance *inst
559 , struct link_entry_t *link_entry,int status
560 ){
561 struct gl_list_t *result = gl_create(AVG_LINKS_INST);
562 enum find_errors err;
563 if(link_entry->instances_cache == NULL) {
564 result = FindInsts(inst,link_entry->u.vl,&err);
565 if (result==NULL) {
566 switch(err){
567 case impossible_instance:
568 ERROR_REPORTER_HERE(ASC_USER_ERROR,"LINK entry contains impossible instance name");
569 default:
570 ERROR_REPORTER_HERE(ASC_USER_ERROR,"incomplete instances in LINK entry");
571 /* statement is not ready to be executed */
572 }
573 }
574 return result;
575 }else{
576 result = link_entry->instances_cache;
577 }
578 return result;
579 }
580
581
582 /** DS: get the list (link_table) with all the declarative link entries located in the TypeDescription */
583 extern struct gl_list_t *getLinkTableDeclarative(struct Instance *model){
584 struct TypeDescription *modelType;
585 modelType = InstanceTypeDesc(model);
586
587 if(modelType->t == model_type) {
588 return modelType->u.modarg.link_table;
589 }else{
590 return NULL;
591 ERROR_REPORTER_HERE(ASC_USER_WARNING,"the getLinkTableDeclarative procedure is called by a non-model instance");
592 }
593 }
594
595
596 /** DS: get the list (link_table) with all the non-declarative link entries located in the ModelInstance */
597 extern struct gl_list_t *getLinkTableProcedural(struct Instance *model){
598 struct TypeDescription *modelType;
599 modelType = InstanceTypeDesc(model);
600 if(modelType->t == model_type) {
601 return MOD_INST(model)->link_table;
602 }else{
603 return NULL;
604 ERROR_REPORTER_HERE(ASC_USER_WARNING,"the getLinkTableProcedural procedure is called by a non-model instance");
605 }
606 }
607
608
609 extern int isDeclarative(struct Instance* model, struct link_entry_t *target_link_entry){
610 struct TypeDescription *modelType;
611 struct link_entry_t *link_entry;
612 int c, len;
613
614 /* DS: get all the links that contain the target instance from the declarative part (i.e. stored in the model TypeDescription) */
615 modelType = InstanceTypeDesc(model);
616 len = gl_length(modelType->u.modarg.link_table);
617
618 for(c=1;c<=len;c++){
619 link_entry = (struct link_entry_t *)gl_fetch(modelType->u.modarg.link_table,c);
620 if(CmpLinkEntry(target_link_entry->key_cache,target_link_entry->u.vl,link_entry) == 0) {
621 return 1;
622 }
623 }
624 return 0;
625 }
626
627
628 extern void clearLinkCache(struct Instance* model){
629 struct gl_list_t* link_table;
630 struct link_entry_t *link_entry;
631 int c,len;
632
633 link_table = getLinkTableDeclarative(model);
634 len = gl_length(link_table);
635 for(c=1;c<=len;c++) {
636 link_entry = gl_fetch(link_table,c);
637 link_entry->instances_cache = NULL;
638 }
639
640 link_table = getLinkTableProcedural(model);
641 len = gl_length(link_table);
642 for(c=1;c<=len;c++) {
643 link_entry = gl_fetch(link_table,c);
644 link_entry->instances_cache = NULL;
645 }
646 }
647
648 extern void populateLinkCache(struct Instance* model){
649 struct gl_list_t *link_table;
650 struct link_entry_t *link_entry;
651 enum find_errors err;
652 int c,len;
653
654 link_table = getLinkTableDeclarative(model);
655 len = gl_length(link_table);
656 for(c=1;c<=len;c++) {
657 link_entry = gl_fetch(link_table,c);
658 link_entry->instances_cache = FindInsts(model,link_entry->u.vl,&err);
659 if (link_entry->instances_cache==NULL) {
660 switch(err){
661 case impossible_instance:
662 ERROR_REPORTER_HERE(ASC_USER_ERROR,"LINK statement contains an impossible instance name (populateLinkCache)");
663 default:
664 ERROR_REPORTER_HERE(ASC_USER_ERROR,"Incomplete instances in LINK (populateLinkCache)");
665 }
666 }
667 }
668
669 link_table = getLinkTableProcedural(model);
670 len = gl_length(link_table);
671 for(c=1;c<=len;c++) {
672 link_entry = gl_fetch(link_table,c);
673 link_entry->instances_cache = FindInsts(model,link_entry->u.vl,&err);
674 if (link_entry->instances_cache==NULL) {
675 switch(err){
676 case impossible_instance:
677 ERROR_REPORTER_HERE(ASC_USER_ERROR,"LINK statement contains an impossible instance name (populateLinkCache)");
678 default:
679 ERROR_REPORTER_HERE(ASC_USER_ERROR,"Incomplete instances in LINK (populateLinkCache)");
680 }
681 }
682 }
683 }
684
685
686 extern int getOdeType(struct Instance *model ,struct Instance *inst){
687
688 struct link_entry_t *link_entry;
689 struct gl_list_t *der_links,*independent_links;
690 symchar *der_key,*independent_key;
691 CONST struct VariableList *var;
692 int i,k,maxorder;
693
694 der_key = AddSymbol("ode");
695 der_links = getLinks(model,der_key,0);
696
697 for(i=1;i<=gl_length(der_links);i++) {
698 link_entry = (struct link_entry_t*) gl_fetch(der_links,i);
699 var = link_entry->u.vl;
700
701 maxorder = link_entry->length;
702 k = 0;
703 while(var!=NULL){
704 char *s = WriteInstanceNameString(inst,model);
705 int c = strcmp(SCP(SimpleNameIdPtr(NamePointer(var))),s);
706 ASC_FREE(s);
707 if(c == 0 ) {
708 gl_destroy(der_links);
709 return maxorder - k;
710 }
711 k++;
712 var = NextVariableNode(var);
713 }
714 }
715
716 gl_destroy(der_links);
717 independent_key = AddSymbol("independent");
718 independent_links = getLinks(model,independent_key,0);
719
720 for(i=1;i<=gl_length(independent_links);i++) {
721 link_entry = (struct link_entry_t*) gl_fetch(independent_links,i);
722 var = link_entry->u.vl;
723
724 k = 0;
725 while(var!=NULL){
726 char *s = WriteInstanceNameString(inst,model);
727 int c = strcmp(SCP(SimpleNameIdPtr(NamePointer(var))),s);
728 ASC_FREE(s);
729 if(c == 0 ) {
730 gl_destroy(independent_links);
731 return -1;
732 }
733 k++;
734 var = NextVariableNode(var);
735 }
736 }
737
738 gl_destroy(independent_links);
739 return 0;
740 }
741
742 extern int getOdeId(struct Instance *model,struct Instance *inst){
743 struct link_entry_t *link_entry;
744 struct gl_list_t *der_links;
745 symchar *der_key;
746 CONST struct VariableList *var;
747 int i;
748
749 der_key = AddSymbol("ode");
750 der_links = getLinks(model,der_key,0);
751
752 for(i=1;i<=gl_length(der_links);i++) {
753 CONSOLE_DEBUG("Inside for");
754 link_entry = (struct link_entry_t*) gl_fetch(der_links,i);
755 var = link_entry->u.vl;
756
757 while(var!=NULL){
758 char *s = WriteInstanceNameString(inst,model);
759 int c = strcmp(SCP(SimpleNameIdPtr(NamePointer(var))),s);
760 ASC_FREE(s);
761 if(c == 0){
762 gl_destroy(der_links);
763 return i;
764 }
765 var = NextVariableNode(var);
766 }
767 }
768 gl_destroy(der_links);
769 return 0;
770 }
771
772
773 /**< DS: End of LINK functions *******/
774
775 /* function that tests the LINK functions implemented - prints the output in the console */
776 void TestingRoutine(struct Instance *model)
777 {
778 struct TypeDescription *modelType;
779 modelType = InstanceTypeDesc(model);
780 int c1, len1, len2;
781
782 /* test getLinkTypes */
783 struct gl_list_t *linkTypes;
784 symchar *keyc1;
785 linkTypes = getLinkTypes(model,0);
786 len1 = gl_length(linkTypes);
787 CONSOLE_DEBUG("\n number of unique link types: %d \n",len1);
788 CONSOLE_DEBUG("\n The unique link keys are: ");
789 for(c1=1;c1<=len1;c1++){
790 keyc1= (symchar *)gl_fetch(linkTypes,c1);
791 CONSOLE_DEBUG("%s ",SCP(keyc1));
792 }
793 CONSOLE_DEBUG("\n");
794
795 /* test getLinks */
796 struct gl_list_t *links;
797 struct link_entry_t *lnk;
798 struct Instance *i1;
799 links = getLinks(model,keyc1,0);
800 len2 = gl_length(links);
801 CONSOLE_DEBUG("\n number of links with key %s is: %d \n",SCP(keyc1),len2);
802
803 /* just a test for comparing two instances pointer-wise */
804 /*
805 struct Instance *i11,*i22;
806 struct link_entry_t *lnk1,lnk2;
807
808 lnk1 = (struct link_entry_t *)gl_fetch(modelType->u.modarg.link_table,1);
809 lnk2 = (struct link_entry_t *)gl_fetch(MOD_INST(model)->link_table,1);
810 i11 = (struct Instance *)gl_fetch(lnk1->instances_cache,2);
811 i22 = (struct Instance *)gl_fetch(lnk2->instances_cache,1);
812 if(i11 == i22){
813 printf("\n are equal \n");
814 } */
815
816 /* test getLinksReferencing */
817 lnk = (struct link_entry_t *)gl_fetch(MOD_INST(model)->link_table,1);
818 /* take the first link from all the non-declarative and declarative LINK Tables, just for testing */
819 populateLinkCache(model);
820 i1= (struct Instance *)gl_fetch(lnk->instances_cache,1);
821 CONSOLE_DEBUG("\n number links referencing the first instance and key %s is %ld \n"
822 ,SCP(keyc1),gl_length(getLinksReferencing(model,keyc1,i1,0))
823 );
824
825 /* test getLinkInstances */
826
827 /* test getLinkInstancesFlat */
828
829 /* test isDeclarative */
830 modelType = InstanceTypeDesc(model);
831 CONSOLE_DEBUG("\n the link should be declarative %d\n"
832 ,isDeclarative(model,(struct link_entry_t *)gl_fetch(modelType->u.modarg.link_table,1))
833 );
834 CONSOLE_DEBUG("\n the link should be non-declarative %d\n"
835 ,isDeclarative(model,(struct link_entry_t *)gl_fetch(MOD_INST(model)->link_table,1))
836 );
837
838 /* test removeNonDeclarative LINKs */
839 removeNonDeclarativeLinkEntry(model,NULL,0); /*since the key is NULL, all non declarative LINKS are removed */
840
841
842 /* test getLinkTableDeclarative (already tested in previous functions) */
843 /* test getLinkTableProcedural (already tested in previous functions) */
844 }
845

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