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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 423 - (show annotations) (download) (as text)
Mon Apr 3 23:15:49 2006 UTC (18 years, 11 months ago) by ben.allan
File MIME type: text/x-csrc
File size: 384671 byte(s)
Fixed instatiation of blackbox (and probably glassbox)
relations, for poorly tested definitions of 'fix'.
Blackbox evaluation is still broken.

There seems to be some chaos around win32_lean_and_mean
in ascConfig.h

updated reconfig. setenv TKROOT /where/is/tk8.3dir before 
running and all is good.
1 /*
2 * Ascend Instantiator Implementation
3 * by Tom Epperly
4 * Created: 1/24/90
5 * Version: $Revision: 1.84 $
6 * Version control file: $RCSfile: instantiate.c,v $
7 * Date last modified: $Date: 2003/02/06 04:08:30 $
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) 1997 Benjamin Allan, Vicente Rico-Ramirez
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 #include <stdarg.h>
32 #include <utilities/ascConfig.h>
33 #include <utilities/ascMalloc.h>
34 #include <utilities/ascPanic.h>
35 #include <general/pool.h>
36 #include <general/list.h>
37 #include <general/dstring.h>
38 #include "compiler.h"
39 #if TIMECOMPILER
40 #include <time.h>
41 #include <general/tm_time.h>
42 #endif
43 #include "bit.h"
44 #include "symtab.h"
45 #include "fractions.h"
46 #include "dimen.h"
47 #include "functype.h"
48 #include "types.h"
49 #include "instance_enum.h"
50 #include "stattypes.h"
51 #include "statement.h"
52 #include "child.h"
53 #include "type_desc.h"
54 #include "type_descio.h"
55 #include "module.h"
56 #include "library.h"
57 #include "sets.h"
58 #include "setio.h"
59 #include "extfunc.h"
60 #include "extcall.h"
61 #include "dimen.h"
62 #include "forvars.h"
63 #include "exprs.h"
64 #include "name.h"
65 #include "nameio.h"
66 #include "vlist.h"
67 #include "slist.h"
68 #include "evaluate.h"
69 #include "value_type.h"
70 #include "statio.h"
71 #include "pending.h"
72 #include "find.h"
73 #include "relation_type.h"
74 #include "relation.h"
75 #include "logical_relation.h"
76 #include "logrelation.h"
77 #include "relation_util.h"
78 #include "logrel_util.h"
79 #include "instance_types.h"
80 #include "cmpfunc.h"
81 #include "instance_io.h"
82 #include "when.h"
83 #include "case.h"
84 #include "when_util.h"
85 #include "select.h"
86 /* new headers */
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 "anontype.h"
103 #include "anoncopy.h"
104 #include "parpend.h"
105 #include "parpend.h"
106 #include "bintoken.h"
107 #include "watchpt.h"
108 #include "initialize.h"
109 #include "instantiate.h"
110 /* don't even THINK ABOUT adding instmacro.h to this list */
111
112 #define MAXNUMBER 4 /* maximum number of iterations allowed
113 * without change */
114 #define PASS2MAXNUMBER 1 /* maximum number of iterations allowed
115 * without change doing relations. In
116 * system where rels reference rels, > 1 */
117
118 #define PASS3MAXNUMBER 4 /* maximum number of iterations allowed
119 * without change doing logical relations.
120 * In system where logrels reference logrels,
121 * > 1 */
122
123 #define PASS4MAXNUMBER 1 /* maximum number of iterations allowed
124 * without change executing WHEN. In
125 * system where WHEN reference WHEN, > 1 */
126
127 #define AVG_CASES 2L /* size to which all cases lists are */
128 /* initialized (WHEN instance) */
129 #define AVG_REF 2L /* size to which all list of references */
130 /* in a case are initialized (WHEN) */
131
132 #define NO_INCIDENCES 7 /* avg number of vars in a external reln */
133
134 static int g_iteration = 0; /* the current iteration. */
135
136 /* moved from tcltk98/generic/interface/SimsProc.c */
137 struct Instance *g_cursim;
138
139 #define NEW_ext 1
140 #define OLD_ext 0
141 /*************************************************************************\
142 variable to check agreement in the number of boolean, integer or symbol
143 variables in the WHEN/SELECT statement with the number of boolean, integer
144 or symbol values in each of the CASEs
145 \*************************************************************************/
146
147 #define MAX_VAR_IN_LIST 20
148
149 /*
150 * Variables to switch old and new pass 2 instantiation.
151 * The condition for using new pass 2 (anonymous type-based
152 * relation copying) is g_use_copyanon != 0
153 * || FORCE applied.
154 */
155
156 int g_use_copyanon = 1;
157 /* g_use_copyanon is the user switch for anonymous type based relation
158 * copying. if 0, no copying by that method is done.
159 */
160
161 #if TIMECOMPILER
162 static
163 int g_ExecuteREL_CreateTokenRelation_calls = 0;
164 /* count the number of calls to CreateTokenRelation from ExecuteREL */
165 int g_CopyAnonRelation = 0;
166 #endif
167
168 long int g_compiler_counter = 1;
169 /*
170 * What: counter incremented every time a compiler action capable of
171 * changing the instance tree is executed.
172 * At present the compiler cares nothing about this counter,
173 * but it is provided as a service to clients.
174 *
175 * Real applications:
176 * 1) This variable is used for keeping track of calls to
177 * the compiler which will create the need for a total solver system
178 * rebuild. This variable should be incremented anytime a function
179 * which changes the instance tree is called.
180 */
181
182 /* #define DEBUG_RELS */
183 /* undef DEBUG_RELS if you want less spew in pass 2 */
184
185 #ifdef DEBUG_RELS
186 /* root of tree being visited in pass 2. */
187 struct Instance *debug_rels_work;
188 #endif /* dbgrels */
189
190 static unsigned
191 int g_instantiate_relns = ALLRELS; /* default is to do all rels */
192
193 /* pointer to possible error message for child expansion.
194 * messy way of error handling; do not imitate.
195 */
196 static char *g_trychildexpansion_errmessage = NULL;
197 #define TCEM g_trychildexpansion_errmessage
198
199 /* error messages */
200 #define REDEFINE_CHILD_MESG "IS_A statement attempting to redefine child "
201 #define REDEFINE_CHILD_MESG2 "ALIASES statement attempting to redefine child "
202 #define UNDEFINED_TYPE_MESG "IS_A statement refers to undefined type "
203 #define IRT_UNDEFINED_TYPE "IS_REFINED_TO statement refers to undefined type "
204 #define REASSIGN_MESG1 "Attempt to reassign constant "
205 #define REASSIGN_MESG2 " value."
206
207 #ifndef lint
208 static CONST char InstantiatorRCSid[] = "$Id: instantiate.c,v 1.84 2003/02/06 04:08:30 ballan Exp $";
209 #endif
210
211
212 /************************* forward declarations ************************/
213
214 static
215 void WriteForValueError(struct Statement *, struct value_t);
216 static
217 void MakeInstance(CONST struct Name *, struct TypeDescription *, int,
218 struct Instance *, struct Statement *, struct Instance *);
219 static
220 int CheckVarList(struct Instance *, struct Statement *);
221 static
222 int CheckWhereStatements(struct Instance *,struct StatementList *);
223 static
224 int ExecuteISA(struct Instance *, struct Statement *);
225 static
226 int ExecuteCASGN(struct Instance *, struct Statement *);
227 static
228 int DigestArguments(struct Instance *,
229 struct gl_list_t *, struct StatementList *,
230 struct StatementList *, struct Statement *);
231 static
232 int DeriveSetType(CONST struct Set *, struct Instance *,CONST unsigned int);
233
234 static
235 struct gl_list_t *FindInsts(struct Instance *, CONST struct VariableList *,
236 enum find_errors *);
237
238 static
239 void MissingInsts(struct Instance *, CONST struct VariableList *,int);
240 static
241 struct gl_list_t *FindArgInsts(struct Instance *, struct Set *,
242 enum find_errors *);
243 static void AddIncompleteInst(struct Instance *);
244 static int CheckALIASES(struct Instance *, struct Statement *);
245 static int CheckARR(struct Instance *, struct Statement *);
246 static int CheckISA(struct Instance *, struct Statement *);
247 static
248 int AssignStructuralValue(struct Instance *,struct value_t,struct Statement *);
249 static int CheckSELECT(struct Instance *, struct Statement *);
250 static int CheckWHEN(struct Instance *, struct Statement *);
251 static void MakeRealWhenCaseReferencesFOR(struct Instance *,
252 struct Instance *,
253 struct Statement *,
254 struct gl_list_t *);
255 static void MakeWhenCaseReferencesFOR(struct Instance *,
256 struct Instance *,
257 struct Statement *,
258 struct gl_list_t *);
259 static int Pass1CheckFOR(struct Instance *, struct Statement *);
260 static int Pass1ExecuteFOR(struct Instance *, struct Statement *);
261 #ifdef THIS_IS_AN_UNUSED_FUNCTION
262 static int Pass1RealCheckFOR(struct Instance *, struct Statement *);
263 #endif /* THIS_IS_AN_UNUSED_FUNCTION */
264 static void Pass1RealExecuteFOR(struct Instance *, struct Statement *);
265 static int Pass2CheckFOR(struct Instance *, struct Statement *);
266 static int Pass2ExecuteFOR(struct Instance *, struct Statement *);
267 static void Pass2FORMarkCond(struct Instance *, struct Statement *);
268 static void Pass2FORMarkCondRelations(struct Instance *, struct Statement *);
269 static int Pass2RealCheckFOR(struct Instance *, struct Statement *);
270 static int Pass2RealExecuteFOR(struct Instance *, struct Statement *);
271 static int Pass3CheckFOR(struct Instance *, struct Statement *);
272 static int Pass3ExecuteFOR(struct Instance *, struct Statement *);
273 static int Pass3RealCheckFOR (struct Instance *, struct Statement *);
274 static int Pass3RealExecuteFOR(struct Instance *, struct Statement *);
275 static void Pass3FORMarkCond(struct Instance *, struct Statement *);
276 static void Pass3FORMarkCondLogRels(struct Instance *, struct Statement *);
277 static int Pass4CheckFOR(struct Instance *, struct Statement *);
278 static int Pass4ExecuteFOR(struct Instance *, struct Statement *);
279 static int Pass4RealCheckFOR(struct Instance *, struct Statement *);
280 static int ExecuteUnSelectedForStatements(struct Instance *,
281 struct StatementList *);
282 static void ExecuteDefault(struct Instance *, struct Statement *,
283 unsigned long int *);
284 static void RealDefaultFor(struct Instance *, struct Statement *,
285 unsigned long int *);
286 static void DefaultStatementList(struct Instance *, struct gl_list_t *,
287 unsigned long int *);
288 static void ExecuteDefaultStatements(struct Instance *, struct gl_list_t *,
289 unsigned long int *);
290 static int ExecuteSELECT(struct Instance *, unsigned long *,
291 struct Statement *);
292 static void ExecuteDefaultsInSELECT(struct Instance *, unsigned long *,
293 struct Statement *, unsigned long int *);
294 static void RealExecuteWHEN(struct Instance *, struct Statement *);
295 static int ExecuteUnSelectedSELECT(struct Instance *, unsigned long *,
296 struct Statement *);
297 static void ExecuteUnSelectedStatements(struct Instance *i,unsigned long *,
298 struct StatementList *);
299 static void ExecuteUnSelectedWhenStatements(struct Instance *,
300 struct StatementList *);
301 static int ExecuteUnSelectedWHEN(struct Instance *, struct Statement *);
302 static void ReEvaluateSELECT(struct Instance *, unsigned long *,
303 struct Statement *, int, int *);
304
305 /***************************************************************************/
306
307
308 static
309 void ClearIteration(void)
310 {
311 g_iteration = 0;
312 }
313
314 static
315 void WriteStatementLocation(FILE *f, struct Statement *stat)
316 {
317 if (stat!= NULL){
318 FPRINTF(f,"\nStatement located on line %lu of %s.\n",
319 StatementLineNum(stat),
320 Asc_ModuleBestName(StatementModule(stat)));
321 }
322 else
323 FPRINTF(f,"NULL statement.\n");
324 }
325
326 static
327 void WriteSetError(struct Statement *statement, struct TypeDescription *def)
328 {
329 WSEM(ASCERR,statement, (GetBaseType(def) == set_type) ?
330 "No set type specified in IS_A statement"
331 : "Set type specified for a non-set type");
332 }
333
334 /*
335 * This code will emit error messages only on the last
336 * iteration when trying to clear pending statements.
337 * g_iteration is the global iteration counter, and MAXNUMBER
338 * is the number of times that the instantiator will try
339 * to clear the list, without change.
340 */
341 static
342 void WriteUnexecutedMessage(FILE *f, struct Statement *stat, CONST char *msg)
343 {
344 if (g_iteration>=(MAXNUMBER)) WSSM(f,stat,msg,0);
345 }
346
347
348 /*
349 * Write Unexecuted Error Message in Pass 3 WUEMPASS3
350 *
351 * This code will emit error messages only on the last
352 * iteration of pass3 when trying to clear pending statements.
353 * g_iteration is the global iteration counter, and PASS3MAXNUMBER
354 * is the number of times that the instantiator will try
355 * to clear the list, without change.
356 */
357
358 static
359 void WUEMPASS3(FILE *f, struct Statement *stat, CONST char *msg)
360 {
361 if (g_iteration>=(PASS3MAXNUMBER)) WSSM(f,stat,msg,0);
362 }
363
364
365 /***************************************************************\
366 dense array processing, mostly.
367 \***************************************************************/
368
369 /*
370 * returns 0 if c is NULL, probably should be -1.
371 * -2 if c is illegal set type
372 * 1 if c IS_A integer_constant set type
373 * 0 if c IS_A symbol_constant set type
374 * statement is used only to issue error messages.
375 */
376 static
377 int CalcSetType(symchar *c, struct Statement *statement)
378 {
379 struct TypeDescription *desc;
380 if (c==NULL) return 0;
381 if ((desc = FindType(c)) != NULL){
382 switch(GetBaseType(desc)){
383 case integer_constant_type: return 1;
384 case symbol_constant_type: return 0;
385 default:
386 WSEM(ASCERR,statement, "Incorrect set type in IS_A");
387 /* lint should keep us from ever getting here */
388 return -2;
389 }
390 } else{
391 WSEM(ASCERR,statement, "Unable to determine type of set.");
392 return -2;
393 }
394 }
395
396 /* last minute check for set values that subscript arrays.
397 * probably should check constantness too but does not.
398 * return 0 if ok, 1 if not.
399 */
400 static
401 int CheckSetVal(struct value_t setval)
402 {
403 if (ValueKind(setval) != set_value) {
404 switch (ValueKind(setval)) {
405 case integer_value:
406 TCEM = "Incorrectly integer-valued array range.";
407 break;
408 case symbol_value:
409 TCEM = "Incorrect symbol-valued array range.";
410 break;
411 case real_value:
412 TCEM = "Incorrect real-valued array subscript.";
413 break;
414 case boolean_value:
415 TCEM = "Incorrect boolean-valued array subscript.";
416 break;
417 case list_value:
418 TCEM = "Incorrect list-valued array subscript.";
419 break;
420 case error_value:
421 switch (ErrorValue(setval)) {
422 case type_conflict:
423 TCEM = "Set expression type conflict in array subscript.";
424 break;
425 default:
426 TCEM = "Generic error 1 in array subscript.";
427 break;
428 }
429 break;
430 case set_value: /* really weird if this happens, since if eliminated it */
431 break;
432 default:
433 TCEM = "Generic error 2 in array subscript.";
434 break;
435 }
436 return 1;
437 }
438 return 0;
439 }
440 /* This attempts to evaluate a the next undone subscript of the
441 * array and call ExpandArray with that set value.
442 * In the case of ALIAS arrays this must always succeed, because
443 * we have checked first that it will. If it did not we would
444 * be stuck because later calls to ExpandArray will not know
445 * the difference between the unexpanded alias array and the
446 * unexpanded IS_A array.
447 * Similarly, in the case of parameterized arrays this must
448 * always succeed, OTHERWISE ExpandArray will not know the
449 * arguments of the IS_A type, arginst next time around.
450 *
451 * In the event that the set given or set value expanded is bogus,
452 * returns 1 and statement from which this call was derived is
453 * semantically garbage.
454 */
455 static
456 int ValueExpand(struct Instance *i, unsigned long int pos,
457 struct value_t value, int *changed,
458 struct Instance *rhsinst, struct Instance *arginst,
459 struct gl_list_t *rhslist)
460 {
461 struct value_t setval;
462 switch(ValueKind(value)){
463 case list_value:
464 setval = CreateSetFromList(value);
465 if (CheckSetVal(setval)) {
466 return 1;
467 }
468 ExpandArray(i,pos,SetValue(setval),rhsinst,arginst,rhslist);
469 /* this may modify the pending instance list if
470 * rhslist and rhsinst both == NULL.
471 */
472 *changed = 1;
473 DestroyValue(&setval);
474 break;
475 case error_value:
476 switch(ErrorValue(value)){
477 case name_unfound:
478 case undefined_value:
479 break;
480 default:
481 TCEM = "Array instance has incorrect index type.";
482 return 1;
483 }
484 break;
485 default:
486 TCEM = "Array instance has incorrect index value type.";
487 return 1;
488 }
489 return 0;
490 }
491
492 /* When an incorrect combination of sparse and dense indices is found,
493 * marks the statement wrong and whines. If the statement has already
494 * been marked wrong, does not whine.
495 * In FOR loops,
496 * this function warns about a problem that the implementation really
497 * should allow. Alas, the fix is pending a complete rework of arrays.
498 * In user is idiot case,
499 * this really should have been ruled out by checkisa, which lets a little
500 * too much trash through. Our whole array implementation sucks.
501 */
502 static
503 void SignalChildExpansionFailure(struct Instance *work,unsigned long cnum)
504 {
505 struct TypeDescription *desc;
506 ChildListPtr clp;
507 struct Statement *statement;
508
509 assert(work!= NULL);
510 assert(cnum!= 0);
511 assert(InstanceKind(work)==MODEL_INST);
512 desc = InstanceTypeDesc(work);
513 clp = GetChildList(desc);
514 statement = (struct Statement *)ChildStatement(clp,cnum);
515 if ( StatWrong(statement) != 0) {
516 return;
517 }
518 if (TCEM != NULL) {
519 FPRINTF(ASCERR,"%s\n",TCEM);
520 TCEM = NULL;
521 }
522 if (StatInFOR(statement)) {
523 MarkStatContext(statement,context_WRONG);
524 WSEM(ASCERR,statement, "Add another FOR index. In FOR loops,"
525 " all array subscripts must be scalar values, not sets.");
526 WSS(ASCERR,statement);
527 } else {
528 MarkStatContext(statement,context_WRONG);
529 WSEM(ASCERR,statement, "Subscripts of conflicting or incorrect types"
530 " in rectangular array.");
531 WSS(ASCERR,statement);
532 }
533 return;
534 }
535
536 /*
537 * Should never be called with BOTH rhs(inst/list) and arginst != NULL,
538 * but one or both may be NULL depending on other circumstances.
539 * Should never be called on ALIASES/IS_A inside a for loop.
540 * Returns an error number other than 0 if called inside a for loop.
541 * If error, outer scope should mark statement incorrect.
542 */
543 static
544 int TryChildExpansion(struct Instance *child,
545 struct Instance *parent,
546 int *changed,
547 struct Instance *rhsinst,
548 struct Instance *arginst,
549 struct gl_list_t *rhslist)
550 {
551 unsigned long pos,oldpos=0;
552 struct value_t value;
553 CONST struct Set *setp;
554 int error=0;
555 assert(arginst==NULL || (rhsinst==NULL && rhslist==NULL));
556 /* one must be NULL as alii do not have args */
557 while((pos=NextToExpand(child))>oldpos){
558 oldpos=pos;
559 setp = IndexSet(child,pos);
560 if (GetEvaluationContext() != NULL) {
561 error++;
562 FPRINTF(ASCERR,"TryChildExpansion with mixed instance\n");
563 } else {
564 SetEvaluationContext(parent); /* could be wrong for mixed style arrays */
565 value = EvaluateSet(setp,InstanceEvaluateName);
566 SetEvaluationContext(NULL);
567 if (ValueExpand(child,pos,value,changed,rhsinst,arginst,rhslist) != 0) {
568 error++;
569 }
570 DestroyValue(&value);
571 }
572 }
573 return error;
574 }
575
576 /* expands, if possible, children of nonrelation,
577 * nonalias, nonparameterized arrays.
578 */
579 static
580 void TryArrayExpansion(struct Instance *work, int *changed)
581 {
582 unsigned long c,len;
583 struct Instance *child;
584 struct TypeDescription *desc;
585 len = NumberChildren(work);
586 for(c=1;c<=len;c++){
587 child = InstanceChild(work,c);
588 if (child!=NULL){
589 switch(InstanceKind(child)){
590 case ARRAY_INT_INST:
591 case ARRAY_ENUM_INST:
592 desc = InstanceTypeDesc(child);
593 /* no alii, no parameterized types, no for loops allowed. */
594 if ((!GetArrayBaseIsRelation(desc))&&(!RectangleArrayExpanded(child)) &&
595 (!GetArrayBaseIsLogRel(desc)) ) {
596 if (TryChildExpansion(child,work,changed,NULL,NULL,NULL)!= 0) {
597 SignalChildExpansionFailure(work,c);
598 }
599 }
600 break;
601 default:
602 #if 0 /* example of what not to do here */
603 FPRINTF(ASCERR,"TryArrayExpansion called with non-array instance\n");
604 /* calling with non array child is fairly common and unavoidable */
605 #endif
606 break;
607 }
608 }
609 }
610 }
611
612 static
613 void DestroyIndexList(struct gl_list_t *gl)
614 {
615 struct IndexType *ptr;
616 int c,len;
617 if (gl!=NULL) {
618 for (c=1,len = gl_length(gl);c <= len;c++) {
619 ptr = (struct IndexType *)gl_fetch(gl,c);
620 if (ptr) DestroyIndexType(ptr);
621 }
622 gl_destroy(gl);
623 }
624 }
625
626 static
627 int FindExprType(CONST struct Expr *ex, struct Instance *parent,
628 CONST unsigned int searchfor)
629 /*********************************************************************\
630 returns 1 if ex believed to be integer, 0 if symbol, and -1 if
631 confused. if searchfor TRUE, includes fortable in search
632 \*********************************************************************/
633 {
634 struct Instance *i;
635 struct gl_list_t *ilist;
636 enum find_errors err;
637 switch(ExprType(ex)){
638 case e_var:
639 ilist = FindInstances(parent,ExprName(ex),&err);
640 if ((ilist!=NULL)&&(gl_length(ilist)>0)){
641 i = (struct Instance *)gl_fetch(ilist,1);
642 gl_destroy(ilist);
643 switch(InstanceKind(i)){
644 case INTEGER_ATOM_INST:
645 case INTEGER_INST:
646 case INTEGER_CONSTANT_INST:
647 return 1;
648 case SYMBOL_ATOM_INST:
649 case SYMBOL_INST:
650 case SYMBOL_CONSTANT_INST:
651 return 0;
652 case SET_ATOM_INST:
653 case SET_INST:
654 return IntegerSetInstance(i);
655 default:
656 FPRINTF(ASCERR,"Incorrect index type; guessing integer index.\n");
657 return 1;
658 }
659 } else {
660 if (ilist!=NULL) gl_destroy(ilist);
661 if (GetEvaluationForTable()!=NULL) {
662 symchar *name;
663 struct for_var_t *ptr;
664 AssertMemory(GetEvaluationForTable());
665 name = SimpleNameIdPtr(ExprName(ex));
666 if (name!=NULL) {
667 ptr = FindForVar(GetEvaluationForTable(),name);
668 if (ptr!=NULL) {
669 switch(GetForKind(ptr)) {
670 case f_integer:
671 return 1;
672 case f_symbol:
673 return 0;
674 default:
675 FPRINTF(ASCERR,"Undefined FOR or indigestible variable.\n");
676 }
677 }
678 }
679 }
680 return -1;
681 }
682 case e_int:
683 return 1;
684 case e_symbol:
685 return 0;
686 case e_set:
687 return DeriveSetType(ExprSValue(ex),parent,searchfor);
688 default:
689 if (g_iteration>=(MAXNUMBER)) {
690 /* referencing g_iteration sucks, but seeing spew sucks more.*/
691 /* WUM, which we want, needs a statement ptr we can't supply. */
692 FPRINTF(ASCERR,"Heuristic FindExprType failed. Check your indices.\n");
693 FPRINTF(ASCERR,"Report this failure to %s if no apparent error.\n",
694 ASC_MILD_BUGMAIL);
695 FPRINTF(ASCERR,"Assuming integer array index.\n");
696 }
697 return -1;
698 }
699 }
700
701 static
702 int DeriveSetType(CONST struct Set *sptr, struct Instance *parent,
703 CONST unsigned int searchfor)
704 /*********************************************************************\
705 returns -1 if has no clue,
706 returns 1 if set appears to be int set
707 returns 0 if apparently symbol_constant set.
708 \*********************************************************************/
709 {
710 register CONST struct Set *ptr;
711 int result=-1; /* -1 indicates a failure */
712 ptr = sptr;
713 /* if it contains a range it must be an integer set */
714 while(ptr!=NULL){
715 if (SetType(ptr)) return 1;
716 ptr = NextSet(ptr);
717 }
718 ptr = sptr;
719 /* try to find the type from the expressions */
720 while(ptr!=NULL){
721 if ((result = FindExprType(GetSingleExpr(ptr),parent,searchfor)) >= 0) {
722 return result;
723 }
724 ptr = NextSet(ptr);
725 }
726 return -1; /* undefined type */
727 }
728
729 /*
730 * Returns a gllist contain the string form (or forms) of array
731 * subscripts(s)
732 * e.g. Name a[1..2]['foo']
733 * will return a gllist containing something like:
734 * "1..2"
735 * "foo"
736 */
737 static
738 struct gl_list_t *ArrayIndices(CONST struct Name *name,
739 struct Instance *parent)
740 {
741 struct gl_list_t *result;
742 int settype;
743 CONST struct Set *sptr;
744
745 if (!NameId(name)) return NULL;
746 name = NextName(name);
747 if (name == NULL) return NULL;
748 result = gl_create(2L);
749 while (name!=NULL){
750 if (NameId(name)){
751 DestroyIndexList(result);
752 return NULL;
753 }
754 sptr = NameSetPtr(name);
755 if ((settype = DeriveSetType(sptr,parent,0)) >= 0){
756 gl_append_ptr(result,
757 (VOIDPTR)CreateIndexType(CopySetList(sptr),settype));
758 } else{
759 DestroyIndexList(result);
760 return NULL;
761 }
762 name = NextName(name);
763 }
764 return result;
765 }
766
767 /**************************************************************************\
768 Sparse and Dense Array Processing.
769 \**************************************************************************/
770
771 /* this function has been modified to handle list results when called
772 * from check aliases and dense executearr.
773 * The indices made here in the aliases case where the alias is NOT
774 * inside a FOR loop are NOT for consumption by anyone because they
775 * contain a dummy index type. They merely indicate that
776 * indices can be made. They should be immediately destroyed.
777 * DestroyIndexType is the only thing that groks the Dummy.
778 * This should not be called on the final subscript of an ALIASES/IS_A
779 * inside a FOR loop unless you can grok a dummy in last place.
780 */
781 static
782 struct IndexType *MakeIndex(struct Instance *inst,
783 CONST struct Set *sptr,
784 struct Statement *stat, int last)
785 {
786 struct value_t value;
787 struct value_t setval;
788 int intset;
789 assert(GetEvaluationContext()==NULL);
790 SetEvaluationContext(inst);
791 if (StatInFOR(stat)) {
792 if (sptr == NULL ||
793 NextSet(sptr) != NULL ||
794 SetType(sptr) != 0 ) {
795 /* must be simple index */
796 WriteUnexecutedMessage(ASCERR,stat,
797 "Next subscript in FOR loop IS_A must be a scalar value,"
798 " not a set value.");
799 SetEvaluationContext(NULL);
800 return NULL;
801 }
802 value = EvaluateExpr(GetSingleExpr(sptr),NULL,InstanceEvaluateName);
803 SetEvaluationContext(NULL);
804 switch(ValueKind(value)){
805 case real_value:
806 case boolean_value:
807 case set_value:
808 case list_value:
809 if (last==0) {
810 WSEM(ASCERR,stat, "Index to sparse array is of an incorrect type");
811 DestroyValue(&value);
812 return NULL;
813 } else {
814 setval = CreateSetFromList(value);
815 intset = (SetKind(SetValue(setval)) == integer_set);
816 DestroyValue(&value);
817 DestroyValue(&setval);
818 return CreateDummyIndexType(intset);
819 /* damn thing ends up in typedesc of arrays. */
820 }
821 case integer_value:
822 DestroyValue(&value);
823 return CreateIndexType(CopySetList(sptr),1);
824 case symbol_value:
825 DestroyValue(&value);
826 return CreateIndexType(CopySetList(sptr),0);
827 case error_value:
828 switch(ErrorValue(value)){
829 case undefined_value:
830 if (StatementType(stat)==REL||StatementType(stat)==LOGREL) {
831 WSSM(ASCERR,stat,"Undefined relation array indirect indices",3);
832 /* don't want to warn about sparse IS_A/aliases here */
833 }
834 break;
835 case name_unfound:
836 break;
837 default:
838 WSSM(ASCERR,stat, "Error in sparse array indices",3);
839 break;
840 }
841 DestroyValue(&value);
842 return NULL;
843 default:
844 WSEM(ASCERR,stat, "Unknown result value type in MakeIndex.\n");
845 Asc_Panic(2, NULL, "Unknown result value type in MakeIndex.\n");
846 exit(2);/* Needed to keep gcc from whining */
847 }
848 } else { /* checking subscripts on dense ALIASES/param'd IS_A statement */
849 if (sptr==NULL) {
850 SetEvaluationContext(NULL);
851 return NULL;
852 }
853 value = EvaluateSet(sptr,InstanceEvaluateName);
854 SetEvaluationContext(NULL);
855 switch(ValueKind(value)){
856 case list_value:
857 DestroyValue(&value);
858 return CreateDummyIndexType(0 /* doesn't matter -- dense alias check */);
859 case error_value:
860 switch(ErrorValue(value)){
861 case undefined_value:
862 case name_unfound:
863 DestroyValue(&value);
864 return NULL;
865 default:
866 DestroyValue(&value);
867 WSSM(ASCERR,stat, "Error evaluating index to dense array",3);
868 return NULL;
869 }
870 default:
871 DestroyValue(&value);
872 WSEM(ASCERR,stat, "Bad index to dense alias array");
873 Asc_Panic(2, NULL, "Bad index to dense alias array");
874 exit(2);/* Needed to keep gcc from whining */
875 }
876 /* return NULL; */ /* unreachable */
877 }
878 }
879
880 /*
881 * This function is used for making the indices of individual
882 * elements of sparse arrays (and for checking that it is possible)
883 * and for checking that the indices of dense alias arrays (a
884 * very wierd thing to have) and dense parameterized IS_A
885 * are fully defined so that aliases
886 * and parameterized/sparse IS_A can be fully constructed in 1 pass.
887 * paves over the last subscript on sparse ALIASES-IS_A.
888 */
889 static
890 struct gl_list_t *MakeIndices(struct Instance *inst,
891 CONST struct Name *name,
892 struct Statement *stat)
893 {
894 struct gl_list_t *result;
895 CONST struct Set *sptr;
896 struct IndexType *ptr;
897 int last;
898
899
900 result = gl_create((unsigned long)NameLength(name));
901 while(name != NULL){
902 if (NameId(name)){
903 DestroyIndexList(result);
904 return NULL;
905 }
906 sptr = NameSetPtr(name);
907 last = (NextName(name)==NULL && StatementType(stat)==ARR);
908 ptr = MakeIndex(inst,sptr,stat,last);
909 if (ptr != NULL) {
910 gl_append_ptr(result,(VOIDPTR)ptr);
911 } else {
912 DestroyIndexList(result);
913 return NULL;
914 }
915 name = NextName(name);
916 }
917 return result;
918 }
919
920 /*************************************************************************\
921 Sparse and Dense Array Processing.
922 \**************************************************************************/
923 static
924 void LinkToParentByName(struct Instance *inst,
925 struct Instance *child,
926 symchar *name)
927 {
928 struct InstanceName rec;
929 unsigned long pos;
930 SetInstanceNameType(rec,StrName);
931 SetInstanceNameStrPtr(rec,name);
932 pos = ChildSearch(inst,&rec);
933 LinkToParentByPos(inst,child,pos);
934 }
935
936 void LinkToParentByPos(struct Instance *inst,
937 struct Instance *child,
938 unsigned long pos)
939 {
940 assert(pos);
941 assert(child != NULL);
942 assert(inst != NULL);
943
944 StoreChildPtr(inst,pos,child);
945 AddParent(child,inst);
946 }
947
948 static
949 struct Instance *GetArrayHead(struct Instance *inst, CONST struct Name *name)
950 {
951 struct InstanceName rec;
952 unsigned long pos;
953 if (NameId(name)){
954 SetInstanceNameType(rec,StrName);
955 SetInstanceNameStrPtr(rec,NameIdPtr(name));
956 pos=ChildSearch(inst,&rec);
957 if (pos>0) {
958 return InstanceChild(inst,pos);
959 } else {
960 return NULL;
961 }
962 }
963 return NULL;
964 }
965
966 /*
967 * We are inside a FOR loop.
968 * If rhsinst is not null, we are in an alias statement and
969 * will use rhsinst as the child added instead of
970 * creating a new child.
971 * If arginst is not null, we will use it to aid in
972 * creating IS_A elements.
973 * at least one of arginst, rhsinst must be NULL.
974 * If last !=0, returns NULL naturally and ok.
975 */
976 static
977 struct Instance *DoNextArray(struct Instance *parentofary, /* MODEL */
978 struct Instance *ptr, /* array layer */
979 CONST struct Name *name, /* subscript */
980 struct Statement *stat,
981 struct Instance *rhsinst, /*ALIASES*/
982 struct Instance *arginst, /* IS_A */
983 struct gl_list_t *rhslist, /*ARR*/
984 int last /* ARR */)
985 {
986 CONST struct Set *sptr;
987 struct value_t value;
988 struct value_t setval;
989 long i;
990 symchar *sym;
991
992 if (NameId(name) != 0) return NULL; /* must be subscript, i.e. set */
993 sptr = NameSetPtr(name);
994 if ((sptr==NULL)||(NextSet(sptr)!=NULL)||(SetType(sptr))) {
995 return NULL;
996 }
997 assert(GetEvaluationContext()==NULL);
998 assert(rhsinst==NULL || arginst==NULL);
999 SetEvaluationContext(parentofary);
1000 value = EvaluateExpr(GetSingleExpr(sptr),NULL,InstanceEvaluateName);
1001 SetEvaluationContext(NULL);
1002 switch(ValueKind(value)){
1003 case real_value:
1004 case set_value:
1005 case boolean_value:
1006 case list_value:
1007 if (last==0) {
1008 WSEM(ASCERR,stat, "Index to array is of an incorrect type");
1009 DestroyValue(&value);
1010 return NULL;
1011 } else {
1012 /* we are at last subscript of ALIASES/IS_A in for loop. */
1013 /* expand using rhslist pretending dense array. */
1014 setval = CreateSetFromList(value);
1015 ExpandArray(ptr,1L,SetValue(setval),NULL,NULL,rhslist);
1016 DestroyValue(&setval);
1017 DestroyValue(&value);
1018 return NULL;
1019 }
1020 case integer_value:
1021 i = IntegerValue(value);
1022 DestroyValue(&value);
1023 return FindOrAddIntChild(ptr,i,rhsinst,arginst);
1024 case symbol_value:
1025 sym = SymbolValue(value);
1026 DestroyValue(&value);
1027 return FindOrAddStrChild(ptr,sym,rhsinst,arginst);
1028 case error_value:
1029 switch(ErrorValue(value)){
1030 case undefined_value:
1031 if (StatementType(stat)==REL||StatementType(stat)==LOGREL) {
1032 WSSM(ASCERR,stat, "Undefined relation array indirect indices",3);
1033 }
1034 break;
1035 case name_unfound:
1036 break;
1037 default:
1038 WSEM(ASCERR,stat, "Error in array indices");
1039 break;
1040 }
1041 DestroyValue(&value);
1042 return NULL;
1043 default:
1044 Asc_Panic(2, NULL ,"Unknown result value type.\n");
1045 exit(2);/* Needed to keep gcc from whining */
1046 }
1047 }
1048
1049 /*
1050 * We are inside a FOR loop.
1051 * If rhsinst is not null, we are in an alias statement and
1052 * will eventually use rhsinst as the child added instead of
1053 * creating a new child.
1054 * we expand each subscript individually here rahter than recursively.
1055 * If we are on last subscript of an ALIASES/IS_A, we copy the
1056 * layer in rhslist rather than expanding individually.
1057 * rhslist and intset only make sense simultaneously.
1058 */
1059 static
1060 struct Instance *AddArrayChild(struct Instance *parentofary,
1061 CONST struct Name *name,
1062 struct Statement *stat,
1063 struct Instance *rhsinst,
1064 struct Instance *arginst,
1065 struct gl_list_t *rhslist)
1066 {
1067 struct Instance *ptr;
1068 int last;
1069
1070 ptr = GetArrayHead(parentofary,name);
1071 if(ptr != NULL) {
1072 name = NextName(name);
1073 while(name!=NULL){
1074 last = (rhslist != NULL && NextName(name)==NULL);
1075 ptr = DoNextArray(parentofary,ptr,name,stat,
1076 rhsinst,arginst,rhslist,last);
1077 if (ptr==NULL){
1078 return NULL;
1079 }
1080 name = NextName(name);
1081 }
1082 return ptr;
1083 } else {
1084 return NULL;
1085 }
1086 }
1087
1088 /*
1089 * Create the sparse array typedesc based on the statement kind
1090 * and also add first child named. intset and def used for nonrelation types
1091 * only.
1092 * This function returns the child pointer because relation functions
1093 * need it, not because the child is unconnected.
1094 * If rhsinst is not NULL, uses rhsinst instead of creating new one.
1095 * If rhslist is not NULL, uses rhslist instead of rhsinst or creating.
1096 * It is expected that all subscripts will be evaluatable and that
1097 * in the case of the ALIASES-IS_A statement, the IS_A part is done
1098 * just before the ALIASES part.
1099 */
1100 static
1101 struct Instance *MakeSparseArray(struct Instance *parent,
1102 CONST struct Name *name,
1103 struct Statement *stat,
1104 struct TypeDescription *def,
1105 int intset,
1106 struct Instance *rhsinst,
1107 struct Instance *arginst,
1108 struct gl_list_t *rhslist)
1109 {
1110 struct TypeDescription *desc = NULL;
1111 struct Instance *aryinst;
1112 struct gl_list_t *indices;
1113 indices = MakeIndices(parent,NextName(name),stat);
1114 if (indices != NULL) {
1115 switch (StatementType(stat)) {
1116 case REL:
1117 assert(def==NULL && rhsinst==NULL && rhslist == NULL && arginst == NULL);
1118 desc = CreateArrayTypeDesc(StatementModule(stat),FindRelationType(),
1119 0,1,0,0,indices);
1120 break;
1121 case LOGREL:
1122 assert(def==NULL && rhsinst==NULL && rhslist == NULL && arginst == NULL);
1123 desc = CreateArrayTypeDesc(StatementModule(stat),FindLogRelType(),
1124 0,0,1,0,indices);
1125 break;
1126 case WHEN:
1127 assert(def==NULL && rhsinst==NULL && rhslist == NULL && arginst == NULL);
1128 desc = CreateArrayTypeDesc(StatementModule(stat),
1129 FindWhenType(),0,0,0,1,indices);
1130 break;
1131 case ISA:
1132 case ALIASES:
1133 case ARR:
1134 assert(def!=NULL);
1135 desc = CreateArrayTypeDesc(StatementModule(stat),def,
1136 intset,0,0,0,indices);
1137 break;
1138 default:
1139 WSEM(ASCERR,stat, "Utter screw-up in MakeSparseArray");
1140 Asc_Panic(2, NULL, "Utter screw-up in MakeSparseArray");
1141 }
1142 aryinst = CreateArrayInstance(desc,1);
1143 LinkToParentByName(parent,aryinst,NameIdPtr(name));
1144 return AddArrayChild(parent,name,stat,rhsinst,arginst,rhslist);
1145 } else {
1146 return NULL;
1147 }
1148 }
1149
1150
1151 /* handles construction of alias statements, allegedly, per lhs.
1152 * parent function should find rhs and send it in as rhsinst.
1153 * rhsinst == null should never be used with this function.
1154 * currently, arrays ignored, fatally.
1155 */
1156 static
1157 void MakeAliasInstance(CONST struct Name *name,
1158 CONST struct TypeDescription *basedef,
1159 struct Instance *rhsinst,
1160 struct gl_list_t *rhslist,
1161 int intset,
1162 struct Instance *parent,
1163 struct Statement *statement)
1164 {
1165 symchar *childname;
1166 int changed;
1167 unsigned long pos;
1168 struct Instance *inst;
1169 struct InstanceName rec;
1170 struct TypeDescription *arydef, *def;
1171 struct gl_list_t *indices;
1172 int tce;
1173 assert(rhsinst != NULL || rhslist !=NULL); /* one required */
1174 assert(rhsinst == NULL || rhslist ==NULL); /* only one allowed */
1175 childname = SimpleNameIdPtr(name);
1176 if (childname !=NULL){
1177 /* case of simple part name */
1178 if (StatInFOR(statement) && StatWrong(statement)==0) {
1179 MarkStatContext(statement,context_WRONG);
1180 WSEM(ASCERR,statement,"Unindexed statement in FOR loop not allowed.");
1181 WSS(ASCERR,statement);
1182 return;
1183 }
1184 SetInstanceNameType(rec,StrName);
1185 SetInstanceNameStrPtr(rec,childname);
1186 pos = ChildSearch(parent,&rec);
1187 if (pos>0){
1188 /* case of part expected */
1189 if (InstanceChild(parent,pos)==NULL){
1190 /* case of part not there yet */
1191 inst = rhsinst;
1192 StoreChildPtr(parent,pos,inst);
1193 if (SearchForParent(inst,parent)==0) {
1194 /* case where we don't already have it at this scope */
1195 AddParent(inst,parent);
1196 }
1197 } else{ /* redefining instance */
1198 /* case of part already there and we barf */
1199 char *msg = ascmalloc(SCLEN(childname)+
1200 strlen(REDEFINE_CHILD_MESG2)+1);
1201 strcpy(msg,REDEFINE_CHILD_MESG2);
1202 strcat(msg,SCP(childname));
1203 WSEM(ASCERR,statement,msg);
1204 ascfree(msg);
1205 }
1206 } else{ /* unknown child name */
1207 /* case of part not expected */
1208 WSEM(ASCERR,statement, "Unknown child name. Never should happen");
1209 Asc_Panic(2, NULL, "Unknown child name. Never should happen");
1210 }
1211 } else{
1212 /* if reach the else, means compound identifier or garbage */
1213 indices = ArrayIndices(name,parent);
1214 if (rhsinst != NULL) {
1215 def = InstanceTypeDesc(rhsinst);
1216 } else {
1217 def = (struct TypeDescription *)basedef;
1218 }
1219 if (indices!=NULL){ /* array of some sort */
1220 childname = NameIdPtr(name);
1221 SetInstanceNameType(rec,StrName);
1222 SetInstanceNameStrPtr(rec,childname);
1223 pos = ChildSearch(parent,&rec);
1224 if (!StatInFOR(statement)) {
1225 /* rectangle arrays */
1226 arydef = CreateArrayTypeDesc(StatementModule(statement),
1227 def,intset,0,0,0,indices);
1228 if (pos>0) {
1229 inst = CreateArrayInstance(arydef,1);
1230 if (inst!=NULL){
1231 changed = 0;
1232 tce = TryChildExpansion(inst,parent,&changed,rhsinst,NULL,rhslist);
1233 /* we're not in a for loop, so can't fail unless user is idiot. */
1234 LinkToParentByPos(parent,inst,pos); /* don't want to lose memory */
1235 /* if user is idiot, whine. */
1236 if (tce != 0) {
1237 SignalChildExpansionFailure(parent,pos);
1238 }
1239 } else {
1240 WSEM(ASCERR,statement, "Unable to create alias array instance");
1241 Asc_Panic(2, NULL, "Unable to create alias array instance");
1242 }
1243 } else {
1244 DeleteTypeDesc(arydef);
1245 WSEM(ASCERR,statement,
1246 "Unknown array child name. Never should happen");
1247 Asc_Panic(2, NULL, "Unknown array child name. Never should happen");
1248 }
1249 } else {
1250 /* sparse array */
1251 DestroyIndexList(indices);
1252 if (pos>0) {
1253 if (InstanceChild(parent,pos)==NULL) {
1254 /* need to make alias array */
1255 /* should check for NULL return here */
1256 (void)
1257 MakeSparseArray(parent,name,statement,def,
1258 intset,rhsinst,NULL,rhslist);
1259 } else {
1260 /* need to add alias array element */
1261 /* should check for NULL return here */
1262 (void) AddArrayChild(parent,name,statement,
1263 rhsinst,NULL,rhslist);
1264 }
1265 } else {
1266 WSEM(ASCERR,statement,
1267 "Unknown array child name. Never should happen");
1268 Asc_Panic(2, NULL, "Unknown array child name. Never should happen");
1269 }
1270 }
1271 } else {
1272 /* bad child name. cannot create parts of parts. should never
1273 * happen, being trapped out in typelint.
1274 */
1275 WSEM(ASCERR,statement,"Bad ALIASES child name.");
1276 }
1277 }
1278 }
1279
1280 /* returns 1 if concluded with statement, 0 if might try later.
1281 */
1282 static
1283 int ExecuteALIASES(struct Instance *inst, struct Statement *statement)
1284 {
1285 CONST struct VariableList *vlist;
1286 struct gl_list_t *rhslist;
1287 struct Instance *rhsinst;
1288 CONST struct Name *name;
1289 enum find_errors ferr;
1290 int intset;
1291
1292 assert(StatementType(statement)==ALIASES);
1293 if (StatWrong(statement)) {
1294 /* incorrect statements should be warned about when they are
1295 * marked wrong, so we just ignore them here.
1296 */
1297 return 1;
1298 }
1299 if (!CheckALIASES(inst,statement)) {
1300 WriteUnexecutedMessage(ASCERR,statement,
1301 "Possibly undefined sets/ranges in ALIASES statement.");
1302 return 0;
1303 }
1304 name = AliasStatName(statement);
1305 rhslist = FindInstances(inst,name,&ferr);
1306 if (rhslist == NULL) {
1307 WriteUnexecutedMessage(ASCERR,statement,
1308 "Possibly undefined right hand side in ALIASES statement.");
1309 return 0; /* rhs not compiled yet */
1310 }
1311 if (gl_length(rhslist)>1) {
1312 WSEM(ASCERR,statement,"ALIASES needs exactly 1 RHS");
1313 gl_destroy(rhslist);
1314 return 1; /* rhs not unique for current values of sets */
1315 }
1316 rhsinst = (struct Instance *)gl_fetch(rhslist,1);
1317 gl_destroy(rhslist);
1318 if (InstanceKind(rhsinst)==REL_INST || LREL_INST ==InstanceKind(rhsinst)) {
1319 WSEM(ASCERR,statement,"Direct ALIASES of relations are not permitted");
1320 MarkStatContext(statement,context_WRONG);
1321 WSS(ASCERR,statement);
1322 return 1; /* relations only aliased through models */
1323 }
1324 intset = ( (InstanceKind(rhsinst)==SET_ATOM_INST) &&
1325 (IntegerSetInstance(rhsinst)) );
1326 vlist = GetStatVarList(statement);
1327 while (vlist!=NULL){
1328 MakeAliasInstance(NamePointer(vlist),NULL,rhsinst,
1329 NULL,intset,inst,statement);
1330 vlist = NextVariableNode(vlist);
1331 }
1332 return 1;
1333 }
1334
1335
1336 /****************** support for ALIASES-IS_A statements ******************/
1337
1338 /* enforce max len and no ' rules for subscripts. string returned
1339 * may not be string sent.
1340 */
1341 static
1342 char *DeSingleQuote(char *s)
1343 {
1344 char *old;
1345 int len;
1346 if (s==NULL) {
1347 return s;
1348 }
1349 len = strlen(s);
1350 if (len > 40) {
1351 old = s;
1352 s = (char *)ascmalloc(41);
1353 strncpy(s,old,17);
1354 s[17] = '.';
1355 s[18] = '.';
1356 s[19] = '.';
1357 s[20] = '\0';
1358 strcat(s,(old+len-20));
1359 ascfree(old);
1360 }
1361 old = s;
1362 while (*s != '\0') {
1363 if (*s =='\'') {
1364 *s = '_';
1365 }
1366 s++;
1367 }
1368
1369 return old;
1370 }
1371
1372 /* returns a symchar based on but not in strset,
1373 * and adds original and results to sym table.
1374 * destroys the s given.
1375 */
1376 static
1377 symchar *UniquifyString(char *s, struct set_t *strset)
1378 {
1379 int oldlen, maxlen, c;
1380 char *new;
1381 symchar *tmp;
1382
1383 tmp = AddSymbol(s);
1384 if (StrMember(tmp,strset)!=0) {
1385 oldlen = strlen(s);
1386 maxlen = oldlen+12;
1387 new = ascrealloc(s,oldlen+14);
1388 assert(new!=NULL);
1389 while ( (oldlen+1) < maxlen) {
1390 new[oldlen+1] = '\0';
1391 for(c = 'a'; c <= 'z'; c++){
1392 new[oldlen] = (char)c;
1393 tmp = AddSymbol(new);
1394 if (StrMember(tmp,strset)==0) {
1395 ascfree(new);
1396 return tmp;
1397 }
1398 }
1399 oldlen++;
1400 }
1401 Asc_Panic(2, NULL,
1402 "Unable to generate unique compound alias subscript.\n");
1403 exit(2);/* Needed to keep gcc from whining */
1404 } else {
1405 ascfree(s);
1406 return tmp;
1407 }
1408 }
1409
1410 static
1411 struct value_t GenerateSubscripts(struct Instance *iref,
1412 struct gl_list_t *rhslist,
1413 int intset)
1414 {
1415 struct set_t *setinstval;
1416 unsigned long c,len;
1417 char *str;
1418 symchar *sym;
1419
1420 setinstval = CreateEmptySet();
1421 len = gl_length(rhslist);
1422 if (intset!=0) {
1423 /* create subscripts 1..rhslistlen */
1424 for (c=1;c<=len; c++) {
1425 AppendIntegerElement(setinstval,c);
1426 }
1427 return CreateSetValue(setinstval);
1428 }
1429 /* create string subscripts */
1430 for (c=1; c<= len; c++) {
1431 str = WriteInstanceNameString((struct Instance *)gl_fetch(rhslist,c),iref);
1432 str = DeSingleQuote(str); /* transmogrify for length and ' marks */
1433 sym = UniquifyString(str,setinstval); /* convert to symbol and free str */
1434 AppendStringElement(setinstval,sym);
1435 }
1436 return CreateSetValue(setinstval);
1437 }
1438
1439 static
1440 void DestroyArrayElements(struct gl_list_t *rhslist)
1441 {
1442 unsigned long c,len;
1443 if (rhslist==NULL){
1444 return;
1445 }
1446 for (c=1, len = gl_length(rhslist); c <= len; c++) {
1447 FREEPOOLAC(gl_fetch(rhslist,c));
1448 }
1449 gl_destroy(rhslist);
1450 }
1451
1452 /*
1453 * this function computes the subscript set (or generates it if
1454 * needed) and checks it for matching against the instance list
1455 * and whines when things aren't kosher.
1456 * When things are kosher, creates a gl_list of array children.
1457 * This list is returned through rhslist.
1458 */
1459 static
1460 struct value_t ComputeArrayElements(struct Instance *inst,
1461 struct Statement *statement,
1462 struct gl_list_t *rhsinstlist,
1463 struct gl_list_t **rhslist)
1464 {
1465 struct value_t subslist;
1466 struct value_t subscripts;
1467 struct value_t result; /* return value is the expanded subscript set */
1468 CONST struct Set *setp;
1469 struct set_t *sip;
1470 int intset;
1471 unsigned long c, len;
1472 struct ArrayChild *ptr;
1473
1474 assert((*rhslist)==NULL && rhsinstlist != NULL && rhslist != NULL);
1475
1476 intset = ArrayStatIntSet(statement);
1477 len = gl_length(rhsinstlist);
1478 setp = ArrayStatSetValues(statement);
1479 if (setp==NULL) {
1480 /* value generated is a set and automatically is of correct CARD() */
1481 result = GenerateSubscripts(inst,rhsinstlist,intset);
1482 /* fill up rhslist and return */
1483 *rhslist = gl_create(len);
1484 sip = SetValue(result);
1485 if (intset != 0) {
1486 for (c = 1; c <= len; c++) {
1487 ptr = MALLOCPOOLAC;
1488 ptr->inst = gl_fetch(rhsinstlist,c);
1489 ptr->name.index = FetchIntMember(sip,c);
1490 gl_append_ptr(*rhslist,(VOIDPTR)ptr);
1491 }
1492 } else {
1493 for (c = 1; c <= len; c++) {
1494 ptr = MALLOCPOOLAC;
1495 ptr->inst = gl_fetch(rhsinstlist,c);
1496 ptr->name.str = FetchStrMember(sip,c);
1497 gl_append_ptr(*rhslist,(VOIDPTR)ptr);
1498 }
1499 }
1500 return result;
1501 } else {
1502 /* cook up the users list */
1503 assert(GetEvaluationContext()==NULL);
1504 SetEvaluationContext(inst);
1505 subslist = EvaluateSet(setp,InstanceEvaluateName);
1506 SetEvaluationContext(NULL);
1507 /* check that it evaluates */
1508 if (ValueKind(subslist)==error_value) {
1509 switch(ErrorValue(subslist)) {
1510 case name_unfound:
1511 case undefined_value:
1512 DestroyValue(&subslist);
1513 WriteUnexecutedMessage(ASCERR,statement,
1514 "Undefined values in WITH_VALUE () list");
1515 return CreateErrorValue(undefined_value);
1516 default:
1517 WSEM(ASCERR,statement,"Bad result in evaluating WITH_VALUE list\n");
1518 MarkStatContext(statement,context_WRONG);
1519 WSS(ASCERR,statement);
1520 DestroyValue(&subslist);
1521 }
1522 }
1523 /* collect sets to assign later */
1524 result = CreateSetFromList(subslist); /* unique list */
1525 ListMode=1;
1526 subscripts = CreateOrderedSetFromList(subslist); /* as ordered to insts */
1527 ListMode=0;
1528 DestroyValue(&subslist); /* done with it */
1529 /* check everything dumb that can happen */
1530 if ( ValueKind(result) != set_value ||
1531 Cardinality(SetValue(subscripts)) != Cardinality(SetValue(result))
1532 ) {
1533 DestroyValue(&result);
1534 DestroyValue(&subscripts);
1535 WSEM(ASCERR,statement,
1536 "WITH_VALUE list does not form a proper subscript set.\n");
1537 MarkStatContext(statement,context_WRONG);
1538 WSS(ASCERR,statement);
1539 return CreateErrorValue(type_conflict);
1540 }
1541 /* check sanity of values. may need fixing around empty set. */
1542 if ( (SetKind(SetValue(subscripts))==integer_set) != (intset!=0)) {
1543 WSEM(ASCERR,statement,
1544 "Unable to construct set. Values and set type mismatched\n");
1545 DestroyValue(&result);
1546 DestroyValue(&subscripts);
1547 MarkStatContext(statement,context_WRONG);
1548 WSS(ASCERR,statement);
1549 return CreateErrorValue(type_conflict);
1550 }
1551 /* check set size == instances to alias */
1552 if (Cardinality(SetValue(subscripts)) != len) {
1553 WSEM(ASCERR,statement,"In: ");
1554 FPRINTF(ASCERR,
1555 "WITH_VALUE list length (%lu) != number of instances given (%lu)\n",
1556 Cardinality(SetValue(subscripts)),len);
1557 DestroyValue(&result);
1558 DestroyValue(&subscripts);
1559 MarkStatContext(statement,context_WRONG);
1560 WSS(ASCERR,statement);
1561 return CreateErrorValue(type_conflict);
1562 }
1563 /* fill up rhslist and return */
1564 *rhslist = gl_create(len);
1565 sip = SetValue(subscripts);
1566 if (intset != 0) {
1567 for (c = 1; c <= len; c++) {
1568 ptr = MALLOCPOOLAC;
1569 ptr->inst = gl_fetch(rhsinstlist,c);
1570 ptr->name.index = FetchIntMember(sip,c);
1571 gl_append_ptr(*rhslist,(VOIDPTR)ptr);
1572 }
1573 } else {
1574 for (c = 1; c <= len; c++) {
1575 ptr = MALLOCPOOLAC;
1576 ptr->inst = gl_fetch(rhsinstlist,c);
1577 ptr->name.str = FetchStrMember(sip,c);
1578 gl_append_ptr(*rhslist,(VOIDPTR)ptr);
1579 }
1580 }
1581 DestroyValue(&subscripts);
1582 return result;
1583 }
1584 }
1585
1586 /* returns 1 if concluded with statement, 0 if might try later.
1587 */
1588 static
1589 int ExecuteARR(struct Instance *inst, struct Statement *statement)
1590 {
1591 CONST struct VariableList *vlist;
1592 struct gl_list_t *rhsinstlist; /* list of instances found to alias */
1593 struct gl_list_t *setinstl; /* instance found searching for IS_A'd set */
1594 struct gl_list_t *rhslist=NULL; /* list of arraychild structures */
1595 struct value_t subsset;
1596 #ifndef NDEBUG
1597 struct Instance *rhsinst;
1598 #endif
1599 struct Instance *setinst;
1600 enum find_errors ferr;
1601 CONST struct TypeDescription *basedef;
1602 ChildListPtr icl;
1603 int intset;
1604
1605 assert(StatementType(statement)==ARR);
1606 if (StatWrong(statement)) {
1607 /* incorrect statements should be warned about when they are
1608 * marked wrong, so we just ignore them here.
1609 */
1610 return 1;
1611 }
1612 if (!CheckARR(inst,statement)) {
1613 WriteUnexecutedMessage(ASCERR,statement,
1614 "Possibly undefined instances/sets/ranges in ALIASES-IS_A statement.");
1615 return 0;
1616 }
1617 rhsinstlist = FindInsts(inst,GetStatVarList(statement),&ferr);
1618 if (rhsinstlist == NULL) {
1619 MissingInsts(inst,GetStatVarList(statement),0);
1620 WriteUnexecutedMessage(ASCERR,statement,
1621 "Incompletely defined source instance list in ALIASES-IS_A statement.");
1622 return 0; /* rhs's not compiled yet */
1623 }
1624 /* check for illegal rhs types. parser normally bars this. */
1625 #ifndef NDEBUG
1626 if (gl_length(rhsinstlist) >0) {
1627 rhsinst = (struct Instance *)gl_fetch(rhsinstlist,1);
1628 if (BaseTypeIsEquation(InstanceTypeDesc(rhsinst))) {
1629 WSEM(ASCERR,statement,
1630 "Direct ALIASES of rels/lrels/whens are not permitted");
1631 MarkStatContext(statement,context_WRONG);
1632 WSS(ASCERR,statement);
1633 gl_destroy(rhsinstlist);
1634 return 1; /* (log)relations/whens only aliased through models */
1635 }
1636 }
1637 #endif
1638 /* evaluate name list, if given, OTHERWISE generate it, and check CARD.
1639 * issues warnings as needed
1640 */
1641 subsset = ComputeArrayElements(inst,statement,rhsinstlist,&rhslist);
1642 gl_destroy(rhsinstlist);
1643 /* check return values of subsset and rhslist here */
1644 if (ValueKind(subsset)== error_value) {
1645 if (ErrorValue(subsset) == undefined_value) {
1646 DestroyValue(&subsset);
1647 return 0;
1648 } else {
1649 DestroyValue(&subsset);
1650 return 1;
1651 }
1652 }
1653 assert(rhslist!=NULL); /* might be empty, but not NULL */
1654 /* make set ATOM */
1655 vlist = ArrayStatSetName(statement);
1656 intset = ArrayStatIntSet(statement);
1657 MakeInstance(NamePointer(vlist),FindSetType(),intset,inst,statement,NULL);
1658 /* get instance and assign. */
1659 setinstl = FindInstances(inst,NamePointer(vlist),&ferr);
1660 if (setinstl == NULL || gl_length(setinstl) != 1L) {
1661 FPRINTF(ASCERR,"Unable to construct set.\n");
1662 FPRINTF(ASCERR,"Bizarre error in ALIASES-IS_A. Please report it to:\n%s",
1663 ASC_BIG_BUGMAIL);
1664 if (setinstl!=NULL) {
1665 gl_destroy(setinstl);
1666 }
1667 DestroyArrayElements(rhslist);
1668 DestroyValue(&subsset);
1669 MarkStatContext(statement,context_WRONG);
1670 WSS(ASCERR,statement);
1671 /* should nuke entire compound ALIASES/IS_A array pair already built */
1672 return 1;
1673 } else {
1674 setinst = (struct Instance *)gl_fetch(setinstl,1);
1675 gl_destroy(setinstl);
1676 AssignSetAtomList(setinst,CopySet(SetValue(subsset)));
1677 DestroyValue(&subsset);
1678 }
1679
1680 /* create ALIASES-IS_A array */
1681 /* recycle the local pointer to our set ATOM to check base type of rhslist */
1682 setinst = CAC(gl_fetch(rhslist,1))->inst;
1683 intset = ( InstanceKind(setinst)==SET_ATOM_INST &&
1684 IntegerSetInstance(setinst)!=0 );
1685 /* the real question is does anyone downstream care if intset correct?
1686 * probably not since its an alias anyway.
1687 */
1688 vlist = ArrayStatAvlNames(statement);
1689 icl = GetChildList(InstanceTypeDesc(inst));
1690 basedef = ChildBaseTypePtr(icl,ChildPos(icl,NameIdPtr(NamePointer(vlist))));
1691 while (vlist!=NULL){
1692 /* fix me for sparse case. dense ok. */
1693 MakeAliasInstance(NamePointer(vlist), basedef,NULL,
1694 rhslist, intset, inst, statement);
1695 vlist = NextVariableNode(vlist);
1696 }
1697 /* clean up memory */
1698 DestroyArrayElements(rhslist);
1699
1700 return 1;
1701 }
1702
1703
1704 /*
1705 * Makes a single instance of the type given,which must not be array
1706 * or relation of any kind or when.
1707 * If type is a MODEL, adds the MODEL to pending list.
1708 * The argument intset is only used if type is set, then
1709 * if intset==1, set ATOM made will be integer set.
1710 * Attempts to find a UNIVERSAL before making the instance.
1711 * statement is used only for error messages.
1712 */
1713 static
1714 struct Instance *MakeSimpleInstance(struct TypeDescription *def,
1715 int intset,
1716 struct Statement *statement,
1717 struct Instance *arginst)
1718 {
1719 struct Instance *inst;
1720
1721 inst = ShortCutMakeUniversalInstance(def);
1722 if (inst==NULL) {
1723 switch(GetBaseType(def)){
1724 case model_type:
1725 inst = CreateModelInstance(def); /* if we are here - build one */
1726 if (!GetUniversalFlag(def)||!InstanceInList(inst)) {
1727 /* add PENDING model if not UNIVERSAL, or UNIVERSAL and
1728 * this is the very first time seen - don't ever want an instance
1729 * in the pending list twice.
1730 */
1731 /*
1732 * here we need to shuffle in info from arginst.
1733 * note that because this is inside the UNIVERSAL check,
1734 * only the first set of arguments to a UNIVERSAL type will
1735 * ever apply.
1736 */
1737 ConfigureInstFromArgs(inst,arginst);
1738 AddBelow(NULL,inst);
1739 }
1740 break;
1741 case real_type:
1742 case real_constant_type:
1743 inst = CreateRealInstance(def);
1744 break;
1745 case boolean_type:
1746 case boolean_constant_type:
1747 inst = CreateBooleanInstance(def);
1748 break;
1749 case integer_type:
1750 case integer_constant_type:
1751 inst = CreateIntegerInstance(def);
1752 break;
1753 case set_type:
1754 inst = CreateSetInstance(def,intset);
1755 break;
1756 case symbol_type:
1757 case symbol_constant_type:
1758 inst = CreateSymbolInstance(def);
1759 break;
1760 case relation_type:
1761 inst = NULL;
1762 FPRINTF(ASCERR,"Type '%s' is not allowed in IS_A.\n",
1763 SCP(GetBaseTypeName(relation_type)));
1764 case logrel_type:
1765 inst = NULL;
1766 FPRINTF(ASCERR,"Type '%s' is not allowed in IS_A.\n",
1767 SCP(GetBaseTypeName(logrel_type)));
1768 break;
1769 case when_type:
1770 inst = NULL;
1771 FPRINTF(ASCERR,"Type '%s' is not allowed in IS_A.\n",
1772 SCP(GetBaseTypeName(when_type)));
1773 break;
1774 case array_type:
1775 default: /* picks up patch_type */
1776 WSEM(ASCERR,statement, "MakeSimpleInstance error. PATCH/ARRAY found.\n");
1777 Asc_Panic(2, NULL, "MakeSimpleInstance error. PATCH/ARRAY found.\n");
1778 }
1779 }
1780 return inst;
1781 }
1782
1783 static unsigned long g_unasscon_count = 0L;
1784 /* counter for the following functions */
1785 static
1786 void CountUnassignedConst(struct Instance *i)
1787 {
1788 if (i!=NULL && (IsConstantInstance(i) || InstanceKind(i)==SET_ATOM_INST) ) {
1789 if (AtomAssigned(i)==0) {
1790 g_unasscon_count++;
1791 }
1792 }
1793 }
1794 /* Returns 0 if all constant scalars in ipass are assigned,
1795 * for ipass that are of set/scalar array/scalar type.
1796 * Handles null input gracefully, as if there is something
1797 * unassigned in it.
1798 * Variable types are considered permanently assigned, since
1799 * we are checking for constants being unassigned.
1800 * Assumes arrays, if passed in, are fully expanded.
1801 */
1802 static
1803 int ArgValuesUnassigned(struct Instance *ipass)
1804 {
1805 struct TypeDescription *abd;
1806 if (ipass==NULL) return 1;
1807 switch (InstanceKind(ipass)) {
1808 case ERROR_INST:
1809 return 1;
1810 case SIM_INST:
1811 case MODEL_INST:
1812 case REL_INST:
1813 case LREL_INST:
1814 case WHEN_INST:
1815 return 0;
1816 case ARRAY_INT_INST:
1817 case ARRAY_ENUM_INST:
1818 abd = GetArrayBaseType(InstanceTypeDesc(ipass));
1819 if (BaseTypeIsConstant(abd)==0 && BaseTypeIsSet(abd)==0) {
1820 return 0;
1821 }
1822 g_unasscon_count = 0;
1823 SilentVisitInstanceTree(ipass,CountUnassignedConst,0,0);
1824 if (g_unasscon_count != 0) {
1825 return 1;
1826 } else {
1827 return 0;
1828 }
1829 case REAL_INST:
1830 case INTEGER_INST:
1831 case BOOLEAN_INST:
1832 case SYMBOL_INST:
1833 case SET_INST:
1834 case REAL_ATOM_INST:
1835 case INTEGER_ATOM_INST:
1836 case BOOLEAN_ATOM_INST:
1837 case SYMBOL_ATOM_INST:
1838 return 0;
1839 case SET_ATOM_INST:
1840 case REAL_CONSTANT_INST:
1841 case BOOLEAN_CONSTANT_INST:
1842 case INTEGER_CONSTANT_INST:
1843 case SYMBOL_CONSTANT_INST:
1844 return (AtomAssigned(ipass)==0); /* return 0 if assigned, 1 not */
1845 default:
1846 return 1; /* NOTREACHED */
1847 }
1848 }
1849 /*
1850 * This function appends the pointers in the set chain s
1851 * into the list given args. args must not be NULL unless s is.
1852 * If needed, args will be expanded, but if you know the length
1853 * to expect, make args of that size before calling and this
1854 * will be faster.
1855 * This does not go into the expressions (which may contain other
1856 * sets themselves) of the set nodes and disassemble them.
1857 * The list may be safely destroyed, but its contents should not
1858 * be destroyed with it as they belong to something else in all
1859 * likelihood.
1860 * This function should be moved into a set header someplace.
1861 */
1862 static
1863 void SplitArgumentSet(CONST struct Set *s, struct gl_list_t *args)
1864 {
1865 struct Set *sp;
1866 if (s==NULL) return;
1867 assert(args !=NULL); /* debug WriteSet(ASCERR,s); FPRINTF(ASCERR,"\n"); */
1868 while (s!=NULL) {
1869 sp = CopySetNode(s);
1870 gl_append_ptr(args,(VOIDPTR)sp);
1871 s = NextSet(s);
1872 }
1873 }
1874
1875 #define GETARG(l,n) ((struct Set *)gl_fetch((l),(n)))
1876
1877 /*
1878 * returns 1 if all ok,
1879 * returns 0 if any array child is < type required,
1880 * returns -1 if some array child is type incompatible with ptype/stype.
1881 * Does some optimization around arrays of sets and array basetypes.
1882 * Doesn't check names.
1883 */
1884 static
1885 int ArrayElementsTypeCompatible(CONST struct Instance *ipass,
1886 CONST struct TypeDescription *ptype,
1887 symchar *stype)
1888 {
1889 struct gl_list_t *achildren=NULL;
1890 CONST struct TypeDescription *atype;
1891 CONST struct TypeDescription *mrtype;
1892 unsigned long c,len,lessrefined=0L;
1893 struct Instance *i;
1894
1895 if (ipass==NULL || ptype == NULL) {
1896 return -1; /* hosed input */
1897 }
1898 assert(IsArrayInstance(ipass) != 0);
1899 atype = GetArrayBaseType(InstanceTypeDesc(ipass));
1900 if (BaseTypeIsSet(atype)==0 && MoreRefined(atype,ptype)==atype) {
1901 /* if not set and if array base is good enough */
1902 return 1;
1903 }
1904 achildren = CollectArrayInstances(ipass,NULL);
1905 len = gl_length(achildren);
1906 for (c = 1; c <= len; c++) {
1907 i = (struct Instance *)gl_fetch(achildren,c);
1908 atype = InstanceTypeDesc(i);
1909 if (InstanceKind(i) == SET_ATOM_INST) {
1910 /* both should be of same type "set" */
1911 if (atype!=ptype ||
1912 (IntegerSetInstance(i)==0 &&
1913 stype == GetBaseTypeName(integer_constant_type))
1914 || (IntegerSetInstance(i)==1 &&
1915 stype == GetBaseTypeName(symbol_constant_type))
1916 ) {
1917 /* set type mismatch */
1918 gl_destroy(achildren);
1919 return -1;
1920 } else {
1921 /* assumption about arrays of sets being sane, if 1 element is. */
1922 gl_destroy(achildren);
1923 return 1;
1924 }
1925 }
1926 if (ptype==atype) {
1927 continue;
1928 }
1929 mrtype = MoreRefined(ptype,atype);
1930 if (mrtype == NULL) {
1931 gl_destroy(achildren);
1932 return -1;
1933 }
1934 if (mrtype == ptype) {
1935 lessrefined++;
1936 }
1937 }
1938 gl_destroy(achildren);
1939 return (lessrefined==0L); /* if any elements are inadequately refined, 0 */
1940 }
1941
1942 /* returns a value_t, but the real result is learned by consulting err.
1943 * err == 0 means some interesting value found.
1944 * err == 1 means try again later
1945 * err == -1 means things are hopeless.
1946 */
1947 static
1948 struct value_t FindArgValue(struct Instance *parent,
1949 struct Set *argset,
1950 int *err)
1951 {
1952 int previous_context;
1953 struct value_t value;
1954
1955 assert(err!=NULL);
1956 *err=0;
1957 previous_context = GetDeclarativeContext();
1958 SetDeclarativeContext(0);
1959 assert(GetEvaluationContext()==NULL);
1960 SetEvaluationContext(parent);
1961 value = EvaluateExpr(GetSingleExpr(argset),
1962 NULL,
1963 InstanceEvaluateName);
1964 SetEvaluationContext(NULL);
1965 SetDeclarativeContext(previous_context);
1966 if (ValueKind(value)==error_value) {
1967 switch(ErrorValue(value)){
1968 case name_unfound:
1969 *err = 1;
1970 DestroyValue(&value);
1971 return CreateErrorValue(undefined_value);
1972 case undefined_value:
1973 *err = 1;
1974 return value;
1975 default:
1976 *err = -1;
1977 }
1978 }
1979 if (IsConstantValue(value)==0){
1980 *err = -1;
1981 DestroyValue(&value);
1982 return CreateErrorValue(type_conflict);
1983 }
1984 return value;
1985 }
1986
1987 /* return codes and message handling for MakeParameterInst */
1988 #define MPIOK 1
1989 #define MPIWAIT 0
1990 #define MPIINPUT -1
1991 #define MPIARGTYPE -2
1992 #define MPIARRINC -3
1993 #define MPIBADASS -4
1994 #define MPIARRRNG -5
1995 #define MPIINSMEM -6
1996 #define MPIBADARG -7
1997 #define MPIMULTI -8
1998 #define MPIBADVAL -9
1999 #define MPIWEIRD -10
2000 #define MPIUNMADE -11
2001 #define MPIWEAKTYPE -12
2002 #define MPIUNASSD -13
2003 #define MPIARGVAL -14
2004 #define MPIARGSIZ -15
2005 #define MPIBADWBTS -16
2006 #define MPIBADWNBTS -17
2007 #define MPIBADMERGE -18
2008 #define MPIREASGN -19
2009 #define MPIREDEF -20
2010 #define MPIFOR -21
2011 #define MPIBADREL -22
2012 #define MPIEXCEP -23
2013 #define MPIVARREL -24
2014 #define MPINOTBOOL -25
2015 static
2016 char *g_mpi_message[] = {
2017 /* 0 */ "Nothing wrong with parameter",
2018 /* -1 */ "Bad input statement or parent or arginstptr.",
2019 /* -2 */ "Incompatible argument type.",
2020 /* -3 */ "Incomplete assignment of absorbed pass-by-value array.",
2021 /* -4 */ "Error in absorbed assignment RHS.",
2022 /* -5 */ "Mismatch in range of array subscripts.",
2023 /* -6 */ "Insufficient memory - crashing soon",
2024 /* -7 */ "Nonexistent argument. (bad set in array expression, probably)",
2025 /* -8 */ "Too many instances named for 1 parameter slot",
2026 /* -9 */ "Bad expression passed to IS_A",
2027 /* -10 */ "Something rotten in lint",
2028 /* -11 */ "Instance doesn't yet exist",
2029 /* -12 */ "Instance not sufficiently refined",
2030 /* -13 */ "Argument value not assigned",
2031 /* -14 */ "Argument value != required value",
2032 /* -15 */ "Array object given has with too many/too few subscripts.",
2033 /* -16 */ "Incorrect instance named in WILL_BE_THE_SAME.",
2034 /* -17 */ "Nonexistent instance named in WILL_NOT_BE_THE_SAME.",
2035 /* -18 */ "Merged instances found in WILL_NOT_BE_THE_SAME.",
2036 /* -19 */ "Refinement cannot reassign constant value.",
2037 /* -20 */ "Refinement must pass in same objects used in IS_A.",
2038 /* -21 */ "Improper FOR loop in WHERE statements",
2039 /* -22 */ "WHERE condition unsatisfied",
2040 /* -23 */ "WHERE condition incorrect (system exception occurred)",
2041 /* -24 */ "WHERE condition incorrect (nonconstant value)",
2042 /* -25 */ "WHERE condition incorrect (nonboolean value)"
2043 };
2044
2045 /* Returns MPIOK if value in ipass matches WITH_VALUE field of
2046 * statement, or if the test is silly beacause ipass isn't
2047 * a set/constant or if statement does not constrain value.
2048 * Returns MPIWAIT if statement truth cannot be tested because
2049 * WITH_VALUE clause is not yet evaluatable.
2050 * Returns MPIARGVAL if WITH_VALUE is provably unsatisfied.
2051 * On truly garbage input, unlikely to return.
2052 */
2053 static
2054 int ArgValueCorrect(struct Instance *inst,
2055 struct Instance *tmpinst,
2056 CONST struct Statement *statement)
2057 {
2058 CONST struct Expr *check;
2059 int previous_context;
2060 struct value_t value;
2061
2062 assert (inst!=NULL);
2063 assert (tmpinst!=NULL);
2064 assert (statement!=NULL);
2065
2066 if ( StatementType(statement)!= WILLBE ||
2067 (check = GetStatCheckValue(statement)) == NULL ||
2068 ( IsConstantInstance(inst) ==0 &&
2069 InstanceKind(inst) != SET_ATOM_INST)
2070 ) {
2071 return MPIOK;
2072 }
2073 if (!AtomAssigned(inst)) {
2074 return MPIWAIT;
2075 }
2076 previous_context = GetDeclarativeContext();
2077 SetDeclarativeContext(0);
2078 assert(GetEvaluationContext()==NULL);
2079 SetEvaluationContext(tmpinst);
2080 value = EvaluateExpr(check, NULL, InstanceEvaluateName);
2081 SetEvaluationContext(NULL);
2082 SetDeclarativeContext(previous_context);
2083 if (ValueKind(value)==error_value) {
2084 switch(ErrorValue(value)){
2085 case name_unfound:
2086 case undefined_value:
2087 DestroyValue(&value);
2088 return MPIWAIT;
2089 default:
2090 DestroyValue(&value);
2091 return MPIARGVAL;
2092 }
2093 }
2094 if (IsConstantValue(value)==0){
2095 DestroyValue(&value);
2096 FPRINTF(ASCERR,"Variable value found where constant required\n");
2097 return MPIARGVAL;
2098 }
2099 /* ok, so we have a reasonable inst type and a constant value */
2100 switch(InstanceKind(inst)){
2101 case REAL_CONSTANT_INST:
2102 switch(ValueKind(value)){
2103 case real_value:
2104 if ( ( RealValue(value) != RealAtomValue(inst) ||
2105 !SameDimen(RealValueDimensions(value),RealAtomDims(inst)) )
2106 ) {
2107 DestroyValue(&value);
2108 return MPIARGVAL;
2109 }
2110 break;
2111 case integer_value:
2112 if ( ( (double)IntegerValue(value) != RealAtomValue(inst) ||
2113 !SameDimen(Dimensionless(),RealAtomDims(inst)) )
2114 ) {
2115 DestroyValue(&value);
2116 return MPIARGVAL;
2117 }
2118 break;
2119 default:
2120 DestroyValue(&value);
2121 return MPIARGVAL;
2122 }
2123 break;
2124 case BOOLEAN_CONSTANT_INST:
2125 if (ValueKind(value)!=boolean_value ||
2126 BooleanValue(value) != GetBooleanAtomValue(inst) ) {
2127 DestroyValue(&value);
2128 return MPIARGVAL;
2129 }
2130 break;
2131 case INTEGER_CONSTANT_INST:
2132 switch(ValueKind(value)){
2133 case integer_value:
2134 if (GetIntegerAtomValue(inst)!=IntegerValue(value)) {
2135 DestroyValue(&value);
2136 return MPIARGVAL;
2137 }
2138 break;
2139 case real_value: /* case which is parser artifact: real, wild 0 */
2140 if ( RealValue(value)==0.0 &&
2141 IsWild(RealValueDimensions(value)) &&
2142 GetIntegerAtomValue(inst) != 0) {
2143 DestroyValue(&value);
2144 return MPIARGVAL;
2145 }
2146 break;
2147 default:
2148 DestroyValue(&value);
2149 return MPIARGVAL;
2150 }
2151 break;
2152 case SET_ATOM_INST:
2153 if (ValueKind(value)!=set_value ||
2154 !SetsEqual(SetValue(value),SetAtomList(inst))) {
2155 DestroyValue(&value);
2156 return MPIARGVAL;
2157 }
2158 break;
2159 case SYMBOL_CONSTANT_INST:
2160 if (ValueKind(value) != symbol_value ||
2161 SymbolValue(value) != GetSymbolAtomValue(inst)) {
2162 assert(AscFindSymbol(SymbolValue(value))!=NULL);
2163 DestroyValue(&value);
2164 return MPIARGVAL;
2165 }
2166 break;
2167 default:
2168 DestroyValue(&value);
2169 return MPIARGVAL;
2170 }
2171 DestroyValue(&value);
2172 return MPIOK;
2173 }
2174
2175 /* evaluate a logical or real relation and see that it
2176 * is satisfied.
2177 * BUG baa. needs to be exception safe and is not.
2178 * returns MPIOK (satisfied)
2179 * returns MPIBADREL (dissatisified)
2180 * returns MPIVARREL (dissatisified - variable result)
2181 * returns MPIWAIT (not yet determinable)
2182 * returns MPIEXCEP (evaluation is impossible due to float/other error)
2183 * returns MPINOTBOOL (dissatisfied- nonboolean result)
2184 * statement given should be a rel or logrel.
2185 */
2186 static
2187 int MPICheckConstraint(struct Instance *tmpinst, struct Statement *statement)
2188 {
2189 struct value_t value;
2190
2191 IVAL(value);
2192
2193 assert(GetEvaluationContext()==NULL);
2194 SetEvaluationContext(tmpinst);
2195 switch (StatementType(statement)){
2196 case REL:
2197 value = EvaluateExpr(RelationStatExpr(statement),NULL,
2198 InstanceEvaluateName);
2199 break;
2200 case LOGREL:
2201 value = EvaluateExpr(LogicalRelStatExpr(statement),NULL,
2202 InstanceEvaluateName);
2203 break;
2204 default:
2205 SetEvaluationContext(NULL);
2206 return MPIWEIRD;
2207 }
2208 SetEvaluationContext(NULL);
2209 switch (ValueKind(value)){
2210 case error_value:
2211 switch(ErrorValue(value)){
2212 case undefined_value:
2213 DestroyValue(&value);
2214 WriteUnexecutedMessage(ASCERR,statement,
2215 "Incomplete expression (value undefined) in argument condition.");
2216 return MPIWAIT;
2217 case name_unfound:
2218 DestroyValue(&value);
2219 WriteUnexecutedMessage(ASCERR,statement,
2220 "Incomplete expression (name unfound) in argument condition.");
2221 return MPIWAIT;
2222 default:
2223 /* it questionable whether this is a correct action in all cases*/
2224 /* we could probably turn out more useful error messages here */
2225 WSEM(ASCERR,statement, "Condition doesn't make sense.");
2226 DestroyValue(&value);
2227 return MPIBADREL;
2228 }
2229 case boolean_value:
2230 if (IsConstantValue(value)!=0) {
2231 if (BooleanValue(value) != FALSE) {
2232 DestroyValue(&value);
2233 return MPIOK;
2234 } else {
2235 DestroyValue(&value);
2236 WSEM(ASCERR,statement, "Arguments do not conform to requirements");
2237 return MPIBADREL;
2238 }
2239 } else {
2240 DestroyValue(&value);
2241 WSEM(ASCERR,statement, "Requirements cannot be satisfied by variables");
2242 return MPIVARREL;
2243 }
2244 default:
2245 DestroyValue(&value);
2246 WSEM(ASCERR,statement, "Constraint does not evaluate to boolean result.");
2247 return MPINOTBOOL;
2248 }
2249 }
2250
2251 /*
2252 * returns MPIOK if subscripts match declarations,
2253 * MPIWAIT if declarations cannot yet be interpretted,
2254 * or some other error if there is a mismatch.
2255 * So far only the square version. Should have a forvar
2256 * capable recursive version sometime when we allow
2257 * passage of sparse arrays.
2258 * Assumes the array given has proper number of
2259 * subscripts to match name and is fully expanded.
2260 */
2261 static
2262 int MPICheckSubscripts(struct Instance *tmpinst,
2263 struct Instance *aryinst,
2264 struct Statement *s)
2265 {
2266 CONST struct Name *nptr;
2267
2268 nptr = NextName(NamePointer(GetStatVarList(s)));
2269 switch (RectangleSubscriptsMatch(tmpinst,aryinst,nptr)) {
2270 case -2:
2271 return MPIWAIT;
2272 case 1:
2273 return MPIOK;
2274 case 0:
2275 default:
2276 return MPIARRRNG;
2277 }
2278 }
2279
2280 /* links parent and child. if checkdup != 0,
2281 * it will check child to see if it already has this parent.
2282 */
2283 #define NOIPICHECK 0
2284 #define IPICHECK 1
2285 static
2286 int InsertParameterInst(struct Instance *parent,
2287 struct Instance *child,
2288 CONST struct Name *name,
2289 CONST struct Statement *statement,
2290 int checkdup)
2291 {
2292 symchar *childname;
2293 struct InstanceName rec;
2294 unsigned long pos;
2295
2296 childname = NameIdPtr(name);
2297 SetInstanceNameType(rec,StrName);
2298 SetInstanceNameStrPtr(rec,childname);
2299 pos = ChildSearch(parent,&rec);
2300 if (pos>0) {
2301 if (InstanceChild(parent,pos)==NULL) {
2302 StoreChildPtr(parent,pos,child);
2303 if (checkdup == 0 || SearchForParent(child,parent)==0) {
2304 /* case where we don't already have it at this scope */
2305 AddParent(child,parent);
2306 }
2307 return 1;
2308 } else { /* redefining instance */
2309 char *msg = ascmalloc(SCLEN(childname)+
2310 strlen(REDEFINE_CHILD_MESG)+1);
2311 strcpy(msg,REDEFINE_CHILD_MESG);
2312 strcat(msg,SCP(childname));
2313 WSEM(ASCERR,statement,msg);
2314 ascfree(msg);
2315 return 0;
2316 }
2317 } else { /* unknown name */
2318 WSEM(ASCERR,statement, "Unknown parameter name. Never should happen");
2319 Asc_Panic(2, NULL, "Unknown parameter name. Never should happen");
2320 exit(2);/* Needed to keep gcc from whining */
2321 }
2322 }
2323
2324 /*
2325 * The instance this is called with should not have
2326 * any parents whatsoever. The instance this is called
2327 * with will be completely destroyed including any parts
2328 * of the instance that do not have other parents.
2329 */
2330 static
2331 void DestroyParameterInst(struct Instance *i)
2332 {
2333 DestroyInstance(i,NULL);
2334 }
2335 /* destroys everything you send it. If you send some arguments in
2336 * as null, we don't mind.
2337 */
2338 static
2339 void ClearMPImem(
2340 struct gl_list_t *args,
2341 struct gl_list_t *il,
2342 struct Instance *tmpinst,
2343 struct Instance *ipass,
2344 struct value_t *valp
2345 )
2346 {
2347 if (args!=NULL) {
2348 gl_iterate(args,(void (*)(VOIDPTR))DestroySetNode);
2349 gl_destroy(args);
2350 }
2351 if (il!=NULL) {
2352 gl_destroy(il);
2353 }
2354 if (tmpinst!=NULL) {
2355 DestroyParameterInst(tmpinst);
2356 }
2357 if (ipass!=NULL) {
2358 DestroyParameterInst(ipass);
2359 }
2360 if (valp!=NULL) {
2361 DestroyValue(valp);
2362 }
2363 }
2364
2365
2366 static
2367 void mpierror(struct Set *argset,
2368 unsigned long argn,
2369 struct Statement *statement,
2370 int errcode)
2371 {
2372 int arrloc;
2373 if (errcode<0) {
2374 arrloc = (-errcode);
2375 } else {
2376 return;
2377 /* why are we here? */
2378 }
2379 FPRINTF(ASCERR,"Parameter passing error: %s\n",g_mpi_message[arrloc]);
2380 if (argset !=NULL && argn >0) {
2381 FPRINTF(ASCERR," Argument %lu:",argn);
2382 WriteSet(ASCERR,argset);
2383 FPRINTF(ASCERR,"\n");
2384 }
2385 WSEM(ASCERR,statement,"Error in executing statement:");
2386 MarkStatContext(statement,context_WRONG);
2387 WSS(ASCERR,statement);
2388 }
2389
2390 static
2391 void MPIwum(struct Set *argset,
2392 unsigned long argn,
2393 struct Statement *statement,
2394 int msgcode)
2395 {
2396 int arrloc;
2397 if (g_iteration < MAXNUMBER) {
2398 return;
2399 }
2400 if (msgcode<0) {
2401 arrloc = (-msgcode);
2402 } else {
2403 return;
2404 /* why are we here? */
2405 }
2406 FPRINTF(ASCERR,"Parameter list waiting on sufficient type or value of:\n");
2407 if (argset !=NULL && argn >0) {
2408 FPRINTF(ASCERR," Argument %lu:",argn);
2409 WriteSetNode(ASCERR,argset);
2410 FPRINTF(ASCERR,"\n");
2411 }
2412 WriteUnexecutedMessage(ASCERR,statement,g_mpi_message[arrloc]);
2413 }
2414
2415 /* process pass by value scalar: evaluate and make it, or return
2416 * appropriate whine if not possible.
2417 * If this returns anything other than mpiok, the user may
2418 * wish to dispose of tmpinst, args as we do not here.
2419 * We do issue whines here, however.
2420 */
2421 static
2422 int MPIMakeSimple(struct Instance *parent,
2423 struct Instance *tmpinst,
2424 struct Set *argset,
2425 unsigned long argn,
2426 CONST struct Name *nptr,
2427 struct TypeDescription *ptype,
2428 int intset,
2429 struct Statement *ps,
2430 struct Statement *statement
2431 )
2432 {
2433 int tverr; /* error return from checking array elt type, or value */
2434 struct Instance *ipass;
2435 struct value_t vpass;
2436
2437 vpass = FindArgValue(parent,argset,&tverr);
2438 if (tverr != 0) {
2439 if (tverr == 1) { /* try later */
2440 MPIwum(argset,argn,statement,MPIUNASSD);
2441 return MPIWAIT;
2442 } else { /* hopeless */
2443 mpierror(argset,argn,statement,MPIBADVAL);
2444 return MPIBADVAL;
2445 }
2446 }
2447 /* don't forget to dispose of vpass if exiting err after here */
2448 ipass = MakeSimpleInstance(ptype,intset,ps,NULL);
2449 if (ipass==NULL) {
2450 DestroyValue(&vpass);
2451 return MPIINSMEM;
2452 }
2453 /* don't forget to dispose of vpass if exiting err after here */
2454 if (AssignStructuralValue(ipass,vpass,statement)!=1) {
2455 mpierror(argset,argn,statement,MPIARGTYPE);
2456 DestroyParameterInst(ipass);
2457 DestroyValue(&vpass);
2458 return MPIARGTYPE;
2459 }
2460 DestroyValue(&vpass);
2461 /* install ipass in tmpinst */
2462 if ( InsertParameterInst(tmpinst,ipass,nptr,ps,IPICHECK) != 1) {
2463 /* noipicheck because var just created has no parents at all,
2464 * unless of course var is UNIVERSAL... so ipicheck */
2465 mpierror(argset,argn,statement,MPIMULTI);
2466 DestroyParameterInst(ipass);
2467 return MPIMULTI;
2468 }
2469 return MPIOK;
2470 }
2471 #define NOKEEPARGINST 0
2472 #define KEEPARGINST 1
2473 /*
2474 * This function is responsible for checking and assembling the
2475 * arguments of the parameterized type referenced in statement,
2476 * using information derived from the parent instance.
2477 * If the type found in the statement given is not a MODEL type,
2478 * we will immediately return 1 and *arginstptr will be set NULL.
2479 *
2480 * In general, we are trying to check and assemble enough information
2481 * to prove that a parameterized IS_A can be executed or proved wrong
2482 * once ExecuteISA sees it.
2483 *
2484 * If keepargs ==KEEPARGINST, then on a successful return,
2485 * *arginstptr will be to a MODEL instance (with no parents)
2486 * with its children derived via parameter list filled in and
2487 * all other children NULL.
2488 * If there are NO children derived via parameter list or
2489 * the reductions list, then *arginstptr will be NULL.
2490 * If keepargs != KEEPARGINST, then arginstptr will not be
2491 * used/set in any way, OTHERWISE it should be NULL on entry.
2492 * If keepargs != KEEPARGINST, then we will do only the minimal
2493 * necessary work to check that the arginst could be created.
2494 * At present, we can't tell what this last ambition amounts to -
2495 * we do the same amount of work regardless, though we try to put
2496 * the more likely to fail steps first.
2497 *
2498 * A successful return value is 1.
2499 *
2500 * A failure possibly to succeed later is 0.
2501 * Possible causes will be detailed via the WriteUnexecutedMessage
2502 * facility.
2503 *
2504 * A permanent failure is any value < 0.
2505 * Causes will be detailed via the WSEM facility, in addition return
2506 * values < 0 have the interpretations given in g_mpi_message[-value]
2507 * above.
2508 */
2509 /*
2510 * assumes statement is well formed, in terms of
2511 * arglist of IS_A/IS_REFINED_TO (if there is one) being of correct length.
2512 * returns fairly quickly for nonmodel and nonparametric
2513 * MODEL types.
2514 */
2515 static
2516 int MakeParameterInst(struct Instance *parent,
2517 struct Statement *statement,
2518 struct Instance **arginstptr,
2519 int keepargs)
2520 {
2521 struct TypeDescription *d; /* the type we are constructing or checking */
2522 struct TypeDescription *atype; /* the type we are being passed */
2523 struct TypeDescription *ptype; /* the type we are expecting */
2524 struct TypeDescription *mrtype; /* the more refined of two types */
2525 symchar *stype; /* the set type we are expecting */
2526 struct gl_list_t *args; /* parameter Set given split for easy access */
2527 struct gl_list_t *il; /* instance(s) required to digest a parameter */
2528 struct Instance *ipass; /* instance being passed into type */
2529 struct Instance *tmpinst; /* holding instance for derivation work. */
2530 struct StatementList *psl; /* list of parameters the type requires */
2531 struct StatementList *absorbed; /* list of absorbed isas and casgns */
2532 struct Statement *ps; /* a statement from psl */
2533 struct Set *argset; /* set element extracted from arglist */
2534 CONST struct VariableList *vl;
2535 struct for_table_t *SavedForTable;
2536 unsigned long slen,c,argn;
2537 int tverr; /* error return from checking array elt type, or value */
2538 int suberr; /* error return from other routine */
2539 int intset;
2540 enum find_errors ferr;
2541 unsigned int pc; /* number of parameters the type requires */
2542
2543 if (StatWrong(statement)) {
2544 /* incorrect statements should be warned about when they are
2545 * marked wrong, so we just ignore them here.
2546 */
2547 return MPIOK;
2548 }
2549 d = FindType(GetStatType(statement));
2550 if (d==NULL) {
2551 /* lint should make this impossible */
2552 mpierror(NULL,0L,statement,MPIINPUT);
2553 return MPIINPUT;
2554 }
2555 if (keepargs == KEEPARGINST && arginstptr == NULL) {
2556 /* someone screwed up the call, but maybe they get it right later. */
2557 FPRINTF(ASCERR," *** MakeParameterInst miscalled *** \n");
2558 return MPIWAIT;
2559 }
2560 if (keepargs == KEEPARGINST) {
2561 /* init arginstptr */
2562 *arginstptr = NULL;
2563 }
2564 if ( GetBaseType(d)!=model_type) {
2565 return MPIOK;
2566 }
2567 pc = GetModelParameterCount(d);
2568 absorbed = GetModelAbsorbedParameters(d);
2569 if (pc==0 && StatementListLength(absorbed)==0L) {
2570 /* no parameters in this type or its ancestors */
2571 return MPIOK;
2572 }
2573 /* init tmpinst, which we must remember to punt before
2574 * error returns or nokeep returns.
2575 */
2576 /* may want an SCMUI here, not sure. */
2577 tmpinst = CreateModelInstance(d);
2578 if (tmpinst==NULL) {
2579 mpierror(NULL,0L,statement,MPIINPUT);
2580 return MPIINSMEM;
2581 }
2582 args = gl_create((unsigned long)pc);
2583 if (args == NULL) {
2584 mpierror(NULL,0L,statement,MPIINPUT);
2585 ClearMPImem(NULL,NULL,tmpinst,NULL,NULL);
2586 return MPIINSMEM;
2587 }
2588 SplitArgumentSet(GetStatTypeArgs(statement),args);
2589 /* due to typelint, the following assertion should pass. fix lint if not. */
2590 assert(gl_length(args)==(unsigned long)pc);
2591 psl = GetModelParameterList(d);
2592 slen = StatementListLength(psl);
2593 argn = 1L;
2594 for (c = 1; c <= slen; c++) {
2595 ps = GetStatement(psl,c);
2596 vl = GetStatVarList(ps); /* move inside switch if allow FOR later */
2597 ptype = FindType(GetStatType(ps));
2598 stype = GetStatSetType(ps);
2599 intset = CalcSetType(stype,ps);
2600 if (intset <0 || intset >1) {
2601 /* shouldn't be possible -- typelint trapped */
2602 mpierror(NULL,0L,statement,MPIARGTYPE);
2603 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2604 return MPIARGTYPE;
2605 }
2606 switch (StatementType(ps)) {
2607 case WILLBE:
2608 while (vl != NULL) {
2609 argset = GETARG(args,argn);
2610 il = FindArgInsts(parent,argset,&ferr);
2611 if (il == NULL) {
2612 switch(ferr) {
2613 case unmade_instance:
2614 case undefined_instance: /* this case ought to be separable */
2615 MPIwum(argset,argn,statement,MPIUNMADE);
2616 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2617 return MPIWAIT;
2618 case impossible_instance:
2619 mpierror(argset,argn,statement,MPIBADARG);
2620 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2621 return MPIBADARG;
2622 case correct_instance:
2623 mpierror(argset,argn,statement,MPIWEIRD);
2624 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2625 return MPIWEIRD;
2626 }
2627 }
2628 if (gl_length(il)!=1L) {
2629 mpierror(argset,argn,statement,MPIMULTI);
2630 ClearMPImem(args,il,tmpinst,NULL,NULL);
2631 return MPIMULTI;
2632 }
2633 ipass = (struct Instance *)gl_fetch(il,1L);
2634 gl_destroy(il);
2635 il = NULL;
2636 if (SimpleNameIdPtr(NamePointer(vl))==NULL) {
2637 /* arg required is an array, check this.
2638 * check complete expansion of arg, constant type or not.
2639 * check compatible base type of all elements with spec-
2640 * note we haven't checked subscript ranges at this point.
2641 */
2642 if (IsArrayInstance(ipass)==0) {
2643 mpierror(argset,argn,statement,MPIARGTYPE);
2644 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2645 return MPIARGTYPE;
2646 }
2647 if (RectangleArrayExpanded(ipass)==0) {
2648 /* this works for sparse or dense because sparse won't
2649 * exist except in the fully expanded state due to
2650 * the construction all at once.
2651 */
2652 MPIwum(argset,argn,statement,MPIUNMADE);
2653 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2654 return MPIWAIT;
2655 }
2656 if (NumberofDereferences(ipass) !=
2657 (unsigned long)(NameLength(NamePointer(vl)) - 1)) {
2658 /* I may need an offset other than -1 here */
2659 mpierror(argset,argn,statement,MPIARGSIZ);
2660 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2661 return MPIARGTYPE;
2662 }
2663 tverr = ArrayElementsTypeCompatible(ipass,ptype,stype);
2664 switch (tverr) {
2665 case 1:
2666 /* happy happy joy joy */
2667 break;
2668 case 0:
2669 MPIwum(argset,argn,statement,MPIWEAKTYPE);
2670 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2671 return MPIWAIT;
2672 default:
2673 mpierror(argset,argn,statement,MPIARGTYPE);
2674 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2675 return MPIARGTYPE;
2676 }
2677 if (ArgValuesUnassigned(ipass)!=0) {
2678 MPIwum(argset,argn,statement,MPIUNASSD);
2679 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2680 return MPIWAIT;
2681 }
2682 } else {
2683 /* arg must be scalar/set/MODEL */
2684 atype = InstanceTypeDesc(ipass);
2685 if (atype==ptype) {
2686 /* we're happy unless sets of mismatched base */
2687 if (stype!=NULL) {
2688 if ((IntegerSetInstance(ipass)!=0 && intset==0) ||
2689 (IntegerSetInstance(ipass)==0 && intset==1)) {
2690 mpierror(argset,argn,statement,MPIARGTYPE);
2691 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2692 return MPIARGTYPE;
2693 }
2694 }
2695 } else {
2696 mrtype = MoreRefined(atype,ptype);
2697 if (mrtype==NULL) {
2698 mpierror(argset,argn,statement,MPIARGTYPE);
2699 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2700 return MPIARGTYPE;
2701 }
2702 if (mrtype==ptype) {
2703 /* arg is less refined than param spec. maybe better later */
2704 MPIwum(argset,argn,statement,MPIWEAKTYPE);
2705 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2706 return MPIWAIT;
2707 }
2708 }
2709 if (ArgValuesUnassigned(ipass)!=0) {
2710 MPIwum(argset,argn,statement,MPIUNASSD);
2711 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2712 return MPIWAIT;
2713 }
2714 /* here we check against WITH_VALUE clause, if one in ps */
2715 suberr = ArgValueCorrect(ipass,tmpinst,ps);
2716 switch(suberr) {
2717 case MPIOK:
2718 break;
2719 case MPIWAIT:
2720 /* can only occur if other portions of tmpinst needed to compute
2721 * check value are not in place yet. no wum here because
2722 * Digest below will catch it if it's broken.
2723 */
2724 break;
2725 /* may need additional cases depending on argval implementation */
2726 default:
2727 mpierror(argset,argn,statement,MPIARGVAL);
2728 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2729 }
2730 }
2731 /* install ipass in tmpinst */
2732 if ( InsertParameterInst(tmpinst,ipass,NamePointer(vl),ps,IPICHECK)
2733 !=1) {
2734 /* ipicheck because we might be passed same instance in 2 slots */
2735 mpierror(argset,argn,statement,MPIMULTI);
2736 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2737 return MPIMULTI;
2738 }
2739 argn++;
2740 vl = NextVariableNode(vl);
2741 }
2742 break;
2743 case ISA:
2744 argset = GETARG(args,argn);
2745 if (SimpleNameIdPtr(NamePointer(vl))!=NULL) {
2746 /* scalar: evaluate and make it */
2747 suberr = MPIMakeSimple(parent,tmpinst,argset,argn,
2748 NamePointer(vl),ptype,intset,ps,statement);
2749 if (suberr!=MPIOK) {
2750 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2751 return suberr;
2752 }
2753 } else {
2754 /* check completedness, assignedness, base type of array-by-value
2755 * and copy. Note that what we copy may prove to be incompatible
2756 * later when we check the names of subscripts.
2757 */
2758 il = FindArgInsts(parent,argset,&ferr);
2759 if (il == NULL) {
2760 switch(ferr) {
2761 case unmade_instance:
2762 case undefined_instance: /* this case ought to be separable */
2763 MPIwum(argset,argn,statement,MPIUNMADE);
2764 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2765 return MPIWAIT;
2766 case impossible_instance:
2767 mpierror(argset,argn,statement,MPIBADARG);
2768 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2769 return MPIBADARG;
2770 case correct_instance:
2771 mpierror(argset,argn,statement,MPIWEIRD);
2772 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2773 return MPIWEIRD;
2774 }
2775 }
2776 if (gl_length(il)!=1L) {
2777 mpierror(argset,argn,statement,MPIMULTI);
2778 ClearMPImem(args,il,tmpinst,NULL,NULL);
2779 return MPIMULTI;
2780 }
2781 ipass = (struct Instance *)gl_fetch(il,1L);
2782 gl_destroy(il);
2783 il = NULL;
2784 /* arg required is an array, check this.
2785 * check complete expansion of arg, constant type or not.
2786 * check compatible base type of all elements with spec-
2787 * note we haven't checked subscript ranges at this point.
2788 */
2789 if (IsArrayInstance(ipass)==0) {
2790 mpierror(argset,argn,statement,MPIARGTYPE);
2791 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2792 return MPIARGTYPE;
2793 }
2794 if (RectangleArrayExpanded(ipass)==0) {
2795 /* this works for spare or dense because sparse won't
2796 * exist except in the fully expanded state due to
2797 * the construction all at once.
2798 */
2799 MPIwum(argset,argn,statement,MPIUNMADE);
2800 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2801 return MPIWAIT;
2802 }
2803 if (NumberofDereferences(ipass) !=
2804 (unsigned long)(NameLength(NamePointer(vl)) - 1)) {
2805 /* I may need an offset other than -1 here */
2806 mpierror(argset,argn,statement,MPIARGSIZ);
2807 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2808 return MPIARGTYPE;
2809 }
2810 tverr = ArrayElementsTypeCompatible(ipass,ptype,stype);
2811 switch (tverr) {
2812 case 1:
2813 /* happy happy joy joy */
2814 break;
2815 case 0:
2816 /* wum here */
2817 MPIwum(argset,argn,statement,MPIWEAKTYPE);
2818 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2819 return MPIWAIT;
2820 default:
2821 mpierror(argset,argn,statement,MPIARGTYPE);
2822 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2823 return MPIARGTYPE;
2824 }
2825 if (ArgValuesUnassigned(ipass)!=0) {
2826 MPIwum(argset,argn,statement,MPIUNASSD);
2827 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2828 return MPIWAIT;
2829 }
2830 /* this copy will mess up tmpnums in old ipass. */
2831 ipass = CopyInstance(ipass);
2832 /* note the copy has only been verified to work for completed
2833 * arrays of constants, not models.
2834 */
2835 /* we don't care about the old ipass any more. check new one. */
2836 if (ipass==NULL) {
2837 mpierror(argset,argn,statement,MPIINSMEM);
2838 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2839 return MPIMULTI;
2840 }
2841 /* install ipass in tmpinst */
2842 if ( InsertParameterInst(tmpinst,ipass,NamePointer(vl),ps,NOIPICHECK)
2843 !=1 /* arrays cannot be UNIVERSAL */ ) {
2844 mpierror(argset,argn,statement,MPIMULTI);
2845 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2846 return MPIMULTI;
2847 }
2848 /* we still need to check the subscripts for compatibility with
2849 * arg description. can't do yet.
2850 */
2851 }
2852 argn++;
2853 break;
2854 default:
2855 Asc_Panic(2, NULL, "how the hell did typelint let that through?");
2856 /* how the hell did typelint let that through? */
2857 break;
2858 }
2859 }
2860 /* ok, so now we have everything passed (which might be nothing)
2861 * in place. We need to check WITH_VALUE's, subscript ranges,
2862 * and insist all scalars end up assigned while processing
2863 * the absorbed statements. Possibly may still find undefined
2864 * values in rhs of assignments or in subscript ranges, drat.
2865 * May take several passes.
2866 */
2867
2868 suberr = DigestArguments(tmpinst,args,psl,absorbed,statement); /*1*/
2869 switch(suberr) {
2870 case MPIOK:
2871 break;
2872 case MPIWAIT:
2873 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2874 return MPIWAIT;
2875 default:
2876 /* anything else is an error. mpierror will have been called. */
2877 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2878 return MPIINPUT;
2879 }
2880
2881 /* ok, now we need to check where statement list. */
2882 SavedForTable = GetEvaluationForTable();
2883 SetEvaluationForTable(CreateForTable());
2884 suberr = CheckWhereStatements(tmpinst,GetModelParameterWheres(d));
2885 DestroyForTable(GetEvaluationForTable());
2886 SetEvaluationForTable(SavedForTable);
2887 switch(suberr) {
2888 case MPIOK:
2889 break;
2890 case MPIWAIT:
2891 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2892 return MPIWAIT;
2893 default:
2894 /* anything else is an error */
2895 ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2896 mpierror(NULL,0,statement,suberr);
2897 return suberr;
2898 }
2899
2900 ClearMPImem(args,NULL,NULL,NULL,NULL);
2901 if (keepargs == KEEPARGINST) {
2902 *arginstptr = tmpinst;
2903 } else {
2904 DestroyParameterInst(tmpinst);
2905 }
2906 return MPIOK;
2907 }
2908
2909 static
2910 int MPICheckWBTS(struct Instance *tmpinst, struct Statement *statement)
2911 {
2912 struct gl_list_t *instances;
2913 unsigned long c,len;
2914 enum find_errors err;
2915 struct Instance *head = NULL;
2916
2917 instances = FindInsts(tmpinst,GetStatVarList(statement),&err);
2918 if (instances==NULL) {
2919 switch(err){
2920 case impossible_instance:
2921 MissingInsts(tmpinst,GetStatVarList(statement),1);
2922 WSEM(ASCERR,statement,
2923 "WILL_BE_THE_SAME statement contains an impossible instance name");
2924 return MPIBADWBTS;
2925 default:
2926 MissingInsts(tmpinst,GetStatVarList(statement),0);
2927 WriteUnexecutedMessage(ASCERR,statement,
2928 "Incomplete instances in WILL_BE_THE_SAME");
2929 return MPIWAIT; /* statement is not ready to be executed */
2930 }
2931 }
2932 len = gl_length(instances);
2933 if (len >0 ) {
2934 head = gl_fetch(instances,1);
2935 }
2936 for (c=2; c<=len; c++) {
2937 if (((struct Instance *)gl_fetch(instances,c)) != head) {
2938 if (IsArrayInstance(head)==0 &&
2939 MoreRefined(InstanceTypeDesc(gl_fetch(instances,c)),
2940 InstanceTypeDesc(head))==NULL) {
2941 /* can't be merged later */
2942 WSEM(ASCERR,statement,
2943 "WILL_BE_THE_SAME statement contains incompatible instances");
2944 gl_destroy(instances);
2945 return MPIBADWBTS;
2946 } else {
2947 /* maybe merge later */
2948 WriteUnexecutedMessage(ASCERR,statement,
2949 "Unmerged instances in WILL_BE_THE_SAME");
2950 gl_destroy(instances);
2951 return MPIWAIT;
2952 }
2953 }
2954 }
2955 gl_destroy(instances);
2956 return MPIOK;
2957 }
2958
2959 #define MPICheckWB(a,b) MPIWEIRD
2960 /* WILL_BE not yet legal in where section. implement later if req'd */
2961
2962 /*
2963 * verifies that all the instances found, if any, are different.
2964 * uses an nlogn (n = # of instance) algorithm, which
2965 * could be made order n using the interface pointer protocol,
2966 * but the additional overhead makes the multiplier for
2967 * o(n) probably not worth the trouble.
2968 */
2969 static
2970 int MPICheckWNBTS(struct Instance *tmpinst, struct Statement *statement)
2971 {
2972 struct gl_list_t *instances;
2973 enum find_errors err;
2974
2975 instances = FindInsts(tmpinst,GetStatVarList(statement),&err);
2976 if (instances==NULL) {
2977 switch(err){
2978 case impossible_instance:
2979 MissingInsts(tmpinst,GetStatVarList(statement),1);
2980 WSEM(ASCERR,statement,
2981 "WILL_NOT_BE_THE_SAME statement contains an impossible instance name");
2982 return MPIBADWNBTS;
2983 default:
2984 MissingInsts(tmpinst,GetStatVarList(statement),0);
2985 WriteUnexecutedMessage(ASCERR,statement,
2986 "Incomplete instances in WILL_NOT_BE_THE_SAME");
2987 return MPIWAIT; /* statement is not ready to be executed */
2988 }
2989 }
2990 if (gl_unique_list(instances)==0) {
2991 WSEM(ASCERR,statement,
2992 "WILL_NOT_BE_THE_SAME statement contains"
2993 " identical/merged instances");
2994 gl_destroy(instances);
2995 return MPIBADMERGE;
2996 }
2997 gl_destroy(instances);
2998 return MPIOK;
2999 }
3000 /*
3001 * Checks the for statements, along with all the horrid machinery needed
3002 * to make a for loop go.
3003 */
3004 static
3005 int CheckWhereFOR(struct Instance *inst, struct Statement *statement)
3006 {
3007 symchar *name;
3008 struct Expr *ex;
3009 struct StatementList *sl;
3010 unsigned long c,len;
3011 struct value_t value;
3012 struct set_t *sptr;
3013 struct for_var_t *fv;
3014 int code=MPIOK;
3015
3016 name = ForStatIndex(statement);
3017 ex = ForStatExpr(statement);
3018 sl = ForStatStmts(statement);
3019 if (FindForVar(GetEvaluationForTable(),name)){ /* duplicated for variable */
3020 WSEM(ASCERR,statement, "FOR construct uses duplicate index variable");
3021 return MPIFOR;
3022 }
3023 assert(GetEvaluationContext()==NULL);
3024 SetEvaluationContext(inst);
3025 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
3026 SetEvaluationContext(NULL);
3027 switch(ValueKind(value)){
3028 case error_value:
3029 switch(ErrorValue(value)){
3030 case name_unfound:
3031 case undefined_value:
3032 DestroyValue(&value);
3033 WSEM(ASCERR,statement, "FOR has undefined values");
3034 return MPIFOR; /* this maybe should be mpiwait? */
3035 default:
3036 WriteForValueError(statement,value);
3037 DestroyValue(&value);
3038 return MPIFOR;
3039 }
3040 case real_value:
3041 case integer_value:
3042 case symbol_value:
3043 case boolean_value:
3044 case list_value:
3045 WriteStatement(ASCERR,statement,0);
3046 FPRINTF(ASCERR,"FOR expression returns the wrong type.\n");
3047 DestroyValue(&value);
3048 return MPIFOR;
3049 case set_value:
3050 sptr = SetValue(value);
3051 switch(SetKind(sptr)){
3052 case empty_set: break;
3053 case integer_set:
3054 fv = CreateForVar(name);
3055 SetForVarType(fv,f_integer);
3056 AddLoopVariable(GetEvaluationForTable(),fv);
3057 len = Cardinality(sptr);
3058 for(c=1;c<=len;c++){
3059 SetForInteger(fv,FetchIntMember(sptr,c));
3060 code = CheckWhereStatements(inst,sl);
3061 if (code != MPIOK) {
3062 break;
3063 }
3064 }
3065 RemoveForVariable(GetEvaluationForTable());
3066 break;
3067 case string_set:
3068 fv = CreateForVar(name);
3069 SetForVarType(fv,f_symbol);
3070 AddLoopVariable(GetEvaluationForTable(),fv);
3071 len = Cardinality(sptr);
3072 for(c=1;c<=len;c++){
3073 SetForSymbol(fv,FetchStrMember(sptr,c));
3074 code = CheckWhereStatements(inst,sl);
3075 if (code != MPIOK) {
3076 break;
3077 }
3078 }
3079 RemoveForVariable(GetEvaluationForTable());
3080 break;
3081 }
3082 DestroyValue(&value);
3083 }
3084 return code;
3085 }
3086 /*
3087 * checks that all conditions are satisfied, else returns a whine.
3088 * does not call mpierror, so caller ought to if needed.
3089 * returns one of the defined MPI codes.
3090 */
3091 static
3092 int CheckWhereStatements(struct Instance *tmpinst, struct StatementList *sl)
3093 {
3094 unsigned long c,len;
3095 struct Statement *s;
3096 int code=MPIOK;
3097
3098 if (tmpinst ==NULL) {
3099 return MPIWEIRD;
3100 }
3101 len = StatementListLength(sl);
3102 for (c=1;c <= len && code == MPIOK; c++) {
3103 s = GetStatement(sl,c);
3104 switch (StatementType(s)) {
3105 case WBTS:
3106 code = MPICheckWBTS(tmpinst,s);
3107 break;
3108 case WNBTS:
3109 code = MPICheckWNBTS(tmpinst,s);
3110 break;
3111 case WILLBE:
3112 code = MPICheckWB(tmpinst,s);
3113 break;
3114 case LOGREL:
3115 case REL:
3116 /* baa. fix me. bug. need to evaluate rules in a way which is
3117 * exception-safe. EvaluateExpr currently isn't
3118 */
3119 code = MPICheckConstraint(tmpinst,s);
3120 break;
3121 case FOR:
3122 code = CheckWhereFOR(tmpinst,s);
3123 break;
3124 default:
3125 code = MPIWEIRD;
3126 break;
3127 }
3128 }
3129 return code;
3130 }
3131
3132 #if 0 /* migrating, or migraining, depending on your viewpoint, to parpend.h */
3133 enum ppstatus {
3134 pp_ERR =0,
3135 pp_ISA, /* IS_A of simple to be done, from absorbed. */
3136 pp_ISAARR, /* IS_A of array to do, from absorbed and
3137 * gets converted to asar during processing.
3138 */
3139 pp_ARR, /* array that's constructed but requires range checking */
3140 pp_ASGN, /* assignment to do in absorbed objects */
3141 pp_ASSC, /* scalar assignment to check in absorbed objects */
3142 pp_ASAR, /* Array to be checked for being completely assigned,
3143 * but its subscript range is presumed right.
3144 */
3145 pp_WV, /* WITH_VALUE to be checked */
3146 pp_DONE /* finished statement */
3147 };
3148
3149 struct parpendingentry {
3150 struct Set *arg; /* parameter given in user's IS_A statement */
3151 struct Statement *s;
3152 struct Instance *inst;
3153 struct parpendingentry *next;
3154 enum ppstatus status;
3155 int argn; /* the psl position if >0, or -(the absorbed position) if <0 */
3156 /* argn==0 is an error */
3157 };
3158
3159 #endif /* 0 migraining */
3160
3161 /*
3162 * returns a single instance, if such can be properly derived
3163 * from the name given.
3164 * Returns NULL if too many or no instances are found.
3165 * Probably ought to have a return code, but doesn't.
3166 */
3167 static
3168 struct Instance *GetNamedInstance(CONST struct Name *nptr,
3169 CONST struct Instance *tmpinst)
3170 {
3171 struct Instance *i=NULL;
3172 struct gl_list_t *insts;
3173 enum find_errors ferr;
3174
3175 assert(nptr!=NULL);
3176 assert(tmpinst!=NULL);
3177 insts = FindInstances(tmpinst,nptr,&ferr);
3178 if (insts==NULL) {
3179 return NULL;
3180 }
3181 if (gl_length(insts) == 1L) {
3182 i = (struct Instance *)gl_fetch(insts,1);
3183 }
3184 gl_destroy(insts);
3185 return i;
3186 }
3187
3188 /*
3189 * put the parameters open (if any) and absorbed statements into the
3190 * pending list we're creating.
3191 */
3192 static
3193 struct parpendingentry *
3194 CreateParameterPendings(struct Instance *tmpinst,
3195 struct gl_list_t *args,
3196 struct StatementList *psl,
3197 struct StatementList *absorbed)
3198 {
3199 unsigned long c,len;
3200 struct parpendingentry *new, *list=NULL;
3201 CONST struct Expr *ex;
3202 struct gl_list_t *nlist=NULL;
3203
3204 assert(args!=NULL);
3205
3206 len = gl_length(args);
3207 for (c=len; c >= 1; c--) {
3208 new = CreatePPE();
3209 /* Create must not return NULL */
3210 new->arg = gl_fetch(args,c);
3211 new->s = GetStatement(psl,c);
3212 new->inst = NULL;
3213 new->argn = c;
3214 switch (StatementType(new->s)) {
3215 case WILLBE:
3216 /* assumes lint did it's job */
3217 if (NameLength(NamePointer(GetStatVarList(new->s))) > 1) {
3218 /* arrays were connected already, but no subscript check */
3219 new->inst = GetArrayHead(tmpinst,NamePointer(GetStatVarList(new->s)));
3220 new->status = pp_ARR;
3221 } else {
3222 /* scalar */
3223 ex = GetStatCheckValue(new->s);
3224 if (ex != NULL) {
3225 nlist = EvaluateNamesNeededShallow(ex,NULL,NULL);
3226 assert(nlist!=NULL);
3227 if (gl_length(nlist) != 0L) {
3228 new->status = pp_WV;
3229 new->inst =
3230 GetNamedInstance(NamePointer(GetStatVarList(new->s)),tmpinst);
3231 } else {
3232 /* nothing further to check. done already */
3233 DestroyPPE(new);
3234 new = NULL;
3235 }
3236 gl_destroy(nlist);
3237 } else {
3238 DestroyPPE(new);
3239 new = NULL;
3240 }
3241 }
3242 break;
3243 case ISA:
3244 if (NameLength(NamePointer(GetStatVarList(new->s))) > 1) {
3245 /* subscript check */
3246 new->inst = GetArrayHead(tmpinst,NamePointer(GetStatVarList(new->s)));
3247 new->status = pp_ARR;
3248 } else {
3249 /* nothing further to check. assumed done already */
3250 DestroyPPE(new);
3251 new = NULL;
3252 }
3253 break;
3254 default:
3255 Asc_Panic(2, "CreateParameterPendings",
3256 "Unknown statement type in CreateParameterPendings!\n");
3257 break;
3258 }
3259 if (new != NULL) {
3260 /* insert at head, but completed statements don't get added */
3261 new->next = list;
3262 list = new;
3263 }
3264 }
3265 len = StatementListLength(absorbed);
3266 for (c=len; c >= 1; c--) {
3267 new = CreatePPE();
3268 /* Create must not return NULL */
3269 new->arg = NULL;
3270 new->s = GetStatement(absorbed,c);
3271 new->inst = NULL;
3272 new->argn =0; new->argn -= c;
3273 switch (StatementType(new->s)) {
3274 case ISA:
3275 if (NameLength(NamePointer(GetStatVarList(new->s))) > 1) {
3276 /* array needed and subscript check */
3277 new->status = pp_ISAARR;
3278 /* after construction, no check until fully assigned at end */
3279 } else {
3280 /* simplename */
3281 new->status = pp_ISA;
3282 }
3283 break;
3284 case CASGN:
3285 new->status = pp_ASGN;
3286 break;
3287 default:
3288 Asc_Panic(2, "CreateParameterPendings",
3289 "Unknown statement type in CreateParameterPendings!\n");
3290 break;
3291 }
3292 new->next = list;
3293 list = new;
3294 }
3295 return list;
3296 }
3297 /* destroy a list of pending parameter items.
3298 */
3299 static
3300 void DestroyParameterPendings( struct parpendingentry *pp)
3301 {
3302 struct parpendingentry *old;
3303 while (pp!=NULL) {
3304 old = pp;
3305 pp = pp->next;
3306 DestroyPPE(old);
3307 }
3308 }
3309
3310 /*
3311 * this function should not be entered until all WB arguments have
3312 * been installed in tmpinst.
3313 */
3314 static
3315 int DigestArguments(
3316 struct Instance *tmpinst,
3317 struct gl_list_t *args,
3318 struct StatementList *psl,
3319 struct StatementList *absorbed,
3320 struct Statement *statement)
3321 {
3322 struct parpendingentry *pp, /* current work */
3323 *pphead, /* first in work list */
3324 *pplast; /* just prior work, so can delete current */
3325 int change = 1;
3326 int suberr = MPIOK; /* maybe mpi enum */
3327
3328 pphead = pp = CreateParameterPendings(tmpinst,args,psl,absorbed);
3329 while (change && pphead!=NULL && suberr ==MPIOK) {
3330 pplast = NULL;
3331 pp = pphead;
3332 change = 0;
3333 while (pp != NULL && suberr ==MPIOK) {
3334 switch (pp->status) {
3335 case pp_ISA:
3336 /* building a scalar! OTHERWISE recursion could bite us.
3337 * We don't use mpimakesimpleinstance because no argval.
3338 */
3339 suberr = ExecuteISA(tmpinst,pp->s);
3340 if (suberr!=1) {
3341 suberr = MPIWEIRD;
3342 pp->status = pp_ERR;
3343 FPRINTF(ASCERR,"While executing (1) absorbed statement in %s:\n",
3344 SCP(GetName(InstanceTypeDesc(tmpinst))));
3345 WriteStatement(ASCERR,pp->s,2);
3346 mpierror(NULL,0,statement,suberr);
3347 } else {
3348 pp->inst =
3349 GetNamedInstance(NamePointer(GetStatVarList(pp->s)),tmpinst);
3350 if (pp->inst != NULL) {
3351 suberr = MPIOK;
3352 pp->status = pp_ASSC;
3353 } else {
3354 suberr = MPIWEIRD;
3355 pp->status = pp_ERR;
3356 FPRINTF(ASCERR,"While executing (2) absorbed statement in %s:\n",
3357 SCP(GetName(InstanceTypeDesc(tmpinst))));
3358 WriteStatement(ASCERR,pp->s,2);
3359 mpierror(NULL,0,statement,suberr);
3360 }
3361 }
3362 change++;
3363 break;
3364 /* done case */
3365 case pp_ISAARR:
3366 /* IS_A of array that needs doing, range, args assignment */
3367 if (CheckISA(tmpinst,pp->s) == 1) {
3368 /* Must have subscripts defined first, because we do not
3369 * want the array to be put on the global pending list as
3370 * that would be algorithmic suicide. The whole point of
3371 * parameters is reducing a set of operations to a point
3372 * in the ProcessPending execution cycle.
3373 */
3374 suberr = ExecuteISA(tmpinst,pp->s);
3375 /* so the array should be completely expanded now. */
3376 /* we won't check unless problems start to show up,
3377 * since we believe the array code to be correct.
3378 */
3379 if (suberr!=1) {
3380 suberr = MPIWEIRD;
3381 pp->status = pp_ERR;
3382 FPRINTF(ASCERR,"While executing (3) absorbed statement in %s:\n",
3383 SCP(GetName(InstanceTypeDesc(tmpinst))));
3384 WriteStatement(ASCERR,pp->s,2);
3385 mpierror(NULL,0,statement,suberr);
3386 } else {
3387 pp->inst =GetArrayHead(tmpinst,NamePointer(GetStatVarList(pp->s)));
3388 if (pp->inst == NULL) {
3389 suberr = MPIWEIRD;
3390 pp->status = pp_ERR;
3391 FPRINTF(ASCERR,"While executing (4) absorbed statement in %s:\n",
3392 SCP(GetName(InstanceTypeDesc(tmpinst))));
3393 WriteStatement(ASCERR,pp->s,2);
3394 mpierror(NULL,0,statement,suberr);
3395 } else {
3396 suberr = MPIOK;
3397 pp->status = pp_ASAR; /* needs assigning */
3398 }
3399 }
3400 change++;
3401 }
3402 /* done case */
3403 break;
3404 case pp_ARR:
3405 /* someone will have init'd pp->inst */
3406 /* checking whether sets in pp->s expand to match sets
3407 * in pp->inst, the array head and child of tmpinst.
3408 * Must accomodate FOR loops in future.
3409 */
3410 suberr = MPICheckSubscripts(tmpinst,pp->inst,pp->s);
3411 switch(suberr) {
3412 case MPIOK:
3413 pp->status = pp_DONE;
3414 change++;
3415 break;
3416 case MPIWAIT:
3417 suberr = MPIOK;
3418 break;
3419 default:
3420 pp->status = pp_ERR;
3421 WriteInstance(ASCERR,tmpinst);
3422 WriteInstance(ASCERR,pp->inst);
3423 mpierror(pp->arg,pp->argn,statement,suberr);
3424 change++;
3425 break;
3426 }
3427 break;
3428 /* done case */
3429 case pp_ASGN:
3430 if (ExecuteCASGN(tmpinst,pp->s) == 1) {
3431 pp->status = pp_DONE;
3432 change++;
3433 }
3434 /* done case */
3435 break;
3436 case pp_WV: /* WITH_VALUE that needs checking */
3437 if (ArgValueCorrect(pp->inst,tmpinst,pp->s)==MPIOK) {
3438 pp->status = pp_DONE;
3439 change++;
3440 }
3441 /* done case */
3442 break;
3443 case pp_ASAR:
3444 case pp_ASSC:
3445 if (ArgValuesUnassigned(pp->inst)==0) {
3446 pp->status = pp_DONE;
3447 change++;
3448 }
3449 /* done case */
3450 break;
3451 case pp_DONE:
3452 FPRINTF(ASCERR,"Unexpected pp_DONE in DigestParameters!\n");
3453 break;
3454 /* say what? should have been deleted already. */
3455 /* done case */
3456 case pp_ERR:
3457 /* shouldn't have gone through the loop to reach an err marked pp */
3458 default:
3459 Asc_Panic(2, NULL, "Unexpected status in DigestParameters!\n");
3460 break;
3461 }
3462 /* delete if we finished it, then advance counter. */
3463 if (pp->status == pp_DONE) {
3464 /* delete pp, but pplast cannot change */
3465 if (pplast != NULL) { /* we're somewhere in the middle */
3466 pplast->next = pp->next;
3467 DestroyPPE(pp);
3468 pp = pplast->next; /* could be null */
3469 } else {
3470 /* we're at the top */
3471 pphead = pp->next;
3472 DestroyPPE(pp);
3473 pp = pphead; /* could be null */
3474 }
3475 } else {
3476 /* just advance the list, even if pperr. */
3477 pplast = pp;
3478 pp = pplast->next;
3479 /* if pp --> NULL, inner while will fail, outer may */
3480 }
3481 }
3482 }
3483 /* either fell out on error, in which case it is in pplast and the
3484 * error whine already was done,
3485 * or pphead !=NULL, but changed didn't move, in which case we
3486 * need to look for unexecuted assignments, unchecked WITH_VALUE's,
3487 * and unverified array subscripts and wum about them,
3488 * or pphead == NULL and we're done and can get out.
3489 */
3490 if (suberr!= MPIOK) {
3491 DestroyParameterPendings(pphead);
3492 return suberr;
3493 }
3494 if (pphead == NULL) {
3495 return suberr; /* the normal exit */
3496 }
3497 pp = pphead;
3498 while (pp!=NULL) {
3499 char *msg;
3500 CONST struct Statement *stat;
3501 switch (pp->status) {
3502 case pp_ISA:
3503 msg = "Oddly unable to construct parameter scalar";
3504 stat = pp->s;
3505 break;
3506 case pp_ISAARR:
3507 msg = "Unable to construct array parameter. Probably missing subscripts";
3508 stat = pp->s;
3509 break;
3510 case pp_ARR:
3511 msg = "Unable to check parameter array subscripts.";
3512 stat = pp->s;
3513 break;
3514 case pp_ASGN:
3515 msg = "Unable to execute assigment: LHS unmade or RHS not evaluatable";
3516 stat = pp->s;
3517 break;
3518 case pp_ASSC:
3519 msg ="Unable to set scalar param: RHS not evaluatable or incorrect type";
3520 stat = pp->s;
3521 break;
3522 case pp_ASAR:
3523 msg = "Parameters: Not all array elements assigned during refinement";
3524 stat = pp->s;
3525 break;
3526 case pp_WV:
3527 msg = "Unable to verify parameter value: probably bad WITH_VALUE RHS";
3528 stat = pp->s;
3529 break;
3530 case pp_ERR:
3531 stat = statement;
3532 msg = "Unexpected pp_ERR pending in parameters";
3533 break;
3534 case pp_DONE:
3535 msg = NULL;
3536 break;
3537 default:
3538 msg = NULL;
3539 }
3540 if (msg != NULL) {
3541 WriteUnexecutedMessage(ASCERR,statement,msg);
3542 }
3543 pp = pp->next;
3544 }
3545 DestroyParameterPendings(pphead);
3546 return MPIWAIT;
3547 }
3548
3549 static
3550 void ConfigureCopy(struct Instance *inst,
3551 CONST struct Instance *arginst,
3552 unsigned long cnum)
3553 {
3554 struct Instance *src,*copy;
3555
3556 src = InstanceChild(arginst,cnum);
3557 assert(src!=NULL);
3558 copy = CopyInstance(src);
3559 assert(copy!=NULL);
3560 StoreChildPtr(inst,cnum,copy);
3561 /* hunting out UNIVERSAL/arrays we could make this check much
3562 * less needed.
3563 */
3564 if (SearchForParent(copy,inst)==0) {
3565 AddParent(copy,inst);
3566 }
3567 }
3568
3569 /* assumes inst, arginst of same type. copies reference
3570 * children of arginst to same slots in inst.
3571 */
3572 static
3573 void ConfigureReference(struct Instance *inst,
3574 CONST struct Instance *arginst,
3575 unsigned long cnum)
3576 {
3577 struct Instance *src;
3578
3579 src = InstanceChild(arginst,cnum);
3580 assert(src!=NULL);
3581 StoreChildPtr(inst,cnum,src);
3582 /* hunting out UNIVERSAL/arrays we could make this check much
3583 * less needed.
3584 */
3585 if (SearchForParent(src,inst)==0) {
3586 AddParent(src,inst);
3587 }
3588 }
3589
3590 /* Connect WILL_BE'd children from arginst to inst.
3591 * Copy IS_A'd children from arginst to inst.
3592 * At this point there can be no alias children -- all
3593 * are either WILL_BE or IS_A of constants/arrays.
3594 * This must only be called with models when arginst !=NULL.
3595 * arginst == NULL --> immediate, no action return.
3596 * inst and arginst are assumed to be the same type.
3597 */
3598 void ConfigureInstFromArgs(struct Instance *inst,
3599 CONST struct Instance *arginst)
3600 {
3601 ChildListPtr clist;
3602 unsigned long c,len;
3603
3604 if (arginst == NULL) {
3605 return;
3606 }
3607 assert(InstanceKind(inst)==MODEL_INST);
3608 assert(InstanceTypeDesc(inst)==InstanceTypeDesc(arginst));
3609 clist = GetChildList(InstanceTypeDesc(inst));
3610 len = ChildListLen(clist);
3611 for (c=1; c <= len; c++) {
3612 switch(ChildOrigin(clist,c)) {
3613 case origin_ALI:
3614 case origin_ARR:
3615 case origin_ISA:
3616 case origin_WB:
3617 case origin_PALI:
3618 case origin_PARR:
3619 if (InstanceChild(arginst,c)!=NULL) {
3620 Asc_Panic(2, NULL, "arginst caught with illegitimate child. Bye!");
3621 }
3622 break;
3623 case origin_PISA:
3624 ConfigureCopy(inst,arginst,c);
3625 break;
3626 case origin_PWB:
3627 ConfigureReference(inst,arginst,c);
3628 break;
3629 case origin_ERR:
3630 default:
3631 Asc_Panic(2, NULL, "arginst caught with alien child. Bye!");
3632 }
3633 }
3634 }
3635
3636 /*
3637 * For Those children not already present in inst,
3638 * which must be of the same type as arginst.
3639 * Connect WILL_BE'd children from arginst to inst.
3640 * Copy IS_A'd children from arginst to inst.
3641 * At this point there can be no alias children -- all
3642 * are either WILL_BE or IS_A of constants/arrays, so far as
3643 * arginst is concerned.
3644 * This must only be called with models when arginst !=NULL.
3645 * arginst == NULL --> immediate, no action return.
3646 * inst is expected to be of same type as arginst.
3647 */
3648 void ReConfigureInstFromArgs(struct Instance *inst,
3649 CONST struct Instance *arginst)
3650 {
3651 ChildListPtr clist;
3652 unsigned long c,len;
3653
3654 if (arginst == NULL) {
3655 return;
3656 }
3657 assert(InstanceKind(inst)==MODEL_INST);
3658 assert(InstanceTypeDesc(inst)==InstanceTypeDesc(arginst));
3659 clist = GetChildList(InstanceTypeDesc(arginst));
3660 len = ChildListLen(clist);
3661 for (c=1; c <= len; c++) {
3662 switch(ChildOrigin(clist,c)) {
3663 case origin_ALI:
3664 case origin_ARR:
3665 case origin_ISA:
3666 case origin_WB:
3667 case origin_PALI:
3668 case origin_PARR:
3669 if (InstanceChild(arginst,c)!=NULL) {
3670 Asc_Panic(2, NULL, "arginst caught with illegitimate child. Bye!");
3671 }
3672 break;
3673 case origin_PISA:
3674 if (InstanceChild(inst,c)==NULL) {
3675 /* child that didn't exist in the less refined type. */
3676 ConfigureCopy(inst,arginst,c);
3677 }
3678 break;
3679 case origin_PWB:
3680 if (InstanceChild(inst,c)==NULL) {
3681 /* child that didn't exist in the less refined type. */
3682 ConfigureReference(inst,arginst,c);
3683 }
3684 break;
3685 case origin_ERR:
3686 default:
3687 Asc_Panic(2, NULL, "arginst caught with alien child. Bye!");
3688 }
3689 }
3690 }
3691
3692 static
3693 int EqualChildInsts(struct Instance *i1, struct Instance *i2,
3694 unsigned long c1, unsigned long c2)
3695 {
3696 if (c1==0 || c2==0 || i1 == NULL || i2 == NULL ||
3697 InstanceChild(i1,c1) != InstanceChild(i2,c2)) {
3698 return 1;
3699 }
3700 return 0;
3701 }
3702
3703 /* Bugs:
3704 * do not call this with instances other than variables/constants
3705 * or arrays of same. relations, models, etc make it barf or lie.
3706 * On proper types returns 0 if the inst values are ==
3707 * for the c1th child of i1 and c2th child of i2. OTHERWISE nonzero.
3708 */
3709 static
3710 int CompareChildInsts(struct Instance *i1, struct Instance *i2,
3711 unsigned long c1, unsigned long c2)
3712 {
3713 struct Instance *ch1,* ch2;
3714 assert(i1!=NULL);
3715 assert(i2!=NULL);
3716 ch1 = InstanceChild(i1,c1);
3717 ch2 = InstanceChild(i2,c2);
3718 assert(ch1!=NULL);
3719 assert(ch2!=NULL);
3720 if (InstanceKind(ch1) != InstanceKind(ch2)) {
3721 return 1;
3722 }
3723 if (IsArrayInstance(ch1)) {
3724 return CmpArrayInsts(ch1,ch2);
3725 } else {
3726 return CmpAtomValues(ch1,ch2);
3727 }
3728 }
3729
3730 /* Needs to see that all nonnull children in inst are compatible
3731 * with corresponding children in mpi if such exist.
3732 * arginst must be as or morerefined than inst.
3733 * In particular, needs to be damned picky about where's being met
3734 * and types matching exactly because we won't refine up stuff
3735 * by passing it through a parameter list.
3736 * WILL_BE child pointers of the arginst must = those in inst
3737 * when the inst has a child of that name.
3738 * IS_A child pointers of the arginst must have same value as
3739 * those in inst when the inst has a child of that name.
3740 * When inst has no child of that name, must eventually copy it
3741 * to the expanded instance.
3742 * This has to check that absolutely everything is correct
3743 * because RefineClique/RefineInstance asks no questions.
3744 * This itself assume arginst has been correctly constructed.
3745 */
3746 static
3747 int CheckParamRefinement(struct Instance *parent,
3748 struct Instance *inst,
3749 struct Instance *arginst,
3750 struct Statement *statement)
3751 {
3752 ChildListPtr icl, aicl;
3753 unsigned long oldlen, newlen, c,pos;
3754 symchar *childname;
3755
3756 assert(MoreRefined(InstanceTypeDesc(inst),InstanceTypeDesc(arginst))==
3757 InstanceTypeDesc(arginst));
3758 icl = GetChildList(InstanceTypeDesc(inst));
3759 aicl = GetChildList(InstanceTypeDesc(arginst));
3760 oldlen = ChildListLen(icl);
3761 newlen = ChildListLen(aicl);
3762 if (newlen == oldlen) {
3763 /* very common case, just upgrading types by assigning constants
3764 * in REFINES clause, though things may have been constructed
3765 * with those constants earlier.
3766 */
3767 for (c=1; c <= newlen; c++) {
3768 switch(ChildOrigin(aicl,c)) {
3769 case origin_ALI:
3770 case origin_ARR:
3771 case origin_ISA:
3772 case origin_WB:
3773 case origin_PALI:
3774 case origin_PARR:
3775 if (InstanceChild(arginst,c)!=NULL) {
3776 Asc_Panic(2, NULL, "arginst caught with illegitimate child. Bye!");
3777 }
3778 break;
3779 case origin_PISA:
3780 /* both must be assigned, and to the same values */
3781 if (CompareChildInsts(inst,arginst,c,c)!=0) {
3782 FPRINTF(ASCERR,"Incompatible constants: ");
3783 WriteInstanceName(ASCERR,InstanceChild(inst,c),parent);
3784 FPRINTF(ASCERR,"\n");
3785 mpierror(NULL,0,statement,MPIREASGN);
3786 return MPIREASGN;
3787 }
3788 break;
3789 case origin_PWB:
3790 if (EqualChildInsts(inst,arginst,c,c)!=0) {
3791 FPRINTF(ASCERR,"Different object passed for: ");
3792 WriteInstanceName(ASCERR,InstanceChild(inst,c),parent);
3793 FPRINTF(ASCERR,"\n");
3794 mpierror(NULL,0,statement,MPIREDEF);
3795 return MPIREDEF;
3796 }
3797 break;
3798 case origin_ERR:
3799 default:
3800 Asc_Panic(2, NULL, "arginst caught with alien child. Bye!");
3801 }
3802 }
3803 } else {
3804 /* increased child list */
3805 for (c=1; c <= newlen; c++) {
3806 switch(ChildOrigin(aicl,c)) {
3807 case origin_ALI:
3808 case origin_ARR:
3809 case origin_ISA:
3810 case origin_WB:
3811 case origin_PALI:
3812 case origin_PARR:
3813 if (InstanceChild(arginst,c)!=NULL) {
3814 Asc_Panic(2, NULL, "arginst caught with illegitimate child. Bye!");
3815 }
3816 break;
3817 case origin_PISA:
3818 /* both must be assigned, and to the same values, if inst has it */
3819 childname = ChildStrPtr(aicl,c);
3820 pos = ChildPos(icl,childname);
3821 if (pos > 0 && CompareChildInsts(inst,arginst,pos,c)!=0) {
3822 FPRINTF(ASCERR,"Incompatible constants: ");
3823 WriteInstanceName(ASCERR,InstanceChild(inst,pos),parent);
3824 FPRINTF(ASCERR,"\n");
3825 mpierror(NULL,0,statement,MPIREASGN);
3826 return MPIREASGN;
3827 }
3828 break;
3829 case origin_PWB:
3830 childname = ChildStrPtr(aicl,c);
3831 pos = ChildPos(icl,childname);
3832 if (pos > 0 && EqualChildInsts(inst,arginst,pos,c)!=0) {
3833 FPRINTF(ASCERR,"Different object passed for: ");
3834 WriteInstanceName(ASCERR,InstanceChild(inst,pos),parent);
3835 FPRINTF(ASCERR,"\n");
3836 mpierror(NULL,0,statement,MPIREDEF);
3837 return MPIREDEF;
3838 }
3839 break;
3840 case origin_ERR:
3841 default:
3842 Asc_Panic(2, NULL, "arginst caught with alien child. Bye!");
3843 }
3844 }
3845 }
3846 return MPIOK;
3847 }
3848
3849
3850 /* handles construction of IS_A statements.
3851 * MakeInstance and its subsidiaries must not cannibalize
3852 * parts from arginst, because it may be used again on
3853 * subsequent calls when the IS_A has several lhs.
3854 */
3855 static
3856 void MakeInstance(CONST struct Name *name,
3857 struct TypeDescription *def,
3858 int intset,
3859 struct Instance *parent,
3860 struct Statement *statement,
3861 struct Instance *arginst)
3862 {
3863 symchar *childname;
3864 int changed;
3865 unsigned long pos;
3866 struct Instance *inst;
3867 struct InstanceName rec;
3868 struct TypeDescription *arydef;
3869 struct gl_list_t *indices;
3870 int tce;
3871 /*char *nstr;
3872 nstr = WriteNameString(name);
3873 CONSOLE_DEBUG(nstr);
3874 ascfree(nstr); */
3875 if ((childname = SimpleNameIdPtr(name))!=NULL){ /* simple 1 element name */
3876 if (StatInFOR(statement) && StatWrong(statement)==0) {
3877 MarkStatContext(statement,context_WRONG);
3878 WSEM(ASCERR,statement,"Unindexed statement in FOR loop not allowed.");
3879 WSS(ASCERR,statement);
3880 return;
3881 }
3882 SetInstanceNameType(rec,StrName);
3883 SetInstanceNameStrPtr(rec,childname);
3884 pos = ChildSearch(parent,&rec);
3885 if (pos>0) {
3886 if (InstanceChild(parent,pos)==NULL){
3887 inst = MakeSimpleInstance(def,intset,statement,arginst);
3888 LinkToParentByPos(parent,inst,pos);
3889 } else { /* redefining instance */
3890 char *msg = ascmalloc(SCLEN(childname)+
3891 strlen(REDEFINE_CHILD_MESG)+1);
3892 strcpy(msg,REDEFINE_CHILD_MESG);
3893 strcat(msg,SCP(childname));
3894 WSEM(ASCERR,statement,msg);
3895 ascfree(msg);
3896 }
3897 } else { /* unknown child name */
3898 WSEM(ASCERR,statement, "Unknown child name. Never should happen");
3899 Asc_Panic(2, NULL, "Unknown child name. Never should happen");
3900 }
3901 } else {
3902 /* if reach the else, means compound identifier or garbage */
3903 indices = ArrayIndices(name,parent);
3904 if (indices!=NULL){ /* array of some sort */
3905 childname = NameIdPtr(name);
3906 SetInstanceNameType(rec,StrName);
3907 SetInstanceNameStrPtr(rec,childname);
3908 pos = ChildSearch(parent,&rec);
3909 if (!StatInFOR(statement)) { /* rectangle arrays */
3910 arydef = CreateArrayTypeDesc(StatementModule(statement),
3911 def,intset,0,0,0,indices);
3912 if (pos>0) {
3913 inst = CreateArrayInstance(arydef,1);
3914 if (inst!=NULL){
3915 changed = 0;
3916 tce = TryChildExpansion(inst,parent,&changed,NULL,arginst,NULL);
3917 /* we're not in a for loop, so can't fail unless user is idiot. */
3918 LinkToParentByPos(parent,inst,pos);
3919 /* if user is idiot, whine. */
3920 if (tce != 0) {
3921 SignalChildExpansionFailure(parent,pos);
3922 }
3923 } else {
3924 WSEM(ASCERR,statement, "Unable to create array instance");
3925 Asc_Panic(2, NULL, "Unable to create array instance");
3926 }
3927 } else {
3928 DeleteTypeDesc(arydef);
3929 WSEM(ASCERR,statement,
3930 "Unknown array child name. Never should happen");
3931 Asc_Panic(2, NULL, "Unknown array child name. Never should happen");
3932 }
3933 } else {
3934 DestroyIndexList(indices);
3935 if (pos>0) {
3936 if (InstanceChild(parent,pos)==NULL) {
3937 /* must make IS_A array */
3938 (void) /* should check for NULL return here */
3939 MakeSparseArray(parent,name,statement,
3940 def,intset,NULL,arginst,NULL);
3941 } else {
3942 /* must add array element *//* should check for NULL return here */
3943 (void)AddArrayChild(parent,name,statement,NULL,arginst,NULL);
3944 }
3945 } else {
3946 WSEM(ASCERR,statement,
3947 "Unknown array child name. Never should happen");
3948 Asc_Panic(2, NULL, "Unknown array child name. Never should happen");
3949 }
3950 }
3951 } else {
3952 /* bad child name. cannot create parts of parts. should never
3953 * happen, being trapped out in typelint.
3954 */
3955 WSEM(ASCERR,statement,"Bad IS_A child name.");
3956 }
3957 }
3958 }
3959
3960 static
3961 int ExecuteISA(struct Instance *inst, struct Statement *statement)
3962 {
3963 struct TypeDescription *def;
3964 CONST struct VariableList *vlist;
3965 struct Instance *arginst = NULL;
3966 int mpi;
3967 int intset;
3968
3969 assert(StatementType(statement)==ISA);
3970 if (StatWrong(statement)) {
3971 /* incorrect statements should be warned about when they were
3972 * marked wrong, so we just ignore them here.
3973 */
3974 return 1;
3975 }
3976 if ((def = FindType(GetStatType(statement)))!=NULL){
3977 if ((GetStatSetType(statement)!=NULL) != (GetBaseType(def)==set_type)){
3978 WriteSetError(statement,def);
3979 return 1;
3980 }
3981 if (!CheckISA(inst,statement)) {
3982 /* last pass whine */
3983 WriteUnexecutedMessage(ASCERR,statement,
3984 "Possibly undefined indices in IS_A statement.");
3985 return 0;
3986 }
3987 mpi = MakeParameterInst(inst,statement,&arginst,KEEPARGINST);/*3*/
3988 if (mpi != MPIOK) {
3989 if (mpi == MPIWAIT) {
3990 WriteUnexecutedMessage(ASCERR,statement,
3991 "Possibly undefined arguments in IS_A statement.");
3992 return 0;
3993 } else {
3994 /* bogus args or definition. punt IS_A permanently. */
3995 MarkStatContext(statement,context_WRONG);
3996 WSS(ASCERR,statement);
3997 return 1;
3998 }
3999 }
4000 intset = CalcSetType(GetStatSetType(statement),statement);
4001 if (intset < 0) { /* incorrect set type */
4002 WSEM(ASCERR,statement,"Illegal set type encountered.");
4003 /* should never happen due to lint */
4004 return 0;
4005 }
4006 vlist = GetStatVarList(statement);
4007 while (vlist!=NULL){
4008 MakeInstance(NamePointer(vlist),def,intset,inst,statement,arginst);
4009 vlist = NextVariableNode(vlist);
4010 }
4011 if (arginst != NULL) {
4012 DestroyParameterInst(arginst);
4013 }
4014 return 1;
4015 } else{
4016 /*
4017 * Should never happen, due to lint.
4018 */
4019 char *msg = ascmalloc(strlen(UNDEFINED_TYPE_MESG)+
4020 SCLEN(GetStatType(statement))+1);
4021 strcpy(msg,UNDEFINED_TYPE_MESG);
4022 strcat(msg,SCP(GetStatType(statement)));
4023 WSEM(ASCERR,statement,msg); /* added print. baa. string was here already*/
4024 ascfree(msg);
4025 return 1;
4026 }
4027 }
4028
4029 /* handles construction of Dummy Instance
4030 * A dummy instance is universal.
4031 */
4032 static
4033 void MakeDummyInstance(CONST struct Name *name,
4034 struct TypeDescription *def,
4035 struct Instance *parent,
4036 struct Statement *statement)
4037 {
4038 symchar *childname;
4039 unsigned long pos;
4040 struct Instance *inst;
4041 struct InstanceName rec;
4042
4043 childname = SimpleNameIdPtr(name);
4044 if (childname==NULL) {
4045 childname = NameIdPtr(name);
4046 }
4047 SetInstanceNameType(rec,StrName);
4048 SetInstanceNameStrPtr(rec,childname);
4049 pos = ChildSearch(parent,&rec);
4050 if (pos>0) {
4051 if (InstanceChild(parent,pos)==NULL){
4052 inst = ShortCutMakeUniversalInstance(def);
4053 if (inst==NULL) {
4054 inst = CreateDummyInstance(def);
4055 }
4056 LinkToParentByPos(parent,inst,pos);
4057 } else { /* redefining instance */
4058 char *msg = ascmalloc(SCLEN(childname) +
4059 strlen(REDEFINE_CHILD_MESG)+1);
4060 strcpy(msg,REDEFINE_CHILD_MESG);
4061 strcat(msg,SCP(childname));
4062 WSEM(ASCERR,statement,msg);
4063 ascfree(msg);
4064 }
4065 } else { /* unknown child name */
4066 WSEM(ASCERR,statement, "Unknown child name. Never should happen");
4067 Asc_Panic(2, NULL, "Unknown child name. Never should happen");
4068 }
4069 }
4070
4071
4072 /* Used for IS_A statement inside a non-matching CASE of a
4073 * SELECT statement.
4074 * Make a dummy instance for each name in vlisti,
4075 * but arrays are not expanded over subscripts.
4076 * The dummy instance is UNIVERSAL.
4077 */
4078 static
4079 int ExecuteUnSelectedISA( struct Instance *inst, struct Statement *statement)
4080 {
4081 struct TypeDescription *def;
4082 CONST struct VariableList *vlist;
4083 assert(StatementType(statement)==ISA);
4084 if ((def = FindDummyType())!=NULL){
4085 vlist = GetStatVarList(statement);
4086 while (vlist!=NULL){
4087 MakeDummyInstance(NamePointer(vlist),def,inst,statement);
4088 vlist = NextVariableNode(vlist);
4089 }
4090 return 1;
4091 } else{
4092 /*
4093 * Should never happen, due to lint.
4094 */
4095 char *msg = ascmalloc(strlen(UNDEFINED_TYPE_MESG)+11);
4096 strcpy(msg,UNDEFINED_TYPE_MESG);
4097 strcat(msg,"dummy_type");
4098 WSEM(ASCERR,statement,msg);
4099 ascfree(msg);
4100 return 1;
4101 }
4102 }
4103
4104
4105 /*
4106 * For ALIASES inside a non matching CASEs of a SELECT statement, we
4107 * do not even have to care about the rhs. Similar to ISAs, we only
4108 * take the list of variables and create the dummy instance
4109 */
4110 static
4111 int ExecuteUnSelectedALIASES(struct Instance *inst,
4112 struct Statement *statement)
4113 {
4114 CONST struct VariableList *vlist;
4115
4116 assert(StatementType(statement)==ALIASES);
4117 vlist = GetStatVarList(statement);
4118 while (vlist!=NULL){
4119 MakeDummyInstance(NamePointer(vlist),FindDummyType(),inst,statement);
4120 vlist = NextVariableNode(vlist);
4121 }
4122 return 1;
4123 }
4124
4125
4126 /*
4127 **************************************************************************
4128 * Reference Statement Processing
4129 *
4130 * Highly incomplete KAA_DEBUG
4131 **************************************************************************
4132 */
4133
4134 #ifdef THIS_IS_AN_UNUSED_FUNCTION
4135 static
4136 struct Instance *RealExecuteRef(struct Name *name,
4137 struct TypeDescription *def,
4138 int intset,
4139 struct Instance *parent,
4140 struct Statement *statement)
4141 {
4142 struct Instance *result = NULL;
4143
4144 return result;
4145 }
4146 #endif /* THIS_IS_AN_UNUSED_FUNCTION */
4147
4148 static
4149 int ExecuteREF(struct Instance *inst, struct Statement *statement)
4150 {
4151 (void)inst; /* stop gcc whine about unused parameter */
4152 (void)statement; /* stop gcc whine about unused parameter */
4153 return 1;
4154 }
4155
4156 /*
4157 * Finds all the instances required to evaluate set element given.
4158 * If problem, returns NULL and err should be consulted.
4159 * Note this may have some angst around FOR vars, as it
4160 * should since forvars are not instances.
4161 * Lint is precluding passing a forvar where an instance is required.
4162 * err should only be consulted if result comes back NULL.
4163 * Note also that we will ignore any sets chained on to the end
4164 * of s.
4165 */
4166 static
4167 struct gl_list_t *FindArgInsts(struct Instance *parent,
4168 struct Set *s,
4169 enum find_errors *err)
4170 {
4171 struct gl_list_t *result,*temp; /* instance lists */
4172 struct gl_list_t *nl=NULL; /* name list */
4173 unsigned nc,nlen;
4174
4175 result = gl_create(2L);
4176 nl = EvaluateSetNamesNeededShallow(s,nl);
4177 nlen = gl_length(nl);
4178 for (nc=1; nc <= nlen; nc++) {
4179 temp = FindInstances(parent,(struct Name *)gl_fetch(nl,nc),err);
4180 if (temp==NULL){
4181 gl_destroy(nl);
4182 gl_destroy(result);
4183 return NULL;
4184 }
4185 gl_append_list(result,temp);
4186 gl_destroy(temp);
4187 }
4188 gl_destroy(nl);
4189 return result;
4190 }
4191
4192 /**************************************************************************\
4193 FindInsts: makes sure at least one thing is found for
4194 each name item on list (else returned list will be NULL)
4195 and returns the collected instances.
4196 \**************************************************************************/
4197 static
4198 struct gl_list_t *FindInsts(struct Instance *inst,
4199 CONST struct VariableList *list,
4200 enum find_errors *err)
4201 {
4202 struct gl_list_t *result,*temp;
4203 unsigned c,len;
4204 result = gl_create(7L);
4205 while(list!=NULL){
4206 temp = FindInstances(inst,NamePointer(list),err);
4207 if (temp==NULL){
4208 gl_destroy(result);
4209 return NULL;
4210 }
4211 len = gl_length(temp);
4212 for(c=1;c<=len;c++) {
4213 gl_append_ptr(result,gl_fetch(temp,c));
4214 }
4215 gl_destroy(temp);
4216 list = NextVariableNode(list);
4217 }
4218 return result;
4219 }
4220
4221 /**************************************************************************\
4222 MissingInsts: makes sure at least one thing is found for
4223 each name item on list (else prints the name with a little message)
4224 if noisy != 0 || on last iteration, does the printing, OTHERWISE
4225 returns immediately.
4226 \**************************************************************************/
4227 static
4228 void MissingInsts(struct Instance *inst,
4229 CONST struct VariableList *list,
4230 int noisy)
4231 {
4232 struct gl_list_t *temp;
4233 enum find_errors err;
4234
4235 if (g_iteration >= (MAXNUMBER-1) || noisy != 0) {
4236 while(list!=NULL){
4237 temp = FindInstances(inst,NamePointer(list),&err);
4238 if (temp==NULL){
4239 ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR);
4240 FPRINTF(ASCERR,"Problem finding instance(s): \n");
4241 WriteName(ASCERR,NamePointer(list));
4242 FPRINTF(ASCERR,"\n");
4243 error_reporter_end_flush();
4244 } else {
4245 gl_destroy(temp);
4246 }
4247 list = NextVariableNode(list);
4248 }
4249 }
4250 }
4251
4252 /**************************************************************************\
4253 VerifyInsts: makes sure at least one thing is found for
4254 each name item on list. Returns 1 if so, or 0 if not.
4255 Does not return the collected instances.
4256 \**************************************************************************/
4257 static
4258 int VerifyInsts(struct Instance *inst,
4259 CONST struct VariableList *list,
4260 enum find_errors *err)
4261 {
4262 struct gl_list_t *temp;
4263 while(list!=NULL){
4264 temp = FindInstances(inst,NamePointer(list),err);
4265 if (temp==NULL){
4266 gl_destroy(temp);
4267 return 0;
4268 }
4269 gl_destroy(temp);
4270 list = NextVariableNode(list);
4271 }
4272 return 1;
4273 }
4274
4275 static
4276 int SameClique(struct Instance *i1, struct Instance *i2)
4277 {
4278 register struct Instance *i=i1;
4279 do {
4280 if (i==i2) return 1;
4281 i = NextCliqueMember(i);
4282 } while(i!=i1);
4283 return 0;
4284 }
4285
4286 static
4287 int InPrecedingClique(struct gl_list_t *list, unsigned long int pos,
4288 struct Instance *inst)
4289 {
4290 unsigned long c;
4291 struct Instance *i;
4292 assert(pos<=gl_length(list));
4293 for(c=1;c<pos;c++){
4294 i = (struct Instance *)gl_fetch(list,c);
4295 if (SameClique(i,inst)) return 1;
4296 }
4297 return 0;
4298 }
4299
4300 static
4301 void RemoveExtras(struct gl_list_t *list)
4302 /*********************************************************************\
4303 This procedure takes time proportional to n^2.
4304 \*********************************************************************/
4305 {
4306 unsigned long c=1;
4307 struct Instance *inst;
4308 while(c<=gl_length(list)){
4309 inst = (struct Instance *)gl_fetch(list,c);
4310 if (InPrecedingClique(list,c,inst)) gl_delete(list,c,0);
4311 else c++;
4312 }
4313 }
4314
4315 static
4316 int ListContainsFundamental(struct gl_list_t *list)
4317 {
4318 unsigned long c=1;
4319 CONST struct Instance *inst;
4320 while(c <= gl_length(list)){
4321 inst = (CONST struct Instance *)gl_fetch(list,c);
4322 if ( IsFundamentalInstance(inst) ){
4323 return 1;
4324 }
4325 c++;
4326 }
4327 return 0;
4328 }
4329
4330 static
4331 int ListContainsParameterized(struct gl_list_t *list)
4332 {
4333 unsigned long c,len;
4334 CONST struct Instance *inst;
4335 CONST struct TypeDescription *d;
4336
4337 len = gl_length(list);
4338 for (c=1; c <= len; c++) {
4339 inst = (CONST struct Instance *)gl_fetch(list,c);
4340 if (inst != NULL) {
4341 d = InstanceTypeDesc(inst);
4342 if (d != NULL) {
4343 if (TypeHasParameterizedInsts(d)!=0) {
4344 return 1;
4345 }
4346 } else {
4347 FPRINTF(ASCERR,"NULL TypeDescription in ExecuteAA\n");
4348 return 1;
4349 }
4350 } else {
4351 FPRINTF(ASCERR,"NULL instance in ExecuteAA\n");
4352 return 1;
4353 }
4354 }
4355 return 0;
4356 }
4357
4358 static
4359 int ExecuteIRT(struct Instance *work, struct Statement *statement)
4360 {
4361 struct TypeDescription *def, *more_refined;
4362 enum find_errors err;
4363 struct gl_list_t *instances; /* presently leaking ? */
4364 struct Instance *inst, *arginst;
4365 unsigned long c,len;
4366 int suberr;
4367
4368 assert(StatementType(statement)==IRT);
4369
4370 def = FindType(GetStatType(statement)); /* sort of redundant, but safe */
4371 if (def!=NULL) {
4372 instances = FindInsts(work,GetStatVarList(statement),&err);
4373 if (instances != NULL){
4374 if (ListContainsFundamental(instances)){
4375 WSEM(ASCERR,statement,
4376 "IS_REFINED_TO statement affects a part of an atom");
4377 gl_destroy(instances);
4378 MarkStatContext(statement,context_WRONG);
4379 WSS(ASCERR,statement);
4380 return 1;
4381 }
4382 RemoveExtras(instances); /* slow process to make sure each clique is */
4383 /* only represented once in the list */
4384 suberr = MakeParameterInst(work,statement,&arginst,KEEPARGINST);/*2*/
4385 if (suberr != MPIOK) {
4386 gl_destroy(instances);
4387 if (suberr == MPIWAIT) {
4388 WriteUnexecutedMessage(ASCERR,statement,
4389 "Possibly undefined arguments in IS_REFINED_TO statement.");
4390 return 0;
4391 } else {
4392 /* bogus args or definition. punt IRT permanently. */
4393 MarkStatContext(statement,context_WRONG);
4394 WSS(ASCERR,statement);
4395 return 1;
4396 }
4397 }
4398 len = gl_length(instances);
4399 /* first we check compatibility -
4400 * no half executed statements and no parameterized cliques.
4401 */
4402 for(c=1;c<=len;c++){
4403 inst = (struct Instance *)gl_fetch(instances,c);
4404 more_refined = MoreRefined(def,InstanceTypeDesc(inst));
4405 if ( more_refined == NULL){
4406 FPRINTF(ASCERR,"Incompatible instance: ");
4407 WriteInstanceName(ASCERR,inst,work);
4408 FPRINTF(ASCERR,"\n");
4409 WSEM(ASCERR,statement,
4410 "Unconformable refinement in IS_REFINED_TO statement");
4411 gl_destroy(instances);
4412 MarkStatContext(statement,context_WRONG);
4413 WSS(ASCERR,statement);
4414 if (arginst!=NULL) {
4415 DestroyParameterInst(arginst);
4416 }
4417 return 1;
4418 }
4419 if (arginst!=NULL) {
4420 if (inst != NextCliqueMember(inst)) {
4421 FPRINTF(ASCERR,"ARE_ALIKE'd instance: ");
4422 WriteInstanceName(ASCERR,inst,work);
4423 FPRINTF(ASCERR,"\n");
4424 WSEM(ASCERR,statement,
4425 "Refinement of clique to parameterized type family disallowed");
4426 gl_destroy(instances);
4427 MarkStatContext(statement,context_WRONG);
4428 WSS(ASCERR,statement);
4429 DestroyParameterInst(arginst);
4430 return 1;
4431 }
4432 suberr = CheckParamRefinement(work,inst,arginst,statement);
4433 /* CheckParamRefinement is responsible for mpierrors wums */
4434 switch (suberr) {
4435 case MPIOK:
4436 break;
4437 case MPIWAIT:
4438 gl_destroy(instances);
4439 DestroyParameterInst(arginst);
4440 return 0;
4441 default:
4442 MarkStatContext(statement,context_WRONG);
4443 WSS(ASCERR,statement);
4444 DestroyParameterInst(arginst);
4445 return 1;
4446 }
4447 }
4448 }
4449 /* ok, so we're going to repeat a little list/type lookups */
4450 for(c=1;c<=len;c++){
4451 inst = (struct Instance *)gl_fetch(instances,c);
4452 more_refined = MoreRefined(def,InstanceTypeDesc(inst));
4453 if (more_refined == def) {
4454 /* whole set will need refining. */
4455 inst = RefineClique(inst,def,arginst);
4456 }
4457 }
4458 DestroyParameterInst(arginst);
4459 gl_destroy(instances);
4460 return 1;
4461 } else {
4462 switch(err){
4463 case impossible_instance:
4464 WSEM(ASCERR,statement,
4465 "IS_REFINED_TO statement contains an impossible instance name");
4466 MissingInsts(work,GetStatVarList(statement),1);
4467 return 1;
4468 default:
4469 MissingInsts(work,GetStatVarList(statement),0);
4470 WriteUnexecutedMessage(ASCERR,statement,
4471 "Could not execute IS_REFINED_TO");
4472 return 0; /* statement is not ready to be executed */
4473 }
4474 }
4475 } else {
4476 char *msg = ascmalloc(strlen(IRT_UNDEFINED_TYPE)+
4477 SCLEN(GetStatType(statement))+1);
4478 strcpy(msg,IRT_UNDEFINED_TYPE);
4479 strcat(msg,SCP(GetStatType(statement)));
4480 WSEM(ASCERR,statement,msg);
4481 ascfree(msg);
4482 return 1;
4483 }
4484 }
4485
4486 static
4487 void RemoveDuplicates(struct gl_list_t *list)
4488 /*********************************************************************\
4489 This assumes that Null is not in the list.
4490 \*********************************************************************/
4491 {
4492 VOIDPTR ptr=NULL;
4493 unsigned c=1;
4494 gl_sort(list,(CmpFunc)CmpPtrs);
4495 while(c<=gl_length(list)){
4496 if (ptr == gl_fetch(list,c)) {
4497 gl_delete(list,c,0);
4498 } else {
4499 ptr = gl_fetch(list,c);
4500 c++;
4501 }
4502 }
4503 }
4504
4505 static
4506 struct TypeDescription *MostRefined(struct gl_list_t *list)
4507 /*********************************************************************\
4508 Return NULL if the list is not conformable or empty. Otherwise,
4509 return the type description of the most refined instance.
4510 \*********************************************************************/
4511 {
4512 struct TypeDescription *mostrefined;
4513 struct Instance *inst;
4514 unsigned long c,len;
4515 assert(list!=NULL);
4516 len = gl_length(list);
4517 if (len==0) return NULL;
4518 inst = (struct Instance *)gl_fetch(list,1);
4519 mostrefined = InstanceTypeDesc(inst);
4520 for(c=2;c<=len;c++){
4521 inst = (struct Instance *)gl_fetch(list,c);
4522 mostrefined = MoreRefined(mostrefined,InstanceTypeDesc(inst));
4523 if (mostrefined==NULL) return NULL;
4524 }
4525 return mostrefined;
4526 }
4527
4528 static
4529 int ExecuteATS(struct Instance *inst, struct Statement *statement)
4530 {
4531 struct gl_list_t *instances;
4532 enum find_errors err;
4533 unsigned long c,len;
4534 struct Instance *inst1,*inst2;
4535
4536 instances = FindInsts(inst,GetStatVarList(statement),&err);
4537 if (instances != NULL){
4538 if (ListContainsFundamental(instances)){
4539 WSEM(ASCERR,statement,
4540 "ARE_THE_SAME statement affects a part of an atom");
4541 gl_destroy(instances);
4542 return 1;
4543 }
4544 RemoveDuplicates(instances); /* make sure that no instances occurs */
4545 /* multiple times */
4546 if ((gl_length(instances)==0)||(MostRefined(instances)!=NULL)){
4547 len = gl_length(instances);
4548 if (len>1){
4549 inst1 = (struct Instance *)gl_fetch(instances,1);
4550 for(c=2;c<=len;c++){
4551 inst2 = (struct Instance *)gl_fetch(instances,c);
4552 inst1 = MergeInstances(inst1,inst2);
4553 if (inst1==NULL){
4554 WSEM(ASCERR,statement, "Fatal ARE_THE_SAME error");
4555 Asc_Panic(2, NULL, "Fatal ARE_THE_SAME error");
4556 /*NOTREACHED Wanna bet? ! */
4557 }
4558 }
4559 PostMergeCheck(inst1);
4560 }
4561 } else {
4562 WSEM(ASCERR,statement,
4563 "ARE_THE_SAME statement contains unconformable instances");
4564 }
4565 gl_destroy(instances);
4566 return 1;
4567 } else {
4568 switch(err){
4569 case impossible_instance:
4570 MissingInsts(inst,GetStatVarList(statement),1);
4571 WSEM(ASCERR,statement, "ARE_THE_SAME contains impossible instance");
4572 return 1;
4573 default:
4574 MissingInsts(inst,GetStatVarList(statement),0);
4575 WriteUnexecutedMessage(ASCERR,statement,
4576 "Could not execute ARE_THE_SAME");
4577 return 0; /* statement is not ready to be executed */
4578 }
4579 }
4580 }
4581
4582 /* disallows parameterized objects from being added to cliques.
4583 */
4584 static
4585 int ExecuteAA(struct Instance *inst, struct Statement *statement)
4586 {
4587 struct gl_list_t *instances;
4588 enum find_errors err;
4589 struct TypeDescription *mostrefined = NULL;
4590 unsigned long c,len;
4591 struct Instance *inst1,*inst2;
4592 instances = FindInsts(inst,GetStatVarList(statement),&err);
4593 if (instances != NULL){
4594 if (ListContainsFundamental(instances)){
4595 WSEM(ASCERR,statement, "ARE_ALIKE statement affects a part of an atom");
4596 gl_destroy(instances);
4597 return 1;
4598 }
4599 if (ListContainsParameterized(instances)){
4600 WSEM(ASCERR,statement, "ARE_ALIKE statement affects parameterized type");
4601 gl_destroy(instances);
4602 return 1;
4603 }
4604 if ((gl_length(instances)==0) ||
4605 ((mostrefined = MostRefined(instances))!=NULL)){
4606 RemoveExtras(instances); /* slow process to make sure each clique is */
4607 /* only represented once in the list */
4608 len = gl_length(instances);
4609 /* refine instances */
4610 for(c=1;c<=len;c++){
4611 inst1 = (struct Instance *)gl_fetch(instances,c);
4612 inst2 = RefineClique(inst1,mostrefined,NULL);
4613 if (inst2!=inst1) {
4614 gl_store(instances,c,(char *)inst2);
4615 }
4616 }
4617 /* merge cliques */
4618 if (len>1){
4619 inst1 = (struct Instance *)gl_fetch(instances,1);
4620 for(c=2;c<=len;c++){
4621 inst2 = (struct Instance *)gl_fetch(instances,c);
4622 MergeCliques(inst1,inst2);
4623 }
4624 }
4625 } else {
4626 WSEM(ASCERR,statement,
4627 "ARE_ALIKE statement contains unconformable instances");
4628 }
4629 gl_destroy(instances);
4630 return 1;
4631 } else {
4632 switch(err){
4633 case impossible_instance:
4634 MissingInsts(inst,GetStatVarList(statement),1);
4635 WSEM(ASCERR,statement, "ARE_ALIKE contains impossible instance");
4636 return 1;
4637 default:
4638 MissingInsts(inst,GetStatVarList(statement),0);
4639 WriteUnexecutedMessage(ASCERR,statement,
4640 "Could not execute ARE_ALIKE");
4641 return 0;
4642 }
4643 }
4644 }
4645
4646
4647 /**************************************************************************\
4648 Relation Processing.
4649 \**************************************************************************/
4650 static
4651 struct Instance *MakeRelationInstance(struct Name *name,
4652 struct TypeDescription *def,
4653 struct Instance *parent,
4654 struct Statement *stat,
4655 enum Expr_enum type)
4656 {
4657 /* CONSOLE_DEBUG("..."); */
4658 symchar *childname;
4659 struct Instance *child;
4660 struct InstanceName rec;
4661 unsigned long pos;
4662 childname = SimpleNameIdPtr(name);
4663 if (childname!=NULL){
4664 SetInstanceNameType(rec,StrName);
4665 SetInstanceNameStrPtr(rec,childname);
4666 pos = ChildSearch(parent,&rec);
4667 if(pos>0){
4668 /* following assertion should be true */
4669 assert(InstanceChild(parent,pos)==NULL);
4670 child = CreateRelationInstance(def,type); /* token relation */
4671 LinkToParentByPos(parent,child,pos);
4672 return child;
4673 } else {
4674 return NULL;
4675 }
4676 } else { /* sparse array of relations */
4677 childname = NameIdPtr(name);
4678 SetInstanceNameType(rec,StrName);
4679 SetInstanceNameStrPtr(rec,childname);
4680 pos = ChildSearch(parent,&rec);
4681 if (pos>0) {
4682 if (InstanceChild(parent,pos)==NULL){
4683 /* must make array */
4684 child = MakeSparseArray(parent,name,stat,NULL,0,NULL,NULL,NULL);
4685 } else {
4686 /* must add array element */
4687 child = AddArrayChild(parent,name,stat,NULL,NULL,NULL);
4688 }
4689 return child;
4690 } else {
4691 return NULL;
4692 }
4693 }
4694 }
4695
4696
4697 /*
4698 * ok, now we can whine real loud about what's missing.
4699 * even in relations referencing relations, because they
4700 * should have been added to pendings in dependency order. (hah!)
4701 */
4702 static
4703 int ExecuteREL(struct Instance *inst, struct Statement *statement)
4704 {
4705 struct Name *name;
4706 enum relation_errors err;
4707 enum find_errors ferr;
4708 struct relation *reln;
4709 struct Instance *child;
4710 struct gl_list_t *instances;
4711 enum Expr_enum reltype;
4712
4713 name = RelationStatName(statement);
4714 instances = FindInstances(inst,name,&ferr);
4715 /* see if the relation is there already */
4716 if (instances==NULL){
4717 if (ferr == unmade_instance){ /* make a reln head */
4718 child = MakeRelationInstance(name,FindRelationType(),
4719 inst,statement,e_token);
4720 if (child==NULL){
4721 WSEM(ASCERR,statement, "Unable to create expression structure");
4722 /* print a better message here if needed. maybe an if!makeindices moan*/
4723 return 1;
4724 }
4725 } else {
4726 /* undefined instances in the relation name, or out of memory */
4727 WSSM(ASCERR,statement, "Unable to execute relation label",3);
4728 return 1;
4729 }
4730 } else {
4731 if(gl_length(instances)==1){
4732 child = (struct Instance *)gl_fetch(instances,1);
4733 assert((InstanceKind(child)==REL_INST) ||
4734 (InstanceKind(child)==DUMMY_INST));
4735 gl_destroy(instances);
4736 if (InstanceKind(child)==DUMMY_INST) {
4737 #ifdef DEBUG_RELS
4738 WSEM(ASCERR,statement, "DUMMY_INST foundin compiling relation.");
4739 #endif
4740 return 1;
4741 }
4742 #ifdef DEBUG_RELS
4743 WSEM(ASCERR,statement, "REL_INST found in compiling relation.");
4744 #endif
4745 } else {
4746 WSEM(ASCERR,statement, "Expression name refers to more than one object");
4747 gl_destroy(instances); /* bizarre! */
4748 return 1;
4749 }
4750 }
4751
4752 /*
4753 * child now contains the pointer to the relation instance.
4754 * We should perhaps double check that the reltype
4755 * has not been set or has been set to e_undefined. !! FIX !!
4756 */
4757 if (GetInstanceRelation(child,&reltype)==NULL) {
4758 if ( (g_instantiate_relns & TOKRELS) ==0) {
4759 #ifdef DEBUG_RELS
4760 WSNM(ASCERR,statement, "TOKRELS 0 found in compiling relation.");
4761 #endif
4762 return 1;
4763 }
4764 #if TIMECOMPILER
4765 g_ExecuteREL_CreateTokenRelation_calls++;
4766 #endif
4767 reln = CreateTokenRelation(inst,child,RelationStatExpr(statement),
4768 &err,&ferr);
4769 if (reln != NULL){
4770 SetInstanceRelation(child,reln,e_token);
4771 #ifdef DEBUG_RELS
4772 WSNM(ASCERR,statement, "Created relation.");
4773 #endif
4774 return 1;
4775 } else {
4776 SetInstanceRelation(child,NULL,e_token);
4777 switch(err){
4778 case incorrect_structure:
4779 WSSM(ASCERR,statement, "Bad relation expression in ExecuteRel",3);
4780 return 1;
4781 case incorrect_inst_type:
4782 WSSM(ASCERR,statement, "Incorrect instance types in relation",3);
4783 return 1;
4784 case incorrect_boolean_inst_type:
4785 WSSM(ASCERR,statement, "Incorrect boolean instance in relation",3);
4786 return 1;
4787 case incorrect_integer_inst_type:
4788 WSSM(ASCERR,statement, "Incorrect integer instance in relation",3);
4789 return 1;
4790 case incorrect_symbol_inst_type:
4791 WSSM(ASCERR,statement, "Incorrect symbol instance in relation",3);
4792 return 1;
4793 case incorrect_real_inst_type:
4794 WSSM(ASCERR,statement,
4795 "Incorrect real child of atom instance in relation",3);
4796 return 1;
4797 case find_error:
4798 switch(ferr){
4799 case unmade_instance:
4800 case undefined_instance:
4801 WSSM(ASCERR,statement,
4802 "Unmade or Undefined instances in relation",3);
4803 return 1;
4804 case impossible_instance:
4805 WSSM(ASCERR,statement,
4806 "Relation contains an impossible instance",3);
4807 return 1;
4808 case correct_instance:
4809 Asc_Panic(2, NULL, "Incorrect error response.\n");/*NOTREACHED*/
4810 default:
4811 Asc_Panic(2, NULL, "Unknown error response.\n");/*NOTREACHED*/
4812 }
4813 case integer_value_undefined:
4814 case real_value_wild:
4815 case real_value_undefined:
4816 WriteUnexecutedMessage(ASCERR,statement,
4817 "Unassigned constants or wild dimensioned real constant in relation");
4818 return 1;
4819 case okay:
4820 Asc_Panic(2, NULL, "Incorrect error response.\n");/*NOTREACHED*/
4821 default:
4822 Asc_Panic(2, NULL, "Unknown error response.\n");/*NOTREACHED*/
4823 exit(2);/* Needed to keep gcc from whining */
4824 }
4825 }
4826 #ifdef DEBUG_RELS
4827 WSNM(ASCERR,statement, " Failed relation -- unexpected scenario.");
4828 #endif
4829 } else{
4830 /* Do nothing, somebody already completed the relation. */
4831 #ifdef DEBUG_RELS
4832 WSNM(ASCERR,statement, "Already compiled in compiling relation?!.");
4833 #endif
4834 return 1;
4835 }
4836 #ifdef DEBUG_RELS
4837 WSNM(ASCERR,statement, "End of ExecuteREL. huh?");
4838 #endif
4839 }
4840
4841 /*
4842 * set a relation instance as Conditional. This is done by activating
4843 * a bit ( relinst_set_conditional(rel,TRUE) ) and by using a flag
4844 * SetRelationIsCond(reln). Only one of these two would be strictly
4845 * required
4846 */
4847 static
4848 void MarkREL(struct Instance *inst, struct Statement *statement)
4849 {
4850 struct Name *name;
4851 enum find_errors ferr;
4852 struct relation *reln;
4853 struct Instance *rel;
4854 struct gl_list_t *instances;
4855 enum Expr_enum reltype;
4856
4857 name = RelationStatName(statement);
4858 instances = FindInstances(inst,name,&ferr);
4859 if (instances==NULL){
4860 gl_destroy(instances);
4861 return;
4862 }
4863 else{
4864 if(gl_length(instances)==1){
4865 rel = (struct Instance *)gl_fetch(instances,1);
4866 gl_destroy(instances);
4867 assert(InstanceKind(rel)==REL_INST);
4868 relinst_set_conditional(rel,TRUE);
4869 reln = GetInstanceRelToModify(rel,&reltype);
4870 if (reln == NULL) {
4871 return ;
4872 }
4873 SetRelationIsCond(reln);
4874 } else{ /* expression name refers to more than one object */
4875 gl_destroy(instances);
4876 return;
4877 }
4878 }
4879 }
4880
4881 /*
4882 * set a logical relation instance as Conditional. This is done by activating
4883 * a bit ( logrelinst_set_conditional(lrel,TRUE) ) and by using a flag
4884 * SetLogRelIsCond(reln). Only one of these two would be strictly
4885 * required
4886 */
4887 static
4888 void MarkLOGREL(struct Instance *inst, struct Statement *statement)
4889 {
4890 struct Name *name;
4891 enum find_errors ferr;
4892 struct logrelation *lreln;
4893 struct Instance *lrel;
4894 struct gl_list_t *instances;
4895
4896 name = LogicalRelStatName(statement);
4897 instances = FindInstances(inst,name,&ferr);
4898 if (instances==NULL){
4899 gl_destroy(instances);
4900 return;
4901 }
4902 else{
4903 if(gl_length(instances)==1){
4904 lrel = (struct Instance *)gl_fetch(instances,1);
4905 gl_destroy(instances);
4906 assert(InstanceKind(lrel)==LREL_INST);
4907 logrelinst_set_conditional(lrel,TRUE);
4908 lreln = GetInstanceLogRelToModify(lrel);
4909 if (lreln == NULL) {
4910 return;
4911 }
4912 SetLogRelIsCond(lreln);
4913 } else{ /* expression name refers to more than one object */
4914 gl_destroy(instances);
4915 return;
4916 }
4917 }
4918 }
4919
4920
4921 /*
4922 * For its use in ExecuteUnSelectedStatements.
4923 * Execute the REL or LOGREL statements inside those cases of a SELECT
4924 * which do not match the selection variables
4925 */
4926 static
4927 int ExecuteUnSelectedEQN(struct Instance *inst, struct Statement *statement)
4928 {
4929 struct Name *name;
4930 enum find_errors ferr;
4931 struct Instance *child;
4932 struct gl_list_t *instances;
4933
4934 switch(StatementType(statement)) {
4935 case REL:
4936 name = RelationStatName(statement);
4937 break;
4938 case LOGREL:
4939 name = LogicalRelStatName(statement);
4940 break;
4941 default:
4942 Asc_Panic(2, NULL, "Incorrect argument passed to ExecuteUnSelectedEQN\n");
4943 name = NULL;
4944 }
4945 instances = FindInstances(inst,name,&ferr);
4946 /* see if the relation is there already */
4947 if (instances==NULL) {
4948 MakeDummyInstance(name,FindDummyType(),inst,statement);
4949 } else {
4950 if(gl_length(instances)==1){
4951 child = (struct Instance *)gl_fetch(instances,1);
4952 assert(InstanceKind(child)==DUMMY_INST);
4953 gl_destroy(instances);
4954 } else{
4955 WSEM(ASCERR,statement, "Expression name refers to more than one object");
4956 gl_destroy(instances);
4957 Asc_Panic(2, NULL, "Expression name refers to more than one object");
4958 }
4959 }
4960 return 1;
4961 }
4962
4963
4964 /******************************************************************\
4965 LOGICAL RELATIONS Processing
4966 Making instances of logical relations or arrays of instances of
4967 logical relations.
4968 \******************************************************************/
4969 static
4970 struct Instance *MakeLogRelInstance(struct Name *name,
4971 struct TypeDescription *def,
4972 struct Instance *parent,
4973 struct Statement *stat)
4974 {
4975 symchar *childname;
4976 struct Instance *child;
4977 struct InstanceName rec;
4978 unsigned long pos;
4979 if ((childname=SimpleNameIdPtr(name))!=NULL){ /* simple name */
4980 SetInstanceNameType(rec,StrName);
4981 SetInstanceNameStrPtr(rec,childname);
4982 if(0 != (pos = ChildSearch(parent,&rec))){
4983 /* following assertion should be true */
4984 assert(InstanceChild(parent,pos)==NULL);
4985 child = CreateLogRelInstance(def);
4986 LinkToParentByPos(parent,child,pos);
4987 return child;
4988 } else {
4989 return NULL;
4990 }
4991 } else { /* sparse array of logical relations */
4992 childname = NameIdPtr(name);
4993 SetInstanceNameType(rec,StrName);
4994 SetInstanceNameStrPtr(rec,childname);
4995 if(0 != (pos = ChildSearch(parent,&rec))){
4996 if (InstanceChild(parent,pos)==NULL){ /* need to make array */
4997 child = MakeSparseArray(parent,name,stat,NULL,0,NULL,NULL,NULL);
4998 } else { /* need to add array element */
4999 child = AddArrayChild(parent,name,stat,NULL,NULL,NULL);
5000 }
5001 return child;
5002 } else {
5003 return NULL;
5004 }
5005 }
5006 }
5007
5008 static
5009 int ExecuteLOGREL(struct Instance *inst, struct Statement *statement)
5010 {
5011 struct Name *name;
5012 enum logrelation_errors err;
5013 enum find_errors ferr;
5014 struct logrelation *lreln;
5015 struct Instance *child;
5016 struct gl_list_t *instances;
5017
5018 name = LogicalRelStatName(statement);
5019 instances = FindInstances(inst,name,&ferr);
5020 /* see if the logical relation is there already */
5021 if (instances==NULL){
5022 gl_destroy(instances);
5023 if (ferr == unmade_instance){
5024 child = MakeLogRelInstance(name,FindLogRelType(),inst,statement);
5025 if (child==NULL){
5026 WUEMPASS3(ASCERR,statement, "Unable to create expression structure");
5027 /* print a better message here if needed */
5028 return 1;
5029 }
5030 }
5031 else {
5032 WUEMPASS3(ASCERR,statement, "Unable to execute expression");
5033 return 1;
5034 }
5035 }
5036 else{
5037 if(gl_length(instances)==1){
5038 child = (struct Instance *)gl_fetch(instances,1);
5039 assert( (InstanceKind(child)==LREL_INST) ||
5040 (InstanceKind(child)==DUMMY_INST));
5041 gl_destroy(instances);
5042 if (InstanceKind(child)==DUMMY_INST) {
5043 return 1;
5044 }
5045 } else{
5046 WUEMPASS3(ASCERR,statement,
5047 "Expression name refers to more than one object");
5048 gl_destroy(instances);
5049 return 1;
5050 }
5051 }
5052
5053 /*
5054 * child now contains the pointer to the logical relation.
5055 */
5056 if (GetInstanceLogRel(child)==NULL){
5057 /* if ( (g_instantiate_relns & TOKRELS) ==0) {
5058 return 1;
5059 } */
5060 if ((lreln = CreateLogicalRelation(inst,child,
5061 LogicalRelStatExpr(statement),&err,&ferr))!=NULL){
5062 SetInstanceLogRel(child,lreln);
5063 return 1;
5064 } else {
5065 SetInstanceLogRel(child,NULL);
5066 switch(err){
5067 case incorrect_logstructure:
5068 WUEMPASS3(ASCERR,statement,
5069 "Bad logical relation expression in ExecuteLOGREL\n");
5070 return 0;
5071 case incorrect_linst_type:
5072 WUEMPASS3(ASCERR,statement,
5073 "Incorrect instance types in logical relation");
5074 return 0;
5075 case incorrect_boolean_linst_type:
5076 WUEMPASS3(ASCERR,statement,
5077 "Incorrect boolean child of atom instance in logical relation");
5078 return 0;
5079 case incorrect_integer_linst_type:
5080 WUEMPASS3(ASCERR,statement,
5081 "Incorrect integer instance in logical relation");
5082 return 0;
5083 case incorrect_symbol_linst_type:
5084 WUEMPASS3(ASCERR,statement,
5085 "Incorrect symbol instance in logical relation");
5086 return 0;
5087 case incorrect_real_linst_type:
5088 WUEMPASS3(ASCERR,statement,
5089 "Incorrect real instance in logical relation");
5090 return 0;
5091 case find_logerror:
5092 switch(ferr){
5093 case unmade_instance:
5094 case undefined_instance:
5095 WUEMPASS3(ASCERR,statement,
5096 "Unmade or Undefined instances in logical relation");
5097 return 0;
5098 case impossible_instance:
5099 WUEMPASS3(ASCERR,statement,
5100 "Logical Relation contains an impossible instance");
5101 return 0;
5102 case correct_instance:
5103 Asc_Panic(2, NULL, "Incorrect error response.\n");/*NOTREACHED*/
5104 default:
5105 Asc_Panic(2, NULL, "Unknown error response.\n");/*NOTREACHED*/
5106 }
5107 case boolean_value_undefined:
5108 WUEMPASS3(ASCERR,statement,
5109 "Unassigned constants in logical relation");
5110 return 0;
5111 case lokay:
5112 Asc_Panic(2, NULL, "Incorrect error response.\n");/*NOTREACHED*/
5113 exit(2);/* Needed to keep gcc from whining */
5114 default:
5115 Asc_Panic(2, NULL, "Unknown error response.\n");/*NOTREACHED*/
5116 exit(2);/* Needed to keep gcc from whining */
5117 }
5118 }
5119 } else{
5120 /* do nothing. someone already completed the logrelation */
5121 return 1;
5122 }
5123 }
5124
5125
5126
5127 /**************************************************************************\
5128 External Procedures Processing.
5129 \**************************************************************************/
5130
5131 /*
5132 **************************************************************************
5133 * BlackBox Relations processing.
5134 *
5135 **************************************************************************
5136 */
5137 static
5138 struct gl_list_t *MakeExtIndices(unsigned long nindices)
5139 {
5140 struct gl_list_t *result;
5141 struct Set *s;
5142 struct IndexType *index;
5143 unsigned long c;
5144
5145 if (nindices) {
5146 result = gl_create(nindices);
5147 for (c=1;c<=nindices;c++) {
5148 s = CreateSingleSet(CreateIntExpr(c));
5149 index = CreateIndexType(s,1); /* create an integer index ??? */
5150 gl_append_ptr(result,(VOIDPTR)index);
5151 }
5152 return result;
5153 } else {
5154 return NULL;
5155 }
5156 }
5157
5158 /*
5159 * This function accepts an array instance for a relation array
5160 * and will construct the appropriate number of children for this
5161 * array and append them to the instance.
5162 */
5163 static
5164 int AddExtArrayChildren(struct Instance *inst, /* this is the aryinst */
5165 struct Statement *stat,
5166 struct gl_list_t *arglist,
5167 struct Instance *data,
5168 unsigned long n_input_args,
5169 unsigned long n_output_args)
5170 {
5171 struct Instance *subject;
5172 struct Instance *relinst;
5173 struct relation *reln;
5174 struct ExternalFunc *efunc;
5175 struct gl_list_t *inputs, *outputs;
5176 unsigned long n_inputs,n_outputs;
5177 unsigned long start,end,c;
5178
5179 if (arglist) {
5180 start = 1L; end = n_input_args;
5181 inputs = LinearizeArgList(arglist,start,end);
5182 n_inputs = gl_length(inputs);
5183
5184 /* Now process the outputs */
5185 start = n_input_args+1; end = n_input_args + n_output_args;
5186 outputs = LinearizeArgList(arglist,start,end);
5187 n_outputs = gl_length(outputs);
5188 efunc = LookupExtFunc(ExternalStatFuncName(stat));
5189
5190 /* Now create the relations, all with the same
5191 * nodestamp. Valid nodestamps are >= 1.
5192 */
5193 g_ExternalNodeStamps++;
5194 for (c=1;c<=n_outputs;c++){
5195 relinst = FindOrAddIntChild(inst,c,NULL,NULL);
5196 subject = (struct Instance *)gl_fetch(outputs,c);
5197 reln = CreateBlackBoxRelation(relinst,efunc,arglist,
5198 subject,inputs,data);
5199 SetInstanceRelation(relinst,reln,e_blackbox);
5200 }
5201 gl_destroy(inputs);
5202 gl_destroy(outputs);
5203 return 0;
5204 } else {
5205 return 1;
5206 }
5207 }
5208
5209 /*
5210 * This function creates the array instance for which the
5211 * children of the array of relations will be apppended.
5212 */
5213 static
5214 struct Instance *MakeExtRelationArray(struct Instance * inst,
5215 struct Name *name,
5216 struct Statement *stat)
5217 {
5218
5219 symchar *relation_name;
5220 struct TypeDescription *desc;
5221 struct InstanceName rec;
5222 unsigned long pos;
5223 struct gl_list_t *indices;
5224 struct Instance *aryinst; /* this is what will be returned */
5225
5226 relation_name = NameIdPtr(name);
5227 SetInstanceNameType(rec,StrName);
5228 SetInstanceNameStrPtr(rec,relation_name);
5229 pos = ChildSearch(inst,&rec);
5230 if (pos) {
5231 if(InstanceChild(inst,pos)==NULL) { /* need to make array */
5232 indices = MakeExtIndices(1);
5233 desc = CreateArrayTypeDesc(StatementModule(stat),
5234 FindRelationType(),0,1,0,0,indices);
5235 aryinst = CreateArrayInstance(desc,1);
5236 LinkToParentByName(inst,aryinst,relation_name);
5237 return aryinst;
5238 }
5239 else
5240 return (InstanceChild(inst,pos)); /* exists so just return it */
5241 }
5242 else
5243 return NULL; /* array name not found -- error */
5244 }
5245
5246 static
5247 int CheckExtCallArgTypes(struct gl_list_t *arglist)
5248 {
5249 unsigned long len1,c1;
5250 unsigned long len2,c2;
5251 struct gl_list_t *branch;
5252 struct Instance *arg;
5253
5254 len1 = gl_length(arglist);
5255 for (c1=1;c1<=len1;c1++){
5256 branch = (struct gl_list_t *)gl_fetch(arglist,c1);
5257 if (!branch) return 1;
5258 len2 = gl_length(branch);
5259 for(c2=1;c2<=len2;c2++){
5260 arg = (struct Instance *)gl_fetch(branch,c2);
5261 if ((InstanceKind(arg)) != REAL_ATOM_INST) {
5262 return 1;
5263 }
5264 }
5265 }
5266 return 0;
5267 }
5268
5269 /*
5270 * This function if fully successful will return a list of
5271 * lists. This will be wasteful if many singlets are used
5272 * as args, other wise it should be more useful than other
5273 * representations.
5274 */
5275
5276 static
5277 struct gl_list_t *ProcessArgs(struct Instance *inst,
5278 CONST struct VariableList *vl,
5279 enum find_errors *ferr)
5280 {
5281 struct gl_list_t *arglist;
5282 struct gl_list_t *branch;
5283
5284 ListMode=1;
5285 arglist = gl_create(10L);
5286 while(vl!=NULL){
5287 branch = FindInstances(inst,NamePointer(vl),ferr);
5288 if (branch==NULL){
5289 DestroySpecialList(arglist);
5290 ListMode=0;
5291 return NULL;
5292 }
5293 gl_append_ptr(arglist,(VOIDPTR)branch);
5294 vl = NextVariableNode(vl);
5295 }
5296 ListMode=0;
5297 return arglist;
5298 }
5299
5300 static
5301 struct gl_list_t *CheckExtCallArgs(struct Instance *inst,
5302 struct Statement *stat,
5303 enum find_errors *ferr)
5304 {
5305 struct VariableList *vl;
5306 struct gl_list_t *result;
5307
5308 vl = ExternalStatVlist(stat);
5309 result = ProcessArgs(inst,vl,ferr);
5310 if (result==NULL){
5311 return NULL;
5312 }
5313 return result;
5314 }
5315
5316 static
5317 struct Instance *CheckExtCallData(struct Instance *inst,
5318 struct Statement *stat,
5319 enum find_errors *ferr)
5320 {
5321 struct Name *n;
5322 struct Instance *result;
5323 struct gl_list_t *instances;
5324
5325 n = ExternalStatData(stat);
5326 if (n) {
5327 instances = FindInstances(inst,n,ferr);
5328 if (instances){ /* only 1 data instance is allowed */
5329 if (gl_length(instances) > 1){
5330 gl_destroy(instances);
5331 *ferr = impossible_instance;
5332 return NULL;
5333 }
5334 else{ /* all ok */
5335 result = (struct Instance *)gl_fetch(instances,1L);
5336 gl_destroy(instances);
5337 /* This may be relaxed later to allow types other than
5338 * MODEL_INSTS. The limitation is really for speed.
5339 */
5340 if (InstanceKind(result)!=MODEL_INST) {
5341 *ferr = impossible_instance;
5342 return NULL;
5343 }
5344 return result;
5345 }
5346 }
5347 else{ /* instance not found -- check ferr */
5348 return NULL;
5349 }
5350 }
5351 else{ /* No data was given so return NULL */
5352 *ferr = correct_instance;
5353 return NULL;
5354 }
5355 }
5356
5357 static
5358 int ExecuteBlackBoxEXT(struct Instance *inst, struct Statement *statement)
5359 {
5360 struct Name *name;
5361 enum find_errors ferr;
5362 struct gl_list_t *arglist=NULL;
5363 struct Instance *aryinst, *data=NULL;
5364 unsigned long len, n_input_args=0L, n_output_args=0L;
5365 struct ExternalFunc *efunc;
5366 CONST char *funcname;
5367
5368 CONSOLE_DEBUG("ENTERED ExecuteBlackBoxExt\n");
5369
5370 /* make or find the array head */
5371 name = ExternalStatName(statement);
5372 aryinst = MakeExtRelationArray(inst,name,statement);
5373 if (aryinst==NULL) {
5374 WriteStatementLocation(ASCERR,statement);
5375 CONSOLE_DEBUG("Unable to create external expression structure.\n");
5376 return 1;
5377 }
5378 /* we now have an array head */
5379 if (!RectangleArrayExpanded(aryinst)){ /* need to make children */
5380 if (ExternalStatData(statement)){
5381 data = CheckExtCallData(inst,statement,&ferr); /* check data */
5382 switch(ferr){
5383 case correct_instance:
5384 break;
5385 case unmade_instance:
5386 return 0;
5387 case undefined_instance:
5388 return 0;
5389 case impossible_instance:
5390 WriteStatementLocation(ASCERR,statement);
5391 FPRINTF(ASCERR,"Statement contains impossible DATA instance\n");
5392 return 1;
5393 default:
5394 WriteStatementLocation(ASCERR,statement);
5395 FPRINTF(ASCERR,"Something really wrong in ExecuteEXT routine\n");
5396 return 1;
5397 }
5398 }
5399 arglist = CheckExtCallArgs(inst,statement,&ferr); /* check main args */
5400 if (arglist==NULL){
5401 switch(ferr){
5402 case unmade_instance:
5403 return 0;
5404 case undefined_instance:
5405 return 0; /* for the time being give another crack */
5406 case impossible_instance:
5407 WriteStatementLocation(ASCERR,statement);
5408 FPRINTF(ASCERR,"Statement contains impossible instance\n");
5409 return 1;
5410 default:
5411 WriteStatementLocation(ASCERR,statement);
5412 FPRINTF(ASCERR,"Something really wrong in ExecuteEXT routine\n");
5413 return 1;
5414 }
5415 }
5416
5417 /*
5418 * Get function call details. The external function had better
5419 * loaded at this stage or report an error.
5420 */
5421 funcname = ExternalStatFuncName(statement);
5422 FPRINTF(ASCERR,">>>>>> ExecuteBlackBoxEXT %s\n",funcname);
5423
5424 efunc = LookupExtFunc(funcname);
5425 if (!efunc) {
5426 FPRINTF(ASCERR,"External function %s was not loaded\n",funcname);
5427 return 1;
5428 }
5429 n_input_args = NumberInputArgs(efunc);
5430 n_output_args = NumberOutputArgs(efunc);
5431 if ((len =gl_length(arglist)) != (n_input_args + n_output_args)) {
5432 WriteStatementLocation(ASCERR,statement);
5433 FPRINTF(ASCERR,"Incorrect number of arguements for statement\n");
5434 return 1;
5435 }
5436 /* we should have a valid arglist at this stage */
5437 if (CheckExtCallArgTypes(arglist)) {
5438 WriteStatementLocation(ASCERR,statement);
5439 FPRINTF(ASCERR,"Wrong type of args to external statement\n");
5440 DestroySpecialList(arglist);
5441 return 1;
5442 }
5443 if (AddExtArrayChildren(aryinst,statement,arglist,data,
5444 n_input_args,n_output_args)) {
5445 WriteStatementLocation(ASCERR,statement);
5446 FPRINTF(ASCERR,"Unable to execute external expression.\n");
5447 DestroySpecialList(arglist);
5448 return 1;
5449 } else {
5450 DestroySpecialList(arglist);
5451 }
5452 return 1; /* all should be ok */
5453 } else {
5454 return 1; /* all should be ok ???*/
5455 }
5456 }
5457
5458
5459 /*
5460 **************************************************************************
5461 * GlassBox Relations processing.
5462 *
5463 * GlassBox relations processing. As is to be expected this code
5464 * is a hybrid between TRUE ascend relations and blackbox relations.
5465 **************************************************************************
5466 */
5467
5468 static
5469 struct gl_list_t *CheckGlassBoxArgs(struct Instance *inst,
5470 struct Statement *stat,
5471 enum relation_errors *err,
5472 enum find_errors *ferr)
5473 {
5474 struct Instance *var;
5475 CONST struct VariableList *vl;
5476 struct gl_list_t *varlist = NULL, *tmp = NULL;
5477 unsigned long len,c;
5478 int error = 0;
5479
5480 vl = ExternalStatVlist(stat);
5481 if (!vl) {
5482 *ferr = impossible_instance; /* a relation with no incidence ! */
5483 return NULL;
5484 }
5485
5486 ListMode = 1; /* order is very important */
5487 varlist = gl_create(NO_INCIDENCES); /* could be fine tuned */
5488 while (vl!=NULL) {
5489 tmp = FindInstances(inst,NamePointer(vl),ferr);
5490 if (tmp) {
5491 len = gl_length(tmp);
5492 for (c=1;c<=len;c++) {
5493 var = (struct Instance *)gl_fetch(tmp,c);
5494 if (InstanceKind(var) != REAL_ATOM_INST) {
5495 error++;
5496 *err = incorrect_inst_type;
5497 *ferr = correct_instance;
5498 gl_destroy(tmp);
5499 goto cleanup;
5500 }
5501 gl_append_ptr(varlist,(VOIDPTR)var);
5502 }
5503 gl_destroy(tmp);
5504 } else { /* ferr will be already be set */
5505 error++;
5506 goto cleanup;
5507 }
5508 vl = NextVariableNode(vl);
5509 }
5510
5511 cleanup:
5512 ListMode = 0;
5513 if (error) {
5514 gl_destroy(varlist);
5515 return NULL;
5516 }
5517 else
5518 return varlist;
5519 }
5520
5521 static
5522 int CheckGlassBoxIndex(struct Instance *inst,
5523 struct Statement *stat,
5524 enum relation_errors *err)
5525 {
5526 int result;
5527 CONST struct Name *n;
5528 symchar *str; /* a string representation of the index */
5529
5530 (void)inst; /* stop gcc whine about unused parameter */
5531
5532 n = ExternalStatData(stat);
5533 if (!n) {
5534 *err = incorrect_num_args; /* we must have an index */
5535 return -1;
5536 }
5537
5538 str = SimpleNameIdPtr(n);
5539 if (str) {
5540 result = atoi(SCP(str)); /* convert to integer. FIXME strtod */
5541 *err = okay;
5542 return result;
5543 }
5544 else{
5545 *err = incorrect_structure; /* we really need to expand */
5546 return -1; /* the relation_error types. !! */
5547 }
5548 }
5549
5550 static
5551 int ExecuteGlassBoxEXT(struct Instance *inst, struct Statement *statement)
5552 {
5553 struct Name *name;
5554 enum relation_errors err;
5555 enum find_errors ferr;
5556 struct Instance *child;
5557 struct gl_list_t *instances;
5558 struct gl_list_t *varlist;
5559 struct relation *reln;
5560 struct ExternalFunc *efunc;
5561 CONST char *funcname;
5562 enum Expr_enum type;
5563 int index;
5564
5565 /*
5566 * Get function call details. The external function had better
5567 * loaded at this stage or report an error. No point in wasting
5568 * time.
5569 */
5570 funcname = ExternalStatFuncName(statement);
5571 efunc = LookupExtFunc(funcname);
5572 if (!efunc) {
5573 FPRINTF(ASCERR,"External function %s was not loaded\n",funcname);
5574 return 1;
5575 }
5576
5577 name = ExternalStatName(statement);
5578 instances = FindInstances(inst,name,&ferr);
5579 if (instances==NULL){
5580 if (ferr == unmade_instance){ /* glassbox reln */
5581 child = MakeRelationInstance(name,FindRelationType(),
5582 inst,statement,e_glassbox);
5583 if (child==NULL){
5584 WSEM(ASCERR,statement, "Unable to create expression structure");
5585 return 1;
5586 }
5587 }
5588 else {
5589 WSEM(ASCERR,statement, "Unable to execute expression");
5590 return 1;
5591 }
5592 }
5593 else{
5594 if(gl_length(instances)==1){
5595 child = (struct Instance *)gl_fetch(instances,1);
5596 assert(InstanceKind(child)==REL_INST);
5597 gl_destroy(instances);
5598 }
5599 else{
5600 WSEM(ASCERR,statement, "Expression name refers to more than one object");
5601 gl_destroy(instances);
5602 return 1;
5603 }
5604 }
5605
5606 /*
5607 * child now contains the pointer to the relation instance;
5608 * Ensure that the variable list is ready.
5609 */
5610 /* FIX FIX FIX -- give some more error diagnostics for err and ferr */
5611 varlist = CheckGlassBoxArgs(inst,statement,&err,&ferr);
5612 if (varlist==NULL){
5613 switch(ferr){
5614 case unmade_instance:
5615 return 0;
5616 case undefined_instance:
5617 return 0; /* for the time being give another crack */
5618 case impossible_instance:
5619 WriteStatementLocation(ASCERR,statement);
5620 FPRINTF(ASCERR,"Statement contains impossible instance\n");
5621 return 1;
5622 default:
5623 WriteStatementLocation(ASCERR,statement);
5624 FPRINTF(ASCERR,"Something really wrong in ExecuteGlassEXT routine\n");
5625 return 1;
5626 }
5627 }
5628
5629 /*
5630 * Get the index of the relation for mapping into the external
5631 * call. An index < 0 is invalid.
5632 */
5633 index = CheckGlassBoxIndex(inst,statement,&err);
5634 if (index < 0) {
5635 FPRINTF(ASCERR,"Invalid index in external relation statement\n");
5636 return 1;
5637 }
5638
5639 /*
5640 * All should be ok at this stage. Create the relation
5641 * structure and attach it to the relation instance.
5642 * CreateGlassBoxRelation makes a copy of the varlist.
5643 * But before we go through the trouble of making the
5644 * relation, we will check that none exists already. If
5645 * one has been created we cleanup and return 1.
5646 */
5647 if (GetInstanceRelation(child,&type)!=NULL) {
5648 goto error;
5649 }
5650 reln = CreateGlassBoxRelation(child,efunc,varlist,index,e_equal);
5651 if (!reln) {
5652 Asc_Panic(2, NULL,
5653 "Major error: Unable to create external relation structure\n");
5654 }
5655 SetInstanceRelation(child,reln,e_glassbox);
5656
5657 error:
5658 if (varlist) gl_destroy(varlist);
5659 return 1;
5660 }
5661
5662 static
5663 int ExecuteEXT(struct Instance *inst, struct Statement *statement)
5664 {
5665 int mode;
5666
5667 CONSOLE_DEBUG("...");
5668
5669 mode = ExternalStatMode(statement);
5670 switch(mode) {
5671 default:
5672 case 0:
5673 WriteStatementLocation(ASCERR,statement);
5674 FPRINTF(ASCERR,"Invalid external statement in declarative section. \n");
5675 return 1;
5676 case 1:
5677 return ExecuteGlassBoxEXT(inst,statement);
5678 case 2:
5679 return ExecuteBlackBoxEXT(inst,statement);
5680 }
5681 }
5682
5683 /**************************************************************************\
5684 Assignment Processing.
5685 \**************************************************************************/
5686 static
5687 void StructuralAsgnErrorReport(struct Statement *statement,
5688 struct value_t *value)
5689 {
5690 WSEM(ASCERR,statement,
5691 "Structural assignment right hand side is not constant");
5692 DestroyValue(value);
5693 }
5694
5695 /*
5696 * returns 1 if error will be persistent, or 0 if error may
5697 * go away later when more compiling is done.
5698 * Issues some sort of message in the case of persistent errors.
5699 */
5700 static
5701 int AsgnErrorReport(struct Statement *statement, struct value_t *value)
5702 {
5703 switch(ErrorValue(*value)){
5704 case undefined_value:
5705 case name_unfound: DestroyValue(value); return 0;
5706 case incorrect_name:
5707 WSEM(ASCERR,statement,
5708 "Assignment right hand side contains non-existent instance");
5709 DestroyValue(value);
5710 return 1;
5711 case temporary_variable_reused:
5712 WSEM(ASCERR,statement, "Assignment re-used temporary variable");
5713 DestroyValue(value);
5714 return 1;
5715 case dimension_conflict:
5716 WSEM(ASCERR,statement,
5717 "Assignment right hand side is dimensionally inconsistent");
5718 DestroyValue(value);
5719 return 1;
5720 case incorrect_such_that:
5721 WSEM(ASCERR,statement, "Assignment uses incorrect such that expression");
5722 DestroyValue(value);
5723 return 1;
5724 case empty_choice:
5725 WSEM(ASCERR,statement, "Assignment has CHOICE of an empty set");
5726 DestroyValue(value);
5727 return 1;
5728 case empty_intersection:
5729 WSEM(ASCERR,statement,
5730 "Assignment has an empty INTERSECTION() construct which is undefined");
5731 DestroyValue(value);
5732 return 1;
5733 case type_conflict:
5734 WSEM(ASCERR,statement,
5735 "Assignment right hand side contains a type conflict");
5736 DestroyValue(value);
5737 return 1;
5738 default:
5739 WSEM(ASCERR,statement, "Assignment contains strange error");
5740 DestroyValue(value);
5741 return 1;
5742 }
5743 }
5744
5745 static
5746 void ReAssignmentError(CONST char *str, struct Statement *statement)
5747 {
5748 char *msg = ascmalloc(strlen(REASSIGN_MESG1)+strlen(REASSIGN_MESG2)+
5749 strlen(str)+1);
5750 strcpy(msg,REASSIGN_MESG1);
5751 strcat(msg,str);
5752 strcat(msg,REASSIGN_MESG2);
5753 WSEM(ASCERR,statement,msg);
5754 ascfree(msg);
5755 }
5756
5757 /*
5758 * returns 1 if ok, 0 if unhappy.
5759 * for any given statement, once unhappy = always unhappy.
5760 */
5761 static
5762 int AssignStructuralValue(struct Instance *inst,
5763 struct value_t value,
5764 struct Statement *statement)
5765 {
5766 switch(InstanceKind(inst)){
5767 case MODEL_INST:
5768 case ARRAY_INT_INST:
5769 case ARRAY_ENUM_INST:
5770 case REL_INST:
5771 case LREL_INST:
5772 WSEM(ASCERR,statement, "Arg! Attempt to assign to a non-scalar");
5773 return 0;
5774 case REAL_ATOM_INST:
5775 case REAL_INST:
5776 case BOOLEAN_ATOM_INST:
5777 case BOOLEAN_INST:
5778 case INTEGER_ATOM_INST:
5779 case INTEGER_INST:
5780 case SYMBOL_ATOM_INST:
5781 case SYMBOL_INST:
5782 WSEM(ASCERR,statement, "Assignment to non-constant LHS ignored");
5783 return 0;
5784 case REAL_CONSTANT_INST:
5785 switch(ValueKind(value)){
5786 case real_value:
5787 if ( AtomAssigned(inst) &&
5788 ( RealValue(value) != RealAtomValue(inst) ||
5789 !SameDimen(RealValueDimensions(value),RealAtomDims(inst)) )
5790 ) {
5791 ReAssignmentError(SCP(GetBaseTypeName(real_constant_type)),statement);
5792 return 0;
5793 } else {
5794 if (!AtomAssigned(inst)) {
5795 if ( !IsWild(RealAtomDims(inst)) &&
5796 !SameDimen(RealValueDimensions(value),RealAtomDims(inst)) ) {
5797 WSEM(ASCERR,statement, "Dimensionally inconsistent assignment");
5798 return 0;
5799 } else {
5800 if (IsWild(RealAtomDims(inst))) {
5801 SetRealAtomDims(inst,RealValueDimensions(value));
5802 }
5803 SetRealAtomValue(inst,RealValue(value),0);
5804 }
5805 }
5806 }
5807 /* case of same value,dimen reassigned is silently ignored */
5808 return 1;
5809 case integer_value:
5810 if ( AtomAssigned(inst) &&
5811 ( (double)IntegerValue(value) != RealAtomValue(inst) ||
5812 !SameDimen(Dimensionless(),RealAtomDims(inst)) )
5813 ) {
5814 ReAssignmentError(SCP(GetBaseTypeName(real_constant_type)),
5815 statement);
5816 return 0;
5817 } else {
5818 if (!AtomAssigned(inst)) {
5819 if ( !IsWild(RealAtomDims(inst)) &&
5820 !SameDimen(Dimensionless(),RealAtomDims(inst)) ) {
5821 WSEM(ASCERR,statement, "Dimensionally inconsistent assignment");
5822 return 0;
5823 } else {
5824 if (IsWild(RealAtomDims(inst))) {
5825 SetRealAtomDims(inst,Dimensionless());
5826 }
5827 SetRealAtomValue(inst,(double)IntegerValue(value),0);
5828 }
5829 }
5830 }
5831 /* case of same value,dimen reassigned is silently ignored */
5832 return 1;
5833 default:
5834 WSEM(ASCERR,statement,
5835 "Attempt to assign non-real value to a real instance");
5836 }
5837 return 0;
5838 case BOOLEAN_CONSTANT_INST:
5839 if (ValueKind(value)!=boolean_value){
5840 WSEM(ASCERR,statement,
5841 "Attempt to assign a non-boolean value to a boolean instance");
5842 return 0;
5843 } else {
5844 if ( AtomAssigned(inst) &&
5845 BooleanValue(value) != GetBooleanAtomValue(inst) ) {
5846 ReAssignmentError(SCP(GetBaseTypeName(boolean_constant_type)),
5847 statement);
5848 return 0;
5849 } else {
5850 if (!AtomAssigned(inst)) {
5851 SetBooleanAtomValue(inst,BooleanValue(value),0);
5852 }
5853 }
5854 }
5855 return 1;
5856 case INTEGER_CONSTANT_INST:
5857 switch(ValueKind(value)){
5858 case integer_value:
5859 if (AtomAssigned(inst)
5860 && (GetIntegerAtomValue(inst)!=IntegerValue(value))) {
5861 ReAssignmentError(SCP(GetBaseTypeName(integer_constant_type)),
5862 statement);
5863 return 0;
5864 } else {
5865 if (!AtomAssigned(inst)) {
5866 SetIntegerAtomValue(inst,IntegerValue(value),0);
5867 }
5868 }
5869 return 1;
5870 case real_value: /* case which is parser artifact: real, wild 0 */
5871 if ( RealValue(value)==0.0 && IsWild(RealValueDimensions(value)) ) {
5872 if (!AtomAssigned(inst)) {
5873 SetIntegerAtomValue(inst,(long)0,0);
5874 } else{
5875 if (AtomAssigned(inst) && (GetIntegerAtomValue(inst)!=0)) {
5876 ReAssignmentError(SCP(GetBaseTypeName(integer_constant_type)),
5877 statement);
5878 return 0;
5879 }
5880 }
5881 return 1;
5882 }
5883 /* intended to fall through to default if not wild real or not 0 */
5884 default:
5885 WSEM(ASCERR,statement,
5886 "Attempt to assign a non-integer value to an integer instance");
5887 }
5888 return 0;
5889 case SET_ATOM_INST:
5890 case SET_INST:
5891 if (ValueKind(value)==set_value){
5892 if (AtomAssigned(inst)&&
5893 !SetsEqual(SetValue(value),SetAtomList(inst))) {
5894 ReAssignmentError(SCP(GetBaseTypeName(set_type)),
5895 statement);
5896 return 0;
5897 } else{
5898 if(!AtomAssigned(inst)) {
5899 struct set_t *cslist;
5900 cslist = CopySet(SetValue(value));
5901 if (!AssignSetAtomList(inst,cslist)) {
5902 DestroySet(cslist);
5903 return 0;
5904 }
5905 }
5906 /* quietly ignore benign reassignment */
5907 }
5908 return 1;
5909 } else {
5910 WSEM(ASCERR,statement,
5911 "Attempt to assign a non-set value to a set instance");
5912 return 0;
5913 }
5914 case SYMBOL_CONSTANT_INST:
5915 if (ValueKind(value)==symbol_value){
5916 assert(AscFindSymbol(SymbolValue(value))!=NULL);
5917 if (AtomAssigned(inst) &&
5918 (SymbolValue(value) != GetSymbolAtomValue(inst))) {
5919 ReAssignmentError(SCP(GetBaseTypeName(symbol_constant_type)),
5920 statement);
5921 return 0;
5922 } else{
5923 if (!AtomAssigned(inst)) {
5924 SetSymbolAtomValue(inst,SymbolValue(value));
5925 }
5926 }
5927 return 1;
5928 } else {
5929 WSEM(ASCERR,statement,
5930 "Attempt to assign a non-symbol value to a symbol instance");
5931 }
5932 return 0;
5933 default:
5934 WSEM(ASCERR,statement, "Error: Unknown value type");
5935 return 0;
5936 }
5937 }
5938
5939 /*
5940 * Execute structural and dimensional assignments.
5941 * This is called by execute statements and exec for statements.
5942 * Assignments to variable types are ignored.
5943 * Variable defaults expressions are done in executedefaults.
5944 * rhs expressions must yield constant value_t.
5945 * Incorrect statements will be marked context_WRONG where possible.
5946 */
5947 static
5948 int ExecuteCASGN(struct Instance *work, struct Statement *statement)
5949 {
5950 struct gl_list_t *instances;
5951 struct Instance *inst;
5952 unsigned long c,len;
5953 struct value_t value;
5954 enum find_errors err;
5955 int previous_context;
5956 int rval;
5957
5958 if (StatWrong(statement)) return 1; /* if we'll never execute it, it's ok */
5959
5960 previous_context = GetDeclarativeContext();
5961 SetDeclarativeContext(0);
5962 instances = FindInstances(work,AssignStatVar(statement),&err);
5963 if (instances != NULL){
5964 assert(GetEvaluationContext()==NULL);
5965 SetEvaluationContext(work);
5966 value = EvaluateExpr(AssignStatRHS(statement),NULL,
5967 InstanceEvaluateName);
5968 SetEvaluationContext(NULL);
5969 if (ValueKind(value)==error_value || !IsConstantValue(value) ){
5970 if (ValueKind(value)==error_value) {
5971 gl_destroy(instances);
5972 SetDeclarativeContext(previous_context);
5973 rval = AsgnErrorReport(statement,&value);
5974 if (rval) {
5975 MarkStatContext(statement,context_WRONG);
5976 WSS(ASCERR,statement);
5977 }
5978 return rval;
5979 } else {
5980 gl_destroy(instances);
5981 SetDeclarativeContext(previous_context);
5982 StructuralAsgnErrorReport(statement,&value);
5983 WSEM(ASCERR,statement, "Assignment is impossible");
5984 MarkStatContext(statement,context_WRONG);
5985 WSS(ASCERR,statement);
5986 return 1;
5987 }
5988 } else {
5989 /* good rhs value, but may be mismatched to set ATOM */
5990 len = gl_length(instances);
5991 for(c=1;c<=len;c++){
5992 inst = (struct Instance *)gl_fetch(instances,c);
5993 if (!AssignStructuralValue(inst,value,statement)) {
5994 MarkStatContext(statement,context_WRONG);
5995 WSEM(ASCERR,statement, "Assignment is impossible (wrong set type)");
5996 WSS(ASCERR,statement);
5997 }
5998 }
5999 DestroyValue(&value);
6000 gl_destroy(instances);
6001 SetDeclarativeContext(previous_context);
6002 return 1;
6003 }
6004 } else {
6005 switch(err){
6006 case impossible_instance:
6007 WSEM(ASCERR,statement, "Left hand side of assignment statement"
6008 " contains an impossible instance");
6009 SetDeclarativeContext(previous_context);
6010 return 1;
6011 default: /* unmade instances or something */
6012 SetDeclarativeContext(previous_context);
6013 return 0;
6014 }
6015 }
6016 }
6017
6018 /**************************************************************************\
6019 Check routines.
6020 \**************************************************************************/
6021 /*
6022 * Returns 1 if name can be found in name, or 0 OTHERWISE.
6023 * only deals well with n and sub being Id names.
6024 */
6025 static
6026 int NameContainsName(CONST struct Name *n,CONST struct Name *sub)
6027 {
6028 struct gl_list_t *nl;
6029 unsigned long c,len;
6030 struct Expr *en;
6031
6032 assert(n!=NULL);
6033 assert(sub!=NULL);
6034 en = (struct Expr *)ascmalloc(sizeof(struct Expr));
6035 InitVarExpr(en,n);
6036 nl = EvaluateNamesNeededShallow(en,NULL,NULL);
6037 /* should this function be checking deep instead? can't tell yet. */
6038 if (nl==NULL || gl_length(nl)==0) {
6039 return 0; /* should never happen */
6040 }
6041 for (c=1, len = gl_length(nl); c <= len; c++) {
6042 if (CompareNames((struct Name *)gl_fetch(nl,c),sub)==0) {
6043 gl_destroy(nl);
6044 return 1;
6045 }
6046 }
6047 gl_destroy(nl);
6048 ascfree(en);
6049 return 0;
6050 }
6051 /*
6052 * Checks that the namelist, less any components that contain arrsetname,
6053 * can be evaluated to constant values.
6054 * Returns 1 if it can be evaluated.
6055 *
6056 * This is heuristic. It can fail in very very twisty circumstances.
6057 * What saves the heuristic is that usually all the other conditions
6058 * on the compound ALIASES (that rhs's must exist and so forth) will
6059 * be satisfied before this check is performed and that that will mean
6060 * enough structure to do the job at Execute time will be in place even
6061 * if this returns a FALSE positive.
6062 * Basically to trick this thing you have to do indirect addressing with
6063 * the set elements of the IS_A set in declaring the lhs of the ALIASES
6064 * part. Of course if you really do that sort of thing, you should be
6065 * coding in C++ or F90 anyway.
6066 *
6067 * What it comes down to is that this array constructor from diverse
6068 * elements really sucks -- but so does varargs and that's what we're
6069 * using the compound alias array constructor to implement.
6070 *
6071 * There is an extremely expensive alternative that is not heuristic --
6072 * create the IS_A set (which might be a sparse array) during the
6073 * check process and blow it away when the check fails. This is an
6074 * utter nuisance and a cost absurdity.
6075 * --baa 1/97.
6076 */
6077 static
6078 int ArrayCheckNameList(struct Instance *inst,
6079 struct Statement *statement,
6080 struct gl_list_t *nl,
6081 CONST struct Name *arrsetname)
6082 {
6083 unsigned long c,len,i,ilen;
6084 struct Instance *fi;
6085 CONST struct Name *n;
6086 struct gl_list_t *il;
6087 symchar *name;
6088 enum find_errors err;
6089
6090 len = gl_length(nl);
6091 if (len==0) {
6092 return 1;
6093 }
6094 for (c=1; c <= len; c++) {
6095 n = (struct Name *)gl_fetch(nl,c);
6096 if (NameContainsName(n,arrsetname) == 0 ) {
6097 name = SimpleNameIdPtr(n);
6098 if (name !=NULL && StatInFOR(statement) &&
6099 FindForVar(GetEvaluationForTable(),name)!=NULL) {
6100 continue;
6101 }
6102 /* else hunt up the instances */
6103 il = FindInstances(inst,n,&err);
6104 if (il == NULL) {
6105 return 0;
6106 }
6107 for (i=1, ilen=gl_length(il); i <=ilen; i++) {
6108 fi = (struct Instance *)gl_fetch(il,i);
6109 switch(InstanceKind(fi)) {
6110 case SET_ATOM_INST:
6111 case INTEGER_CONSTANT_INST:
6112 case SYMBOL_CONSTANT_INST:
6113 if (AtomAssigned(fi)==0) {
6114 gl_destroy(il);
6115 return 0;
6116 }
6117 break;
6118 case MODEL_INST:
6119 case ARRAY_INT_INST:
6120 case ARRAY_ENUM_INST:
6121 /* ok, it was found. odd, that, but it might be ok */
6122 break;
6123 /* fundamental, variable, relation, when, logrel, realcon, boolcon
6124 * can none of them figure in the definition of valid set.
6125 * so we exit early and execution will fail as required.
6126 */
6127 default:
6128 gl_destroy(il);
6129 return 1;
6130 }
6131 }
6132 }
6133 }
6134 return 1;
6135 }
6136 /*
6137 * check the subscripts for definedness, including FOR table checks and
6138 * checks for the special name in the compound ALIASES-IS_A statement.
6139 * Assumes it is going to be handed a name consisting entirely of
6140 * subscripts.
6141 */
6142 static
6143 int FailsCompoundArrayCheck(struct Instance *inst,
6144 CONST struct Name *name,
6145 struct Statement *statement,
6146 CONST struct Name *arrsetname)
6147 {
6148 struct gl_list_t *nl;
6149 CONST struct Set *sptr;
6150 int ok;
6151
6152 while(name != NULL){
6153 /* foreach subscript */
6154 if (NameId(name)!=0){ /* what's a . doing in the name? */
6155 return 1;
6156 }
6157 sptr = NameSetPtr(name);
6158 nl = EvaluateSetNamesNeeded(sptr,NULL);
6159 if (nl != NULL) {
6160 ok = ArrayCheckNameList(inst,statement,nl,arrsetname);
6161 gl_destroy(nl);
6162 if (ok == 0 ) {
6163 return 1;
6164 }
6165 } else {
6166 return 1;
6167 }
6168 name = NextName(name);
6169 }
6170 return 0;
6171 }
6172
6173 static
6174 int FailsIndexCheck(CONST struct Name *name, struct Statement *statement,
6175 struct Instance *inst, CONST unsigned int searchfor,
6176 CONST struct Name *arrsetname)
6177 /*********************************************************************\
6178 The name pointer is known to be an array, so now it is checked to make
6179 sure that each index type can be determined.
6180 It is not a . qualified name.
6181
6182 With searchfor == 0:
6183 This routine deliberately lets some errors through because the will
6184 be trapped elsewhere. Its *only* job is to detect undefined index
6185 types. (defined indices simply missing values will merely be done
6186 in a later array expansion.
6187 Returns 1 if set type indeterminate.
6188
6189 With searchfor != 0:
6190 Tries to expand the indices completely and returns 1 if fails.
6191 arrset name is a special name that may be used in indices when
6192 creating compound ALIASES-IS_A -- it is the name the IS_A will create.
6193 It is only considered if searchfor != 0.
6194 \*********************************************************************/
6195 {
6196 CONST struct Set *sptr;
6197 struct gl_list_t *indices;
6198 if (!NameId(name)) {
6199 return 0; /* this is a different type of error */
6200 }
6201 /* hunt the subscripts */
6202 name = NextName(name);
6203 if (name == NULL) {
6204 return 0; /* this is a different type of error */
6205 }
6206 if (searchfor == 0) { /* not in FOR loop and not ALIASES of either sort */
6207 while (name != NULL){
6208 if (NameId(name) !=0 ) {
6209 /* what's a . doing here? */
6210 return 0;
6211 }
6212 sptr = NameSetPtr(name);
6213 if (DeriveSetType(sptr,inst,0) < 0) {
6214 return 1; /* confusion reigns */
6215 }
6216 name = NextName(name);
6217 }
6218 } else {
6219 assert(statement!=NULL);
6220 if (arrsetname == NULL) {
6221 /* sparse IS_A or ALIASES but not ALIASES/IS_A */
6222 indices = MakeIndices(inst,name,statement);
6223 if (indices != NULL) {
6224 DestroyIndexList(indices);
6225 return 0;
6226 } else {
6227 return 1;
6228 }
6229 } else {
6230 /* sparse or dense ALIASES-IS_A where we have to handle a
6231 * special name we
6232 * can't tell the value of yet because the IS_A hasn't been
6233 * compiled.
6234 */
6235 return FailsCompoundArrayCheck(inst,name,statement,arrsetname);
6236 }
6237 }
6238 return 0;
6239 }
6240
6241 static
6242 int ContainsUnknownArrayIndex(struct Instance *inst,
6243 struct Statement *stat,
6244 CONST struct Name *name,
6245 CONST unsigned int searchfor,
6246 CONST struct Name *arrsetname)
6247 /*********************************************************************\
6248 This has to check this member of the variable list for unknown
6249 array indices. It returns TRUE iff it contains an unknown index;
6250 otherwise, it returns FALSE.
6251 If searchfor !=0, include for indices in list of valid things,
6252 and insist that values actually have been assigned as well.
6253 \*********************************************************************/
6254 {
6255 if (!SimpleNameIdPtr(name)){ /* simple names never miss indices */
6256 if (FailsIndexCheck(name,stat,inst,searchfor,arrsetname)) return 1;
6257 }
6258 return 0;
6259 }
6260
6261 static
6262 int CheckALIASES(struct Instance *inst, struct Statement *stat)
6263 /*********************************************************************\
6264 If there are no array instances, this should always return TRUE. When
6265 there are array instances to be created, it has to check to make sure
6266 that all of the index types can be determined and their values are
6267 defined!
6268
6269 aliases always appears to be in for loop because we must always have
6270 a definition of all the sets because an alias array can't be finished
6271 up later.
6272 \*********************************************************************/
6273 {
6274 CONST struct VariableList *vlist;
6275 int cu;
6276 struct gl_list_t *rhslist;
6277 CONST struct Name *name;
6278 enum find_errors ferr;
6279
6280 vlist = GetStatVarList(stat);
6281 while (vlist != NULL){
6282 cu = ContainsUnknownArrayIndex(inst,stat,NamePointer(vlist),1,NULL);
6283 if (cu) {
6284 return 0;
6285 }
6286 vlist = NextVariableNode(vlist);
6287 }
6288
6289 /*
6290 * Checking the existence of the rhs in the aliases statement
6291 */
6292 name = AliasStatName(stat);
6293 rhslist = FindInstances(inst,name,&ferr);
6294 if (rhslist == NULL) {
6295 WriteUnexecutedMessage(ASCERR,stat,
6296 "Possibly undefined right hand side in ALIASES statement.");
6297 return 0; /* rhs not compiled yet */
6298 }
6299 if (gl_length(rhslist)>1) {
6300 WSEM(ASCERR,stat,"ALIASES needs exactly 1 RHS");
6301 }
6302 gl_destroy(rhslist);
6303
6304 return 1;
6305 }
6306
6307 static
6308 int CheckARR(struct Instance *inst, struct Statement *stat)
6309 /*********************************************************************\
6310 This has to make sure the RHS list of the ALIASES and the WITH_VALUE
6311 of the IS_A are both satisfied.
6312
6313 When the statement is in a FOR loop, this has to check to make sure
6314 that all of the LHS index types can be determined and their values are
6315 defined!
6316 ALIASES always appears to be in for loop because we must always have
6317 a definition of all the sets because an alias array can't be finished
6318 up later.
6319 \*********************************************************************/
6320 {
6321 CONST struct VariableList *vlist;
6322 struct value_t value;
6323 int cu;
6324
6325 assert(StatementType(stat)==ARR);
6326
6327 /* check subscripts on IS_A portion lhs. all mess should be in fortable */
6328 cu = ContainsUnknownArrayIndex(inst,
6329 stat,
6330 NamePointer( ArrayStatSetName(stat)),
6331 1,
6332 NULL);
6333 if (cu != 0) {
6334 return 0;
6335 }
6336 /* check ALIASES portion lhs list */
6337 vlist = ArrayStatAvlNames(stat);
6338 while (vlist != NULL){
6339 cu = ContainsUnknownArrayIndex(inst,
6340 stat,
6341 NamePointer(vlist),
6342 1,
6343 NamePointer(ArrayStatSetName(stat)));
6344 if (cu != 0) {
6345 return 0;
6346 }
6347 vlist = NextVariableNode(vlist);
6348 }
6349 /* check ALIASES portion rhs (list of instances collecting to an array) */
6350 if (CheckVarList(inst,stat)==0) {
6351 return 0;
6352 }
6353 /* check IS_A WITH_VALUE list */
6354 if (ArrayStatSetValues(stat)!=NULL) {
6355 assert(GetEvaluationContext()==NULL);
6356 SetEvaluationContext(inst);
6357 value = EvaluateSet(ArrayStatSetValues(stat),InstanceEvaluateName);
6358 SetEvaluationContext(NULL);
6359 switch(ValueKind(value)){
6360 case list_value:
6361 /* set may be garbage, in which case execute will whine */
6362 break;
6363 case error_value:
6364 switch(ErrorValue(value)){
6365 case name_unfound:
6366 case undefined_value:
6367 DestroyValue(&value);
6368 return 0;
6369 default:
6370 FPRINTF(ASCERR,"Compound alias instance has incorrect index type.\n");
6371 break;
6372 }
6373 break;
6374 default:
6375 FPRINTF(ASCERR,
6376 "Compound alias instance has incorrect index value type.\n");
6377 break;
6378 }
6379 DestroyValue(&value);
6380 }
6381 return 1;
6382 }
6383
6384 static
6385 int CheckISA(struct Instance *inst, struct Statement *stat)
6386 /*********************************************************************\
6387 If there are no array instances, this should always return TRUE. When
6388 there are array instances to be created, it has to check to make sure
6389 that all of the index types can be determined.
6390 If statement requires type args, also checks that all array indices
6391 can be evaluated.
6392
6393 Currently, this can handle checking for completable sets in any
6394 statement's var list, not just ISAs.
6395
6396 It does not at present check arguments of IS_A's.
6397 \*********************************************************************/
6398 {
6399 CONST struct VariableList *vlist;
6400 int cu;
6401 unsigned int searchfor;
6402 if (StatWrong(stat)) return 1; /* if we'll never execute it, it's ok */
6403 searchfor = ( StatInFOR(stat)!=0 ||
6404 GetStatNeedsArgs(stat) > 0 ||
6405 StatModelParameter(stat)!=0 );
6406 vlist = GetStatVarList(stat);
6407 while (vlist != NULL){
6408 cu =
6409 ContainsUnknownArrayIndex(inst,stat,NamePointer(vlist),searchfor,NULL);
6410 if (cu) {
6411 return 0;
6412 }
6413 vlist = NextVariableNode(vlist);
6414 }
6415 return 1;
6416 }
6417
6418 /***********************************************************************/
6419 /*
6420 * checks that all the names in a varlist exist as instances.
6421 * returns 1 if TRUE, 0 if not.
6422 */
6423 static
6424 int CheckVarList(struct Instance *inst, struct Statement *statement)
6425 {
6426 enum find_errors err;
6427 int instances;
6428 instances = VerifyInsts(inst,GetStatVarList(statement),&err);
6429 if (instances){
6430 return 1;
6431 } else {
6432 switch(err){
6433 case impossible_instance: return 1;
6434 default: return 0;
6435 }
6436 }
6437 }
6438
6439 static
6440 int CheckIRT(struct Instance *inst, struct Statement *statement)
6441 {
6442 if (FindType(GetStatType(statement))==NULL) return 1;
6443 return CheckVarList(inst,statement);
6444 }
6445
6446 static
6447 int CheckATS(struct Instance *inst, struct Statement *statement)
6448 {
6449 return CheckVarList(inst,statement);
6450 }
6451
6452 static
6453 int CheckAA(struct Instance *inst, struct Statement *statement)
6454 {
6455 return CheckVarList(inst,statement);
6456 }
6457
6458 /***********************************************************************/
6459 /*
6460 * Checks that the lhs of an assignment statement expands into
6461 * a complete set of instances.
6462 * Not check that the first of those instances is type compatible with
6463 * the value being assigned.
6464 */
6465 static
6466 int CheckCASGN(struct Instance *inst, struct Statement *statement)
6467 {
6468 struct gl_list_t *instances;
6469 struct value_t value;
6470 enum find_errors err;
6471 instances = FindInstances(inst,AssignStatVar(statement),&err);
6472 if (instances != NULL){
6473 gl_destroy(instances);
6474 assert(GetEvaluationContext()==NULL);
6475 SetEvaluationContext(inst);
6476 value = EvaluateExpr(AssignStatRHS(statement),NULL,
6477 InstanceEvaluateName);
6478 SetEvaluationContext(NULL);
6479 if (ValueKind(value)==error_value){
6480 switch(ErrorValue(value)){
6481 case undefined_value:
6482 case name_unfound:
6483 DestroyValue(&value);
6484 return 0;
6485 default: /* it is a question whether this is a correct action */
6486 break; /* should we handle other error classes? */
6487 }
6488 }
6489 DestroyValue(&value);
6490 return 1; /* everything is okay */
6491 } else {
6492 switch(err){
6493 case impossible_instance: return 1;
6494 default:
6495 return 0;
6496 }
6497 }
6498 }
6499
6500 /***********************************************************************/
6501 #ifdef THIS_IS_AN_UNUSED_FUNCTION
6502 static
6503 int CheckASGN(struct Instance *inst, struct Statement *statement)
6504 {
6505 struct gl_list_t *instances;
6506 struct value_t value;
6507 enum find_errors err;
6508 instances = FindInstances(inst,DefaultStatVar(statement),&err);
6509 if (instances != NULL){
6510 gl_destroy(instances);
6511 assert(GetEvaluationContext()==NULL);
6512 SetEvaluationContext(inst);
6513 value = EvaluateExpr(DefaultStatRHS(statement),NULL,
6514 InstanceEvaluateName);
6515 SetEvaluationContext(NULL);
6516 if (ValueKind(value)==error_value){
6517 switch(ErrorValue(value)){
6518 case undefined_value:
6519 case name_unfound:
6520 DestroyValue(&value);
6521 return 0;
6522 default: /* it is a question whether this is a correct action */
6523 break; /* should we handle other error classes? */
6524 }
6525 }
6526 DestroyValue(&value);
6527 return 1; /* everything is okay */
6528 }
6529 else{
6530 switch(err){
6531 case impossible_instance: return 1;
6532 default:
6533 return 0;
6534 }
6535 }
6536 }
6537 #endif /* THIS_IS_AN_UNUSED_FUNCTION */
6538
6539
6540 /***********************************************************************/
6541 /*
6542 * Check if the relation exists, also, if it exists as relation or as a
6543 * dummy instance. return -1 for DUMMY. 1 for relation. 0 if the checking
6544 * fails.
6545 */
6546 static
6547 int CheckRelName(struct Instance *work, struct Name *name)
6548 {
6549 struct gl_list_t *instances;
6550 struct Instance *inst;
6551 enum find_errors ferr;
6552 instances = FindInstances(work,name,&ferr);
6553 if (instances==NULL){
6554 return 1;
6555 }
6556 else{
6557 if (gl_length(instances)==1){
6558 inst = (struct Instance *)gl_fetch(instances,1);
6559 assert((InstanceKind(inst)==REL_INST) ||
6560 (InstanceKind(inst)==DUMMY_INST));
6561 gl_destroy(instances);
6562 if (InstanceKind(inst)==DUMMY_INST) {
6563 return -1;
6564 }
6565 return 1;
6566 }
6567 else {
6568 gl_destroy(instances);
6569 return 0;
6570 }
6571 }
6572 }
6573
6574 /*
6575 * If the relation is already there, it may be a dummy instance. In
6576 * such a case, do not check the expression. Currently not in
6577 * use.
6578 */
6579 static
6580 int CheckREL(struct Instance *inst, struct Statement *statement)
6581 {
6582
6583 if (!CheckRelName(inst,RelationStatName(statement))) {
6584 return 0;
6585 }
6586 if ( CheckRelName(inst,RelationStatName(statement)) == -1) {
6587 return 1;
6588 }
6589 return CheckRelation(inst,RelationStatExpr(statement));
6590 }
6591
6592 /***********************************************************************/
6593
6594 /* Check that the logical relation instance of some name has not been
6595 * previously created, or if it has, the instance is unique and
6596 * corresponds to a logical relation or to a dummy.
6597 * return -1 for DUMMY. 1 for log relation. 0 if the checking fails.
6598 */
6599 static
6600 int CheckLogRelName(struct Instance *work, struct Name *name)
6601 {
6602 struct gl_list_t *instances;
6603 struct Instance *inst;
6604 enum find_errors ferr;
6605 instances = FindInstances(work,name,&ferr);
6606 if (instances==NULL){
6607 return 1;
6608 }
6609 else{
6610 if (gl_length(instances)==1){
6611 inst = (struct Instance *)gl_fetch(instances,1);
6612 assert((InstanceKind(inst)==LREL_INST) ||
6613 (InstanceKind(inst)==DUMMY_INST));
6614 gl_destroy(instances);
6615 if (InstanceKind(inst)==DUMMY_INST) {
6616 return -1;
6617 }
6618 return 1;
6619 }
6620 else {
6621 gl_destroy(instances);
6622 return 0;
6623 }
6624 }
6625 }
6626
6627 /* Checking of Logical relation. First the name, then the expression.
6628 * If the logrel exists as a dummy, then do not check the expression.
6629 * Currently not in use.
6630 */
6631 static
6632 int CheckLOGREL(struct Instance *inst, struct Statement *statement)
6633 {
6634 if (!CheckLogRelName(inst,LogicalRelStatName(statement)))
6635 return 0;
6636 if ( CheckLogRelName(inst,LogicalRelStatName(statement)) == -1)
6637 return 1;
6638 return CheckLogRel(inst,LogicalRelStatExpr(statement));
6639 }
6640
6641
6642 /***********************************************************************/
6643 /* Checking FNAME statement */
6644
6645 /* The following two functions check that the FNAME inside a WHEN
6646 * make reference to instance of models, relations, or arrays of
6647 * models or relations previously created.
6648 */
6649 static
6650 int CheckArrayRelMod(struct Instance *child)
6651 {
6652 struct Instance *arraychild;
6653 unsigned long len,c;
6654 switch (InstanceKind(child)) {
6655 case REL_INST:
6656 case LREL_INST:
6657 case MODEL_INST:
6658 return 1;
6659 case ARRAY_INT_INST:
6660 case ARRAY_ENUM_INST:
6661 len = NumberChildren(child);
6662 for(c=1;c<=len;c++){
6663 arraychild = InstanceChild(child,c);
6664 if (!CheckArrayRelMod(arraychild)){
6665 return 0;
6666 }
6667 }
6668 return 1;
6669 default:
6670 FPRINTF(ASCERR,
6671 "Incorrect array instance name inside a WHEN statement\n");
6672 return 0;
6673 }
6674 }
6675
6676 static
6677 int CheckRelModName(struct Instance *work, struct Name *name)
6678 {
6679 struct gl_list_t *instances;
6680 struct Instance *inst, *child;
6681 enum find_errors ferr;
6682 unsigned long len,c;
6683 instances = FindInstances(work,name,&ferr);
6684 if (instances==NULL){
6685 FPRINTF(ASCERR,"\n");
6686 FPRINTF(ASCERR,
6687 "Name of an unmade instance (Relation/Model) inside a %s \n",
6688 "WHEN statement:");
6689 WriteName(ASCERR,name);
6690 gl_destroy(instances);
6691 return 0;
6692 }
6693 else{
6694 if (gl_length(instances)==1){
6695 inst = (struct Instance *)gl_fetch(instances,1);
6696 switch (InstanceKind(inst)) {
6697 case REL_INST:
6698 case LREL_INST:
6699 case MODEL_INST:
6700 gl_destroy(instances);
6701 return 1;
6702 case ARRAY_INT_INST:
6703 case ARRAY_ENUM_INST:
6704 len = NumberChildren(inst);
6705 for(c=1;c<=len;c++){
6706 child = InstanceChild(inst,c);
6707 if (!CheckArrayRelMod(child)){
6708 gl_destroy(instances);
6709 return 0;
6710 }
6711 }
6712 gl_destroy(instances);
6713 return 1;
6714 default:
6715 FPRINTF(ASCERR,"\n");
6716 FPRINTF(ASCERR,
6717 "Incorrect instance name (No Model/Relation) inside a %s \n",
6718 " WHEN statement:");
6719 WriteName(ASCERR,name);
6720 gl_destroy(instances);
6721 return 0;
6722 }
6723 }
6724 else {
6725 FPRINTF(ASCERR,"\n");
6726 FPRINTF(ASCERR,
6727 "Error in WHEN statement. Name assigned to more than one %s \n",
6728 "instance type:");
6729 WriteName(ASCERR,name);
6730 gl_destroy(instances);
6731 return 0;
6732 }
6733 }
6734 }
6735
6736 /*
6737 * A FNAME statement stands for a relation, model, or an array of models
6738 * or relations. This checking is to make sure that those instance
6739 * were already created
6740 */
6741 static
6742 int CheckFNAME(struct Instance *inst, struct Statement *statement)
6743 {
6744 if (!CheckRelModName(inst,FnameStat(statement)))
6745 return 0;
6746 else
6747 return 1;
6748 }
6749
6750 /***********************************************************************/
6751
6752 /* Only logrelations and FOR loops of logrelations are allowed inside a
6753 * conditional statement in Pass3. This function ask for recursively
6754 * checking these statements */
6755 static
6756 int Pass3CheckCondStatements(struct Instance *inst,
6757 struct Statement *statement)
6758 {
6759 assert(inst&&statement);
6760 switch(StatementType(statement)){
6761 case LOGREL:
6762 return CheckLOGREL(inst,statement);
6763 case FOR:
6764 return Pass3RealCheckFOR(inst,statement);
6765 case REL:
6766 case ALIASES:
6767 case ARR:
6768 case ISA:
6769 case IRT:
6770 case ATS:
6771 case AA:
6772 case CALL:
6773 case EXT:
6774 case ASGN:
6775 case CASGN:
6776 case COND:
6777 case WHEN:
6778 case FNAME:
6779 case SELECT:
6780 WSEM(ASCERR,statement,
6781 "Statement not allowed inside a CONDITIONAL statement\n");
6782 return 0;
6783 default:
6784 FPRINTF(ASCERR,"Inappropriate statement type in CheckStatement\n");
6785 return 1;
6786 }
6787 }
6788
6789 /* Checking the statement list inside a CONDITIONAL statement in Pass3 */
6790 static
6791 int Pass3CheckCOND(struct Instance *inst, struct Statement *statement)
6792 {
6793 struct StatementList *sl;
6794 struct Statement *stat;
6795 unsigned long c,len;
6796 struct gl_list_t *list;
6797 sl = CondStatList(statement);
6798 assert(inst&&sl);
6799 list = GetList(sl);
6800 len = gl_length(list);
6801 for(c=1;c<=len;c++){
6802 stat = (struct Statement *)gl_fetch(list,c);
6803 if (!Pass3CheckCondStatements(inst,stat)) return 0;
6804 }
6805 return 1;
6806 }
6807
6808
6809 /* Only relations and FOR loops of relations are allowed inside a
6810 * conditional statement in Pass2. This function ask for recursively
6811 * checking these statements */
6812 static
6813 int Pass2CheckCondStatements(struct Instance *inst,
6814 struct Statement *statement)
6815 {
6816 assert(inst&&statement);
6817 switch(StatementType(statement)){
6818 case REL:
6819 return CheckREL(inst,statement);
6820 case FOR:
6821 return Pass2RealCheckFOR(inst,statement);
6822 case LOGREL:
6823 case ALIASES:
6824 case ARR:
6825 case ISA:
6826 case IRT:
6827 case ATS:
6828 case AA:
6829 case CALL:
6830 case EXT:
6831 case ASGN:
6832 case CASGN:
6833 case COND:
6834 case WHEN:
6835 case FNAME:
6836 case SELECT:
6837 WSEM(ASCERR,statement,
6838 "Statement not allowed inside a CONDITIONAL statement\n");
6839 return 0;
6840 default:
6841 FPRINTF(ASCERR,"Inappropriate statement type in CheckStatement\n");
6842 return 1;
6843 }
6844 }
6845
6846 /* Checking the statement list inside a CONDITIONAL statement in Pass2 */
6847 static
6848 int Pass2CheckCOND(struct Instance *inst, struct Statement *statement)
6849 {
6850 struct StatementList *sl;
6851 struct Statement *stat;
6852 unsigned long c,len;
6853 struct gl_list_t *list;
6854 sl = CondStatList(statement);
6855 assert(inst&&sl);
6856 list = GetList(sl);
6857 len = gl_length(list);
6858 for(c=1;c<=len;c++){
6859 stat = (struct Statement *)gl_fetch(list,c);
6860 if (!Pass2CheckCondStatements(inst,stat)) return 0;
6861 }
6862 return 1;
6863 }
6864
6865
6866 /***********************************************************************/
6867
6868 /*
6869 * Checking that not other instance has been created with the same
6870 * name of the current WHEN. If it has, it has to be a WHEN or a
6871 * DUMMY. return -1 for DUMMY. 1 for WHEN. 0 if the checking fails.
6872 */
6873 static
6874 int CheckWhenName(struct Instance *work, struct Name *name)
6875 {
6876 struct gl_list_t *instances;
6877 struct Instance *inst;
6878 enum find_errors ferr;
6879 instances = FindInstances(work,name,&ferr);
6880 if (instances==NULL){
6881 return 1;
6882 }
6883 else{
6884 if (gl_length(instances)==1){
6885 inst = (struct Instance *)gl_fetch(instances,1);
6886 assert( (InstanceKind(inst)==WHEN_INST) ||
6887 (InstanceKind(inst)==DUMMY_INST) );
6888 gl_destroy(instances);
6889 if (InstanceKind(inst)==DUMMY_INST) {
6890 return -1;
6891 }
6892 return 1;
6893 }
6894 else {
6895 gl_destroy(instances);
6896 return 0;
6897 }
6898 }
6899 }
6900
6901 /*
6902 * p1 and p2 are pointers to arrays of integers. Here we are checking
6903 * that the type (integer, boolean, symbol) of each variable in the
6904 * variable list of a WHEN (or a SELECT) is the same as the type of
6905 * each value in the list of values a CASE
6906 */
6907 static
6908 int CompListInArray(unsigned long numvar, int *p1, int *p2)
6909 {
6910 unsigned long c;
6911 for (c=1;c<=numvar;c++) {
6912 if (*p2 != 3) { /* To account for ANY */
6913 if (*p1 != *p2) return 0;
6914 }
6915 if (c < numvar) {
6916 p1++;
6917 p2++;
6918 }
6919 }
6920 return 1;
6921 }
6922
6923
6924 /*
6925 * Checking that the values of the set of values of each CASE of a
6926 * WHEN statement are appropriate. This is, they
6927 * are symbol, integer or boolean. The first part of the
6928 * function was written for the case of WHEN statement
6929 * inside a FOR loop. This function also sorts
6930 * the kinds of values in the set by assigning a value
6931 * to the integer *p2
6932 */
6933 static
6934 int CheckWhenSetNode(struct Instance *ref, CONST struct Expr *expr,
6935 int *p2)
6936 {
6937 symchar *str;
6938 struct for_var_t *fvp;
6939 struct Set *set;
6940 CONST struct Expr *es;
6941 switch (ExprType(expr)) {
6942 case e_boolean:
6943 if (ExprBValue(expr)==2) {
6944 *p2 = 3; /* ANY */
6945 } else {
6946 *p2=1;
6947 }
6948 return 1;
6949 case e_int:
6950 *p2=0;
6951 return 1;
6952 case e_symbol:
6953 *p2=2;
6954 return 1;
6955 case e_var:
6956 if ((GetEvaluationForTable() != NULL) &&
6957 (NULL != (str = SimpleNameIdPtr(ExprName(expr)))) &&
6958 (NULL != (fvp=FindForVar(GetEvaluationForTable(),str)))) {
6959 if (GetForKind(fvp)==f_integer){
6960 *p2=0;
6961 return 1;
6962 }
6963 else {
6964 if (GetForKind(fvp)==f_symbol){
6965 *p2=2;
6966 return 1;
6967 }
6968 else {
6969 FPRINTF(ASCERR,"\n");
6970 FPRINTF(ASCERR,"Innapropriate index in the list of %s\n",
6971 "values of a CASE of a WHEN statement");
6972 WriteName(ASCERR,ExprName(expr));
6973 FPRINTF(ASCERR,"Only symbols or integers are allowed\n");
6974 FPRINTF(ASCERR,"\n");
6975 return 0;
6976 }
6977 }
6978 }
6979 else {
6980 FPRINTF(ASCERR,"\n");
6981 FPRINTF(ASCERR,"Innapropriate value type in the list of %s\n",
6982 "values of a CASE of a WHEN statement");
6983 FPRINTF(ASCERR,"Index has not been created\n");
6984 WriteName(ASCERR,ExprName(expr));
6985 FPRINTF(ASCERR,"\n");
6986 return 0;
6987 }
6988 case e_set:
6989 set = expr->v.s;
6990 if (set->range) {
6991 return 0;
6992 }
6993 es = GetSingleExpr(set);
6994 return CheckWhenSetNode(ref,es,p2);
6995 default:
6996 FPRINTF(ASCERR,"\n");
6997 FPRINTF(ASCERR,"Innapropriate value type in the list of %s\n",
6998 "values of a CASE of a WHEN statement");
6999 FPRINTF(ASCERR,"Only symbols or integers and booleans are allowed\n");
7000 FPRINTF(ASCERR,"\n");
7001 return 0;
7002 }
7003 }
7004
7005
7006 /*
7007 * Checking that the variables of the list of variables of a
7008 * WHEN statement are appropriate. This is, they
7009 * are boolean, integer or symbol instances. The first part of the
7010 * function was written for the case of WHEN statement
7011 * inside a FOR loop. This function also sorts
7012 * the kinds of variables in the list by assigning a value
7013 * to the integer *p1
7014 */
7015 static
7016 int CheckWhenVariableNode(struct Instance *ref,
7017 CONST struct Name *name,
7018 int *p1)
7019 {
7020 struct gl_list_t *instances;
7021 struct Instance *inst;
7022 enum find_errors err;
7023 symchar *str;
7024 struct for_var_t *fvp;
7025 str = SimpleNameIdPtr(name);
7026 if( str!=NULL &&
7027 GetEvaluationForTable()!=NULL &&
7028 (fvp=FindForVar(GetEvaluationForTable(),str))!=NULL) {
7029
7030 switch (GetForKind(fvp)) {
7031 case f_integer:
7032 *p1=0;
7033 return 1;
7034 case f_symbol:
7035 *p1=2;
7036 return 1;
7037 default:
7038 FPRINTF(ASCERR,"\n");
7039 FPRINTF(ASCERR,"Innapropriate index in the list of %s\n",
7040 "variables of a WHEN statement");
7041 FPRINTF(ASCERR,"only symbol or integer allowed\n");
7042 FPRINTF(ASCERR,"\n");
7043 return 0;
7044 }
7045
7046 }
7047 instances = FindInstances(ref,name,&err);
7048 if (instances == NULL){
7049 switch(err){
7050 case unmade_instance:
7051 case undefined_instance:
7052 FPRINTF(ASCERR,"\n");
7053 FPRINTF(ASCERR,"Unmade instance in the list of %s\n",
7054 "variables of a WHEN statement");
7055 WriteName(ASCERR,name);
7056 FPRINTF(ASCERR,"\n");
7057 return 0;
7058 default:
7059 FPRINTF(ASCERR,"\n");
7060 FPRINTF(ASCERR,"Unmade instance in the list of %s\n",
7061 "variables of a WHEN statement");
7062 WriteName(ASCERR,name);
7063 FPRINTF(ASCERR,"\n");
7064 return 0;
7065 }
7066 } else {
7067 if (gl_length(instances)==1) {
7068 inst = (struct Instance *)gl_fetch(instances,1);
7069 gl_destroy(instances);
7070 switch(InstanceKind(inst)){
7071 case BOOLEAN_ATOM_INST:
7072 *p1=1;
7073 return 1;
7074 case BOOLEAN_CONSTANT_INST:
7075 if (AtomAssigned(inst)) {
7076 *p1=1;
7077 return 1;
7078 } else {
7079 FPRINTF(ASCERR,"\n");
7080 FPRINTF(ASCERR,"Undefined constant in the list of %s\n",
7081 "variables of a WHEN statement");
7082 WriteName(ASCERR,name);
7083 FPRINTF(ASCERR,"\n");
7084 return 0;
7085 }
7086 case INTEGER_ATOM_INST:
7087 *p1=0;
7088 return 1;
7089 case INTEGER_CONSTANT_INST:
7090 if (AtomAssigned(inst)) {
7091 *p1=0;
7092 return 1;
7093 } else {
7094 FPRINTF(ASCERR,"\n");
7095 FPRINTF(ASCERR,"Undefined constant in the list of %s\n",
7096 "variables of a WHEN statement");
7097 WriteName(ASCERR,name);
7098 FPRINTF(ASCERR,"\n");
7099 return 0;
7100 }
7101 case SYMBOL_ATOM_INST:
7102 *p1=2;
7103 return 1;
7104 case SYMBOL_CONSTANT_INST:
7105 if (AtomAssigned(inst)) {
7106 *p1=2;
7107 return 1;
7108 } else {
7109 FPRINTF(ASCERR,"\n");
7110 FPRINTF(ASCERR,"Undefined constant in the list of %s\n",
7111 "variables of a WHEN statement");
7112 WriteName(ASCERR,name);
7113 FPRINTF(ASCERR,"\n");
7114 return 0;
7115 }
7116 default:
7117 FPRINTF(ASCERR,"\n");
7118 FPRINTF(ASCERR,"Inappropriate instance in the list of %s\n",
7119 "variables of a WHEN statement");
7120 FPRINTF(ASCERR,"Only boolean, integer and symbols are allowed\n");
7121 WriteName(ASCERR,name);
7122 FPRINTF(ASCERR,"\n");
7123 return 0;
7124 }
7125 } else {
7126 gl_destroy(instances);
7127 FPRINTF(ASCERR,"\n");
7128 FPRINTF(ASCERR,"Inappropriate instance in the list of %s\n",
7129 "variables of a WHEN statement");
7130 FPRINTF(ASCERR,"Multiple instances of\n");
7131 WriteName(ASCERR,name);
7132 FPRINTF(ASCERR,"\n");
7133 return 0;
7134 }
7135 }
7136 }
7137
7138
7139 /*
7140 * Inside a WHEN, only FNAMEs (name of models, relations or array of)
7141 * and nested WHENs ( and FOR loops of them) are allowed. This function
7142 * asks for the checking of these statements.
7143 */
7144 static
7145 int CheckWhenStatements(struct Instance *inst, struct Statement *statement)
7146 {
7147
7148 assert(inst&&statement);
7149 switch(StatementType(statement)){
7150 case WHEN:
7151 return CheckWHEN(inst,statement);
7152 case FNAME:
7153 return CheckFNAME(inst,statement);
7154 case FOR:
7155 return Pass4RealCheckFOR(inst,statement);
7156 case ALIASES:
7157 case ARR:
7158 case ISA:
7159 case IRT:
7160 case ATS:
7161 case AA:
7162 case REL:
7163 case LOGREL:
7164 case EXT:
7165 case CALL:
7166 case ASGN:
7167 case SELECT:
7168 WSEM(ASCERR,statement,
7169 "Statement not allowed inside a WHEN statement\n");
7170 return 0;
7171 default:
7172 FPRINTF(ASCERR,"Inappropriate statement type in CheckStatement\n");
7173 return 1;
7174 }
7175 }
7176
7177 /*
7178 * Call CheckWhenSetNode for each value in the set of values included
7179 * in the CASE of a WHEN statement
7180 */
7181 static
7182 int CheckWhenSetList(struct Instance *inst, struct Set *s, int *p2)
7183 {
7184 struct Set *set;
7185 CONST struct Expr *expr;
7186 set = s;
7187 while (set!=NULL) {
7188 expr = GetSingleExpr(set);
7189 if (!CheckWhenSetNode(inst,expr,p2)) return 0;
7190 set = NextSet(set);
7191 p2++;
7192 }
7193 return 1;
7194 }
7195
7196 /*
7197 * Call CheckWhenVariableNode for each variable vl in the variable
7198 * list of a WHEN statement
7199 */
7200 static
7201 int CheckWhenVariableList(struct Instance *inst, struct VariableList *vlist,
7202 int *p1)
7203 {
7204 CONST struct Name *name;
7205 CONST struct VariableList *vl;
7206 vl = vlist;
7207 while (vl!=NULL) {
7208 name = NamePointer(vl);
7209 if (!CheckWhenVariableNode(inst,name,p1)) return 0;
7210 vl = NextVariableNode(vl);
7211 p1++;
7212 }
7213 return 1;
7214 }
7215
7216 /*
7217 * Checking the list statements of statements inside each CASE of the
7218 * WHEN statement by calling CheckWhenStatements
7219 */
7220 static
7221 int CheckWhenStatementList(struct Instance *inst, struct StatementList *sl)
7222 {
7223 struct Statement *statement;
7224 unsigned long c,len;
7225 struct gl_list_t *list;
7226 assert(inst&&sl);
7227 list = GetList(sl);
7228 len = gl_length(list);
7229 for(c=1;c<=len;c++){
7230 statement = (struct Statement *)gl_fetch(list,c);
7231 if (!CheckWhenStatements(inst,statement)) return 0;
7232 }
7233 return 1;
7234 }
7235
7236
7237 /* Checking of the Select statements. It checks that:
7238 * 1) The name of the WHEN. If it was already created. It has to be
7239 * a WHEN or a DUMMY. If a Dummy (case -1 of CheckWhenName),
7240 * do not check the structure of the WHEN statement, return 1.
7241 * 2) The number of conditional variables is equal to the number
7242 * of values in each of the CASEs.
7243 * 3) That the conditional variables exist, and are boolean
7244 * integer or symbol.
7245 * 4) The number and the type of conditional variables is the same
7246 * as the number of values in each of the CASEs.
7247 * 5) Only one OTHERWISE case is present.
7248 * 6) The statements inside a WHEN are only a FNAME or a nested WHEN,
7249 * and ask for the chcking of these interior statements.
7250 */
7251 static
7252 int CheckWHEN(struct Instance *inst, struct Statement *statement)
7253 {
7254 struct Name *wname;
7255 struct VariableList *vlist;
7256 struct WhenList *w1;
7257 struct Set *s;
7258 struct StatementList *sl;
7259 unsigned long numother;
7260 unsigned long numvar;
7261 unsigned long numset;
7262 int vl[MAX_VAR_IN_LIST],*p1;
7263 int casel[MAX_VAR_IN_LIST],*p2;
7264 wname = WhenStatName(statement);
7265 if (wname!=NULL) {
7266 if (!CheckWhenName(inst,wname)) {
7267 FPRINTF(ASCERR,"\n");
7268 FPRINTF(ASCERR,"Name of a WHEN already exits in ");
7269 WriteInstanceName(ASCERR,inst,NULL);
7270 FPRINTF(ASCERR,"\n");
7271 WSEM(ASCERR,statement,"The following statement will not be executed: \n");
7272 FPRINTF(ASCERR,"\n");
7273 return 0;
7274 }
7275 if ( CheckWhenName(inst,wname) == -1) return 1;
7276 }
7277 vlist = WhenStatVL(statement);
7278 numvar = VariableListLength(vlist);
7279 assert(numvar<=MAX_VAR_IN_LIST);
7280 p1 = &vl[0];
7281 p2 = &casel[0];
7282 numother=0;
7283 if (!CheckWhenVariableList(inst,vlist,p1)) {
7284 FPRINTF(ASCERR,"In ");
7285 WriteInstanceName(ASCERR,inst,NULL);
7286 WSEM(ASCERR,statement," the following statement will not be executed:\n");
7287 FPRINTF(ASCERR,"\n");
7288 return 0;
7289 }
7290 w1 = WhenStatCases(statement);
7291 while (w1!=NULL){
7292 s = WhenSetList(w1);
7293 if (s!=NULL) {
7294 numset = SetLength(s);
7295 if (numvar != numset) {
7296 FPRINTF(ASCERR,"\n");
7297 FPRINTF(ASCERR,"Number of variables different from %s\n",
7298 "number of values in a CASE");
7299 FPRINTF(ASCERR,"In ");
7300 WriteInstanceName(ASCERR,inst,NULL);
7301 WSEM(ASCERR,statement,
7302 " the following statement will not be executed: \n");
7303 FPRINTF(ASCERR,"\n");
7304 return 0;
7305 }
7306 if (!CheckWhenSetList(inst,s,p2)) {
7307 FPRINTF(ASCERR,"\n");
7308 FPRINTF(ASCERR,"In ");
7309 WriteInstanceName(ASCERR,inst,NULL);
7310 WSEM(ASCERR,statement,
7311 " the following statement will not be executed: \n");
7312 FPRINTF(ASCERR,"\n");
7313 return 0;
7314 }
7315 p1 = &vl[0];
7316 p2 = &casel[0];
7317 if (!CompListInArray(numvar,p1,p2)) {
7318 FPRINTF(ASCERR,"\n");
7319 FPRINTF(ASCERR,"Type of variables different from type %s\n",
7320 "of values in a CASE");
7321 FPRINTF(ASCERR,"In ");
7322 WriteInstanceName(ASCERR,inst,NULL);
7323 WSEM(ASCERR,statement,
7324 " the following statement will not be executed: \n");
7325 FPRINTF(ASCERR,"\n");
7326 return 0;
7327 }
7328 }
7329 else {
7330 numother++;
7331 if (numother>1) {
7332 FPRINTF(ASCERR,"\n");
7333 FPRINTF(ASCERR,"More than one default case in a WHEN\n");
7334 FPRINTF(ASCERR,"In ");
7335 WriteInstanceName(ASCERR,inst,NULL);
7336 WSEM(ASCERR,statement,
7337 " the following statement will not be executed: \n");
7338 FPRINTF(ASCERR,"\n");
7339 return 0;
7340 }
7341 }
7342 sl = WhenStatementList(w1);
7343 if (!CheckWhenStatementList(inst,sl)) {
7344 FPRINTF(ASCERR,"\n");
7345 FPRINTF(ASCERR,"In ");
7346 WriteInstanceName(ASCERR,inst,NULL);
7347 WSEM(ASCERR,statement,
7348 " the following statement will not be executed: \n");
7349 FPRINTF(ASCERR,"\n");
7350 return 0;
7351 }
7352 w1 = NextWhenCase(w1); }
7353 return 1;
7354 }
7355
7356
7357 /***********************************************************************/
7358 /* Check SELECT Functions */
7359
7360 /*****************************
7361 * Code curently not in use. It would be used in case that we want to do
7362 * the checking of all of the statement list in all of the cases of a
7363 * SELECT simultaneously, previous to execution.
7364 * Actually, the code is in disrepair, particularly around what is
7365 * allowed in SELECT. We surely need to create a CheckSelectStatement
7366 * function specific for each pass of instantiation.
7367 */
7368 #ifdef THIS_IS_AN_UNUSED_FUNCTION
7369 static
7370 int CheckSelectStatements(struct Instance *inst, struct Statement *statement)
7371 {
7372 assert(inst&&statement);
7373 switch(StatementType(statement)){
7374 case ALIASES:
7375 case ISA:
7376 case IRT:
7377 case ATS:
7378 case AA:
7379 case ARR:
7380 return 1;
7381 case FOR:
7382 return Pass1RealCheckFOR(inst,statement);
7383 case ASGN:
7384 return CheckASGN(inst,statement);
7385 case CASGN:
7386 return CheckCASGN(inst,statement);
7387 case SELECT:
7388 return CheckSELECT(inst,statement);
7389 case REL: /* broken */
7390 case LOGREL: /* broken */
7391 case EXT: /* broken */
7392 case CALL: /* broken */
7393 case WHEN: /* broken */
7394 case FNAME:
7395 if (g_iteration>=MAXNUMBER) { /* see WriteUnexecutedMessage */
7396 WSEM(ASCERR,statement,
7397 "Statement not allowed inside a SELECT statement\n"); }
7398 /** AND WHY NOT? fix me. **/
7399 return 0;
7400 default:
7401 FPRINTF(ASCERR,"Inappropriate statement type in CheckStatement\n");
7402 return 1;
7403 }
7404 }
7405 #endif /* THIS_IS_AN_UNUSED_FUNCTION */
7406
7407
7408 #ifdef THIS_IS_AN_UNUSED_FUNCTION
7409 /* Currently not in use */
7410 static
7411 int CheckSelectStatementList(struct Instance *inst, struct StatementList *sl)
7412 {
7413 struct Statement *statement;
7414 unsigned long c,len;
7415 struct gl_list_t *list;
7416 assert(inst&&sl);
7417 list = GetList(sl);
7418 len = gl_length(list);
7419 for(c=1;c<=len;c++){
7420 statement = (struct Statement *)gl_fetch(list,c);
7421 if (!CheckSelectStatements(inst,statement)) return 0;
7422 }
7423 return 1;
7424 }
7425 #endif /* THIS_IS_AN_UNUSED_FUNCTION */
7426
7427
7428 /*
7429 * Current checking of the Select statement starts here.
7430 *
7431 * Checking that the values of the set of values of each CASE of a
7432 * SELECT statement are appropriate. This is, they
7433 * are symbol, integer or boolean. The first part of the
7434 * function was written for the case of SELECT statement
7435 * inside a FOR loop. Therefore, it is going to be there,
7436 * but not used at the moment.This function also sorts
7437 * the kinds of values in the set by assigning a value
7438 * to the integer *p2
7439 */
7440 static
7441 int CheckSelectSetNode(struct Instance *ref, CONST struct Expr *expr,
7442 int *p2 )
7443 {
7444 symchar *str;
7445 struct for_var_t *fvp;
7446 struct Set *set;
7447 CONST struct Expr *es;
7448 switch (ExprType(expr)) {
7449 case e_boolean:
7450 if (ExprBValue(expr)==2) {
7451 *p2 = 3; /* ANY */
7452 } else {
7453 *p2=1;
7454 }
7455 return 1;
7456 case e_int:
7457 *p2=0;
7458 return 1;
7459 case e_symbol:
7460 *p2=2;
7461 return 1;
7462 case e_var:
7463 if ((NULL != GetEvaluationForTable()) &&
7464 (NULL != (str = SimpleNameIdPtr(ExprName(expr)))) &&
7465 (NULL != (fvp=FindForVar(GetEvaluationForTable(),str)))) {
7466 if (GetForKind(fvp)==f_integer){
7467 *p2=0;
7468 return 1;
7469 }
7470 else {
7471 if (GetForKind(fvp)==f_symbol){
7472 *p2=2;
7473 return 1;
7474 }
7475 else return 0;
7476 }
7477 }
7478 else return 0;
7479 case e_set:
7480 set = expr->v.s;
7481 if (set->range) {
7482 return 0;
7483 }
7484 es = GetSingleExpr(set);
7485 return CheckSelectSetNode(ref,es,p2);
7486 default:
7487 return 0;
7488 }
7489 }
7490
7491 /*
7492 * Checking that the variables of the list of variables of a
7493 * SELECT statement are appropriate. This is, they
7494 * are constant and are assigned. The first part of the
7495 * function was written for the case of SELECT statement
7496 * inside a FOR loop. Therefore, it is going to be there,
7497 * but not used at the moment.This function also sorts
7498 * the kinds of variables in the list by assigning a value
7499 * to the integer *p1
7500 */
7501 static
7502 int CheckSelectVariableNode(struct Instance *ref,
7503 CONST struct Name *name,
7504 int *p1)
7505 {
7506 struct gl_list_t *instances;
7507 struct Instance *inst;
7508 enum find_errors err;
7509 symchar *str;
7510 struct for_var_t *fvp;
7511
7512 str = SimpleNameIdPtr(name);
7513 if( str!=NULL &&
7514 GetEvaluationForTable() != NULL &&
7515 (fvp=FindForVar(GetEvaluationForTable(),str))!=NULL) {
7516
7517 switch (GetForKind(fvp)) {
7518 case f_integer:
7519 *p1=0;
7520 return 1;
7521 case f_symbol:
7522 *p1=2;
7523 return 1;
7524 default:
7525 return 0;
7526 }
7527 }
7528
7529 instances = FindInstances(ref,name,&err);
7530 if (instances == NULL){
7531 switch(err){
7532 case unmade_instance:
7533 case undefined_instance: return 0;
7534 default:
7535 return 0;
7536 }
7537 }
7538 else{
7539 if (gl_length(instances)==1) {
7540 inst = (struct Instance *)gl_fetch(instances,1);
7541 gl_destroy(instances);
7542 switch(InstanceKind(inst)){
7543 case BOOLEAN_CONSTANT_INST:
7544 if (AtomAssigned(inst)) {
7545 *p1 = 1;
7546 return 1;
7547 }
7548 else {
7549 return 0;
7550 }
7551 case INTEGER_CONSTANT_INST:
7552 if (AtomAssigned(inst)) {
7553 *p1 = 0;
7554 return 1;
7555 }
7556 else {
7557 return 0;
7558 }
7559 case SYMBOL_CONSTANT_INST:
7560 if (AtomAssigned(inst)) {
7561 *p1 = 2;
7562 return 1;
7563 }
7564 else {
7565 return 0;
7566 }
7567 default:
7568 return 0;
7569 }
7570 }
7571 else {
7572 gl_destroy(instances);
7573 return 0;
7574 }
7575 }
7576 }
7577
7578 /*
7579 * Call CheckSelectSetNode for each set member of the set of
7580 * values of each CASE of a SELECT statement
7581 */
7582 static
7583 int CheckSelectSetList(struct Instance *inst, struct Set *s, int *p2 )
7584 {
7585 struct Set *set;
7586 CONST struct Expr *expr;
7587 set = s;
7588 while (set!=NULL) {
7589 expr = GetSingleExpr(set);
7590 if (!CheckSelectSetNode(inst,expr,p2)) return 0;
7591 set = NextSet(set);
7592 p2++;
7593 }
7594 return 1;
7595 }
7596
7597 /*
7598 * Call CheckSelectVariableNode for each variable vl in the variable
7599 *list of a SELECT statement
7600 */
7601 static
7602 int CheckSelectVariableList(struct Instance *inst, struct VariableList *vlist,
7603 int *p1)
7604 {
7605 CONST struct Name *name;
7606 CONST struct VariableList *vl;
7607 vl = vlist;
7608 while (vl!=NULL) {
7609 name = NamePointer(vl);
7610 if (!CheckSelectVariableNode(inst,name,p1)) return 0;
7611 vl = NextVariableNode(vl);
7612 p1++;
7613 }
7614 return 1;
7615 }
7616
7617
7618 /*
7619 * The conditions for checkselect is that
7620 * 1) The number of selection variables is equal to the number
7621 * of values in each of the CASEs.
7622 * 2) That the selection variables exist, are constant and
7623 * are assigned.
7624 * 3) Only one OTHERWISE case is present.
7625 */
7626 static
7627 int CheckSELECT(struct Instance *inst, struct Statement *statement)
7628 {
7629 struct VariableList *vlist;
7630 struct SelectList *sel1;
7631 struct Set *set;
7632 unsigned long numother;
7633 unsigned long numsvar;
7634 unsigned long numsset;
7635 int vl[MAX_VAR_IN_LIST], *p1;
7636 int casel[MAX_VAR_IN_LIST], *p2;
7637
7638 vlist = SelectStatVL(statement);
7639 numsvar = VariableListLength(vlist);
7640 assert(numsvar<=MAX_VAR_IN_LIST);
7641 p1 = &vl[0];
7642 p2 = &casel[0];
7643 numother = 0;
7644
7645 if (!CheckSelectVariableList(inst,vlist,p1)) return 0;
7646 sel1 = SelectStatCases(statement);
7647 while (sel1!=NULL){
7648 set = SelectSetList(sel1);
7649 if (set!=NULL) {
7650 numsset = SetLength(set);
7651 if (numsvar != numsset) return 0;
7652 if (!CheckSelectSetList(inst,set,p2)) return 0;
7653 p1 = &vl[0];
7654 p2 = &casel[0];
7655 if (!CompListInArray(numsvar,p1,p2)) return 0;
7656 }
7657 else {
7658 numother++;
7659 if (numother>1) return 0;
7660 }
7661 sel1 = NextSelectCase(sel1);
7662 }
7663 return 1;
7664 }
7665
7666
7667 /***********************************************************************/
7668
7669 /* BUG!: CheckStatement and New flavors of same ignore the
7670 type EXT. We never use external relations inside a loop?!
7671 well, ok, maybe they are always hidden as models */
7672
7673 static
7674 int Pass4CheckStatement(struct Instance *inst, struct Statement *stat)
7675 {
7676 assert(stat&&inst);
7677 switch(StatementType(stat)){
7678 case WHEN:
7679 return CheckWHEN(inst,stat);
7680 case FNAME:
7681 return CheckFNAME(inst,stat);
7682 case FOR:
7683 return Pass4CheckFOR(inst,stat);
7684 case COND:
7685 case SELECT:
7686 case REL:
7687 case LOGREL:
7688 case ISA:
7689 case ARR:
7690 case ALIASES:
7691 case IRT:
7692 case ATS:
7693 case AA:
7694 case CASGN:
7695 case ASGN:
7696 default:
7697 return 1; /* ignore all in phase 4.*/
7698 }
7699 }
7700
7701
7702 static
7703 int Pass3CheckStatement(struct Instance *inst, struct Statement *stat)
7704 {
7705 assert(stat&&inst);
7706 switch(StatementType(stat)){
7707 case FOR:
7708 return Pass3RealCheckFOR(inst,stat);
7709 case LOGREL:
7710 return CheckLOGREL(inst,stat);
7711 case COND:
7712 return Pass3CheckCOND(inst,stat);
7713 case REL:
7714 case ALIASES:
7715 case ARR:
7716 case ISA:
7717 case IRT:
7718 case ATS:
7719 case AA:
7720 case CASGN:
7721 case ASGN:
7722 case WHEN:
7723 case SELECT:
7724 case FNAME:
7725 default:
7726 return 1; /* ignore all in phase 3. nondeclarative flagged in pass1 */
7727 }
7728 }
7729
7730
7731 static
7732 int Pass2CheckStatement(struct Instance *inst, struct Statement *stat)
7733 {
7734 assert(stat&&inst);
7735 switch(StatementType(stat)){
7736 case FOR:
7737 return Pass2RealCheckFOR(inst,stat);
7738 case REL:
7739 return CheckREL(inst,stat);
7740 case COND:
7741 return Pass2CheckCOND(inst,stat);
7742 case LOGREL:
7743 case ALIASES:
7744 case ARR:
7745 case ISA:
7746 case IRT:
7747 case ATS:
7748 case AA:
7749 case CASGN:
7750 case ASGN:
7751 case WHEN:
7752 case SELECT:
7753 case FNAME:
7754 default:
7755 return 1; /* ignore all in phase 2. nondeclarative flagged in pass1 */
7756 }
7757 }
7758
7759 /**
7760 * checking statementlist, as in a FOR loop check.
7761 * @TODO FIXME BUG!: CheckStatement and New flavors of same ignore the
7762 * type EXT. We never use external relations inside a loop?!
7763 */
7764 static
7765 int Pass1CheckStatement(struct Instance *inst, struct Statement *stat)
7766 {
7767 assert(stat&&inst);
7768 switch(StatementType(stat)){
7769 case ALIASES:
7770 return CheckALIASES(inst,stat);
7771 case ARR:
7772 return CheckARR(inst,stat);
7773 case ISA:
7774 if ( CheckISA(inst,stat) == 0 ) {
7775 return 0;
7776 }
7777 return MakeParameterInst(inst,stat,NULL,NOKEEPARGINST); /*1*/
7778 case IRT:
7779 if ( CheckIRT(inst,stat) == 0 ) {
7780 return 0;
7781 }
7782 return MakeParameterInst(inst,stat,NULL,NOKEEPARGINST); /*1b*/
7783 case ATS:
7784 return CheckATS(inst,stat);
7785 case AA:
7786 return CheckAA(inst,stat);
7787 case FOR:
7788 return Pass1CheckFOR(inst,stat);
7789 case REL:
7790 return 1; /* ignore'm in phase 1 */
7791 case COND:
7792 return 1; /* ignore'm in phase 1 */
7793 case LOGREL:
7794 return 1; /* ignore'm in phase 1 */
7795 case CASGN:
7796 return CheckCASGN(inst,stat);
7797 case ASGN:
7798 return 1; /* ignore'm in phase 1 */
7799 case WHEN:
7800 return 1; /* ignore'm in phase 1 */
7801 case SELECT:
7802 return CheckSELECT(inst,stat);
7803 case FNAME:
7804 FPRINTF(ASCERR,"FNAME are only allowed inside a WHEN Statement\n");
7805 return 0;
7806 default:
7807 FPRINTF(ASCERR,"Inappropriate statement type in CheckStatement.\n");
7808 return 1;
7809 }
7810 }
7811
7812 static
7813 int Pass4CheckStatementList(struct Instance *inst, struct StatementList *sl)
7814 {
7815 unsigned long c,len;
7816 struct gl_list_t *list;
7817 struct Statement *stat;
7818 assert(inst&&sl);
7819 list = GetList(sl);
7820 len = gl_length(list);
7821 for(c=1;c<=len;c++){
7822 stat = (struct Statement *)gl_fetch(list,c);
7823 if (!Pass4CheckStatement(inst,stat)) return 0;
7824 }
7825 return 1;
7826 }
7827
7828 static
7829 int Pass3CheckStatementList(struct Instance *inst, struct StatementList *sl)
7830 {
7831 unsigned long c,len;
7832 struct gl_list_t *list;
7833 struct Statement *stat;
7834 assert(inst&&sl);
7835 list = GetList(sl);
7836 len = gl_length(list);
7837 for(c=1;c<=len;c++){
7838 stat = (struct Statement *)gl_fetch(list,c);
7839 if (!Pass3CheckStatement(inst,stat)) return 0;
7840 }
7841 return 1;
7842 }
7843
7844 static
7845 int Pass2CheckStatementList(struct Instance *inst, struct StatementList *sl)
7846 {
7847 unsigned long c,len;
7848 struct gl_list_t *list;
7849 struct Statement *stat;
7850 assert(inst&&sl);
7851 list = GetList(sl);
7852 len = gl_length(list);
7853 for(c=1;c<=len;c++){
7854 stat = (struct Statement *)gl_fetch(list,c);
7855 if (Pass2CheckStatement(inst,stat)==0) return 0;
7856 }
7857 return 1;
7858 }
7859
7860 static
7861 int Pass1CheckStatementList(struct Instance *inst, struct StatementList *sl)
7862 {
7863 unsigned long c,len;
7864 struct gl_list_t *list;
7865 struct Statement *stat;
7866 assert(inst&&sl);
7867 list = GetList(sl);
7868 len = gl_length(list);
7869 for(c=1;c<=len;c++){
7870 stat = (struct Statement *)gl_fetch(list,c);
7871 if (Pass1CheckStatement(inst,stat)==0) return 0;
7872 }
7873 return 1;
7874 }
7875
7876
7877 /*************************************************************************\
7878 FNAME Statement Processing
7879 \*************************************************************************/
7880
7881 /*
7882 * The FNAME statement is just used to stand for the model relations or
7883 * arrays inside the CASES of a WHEN statement. Actually, this
7884 * statement does not need to be executed. It is required only
7885 * for checking and for avoiding conflicts in the semantics.
7886 */
7887 static
7888 int ExecuteFNAME(struct Instance *inst, struct Statement *statement)
7889 {
7890 (void)inst; /* stop gcc whine about unused parameter */
7891 (void)statement; /* stop gcc whine about unused parameter */
7892 return 1;
7893 }
7894
7895
7896
7897 /******************************************************************\
7898 CONDITIONAL Statement Processing
7899 \******************************************************************/
7900
7901 /* The logical relations inside a conditional statement do not have
7902 * to be satisified. They are going to be used to check conditions in
7903 * the solution of other logical relations. So, we need something to
7904 * distinguish a conditional logrelation from a non-conditional
7905 * logrelation. The next three functions "Mark" those log relations
7906 * inside a CONDITIONAL statement as Conditional logrelations.
7907 * Right now we not only set a bit indicating
7908 * that the logrelation is conditional, but also set a flag equal to 1.
7909 * This is done in MarkLOGREL above. The flag could be eliminated, but
7910 * we need to fix some places in which it is used, and to use the
7911 * bit instead.
7912 */
7913 static
7914 void Pass3MarkCondLogRels(struct Instance *inst, struct Statement *statement)
7915 {
7916 switch(StatementType(statement)){
7917 case LOGREL:
7918 MarkLOGREL(inst,statement);
7919 break;
7920 case FOR:
7921 if ( ForContainsLogRelations(statement) ) {
7922 Pass3FORMarkCond(inst,statement);
7923 }
7924 break;
7925 case REL:
7926 break;
7927 default:
7928 WSEM(ASCERR,statement,
7929 "Inappropriate statement type in CONDITIONAL Statement");
7930 }
7931 }
7932
7933 static
7934 void Pass3MarkCondLogRelStatList(struct Instance *inst,
7935 struct StatementList *sl)
7936 {
7937 struct Statement *stat;
7938 unsigned long c,len;
7939 struct gl_list_t *list;
7940 list = GetList(sl);
7941 len = gl_length(list);
7942 for(c=1;c<=len;c++){
7943 stat = (struct Statement *)gl_fetch(list,c);
7944 switch(StatementType(stat)){
7945 case LOGREL:
7946 MarkLOGREL(inst,stat);
7947 break;
7948 case FOR:
7949 if ( ForContainsLogRelations(stat) ) {
7950 Pass3FORMarkCondLogRels(inst,stat);
7951 }
7952 break;
7953 case REL:
7954 break;
7955 default:
7956 WSEM(ASCERR,stat,
7957 "Inappropriate statement type in CONDITIONAL Statement");
7958 }
7959 }
7960 }
7961
7962 static
7963 void Pass3MarkCondLogRelStat(struct Instance *inst,
7964 struct Statement *statement)
7965 {
7966 struct StatementList *sl;
7967 struct Statement *stat;
7968 unsigned long c,len;
7969 struct gl_list_t *list;
7970 sl = CondStatList(statement);
7971 list = GetList(sl);
7972 len = gl_length(list);
7973 for(c=1;c<=len;c++){
7974 stat = (struct Statement *)gl_fetch(list,c);
7975 Pass3MarkCondLogRels(inst,stat);
7976 }
7977 }
7978
7979
7980 /*
7981 * Execution of the statements allowed inside a CONDITIONAL
7982 * statement. Only log/relations and FOR loops containing only
7983 * log/relations are allowed.
7984 */
7985 static
7986 int Pass3ExecuteCondStatements(struct Instance *inst,
7987 struct Statement *statement)
7988 {
7989 switch(StatementType(statement)){
7990 case LOGREL:
7991 return ExecuteLOGREL(inst,statement);
7992 case FOR:
7993 if ( ForContainsLogRelations(statement) ) {
7994 return Pass3ExecuteFOR(inst,statement);
7995 }
7996 else {
7997 return 1;
7998 }
7999 case REL:
8000 return 1; /* assume done */
8001 default:
8002 WSEM(ASCERR,statement,
8003 "Inappropriate statement type in CONDITIONAL Statement");
8004 return 0;
8005 }
8006 }
8007
8008 static
8009 int Pass3RealExecuteCOND(struct Instance *inst, struct Statement *statement)
8010 {
8011 struct StatementList *sl;
8012 struct Statement *stat;
8013 unsigned long c,len;
8014 struct gl_list_t *list;
8015 sl = CondStatList(statement);
8016 list = GetList(sl);
8017 len = gl_length(list);
8018 for(c=1;c<=len;c++){
8019 stat = (struct Statement *)gl_fetch(list,c);
8020 if (!Pass3ExecuteCondStatements(inst,stat)) return 0;
8021 }
8022 return 1;
8023 }
8024
8025 /*
8026 * Execution of the Conditional statements. In pass3 we consider only
8027 * logrelations (or FOR loops of logrelations),so the checking is not
8028 * done at all. After execution, the logrelations are set as conditional
8029 * by means of a bit and a flag
8030 */
8031 static
8032 int Pass3ExecuteCOND(struct Instance *inst, struct Statement *statement)
8033 {
8034 int return_value;
8035
8036 if (Pass3RealExecuteCOND(inst,statement)) {
8037 return_value = 1;
8038 }
8039 else{
8040 return_value = 0;
8041 }
8042 Pass3MarkCondLogRelStat(inst,statement);
8043 return return_value;
8044 }
8045
8046 /* The relations inside a conditional statement do not have to be
8047 * solved. They are going to be used as boundaries in conditional
8048 * programming. So, we need something to distinguish a conditional
8049 * relation from a non-conditional relation. The next three functions
8050 * "Mark" those relations inside a CONDITIONAL statement as
8051 * Conditional relations. Right now we not only set a bit indicating
8052 * that the relation is conditional, but also set a flag equal to 1.
8053 * This is done in MarkREL above. The flag could be eliminated, but
8054 * we need to fix some places in which it is used, and to use the
8055 * bit instead.
8056 */
8057 static
8058 void Pass2MarkCondRelations(struct Instance *inst, struct Statement *statement)
8059 {
8060 switch(StatementType(statement)){
8061 case REL:
8062 MarkREL(inst,statement);
8063 break;
8064 case FOR:
8065 if ( ForContainsRelations(statement) ) {
8066 Pass2FORMarkCond(inst,statement);
8067 }
8068 break;
8069 case LOGREL:
8070 break;
8071 default:
8072 WSEM(ASCERR,statement,
8073 "Inappropriate statement type in CONDITIONAL Statement");
8074 }
8075 }
8076
8077 static
8078 void Pass2MarkCondRelStatList(struct Instance *inst, struct StatementList *sl)
8079 {
8080 struct Statement *stat;
8081 unsigned long c,len;
8082 struct gl_list_t *list;
8083 list = GetList(sl);
8084 len = gl_length(list);
8085 for(c=1;c<=len;c++){
8086 stat = (struct Statement *)gl_fetch(list,c);
8087 switch(StatementType(stat)){
8088 case REL:
8089 MarkREL(inst,stat);
8090 break;
8091 case FOR:
8092 if ( ForContainsRelations(stat) ) {
8093 Pass2FORMarkCondRelations(inst,stat);
8094 }
8095 break;
8096 case LOGREL:
8097 break;
8098 default:
8099 WSEM(ASCERR,stat,
8100 "Inappropriate statement type in CONDITIONAL Statement");
8101 }
8102 }
8103 }
8104
8105 static
8106 void Pass2MarkCondRelStat(struct Instance *inst, struct Statement *statement)
8107 {
8108 struct StatementList *sl;
8109 struct Statement *stat;
8110 unsigned long c,len;
8111 struct gl_list_t *list;
8112 sl = CondStatList(statement);
8113 list = GetList(sl);
8114 len = gl_length(list);
8115 for(c=1;c<=len;c++){
8116 stat = (struct Statement *)gl_fetch(list,c);
8117 Pass2MarkCondRelations(inst,stat);
8118 }
8119 }
8120
8121 /*
8122 * Execution of the statements allowed inside a CONDITIONAL
8123 * statement. Only relations and FOR loops containing only
8124 * relations are considered in Pass2.
8125 */
8126 static
8127 int Pass2ExecuteCondStatements(struct Instance *inst,
8128 struct Statement *statement)
8129 {
8130 switch(StatementType(statement)){
8131 case REL:
8132 #ifdef DEBUG_RELS
8133 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
8134 FPRINTF(stderr,"Pass2ExecuteCondStatements: case REL");
8135 WriteStatement(stderr, statement, 3);
8136 error_reporter_end_flush();
8137 #endif
8138 return ExecuteREL(inst,statement);
8139 case FOR:
8140 if ( ForContainsRelations(statement) ) {
8141 #ifdef DEBUG_RELS
8142 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
8143 FPRINTF(stderr,"Pass2ExecuteCondStatements: case FOR");
8144 WriteStatement(stderr, statement, 3);
8145 error_reporter_end_flush();
8146 #endif
8147 return Pass2ExecuteFOR(inst,statement);
8148 }
8149 return 1;
8150 case LOGREL:
8151 return 1; /* Ignore */
8152 default:
8153 WSEM(ASCERR,statement,
8154 "Inappropriate statement type in CONDITIONAL Statement");
8155 return 0;
8156 }
8157 }
8158
8159 static
8160 int Pass2RealExecuteCOND(struct Instance *inst, struct Statement *statement)
8161 {
8162 struct StatementList *sl;
8163 struct Statement *stat;
8164 unsigned long c,len;
8165 struct gl_list_t *list;
8166 sl = CondStatList(statement);
8167 list = GetList(sl);
8168 len = gl_length(list);
8169 for(c=1;c<=len;c++){
8170 stat = (struct Statement *)gl_fetch(list,c);
8171 if (!Pass2ExecuteCondStatements(inst,stat)) return 0;
8172 }
8173 return 1;
8174 }
8175
8176 /*
8177 * Execution of the Conditional statements. In pass2 we consider only
8178 * relations (or FOR loops of relations),so the checking is not
8179 * done at all. After execution, the relations are set as conditional
8180 * by means of a bit and a flag
8181 */
8182 static
8183 int Pass2ExecuteCOND(struct Instance *inst, struct Statement *statement)
8184 {
8185 int return_value;
8186
8187 if (Pass2RealExecuteCOND(inst,statement)) {
8188 return_value = 1;
8189 }
8190 else{
8191 return_value = 0;
8192 }
8193 Pass2MarkCondRelStat(inst,statement);
8194 return return_value;
8195 }
8196
8197
8198 /*
8199 * For its use in ExecuteUnSelectedStatements.
8200 * Execute the statements of a CONDITIONAL statement which is inside
8201 * a CASE not matching the selection variables.
8202 * Only FOR loops containing log/relations or log/relations are allowed
8203 * inside CONDITIONAL statements. This function ultimately call
8204 * the function ExecuteUnSelectedEQN, to create Dummy instances
8205 * for the relations inside CONDITIONAL
8206 */
8207 static
8208 int ExecuteUnSelectedCOND(struct Instance *inst, struct Statement *statement)
8209 {
8210 struct StatementList *sl;
8211 struct Statement *stat;
8212 unsigned long c,len;
8213 struct gl_list_t *list;
8214 int return_value = 0;
8215
8216 sl = CondStatList(statement);
8217 list = GetList(sl);
8218 len = gl_length(list);
8219 for(c=1;c<=len;c++){
8220 stat = (struct Statement *)gl_fetch(list,c);
8221 switch(StatementType(stat)){
8222 case FOR:
8223 return_value = ExecuteUnSelectedForStatements(inst,ForStatStmts(stat));
8224 break;
8225 case REL:
8226 case LOGREL:
8227 return_value = ExecuteUnSelectedEQN(inst,stat);
8228 break;
8229 default:
8230 WSEM(stderr,stat,
8231 "Inappropriate statement type in CONDITIONAL Statement");
8232 Asc_Panic(2, NULL,
8233 "Inappropriate statement type in CONDITIONAL Statement");
8234 }
8235 assert(return_value);
8236 }
8237 return 1;
8238 }
8239
8240
8241 /*************************************************************************\
8242 WHEN Statement Processing
8243 \*************************************************************************/
8244
8245 /* Find the instances corresponding to the list of conditional
8246 * variables of a WHEN, and append ther pointers in a gl_list.
8247 * This gl_list becomes part of the WHEN instance.
8248 * Also, this function notify those instances that the WHEN is
8249 * pointing to them, so that their list of whens is updated.
8250 */
8251 static
8252 struct gl_list_t *MakeWhenVarList(struct Instance *inst,
8253 struct Instance *child,
8254 CONST struct VariableList *vlist)
8255 {
8256 CONST struct Name *name;
8257 struct Instance *var;
8258 struct gl_list_t *instances;
8259 struct gl_list_t *whenvars;
8260 enum find_errors err;
8261 unsigned long numvar;
8262
8263 numvar = VariableListLength(vlist);
8264 whenvars = gl_create(numvar);
8265
8266 while(vlist != NULL){
8267 name = NamePointer(vlist);
8268 instances = FindInstances(inst,name,&err);
8269 if (instances == NULL){
8270 Asc_Panic(2, NULL, "Instance not found in MakeWhenVarList \n");
8271 }
8272 else{
8273 if (gl_length(instances)==1) {
8274 var = (struct Instance *)gl_fetch(instances,1);
8275 gl_destroy(instances);
8276 switch(InstanceKind(var)){
8277 case BOOLEAN_ATOM_INST:
8278 case INTEGER_ATOM_INST:
8279 case SYMBOL_ATOM_INST:
8280 case BOOLEAN_CONSTANT_INST:
8281 case INTEGER_CONSTANT_INST:
8282 case SYMBOL_CONSTANT_INST:
8283 gl_append_ptr(whenvars,(VOIDPTR)var);
8284 AddWhen(var,child);
8285 break;
8286 default:
8287 Asc_Panic(2, NULL,
8288 "Incorrect instance type in MakeWhenVarList \n");
8289 }
8290 }
8291 else {
8292 gl_destroy(instances);
8293 Asc_Panic(2, NULL,
8294 "Variable name assigned to more than one instance \n");
8295 }
8296 }
8297 vlist = NextVariableNode(vlist);
8298 }
8299 return whenvars;
8300 }
8301
8302 /* The following four functions create the gl_list of references of
8303 * each CASE of a WHEN instance. By list of references I mean the
8304 * list of pointers to relations, models or arrays which will become
8305 * active if such a CASE applies.
8306 */
8307
8308 /* dealing with arrays */
8309 static
8310 void MakeWhenArrayReference(struct Instance *when,
8311 struct Instance *child,
8312 struct gl_list_t *listref)
8313 {
8314 struct Instance *arraychild;
8315 unsigned long len,c;
8316 switch (InstanceKind(child)) {
8317 case REL_INST:
8318 gl_append_ptr(listref,(VOIDPTR)child);
8319 AddWhen(child,when);
8320 relinst_set_in_when(child,TRUE);
8321 return;
8322 case LREL_INST:
8323 gl_append_ptr(listref,(VOIDPTR)child);
8324 AddWhen(child,when);
8325 logrelinst_set_in_when(child,TRUE);
8326 return;
8327 case MODEL_INST:
8328 gl_append_ptr(listref,(VOIDPTR)child);
8329 AddWhen(child,when);
8330 model_set_in_when(child,TRUE);
8331 return;
8332 case WHEN_INST:
8333 gl_append_ptr(listref,(VOIDPTR)child);
8334 AddWhen(child,when);
8335 return;
8336 case ARRAY_INT_INST:
8337 case ARRAY_ENUM_INST:
8338 len = NumberChildren(child);
8339 for(c=1;c<=len;c++){
8340 arraychild = InstanceChild(child,c);
8341 MakeWhenArrayReference(when,arraychild,listref);
8342 }
8343 return;
8344 default:
8345 Asc_Panic(2, NULL,
8346 "Incorrect array instance name inside a WHEN statement\n");
8347 }
8348 }
8349
8350 static
8351 void MakeWhenReference(struct Instance *ref,
8352 struct Instance *child,
8353 struct Name *name,
8354 struct gl_list_t *listref)
8355 {
8356 struct Instance *inst,*arraychild;
8357 struct gl_list_t *instances;
8358 enum find_errors err;
8359 unsigned long len,c;
8360
8361 instances = FindInstances(ref,name,&err);
8362 if (instances==NULL){
8363 gl_destroy(instances);
8364 FPRINTF(ASCERR,"\n");
8365 WriteName(ASCERR,name);
8366 Asc_Panic(2, NULL,
8367 "Name of an unmade instance (Relation-Model)"
8368 " inside a WHEN statement \n");
8369 } else {
8370 if (gl_length(instances)==1){
8371 inst = (struct Instance *)gl_fetch(instances,1);
8372 gl_destroy(instances);
8373 switch (InstanceKind(inst)) {
8374 case REL_INST:
8375 gl_append_ptr(listref,(VOIDPTR)inst);
8376 AddWhen(inst,child);
8377 relinst_set_in_when(inst,TRUE);
8378 return;
8379 case LREL_INST:
8380 gl_append_ptr(listref,(VOIDPTR)inst);
8381 AddWhen(inst,child);
8382 logrelinst_set_in_when(inst,TRUE);
8383 return;
8384 case MODEL_INST:
8385 gl_append_ptr(listref,(VOIDPTR)inst);
8386 AddWhen(inst,child);
8387 model_set_in_when(inst,TRUE);
8388 return;
8389 case WHEN_INST:
8390 gl_append_ptr(listref,(VOIDPTR)inst);
8391 AddWhen(inst,child);
8392 return;
8393 case ARRAY_INT_INST:
8394 case ARRAY_ENUM_INST:
8395 len = NumberChildren(inst);
8396 for(c=1;c<=len;c++){
8397 arraychild = InstanceChild(inst,c);
8398 MakeWhenArrayReference(child,arraychild,listref);
8399 }
8400 return;
8401 default:
8402 gl_destroy(instances);
8403 FPRINTF(ASCERR,"\n");
8404 WriteName(ASCERR,name);
8405 Asc_Panic(2, NULL,
8406 "Incorrect instance name inside a WHEN statement\n");
8407 break;
8408 }
8409 } else {
8410 gl_destroy(instances);
8411 FPRINTF(ASCERR,"\n");
8412 WriteName(ASCERR,name);
8413 Asc_Panic(2, NULL,
8414 "Error in WHEN statement. Name assigned"
8415 " to more than one instance type\n");
8416 }
8417 }
8418 }
8419
8420 /* dealing with nested WHENs, nested FOR loops etc. */
8421 static
8422 void MakeWhenCaseReferences(struct Instance *inst,
8423 struct Instance *child,
8424 struct StatementList *sl,
8425 struct gl_list_t *listref)
8426 {
8427 struct Statement *statement;
8428 struct Name *name;
8429 unsigned long c,len;
8430 struct gl_list_t *list;
8431 list = GetList(sl);
8432 len = gl_length(list);
8433 for(c=1;c<=len;c++){
8434 statement = (struct Statement *)gl_fetch(list,c);
8435 switch(StatementType(statement)){
8436 case WHEN:
8437 name = WhenStatName(statement);
8438 MakeWhenReference(inst,child,name,listref);
8439 break;
8440 case FNAME:
8441 name = FnameStat(statement);
8442 MakeWhenReference(inst,child,name,listref);
8443 break;
8444 case FOR:
8445 MakeWhenCaseReferencesFOR(inst,child,statement,listref);
8446 break;
8447 default:
8448 WSEM(stderr,statement,
8449 "Inappropriate statement type in WHEN Statement");
8450 Asc_Panic(2, NULL, "Inappropriate statement type in WHEN Statement");
8451 }
8452 }
8453 }
8454
8455 /* The following function is almos identical from the previous one.
8456 * They differ only in the case of a FOR loop. This function is
8457 * required to appropriately deal with nested FOR loops which
8458 * contain FNAMEs or WHENs
8459 */
8460 static
8461 void MakeRealWhenCaseReferencesList(struct Instance *inst,
8462 struct Instance *child,
8463 struct StatementList *sl,
8464 struct gl_list_t *listref)
8465 {
8466 struct Statement *statement;
8467 struct Name *name;
8468 unsigned long c,len;
8469 struct gl_list_t *list;
8470 list = GetList(sl);
8471 len = gl_length(list);
8472 for(c=1;c<=len;c++){
8473 statement = (struct Statement *)gl_fetch(list,c);
8474 switch(StatementType(statement)){
8475 case WHEN:
8476 name = WhenStatName(statement);
8477 MakeWhenReference(inst,child,name,listref);
8478 break;
8479 case FNAME:
8480 name = FnameStat(statement);
8481 MakeWhenReference(inst,child,name,listref);
8482 break;
8483 case FOR:
8484 MakeRealWhenCaseReferencesFOR(inst,child,statement,listref);
8485 break;
8486 default:
8487 WSEM(ASCERR,statement,
8488 "Inappropriate statement type in declarative section");
8489 Asc_Panic(2, NULL,"Inappropriate statement type in declarative section");
8490 break;
8491 }
8492 }
8493 return ;
8494 }
8495
8496
8497 /* Make a WHEN instance or an array of WHEN instances by calling
8498 * CreateWhenInstance. It does not create the lists of pointers
8499 * to the conditional variables or the models or relations.
8500 */
8501
8502 static
8503 struct Instance *MakeWhenInstance(struct Instance *parent,
8504 struct Name *name,
8505 struct Statement *stat)
8506 {
8507 symchar *when_name;
8508 struct TypeDescription *desc;
8509 struct Instance *child;
8510 struct InstanceName rec;
8511 unsigned long pos;
8512 if ((when_name=SimpleNameIdPtr(name))!=NULL){
8513 SetInstanceNameType(rec,StrName);
8514 SetInstanceNameStrPtr(rec,when_name);
8515 if(0 != (pos = ChildSearch(parent,&rec))){
8516 assert(InstanceChild(parent,pos)==NULL);
8517 desc = FindWhenType();
8518 child = CreateWhenInstance(desc);
8519 LinkToParentByPos(parent,child,pos);
8520 return child;
8521 }
8522 else return NULL;
8523 } else{ /* sparse array of when */
8524 when_name = NameIdPtr(name);
8525 SetInstanceNameType(rec,StrName);
8526 SetInstanceNameStrPtr(rec,when_name);
8527 if(0 != (pos = ChildSearch(parent,&rec))){
8528 if (InstanceChild(parent,pos)==NULL){ /* need to make array */
8529 child = MakeSparseArray(parent,name,stat,NULL,0,NULL,NULL,NULL);
8530 } else { /* need to add array element */
8531 child = AddArrayChild(parent,name,stat,NULL,NULL,NULL);
8532 }
8533 return child;
8534 }
8535 else {
8536 return NULL;
8537 }
8538 }
8539 }
8540
8541 /*
8542 * Executing the possible kind of statements inside a WHEN. It
8543 * consider the existence of FOR loops and nested WHENs
8544 */
8545 static
8546 void ExecuteWhenStatements(struct Instance *inst,
8547 struct StatementList *sl)
8548 {
8549 struct Statement *statement;
8550 unsigned long c,len;
8551 int return_value = 0;
8552 struct gl_list_t *list;
8553 list = GetList(sl);
8554 len = gl_length(list);
8555 for(c=1;c<=len;c++){
8556 statement = (struct Statement *)gl_fetch(list,c);
8557 switch(StatementType(statement)){
8558 case WHEN:
8559 return_value = 1;
8560 RealExecuteWHEN(inst,statement);
8561 break;
8562 case FNAME:
8563 return_value = ExecuteFNAME(inst,statement);
8564 break;
8565 case FOR:
8566 return_value = 1;
8567 Pass4ExecuteFOR(inst,statement);
8568 break;
8569 default:
8570 WSEM(stderr,statement,
8571 "Inappropriate statement type in WHEN Statement");
8572 Asc_Panic(2, NULL, "Inappropriate statement type in WHEN Statement");
8573 }
8574 assert(return_value);
8575 }
8576 }
8577
8578
8579 /*
8580 * Creates a CASE included in a WHEN statement. It involves the
8581 * allocation of memory of the CASE and the creation of the
8582 * gl_list of references (pointer to models, arrays, relations)
8583 * which will be contained in such a case.
8584 */
8585 static
8586 struct Case *RealExecuteWhenStatements(struct Instance *inst,
8587 struct Instance *child,
8588 struct WhenList *w1)
8589 {
8590 struct StatementList *sl;
8591 struct Case *cur_case;
8592 struct gl_list_t *listref;
8593 struct Set *set;
8594
8595 listref = gl_create(AVG_REF);
8596
8597 set = WhenSetList(w1);
8598 cur_case = CreateCase(CopySetByReference(set),NULL);
8599 sl = WhenStatementList(w1);
8600 ExecuteWhenStatements(inst,sl);
8601 MakeWhenCaseReferences(inst,child,sl,listref);
8602 SetCaseReferences(cur_case,listref);
8603 return cur_case;
8604 }
8605
8606 /* Call the Creation of a WHEN instance. This function is also in charge
8607 * of filling the gl_list of conditional variables and the gl_list of
8608 * CASEs contained in the WHEN instance
8609 */
8610 static
8611 void RealExecuteWHEN(struct Instance *inst, struct Statement *statement)
8612 {
8613 struct VariableList *vlist;
8614 struct WhenList *w1;
8615 struct Instance *child;
8616 struct Name *wname;
8617 struct Case *cur_case;
8618 enum find_errors ferr;
8619 struct gl_list_t *instances;
8620 struct gl_list_t *whenvars;
8621 struct gl_list_t *whencases;
8622
8623 wname = WhenStatName(statement);
8624 instances = FindInstances(inst,wname,&ferr);
8625 if (instances==NULL) {
8626 /* if (ferr == unmade_instance) { */
8627 child = MakeWhenInstance(inst,wname,statement);
8628 if (child == NULL) {
8629 WSEM(ASCERR,statement,"Unable to create when instance");
8630 Asc_Panic(2, NULL, "Unable to create when instance");
8631 }
8632 /* }
8633 else {
8634 WSEM(ASCERR,statement,"Unable to execute statement");
8635 Asc_Panic(2, NULL, "Unable to execute statement");
8636 } */
8637 } else {
8638 if(gl_length(instances)==1){
8639 child = (struct Instance *)gl_fetch(instances,1);
8640 assert( (InstanceKind(child)==WHEN_INST)
8641 || (InstanceKind(child)==DUMMY_INST) );
8642 gl_destroy(instances);
8643 if (InstanceKind(child)==DUMMY_INST) {
8644 return;
8645 }
8646 } else{
8647 WSEM(ASCERR,statement, "Expression name refers to more than one object");
8648 gl_destroy(instances);
8649 Asc_Panic(2, NULL, "Expression name refers to more than one object");
8650 child = NULL;
8651 }
8652 }
8653 vlist = WhenStatVL(statement);
8654 whenvars = MakeWhenVarList(inst,child,vlist);
8655 SetWhenVarList(child,whenvars);
8656 whencases = gl_create(AVG_CASES);
8657 w1 = WhenStatCases(statement);
8658 while (w1!=NULL){
8659 cur_case = RealExecuteWhenStatements(inst,child,w1);
8660 gl_append_ptr(whencases,(VOIDPTR)cur_case);
8661 w1 = NextWhenCase(w1);
8662 }
8663 SetWhenCases(child,whencases);
8664 }
8665
8666
8667 /* After Checking the WHEN statement, it calls for its execution */
8668 static
8669 int ExecuteWHEN(struct Instance *inst, struct Statement *statement)
8670 {
8671 if (CheckWHEN(inst,statement)){
8672 RealExecuteWHEN(inst,statement);
8673 return 1;
8674 }
8675 else{
8676 return 0;
8677 }
8678 }
8679
8680
8681 /*
8682 * Written because of the possiblity of nested WHEN and
8683 * Nested WHEN inside a FOR loop in an unselected case of
8684 * SELECT statement
8685 */
8686 static
8687 void ExecuteUnSelectedWhenStatements(struct Instance *inst,
8688 struct StatementList *sl)
8689 {
8690 struct Statement *statement;
8691 unsigned long c,len;
8692 int return_value = 0;
8693 struct gl_list_t *list;
8694 list = GetList(sl);
8695 len = gl_length(list);
8696 for(c=1;c<=len;c++){
8697 statement = (struct Statement *)gl_fetch(list,c);
8698 switch(StatementType(statement)){
8699 case WHEN:
8700 return_value = ExecuteUnSelectedWHEN(inst,statement);
8701 break;
8702 case FNAME:
8703 return_value = 1;
8704 break;
8705 case FOR:
8706 return_value = ExecuteUnSelectedForStatements(inst,
8707 ForStatStmts(statement));
8708 break;
8709 default:
8710 WSEM(stderr,statement,
8711 "Inappropriate statement type in WHEN Statement");
8712 Asc_Panic(2, NULL, "Inappropriate statement type in WHEN Statement");
8713 }
8714 assert(return_value);
8715 }
8716 }
8717
8718 /*
8719 * For its use in ExecuteUnSelectedStatements.
8720 * Execute the WHEN statements inside those cases of a SELECT
8721 * which do not match the selection variables
8722 */
8723 static
8724 int ExecuteUnSelectedWHEN(struct Instance *inst, struct Statement *statement)
8725 {
8726 struct WhenList *w1;
8727 struct Instance *child;
8728 struct Name *wname;
8729 struct StatementList *sl;
8730 enum find_errors ferr;
8731 struct gl_list_t *instances;
8732 struct TypeDescription *def;
8733
8734 wname = WhenStatName(statement);
8735 instances = FindInstances(inst,wname,&ferr);
8736 if (instances==NULL) {
8737 def = FindDummyType();
8738 MakeDummyInstance(wname,def,inst,statement);
8739 }
8740 else {
8741 if(gl_length(instances)==1){
8742 child = (struct Instance *)gl_fetch(instances,1);
8743 assert(InstanceKind(child)==DUMMY_INST);
8744 gl_destroy(instances);
8745 } else{
8746 WSEM(ASCERR,statement, "Expression name refers to more than one object");
8747 gl_destroy(instances);
8748 Asc_Panic(2, NULL, "Expression name refers to more than one object");
8749 }
8750 }
8751
8752 w1 = WhenStatCases(statement);
8753 while (w1!=NULL){
8754 sl = WhenStatementList(w1);
8755 ExecuteUnSelectedWhenStatements(inst,sl);
8756 w1 = NextWhenCase(w1);
8757 }
8758 return 1;
8759 }
8760
8761
8762 /*************************************************************************\
8763 SELECT Statement Processing
8764 \*************************************************************************/
8765
8766 /*
8767 * Execution of the Statements inside the case that
8768 * matches the selection variables
8769 */
8770 static
8771 void ExecuteSelectStatements(struct Instance *inst, unsigned long *count,
8772 struct StatementList *sl)
8773 {
8774 struct BitList *blist;
8775 struct Statement *statement;
8776 unsigned long c,len;
8777 int return_value;
8778 struct gl_list_t *list;
8779
8780 blist = InstanceBitList(inst);
8781 list = GetList(sl);
8782 len = gl_length(list);
8783 for(c=1;c<=len;c++){
8784 (*count)++;
8785 statement = (struct Statement *)gl_fetch(list,c);
8786 switch(StatementType(statement)){
8787 case ALIASES:
8788 return_value = ExecuteALIASES(inst,statement);
8789 if (return_value) ClearBit(blist,*count);
8790 break;
8791 case CASGN:
8792 return_value = ExecuteCASGN(inst,statement);
8793 if (return_value) {
8794 ClearBit(blist,*count);
8795 }
8796 break;
8797 case ARR:
8798 return_value = ExecuteISA(inst,statement);
8799 if (return_value) ClearBit(blist,*count);
8800 break;
8801 case ISA:
8802 return_value = ExecuteISA(inst,statement);
8803 if (return_value) ClearBit(blist,*count);
8804 break;
8805 case IRT:
8806 return_value = ExecuteIRT(inst,statement);
8807 if (return_value) ClearBit(blist,*count);
8808 break;
8809 case ATS:
8810 return_value = ExecuteATS(inst,statement);
8811 if (return_value) ClearBit(blist,*count);
8812 break;
8813 case AA:
8814 return_value = ExecuteAA(inst,statement);
8815 if (return_value) ClearBit(blist,*count);
8816 break;
8817 case FOR:
8818 return_value = Pass1ExecuteFOR(inst,statement);
8819 if (return_value) ClearBit(blist,*count);
8820 break;
8821 case EXT:
8822 #if OLD_ext
8823 return_value = ExecuteEXT(inst,statement);
8824 if (return_value) ClearBit(blist,*count);
8825 break;
8826 #endif
8827 case ASGN:
8828 case REL:
8829 case LOGREL:
8830 case COND:
8831 case CALL:
8832 case WHEN:
8833 return_value = 1; /* ignore'm */
8834 ClearBit(blist,*count);
8835 break;
8836 case FNAME:
8837 if (g_iteration>=MAXNUMBER) {
8838 WSEM(ASCERR,statement,
8839 "FNAME not allowed inside a SELECT Statement");
8840 }
8841 return_value = 1; /* Ignore it */
8842 ClearBit(blist,*count);
8843 break;
8844 case SELECT:
8845 return_value = ExecuteSELECT(inst,count,statement);
8846 break;
8847 default:
8848 WSEM(stderr,statement,
8849 "Inappropriate statement type in declarative section SELECT\n");
8850 Asc_Panic(2, NULL,
8851 "Inappropriate statement type"
8852 " in declarative section SELECT");
8853 }
8854 }
8855 }
8856
8857
8858 /*
8859 * Execution of the UnSelected Statements inside those cases of the
8860 * SELECT that do not match match the selection variables
8861 */
8862
8863 static
8864 void ExecuteUnSelectedStatements(struct Instance *inst,unsigned long *count,
8865 struct StatementList *sl)
8866 {
8867 struct BitList *blist;
8868 struct Statement *statement;
8869 unsigned long c,len;
8870 int return_value;
8871 struct gl_list_t *list;
8872
8873 blist = InstanceBitList(inst);
8874 list = GetList(sl);
8875 len = gl_length(list);
8876 for(c=1;c<=len;c++){
8877 (*count)++;
8878 statement = (struct Statement *)gl_fetch(list,c);
8879 switch(StatementType(statement)){
8880 case ARR:
8881 case IRT:
8882 case ATS:
8883 case AA:
8884 case EXT:
8885 case CALL:
8886 case CASGN:
8887 case ASGN:
8888 ClearBit(blist,*count);
8889 break;
8890 case FNAME:
8891 if (g_iteration>=MAXNUMBER) {
8892 WSEM(ASCERR,statement,"FNAME not allowed inside a SELECT Statement");
8893 }
8894 return_value = 1; /*ignore it */
8895 ClearBit(blist,*count);
8896 break;
8897 case ALIASES:
8898 return_value = ExecuteUnSelectedALIASES(inst,statement);
8899 if (return_value) ClearBit(blist,*count);
8900 break;
8901 case ISA:
8902 return_value = ExecuteUnSelectedISA(inst,statement);
8903 if (return_value) ClearBit(blist,*count);
8904 break;
8905 case FOR:
8906 return_value = ExecuteUnSelectedForStatements(inst,
8907 ForStatStmts(statement));
8908 if (return_value) ClearBit(blist,*count);
8909 break;
8910 case REL:
8911 case LOGREL:
8912 return_value = ExecuteUnSelectedEQN(inst,statement);
8913 ClearBit(blist,*count);
8914 break;
8915 case COND:
8916 return_value = ExecuteUnSelectedCOND(inst,statement);
8917 ClearBit(blist,*count);
8918 break;
8919 case WHEN:
8920 return_value = ExecuteUnSelectedWHEN(inst,statement);
8921 ClearBit(blist,*count);
8922 break;
8923 case SELECT:
8924 return_value = ExecuteUnSelectedSELECT(inst,count,statement);
8925 break;
8926 default:
8927 WSEM(stderr,statement,
8928 "Inappropriate statement type in declarative section unSELECTed\n");
8929 Asc_Panic(2, NULL, "Inappropriate statement type"
8930 " in declarative section unSELECTed\n");
8931 }
8932 }
8933 }
8934
8935 /*
8936 * Execution of the SELECT statement inside a case that does not
8937 * match the selection variables
8938 */
8939 static
8940 int ExecuteUnSelectedSELECT(struct Instance *inst, unsigned long *c,
8941 struct Statement *statement)
8942 {
8943 struct BitList *blist;
8944 struct SelectList *sel1;
8945 struct StatementList *sl;
8946
8947 blist = InstanceBitList(inst);
8948 ClearBit(blist,*c);
8949 sel1 = SelectStatCases(statement);
8950 while (sel1!=NULL){
8951 sl = SelectStatementList(sel1);
8952 ExecuteUnSelectedStatements(inst,c,sl);
8953 sel1 = NextSelectCase(sel1);
8954 }
8955 return 1;
8956 }
8957
8958
8959 /*
8960 * Compare current values of the selection variables with
8961 * the set of values in a CASE of a SELECT statement, and try to find
8962 * is such values are the same. If they are, the function will return 1,
8963 * else, it will return 0.
8964 */
8965 static
8966 int AnalyzeSelectCase(struct Instance *ref, struct VariableList *vlist,
8967 struct Set *s)
8968 {
8969 CONST struct Expr *expr;
8970 CONST struct Name *name;
8971 symchar *value;
8972 symchar *symvar;
8973 CONST struct VariableList *vl;
8974 CONST struct Set *values;
8975 int val;
8976 int valvar;
8977 struct gl_list_t *instances;
8978 struct Instance *inst;
8979 enum find_errors err;
8980
8981 assert(s!= NULL);
8982 assert(vlist != NULL);
8983 values = s;
8984 vl = vlist;
8985
8986 while (vl!=NULL) {
8987 name = NamePointer(vl);
8988 expr = GetSingleExpr(values);
8989 instances = FindInstances(ref,name,&err);
8990 assert(gl_length(instances)==1);
8991 inst = (struct Instance *)gl_fetch(instances,1);
8992 gl_destroy(instances);
8993 switch(ExprType(expr)) {
8994 case e_boolean:
8995 val = ExprBValue(expr);
8996 if (val == 2) { /* ANY */
8997 break;
8998 }
8999 valvar = GetBooleanAtomValue(inst);
9000 if (val != valvar) return 0;
9001 break;
9002 case e_int:
9003 assert(InstanceKind(inst)==INTEGER_CONSTANT_INST);
9004 val = ExprIValue(expr);
9005 valvar = GetIntegerAtomValue(inst);
9006 if (val != valvar) return 0;
9007 break;
9008 case e_symbol:
9009 assert(InstanceKind(inst)==SYMBOL_CONSTANT_INST);
9010 symvar = ExprSymValue(expr);
9011 value = GetSymbolAtomValue(inst);
9012 if (symvar != value) {
9013 assert(AscFindSymbol(symvar)!=NULL);
9014 return 0;
9015 }
9016 break;
9017 default:
9018 FPRINTF(stderr,"Something wrong happens in AnalyzeSelectCase \n");
9019 return 0;
9020 }
9021 vl = NextVariableNode(vl);
9022 values = NextSet(values);
9023 }
9024
9025 return 1;
9026 }
9027
9028
9029 /* This function will determine which case of a SELECT statement
9030 * applies for the current values of the selection variables.
9031 * this function will call for the execution of the case which
9032 * matches. It handles OTHERWISE properly (case when set == NULL).
9033 * At most one case is going to be executed.
9034 */
9035
9036 static
9037 void RealExecuteSELECT(struct Instance *inst, unsigned long *c,
9038 struct Statement *statement)
9039 {
9040 struct VariableList *vlist;
9041 struct SelectList *sel1;
9042 struct Set *set;
9043 struct StatementList *sl;
9044 int case_match;
9045
9046 vlist = SelectStatVL(statement);
9047 sel1 = SelectStatCases(statement);
9048 case_match =0;
9049
9050 while (sel1!=NULL){
9051 set = SelectSetList(sel1);
9052 sl = SelectStatementList(sel1);
9053 if (case_match==0) {
9054 if (set != NULL) {
9055 case_match = AnalyzeSelectCase(inst,vlist,set);
9056 if (case_match==1) {
9057 ExecuteSelectStatements(inst,c,sl);
9058 }
9059 else {
9060 ExecuteUnSelectedStatements(inst,c,sl);
9061 }
9062 }
9063 else {
9064 ExecuteSelectStatements(inst,c,sl);
9065 case_match = 1;
9066 }
9067 }
9068 else {
9069 ExecuteUnSelectedStatements(inst,c,sl);
9070 }
9071 sel1 = NextSelectCase(sel1);
9072 }
9073
9074 if (case_match == 0) {
9075 FPRINTF(ASCERR,"No case matched in SELECT statement\n");
9076 }
9077 }
9078
9079
9080 /* If A SELECT statement passess its checking, this function
9081 * will ask for its execution, otherwise the SELECT and all
9082 * the other statements inside of it, will not be touched.
9083 * The counter in the bitlist is increased properly.
9084 * NOTE for efficiency: Maybe we should integrate the
9085 * Check function of the SELECT together with the analysis
9086 * of the CASEs to see which of them matches.We are doing
9087 * twice the execution of some C functions.
9088 */
9089 static
9090 int ExecuteSELECT(struct Instance *inst, unsigned long *c,
9091 struct Statement *statement)
9092 {
9093 unsigned long tmp;
9094 struct BitList *blist;
9095
9096 blist = InstanceBitList(inst);
9097 if (CheckSELECT(inst,statement)){
9098 ClearBit(blist,*c);
9099 RealExecuteSELECT(inst,c,statement);
9100 return 1;
9101 }
9102 else{
9103 tmp = SelectStatNumberStats(statement);
9104 *c = (*c) + tmp;
9105 return 0;
9106 }
9107 }
9108
9109
9110 /*
9111 * This function jumps the statements inside non-matching
9112 * cases of a SELECT statement, so that they are not analyzed
9113 * in compilation passes > 1.
9114 * If there is a SELECT inside a SELECT,
9115 * the function uses the number of statements in the nested
9116 * SELECTs
9117 */
9118 static
9119 void JumpSELECTStats(unsigned long *count,struct StatementList *sl)
9120 {
9121 unsigned long c,length;
9122 int tmp;
9123 struct Statement *s;
9124
9125 length = StatementListLength(sl);
9126 *count = (*count) + length;
9127 for(c=1;c<=length;c++){
9128 tmp = 0;
9129 s = GetStatement(sl,c);
9130 assert(s!=NULL);
9131 switch(StatementType(s)) {
9132 case SELECT:
9133 tmp = SelectStatNumberStats(s);
9134 break;
9135 default:
9136 break;
9137 }
9138 *count = (*count) + tmp;
9139 }
9140 return;
9141 }
9142
9143 /* This function is used only for setting the
9144 * bits ON for some statements in the matching case of a
9145 * SELECT statement. Only these statements will be
9146 * analyzed in Pass > 1. The conditions to set a bit ON
9147 * depend on the number of pass.
9148 */
9149 static
9150 void SetBitsOnOfSELECTStats(struct Instance *inst, unsigned long *count,
9151 struct StatementList *sl, int pass, int *changed)
9152 {
9153 unsigned long c,length;
9154 struct Statement *s;
9155 struct BitList *blist;
9156
9157 blist = InstanceBitList(inst);
9158 length = StatementListLength(sl);
9159 for(c=1;c<=length;c++){
9160 s = GetStatement(sl,c);
9161 assert(s!=NULL);
9162 (*count)++;
9163 switch (pass) {
9164 case 2:
9165 switch(StatementType(s)) {
9166 case REL:
9167 SetBit(blist,*count);
9168 (*changed)++;
9169 break;
9170 case COND:
9171 if (CondContainsRelations(s)) {
9172 SetBit(blist,*count);
9173 (*changed)++;
9174 }
9175 break;
9176 case FOR:
9177 if ( ForContainsRelations(s) ) {
9178 SetBit(blist,*count);
9179 (*changed)++;
9180 }
9181 break;
9182 case SELECT:
9183 if (SelectContainsRelations(s)) {
9184 ReEvaluateSELECT(inst,count,s,pass,changed);
9185 }
9186 else {
9187 *count = *count + SelectStatNumberStats(s);
9188 }
9189 break;
9190 default:
9191 break;
9192 }
9193 break;
9194 case 3:
9195 switch(StatementType(s)) {
9196 case LOGREL:
9197 SetBit(blist,*count);
9198 (*changed)++;
9199 break;
9200 case COND:
9201 if (CondContainsLogRelations(s)) {
9202 SetBit(blist,*count);
9203 (*changed)++;
9204 }
9205 break;
9206 case FOR:
9207 if ( ForContainsLogRelations(s) ) {
9208 SetBit(blist,*count);
9209 (*changed)++;
9210 }
9211 break;
9212 case SELECT:
9213 if (SelectContainsLogRelations(s)) {
9214 ReEvaluateSELECT(inst,count,s,pass,changed);
9215 }
9216 else {
9217 *count = *count + SelectStatNumberStats(s);
9218 }
9219 break;
9220 default:
9221 break;
9222 }
9223 break;
9224 case 4:
9225 switch(StatementType(s)) {
9226 case WHEN:
9227 SetBit(blist,*count);
9228 (*changed)++;
9229 break;
9230 case FOR:
9231 if ( ForContainsWhen(s) ) {
9232 SetBit(blist,*count);
9233 (*changed)++;
9234 }
9235 break;
9236 case SELECT:
9237 if (SelectContainsWhen(s)) {
9238 ReEvaluateSELECT(inst,count,s,pass,changed);
9239 }
9240 else {
9241 *count = *count + SelectStatNumberStats(s);
9242 }
9243 break;
9244 default:
9245 break;
9246 }
9247 break;
9248 default:
9249 FPRINTF(ASCERR,"Wrong pass Number in SetBitsOnOfSELECTStats \n");
9250 break;
9251 }
9252 }
9253 return;
9254 }
9255
9256
9257 /* This function will determine which case of a SELECT statement
9258 * applies for the current values of the selection variables.
9259 * Similar performance from RealExecuteSELECT, but this function
9260 * does not call for execution, it is used only for "jumping"
9261 * the statements inside a non-matching case, or seting the
9262 * bits on for some statements in the matching case.
9263 * It handles OTHERWISE properly (case when set == NULL).
9264 */
9265 static
9266 void SetBitOfSELECTStat(struct Instance *inst, unsigned long *c,
9267 struct Statement *statement, int pass, int *changed)
9268 {
9269 struct VariableList *vlist;
9270 struct SelectList *sel1;
9271 struct Set *set;
9272 struct StatementList *sl;
9273 int case_match;
9274
9275 vlist = SelectStatVL(statement);
9276 sel1 = SelectStatCases(statement);
9277 case_match =0;
9278
9279 while (sel1!=NULL){
9280 set = SelectSetList(sel1);
9281 sl = SelectStatementList(sel1);
9282 if (case_match==0) {
9283 if (set != NULL) {
9284 case_match = AnalyzeSelectCase(inst,vlist,set);
9285 if (case_match==1) {
9286 SetBitsOnOfSELECTStats(inst,c,sl,pass,changed);
9287 }
9288 else {
9289 JumpSELECTStats(c,sl);
9290 }
9291 }
9292 else {
9293 SetBitsOnOfSELECTStats(inst,c,sl,pass,changed);
9294 case_match = 1;
9295 }
9296 }
9297 else {
9298 JumpSELECTStats(c,sl);
9299 }
9300 sel1 = NextSelectCase(sel1);
9301 }
9302 }
9303
9304 /*
9305 * For compilation passes > 1, this function will tell me if I
9306 * should Set the Bits on for statements inside the CASEs of
9307 * a SELECT statement. This evaluation is needed because there may be
9308 * relations, whens or log rels that should not be executed
9309 * at all (when the selection variables do not exist, for example)
9310 * or should not be reanlyzed in pass2 3 and 4 (when they are
9311 * already dummys, for example). This re-evaluation will not be done
9312 * if the SELECT does not contain rels, logrels or when.
9313 * NOTE for efficiency: Maybe we should integrate the
9314 * Check function of the SELECT together with the analysis
9315 * of the CASEs to see which of them matches.We are doing
9316 * twice the execution of some C functions.
9317 */
9318
9319 static
9320 void ReEvaluateSELECT(struct Instance *inst, unsigned long *c,
9321 struct Statement *statement, int pass, int *changed)
9322 {
9323 unsigned long tmp;
9324 struct BitList *blist;
9325
9326 blist = InstanceBitList(inst);
9327 if (CheckSELECT(inst,statement)){
9328 SetBitOfSELECTStat(inst,c,statement,pass,changed);
9329 }
9330 else{
9331 tmp = SelectStatNumberStats(statement);
9332 *c = (*c) + tmp;
9333 }
9334 return;
9335 }
9336
9337
9338 /* This function is used only for setting the
9339 * bits ON for some statements in the matching case of a
9340 * SELECT statement. Only these statements will be
9341 * analyzed in Pass > 1. The conditions to set a bit ON
9342 * depend on the number of pass.
9343 */
9344 static
9345 void ExecuteDefaultsInSELECTCase(struct Instance *inst, unsigned long *count,
9346 struct StatementList *sl,
9347 unsigned long int *depth)
9348 {
9349 unsigned long c,length;
9350 struct Statement *s;
9351 struct for_table_t *SavedForTable;
9352
9353 length = StatementListLength(sl);
9354 for(c=1;c<=length;c++){
9355 s = GetStatement(sl,c);
9356 assert(s!=NULL);
9357 (*count)++;
9358 switch(StatementType(s)) {
9359 case ASGN:
9360 ExecuteDefault(inst,s,depth);
9361 break;
9362 case FOR:
9363 if ( ForContainsDefaults(s) ){
9364 SavedForTable = GetEvaluationForTable();
9365 SetEvaluationForTable(CreateForTable());
9366 RealDefaultFor(inst,s,depth);
9367 DestroyForTable(GetEvaluationForTable());
9368 SetEvaluationForTable(SavedForTable);
9369 }
9370 break;
9371 case SELECT:
9372 ExecuteDefaultsInSELECT(inst,count,s,depth);
9373 break;
9374 default:
9375 break;
9376 }
9377 }
9378 return;
9379 }
9380
9381
9382 /* This function will determine which case of a SELECT statement
9383 * applies for the current values of the selection variables.
9384 * Similar performance from RealExecuteSELECT. This function
9385 * is used only for "jumping" the statements inside a non-matching
9386 * case, or Executing Defaults in the matching case.
9387 * It handles OTHERWISE properly (case when set == NULL).
9388 */
9389 static
9390 void ExecuteDefaultsInSELECTStat(struct Instance *inst, unsigned long *c,
9391 struct Statement *statement,
9392 unsigned long int *depth)
9393 {
9394 struct VariableList *vlist;
9395 struct SelectList *sel1;
9396 struct Set *set;
9397 struct StatementList *sl;
9398 int case_match;
9399
9400 vlist = SelectStatVL(statement);
9401 sel1 = SelectStatCases(statement);
9402 case_match =0;
9403
9404 while (sel1!=NULL){
9405 set = SelectSetList(sel1);
9406 sl = SelectStatementList(sel1);
9407 if (case_match==0) {
9408 if (set != NULL) {
9409 case_match = AnalyzeSelectCase(inst,vlist,set);
9410 if (case_match==1) {
9411 ExecuteDefaultsInSELECTCase(inst,c,sl,depth);
9412 }
9413 else {
9414 JumpSELECTStats(c,sl);
9415 }
9416 }
9417 else {
9418 ExecuteDefaultsInSELECTCase(inst,c,sl,depth);
9419 case_match = 1;
9420 }
9421 }
9422 else {
9423 JumpSELECTStats(c,sl);
9424 }
9425 sel1 = NextSelectCase(sel1);
9426 }
9427 }
9428
9429 /*
9430 * For Execution of Defaults, which uses a Visit Instance Tree instead of
9431 * a BitList. this function will tell me if I
9432 * should Set the Bits on for statements inside the CASEs of
9433 * a SELECT statement. This evaluation is needed because there is
9434 * the possibility of different assignments to the same variable in
9435 * different cases of the select. I need to execute only those in
9436 * cases mathing the selection variables.
9437 * It is becoming annoying to have so similar functions, I need
9438 * to create a robust and general function which considers all the
9439 * possible applications.
9440 */
9441 static
9442 void ExecuteDefaultsInSELECT(struct Instance *inst, unsigned long *c,
9443 struct Statement *statement,
9444 unsigned long int *depth)
9445 {
9446 unsigned long tmp;
9447
9448 if (CheckSELECT(inst,statement)){
9449 ExecuteDefaultsInSELECTStat(inst,c,statement,depth);
9450 }
9451 else{
9452 tmp = SelectStatNumberStats(statement);
9453 *c = (*c) + tmp;
9454 }
9455 return;
9456 }
9457
9458
9459 /**************************************************************************\
9460 FOR Statement processing.
9461 \**************************************************************************/
9462 static
9463 void WriteForValueError(struct Statement *statement, struct value_t value)
9464 {
9465 switch(ErrorValue(value)){
9466 case type_conflict:
9467 WSEM(ASCERR,statement, "Type conflict in FOR expression");
9468 break;
9469 case incorrect_name:
9470 WSEM(ASCERR,statement, "Impossible instance in FOR expression");
9471 break;
9472 case temporary_variable_reused:
9473 WSEM(ASCERR,statement, "Temporary variable reused in FOR expression");
9474 break;
9475 case dimension_conflict:
9476 WSEM(ASCERR,statement, "Dimension conflict in FOR expression");
9477 break;
9478 case incorrect_such_that:
9479 WSEM(ASCERR,statement, "Incorrect such that expression in FOR expression");
9480 break;
9481 case empty_choice:
9482 WSEM(ASCERR,statement,
9483 "CHOICE is called on an empty set in FOR expression");
9484 break;
9485 case empty_intersection:
9486 WSEM(ASCERR,statement, "Empty INTERSECTION() in FOR expression");
9487 break;
9488 default:
9489 WSEM(ASCERR,statement, "Unexpected error in FOR expression");
9490 break;
9491 }
9492 }
9493
9494 static
9495 int Pass4ExecuteForStatements(struct Instance *inst,
9496 struct StatementList *sl)
9497 {
9498 struct Statement *statement;
9499 unsigned long c,len;
9500 struct gl_list_t *list;
9501 list = GetList(sl);
9502 len = gl_length(list);
9503 for(c=1;c<=len;c++){
9504 statement = (struct Statement *)gl_fetch(list,c);
9505 switch(StatementType(statement)){
9506 case WHEN:
9507 if (!ExecuteWHEN(inst,statement)) return 0;
9508 break;
9509 case FNAME:
9510 if (!ExecuteFNAME(inst,statement)) return 0;
9511 break;
9512 case FOR:
9513 if (!Pass4ExecuteFOR(inst,statement)) return 0;
9514 break;
9515 case SELECT:
9516 WSEM(ASCERR,statement,
9517 "SELECT statements are not allowed inside a FOR Statement");
9518 return 0;
9519 /* I probably need to change NP4REF to integer */
9520 case ALIASES:
9521 case ARR:
9522 case ISA:
9523 case IRT:
9524 case ATS:
9525 case AA:
9526 case REF:
9527 case ASGN:
9528 case CASGN:
9529 case REL:
9530 case LOGREL:
9531 case COND:
9532 case CALL:
9533 case EXT: /* ignore'm */
9534 break;
9535 default:
9536 WSEM(ASCERR,statement,
9537 "Inappropriate statement type in declarative section WHEN");
9538 Asc_Panic(2, NULL,
9539 "Inappropriate statement type in declarative section WHEN");
9540 }
9541 }
9542 return 1;
9543 }
9544
9545
9546 /* Note: this function must not be called until all the rel,ext
9547 * statements in sl pass their checks.
9548 */
9549 static
9550 int Pass3ExecuteForStatements(struct Instance *inst,
9551 struct StatementList *sl)
9552 {
9553 struct Statement *statement;
9554 unsigned long c,len;
9555 int return_value;
9556 struct gl_list_t *list;
9557 list = GetList(sl);
9558 len = gl_length(list);
9559
9560 return_value =1;
9561 for(c=1;c<=len;c++){
9562 statement = (struct Statement *)gl_fetch(list,c);
9563 switch(StatementType(statement)){
9564 case ALIASES:
9565 case ARR:
9566 case ISA:
9567 case IRT:
9568 case ATS:
9569 case AA:
9570 case REF:
9571 case ASGN:
9572 case REL:
9573 case CALL:
9574 case EXT: /* ignore'm */
9575 case CASGN:
9576 case WHEN:
9577 return_value = 1; /* ignore'm until pass 4 */
9578 break;
9579 case FNAME:
9580 WSEM(ASCERR,statement,
9581 "FNAME statements are only allowed inside a WHEN Statement");
9582 return_value = 0;
9583 break;
9584 case SELECT:
9585 WSEM(ASCERR,statement,
9586 "SELECT statements are not allowed inside a FOR Statement");
9587 return_value = 0;
9588 break;
9589 case FOR:
9590 if ( ForContainsLogRelations(statement) ) {
9591 return_value = Pass3RealExecuteFOR(inst,statement);
9592 }
9593 break;
9594 case COND:
9595 WSEM(ASCERR,statement,
9596 "COND not allowed inside a FOR. Try FOR inside COND");
9597 return_value = 0;
9598 break;
9599 case LOGREL:
9600 if (ExecuteLOGREL(inst,statement)) {
9601 return_value = 1;
9602 }
9603 else {
9604 return_value = 0;
9605 }
9606 break;
9607 default:
9608 WSEM(ASCERR,statement,
9609 "Inappropriate statement type in declarative section log rel\n");
9610 Asc_Panic(2, NULL, "Inappropriate statement type"
9611 " in declarative section log rel\n");
9612 }
9613 if (!return_value) {
9614 return 0;
9615 }
9616 }
9617 return 1;
9618 }
9619
9620
9621 /* Note: this function must not be called until all the rel,ext
9622 * statements in sl pass their checks.
9623 * This is because if any of the Executes fail
9624 * (returning 0) we abort (at least when assert is active).
9625 * This should be changed.
9626 */
9627 static
9628 void Pass2ExecuteForStatements(struct Instance *inst,
9629 struct StatementList *sl)
9630 {
9631 struct Statement *statement;
9632 unsigned long c,len;
9633 int return_value = 0;
9634 struct gl_list_t *list;
9635 list = GetList(sl);
9636 len = gl_length(list);
9637 for(c=1;c<=len;c++){
9638 statement = (struct Statement *)gl_fetch(list,c);
9639 switch(StatementType(statement)){
9640 case ALIASES:
9641 case ARR:
9642 case ISA:
9643 case IRT:
9644 case ATS:
9645 case AA:
9646 case CALL:
9647 case REF:
9648 case ASGN: /* ignore'm */
9649 case CASGN:
9650 case LOGREL:
9651 return_value = 1; /* ignore'm until pass 3 */
9652 break;
9653 case WHEN:
9654 return_value = 1; /* ignore'm until pass 4 */
9655 break;
9656 case SELECT:
9657 WSEM(ASCERR,statement,
9658 "SELECT statements are not allowed inside a FOR Statement");
9659 return_value = 0;
9660 break;
9661 case FNAME:
9662 WSEM(ASCERR,statement,
9663 "FNAME statements are only allowed inside a WHEN Statement");
9664 return_value = 0;
9665 break;
9666 case FOR:
9667 return_value = 1;
9668 if ( ForContainsRelations(statement) ) {
9669 #ifdef DEBUG_RELS
9670 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
9671 WriteStatement(stderr, statement, 6);
9672 error_reporter_end_flush();
9673 #endif
9674 Pass2RealExecuteFOR(inst,statement);
9675 /* p2ref expected to succeed or fail permanently.
9676 * if it doesn't, this needs fixing.
9677 */
9678 }
9679 break;
9680 case COND:
9681 WSEM(ASCERR,statement,
9682 "COND not allowed inside a FOR. Try FOR inside COND");
9683 return_value = 0;
9684 break;
9685 case REL:
9686 #ifdef DEBUG_RELS
9687 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
9688 WriteStatement(stderr, statement, 6);
9689 error_reporter_end_flush();
9690 #endif
9691 return_value = ExecuteREL(inst,statement);
9692 /* ER expected to succeed or fail permanently,returning 1.
9693 * if it doesn't, this needs fixing.
9694 */
9695 break;
9696 case EXT:
9697 return_value = 1;
9698 if (!ExecuteEXT(inst,statement)) {
9699 WSEM(ASCERR,statement,"Impossible external relation encountered");
9700 }
9701 break;
9702 default:
9703 WSEM(ASCERR,statement,
9704 "Inappropriate statement type in declarative section relations");
9705 Asc_Panic(2, NULL, "Inappropriate statement type"
9706 " in declarative section relations");
9707 }
9708 assert(return_value);
9709 }
9710 }
9711
9712
9713 /* Note: this function must not be called until all the statements in sl
9714 * (except rel, ext)pass their checks.
9715 * This is because if any of the Executes fail
9716 * (returning 0) we abort (at least when assert is active) */
9717 static
9718 void Pass1ExecuteForStatements(struct Instance *inst,
9719 struct StatementList *sl)
9720 {
9721 struct Statement *statement;
9722 unsigned long c,len;
9723 int return_value = 0;
9724 struct gl_list_t *list;
9725 list = GetList(sl);
9726 len = gl_length(list);
9727 for(c=1;c<=len;c++){
9728 statement = (struct Statement *)gl_fetch(list,c);
9729 switch(StatementType(statement)){
9730 case ALIASES:
9731 return_value = ExecuteALIASES(inst,statement);
9732 break;
9733 case ARR:
9734 return_value = ExecuteARR(inst,statement);
9735 break;
9736 case ISA:
9737 return_value = ExecuteISA(inst,statement);
9738 break;
9739 case IRT:
9740 return_value = ExecuteIRT(inst,statement);
9741 break;
9742 case ATS:
9743 return_value = ExecuteATS(inst,statement);
9744 break;
9745 case AA:
9746 return_value = ExecuteAA(inst,statement);
9747 break;
9748 case FOR:
9749 return_value = 1;
9750 Pass1RealExecuteFOR(inst,statement);
9751 break;
9752 case REL:
9753 case CALL:
9754 case EXT:
9755 case ASGN: /* ignore'm */
9756 case LOGREL:
9757 case COND:
9758 case WHEN:
9759 return_value = 1; /* ignore'm until pass 2, 3 or 4 */
9760 break;
9761 case REF:
9762 return_value = ExecuteREF(inst,statement);
9763 break;
9764 case CASGN:
9765 return_value = ExecuteCASGN(inst,statement);
9766 break;
9767 case FNAME:
9768 WSEM(ASCERR,statement,
9769 "FNAME statements are only allowed inside a WHEN Statement");
9770 return_value = 0;
9771 break;
9772 case SELECT:
9773 WSEM(ASCERR,statement,
9774 "SELECT statements are not allowed inside a FOR Statement");
9775 return_value = 0;
9776 break;
9777 default:
9778 WSEM(ASCERR,statement,
9779 "Inappropriate statement type in declarative section");
9780 Asc_Panic(2, NULL,
9781 "Inappropriate statement type in declarative section");
9782 }
9783 assert(return_value);
9784 }
9785 }
9786
9787
9788 /*
9789 * Execute UnSelected statements inside a FOR loop
9790 * Note that we are not expanding arrays. This actually
9791 * may be impossible even if we want to do it.
9792 */
9793
9794 static
9795 int ExecuteUnSelectedForStatements(struct Instance *inst,
9796 struct StatementList *sl)
9797 {
9798 struct Statement *statement;
9799 unsigned long c,len;
9800 int return_value;
9801 struct gl_list_t *list;
9802 list = GetList(sl);
9803 len = gl_length(list);
9804 for(c=1;c<=len;c++){
9805 statement = (struct Statement *)gl_fetch(list,c);
9806 switch(StatementType(statement)){
9807 case ARR:
9808 case IRT:
9809 case ATS:
9810 case AA:
9811 case CALL:
9812 case EXT:
9813 case CASGN:
9814 case ASGN:
9815 return_value = 1;
9816 break;
9817 case FNAME:
9818 if (g_iteration>=MAXNUMBER) {
9819 WSEM(ASCERR,statement,
9820 "FNAME not allowed inside a SELECT Statement");
9821 }
9822 return_value = 1; /*ignore it */
9823 break;
9824 case ALIASES:
9825 return_value = ExecuteUnSelectedALIASES(inst,statement);
9826 break;
9827 case ISA:
9828 return_value = ExecuteUnSelectedISA(inst,statement);
9829 break;
9830 case FOR:
9831 return_value = ExecuteUnSelectedForStatements(inst,
9832 ForStatStmts(statement));
9833 break;
9834 case REL:
9835 case LOGREL:
9836 return_value = ExecuteUnSelectedEQN(inst,statement);
9837 break;
9838 case WHEN:
9839 return_value = ExecuteUnSelectedWHEN(inst,statement);
9840 break;
9841 case COND:
9842 WSEM(ASCERR,statement,
9843 "CONDITIONAL not allowed inside a FOR loop. Try FOR inside COND");
9844 Asc_Panic(2, NULL, "CONDITIONAL not allowed inside a FOR loop."
9845 " Try FOR inside COND");
9846 case SELECT:
9847 WSEM(ASCERR,statement, "SELECT not allowed inside a FOR Statement");
9848 Asc_Panic(2, NULL, "SELECT not allowed inside a FOR Statement");
9849 break;
9850 default:
9851 WSEM(stderr,statement,
9852 "Inappropriate statement type in declarative section unSEL FOR");
9853 Asc_Panic(2, NULL, "Inappropriate statement type in"
9854 " declarative section unSEL FOR");
9855 }
9856 }
9857 return 1;
9858 }
9859
9860
9861
9862 static
9863 int Pass4RealExecuteFOR(struct Instance *inst, struct Statement *statement)
9864 {
9865 symchar *name;
9866 struct Expr *ex;
9867 struct StatementList *sl;
9868 unsigned long c,len;
9869 struct value_t value;
9870 struct set_t *sptr;
9871 struct for_var_t *fv;
9872 name = ForStatIndex(statement);
9873 ex = ForStatExpr(statement);
9874 sl = ForStatStmts(statement);
9875 if (FindForVar(GetEvaluationForTable(),name)){ /* duplicated for variable */
9876 WSEM(ASCERR,statement, "FOR construct uses duplicate index variable");
9877 return 0;
9878 }
9879 assert(GetEvaluationContext()==NULL);
9880 SetEvaluationContext(inst);
9881 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
9882 SetEvaluationContext(NULL);
9883 switch(ValueKind(value)){
9884 case error_value:
9885 switch(ErrorValue(value)){
9886 case name_unfound:
9887 case undefined_value:
9888 DestroyValue(&value);
9889 WSEM(ASCERR,statement, "Phase 4 FOR has undefined values");
9890 return 0;
9891 default:
9892 WriteForValueError(statement,value);
9893 DestroyValue(&value);
9894 return 0;
9895 }
9896 case real_value:
9897 case integer_value:
9898 case symbol_value:
9899 case boolean_value:
9900 case list_value:
9901 WriteStatement(ASCERR,statement,0);
9902 FPRINTF(ASCERR,"FOR expression returns the wrong type.\n");
9903 DestroyValue(&value);
9904 return 0;
9905 case set_value:
9906 sptr = SetValue(value);
9907 switch(SetKind(sptr)){
9908 case empty_set: break;
9909 case integer_set:
9910 fv = CreateForVar(name);
9911 SetForVarType(fv,f_integer);
9912 AddLoopVariable(GetEvaluationForTable(),fv);
9913 len = Cardinality(sptr);
9914 for(c=1;c<=len;c++){
9915 SetForInteger(fv,FetchIntMember(sptr,c));
9916 if (!Pass4ExecuteForStatements(inst,sl)) {
9917 RemoveForVariable(GetEvaluationForTable());
9918 DestroyValue(&value);
9919 return 0 ;
9920 /* currently designed to always succeed or fail permanently */
9921 }
9922 }
9923 RemoveForVariable(GetEvaluationForTable());
9924 break;
9925 case string_set:
9926 fv = CreateForVar(name);
9927 SetForVarType(fv,f_symbol);
9928 AddLoopVariable(GetEvaluationForTable(),fv);
9929 len = Cardinality(sptr);
9930 for(c=1;c<=len;c++){
9931 SetForSymbol(fv,FetchStrMember(sptr,c));
9932 if (!Pass4ExecuteForStatements(inst,sl)) {
9933 RemoveForVariable(GetEvaluationForTable());
9934 DestroyValue(&value);
9935 return 0 ;
9936 /* currently designed to always succeed or fail permanently */
9937 }
9938 }
9939 RemoveForVariable(GetEvaluationForTable());
9940 break;
9941 }
9942 DestroyValue(&value);
9943 }
9944 /* currently designed to always succeed or fail permanently.
9945 * We reached this point meaning we've processed everything.
9946 * Therefore the statment returns 1 and becomes no longer pending.
9947 */
9948 return 1;
9949 }
9950
9951 static
9952 void MakeRealWhenCaseReferencesFOR(struct Instance *inst,
9953 struct Instance *child,
9954 struct Statement *statement,
9955 struct gl_list_t *listref)
9956 {
9957 symchar *name;
9958 struct Expr *ex;
9959 struct StatementList *sl;
9960 unsigned long c,len;
9961 struct value_t value;
9962 struct set_t *sptr;
9963 struct for_var_t *fv;
9964 name = ForStatIndex(statement);
9965 ex = ForStatExpr(statement);
9966 sl = ForStatStmts(statement);
9967 if (FindForVar(GetEvaluationForTable(),name)){ /* duplicated for variable */
9968 WSEM(ASCERR,statement, "FOR construct uses duplicate index variable");
9969 return ;
9970 }
9971 assert(GetEvaluationContext()==NULL);
9972 SetEvaluationContext(inst);
9973 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
9974 SetEvaluationContext(NULL);
9975 switch(ValueKind(value)){
9976 case error_value:
9977 switch(ErrorValue(value)){
9978 case name_unfound:
9979 case undefined_value:
9980 DestroyValue(&value);
9981 WSEM(ASCERR,statement, "Phase 2 FOR has undefined values");
9982 break;
9983 default:
9984 WriteForValueError(statement,value);
9985 DestroyValue(&value);
9986 break;
9987 }
9988 case real_value:
9989 case integer_value:
9990 case symbol_value:
9991 case boolean_value:
9992 case list_value:
9993 WriteStatement(ASCERR,statement,0);
9994 FPRINTF(ASCERR,"FOR expression returns the wrong type.\n");
9995 DestroyValue(&value);
9996 break;
9997 case set_value:
9998 sptr = SetValue(value);
9999 switch(SetKind(sptr)){
10000 case empty_set: break;
10001 case integer_set:
10002 fv = CreateForVar(name);
10003 SetForVarType(fv,f_integer);
10004 AddLoopVariable(GetEvaluationForTable(),fv);
10005 len = Cardinality(sptr);
10006 for(c=1;c<=len;c++){
10007 SetForInteger(fv,FetchIntMember(sptr,c));
10008 MakeRealWhenCaseReferencesList(inst,child,sl,listref);
10009 }
10010 RemoveForVariable(GetEvaluationForTable());
10011 break;
10012 case string_set:
10013 fv = CreateForVar(name);
10014 SetForVarType(fv,f_symbol);
10015 AddLoopVariable(GetEvaluationForTable(),fv);
10016 len = Cardinality(sptr);
10017 for(c=1;c<=len;c++){
10018 SetForSymbol(fv,FetchStrMember(sptr,c));
10019 MakeRealWhenCaseReferencesList(inst,child,sl,listref);
10020 }
10021 RemoveForVariable(GetEvaluationForTable());
10022 break;
10023 }
10024 DestroyValue(&value);
10025 }
10026 }
10027
10028 /* this function needs to be made much less aggressive about exiting
10029 * and more verbose about error messages so we can skip the np3checkfor
10030 * probably also means it needs the 0/1 fail/succeed return code.
10031 */
10032 static
10033 int Pass3RealExecuteFOR(struct Instance *inst, struct Statement *statement)
10034 {
10035 symchar *name;
10036 struct Expr *ex;
10037 struct StatementList *sl;
10038 unsigned long c,len;
10039 struct value_t value;
10040 struct set_t *sptr;
10041 struct for_var_t *fv;
10042 name = ForStatIndex(statement);
10043 ex = ForStatExpr(statement);
10044 sl = ForStatStmts(statement);
10045 if (FindForVar(GetEvaluationForTable(),name)){ /* duplicated for variable */
10046 WSEM(ASCERR,statement, "FOR construct uses duplicate index variable");
10047 return 0;
10048 }
10049 assert(GetEvaluationContext()==NULL);
10050 SetEvaluationContext(inst);
10051 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
10052 SetEvaluationContext(NULL);
10053 switch(ValueKind(value)){
10054 case error_value:
10055 switch(ErrorValue(value)){
10056 case name_unfound:
10057 case undefined_value:
10058 DestroyValue(&value);
10059 WSEM(ASCERR,statement, "Phase 3 FOR has undefined values");
10060 return 0;
10061 default:
10062 WriteForValueError(statement,value);
10063 DestroyValue(&value);
10064 return 0;
10065 }
10066 case real_value:
10067 case integer_value:
10068 case symbol_value:
10069 case boolean_value:
10070 case list_value:
10071 WriteStatement(ASCERR,statement,0);
10072 FPRINTF(ASCERR,"FOR expression returns the wrong type.\n");
10073 DestroyValue(&value);
10074 return 0;
10075 case set_value:
10076 sptr = SetValue(value);
10077 switch(SetKind(sptr)){
10078 case empty_set: break;
10079 case integer_set:
10080 fv = CreateForVar(name);
10081 SetForVarType(fv,f_integer);
10082 AddLoopVariable(GetEvaluationForTable(),fv);
10083 len = Cardinality(sptr);
10084 for(c=1;c<=len;c++){
10085 SetForInteger(fv,FetchIntMember(sptr,c));
10086 if (!Pass3ExecuteForStatements(inst,sl)) return 0;
10087 }
10088 RemoveForVariable(GetEvaluationForTable());
10089 break;
10090 case string_set:
10091 fv = CreateForVar(name);
10092 SetForVarType(fv,f_symbol);
10093 AddLoopVariable(GetEvaluationForTable(),fv);
10094 len = Cardinality(sptr);
10095 for(c=1;c<=len;c++){
10096 SetForSymbol(fv,FetchStrMember(sptr,c));
10097 if (!Pass3ExecuteForStatements(inst,sl)) return 0;
10098 }
10099 RemoveForVariable(GetEvaluationForTable());
10100 break;
10101 }
10102 DestroyValue(&value);
10103 }
10104 return 1;
10105 }
10106
10107
10108 static
10109 void Pass3FORMarkCondLogRels(struct Instance *inst,
10110 struct Statement *statement)
10111 {
10112 symchar *name;
10113 struct Expr *ex;
10114 struct StatementList *sl;
10115 unsigned long c,len;
10116 struct value_t value;
10117 struct set_t *sptr;
10118 struct for_var_t *fv;
10119 name = ForStatIndex(statement);
10120 ex = ForStatExpr(statement);
10121 sl = ForStatStmts(statement);
10122 if (FindForVar(GetEvaluationForTable(),name)){ /* duplicated for variable */
10123 WSEM(ASCERR,statement, "FOR construct uses duplicate index variable");
10124 return ;
10125 }
10126 assert(GetEvaluationContext()==NULL);
10127 SetEvaluationContext(inst);
10128 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
10129 SetEvaluationContext(NULL);
10130 switch(ValueKind(value)){
10131 case error_value:
10132 switch(ErrorValue(value)){
10133 case name_unfound:
10134 case undefined_value:
10135 DestroyValue(&value);
10136 WSEM(ASCERR,statement, "Phase 3 FOR has undefined values");
10137 break;
10138 default:
10139 WriteForValueError(statement,value);
10140 DestroyValue(&value);
10141 break;
10142 }
10143 case real_value:
10144 case integer_value:
10145 case symbol_value:
10146 case boolean_value:
10147 case list_value:
10148 WriteStatement(ASCERR,statement,0);
10149 FPRINTF(ASCERR,"FOR expression returns the wrong type.\n");
10150 DestroyValue(&value);
10151 break;
10152 case set_value:
10153 sptr = SetValue(value);
10154 switch(SetKind(sptr)){
10155 case empty_set: break;
10156 case integer_set:
10157 fv = CreateForVar(name);
10158 SetForVarType(fv,f_integer);
10159 AddLoopVariable(GetEvaluationForTable(),fv);
10160 len = Cardinality(sptr);
10161 for(c=1;c<=len;c++){
10162 SetForInteger(fv,FetchIntMember(sptr,c));
10163 Pass3MarkCondLogRelStatList(inst,sl);
10164 }
10165 RemoveForVariable(GetEvaluationForTable());
10166 break;
10167 case string_set:
10168 fv = CreateForVar(name);
10169 SetForVarType(fv,f_symbol);
10170 AddLoopVariable(GetEvaluationForTable(),fv);
10171 len = Cardinality(sptr);
10172 for(c=1;c<=len;c++){
10173 SetForSymbol(fv,FetchStrMember(sptr,c));
10174 Pass3MarkCondLogRelStatList(inst,sl);
10175 }
10176 RemoveForVariable(GetEvaluationForTable());
10177 break;
10178 }
10179 DestroyValue(&value);
10180 }
10181 }
10182
10183 static
10184 void Pass3FORMarkCond(struct Instance *inst, struct Statement *statement)
10185 {
10186 struct for_table_t *SavedForTable;
10187
10188 SavedForTable = GetEvaluationForTable();
10189 SetEvaluationForTable(CreateForTable());
10190 Pass3FORMarkCondLogRels(inst,statement);
10191 DestroyForTable(GetEvaluationForTable());
10192 SetEvaluationForTable(SavedForTable);
10193 }
10194
10195
10196 /* this function needs to be made much less aggressive about exiting
10197 * and more verbose about error messages so we can skip the np2checkfor
10198 * probably also means it needs the 0/1 fail/succeed return code.
10199 */
10200 static
10201 int Pass2RealExecuteFOR(struct Instance *inst, struct Statement *statement)
10202 {
10203 symchar *name;
10204 struct Expr *ex;
10205 struct StatementList *sl;
10206 unsigned long c,len;
10207 struct value_t value;
10208 struct set_t *sptr;
10209 struct for_var_t *fv;
10210 name = ForStatIndex(statement);
10211 ex = ForStatExpr(statement);
10212 sl = ForStatStmts(statement);
10213 if (FindForVar(GetEvaluationForTable(),name)){ /* duplicated for variable */
10214 WSEM(ASCERR,statement, "FOR construct uses duplicate index variable");
10215 return 0;
10216 }
10217 assert(GetEvaluationContext()==NULL);
10218 SetEvaluationContext(inst);
10219 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
10220 SetEvaluationContext(NULL);
10221 switch(ValueKind(value)){
10222 case error_value:
10223 switch(ErrorValue(value)){
10224 case name_unfound:
10225 case undefined_value:
10226 DestroyValue(&value);
10227 WSEM(ASCERR,statement, "Phase 2 FOR has undefined values");
10228 return 0;
10229 default:
10230 WriteForValueError(statement,value);
10231 DestroyValue(&value);
10232 return 0;
10233 }
10234 case real_value:
10235 case integer_value:
10236 case symbol_value:
10237 case boolean_value:
10238 case list_value:
10239 WriteStatement(ASCERR,statement,0);
10240 FPRINTF(ASCERR,"FOR expression returns the wrong type.\n");
10241 DestroyValue(&value);
10242 return 0;
10243 case set_value:
10244 sptr = SetValue(value);
10245 switch(SetKind(sptr)){
10246 case empty_set:
10247 #ifdef DEBUG_RELS
10248 FPRINTF(stderr,"Pass2RealExecuteFOR empty_set.\n");
10249 #endif
10250 break;
10251 case integer_set:
10252 fv = CreateForVar(name);
10253 SetForVarType(fv,f_integer);
10254 AddLoopVariable(GetEvaluationForTable(),fv);
10255 len = Cardinality(sptr);
10256 #ifdef DEBUG_RELS
10257 FPRINTF(stderr,"Pass2RealExecuteFOR integer_set %lu.\n",len);
10258 #endif
10259 for(c=1;c<=len;c++){
10260 SetForInteger(fv,FetchIntMember(sptr,c));
10261 Pass2ExecuteForStatements(inst,sl);
10262 /* currently designed to always succeed or fail permanently */
10263 }
10264 RemoveForVariable(GetEvaluationForTable());
10265 break;
10266 case string_set:
10267 fv = CreateForVar(name);
10268 SetForVarType(fv,f_symbol);
10269 AddLoopVariable(GetEvaluationForTable(),fv);
10270 len = Cardinality(sptr);
10271 #ifdef DEBUG_RELS
10272 FPRINTF(stderr,"Pass2RealExecuteFOR string_set %lu.\n",len);
10273 #endif
10274 for(c=1;c<=len;c++){
10275 SetForSymbol(fv,FetchStrMember(sptr,c));
10276 Pass2ExecuteForStatements(inst,sl);
10277 /* currently designed to always succeed or fail permanently */
10278 }
10279 RemoveForVariable(GetEvaluationForTable());
10280 break;
10281 }
10282 DestroyValue(&value);
10283 }
10284 /* currently designed to always succeed or fail permanently.
10285 * We reached this point meaning we've processed everything.
10286 * Therefore the statment returns 1 and becomes no longer pending.
10287 */
10288 return 1;
10289 }
10290
10291 static
10292 void Pass2FORMarkCondRelations(struct Instance *inst,
10293 struct Statement *statement)
10294 {
10295 symchar *name;
10296 struct Expr *ex;
10297 struct StatementList *sl;
10298 unsigned long c,len;
10299 struct value_t value;
10300 struct set_t *sptr;
10301 struct for_var_t *fv;
10302 name = ForStatIndex(statement);
10303 ex = ForStatExpr(statement);
10304 sl = ForStatStmts(statement);
10305 if (FindForVar(GetEvaluationForTable(),name)){ /* duplicated for variable */
10306 WSEM(ASCERR,statement, "FOR construct uses duplicate index variable");
10307 return ;
10308 }
10309 assert(GetEvaluationContext()==NULL);
10310 SetEvaluationContext(inst);
10311 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
10312 SetEvaluationContext(NULL);
10313 switch(ValueKind(value)){
10314 case error_value:
10315 switch(ErrorValue(value)){
10316 case name_unfound:
10317 case undefined_value:
10318 DestroyValue(&value);
10319 WSEM(ASCERR,statement, "Phase 2 FOR has undefined values");
10320 break;
10321 default:
10322 WriteForValueError(statement,value);
10323 DestroyValue(&value);
10324 break;
10325 }
10326 case real_value:
10327 case integer_value:
10328 case symbol_value:
10329 case boolean_value:
10330 case list_value:
10331 WriteStatement(ASCERR,statement,0);
10332 FPRINTF(ASCERR,"FOR expression returns the wrong type.\n");
10333 DestroyValue(&value);
10334 break;
10335 case set_value:
10336 sptr = SetValue(value);
10337 switch(SetKind(sptr)){
10338 case empty_set: break;
10339 case integer_set:
10340 fv = CreateForVar(name);
10341 SetForVarType(fv,f_integer);
10342 AddLoopVariable(GetEvaluationForTable(),fv);
10343 len = Cardinality(sptr);
10344 for(c=1;c<=len;c++){
10345 SetForInteger(fv,FetchIntMember(sptr,c));
10346 Pass2MarkCondRelStatList(inst,sl);
10347 }
10348 RemoveForVariable(GetEvaluationForTable());
10349 break;
10350 case string_set:
10351 fv = CreateForVar(name);
10352 SetForVarType(fv,f_symbol);
10353 AddLoopVariable(GetEvaluationForTable(),fv);
10354 len = Cardinality(sptr);
10355 for(c=1;c<=len;c++){
10356 SetForSymbol(fv,FetchStrMember(sptr,c));
10357 Pass2MarkCondRelStatList(inst,sl);
10358 }
10359 RemoveForVariable(GetEvaluationForTable());
10360 break;
10361 }
10362 DestroyValue(&value);
10363 }
10364 }
10365
10366 static
10367 void Pass2FORMarkCond(struct Instance *inst, struct Statement *statement)
10368 {
10369 struct for_table_t *SavedForTable;
10370
10371 SavedForTable = GetEvaluationForTable();
10372 SetEvaluationForTable(CreateForTable());
10373 Pass2FORMarkCondRelations(inst,statement);
10374 DestroyForTable(GetEvaluationForTable());
10375 SetEvaluationForTable(SavedForTable);
10376 }
10377
10378 static
10379 void Pass1RealExecuteFOR(struct Instance *inst, struct Statement *statement)
10380 {
10381 symchar *name;
10382 struct Expr *ex;
10383 struct StatementList *sl;
10384 unsigned long c,len;
10385 struct value_t value;
10386 struct set_t *sptr;
10387 struct for_var_t *fv;
10388 name = ForStatIndex(statement);
10389 ex = ForStatExpr(statement);
10390 sl = ForStatStmts(statement);
10391 if (FindForVar(GetEvaluationForTable(),name)){ /* duplicated for variable */
10392 WSEM(ASCERR,statement, "FOR construct uses duplicate index variable");
10393 return;
10394 }
10395 assert(GetEvaluationContext()==NULL);
10396 SetEvaluationContext(inst);
10397 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
10398 SetEvaluationContext(NULL);
10399 switch(ValueKind(value)){
10400 case error_value:
10401 switch(ErrorValue(value)){
10402 case name_unfound:
10403 case undefined_value:
10404 DestroyValue(&value);
10405 WSEM(ASCERR,statement, "FOR has undefined values");
10406 Asc_Panic(2, NULL, "FOR has undefined values");
10407 default:
10408 WriteForValueError(statement,value);
10409 DestroyValue(&value);
10410 return;
10411 }
10412 case real_value:
10413 case integer_value:
10414 case symbol_value:
10415 case boolean_value:
10416 case list_value:
10417 WriteStatement(ASCERR,statement,0);
10418 FPRINTF(ASCERR,"FOR expression returns the wrong type.\n");
10419 DestroyValue(&value);
10420 return;
10421 case set_value:
10422 sptr = SetValue(value);
10423 switch(SetKind(sptr)){
10424 case empty_set: break;
10425 case integer_set:
10426 fv = CreateForVar(name);
10427 SetForVarType(fv,f_integer);
10428 AddLoopVariable(GetEvaluationForTable(),fv);
10429 len = Cardinality(sptr);
10430 for(c=1;c<=len;c++){
10431 SetForInteger(fv,FetchIntMember(sptr,c));
10432 Pass1ExecuteForStatements(inst,sl);
10433 }
10434 RemoveForVariable(GetEvaluationForTable());
10435 break;
10436 case string_set:
10437 fv = CreateForVar(name);
10438 SetForVarType(fv,f_symbol);
10439 AddLoopVariable(GetEvaluationForTable(),fv);
10440 len = Cardinality(sptr);
10441 for(c=1;c<=len;c++){
10442 SetForSymbol(fv,FetchStrMember(sptr,c));
10443 Pass1ExecuteForStatements(inst,sl);
10444 }
10445 RemoveForVariable(GetEvaluationForTable());
10446 break;
10447 }
10448 DestroyValue(&value);
10449 }
10450 }
10451
10452 static
10453 int Pass4CheckFOR(struct Instance *inst, struct Statement *statement)
10454 {
10455 symchar *name;
10456 struct Expr *ex;
10457 struct StatementList *sl;
10458 unsigned long c,len;
10459 struct value_t value;
10460 struct set_t *sptr;
10461 struct for_var_t *fv;
10462 name = ForStatIndex(statement);
10463 ex = ForStatExpr(statement);
10464 sl = ForStatStmts(statement);
10465 if (FindForVar(GetEvaluationForTable(),name)) return 1; /* will give error */
10466 assert(GetEvaluationContext()==NULL);
10467 SetEvaluationContext(inst);
10468 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
10469 SetEvaluationContext(NULL);
10470 switch(ValueKind(value)){
10471 case error_value:
10472 switch(ErrorValue(value)){
10473 case name_unfound:
10474 case undefined_value:
10475 DestroyValue(&value);
10476 return 0;
10477 default:
10478 DestroyValue(&value);
10479 return 1; /* will give an error */
10480 }
10481 case real_value:
10482 case integer_value:
10483 case symbol_value:
10484 case boolean_value:
10485 case list_value:
10486 DestroyValue(&value);
10487 return 1; /* will give error */
10488 case set_value: /* okay thus far */
10489 sptr = SetValue(value);
10490 switch(SetKind(sptr)){
10491 case empty_set: break; /* always okay */
10492 case integer_set:
10493 fv = CreateForVar(name);
10494 SetForVarType(fv,f_integer);
10495 AddLoopVariable(GetEvaluationForTable(),fv);
10496 len = Cardinality(sptr);
10497 for(c=1;c<=len;c++){
10498 SetForInteger(fv,FetchIntMember(sptr,c));
10499 if (!Pass4CheckStatementList(inst,sl)){
10500 RemoveForVariable(GetEvaluationForTable());
10501 DestroyValue(&value);
10502 return 0;
10503 }
10504 }
10505 RemoveForVariable(GetEvaluationForTable());
10506 break;
10507 case string_set:
10508 fv = CreateForVar(name);
10509 SetForVarType(fv,f_symbol);
10510 AddLoopVariable(GetEvaluationForTable(),fv);
10511 len = Cardinality(sptr);
10512 for(c=1;c<=len;c++){
10513 SetForSymbol(fv,FetchStrMember(sptr,c));
10514 if (!Pass4CheckStatementList(inst,sl)){
10515 RemoveForVariable(GetEvaluationForTable());
10516 DestroyValue(&value);
10517 return 0;
10518 }
10519 }
10520 RemoveForVariable(GetEvaluationForTable());
10521 break;
10522 }
10523 DestroyValue(&value);
10524 return 1; /* everything checks out */
10525 }
10526 /*NOTREACHED*/
10527 return 0; /* we here? */
10528 }
10529
10530 static
10531 int Pass4RealCheckFOR (struct Instance *inst, struct Statement *statement)
10532 {
10533 struct for_table_t *SavedForTable;
10534 SavedForTable = GetEvaluationForTable();
10535 SetEvaluationForTable(CreateForTable());
10536 if (Pass4CheckFOR(inst,statement)) {
10537 DestroyForTable(GetEvaluationForTable());
10538 SetEvaluationForTable(SavedForTable);
10539 return 1;
10540 }
10541 else {
10542 DestroyForTable(GetEvaluationForTable());
10543 SetEvaluationForTable(SavedForTable);
10544 return 0;
10545 }
10546 }
10547
10548 static
10549 int Pass3CheckFOR(struct Instance *inst, struct Statement *statement)
10550 {
10551 symchar *name;
10552 struct Expr *ex;
10553 struct StatementList *sl;
10554 unsigned long c,len;
10555 struct value_t value;
10556 struct set_t *sptr;
10557 struct for_var_t *fv;
10558 name = ForStatIndex(statement);
10559 ex = ForStatExpr(statement);
10560 sl = ForStatStmts(statement);
10561 if (FindForVar(GetEvaluationForTable(),name)) {
10562 return 1; /* will give error */
10563 }
10564 assert(GetEvaluationContext()==NULL);
10565 SetEvaluationContext(inst);
10566 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
10567 SetEvaluationContext(NULL);
10568 switch(ValueKind(value)){
10569 case error_value:
10570 switch(ErrorValue(value)){
10571 case name_unfound:
10572 case undefined_value:
10573 DestroyValue(&value);
10574 return 0;
10575 default:
10576 DestroyValue(&value);
10577 return 1; /* will give an error */
10578 }
10579 case real_value:
10580 case integer_value:
10581 case symbol_value:
10582 case boolean_value:
10583 case list_value:
10584 DestroyValue(&value);
10585 return 1; /* will give error */
10586 case set_value: /* okay thus far */
10587 sptr = SetValue(value);
10588 switch(SetKind(sptr)){
10589 case empty_set: break; /* always okay */
10590 case integer_set:
10591 fv = CreateForVar(name);
10592 SetForVarType(fv,f_integer);
10593 AddLoopVariable(GetEvaluationForTable(),fv);
10594 len = Cardinality(sptr);
10595 for(c=1;c<=len;c++){
10596 SetForInteger(fv,FetchIntMember(sptr,c));
10597 if (!Pass3CheckStatementList(inst,sl)){
10598 RemoveForVariable(GetEvaluationForTable());
10599 DestroyValue(&value);
10600 return 0;
10601 }
10602 }
10603 RemoveForVariable(GetEvaluationForTable());
10604 break;
10605 case string_set:
10606 fv = CreateForVar(name);
10607 SetForVarType(fv,f_symbol);
10608 AddLoopVariable(GetEvaluationForTable(),fv);
10609 len = Cardinality(sptr);
10610 for(c=1;c<=len;c++){
10611 SetForSymbol(fv,FetchStrMember(sptr,c));
10612 if (!Pass3CheckStatementList(inst,sl)){
10613 RemoveForVariable(GetEvaluationForTable());
10614 DestroyValue(&value);
10615 return 0;
10616 }
10617 }
10618 RemoveForVariable(GetEvaluationForTable());
10619 break;
10620 }
10621 DestroyValue(&value);
10622 return 1; /* everything checks out */
10623 }
10624 /*NOTREACHED*/
10625 return 0; /* we here? */
10626 }
10627
10628 static
10629 int Pass3RealCheckFOR (struct Instance *inst, struct Statement *statement)
10630 {
10631 struct for_table_t *SavedForTable;
10632 SavedForTable = GetEvaluationForTable();
10633 SetEvaluationForTable(CreateForTable());
10634 if (Pass3CheckFOR(inst,statement)) {
10635 DestroyForTable(GetEvaluationForTable());
10636 SetEvaluationForTable(SavedForTable);
10637 return 1;
10638 } else {
10639 DestroyForTable(GetEvaluationForTable());
10640 SetEvaluationForTable(SavedForTable);
10641 return 0;
10642 }
10643 }
10644
10645
10646 /* a currently unused function, with therefore unused subsidiary functions */
10647 static
10648 int Pass2CheckFOR(struct Instance *inst, struct Statement *statement)
10649 {
10650 symchar *name;
10651 struct Expr *ex;
10652 struct StatementList *sl;
10653 unsigned long c,len;
10654 struct value_t value;
10655 struct set_t *sptr;
10656 struct for_var_t *fv;
10657 name = ForStatIndex(statement);
10658 ex = ForStatExpr(statement);
10659 sl = ForStatStmts(statement);
10660 if (FindForVar(GetEvaluationForTable(),name)) return 1; /* will give error */
10661 assert(GetEvaluationContext()==NULL);
10662 SetEvaluationContext(inst);
10663 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
10664 SetEvaluationContext(NULL);
10665 switch(ValueKind(value)){
10666 case error_value:
10667 switch(ErrorValue(value)){
10668 case name_unfound:
10669 case undefined_value:
10670 DestroyValue(&value);
10671 return 0;
10672 default:
10673 DestroyValue(&value);
10674 return 1; /* will give an error */
10675 }
10676 case real_value:
10677 case integer_value:
10678 case symbol_value:
10679 case boolean_value:
10680 case list_value:
10681 DestroyValue(&value);
10682 return 1; /* will give error */
10683 case set_value: /* okay thus far */
10684 sptr = SetValue(value);
10685 switch(SetKind(sptr)){
10686 case empty_set: break; /* always okay */
10687 case integer_set:
10688 fv = CreateForVar(name);
10689 SetForVarType(fv,f_integer);
10690 AddLoopVariable(GetEvaluationForTable(),fv);
10691 len = Cardinality(sptr);
10692 for(c=1;c<=len;c++){
10693 SetForInteger(fv,FetchIntMember(sptr,c));
10694 if (!Pass2CheckStatementList(inst,sl)){
10695 RemoveForVariable(GetEvaluationForTable());
10696 DestroyValue(&value);
10697 return 0;
10698 }
10699 }
10700 RemoveForVariable(GetEvaluationForTable());
10701 break;
10702 case string_set:
10703 fv = CreateForVar(name);
10704 SetForVarType(fv,f_symbol);
10705 AddLoopVariable(GetEvaluationForTable(),fv);
10706 len = Cardinality(sptr);
10707 for(c=1;c<=len;c++){
10708 SetForSymbol(fv,FetchStrMember(sptr,c));
10709 if (!Pass2CheckStatementList(inst,sl)){
10710 RemoveForVariable(GetEvaluationForTable());
10711 DestroyValue(&value);
10712 return 0;
10713 }
10714 }
10715 RemoveForVariable(GetEvaluationForTable());
10716 break;
10717 }
10718 DestroyValue(&value);
10719 return 1; /* everything checks out */
10720 }
10721 /*NOTREACHED*/
10722 return 0; /* we here? */
10723 }
10724
10725 static
10726 int Pass2RealCheckFOR (struct Instance *inst, struct Statement *statement)
10727 {
10728 struct for_table_t *SavedForTable;
10729 SavedForTable = GetEvaluationForTable();
10730 SetEvaluationForTable(CreateForTable());
10731 if (Pass2CheckFOR(inst,statement)) {
10732 DestroyForTable(GetEvaluationForTable());
10733 SetEvaluationForTable(SavedForTable);
10734 return 1;
10735 }
10736 else {
10737 DestroyForTable(GetEvaluationForTable());
10738 SetEvaluationForTable(SavedForTable);
10739 return 0;
10740 }
10741 }
10742
10743 /* checks every statement against every value of the loop index */
10744 static
10745 int Pass1CheckFOR(struct Instance *inst, struct Statement *statement)
10746 {
10747 symchar *name;
10748 struct Expr *ex;
10749 struct StatementList *sl;
10750 unsigned long c,len;
10751 struct value_t value;
10752 struct set_t *sptr;
10753 struct for_var_t *fv;
10754 name = ForStatIndex(statement);
10755 ex = ForStatExpr(statement);
10756 sl = ForStatStmts(statement);
10757 if (FindForVar(GetEvaluationForTable(),name)) return 1; /* will give error */
10758 assert(GetEvaluationContext()==NULL);
10759 SetEvaluationContext(inst);
10760 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
10761 SetEvaluationContext(NULL);
10762 switch(ValueKind(value)){
10763 case error_value:
10764 switch(ErrorValue(value)){
10765 case name_unfound:
10766 case undefined_value:
10767 DestroyValue(&value);
10768 return 0;
10769 default:
10770 DestroyValue(&value);
10771 return 1; /* will give an error */
10772 }
10773 case real_value:
10774 case integer_value:
10775 case symbol_value:
10776 case boolean_value:
10777 case list_value:
10778 DestroyValue(&value);
10779 return 1; /* will give error */
10780 case set_value: /* okay thus far */
10781 sptr = SetValue(value);
10782 switch(SetKind(sptr)){
10783 case empty_set: break; /* always okay */
10784 case integer_set:
10785 fv = CreateForVar(name);
10786 SetForVarType(fv,f_integer);
10787 AddLoopVariable(GetEvaluationForTable(),fv);
10788 len = Cardinality(sptr);
10789 for(c=1;c<=len;c++){
10790 SetForInteger(fv,FetchIntMember(sptr,c));
10791 if (!Pass1CheckStatementList(inst,sl)){
10792 RemoveForVariable(GetEvaluationForTable());
10793 DestroyValue(&value);
10794 return 0;
10795 }
10796 }
10797 RemoveForVariable(GetEvaluationForTable());
10798 break;
10799 case string_set:
10800 fv = CreateForVar(name);
10801 SetForVarType(fv,f_symbol);
10802 AddLoopVariable(GetEvaluationForTable(),fv);
10803 len = Cardinality(sptr);
10804 for(c=1;c<=len;c++){
10805 SetForSymbol(fv,FetchStrMember(sptr,c));
10806 if (!Pass1CheckStatementList(inst,sl)){
10807 RemoveForVariable(GetEvaluationForTable());
10808 DestroyValue(&value);
10809 return 0;
10810 }
10811 }
10812 RemoveForVariable(GetEvaluationForTable());
10813 break;
10814 }
10815 DestroyValue(&value);
10816 return 1; /* everything checks out */
10817 }
10818 /*NOTREACHED*/
10819 return 0; /* we here? */
10820 }
10821
10822
10823 #ifdef THIS_IS_AN_UNUSED_FUNCTION
10824 static
10825 int Pass1RealCheckFOR(struct Instance *inst, struct Statement *statement)
10826 {
10827 struct for_table_t *SavedForTable;
10828 SavedForTable = GetEvaluationForTable();
10829 SetEvaluationForTable(CreateForTable());
10830 if (Pass1CheckFOR(inst,statement)){
10831 DestroyForTable(GetEvaluationForTable());
10832 SetEvaluationForTable(SavedForTable);
10833 return 1;
10834 } else {
10835 DestroyForTable(GetEvaluationForTable());
10836 SetEvaluationForTable(SavedForTable);
10837 return 0;
10838 }
10839 }
10840 #endif /* THIS_IS_AN_UNUSED_FUNCTION */
10841
10842
10843 static
10844 int Pass4ExecuteFOR(struct Instance *inst, struct Statement *statement)
10845 {
10846 struct for_table_t *SavedForTable;
10847 SavedForTable = GetEvaluationForTable();
10848 SetEvaluationForTable(CreateForTable());
10849 if ( Pass4RealExecuteFOR(inst,statement) ) {
10850 DestroyForTable(GetEvaluationForTable());
10851 SetEvaluationForTable(SavedForTable);
10852 return 1;
10853 }
10854 else{
10855 DestroyForTable(GetEvaluationForTable());
10856 SetEvaluationForTable(SavedForTable);
10857 return 0;
10858 }
10859 }
10860
10861 static
10862 void MakeWhenCaseReferencesFOR(struct Instance *inst,
10863 struct Instance *child,
10864 struct Statement *statement,
10865 struct gl_list_t *listref)
10866 {
10867 struct for_table_t *SavedForTable;
10868 SavedForTable = GetEvaluationForTable();
10869 SetEvaluationForTable(CreateForTable());
10870 MakeRealWhenCaseReferencesFOR(inst,child,statement,listref);
10871 DestroyForTable(GetEvaluationForTable());
10872 SetEvaluationForTable(SavedForTable);
10873 return;
10874 }
10875
10876 static
10877 int Pass3ExecuteFOR(struct Instance *inst, struct Statement *statement)
10878 {
10879 struct for_table_t *SavedForTable;
10880 SavedForTable = GetEvaluationForTable();
10881 SetEvaluationForTable(CreateForTable());
10882 if ( Pass3RealExecuteFOR(inst,statement) ) {
10883 DestroyForTable(GetEvaluationForTable());
10884 SetEvaluationForTable(SavedForTable);
10885 return 1;
10886 }
10887 else{
10888 DestroyForTable(GetEvaluationForTable());
10889 SetEvaluationForTable(SavedForTable);
10890 return 0;
10891 }
10892 }
10893
10894 static
10895 int Pass2ExecuteFOR(struct Instance *inst, struct Statement *statement)
10896 {
10897 struct for_table_t *SavedForTable;
10898 SavedForTable = GetEvaluationForTable();
10899 SetEvaluationForTable(CreateForTable());
10900 if ( Pass2RealExecuteFOR(inst,statement) ) {
10901 DestroyForTable(GetEvaluationForTable());
10902 SetEvaluationForTable(SavedForTable);
10903 return 1;
10904 }
10905 else{
10906 DestroyForTable(GetEvaluationForTable());
10907 SetEvaluationForTable(SavedForTable);
10908 return 0;
10909 }
10910 }
10911
10912 static
10913 int Pass1ExecuteFOR(struct Instance *inst, struct Statement *statement)
10914 {
10915 struct for_table_t *SavedForTable;
10916 SavedForTable = GetEvaluationForTable();
10917 SetEvaluationForTable(CreateForTable());
10918 if (Pass1CheckFOR(inst,statement)){
10919 Pass1RealExecuteFOR(inst,statement);
10920 DestroyForTable(GetEvaluationForTable());
10921 SetEvaluationForTable(SavedForTable);
10922 return 1;
10923 } else{
10924 DestroyForTable(GetEvaluationForTable());
10925 SetEvaluationForTable(SavedForTable);
10926 return 0;
10927 }
10928 }
10929
10930
10931
10932 /**************************************************************************\
10933 General Statement processing.
10934 \**************************************************************************/
10935 static
10936 int Pass4ExecuteStatement(struct Instance *inst,struct Statement *statement)
10937 {
10938 switch(StatementType(statement)){ /* should be a WHEN statement */
10939 case WHEN:
10940 return ExecuteWHEN(inst,statement);
10941 case FOR:
10942 return Pass4ExecuteFOR(inst,statement);
10943 default:
10944 return 1;
10945 /* For anything else but a WHEN and FOR statement */
10946 }
10947 }
10948
10949 static
10950 int Pass3ExecuteStatement(struct Instance *inst,struct Statement *statement)
10951 {
10952 switch(StatementType(statement)){ /* should be an if relinstance */
10953 case FOR:
10954 return Pass3ExecuteFOR(inst,statement);
10955 case LOGREL:
10956 return ExecuteLOGREL(inst,statement);
10957 case COND:
10958 return Pass3ExecuteCOND(inst,statement);
10959 case WHEN:
10960 return 1; /* assumed done */
10961 case FNAME:
10962 WSEM(ASCERR,statement,"FNAME are allowed only inside a WHEN statement");
10963 return 0;
10964 default:
10965 return 0;
10966 /* Nondeclarative statements flagged in pass3 */
10967 }
10968 }
10969
10970 static
10971 int Pass2ExecuteStatement(struct Instance *inst,struct Statement *statement)
10972 {
10973 switch(StatementType(statement)){ /* should be an if relinstance */
10974 case FOR:
10975 #ifdef DEBUG_RELS
10976 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
10977 WriteStatement(stderr, statement, 3);
10978 error_reporter_end_flush();
10979 #endif
10980 return Pass2ExecuteFOR(inst,statement);
10981 case REL:
10982 #ifdef DEBUG_RELS
10983 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
10984 WriteStatement(stderr, statement, 3);
10985 error_reporter_end_flush();
10986 #endif
10987 /* ER expected to succeed or fail permanently. this may change. */
10988 return ExecuteREL(inst,statement);
10989 case EXT:
10990 CONSOLE_DEBUG("ABOUT TO EXECUTEEXT");
10991 return ExecuteEXT(inst,statement);
10992 case COND:
10993 return Pass2ExecuteCOND(inst,statement);
10994 case LOGREL:
10995 case WHEN:
10996 #ifdef DEBUG_RELS
10997 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
10998 FPRINTF(stderr,"-- IGNORING WHEN STAT\n");
10999 /* write statement */
11000 WriteStatement(stderr, statement, 3);
11001 error_reporter_end_flush();
11002 #endif
11003 return 1; /* assumed done */
11004 case FNAME:
11005 WSEM(ASCERR,statement,"FNAME are allowed only inside a WHEN statement");
11006 return 0;
11007 default:
11008 return 0;
11009 /* Nondeclarative statements flagged in pass2 */
11010 }
11011 }
11012
11013 static
11014 int Pass1ExecuteStatement(struct Instance *inst, unsigned long *c,
11015 struct Statement *statement)
11016 {
11017 switch(StatementType(statement)){
11018 case ALIASES:
11019 return ExecuteALIASES(inst,statement);
11020 case ARR:
11021 return ExecuteARR(inst,statement);
11022 case ISA:
11023 return ExecuteISA(inst,statement);
11024 case IRT:
11025 return ExecuteIRT(inst,statement);
11026 case ATS:
11027 return ExecuteATS(inst,statement);
11028 case AA:
11029 return ExecuteAA(inst,statement);
11030 case FOR:
11031 return Pass1ExecuteFOR(inst,statement);
11032 case REL:
11033 return 1; /* automatically assume done */
11034 case CALL:
11035 case EXT:
11036 return 1; /* automatically assume done */
11037 case REF:
11038 return ExecuteREF(inst,statement);
11039 case CASGN:
11040 return ExecuteCASGN(inst,statement);
11041 case ASGN: /* don't do these in instantiation phase. just mark off */
11042 return 1;
11043 case LOGREL:
11044 return 1; /* automatically assume done */
11045 case COND:
11046 return 1;/* automatically assume done */
11047 case WHEN:
11048 return 1; /* automatically assume done */
11049 case FNAME:
11050 WSEM(ASCERR,statement,"FNAME are allowed only inside a WHEN statement");
11051 return 0;
11052 case SELECT:
11053 return ExecuteSELECT(inst,c,statement);
11054 default:
11055 WSEM(ASCERR,statement,
11056 "Inappropriate statement type in declarative section");
11057 Asc_Panic(2, NULL, "Inappropriate statement type in declarative section");
11058 }
11059 return 0;
11060 }
11061
11062
11063 static
11064 int ArraysExpanded(struct Instance *work)
11065 {
11066 unsigned long c,len;
11067 struct Instance *child;
11068 len = NumberChildren(work);
11069 for(c=1;c<=len;c++){
11070 child = InstanceChild(work,c);
11071 if (child!=NULL)
11072 if ((InstanceKind(child)==ARRAY_INT_INST)||
11073 (InstanceKind(child)==ARRAY_ENUM_INST))
11074 if (!RectangleArrayExpanded(child)) return 0;
11075 }
11076 return 1;
11077 }
11078
11079 static
11080 void Pass4ExecuteWhenStatements(struct BitList *blist,
11081 struct Instance *work,
11082 int *changed)
11083 /*********************************************************************\
11084 Try to execute all the when statements in instance work.
11085 It assumes that work is the top of the pending instance list.
11086 Will skip all non-when statements.
11087 \*********************************************************************/
11088 {
11089 unsigned long c;
11090 struct TypeDescription *def;
11091 struct gl_list_t *statements;
11092 CONST struct StatementList *stats;
11093 def = InstanceTypeDesc(work);
11094 stats = GetStatementList(def);
11095 statements = GetList(stats);
11096 for(c=FirstNonZeroBit(blist);c<BLength(blist);c++){
11097 if (ReadBit(blist,c)){
11098 if ( Pass4ExecuteStatement(work,
11099 (struct Statement *)gl_fetch(statements,c+1)) ) {
11100 ClearBit(blist,c);
11101 *changed = 1;
11102 }
11103 }
11104 }
11105 }
11106
11107 static
11108 void Pass3ExecuteLogRelStatements(struct BitList *blist,
11109 struct Instance *work,
11110 int *changed)
11111 /*********************************************************************\
11112 Try to execute all the unexecuted logical relations in instance work.
11113 It assumes that work is the top of the pending instance list.
11114 Will skip all non-logical relations.
11115 \*********************************************************************/
11116 {
11117 unsigned long c;
11118 struct TypeDescription *def;
11119 struct gl_list_t *statements;
11120 CONST struct StatementList *stats;
11121 def = InstanceTypeDesc(work);
11122 stats = GetStatementList(def);
11123 statements = GetList(stats);
11124 for(c=FirstNonZeroBit(blist);c<BLength(blist);c++){
11125 if (ReadBit(blist,c)){
11126 if ( Pass3ExecuteStatement(work,
11127 (struct Statement *)gl_fetch(statements,c+1)) ) {
11128 ClearBit(blist,c);
11129 *changed = 1;
11130 }
11131 }
11132 }
11133 }
11134
11135 static
11136 void Pass2ExecuteRelationStatements(struct BitList *blist,
11137 struct Instance *work,
11138 int *changed)
11139 /*********************************************************************\
11140 Try to execute all the unexecuted relations in instance work.
11141 Does not assume that work is the top of the pending instance list.
11142 Will skip all non-relations in instance work.
11143 \*********************************************************************/
11144 {
11145 unsigned long c;
11146 struct TypeDescription *def;
11147 struct gl_list_t *statements;
11148 CONST struct StatementList *stats;
11149 def = InstanceTypeDesc(work);
11150 stats = GetStatementList(def);
11151 statements = GetList(stats);
11152 for(c=FirstNonZeroBit(blist);c<BLength(blist);c++){
11153 if (ReadBit(blist,c)){
11154 if ( Pass2ExecuteStatement(work,
11155 (struct Statement *)gl_fetch(statements,c+1)) ) {
11156 ClearBit(blist,c);
11157 *changed = 1;
11158 }
11159 }
11160 }
11161 }
11162
11163 static
11164 void Pass1ExecuteInstanceStatements(struct BitList *blist,
11165 struct Instance *work,
11166 int *changed)
11167 /*********************************************************************\
11168 Try to execute all the unexecuted statements in instance work.
11169 It assumes that work is the top of the pending instance list.
11170 Will skip relations in a new way. Relations instances and arrays of
11171 relations will be left as NULL instances (not merely hollow relations)
11172 \*********************************************************************/
11173 {
11174 unsigned long c;
11175 struct TypeDescription *def;
11176 struct gl_list_t *statements;
11177 CONST struct StatementList *stats;
11178 struct Statement *stat;
11179
11180 def = InstanceTypeDesc(work);
11181 stats = GetStatementList(def);
11182 statements = GetList(stats);
11183 c=FirstNonZeroBit(blist);
11184 while(c<BLength(blist)) {
11185 if (ReadBit(blist,c)){
11186 stat = (struct Statement *)gl_fetch(statements,c+1);
11187 if ( Pass1ExecuteStatement(work,&c,stat) ) {
11188 if (StatementType(stat) != SELECT ) {
11189 ClearBit(blist,c);
11190 }
11191 *changed = 1;
11192 }
11193 }
11194 c++;
11195 }
11196 }
11197
11198 static
11199 void Pass4ProcessPendingInstances(void)
11200 {
11201 struct pending_t *work;
11202 struct Instance *inst;
11203 struct BitList *blist;
11204 int changed = 0,count=0;
11205 unsigned long c;
11206 /*
11207 * pending will have at least one instance, or while will fail
11208 */
11209 while((count < PASS4MAXNUMBER) && NumberPending()>0){
11210 changed = 0;
11211 c = 0;
11212 while(c < NumberPending()){
11213 work = TopEntry();
11214 if (work!=NULL) {
11215 inst = PendingInstance(work);
11216 blist = InstanceBitList(inst);
11217 } else {
11218 blist = NULL; /* this shouldn't be necessary, but is */
11219 inst = NULL;
11220 }
11221 if ((blist!=NULL)&&!BitListEmpty(blist)){
11222 /* only models get here */
11223 Pass4ExecuteWhenStatements(blist,inst,&changed);
11224 /* we do away with TryArrayExpansion because it doesn't do whens */
11225 if (BitListEmpty(blist)) {
11226 /*
11227 * delete PENDING model.
11228 */
11229 RemoveInstance(PendingInstance(work));
11230 } else {
11231 /*
11232 * bitlist is still unhappy, but there's nothing to do about it.
11233 * Move the instance to the bottom and increase the counter
11234 * so that we do not visit it again.
11235 */
11236 if (work == TopEntry()) {
11237 MoveToBottom(work);
11238 }
11239 c++;
11240 }
11241 }
11242 else{
11243 /* We do not attempt to expand non-when arrays in pass4. */
11244 }
11245 }
11246 #if (PASS4MAXNUMBER > 1)
11247 if (!changed) {
11248 #endif
11249 count++;
11250 g_iteration++; /* The global iteration counter */
11251 #if (PASS4MAXNUMBER > 1)
11252 }
11253 #endif
11254 }
11255 /* done, or there were no pendings at all and while failed */
11256 }
11257
11258 static
11259 void Pass3ProcessPendingInstances(void)
11260 {
11261 struct pending_t *work;
11262 struct Instance *inst;
11263 struct BitList *blist;
11264 int changed = 0,count=0;
11265 unsigned long c;
11266 /* Reinitialize the number of iterations */
11267 ClearIteration();
11268 g_iteration++;
11269
11270 /* pending will have at least one instance, or while will fail */
11271 while((count < PASS3MAXNUMBER) && NumberPending()>0){
11272 changed = 0;
11273 c = 0;
11274 while(c < NumberPending()){
11275 work = TopEntry();
11276 if (work!=NULL) {
11277 inst = PendingInstance(work);
11278 /* WriteInstanceName(stderr,inst,NULL); FPRINTF(stderr,"\n"); */
11279 blist = InstanceBitList(inst);
11280 } else {
11281 blist = NULL; /* this shouldn't be necessary, but is */
11282 inst = NULL;
11283 }
11284 if ((blist!=NULL)&&!BitListEmpty(blist)){
11285 /* only models get here */
11286 Pass3ExecuteLogRelStatements(blist,inst,&changed);
11287 /* we do away with TryArrayExpansion because it doesn't do rels */
11288
11289 #if (PASS3MAXNUMBER > 1)
11290 if (BitListEmpty(blist) && ArraysExpanded(inst)) {
11291 /* removal is now unconditional because even if there are
11292 pendings, theres nothing we can do. If we
11293 go back to some uglier scheme, we would still need to test,
11294 but only against bitlist, not ArraysExpanded. */
11295 #endif
11296 RemoveInstance(PendingInstance(work));
11297 /* delete PENDING model. bitlist could still be unhappy,
11298 but there's nothing to do about it. */
11299 /* instance could move while being worked. reget the pointer.
11300 work itself cannot move, in memory that is. its list position
11301 can change. Actually in relation phase, this may not be
11302 true. */
11303 #if (PASS3MAXNUMBER > 1)
11304 /* we aren't touching any model twice, so this isn't needed
11305 unless back to uglier scheme */
11306 } else {
11307 if (work == TopEntry())
11308 MoveToBottom(work);
11309 c++;
11310 }
11311 #endif
11312 }
11313 else{
11314 /* We do not attempt to expand non-logical relation arrays in pass3.*/
11315 }
11316 }
11317 if (!changed) {
11318 count++;
11319 g_iteration++; /* The global iteration counter */
11320 }
11321 }
11322 /* done, or there were no pendings at all and while failed */
11323 }
11324
11325 /*
11326 * This is the singlepass phase2 with anontype sharing of
11327 * relations implemented. If relations can depend on other
11328 * relations (as in future differential work) then this function
11329 * needs to be slightly more sophisticated.
11330 */
11331 static
11332 void Pass2ProcessPendingInstancesAnon(struct Instance *result)
11333 {
11334 struct BitList *blist;
11335 struct Instance *proto; /* first of an anon clique */
11336 struct gl_list_t *atl; /* anonymous types in result */
11337 struct gl_list_t *protovarindices; /* all vars in all rels in local MODEL */
11338 struct AnonType *at;
11339 int changed = 0; /* will become 1 if any local relation made */
11340 int anychange = 0; /* will become 1 if any change anywhere */
11341 unsigned long c,n,alen,clen;
11342 #if TIMECOMPILER
11343 clock_t start,classt;
11344 #endif
11345 CONSOLE_DEBUG("...");
11346
11347 /* pending will have at least one instance, or quick return. */
11348 assert(PASS2MAXNUMBER==1);
11349
11350 if (NumberPending() > 0) {
11351 #if TIMECOMPILER
11352 start = clock();
11353 #endif
11354 atl = Asc_DeriveAnonList(result);
11355 #if TIMECOMPILER
11356 classt = clock();
11357 FPRINTF(ASCERR,
11358 "Classification \t\t%lu (for relation sharing)\n",
11359 (unsigned long)(classt-start));
11360 start = clock();
11361 #endif
11362 alen = gl_length(atl);
11363 /* iterate over all anontypes, working on only models. */
11364 for (n=1; n <= alen; n++) {
11365 changed = 0;
11366 at = Asc_GetAnonType(atl,n);
11367 proto = Asc_GetAnonPrototype(at);
11368 if (InstanceKind(proto) == MODEL_INST && InstanceInList(proto)) {
11369 #ifdef DEBUG_RELS
11370 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
11371 FPRINTF(stderr,"Rels in model: ");
11372 WriteInstanceName(stderr,proto,NULL); FPRINTF(stderr,"\n");
11373 error_reporter_end_flush();
11374 #endif
11375 blist = InstanceBitList(proto);
11376 if ((blist!=NULL) && !BitListEmpty(blist)) {
11377 Pass2ExecuteRelationStatements(blist,proto,&changed);
11378 RemoveInstance(proto);
11379 anychange += changed;
11380 }
11381 /* finish rest of AT clique, if there are any, if we made something */
11382 clen = Asc_GetAnonCount(atl,n);
11383 if (clen==1 || changed == 0) {
11384 continue;
11385 }
11386 protovarindices = Pass2CollectAnonProtoVars(proto);
11387 for (c=2; c <= clen; c++) {
11388 Pass2CopyAnonProto(proto,blist,protovarindices,
11389 Asc_GetAnonTypeInstance(at,c));
11390 }
11391 Pass2DestroyAnonProtoVars(protovarindices);
11392 }
11393 }
11394 Asc_DestroyAnonList(atl);
11395 if (!anychange) {
11396 g_iteration++; /* The global iteration counter */
11397 } else {
11398 /* we did something, so try the binary compile */
11399 #if TIMECOMPILER
11400 classt = clock();
11401 FPRINTF(ASCERR,
11402 "Making tokens \t\t%lu (for relations)\n",
11403 (unsigned long)(classt-start));
11404 start = clock();
11405 #endif
11406 BinTokensCreate(result,BT_C);
11407 #if TIMECOMPILER
11408 classt = clock();
11409 FPRINTF(ASCERR,
11410 "build/link \t\t%lu (for bintokens)\n",
11411 (unsigned long)(classt-start));
11412 #endif
11413 }
11414 }
11415 /* done, or there were no pendings at all and while failed */
11416 }
11417
11418 /*
11419 * This is the old pass1-like flavor of pass2process.
11420 * Do not delete it yet, as it is the way we'll have to
11421 * start thinking if relations reference relations, i.e.
11422 * in the use of derivatives in the ASCEND language.
11423 */
11424 static
11425 void Pass2ProcessPendingInstances(void)
11426 {
11427 struct pending_t *work;
11428 struct Instance *inst;
11429 struct BitList *blist;
11430 int changed = 0,count=0;
11431 unsigned long c;
11432 /* pending will have at least one instance, or while will fail */
11433 while((count < PASS2MAXNUMBER) && NumberPending()>0){
11434 changed = 0;
11435 c = 0;
11436 while(c < NumberPending()){
11437 work = TopEntry();
11438 if (work!=NULL) {
11439 inst = PendingInstance(work);
11440 /* WriteInstanceName(stderr,inst,NULL); FPRINTF(stderr,"\n"); */
11441 blist = InstanceBitList(inst);
11442 } else {
11443 blist = NULL; /* this shouldn't be necessary, but is */
11444 inst = NULL;
11445 }
11446 if ((blist!=NULL)&&!BitListEmpty(blist)){
11447 /* only models get here */
11448 Pass2ExecuteRelationStatements(blist,inst,&changed);
11449 /* we do away with TryArrayExpansion because it doesn't do rels */
11450
11451 #if (PASS2MAXNUMBER > 1)
11452 if (BitListEmpty(blist) && ArraysExpanded(inst)) {
11453 /* removal is now unconditional because even if there are
11454 pendings, theres nothing we can do. If we
11455 go back to some uglier scheme, we would still need to test,
11456 but only against bitlist, not ArraysExpanded. */
11457 #endif
11458 RemoveInstance(PendingInstance(work));
11459 /* delete PENDING model. bitlist could still be unhappy,
11460 but there's nothing to do about it. */
11461 /* instance could move while being worked. reget the pointer.
11462 work itself cannot move, in memory that is. its list position
11463 can change. Actually in relation phase, this may not be
11464 true. */
11465 #if (PASS2MAXNUMBER > 1)
11466 /* we aren't touching any model twice, so this isn't needed
11467 unless back to uglier scheme */
11468 } else {
11469 if (work == TopEntry())
11470 MoveToBottom(work);
11471 c++;
11472 }
11473 #endif
11474 } else{
11475 /* We do not attempt to expand non-relation arrays in pass2. */
11476 }
11477 }
11478 if (!changed) {
11479 count++;
11480 g_iteration++; /* The global iteration counter */
11481 }
11482 }
11483 /* done, or there were no pendings at all and while failed */
11484 }
11485
11486
11487 /*
11488 * in a bizarre way, this will generally lead to a bottom up
11489 * instantiation finishing process, though it is started in a
11490 * top down fashion.
11491 */
11492 static
11493 void Pass1ProcessPendingInstances(void)
11494 {
11495 struct pending_t *work;
11496 struct Instance *inst;
11497 struct BitList *blist;
11498 int changed = 0,count=0;
11499 unsigned long c;
11500 while((count <= MAXNUMBER)&&NumberPending()>0){
11501 changed = 0;
11502 c = 0;
11503 while(c < NumberPending()){
11504 work = TopEntry();
11505 inst = PendingInstance(work);
11506 blist = InstanceBitList(inst);
11507 if ((blist!=NULL)&&!BitListEmpty(blist)){
11508 /* only models get here */
11509 Pass1ExecuteInstanceStatements(blist,inst,&changed);
11510 TryArrayExpansion(inst,&changed);
11511 /* try to expand any nonalias,nonparameterized arrays */
11512 if (BitListEmpty(blist)&&ArraysExpanded(inst)) {
11513 RemoveInstance(PendingInstance(work));
11514 /* delete PENDING model */
11515 /* instance could move while being worked. reget the pointer.
11516 work itself cannot move, in memory that is. its list position
11517 can change */
11518 } else {
11519 if (work == TopEntry()) {
11520 MoveToBottom(work);
11521 }
11522 c++;
11523 }
11524 } else {
11525 TryArrayExpansion(inst,&changed);
11526 /* try to expand any nonalias,nonparameterized arrays */
11527 if (ArraysExpanded(inst)) {
11528 RemoveInstance(PendingInstance(work));
11529 /* delete PENDING array */
11530 /* instance could move while being worked. reget the pointer.
11531 work itself cannot move, in memory that is. its list position
11532 can change */
11533 } else {
11534 if (work == TopEntry())
11535 MoveToBottom(work);
11536 c++;
11537 }
11538 }
11539 }
11540 if (!changed) {
11541 count++;
11542 g_iteration++; /* The global iteration counter */
11543 }
11544 }
11545 }
11546
11547 static
11548 struct gl_list_t *GetInstanceStatementList(struct Instance *i)
11549 {
11550 struct TypeDescription *def;
11551 CONST struct StatementList *slist;
11552 def = InstanceTypeDesc(i);
11553 if (def==NULL) return NULL;
11554 slist = GetStatementList(def);
11555 if (slist==NULL) return NULL;
11556 return GetList(slist);
11557 }
11558
11559 /* run the given default statements of i */
11560 static void ExecuteDefault(struct Instance *i, struct Statement *stat,
11561 unsigned long int *depth)
11562 {
11563 struct gl_list_t *lvals;
11564 register unsigned long c,length;
11565 register struct Instance *ptr;
11566 struct value_t value;
11567 enum find_errors err;
11568 if ( (lvals = FindInstances(i,DefaultStatVar(stat),&err)) != NULL ){
11569 for(c=1,length=gl_length(lvals);c<=length;c++){
11570 ptr = (struct Instance *)gl_fetch(lvals,c);
11571 switch(InstanceKind(ptr)){
11572 case REAL_ATOM_INST:
11573 case REAL_INST:
11574 if (*depth == 0) *depth = InstanceDepth(i);
11575 if (DepthAssigned(ptr) >= *depth){
11576 assert(GetEvaluationContext()==NULL);
11577 SetEvaluationContext(i);
11578 value = EvaluateExpr(DefaultStatRHS(stat),NULL,
11579 InstanceEvaluateName);
11580 SetEvaluationContext(NULL);
11581 if ( IsWild(RealAtomDims(ptr)) ) {
11582 switch(ValueKind(value)) {
11583 case real_value:
11584 SetRealAtomValue(ptr,RealValue(value),*depth);
11585 if ( !IsWild(RealValueDimensions(value)) ) {
11586 SetRealAtomDims(ptr,RealValueDimensions(value));
11587 }
11588 break;
11589 case integer_value:
11590 SetRealAtomValue(ptr,(double)IntegerValue(value),*depth);
11591 SetRealAtomDims(ptr,Dimensionless());
11592 break;
11593 default:
11594 WSEM(ASCERR,stat,"Bad real default value");
11595 break;
11596 }
11597 } else {
11598 switch(ValueKind(value)) {
11599 case real_value:
11600 if ( !SameDimen(RealValueDimensions(value),RealAtomDims(ptr)) ){
11601 WSEM(ASCERR,stat,
11602 "Default right hand side is dimensionally inconsistent");
11603 } else {
11604 SetRealAtomValue(ptr,RealValue(value),*depth);
11605 }
11606 break;
11607 case integer_value:
11608 if ( !SameDimen(Dimensionless(),RealAtomDims(ptr)) ){
11609 WSEM(ASCERR,stat,
11610 "Default right hand side is dimensionally inconsistent");
11611 } else {
11612 SetRealAtomValue(ptr,(double)IntegerValue(value),*depth);
11613 }
11614 break;
11615 default:
11616 WSEM(ASCERR,stat,"Bad real default value");
11617 break;
11618 }
11619 }
11620 DestroyValue(&value);
11621 }
11622 break;
11623 case BOOLEAN_ATOM_INST:
11624 case BOOLEAN_INST:
11625 if (*depth == 0) *depth = InstanceDepth(i);
11626 if (DepthAssigned(ptr) > *depth){
11627 assert(GetEvaluationContext()==NULL);
11628 SetEvaluationContext(i);
11629 value = EvaluateExpr(DefaultStatRHS(stat),NULL,
11630 InstanceEvaluateName);
11631 SetEvaluationContext(NULL);
11632 if (ValueKind(value) == boolean_value){
11633 SetBooleanAtomValue(ptr,BooleanValue(value),*depth);
11634 }
11635 else{
11636 WSEM(ASCERR,stat, "Bad boolean default value");
11637 }
11638 DestroyValue(&value);
11639 }
11640 break;
11641 case INTEGER_ATOM_INST:
11642 case INTEGER_INST:
11643 assert(GetEvaluationContext()==NULL);
11644 SetEvaluationContext(i);
11645
11646 value = EvaluateExpr(DefaultStatRHS(stat),NULL,
11647 InstanceEvaluateName);
11648 SetEvaluationContext(NULL);
11649 if (ValueKind(value) == integer_value){
11650 SetIntegerAtomValue(ptr,IntegerValue(value),0);
11651 }
11652 else{
11653 WSEM(ASCERR,stat, "Bad integer default value");
11654 }
11655 DestroyValue(&value);
11656 break;
11657 case SYMBOL_ATOM_INST:
11658 case SYMBOL_INST:
11659 assert(GetEvaluationContext()==NULL);
11660 SetEvaluationContext(i);
11661 value = EvaluateExpr(DefaultStatRHS(stat),NULL,
11662 InstanceEvaluateName);
11663 SetEvaluationContext(NULL);
11664 if (ValueKind(value) == symbol_value){
11665 SetSymbolAtomValue(ptr,SymbolValue(value));
11666 }
11667 else{
11668 WSEM(ASCERR,stat, "Bad symbol default value");
11669 }
11670 DestroyValue(&value);
11671 break;
11672 default: /* NEED stuff here */
11673 break;
11674 }
11675 }
11676 gl_destroy(lvals);
11677 }
11678 else{
11679 WSEM(ASCERR,stat, "Nonexistent LHS variable in default statement.");
11680 }
11681 }
11682
11683 /* run the default statements of i, including nested fors, but
11684 * not recursive to i children.
11685 */
11686 static
11687 void ExecuteDefaultStatements(struct Instance *i,
11688 struct gl_list_t *slist,
11689 unsigned long int *depth)
11690 {
11691 register unsigned long c,length;
11692 register struct Statement *stat;
11693
11694 if (slist){
11695 length = gl_length(slist);
11696 for(c=1;c<=length;c++){
11697 stat = (struct Statement *)gl_fetch(slist,c);
11698 switch(StatementType(stat)){
11699 case ASGN:
11700 ExecuteDefault(i,stat,depth);
11701 break;
11702 case FOR:
11703 if ( ForContainsDefaults(stat) ){
11704 RealDefaultFor(i,stat,depth);
11705 }
11706 break;
11707 default: /* nobody else is a default */
11708 break;
11709 }
11710 }
11711 }
11712 }
11713
11714 static
11715 void RealDefaultFor(struct Instance *i,
11716 struct Statement *stat,
11717 unsigned long int *depth)
11718 {
11719 symchar *name;
11720 struct Expr *ex;
11721 struct StatementList *sl;
11722 unsigned long c,len;
11723 struct value_t value;
11724 struct set_t *sptr;
11725 struct for_var_t *fv;
11726 sl = ForStatStmts(stat);
11727 name = ForStatIndex(stat);
11728 ex = ForStatExpr(stat);
11729 if (FindForVar(GetEvaluationForTable(),name)){ /* duplicated for variable*/
11730 FPRINTF(ASCERR,"Error during default stage.\n");
11731 WSEM(ASCERR,stat, "FOR construct uses duplicate index variable");
11732 return;
11733 }
11734 assert(GetEvaluationContext()==NULL);
11735 SetEvaluationContext(i);
11736 value = EvaluateExpr(ex,NULL,InstanceEvaluateName);
11737 SetEvaluationContext(NULL);
11738 switch(ValueKind(value)){
11739 case error_value:
11740 switch(ErrorValue(value)){
11741 case name_unfound:
11742 case undefined_value:
11743 DestroyValue(&value);
11744 FPRINTF(ASCERR,"Error in default stage.\n");
11745 WSEM(ASCERR,stat, "FOR has undefined values");
11746 return;
11747 default:
11748 WriteForValueError(stat,value);
11749 DestroyValue(&value);
11750 return;
11751 }
11752 case real_value:
11753 case integer_value:
11754 case symbol_value:
11755 case boolean_value:
11756 case list_value:
11757 FPRINTF(ASCERR,"Error during default stage.\n");
11758 WSEM(ASCERR,stat, "FOR expression returns the wrong type");
11759 DestroyValue(&value);
11760 return;
11761 case set_value:
11762 sptr = SetValue(value);
11763 switch(SetKind(sptr)){
11764 case empty_set: break;
11765 case integer_set:
11766 fv = CreateForVar(name);
11767 SetForVarType(fv,f_integer);
11768 AddLoopVariable(GetEvaluationForTable(),fv);
11769 len = Cardinality(sptr);
11770 for(c=1;c<=len;c++){
11771 SetForInteger(fv,FetchIntMember(sptr,c));
11772 ExecuteDefaultStatements(i,GetList(sl),depth);
11773 }
11774 RemoveForVariable(GetEvaluationForTable());
11775 break;
11776 case string_set:
11777 fv = CreateForVar(name);
11778 SetForVarType(fv,f_symbol);
11779 AddLoopVariable(GetEvaluationForTable(),fv);
11780 len = Cardinality(sptr);
11781 for(c=1;c<=len;c++){
11782 SetForSymbol(fv,FetchStrMember(sptr,c));
11783 ExecuteDefaultStatements(i,GetList(sl),depth);
11784 }
11785 RemoveForVariable(GetEvaluationForTable());
11786 break;
11787 }
11788 DestroyValue(&value);
11789 }
11790 }
11791
11792 static
11793 void DefaultStatementList(struct Instance *i,
11794 struct gl_list_t *slist,
11795 unsigned long int *depth)
11796 {
11797 unsigned long c,length;
11798 struct Statement *stat;
11799 struct for_table_t *SavedForTable;
11800 if (slist){
11801 length = gl_length(slist);
11802 for(c=1;c<=length;c++){
11803 stat = (struct Statement *)gl_fetch(slist,c);
11804 switch(StatementType(stat)){
11805 case ASGN:
11806 ExecuteDefault(i,stat,depth);
11807 break;
11808 case FOR:
11809 if ( ForContainsDefaults(stat) ){
11810 SavedForTable = GetEvaluationForTable();
11811 SetEvaluationForTable(CreateForTable());
11812 RealDefaultFor(i,stat,depth);
11813 DestroyForTable(GetEvaluationForTable());
11814 SetEvaluationForTable(SavedForTable);
11815 }
11816 break;
11817 case SELECT:
11818 if (SelectContainsDefaults(stat)) {
11819 ExecuteDefaultsInSELECT(i,&c,stat,depth);
11820 }
11821 else {
11822 c = c + SelectStatNumberStats(stat) ;
11823 }
11824 break;
11825 default:
11826 break;
11827 }
11828 }
11829 }
11830 }
11831
11832 static
11833 void DefaultInstance(struct Instance *i)
11834 {
11835 if (i && (InstanceKind(i) == MODEL_INST)){
11836 unsigned long depth=0;
11837 if (TypeHasDefaultStatements(InstanceTypeDesc(i)))
11838 DefaultStatementList(i,GetInstanceStatementList(i),&depth);
11839 }
11840 }
11841
11842 static
11843 void DefaultInstanceTree(struct Instance *i)
11844 {
11845 VisitInstanceTree(i,DefaultInstance,0,0);
11846 }
11847
11848 /* This just handles instantiating whens,
11849 * ignoring anything else.
11850 * This works with Pass4ProcessPendingInstances.
11851 */
11852 static
11853 struct Instance *Pass4InstantiateModel(struct Instance *result,
11854 unsigned long *pcount)
11855 {
11856 /* do we need a ForTable on the stack here? don't think so. np4ppi does it */
11857 if (result!=NULL) {
11858 /* pass4 pendings already set by visit */
11859 Pass4ProcessPendingInstances();
11860 if (NumberPending()!=0) {
11861 FPRINTF(ASCERR,
11862 "There are unexecuted Phase 4 (whens) in the instance.\n");
11863 *pcount = NumberPending();
11864 }
11865 ClearList();
11866 }
11867 return result;
11868 }
11869
11870 static
11871 void Pass4SetWhenBits(struct Instance *inst)
11872 {
11873 struct Statement *stat;
11874
11875 if (inst != NULL && InstanceKind(inst)==MODEL_INST) {
11876 struct BitList *blist;
11877
11878 blist = InstanceBitList(inst);
11879 if (blist!=NULL){
11880 unsigned long c;
11881 struct gl_list_t *statements = NULL;
11882 enum stat_t st;
11883 int changed;
11884
11885 changed=0;
11886 if (BLength(blist)) {
11887 statements = GetList(GetStatementList(InstanceTypeDesc(inst)));
11888 }
11889 for(c=0;c<BLength(blist);c++){
11890 stat = (struct Statement *)gl_fetch(statements,c+1);
11891 st= StatementType(stat);
11892 if (st == SELECT) {
11893 if (SelectContainsWhen(stat)) {
11894 ReEvaluateSELECT(inst,&c,stat,4,&changed);
11895 }
11896 else {
11897 c = c + SelectStatNumberStats(stat);
11898 }
11899 }
11900 else {
11901 if ( st == WHEN || (st == FOR && ForContainsWhen(stat)) ) {
11902 SetBit(blist,c);
11903 changed++;
11904 }
11905 }
11906 }
11907 /* if changed = 0 but bitlist not empty, we don't want to retry
11908 thoroughly done insts. if whens, then we can't avoid.
11909 if we did add any bits, then changed!= 0 is sufficient test. */
11910 if ( changed ) {
11911 AddBelow(NULL,inst);
11912 /* add PENDING model */
11913 }
11914 }
11915 }
11916 }
11917
11918
11919
11920 /* This just handles instantiating logical relations,
11921 * ignoring anything else.
11922 * This works with Pass3ProcessPendingInstances.
11923 * No recursion. No reallocation of result.
11924 */
11925 static
11926 struct Instance *Pass3InstantiateModel(struct Instance *result,
11927 unsigned long *pcount)
11928 {
11929 if (result!=NULL) {
11930 /* pass3 pendings already set by visit */
11931 Pass3ProcessPendingInstances();
11932 if (NumberPending()!=0) {
11933 FPRINTF(ASCERR,
11934 "There are unexecuted Phase 3 (logical relations) in the instance.\n");
11935 *pcount = NumberPending();
11936 }
11937 ClearList();
11938 }
11939 return result;
11940 }
11941
11942 static
11943 void Pass3SetLogRelBits(struct Instance *inst)
11944 {
11945 struct Statement *stat;
11946 if (inst != NULL && InstanceKind(inst)==MODEL_INST) {
11947 struct BitList *blist;
11948
11949 blist = InstanceBitList(inst);
11950 if (blist!=NULL){
11951 unsigned long c;
11952 struct gl_list_t *statements = NULL;
11953 enum stat_t st;
11954 int changed;
11955
11956 changed=0;
11957 if (BLength(blist)) {
11958 statements = GetList(GetStatementList(InstanceTypeDesc(inst)));
11959 }
11960 for(c=0;c<BLength(blist);c++){
11961 stat = (struct Statement *)gl_fetch(statements,c+1);
11962 st= StatementType(stat);
11963 if (st == SELECT) {
11964 if (SelectContainsLogRelations(stat)) {
11965 ReEvaluateSELECT(inst,&c,stat,3,&changed);
11966 }
11967 else {
11968 c = c + SelectStatNumberStats(stat);
11969 }
11970 }
11971 else {
11972 if ((st == LOGREL)
11973 || (st == COND && CondContainsLogRelations(stat))
11974 || (st == FOR && ForContainsLogRelations(stat)) ) {
11975 SetBit(blist,c);
11976 changed++;
11977 }
11978 }
11979 }
11980 /* if changed = 0 but bitlist not empty, we don't want to retry
11981 thoroughly done insts. if relations, then we can't avoid.
11982 if we did add any bits, then changed!= 0 is sufficient test. */
11983 if ( changed ) {
11984 AddBelow(NULL,inst);
11985 /* add PENDING model */
11986 }
11987 }
11988 }
11989 }
11990
11991 /* This just handles instantiating relations, ignoring anything else.
11992 * This works with Pass2ProcessPendingInstances AND
11993 * Pass2ProcessPendingInstancesAnon, both of which are required to
11994 * maintain a correct compilation.
11995 * No recursion. No reallocation of result.
11996 */
11997 #define ANONFORCE 0 /* require anonymous type use, even if whining OTHERWISE */
11998 static
11999 struct Instance *Pass2InstantiateModel(struct Instance *result,
12000 unsigned long *pcount)
12001 {
12002 CONSOLE_DEBUG("starting...");
12003 /* do we need a ForTable on the stack here? don't think so. np2ppi does it */
12004 if (result!=NULL) {
12005 CONSOLE_DEBUG("result!=NULL...");
12006 /* pass2 pendings already set by visit */
12007 if (ANONFORCE || g_use_copyanon != 0) {
12008 #if TIMECOMPILER
12009 g_ExecuteREL_CreateTokenRelation_calls = 0;
12010 g_CopyAnonRelation = 0;
12011 #endif
12012 Pass2ProcessPendingInstancesAnon(result);
12013 #if TIMECOMPILER
12014 FPRINTF(ASCERR, "Relations in the instance U %d + C %d = T %d.\n" ,
12015 g_ExecuteREL_CreateTokenRelation_calls,g_CopyAnonRelation,
12016 g_CopyAnonRelation+g_ExecuteREL_CreateTokenRelation_calls);
12017 #endif
12018 } else {
12019 Pass2ProcessPendingInstances();
12020 }
12021 if (NumberPending()!=0) {
12022 FPRINTF(ASCERR,
12023 "There are unexecuted Phase 2 (relations) in the instance.\n");
12024 /* dump them here, nitwit. BAA. */
12025 *pcount = NumberPending();
12026 }
12027 ClearList();
12028 }
12029 CONSOLE_DEBUG("...done");
12030 return result;
12031 }
12032
12033 static
12034 void Pass2SetRelationBits(struct Instance *inst)
12035 {
12036 struct Statement *stat;
12037 if (inst != NULL && InstanceKind(inst)==MODEL_INST) {
12038 struct BitList *blist;
12039 #ifdef DEBUG_RELS
12040 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
12041 FPRINTF(ASCERR,"P2SRB: ");
12042 WriteInstanceName(ASCERR,inst,debug_rels_work);
12043 FPRINTF(ASCERR,"\n");
12044 error_reporter_end_flush();
12045 #endif
12046
12047 blist = InstanceBitList(inst);
12048 if (blist!=NULL){
12049 unsigned long c;
12050 struct gl_list_t *statements = NULL;
12051 enum stat_t st;
12052 int changed;
12053
12054 changed=0;
12055 if (BLength(blist)) {
12056 statements = GetList(GetStatementList(InstanceTypeDesc(inst)));
12057 }
12058 for(c=0;c<BLength(blist);c++){
12059 stat = (struct Statement *)gl_fetch(statements,c+1);
12060 st= StatementType(stat);
12061 if (st == SELECT) {
12062 if (SelectContainsRelations(stat)) {
12063 ReEvaluateSELECT(inst,&c,stat,2,&changed);
12064 }
12065 else {
12066 c = c + SelectStatNumberStats(stat);
12067 }
12068 }
12069 else {
12070 if ( st == REL ||
12071 #if NEW_ext
12072 st == EXT ||
12073 #endif
12074 (st == COND && CondContainsRelations(stat)) ||
12075 (st == FOR && ForContainsRelations(stat)) ){
12076 SetBit(blist,c);
12077 changed++;
12078 }
12079 }
12080 }
12081 /* if changed = 0 but bitlist not empty, we don't want to retry
12082 thoroughly done insts. if relations, then we can't avoid.
12083 if we did add any bits, then changed!= 0 is sufficient test. */
12084 if ( changed ) {
12085 AddBelow(NULL,inst);
12086 /* add PENDING model */
12087 #ifdef DEBUG_RELS
12088 ERROR_REPORTER_START_NOLINE(ASC_PROG_NOTE);
12089 FPRINTF(stderr,"Changed: ");
12090 WriteInstanceName(ASCERR,inst,debug_rels_work);
12091 error_reporter_end_flush();
12092 #endif
12093 }
12094 }
12095 }
12096 }
12097
12098
12099 /* This just handles instantiating models and reinstantiating models/arrays,
12100 * ignoring defaults and relations.
12101 * This works with Pass1ProcessPendingInstances.
12102 * This is not a recursive function.
12103 * Either def should be null or oldresult should null.
12104 * If def is null, it is a reinstantiation, else result will be created.
12105 */
12106 static
12107 struct Instance *Pass1InstantiateModel(struct TypeDescription *def,
12108 unsigned long *pcount,
12109 struct Instance *oldresult)
12110 {
12111 struct Instance *result;
12112 struct for_table_t *SavedForTable;
12113 SavedForTable = GetEvaluationForTable();
12114 SetEvaluationForTable(CreateForTable());
12115
12116 if (def != NULL && oldresult != NULL) {
12117 Asc_Panic(2, "Pass1InstantiateModel",
12118 "Pass1InstantiateModel called with both type and instance.");
12119 }
12120 if (def!=NULL) { /* usual case */
12121 result = ShortCutMakeUniversalInstance(def);
12122 if (result==NULL) {
12123 result = CreateModelInstance(def); /*need to account for absorbed here.*/
12124 /* at present, creating parameterized sims illegal */
12125 }
12126 } else {
12127 result = oldresult;
12128 }
12129 if (result!=NULL) {
12130 ClearList();
12131 if (oldresult !=NULL) {
12132 SilentVisitInstanceTree(result,AddIncompleteInst,1,0);
12133 } else {
12134 AddBelow(NULL,result);
12135 }
12136
12137 /* add PENDING model */
12138 Pass1ProcessPendingInstances();
12139 if (NumberPending()!=0) {
12140 *pcount = NumberPending();
12141 FPRINTF(ASCERR,
12142 "There are %lu unexecuted Phase 1 statements in the instance.\n",
12143 *pcount);
12144 if (g_compiler_warnings < 2 && *pcount >10L) {
12145 FPRINTF(ASCWAR,"More than 10 pending statements and warning %s",
12146 "level too low to allow printing.\n");
12147 } else {
12148 FPRINTF(ASCWAR,"---- Pass 1 pending: -------------\n");
12149 if (g_compiler_warnings > 1) {
12150 CheckInstanceLevel(ASCWAR,result,1);
12151 } else {
12152 FPRINTF(ASCWAR,"(Total object check suppressed.)\n");
12153 }
12154 FPRINTF(ASCWAR,"---- End pass 1 pending-----------\n");
12155 }
12156 /* could instead start an error pool data structure with
12157 a review protocol in place post instantiation. */
12158 }
12159 ClearList();
12160 }
12161 DestroyForTable(GetEvaluationForTable());
12162 SetEvaluationForTable(SavedForTable);
12163 return result;
12164 }
12165
12166 /*
12167 * we have to introduce a new head to instantiatemodel to manage
12168 * the phases.
12169 * 5 phases: model creation, relation creation,
12170 * logical relation creation, when creation,
12171 * defaulting.
12172 * BAA
12173 * each pass is responsible for clearing the pending list it leaves.
12174 */
12175 static
12176 struct Instance *NewInstantiateModel(struct TypeDescription *def)
12177 {
12178 struct Instance *result;
12179 unsigned long pass1pendings,pass2pendings,pass3pendings,pass4pendings;
12180 #if TIMECOMPILER
12181 clock_t start, phase1t,phase2t,phase3t,phase4t,phase5t;
12182 #endif
12183
12184 pass1pendings = 0L;
12185 pass2pendings = 0L;
12186 pass3pendings = 0L;
12187 pass4pendings = 0L;
12188 #if TIMECOMPILER
12189 start = clock();
12190 #endif
12191 result = Pass1InstantiateModel(def,&pass1pendings,NULL);
12192 #if TIMECOMPILER
12193 phase1t = clock();
12194 FPRINTF(ASCERR,"Phase 1 models \t\t%lu\n",(unsigned long)phase1t-start);
12195 #endif
12196 /* At this point, there may be unexecuted non-relation
12197 * statements, but they can never be executed. The
12198 * pending list is therefore empty. We know how many.
12199 * The bitlists know which ones.
12200 */
12201 if (result!=NULL) {
12202 #ifdef DEBUG_RELS
12203 debug_rels_work = result;
12204 #endif
12205 /* now set the bits for relation statements and add pending models */
12206 SilentVisitInstanceTree(result,Pass2SetRelationBits,0,0);
12207 /* note, the order of the visit might be better 1 than 0. don't know
12208 * at present order 0, so we do lower models before those near root
12209 */
12210 if (g_use_copyanon) {
12211 }
12212 result = Pass2InstantiateModel(result,&pass2pendings);
12213 /* result will not move as currently implemented */
12214 #ifdef DEBUG_RELS
12215 debug_rels_work = NULL;
12216 #endif
12217 } else {
12218 return result;
12219 }
12220 #if TIMECOMPILER
12221 phase2t = clock();
12222 FPRINTF(ASCERR,"Phase 2 relations \t\t%lu\n",
12223 (unsigned long)(phase2t-phase1t));
12224 #endif
12225 CONSOLE_DEBUG("Starting phase 3...");
12226 /* at this point, there may be unexecuted non-logical relation
12227 * statements, but they can never be executed. The
12228 * pending list is therefore empty. We know how many.
12229 * The bitlists know which ones.
12230 */
12231 if (result!=NULL) {
12232 /* now set the bits for relation statements and add pending models */
12233 SilentVisitInstanceTree(result,Pass3SetLogRelBits,0,0);
12234 /* note, the order of the visit might be better 1 than 0. don't know
12235 * at present order 0, so we do lower models before those near root
12236 */
12237 result = Pass3InstantiateModel(result,&pass3pendings);
12238 /* result will not move as currently implemented */
12239 } else {
12240 return result;
12241 }
12242 #if TIMECOMPILER
12243 phase3t = clock();
12244 FPRINTF(ASCERR,
12245 "Phase 3 logicals \t\t%lu\n",(unsigned long)(phase3t-phase2t));
12246 #endif
12247 if (result!=NULL) {
12248 /* now set the bits for when statements and add pending models */
12249 SilentVisitInstanceTree(result,Pass4SetWhenBits,0,0);
12250 /* note, the order of the visit might be better 1 than 0. don't know */
12251 /* at present order 0, so we do lower models before those near root */
12252 result = Pass4InstantiateModel(result,&pass4pendings);
12253 /* result will not move as currently implemented */
12254 } else {
12255 return result;
12256 }
12257 #if TIMECOMPILER
12258 phase4t = clock();
12259 FPRINTF(ASCERR,"Phase 4 when-case \t\t%lu\n",
12260 (unsigned long)(phase4t-phase3t));
12261 #endif
12262 if (result!=NULL) {
12263 if (!pass1pendings && !pass2pendings && !pass3pendings && !pass4pendings){
12264 DefaultInstanceTree(result);
12265 }
12266 else{
12267 ERROR_REPORTER_NOLINE(ASC_USER_WARNING,"There are unexecuted statements "
12268 "in the instance.\nDefault assignments not executed.");
12269 }
12270 }
12271 #if TIMECOMPILER
12272 phase5t = clock();
12273 FPRINTF(ASCERR,
12274 "Phase 5 defaults \t\t%lu\n",(unsigned long)(phase5t-phase4t));
12275 if (pass1pendings || pass2pendings || pass3pendings || pass4pendings) {
12276 #ifdef __WIN32__
12277 char *timeunit = "milliseconds";
12278 #else
12279 char *timeunit = "microseconds";
12280 #endif
12281 FPRINTF(ASCERR,"Compilation times (%s):\n",timeunit);
12282 FPRINTF(ASCERR,"Phase 1 models \t\t%lu\n",
12283 (unsigned long)(phase1t-start));
12284 FPRINTF(ASCERR,"Phase 2 relations \t\t%lu\n",
12285 (unsigned long)(phase2t-phase1t));
12286 FPRINTF(ASCERR,"Phase 3 logical \t\t%lu\n",
12287 (unsigned long)(phase3t-phase2t));
12288 FPRINTF(ASCERR,"Phase 4 when-case \t\t%lu\n",
12289 (unsigned long)(phase4t-phase3t));
12290 FPRINTF(ASCERR,"Phase 5 defaults\t\t%lu\n",
12291 (unsigned long)(phase5t-phase4t));
12292 }
12293 FPRINTF(ASCERR,"Total\t\t%lu\n",(unsigned long)(phase5t-start));
12294 #if 0 /* deep performance tuning */
12295 gl_reportrecycler(ASCERR);
12296 #endif
12297 #endif
12298 return result;
12299 }
12300
12301
12302
12303 /* returns 1 if the type is uninstantiable as a sim or 0 other wise */
12304 static
12305 int ValidRealInstantiateType(struct TypeDescription *def)
12306 {
12307 if (def==NULL) return 1;
12308 switch(GetBaseType(def)){
12309 case real_constant_type:
12310 case boolean_constant_type:
12311 case integer_constant_type:
12312 case symbol_constant_type:
12313 case real_type:
12314 case boolean_type:
12315 case integer_type:
12316 case symbol_type:
12317 case set_type:
12318 case dummy_type:
12319 return 0;
12320 case model_type:
12321 if (GetModelParameterCount(def) !=0) {
12322 FPRINTF(ASCERR,
12323 "You cannot instance parameterized types by themselves yet.\n");
12324 FPRINTF(ASCERR,"They can only be contained in models or arrays.\n");
12325 return 1;
12326 }
12327 return 0;
12328 case array_type:
12329 case relation_type:
12330 case logrel_type:
12331 case when_type:
12332 FPRINTF(ASCERR,
12333 "You cannot instance arrays and relations by themselves.\n");
12334 FPRINTF(ASCERR,"They can only be contained in models or arrays.\n");
12335 return 1;
12336 default:
12337 Asc_Panic(2, NULL, "Unknown definition type.\n"); /*NOTREACHED*/
12338 exit(2);/* Needed to keep gcc from whining */
12339 }
12340 }
12341
12342 /* this function not recursive */
12343 static
12344 struct Instance *NewRealInstantiate(struct TypeDescription *def,
12345 int intset)
12346 {
12347 struct Instance *result;
12348 CONSOLE_DEBUG("...");
12349
12350 result = ShortCutMakeUniversalInstance(def); /*does quick Universal check */
12351 if (result) return result;
12352
12353 switch(GetBaseType(def)){
12354 case real_type:
12355 case real_constant_type:
12356 return CreateRealInstance(def);
12357 case boolean_type:
12358 case boolean_constant_type:
12359 return CreateBooleanInstance(def);
12360 case integer_type:
12361 case integer_constant_type:
12362 return CreateIntegerInstance(def);
12363 case symbol_type:
12364 case symbol_constant_type:
12365 return CreateSymbolInstance(def);
12366 case set_type:
12367 return CreateSetInstance(def,intset);
12368 case dummy_type:
12369 return CreateDummyInstance(def);
12370 case model_type:
12371 return NewInstantiateModel(def); /*this is now a nonrecursive controller */
12372 case array_type:
12373 case relation_type:
12374 case logrel_type:
12375 case when_type:
12376 FPRINTF(ASCERR,
12377 "You cannot instance arrays and relations by themselves.\n");
12378 FPRINTF(ASCERR,
12379 "They can only be contained in models or arrays.\n");
12380 return NULL; /* how did we get here? */
12381 default:
12382 Asc_Panic(2, NULL, "Unknown definition type.\n"); /*NOTREACHED*/
12383 exit(2);/* Needed to keep gcc from whining */
12384 }
12385 }
12386
12387 static
12388 void ExecDefMethod(struct Instance *root,symchar *simname, symchar *defmethod)
12389 {
12390 enum Proc_enum runstat;
12391 struct Name *name;
12392 if (InstanceKind(root) == MODEL_INST && defmethod != NULL) {
12393 name = CreateIdName(defmethod);
12394 runstat = Initialize(root,name,(char *)SCP(simname),ASCERR,
12395 (WP_BTUIFSTOP|WP_STOPONERR),NULL,NULL);
12396 DestroyName(name);
12397 }
12398 }
12399
12400 /*
12401 */
12402 struct Instance *NewInstantiate(symchar *type, symchar *name, int intset,
12403 symchar *defmethod)
12404 {
12405 struct Instance *result; /* the SIM_INSTANCE */
12406 struct Instance *root; /* the thing created by instantiate */
12407 struct TypeDescription *def;
12408
12409 ++g_compiler_counter;/*instance tree may change:increment compiler counter*/
12410 def = FindType(type);
12411 if (def==NULL) {
12412 FPRINTF(ASCERR,"Cannot find the type for %s in the library\n",SCP(type));
12413 return NULL;
12414 }
12415 if (ValidRealInstantiateType(def)) return NULL;
12416 /* don't want to set up all the sim crap and then destroy it.
12417 * this stuff below core dumps if root comes back NULL, so we
12418 * check here first.
12419 */
12420
12421 ClearIteration();
12422 result = CreateSimulationInstance(def,name);
12423 root = NewRealInstantiate(def,intset);
12424 LinkToParentByPos(result,root,1);
12425 if (g_ExtVariablesTable!=NULL) {
12426 SetSimulationExtVars(result,g_ExtVariablesTable);
12427 g_ExtVariablesTable = NULL;
12428 }
12429 ClearIteration();
12430 ExecDefMethod(root,name,defmethod);
12431 return result;
12432 }
12433
12434
12435 #ifdef THIS_IS_AN_UNUSED_FUNCTION
12436 static
12437 int IsInstanceComplete(struct Instance *i)
12438 {
12439 struct BitList *blist;
12440 if (i==NULL) {
12441 return 0;
12442 }
12443 blist = InstanceBitList(i);
12444 if (blist) { /* only MODEL_INST have bitlists */
12445 if (BitListEmpty(blist))
12446 return 1;
12447 }
12448 return 1; /* atoms are assumed to be complete */
12449 }
12450 #endif /* THIS_IS_AN_UNUSED_FUNCTION */
12451
12452
12453 int IncompleteArray(CONST struct Instance *i)
12454 {
12455 unsigned long c,len;
12456 struct Instance *child;
12457 register struct TypeDescription *desc;
12458 len = NumberChildren(i);
12459 for(c=1;c<=len;c++){
12460 child = InstanceChild(i,c);
12461 if (child != NULL){
12462 switch(InstanceKind(child)){
12463 case ARRAY_INT_INST:
12464 case ARRAY_ENUM_INST:
12465 desc = InstanceTypeDesc(child);
12466 if ((!GetArrayBaseIsRelation(desc))&&
12467 (!RectangleArrayExpanded(child))&&
12468 (!GetArrayBaseIsLogRel(desc))) {
12469 return 1;
12470 }
12471 default:
12472 break; /* out of switch, not out of for */
12473 }
12474 }
12475 }
12476 return 0;
12477 }
12478
12479 static
12480 void AddIncompleteInst(struct Instance *i)
12481 {
12482 struct BitList *blist;
12483 assert(i!=NULL);
12484 if ( ( (blist = InstanceBitList(i)) != NULL &&
12485 !BitListEmpty(blist) ) ||
12486 IncompleteArray(i)) {
12487 /* model and atom/model array inst pending even if they aren't */
12488 AddBelow(NULL,i);
12489 /* add PENDING model or non-relation array */
12490 }
12491 }
12492
12493 /*
12494 * On entry it is assumed that the instance i has already been
12495 * refined and so will not MOVE during subsequent work.
12496 * The process here must be kept in sync with NewRealInstantiateModel,
12497 * but must, additionally, deal ok with array instances as input.
12498 */
12499 void NewReInstantiate(struct Instance *i)
12500 {
12501 struct Instance *result;
12502 unsigned long pass1pendings,pass2pendings,pass3pendings,pass4pendings;
12503 #if TIMECOMPILER
12504 time_t start, phase1t,phase2t,phase3t,phase4t,phase5t;
12505 #endif
12506 ++g_compiler_counter;/*instance tree will change:increment compiler counter*/
12507 assert(i!=NULL);
12508 if (i==NULL || !IsCompoundInstance(i)) return;
12509 /* can't reinstantiate simple objects, missing objects */
12510
12511 pass1pendings = 0L;
12512 pass2pendings = 0L;
12513 pass3pendings = 0L;
12514 pass4pendings = 0L;
12515 #if TIMECOMPILER
12516 start = clock();
12517 #endif
12518 result = Pass1InstantiateModel(NULL,&pass1pendings,i);
12519 #if TIMECOMPILER
12520 phase1t = clock();
12521 #endif
12522 if (result!=NULL) {
12523 SilentVisitInstanceTree(result,Pass2SetRelationBits,0,0);
12524 result = Pass2InstantiateModel(result,&pass2pendings);
12525 } else {
12526 Asc_Panic(2, NULL ,"Reinstantiation phase 2 went insane. Bye!\n");
12527 }
12528 #if TIMECOMPILER
12529 phase2t = clock();
12530 #endif
12531 if (result!=NULL) {
12532 SilentVisitInstanceTree(result,Pass3SetLogRelBits,0,0);
12533 result = Pass3InstantiateModel(result,&pass3pendings);
12534 } else {
12535 Asc_Panic(2, NULL, "Reinstantiation phase 3 went insane. Bye!\n");
12536 }
12537 #if TIMECOMPILER
12538 phase3t = clock();
12539 #endif
12540 if (result!=NULL) {
12541 SilentVisitInstanceTree(result,Pass4SetWhenBits,0,0);
12542 result = Pass4InstantiateModel(result,&pass4pendings);
12543 } else {
12544 Asc_Panic(2, NULL ,"Reinstantiation phase 4 went insane. Bye!\n");
12545 }
12546 #if TIMECOMPILER
12547 phase4t = clock();
12548 #endif
12549 if (result!=NULL) {
12550 if (!pass1pendings && !pass2pendings && !pass3pendings && !pass4pendings){
12551 DefaultInstanceTree(result);
12552 } else{
12553 FPRINTF(ASCERR,"There are unexecuted statements in the instance.\n");
12554 FPRINTF(ASCERR,"Default assignments not executed.\n");
12555 }
12556 } else {
12557 Asc_Panic(2, NULL, "Reinstantiation phase 5 went insane. Bye!\n");
12558 }
12559 #if TIMECOMPILER
12560 phase5t = clock();
12561 FPRINTF(ASCERR,"Reinstantiation times (microseconds):\n");
12562 FPRINTF(ASCERR,"Phase 1 models \t\t%lu\n",(unsigned long)(phase1t-start));
12563 FPRINTF(ASCERR,"Phase 2 relations \t\t%lu\n",
12564 (unsigned long)(phase2t-phase1t));
12565 FPRINTF(ASCERR,
12566 "Phase 3 logicals \t\t%lu\n",(unsigned long)(phase3t-phase2t));
12567 FPRINTF(ASCERR,"Phase 4 when-case \t\t%lu\n",
12568 (unsigned long)(phase4t-phase3t));
12569 FPRINTF(ASCERR,
12570 "Phase 5 defaults \t\t%lu\n",(unsigned long)(phase5t-phase4t));
12571 FPRINTF(ASCERR,"Total\t\t%lu\n",(unsigned long)(phase5t-start));
12572 #endif
12573 return;
12574 }
12575
12576 /*
12577 * Some supporting code for the new partial instantiation,
12578 * and encapsulation schemes.
12579 */
12580
12581 void SetInstantiationRelnFlags(unsigned int flag)
12582 {
12583 g_instantiate_relns = flag;
12584 }
12585
12586 unsigned int GetInstantiationRelnFlags(void)
12587 {
12588 return g_instantiate_relns;
12589 }
12590
12591 /*
12592 * This is the version of instantiate to deal with with 'patched'
12593 * types. Here name is the name of the patch that is to be
12594 * instantiated. We first find the 'original' type, instantiate it
12595 * and then apply the patch. The things that are properly and fully
12596 * supported is external relations, which is the real reason that
12597 * the patch was designed.
12598 */
12599
12600
12601 void UpdateInstance(struct Instance *root, /* the simulation root */
12602 struct Instance *target,
12603 CONST struct StatementList *slist)
12604 {
12605 struct gl_list_t *list, *instances = NULL;
12606 unsigned long len, c;
12607 struct Statement *stat;
12608 enum find_errors ferr;
12609 struct Instance *scope;
12610 struct Name *name;
12611
12612 (void)root; /* stop gcc whine about unused parameter */
12613
12614 list = GetList(slist);
12615 if (!list) return;
12616 len = gl_length(list);
12617 for (c=1;c<=len;c++) {
12618 stat = (struct Statement *)gl_fetch(list,c);
12619 switch (StatementType(stat)) {
12620 case EXT:
12621 name = ExternalStatScope(stat);
12622 if (name==NULL) {
12623 scope = target;
12624 }
12625 else{
12626 instances = FindInstances(target,name,&ferr);
12627 if (instances) {
12628 if (gl_length(instances)!=1) {
12629 FPRINTF(ASCERR,"More than 1 scope instance found !!\n");
12630 scope = NULL;
12631 }
12632 else{
12633 scope = (struct Instance *)gl_fetch(instances,1L);
12634 }
12635 gl_destroy(instances);
12636 }
12637 else{
12638 FPRINTF(ASCERR,"Unable to find scope instance !!\n");
12639 scope = target;
12640 }
12641 }
12642 ExecuteEXT(scope,stat);
12643 break;
12644 default:
12645 break;
12646 }
12647 }
12648 }
12649
12650
12651 /*
12652 * this function instantiates a thing of type name
12653 * without doing relations.
12654 * Relations are then hacked in from external places
12655 * but OTHERWISE the object appears as a regular
12656 * ascend object. (note HACKED is the right word.)
12657 * This function is obsolete; bintoken.c and multiphase
12658 * instantiation make it irrelevant.
12659 */
12660 struct Instance *InstantiatePatch(symchar *patch,
12661 symchar *name, int intset)
12662 {
12663 struct Instance *result; /* the SIM_INSTANCE */
12664 struct Instance *root; /* the thing created by instantiate */
12665 struct TypeDescription *patchdef;
12666 symchar *original;
12667 unsigned int oldflags;
12668
12669 ++g_compiler_counter;/*instance tree will change:increment compiler counter*/
12670 patchdef = FindType(patch);
12671 if (patchdef==NULL) {
12672 FPRINTF(ASCERR,"Cannot find the patch %s in the libary\n",SCP(patch));
12673 return NULL;
12674 }
12675 if (GetBaseType(patchdef)!=patch_type) {
12676 FPRINTF(ASCERR,"Given type \"%s\" is not a patch\n",SCP(patch));
12677 return NULL;
12678 }
12679 /*
12680 * Do the partial instantiation with the original.
12681 * This requires setting up the instantiate relations flags.
12682 * Any failures after this require going to cleanup.
12683 */
12684
12685 original = GetName(GetPatchOriginal(patchdef));
12686 assert(original!=NULL);
12687 oldflags = GetInstantiationRelnFlags();
12688 SetInstantiationRelnFlags(EXTRELS);
12689 result = Instantiate(original,name,intset,NULL);
12690 if (result) {
12691 root = GetSimulationRoot(result);
12692 if (!root) {
12693 FPRINTF(ASCERR,"NULL root instance\n");
12694 goto cleanup;
12695 }
12696 UpdateInstance(root,root,GetStatementList(patchdef)); /* cast statement?*/
12697 }
12698 else{
12699 FPRINTF(ASCERR,"Instantiation failure: NULL simulation\n");
12700 }
12701
12702 cleanup:
12703 SetInstantiationRelnFlags(oldflags);
12704 return result;
12705 }
12706

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