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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 710 - (hide annotations) (download) (as text)
Thu Jun 29 08:53:37 2006 UTC (16 years, 8 months ago) by johnpye
File MIME type: text/x-csrc
File size: 380387 byte(s)
Added my so-called 'quick fix' to external relation processing.
Still need to pursue corruption of efunc->etype pointer, for some
reason.
1 johnpye 707 /* ASCEND modelling environment
2     Copyright (C) 2006 Carnegie Mellon University
3     Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
4     Copyright (C) 1997 Benjamin Allan, Vicente Rico-Ramirez
5    
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2, or (at your option)
9     any later version.
10    
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15    
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place - Suite 330,
19     Boston, MA 02111-1307, USA.
20     *//*
21     @file
22     Ascend Instantiator Implementation
23    
24     @TODO this file is enormous and should be broken into pieces! -- JP
25     *//*
26     by Tom Epperly
27     Created: 1/24/90
28     Last in CVS: $Revision: 1.84 $ $Date: 2003/02/06 04:08:30 $ $Author: ballan $
29     */
30    
31 aw0a 1 #include <stdarg.h>
32 johnpye 399 #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 aw0a 1 #if TIMECOMPILER
40     #include <time.h>
41 johnpye 399 #include <general/tm_time.h>
42 aw0a 1 #endif
43 johnpye 399 #include "bit.h"
44     #include "symtab.h"
45     #include "fractions.h"
46     #include "dimen.h"
47     #include "functype.h"
48 johnpye 669 #include "expr_types.h"
49 johnpye 399 #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 aw0a 1 /* new headers */
87 johnpye 399 #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 aw0a 1
111 johnpye 707 /* don't even THINK ABOUT adding instmacro.h to this list -- ...what the? */
112    
113 aw0a 1 #define MAXNUMBER 4 /* maximum number of iterations allowed
114     * without change */
115     #define PASS2MAXNUMBER 1 /* maximum number of iterations allowed
116     * without change doing relations. In
117     * system where rels reference rels, > 1 */
118    
119     #define PASS3MAXNUMBER 4 /* maximum number of iterations allowed
120     * without change doing logical relations.
121     * In system where logrels reference logrels,
122     * > 1 */
123    
124     #define PASS4MAXNUMBER 1 /* maximum number of iterations allowed
125     * without change executing WHEN. In
126     * system where WHEN reference WHEN, > 1 */
127    
128     #define AVG_CASES 2L /* size to which all cases lists are */
129     /* initialized (WHEN instance) */
130     #define AVG_REF 2L /* size to which all list of references */
131     /* in a case are initialized (WHEN) */
132    
133     #define NO_INCIDENCES 7 /* avg number of vars in a external reln */
134    
135     static int g_iteration = 0; /* the current iteration. */
136    
137 johnpye 569 /* moved from tcltk/generic/interface/SimsProc.c */
138 johnpye 62 struct Instance *g_cursim;
139 aw0a 1
140 ben.allan 423 #define NEW_ext 1
141     #define OLD_ext 0
142 johnpye 707 /**<
143     variable to check agreement in the number of boolean, integer or symbol
144     variables in the WHEN/SELECT statement with the number of boolean, integer
145     or symbol values in each of the CASEs
146     */
147 aw0a 1
148     #define MAX_VAR_IN_LIST 20
149 johnpye 707 /**<
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 || FORCE applied.
153     */
154 aw0a 1
155     int g_use_copyanon = 1;
156 johnpye 707 /**
157     the user switch for anonymous type based relation
158     copying. if 0, no copying by that method is done.
159     */
160 aw0a 1
161     #if TIMECOMPILER
162 johnpye 707 static int g_ExecuteREL_CreateTokenRelation_calls = 0;
163     /**<
164     count the number of calls to CreateTokenRelation from ExecuteREL
165     */
166    
167 aw0a 1 int g_CopyAnonRelation = 0;
168     #endif
169    
170     long int g_compiler_counter = 1;
171 johnpye 707 /**<
172     What: counter incremented every time a compiler action capable of
173     changing the instance tree is executed.
174     At present the compiler cares nothing about this counter,
175     but it is provided as a service to clients.
176    
177     Real applications:
178     1) This variable is used for keeping track of calls to
179     the compiler which will create the need for a total solver system
180     rebuild. This variable should be incremented anytime a function
181     which changes the instance tree is called.
182     */
183 aw0a 1
184 johnpye 703 /* #define DEBUG_RELS */
185 aw0a 1 /* undef DEBUG_RELS if you want less spew in pass 2 */
186    
187     #ifdef DEBUG_RELS
188     /* root of tree being visited in pass 2. */
189     struct Instance *debug_rels_work;
190     #endif /* dbgrels */
191    
192     static unsigned
193     int g_instantiate_relns = ALLRELS; /* default is to do all rels */
194    
195     /* pointer to possible error message for child expansion.
196     * messy way of error handling; do not imitate.
197     */
198     static char *g_trychildexpansion_errmessage = NULL;
199     #define TCEM g_trychildexpansion_errmessage
200    
201     /* error messages */
202     #define REDEFINE_CHILD_MESG "IS_A statement attempting to redefine child "
203     #define REDEFINE_CHILD_MESG2 "ALIASES statement attempting to redefine child "
204     #define UNDEFINED_TYPE_MESG "IS_A statement refers to undefined type "
205     #define IRT_UNDEFINED_TYPE "IS_REFINED_TO statement refers to undefined type "
206     #define REASSIGN_MESG1 "Attempt to reassign constant "
207     #define REASSIGN_MESG2 " value."
208    
209     #ifndef lint
210     static CONST char InstantiatorRCSid[] = "$Id: instantiate.c,v 1.84 2003/02/06 04:08:30 ballan Exp $";
211     #endif
212    
213 johnpye 707 /*------------------------------------------------------------------------------
214     forward declarations
215     */
216 aw0a 1
217 johnpye 707 static void WriteForValueError(struct Statement *, struct value_t);
218     static void MakeInstance(CONST struct Name *, struct TypeDescription *, int,
219 aw0a 1 struct Instance *, struct Statement *, struct Instance *);
220 johnpye 707 static int CheckVarList(struct Instance *, struct Statement *);
221     static int CheckWhereStatements(struct Instance *,struct StatementList *);
222     static int ExecuteISA(struct Instance *, struct Statement *);
223     static int ExecuteCASGN(struct Instance *, struct Statement *);
224     static int DigestArguments(struct Instance *,
225 aw0a 1 struct gl_list_t *, struct StatementList *,
226     struct StatementList *, struct Statement *);
227 johnpye 707 static int DeriveSetType(CONST struct Set *, struct Instance *,CONST unsigned int);
228 aw0a 1
229 johnpye 707 static struct gl_list_t *FindInsts(struct Instance *, CONST struct VariableList *,
230 aw0a 1 enum find_errors *);
231    
232 johnpye 707 static void MissingInsts(struct Instance *, CONST struct VariableList *,int);
233     static struct gl_list_t *FindArgInsts(struct Instance *, struct Set *,
234 aw0a 1 enum find_errors *);
235     static void AddIncompleteInst(struct Instance *);
236     static int CheckALIASES(struct Instance *, struct Statement *);
237     static int CheckARR(struct Instance *, struct Statement *);
238     static int CheckISA(struct Instance *, struct Statement *);
239 johnpye 707 static int AssignStructuralValue(struct Instance *,struct value_t,struct Statement *);
240 aw0a 1 static int CheckSELECT(struct Instance *, struct Statement *);
241     static int CheckWHEN(struct Instance *, struct Statement *);
242     static void MakeRealWhenCaseReferencesFOR(struct Instance *,
243     struct Instance *,
244     struct Statement *,
245     struct gl_list_t *);
246     static void MakeWhenCaseReferencesFOR(struct Instance *,
247     struct Instance *,
248     struct Statement *,
249     struct gl_list_t *);
250     static int Pass1CheckFOR(struct Instance *, struct Statement *);
251     static int Pass1ExecuteFOR(struct Instance *, struct Statement *);
252     #ifdef THIS_IS_AN_UNUSED_FUNCTION
253     static int Pass1RealCheckFOR(struct Instance *, struct Statement *);
254     #endif /* THIS_IS_AN_UNUSED_FUNCTION */
255     static void Pass1RealExecuteFOR(struct Instance *, struct Statement *);
256     static int Pass2CheckFOR(struct Instance *, struct Statement *);
257     static int Pass2ExecuteFOR(struct Instance *, struct Statement *);
258     static void Pass2FORMarkCond(struct Instance *, struct Statement *);
259     static void Pass2FORMarkCondRelations(struct Instance *, struct Statement *);
260     static int Pass2RealCheckFOR(struct Instance *, struct Statement *);
261     static int Pass2RealExecuteFOR(struct Instance *, struct Statement *);
262     static int Pass3CheckFOR(struct Instance *, struct Statement *);
263     static int Pass3ExecuteFOR(struct Instance *, struct Statement *);
264     static int Pass3RealCheckFOR (struct Instance *, struct Statement *);
265     static int Pass3RealExecuteFOR(struct Instance *, struct Statement *);
266     static void Pass3FORMarkCond(struct Instance *, struct Statement *);
267     static void Pass3FORMarkCondLogRels(struct Instance *, struct Statement *);
268     static int Pass4CheckFOR(struct Instance *, struct Statement *);
269     static int Pass4ExecuteFOR(struct Instance *, struct Statement *);
270     static int Pass4RealCheckFOR(struct Instance *, struct Statement *);
271     static int ExecuteUnSelectedForStatements(struct Instance *,
272     struct StatementList *);
273     static void ExecuteDefault(struct Instance *, struct Statement *,
274     unsigned long int *);
275     static void RealDefaultFor(struct Instance *, struct Statement *,
276     unsigned long int *);
277     static void DefaultStatementList(struct Instance *, struct gl_list_t *,
278     unsigned long int *);
279     static void ExecuteDefaultStatements(struct Instance *, struct gl_list_t *,
280     unsigned long int *);
281     static int ExecuteSELECT(struct Instance *, unsigned long *,
282     struct Statement *);
283     static void ExecuteDefaultsInSELECT(struct Instance *, unsigned long *,
284     struct Statement *, unsigned long int *);
285     static void RealExecuteWHEN(struct Instance *, struct Statement *);
286     static int ExecuteUnSelectedSELECT(struct Instance *, unsigned long *,
287     struct Statement *);
288     static void ExecuteUnSelectedStatements(struct Instance *i,unsigned long *,
289     struct StatementList *);
290     static void ExecuteUnSelectedWhenStatements(struct Instance *,
291     struct StatementList *);
292     static int ExecuteUnSelectedWHEN(struct Instance *, struct Statement *);
293     static void ReEvaluateSELECT(struct Instance *, unsigned long *,
294     struct Statement *, int, int *);
295    
296 johnpye 707 /*-----------------------------------------------------------------------------
297     ...
298     */
299 aw0a 1
300    
301     static
302     void ClearIteration(void)
303     {
304     g_iteration = 0;
305     }
306    
307     static
308     void WriteStatementLocation(FILE *f, struct Statement *stat)
309     {
310     if (stat!= NULL){
311     FPRINTF(f,"\nStatement located on line %lu of %s.\n",
312     StatementLineNum(stat),
313     Asc_ModuleBestName(StatementModule(stat)));
314     }
315     else
316     FPRINTF(f,"NULL statement.\n");
317     }
318    
319     static
320     void WriteSetError(struct Statement *statement, struct TypeDescription *def)
321     {
322 johnpye 529 STATEMENT_ERROR(statement, (GetBaseType(def) == set_type) ?
323 aw0a 1 "No set type specified in IS_A statement"
324     : "Set type specified for a non-set type");
325     }
326    
327 johnpye 707 /**
328     This code will emit error messages only on the last
329     iteration when trying to clear pending statements.
330     g_iteration is the global iteration counter, and MAXNUMBER
331     is the number of times that the instantiator will try
332     to clear the list, without change.
333     */
334 aw0a 1 static
335     void WriteUnexecutedMessage(FILE *f, struct Statement *stat, CONST char *msg)
336     {
337     if (g_iteration>=(MAXNUMBER)) WSSM(f,stat,msg,0);
338     }
339    
340    
341 johnpye 707 /**
342     Write Unexecuted Error Message in Pass 3 WUEMPASS3
343    
344     This code will emit error messages only on the last
345     iteration of pass3 when trying to clear pending statements.
346     g_iteration is the global iteration counter, and PASS3MAXNUMBER
347     is the number of times that the instantiator will try
348     to clear the list, without change.
349     */
350 aw0a 1 static
351     void WUEMPASS3(FILE *f, struct Statement *stat, CONST char *msg)
352     {
353     if (g_iteration>=(PASS3MAXNUMBER)) WSSM(f,stat,msg,0);
354     }
355    
356 johnpye 707 /*------------------------------------------------------------------------------
357     DENSE ARRAY PROCESSING
358 aw0a 1
359 johnpye 707 ...mostly
360     */
361 aw0a 1
362 johnpye 707 /**
363     returns 0 if c is NULL, probably should be -1.
364     -2 if c is illegal set type
365     1 if c IS_A integer_constant set type
366     0 if c IS_A symbol_constant set type
367     @param statement is used only to issue error messages.
368     */
369 aw0a 1 static
370     int CalcSetType(symchar *c, struct Statement *statement)
371     {
372     struct TypeDescription *desc;
373     if (c==NULL) return 0;
374     if ((desc = FindType(c)) != NULL){
375     switch(GetBaseType(desc)){
376     case integer_constant_type: return 1;
377     case symbol_constant_type: return 0;
378     default:
379 johnpye 529 STATEMENT_ERROR(statement, "Incorrect set type in IS_A");
380 aw0a 1 /* lint should keep us from ever getting here */
381     return -2;
382     }
383     } else{
384 johnpye 529 STATEMENT_ERROR(statement, "Unable to determine type of set.");
385 aw0a 1 return -2;
386     }
387     }
388    
389 johnpye 707 /**
390     last minute check for set values that subscript arrays.
391     probably should check constantness too but does not.
392     return 0 if ok, 1 if not.
393     */
394 johnpye 190 static
395 aw0a 1 int CheckSetVal(struct value_t setval)
396     {
397     if (ValueKind(setval) != set_value) {
398     switch (ValueKind(setval)) {
399     case integer_value:
400     TCEM = "Incorrectly integer-valued array range.";
401     break;
402     case symbol_value:
403     TCEM = "Incorrect symbol-valued array range.";
404     break;
405     case real_value:
406     TCEM = "Incorrect real-valued array subscript.";
407     break;
408     case boolean_value:
409     TCEM = "Incorrect boolean-valued array subscript.";
410     break;
411     case list_value:
412     TCEM = "Incorrect list-valued array subscript.";
413     break;
414     case error_value:
415     switch (ErrorValue(setval)) {
416     case type_conflict:
417     TCEM = "Set expression type conflict in array subscript.";
418     break;
419     default:
420     TCEM = "Generic error 1 in array subscript.";
421     break;
422     }
423     break;
424     case set_value: /* really weird if this happens, since if eliminated it */
425     break;
426     default:
427     TCEM = "Generic error 2 in array subscript.";
428     break;
429     }
430     return 1;
431     }
432     return 0;
433     }
434 johnpye 707
435     /**
436     This attempts to evaluate a the next undone subscript of the
437     array and call ExpandArray with that set value.
438     In the case of ALIAS arrays this must always succeed, because
439     we have checked first that it will. If it did not we would
440     be stuck because later calls to ExpandArray will not know
441     the difference between the unexpanded alias array and the
442     unexpanded IS_A array.
443    
444     Similarly, in the case of parameterized arrays this must
445     always succeed, OTHERWISE ExpandArray will not know the
446     arguments of the IS_A type, arginst next time around.
447    
448     In the event that the set given or set value expanded is bogus,
449     returns 1 and statement from which this call was derived is
450     semantically garbage.
451     */
452 aw0a 1 static
453     int ValueExpand(struct Instance *i, unsigned long int pos,
454     struct value_t value, int *changed,
455     struct Instance *rhsinst, struct Instance *arginst,
456     struct gl_list_t *rhslist)
457     {
458     struct value_t setval;
459     switch(ValueKind(value)){
460     case list_value:
461     setval = CreateSetFromList(value);
462     if (CheckSetVal(setval)) {
463     return 1;
464     }
465     ExpandArray(i,pos,SetValue(setval),rhsinst,arginst,rhslist);
466     /* this may modify the pending instance list if
467     * rhslist and rhsinst both == NULL.
468     */
469     *changed = 1;
470     DestroyValue(&setval);
471     break;
472     case error_value:
473     switch(ErrorValue(value)){
474     case name_unfound:
475     case undefined_value:
476     break;
477     default:
478     TCEM = "Array instance has incorrect index type.";
479     return 1;
480     }
481     break;
482     default:
483     TCEM = "Array instance has incorrect index value type.";
484     return 1;
485     }
486     return 0;
487     }
488    
489 johnpye 707 /**
490     When an incorrect combination of sparse and dense indices is found,
491     marks the statement wrong and whines. If the statement has already
492     been marked wrong, does not whine.
493    
494     In FOR loops,
495     this function warns about a problem that the implementation really
496     should allow. Alas, the fix is pending a complete rework of arrays.
497    
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 aw0a 1 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 johnpye 529 STATEMENT_ERROR(statement, "Add another FOR index. In FOR loops,"
525 aw0a 1 " all array subscripts must be scalar values, not sets.");
526     WSS(ASCERR,statement);
527     } else {
528     MarkStatContext(statement,context_WRONG);
529 johnpye 529 STATEMENT_ERROR(statement, "Subscripts of conflicting or incorrect types"
530 aw0a 1 " in rectangular array.");
531     WSS(ASCERR,statement);
532     }
533     return;
534     }
535    
536 johnpye 707 /**
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 aw0a 1 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 johnpye 707 /**
577     expands, if possible, children of nonrelation,
578     nonalias, nonparameterized arrays.
579     */
580 aw0a 1 static
581     void TryArrayExpansion(struct Instance *work, int *changed)
582     {
583     unsigned long c,len;
584     struct Instance *child;
585     struct TypeDescription *desc;
586     len = NumberChildren(work);
587     for(c=1;c<=len;c++){
588     child = InstanceChild(work,c);
589     if (child!=NULL){
590     switch(InstanceKind(child)){
591     case ARRAY_INT_INST:
592     case ARRAY_ENUM_INST:
593     desc = InstanceTypeDesc(child);
594     /* no alii, no parameterized types, no for loops allowed. */
595     if ((!GetArrayBaseIsRelation(desc))&&(!RectangleArrayExpanded(child)) &&
596     (!GetArrayBaseIsLogRel(desc)) ) {
597     if (TryChildExpansion(child,work,changed,NULL,NULL,NULL)!= 0) {
598     SignalChildExpansionFailure(work,c);
599     }
600     }
601     break;
602     default:
603     #if 0 /* example of what not to do here */
604     FPRINTF(ASCERR,"TryArrayExpansion called with non-array instance\n");
605     /* calling with non array child is fairly common and unavoidable */
606     #endif
607     break;
608     }
609     }
610     }
611     }
612    
613     static
614     void DestroyIndexList(struct gl_list_t *gl)
615     {
616     struct IndexType *ptr;
617     int c,len;
618     if (gl!=NULL) {
619     for (c=1,len = gl_length(gl);c <= len;c++) {
620     ptr = (struct IndexType *)gl_fetch(gl,c);
621     if (ptr) DestroyIndexType(ptr);
622     }
623     gl_destroy(gl);
624     }
625     }
626    
627 johnpye 707 /**
628     returns 1 if ex believed to be integer, 0 if symbol, and -1 if
629     confused. if searchfor TRUE, includes fortable in search
630     */
631 aw0a 1 static
632     int FindExprType(CONST struct Expr *ex, struct Instance *parent,
633 johnpye 707 CONST unsigned int searchfor
634     ){
635 aw0a 1 struct Instance *i;
636     struct gl_list_t *ilist;
637     enum find_errors err;
638     switch(ExprType(ex)){
639     case e_var:
640     ilist = FindInstances(parent,ExprName(ex),&err);
641     if ((ilist!=NULL)&&(gl_length(ilist)>0)){
642     i = (struct Instance *)gl_fetch(ilist,1);
643     gl_destroy(ilist);
644     switch(InstanceKind(i)){
645     case INTEGER_ATOM_INST:
646     case INTEGER_INST:
647     case INTEGER_CONSTANT_INST:
648     return 1;
649     case SYMBOL_ATOM_INST:
650     case SYMBOL_INST:
651     case SYMBOL_CONSTANT_INST:
652     return 0;
653     case SET_ATOM_INST:
654     case SET_INST:
655     return IntegerSetInstance(i);
656     default:
657     FPRINTF(ASCERR,"Incorrect index type; guessing integer index.\n");
658     return 1;
659     }
660     } else {
661     if (ilist!=NULL) gl_destroy(ilist);
662     if (GetEvaluationForTable()!=NULL) {
663     symchar *name;
664     struct for_var_t *ptr;
665     AssertMemory(GetEvaluationForTable());
666     name = SimpleNameIdPtr(ExprName(ex));
667     if (name!=NULL) {
668     ptr = FindForVar(GetEvaluationForTable(),name);
669     if (ptr!=NULL) {
670     switch(GetForKind(ptr)) {
671     case f_integer:
672     return 1;
673     case f_symbol:
674     return 0;
675     default:
676     FPRINTF(ASCERR,"Undefined FOR or indigestible variable.\n");
677     }
678     }
679     }
680     }
681     return -1;
682     }
683     case e_int:
684     return 1;
685     case e_symbol:
686     return 0;
687     case e_set:
688     return DeriveSetType(ExprSValue(ex),parent,searchfor);
689     default:
690     if (g_iteration>=(MAXNUMBER)) {
691     /* referencing g_iteration sucks, but seeing spew sucks more.*/
692     /* WUM, which we want, needs a statement ptr we can't supply. */
693     FPRINTF(ASCERR,"Heuristic FindExprType failed. Check your indices.\n");
694     FPRINTF(ASCERR,"Report this failure to %s if no apparent error.\n",
695     ASC_MILD_BUGMAIL);
696     FPRINTF(ASCERR,"Assuming integer array index.\n");
697     }
698     return -1;
699     }
700     }
701    
702 johnpye 707 /**
703     returns -1 if has no clue,
704     returns 1 if set appears to be int set
705     returns 0 if apparently symbol_constant set.
706     */
707 aw0a 1 static
708     int DeriveSetType(CONST struct Set *sptr, struct Instance *parent,
709 johnpye 707 CONST unsigned int searchfor
710     ){
711 aw0a 1 register CONST struct Set *ptr;
712     int result=-1; /* -1 indicates a failure */
713     ptr = sptr;
714     /* if it contains a range it must be an integer set */
715     while(ptr!=NULL){
716     if (SetType(ptr)) return 1;
717     ptr = NextSet(ptr);
718     }
719     ptr = sptr;
720     /* try to find the type from the expressions */
721     while(ptr!=NULL){
722     if ((result = FindExprType(GetSingleExpr(ptr),parent,searchfor)) >= 0) {
723     return result;
724     }
725     ptr = NextSet(ptr);
726     }
727     return -1; /* undefined type */
728     }
729    
730 johnpye 707 /**
731     Returns a gllist contain the string form (or forms) of array
732     subscripts(s)
733     e.g. Name a[1..2]['foo']
734     will return a gllist containing something like:
735     "1..2"
736     "foo"
737     */
738 aw0a 1 static
739     struct gl_list_t *ArrayIndices(CONST struct Name *name,
740     struct Instance *parent)
741     {
742     struct gl_list_t *result;
743     int settype;
744     CONST struct Set *sptr;
745    
746     if (!NameId(name)) return NULL;
747     name = NextName(name);
748     if (name == NULL) return NULL;
749     result = gl_create(2L);
750     while (name!=NULL){
751     if (NameId(name)){
752     DestroyIndexList(result);
753     return NULL;
754     }
755     sptr = NameSetPtr(name);
756     if ((settype = DeriveSetType(sptr,parent,0)) >= 0){
757     gl_append_ptr(result,
758     (VOIDPTR)CreateIndexType(CopySetList(sptr),settype));
759     } else{
760     DestroyIndexList(result);
761     return NULL;
762     }
763     name = NextName(name);
764     }
765     return result;
766     }
767    
768 johnpye 707 /*-----------------------------------------------------------------------------
769     SPARSE AND DENSE ARRAY PROCESSING
770     */
771 aw0a 1
772 johnpye 707 /**
773     this function has been modified to handle list results when called
774     from check aliases and dense executearr.
775     The indices made here in the aliases case where the alias is NOT
776     inside a FOR loop are NOT for consumption by anyone because they
777     contain a dummy index type. They merely indicate that
778     indices can be made. They should be immediately destroyed.
779     DestroyIndexType is the only thing that groks the Dummy.
780     This should not be called on the final subscript of an ALIASES/IS_A
781     inside a FOR loop unless you can grok a dummy in last place.
782     */
783 aw0a 1 static
784     struct IndexType *MakeIndex(struct Instance *inst,
785     CONST struct Set *sptr,
786     struct Statement *stat, int last)
787     {
788     struct value_t value;
789     struct value_t setval;
790     int intset;
791     assert(GetEvaluationContext()==NULL);
792     SetEvaluationContext(inst);
793     if (StatInFOR(stat)) {
794     if (sptr == NULL ||
795     NextSet(sptr) != NULL ||
796     SetType(sptr) != 0 ) {
797     /* must be simple index */
798     WriteUnexecutedMessage(ASCERR,stat,
799     "Next subscript in FOR loop IS_A must be a scalar value,"
800     " not a set value.");
801     SetEvaluationContext(NULL);
802     return NULL;
803     }
804     value = EvaluateExpr(GetSingleExpr(sptr),NULL,InstanceEvaluateName);
805     SetEvaluationContext(NULL);
806     switch(ValueKind(value)){
807     case real_value:
808     case boolean_value:
809     case set_value:
810     case list_value:
811     if (last==0) {
812 johnpye 529 STATEMENT_ERROR(stat, "Index to sparse array is of an incorrect type");
813 aw0a 1 DestroyValue(&value);
814     return NULL;
815     } else {
816     setval = CreateSetFromList(value);
817     intset = (SetKind(SetValue(setval)) == integer_set);
818     DestroyValue(&value);
819     DestroyValue(&setval);
820     return CreateDummyIndexType(intset);
821     /* damn thing ends up in typedesc of arrays. */
822     }
823     case integer_value:
824     DestroyValue(&value);
825     return CreateIndexType(CopySetList(sptr),1);
826     case symbol_value:
827     DestroyValue(&value);
828     return CreateIndexType(CopySetList(sptr),0);
829     case error_value:
830     switch(ErrorValue(value)){
831     case undefined_value:
832     if (StatementType(stat)==REL||StatementType(stat)==LOGREL) {
833     WSSM(ASCERR,stat,"Undefined relation array indirect indices",3);
834     /* don't want to warn about sparse IS_A/aliases here */
835     }
836     break;
837     case name_unfound:
838     break;
839     default:
840     WSSM(ASCERR,stat, "Error in sparse array indices",3);
841     break;
842     }
843     DestroyValue(&value);
844     return NULL;
845     default:
846 johnpye 529 STATEMENT_ERROR(stat, "Unknown result value type in MakeIndex.\n");
847 aw0a 1 Asc_Panic(2, NULL, "Unknown result value type in MakeIndex.\n");
848 johnpye 709
849 aw0a 1 }
850     } else { /* checking subscripts on dense ALIASES/param'd IS_A statement */
851     if (sptr==NULL) {
852     SetEvaluationContext(NULL);
853     return NULL;
854     }
855     value = EvaluateSet(sptr,InstanceEvaluateName);
856     SetEvaluationContext(NULL);
857     switch(ValueKind(value)){
858     case list_value:
859     DestroyValue(&value);
860     return CreateDummyIndexType(0 /* doesn't matter -- dense alias check */);
861     case error_value:
862     switch(ErrorValue(value)){
863     case undefined_value:
864     case name_unfound:
865     DestroyValue(&value);
866     return NULL;
867     default:
868     DestroyValue(&value);
869     WSSM(ASCERR,stat, "Error evaluating index to dense array",3);
870     return NULL;
871     }
872     default:
873     DestroyValue(&value);
874 johnpye 529 STATEMENT_ERROR(stat, "Bad index to dense alias array");
875 aw0a 1 Asc_Panic(2, NULL, "Bad index to dense alias array");
876 johnpye 709
877 aw0a 1 }
878 jds 97 /* return NULL; */ /* unreachable */
879 aw0a 1 }
880     }
881    
882 johnpye 707 /**
883     This function is used for making the indices of individual
884     elements of sparse arrays (and for checking that it is possible)
885     and for checking that the indices of dense alias arrays (a
886     very wierd thing to have) and dense parameterized IS_A
887     are fully defined so that aliases
888     and parameterized/sparse IS_A can be fully constructed in 1 pass.
889     paves over the last subscript on sparse ALIASES-IS_A.
890     */
891 aw0a 1 static
892     struct gl_list_t *MakeIndices(struct Instance *inst,
893     CONST struct Name *name,
894     struct Statement *stat)
895     {
896     struct gl_list_t *result;
897     CONST struct Set *sptr;
898     struct IndexType *ptr;
899     int last;
900    
901    
902     result = gl_create((unsigned long)NameLength(name));
903     while(name != NULL){
904     if (NameId(name)){
905     DestroyIndexList(result);
906     return NULL;
907     }
908     sptr = NameSetPtr(name);
909     last = (NextName(name)==NULL && StatementType(stat)==ARR);
910     ptr = MakeIndex(inst,sptr,stat,last);
911     if (ptr != NULL) {
912     gl_append_ptr(result,(VOIDPTR)ptr);
913     } else {
914     DestroyIndexList(result);
915     return NULL;
916     }
917     name = NextName(name);
918     }
919     return result;
920     }
921    
922     static
923     void LinkToParentByName(struct Instance *inst,
924     struct Instance *child,
925     symchar *name)
926     {
927     struct InstanceName rec;
928     unsigned long pos;
929     SetInstanceNameType(rec,StrName);
930     SetInstanceNameStrPtr(rec,name);
931     pos = ChildSearch(inst,&rec);
932     LinkToParentByPos(inst,child,pos);
933     }
934    
935     void LinkToParentByPos(struct Instance *inst,
936     struct Instance *child,
937     unsigned long pos)
938     {
939     assert(pos);
940     assert(child != NULL);
941     assert(inst != NULL);
942    
943     StoreChildPtr(inst,pos,child);
944     AddParent(child,inst);
945     }
946    
947     static
948     struct Instance *GetArrayHead(struct Instance *inst, CONST struct Name *name)
949     {
950     struct InstanceName rec;
951     unsigned long pos;
952     if (NameId(name)){
953     SetInstanceNameType(rec,StrName);
954     SetInstanceNameStrPtr(rec,NameIdPtr(name));
955     pos=ChildSearch(inst,&rec);
956     if (pos>0) {
957     return InstanceChild(inst,pos);
958     } else {
959     return NULL;
960     }
961     }
962     return NULL;
963     }
964    
965 johnpye 707 /**
966     We are inside a FOR loop.
967     If rhsinst is not null, we are in an alias statement and
968     will use rhsinst as the child added instead of
969     creating a new child.
970     If arginst is not null, we will use it to aid in
971     creating IS_A elements.
972     at least one of arginst, rhsinst must be NULL.
973     If last !=0, returns NULL naturally and ok.
974     */
975 aw0a 1 static
976     struct Instance *DoNextArray(struct Instance *parentofary, /* MODEL */
977     struct Instance *ptr, /* array layer */
978     CONST struct Name *name, /* subscript */
979     struct Statement *stat,
980     struct Instance *rhsinst, /*ALIASES*/
981     struct Instance *arginst, /* IS_A */
982     struct gl_list_t *rhslist, /*ARR*/
983     int last /* ARR */)
984     {
985     CONST struct Set *sptr;
986     struct value_t value;
987     struct value_t setval;
988     long i;
989     symchar *sym;
990    
991     if (NameId(name) != 0) return NULL; /* must be subscript, i.e. set */
992     sptr = NameSetPtr(name);
993     if ((sptr==NULL)||(NextSet(sptr)!=NULL)||(SetType(sptr))) {
994     return NULL;
995     }
996     assert(GetEvaluationContext()==NULL);
997     assert(rhsinst==NULL || arginst==NULL);
998     SetEvaluationContext(parentofary);
999     value = EvaluateExpr(GetSingleExpr(sptr),NULL,InstanceEvaluateName);
1000     SetEvaluationContext(NULL);
1001     switch(ValueKind(value)){
1002     case real_value:
1003     case set_value:
1004     case boolean_value:
1005     case list_value:
1006     if (last==0) {
1007 johnpye 529 STATEMENT_ERROR(stat, "Index to array is of an incorrect type");
1008 aw0a 1 DestroyValue(&value);
1009     return NULL;
1010     } else {
1011     /* we are at last subscript of ALIASES/IS_A in for loop. */
1012     /* expand using rhslist pretending dense array. */
1013     setval = CreateSetFromList(value);
1014     ExpandArray(ptr,1L,SetValue(setval),NULL,NULL,rhslist);
1015     DestroyValue(&setval);
1016     DestroyValue(&value);
1017     return NULL;
1018     }
1019     case integer_value:
1020     i = IntegerValue(value);
1021     DestroyValue(&value);
1022     return FindOrAddIntChild(ptr,i,rhsinst,arginst);
1023     case symbol_value:
1024     sym = SymbolValue(value);
1025     DestroyValue(&value);
1026     return FindOrAddStrChild(ptr,sym,rhsinst,arginst);
1027     case error_value:
1028     switch(ErrorValue(value)){
1029     case undefined_value:
1030     if (StatementType(stat)==REL||StatementType(stat)==LOGREL) {
1031     WSSM(ASCERR,stat, "Undefined relation array indirect indices",3);
1032     }
1033     break;
1034     case name_unfound:
1035     break;
1036     default:
1037 johnpye 529 STATEMENT_ERROR(stat, "Error in array indices");
1038 aw0a 1 break;
1039     }
1040     DestroyValue(&value);
1041     return NULL;
1042     default:
1043     Asc_Panic(2, NULL ,"Unknown result value type.\n");
1044 johnpye 709
1045 aw0a 1 }
1046     }
1047    
1048 johnpye 707 /**
1049     We are inside a FOR loop.
1050     If rhsinst is not null, we are in an alias statement and
1051     will eventually use rhsinst as the child added instead of
1052     creating a new child.
1053     we expand each subscript individually here rahter than recursively.
1054     If we are on last subscript of an ALIASES/IS_A, we copy the
1055     layer in rhslist rather than expanding individually.
1056     rhslist and intset only make sense simultaneously.
1057     */
1058 aw0a 1 static
1059     struct Instance *AddArrayChild(struct Instance *parentofary,
1060     CONST struct Name *name,
1061     struct Statement *stat,
1062     struct Instance *rhsinst,
1063     struct Instance *arginst,
1064     struct gl_list_t *rhslist)
1065     {
1066     struct Instance *ptr;
1067     int last;
1068    
1069     ptr = GetArrayHead(parentofary,name);
1070     if(ptr != NULL) {
1071     name = NextName(name);
1072     while(name!=NULL){
1073     last = (rhslist != NULL && NextName(name)==NULL);
1074     ptr = DoNextArray(parentofary,ptr,name,stat,
1075     rhsinst,arginst,rhslist,last);
1076     if (ptr==NULL){
1077     return NULL;
1078     }
1079     name = NextName(name);
1080     }
1081     return ptr;
1082     } else {
1083     return NULL;
1084     }
1085     }
1086    
1087 johnpye 707 /**
1088     Create the sparse array typedesc based on the statement kind
1089     and also add first child named. intset and def used for nonrelation types
1090     only.
1091    
1092     This function returns the child pointer because relation functions
1093     need it, not because the child is unconnected.
1094    
1095     If rhsinst is not NULL, uses rhsinst instead of creating new one.
1096     If rhslist is not NULL, uses rhslist instead of rhsinst or creating.
1097    
1098     It is expected that all subscripts will be evaluatable and that
1099     in the case of the ALIASES-IS_A statement, the IS_A part is done
1100     just before the ALIASES part.
1101     */
1102 aw0a 1 static
1103     struct Instance *MakeSparseArray(struct Instance *parent,
1104     CONST struct Name *name,
1105     struct Statement *stat,
1106     struct TypeDescription *def,
1107     int intset,
1108     struct Instance *rhsinst,
1109     struct Instance *arginst,
1110     struct gl_list_t *rhslist)
1111     {
1112 johnpye 89 struct TypeDescription *desc = NULL;
1113 aw0a 1 struct Instance *aryinst;
1114     struct gl_list_t *indices;
1115     indices = MakeIndices(parent,NextName(name),stat);
1116     if (indices != NULL) {
1117     switch (StatementType(stat)) {
1118     case REL:
1119     assert(def==NULL && rhsinst==NULL && rhslist == NULL && arginst == NULL);
1120     desc = CreateArrayTypeDesc(StatementModule(stat),FindRelationType(),
1121     0,1,0,0,indices);
1122     break;
1123     case LOGREL:
1124     assert(def==NULL && rhsinst==NULL && rhslist == NULL && arginst == NULL);
1125     desc = CreateArrayTypeDesc(StatementModule(stat),FindLogRelType(),
1126     0,0,1,0,indices);
1127     break;
1128     case WHEN:
1129     assert(def==NULL && rhsinst==NULL && rhslist == NULL && arginst == NULL);
1130     desc = CreateArrayTypeDesc(StatementModule(stat),
1131     FindWhenType(),0,0,0,1,indices);
1132     break;
1133     case ISA:
1134     case ALIASES:
1135     case ARR:
1136     assert(def!=NULL);
1137     desc = CreateArrayTypeDesc(StatementModule(stat),def,
1138     intset,0,0,0,indices);
1139     break;
1140     default:
1141 johnpye 529 STATEMENT_ERROR(stat, "Utter screw-up in MakeSparseArray");
1142 aw0a 1 Asc_Panic(2, NULL, "Utter screw-up in MakeSparseArray");
1143     }
1144     aryinst = CreateArrayInstance(desc,1);
1145     LinkToParentByName(parent,aryinst,NameIdPtr(name));
1146     return AddArrayChild(parent,name,stat,rhsinst,arginst,rhslist);
1147     } else {
1148     return NULL;
1149     }
1150     }
1151    
1152 johnpye 707 /*------------------------------------------------------------------------------
1153     ...
1154     */
1155    
1156     /**
1157     handles construction of alias statements, allegedly, per lhs.
1158     parent function should find rhs and send it in as rhsinst.
1159     rhsinst == null should never be used with this function.
1160     currently, arrays ignored, fatally.
1161     */
1162 aw0a 1 static
1163     void MakeAliasInstance(CONST struct Name *name,
1164     CONST struct TypeDescription *basedef,
1165     struct Instance *rhsinst,
1166     struct gl_list_t *rhslist,
1167     int intset,
1168     struct Instance *parent,
1169     struct Statement *statement)
1170     {
1171     symchar *childname;
1172     int changed;
1173     unsigned long pos;
1174     struct Instance *inst;
1175     struct InstanceName rec;
1176     struct TypeDescription *arydef, *def;
1177     struct gl_list_t *indices;
1178     int tce;
1179     assert(rhsinst != NULL || rhslist !=NULL); /* one required */
1180     assert(rhsinst == NULL || rhslist ==NULL); /* only one allowed */
1181     childname = SimpleNameIdPtr(name);
1182     if (childname !=NULL){
1183     /* case of simple part name */
1184     if (StatInFOR(statement) && StatWrong(statement)==0) {
1185     MarkStatContext(statement,context_WRONG);
1186 johnpye 529 STATEMENT_ERROR(statement,"Unindexed statement in FOR loop not allowed.");
1187 aw0a 1 WSS(ASCERR,statement);
1188     return;
1189     }
1190     SetInstanceNameType(rec,StrName);
1191     SetInstanceNameStrPtr(rec,childname);
1192     pos = ChildSearch(parent,&rec);
1193     if (pos>0){
1194     /* case of part expected */
1195     if (InstanceChild(parent,pos)==NULL){
1196     /* case of part not there yet */
1197     inst = rhsinst;
1198     StoreChildPtr(parent,pos,inst);
1199     if (SearchForParent(inst,parent)==0) {
1200     /* case where we don't already have it at this scope */
1201     AddParent(inst,parent);
1202     }
1203     } else{ /* redefining instance */
1204     /* case of part already there and we barf */
1205 johnpye 709 char *msg = ASC_NEW_ARRAY(char,SCLEN(childname)+strlen(REDEFINE_CHILD_MESG2)+1);
1206 aw0a 1 strcpy(msg,REDEFINE_CHILD_MESG2);
1207     strcat(msg,SCP(childname));
1208 johnpye 529 STATEMENT_ERROR(statement,msg);
1209 aw0a 1 ascfree(msg);
1210     }
1211     } else{ /* unknown child name */
1212     /* case of part not expected */
1213 johnpye 529 STATEMENT_ERROR(statement, "Unknown child name. Never should happen");
1214 aw0a 1 Asc_Panic(2, NULL, "Unknown child name. Never should happen");
1215     }
1216     } else{
1217     /* if reach the else, means compound identifier or garbage */
1218     indices = ArrayIndices(name,parent);
1219     if (rhsinst != NULL) {
1220     def = InstanceTypeDesc(rhsinst);
1221     } else {
1222     def = (struct TypeDescription *)basedef;
1223     }
1224     if (indices!=NULL){ /* array of some sort */
1225     childname = NameIdPtr(name);
1226     SetInstanceNameType(rec,StrName);
1227     SetInstanceNameStrPtr(rec,childname);
1228     pos = ChildSearch(parent,&rec);
1229     if (!StatInFOR(statement)) {
1230     /* rectangle arrays */
1231     arydef = CreateArrayTypeDesc(StatementModule(statement),
1232     def,intset,0,0,0,indices);
1233     if (pos>0) {
1234     inst = CreateArrayInstance(arydef,1);
1235     if (inst!=NULL){
1236     changed = 0;
1237     tce = TryChildExpansion(inst,parent,&changed,rhsinst,NULL,rhslist);
1238     /* we're not in a for loop, so can't fail unless user is idiot. */
1239     LinkToParentByPos(parent,inst,pos); /* don't want to lose memory */
1240     /* if user is idiot, whine. */
1241     if (tce != 0) {
1242     SignalChildExpansionFailure(parent,pos);
1243     }
1244     } else {
1245 johnpye 529 STATEMENT_ERROR(statement, "Unable to create alias array instance");
1246 aw0a 1 Asc_Panic(2, NULL, "Unable to create alias array instance");
1247     }
1248     } else {
1249     DeleteTypeDesc(arydef);
1250 johnpye 529 STATEMENT_ERROR(statement,
1251 aw0a 1 "Unknown array child name. Never should happen");
1252     Asc_Panic(2, NULL, "Unknown array child name. Never should happen");
1253     }
1254     } else {
1255     /* sparse array */
1256     DestroyIndexList(indices);
1257     if (pos>0) {
1258     if (InstanceChild(parent,pos)==NULL) {
1259     /* need to make alias array */
1260     /* should check for NULL return here */
1261     (void)
1262     MakeSparseArray(parent,name,statement,def,
1263     intset,rhsinst,NULL,rhslist);
1264     } else {
1265     /* need to add alias array element */
1266     /* should check for NULL return here */
1267     (void) AddArrayChild(parent,name,statement,
1268     rhsinst,NULL,rhslist);
1269     }
1270     } else {
1271 johnpye 529 STATEMENT_ERROR(statement,
1272 aw0a 1 "Unknown array child name. Never should happen");
1273     Asc_Panic(2, NULL, "Unknown array child name. Never should happen");
1274     }
1275     }
1276     } else {
1277     /* bad child name. cannot create parts of parts. should never
1278     * happen, being trapped out in typelint.
1279     */
1280 johnpye 529 STATEMENT_ERROR(statement,"Bad ALIASES child name.");
1281 aw0a 1 }
1282     }
1283     }
1284    
1285 johnpye 707 /**
1286     @return 1 if concluded with statement, 0 if might try later.
1287     */
1288 aw0a 1 static
1289     int ExecuteALIASES(struct Instance *inst, struct Statement *statement)
1290     {
1291     CONST struct VariableList *vlist;
1292     struct gl_list_t *rhslist;
1293     struct Instance *rhsinst;
1294     CONST struct Name *name;
1295     enum find_errors ferr;
1296     int intset;
1297    
1298     assert(StatementType(statement)==ALIASES);
1299     if (StatWrong(statement)) {
1300     /* incorrect statements should be warned about when they are
1301     * marked wrong, so we just ignore them here.
1302     */
1303     return 1;
1304     }
1305     if (!CheckALIASES(inst,statement)) {
1306     WriteUnexecutedMessage(ASCERR,statement,
1307     "Possibly undefined sets/ranges in ALIASES statement.");
1308     return 0;
1309     }
1310     name = AliasStatName(statement);
1311     rhslist = FindInstances(inst,name,&ferr);
1312     if (rhslist == NULL) {
1313     WriteUnexecutedMessage(ASCERR,statement,
1314     "Possibly undefined right hand side in ALIASES statement.");
1315     return 0; /* rhs not compiled yet */
1316     }
1317     if (gl_length(rhslist)>1) {
1318 johnpye 529 STATEMENT_ERROR(statement,"ALIASES needs exactly 1 RHS");
1319 aw0a 1 gl_destroy(rhslist);
1320     return 1; /* rhs not unique for current values of sets */
1321     }
1322     rhsinst = (struct Instance *)gl_fetch(rhslist,1);
1323     gl_destroy(rhslist);
1324     if (InstanceKind(rhsinst)==REL_INST || LREL_INST ==InstanceKind(rhsinst)) {
1325 johnpye 529 STATEMENT_ERROR(statement,"Direct ALIASES of relations are not permitted");
1326 aw0a 1 MarkStatContext(statement,context_WRONG);
1327     WSS(ASCERR,statement);
1328     return 1; /* relations only aliased through models */
1329     }
1330     intset = ( (InstanceKind(rhsinst)==SET_ATOM_INST) &&
1331     (IntegerSetInstance(rhsinst)) );
1332     vlist = GetStatVarList(statement);
1333     while (vlist!=NULL){
1334     MakeAliasInstance(NamePointer(vlist),NULL,rhsinst,
1335     NULL,intset,inst,statement);
1336     vlist = NextVariableNode(vlist);
1337     }
1338     return 1;
1339     }
1340    
1341    
1342 johnpye 707 /*------------------------------------------------------------------------------
1343     SUPPORT FOR ALIASES-IS_A STATEMENTS
1344     */
1345 aw0a 1
1346 johnpye 707 /**
1347     enforce max len and no-apostrope (') rules for subscripts. string returned
1348     may not be string sent.
1349     */
1350 aw0a 1 static
1351     char *DeSingleQuote(char *s)
1352     {
1353     char *old;
1354     int len;
1355     if (s==NULL) {
1356     return s;
1357     }
1358     len = strlen(s);
1359     if (len > 40) {
1360     old = s;
1361 johnpye 708 s = ASC_NEW_ARRAY(char,41);
1362 aw0a 1 strncpy(s,old,17);
1363     s[17] = '.';
1364     s[18] = '.';
1365     s[19] = '.';
1366     s[20] = '\0';
1367     strcat(s,(old+len-20));
1368     ascfree(old);
1369     }
1370     old = s;
1371     while (*s != '\0') {
1372     if (*s =='\'') {
1373     *s = '_';
1374     }
1375     s++;
1376     }
1377    
1378     return old;
1379     }
1380    
1381 johnpye 707 /**
1382     returns a symchar based on but not in strset,
1383     and adds original and results to sym table.
1384     destroys the s given.
1385     */
1386 aw0a 1 static
1387     symchar *UniquifyString(char *s, struct set_t *strset)
1388     {
1389     int oldlen, maxlen, c;
1390     char *new;
1391     symchar *tmp;
1392    
1393     tmp = AddSymbol(s);
1394     if (StrMember(tmp,strset)!=0) {
1395     oldlen = strlen(s);
1396     maxlen = oldlen+12;
1397     new = ascrealloc(s,oldlen+14);
1398     assert(new!=NULL);
1399     while ( (oldlen+1) < maxlen) {
1400     new[oldlen+1] = '\0';
1401     for(c = 'a'; c <= 'z'; c++){
1402 jds 97 new[oldlen] = (char)c;
1403 aw0a 1 tmp = AddSymbol(new);
1404     if (StrMember(tmp,strset)==0) {
1405     ascfree(new);
1406     return tmp;
1407     }
1408     }
1409     oldlen++;
1410     }
1411     Asc_Panic(2, NULL,
1412     "Unable to generate unique compound alias subscript.\n");
1413 johnpye 709
1414 aw0a 1 } else {
1415     ascfree(s);
1416     return tmp;
1417     }
1418     }
1419    
1420     static
1421     struct value_t GenerateSubscripts(struct Instance *iref,
1422     struct gl_list_t *rhslist,
1423     int intset)
1424     {
1425     struct set_t *setinstval;
1426     unsigned long c,len;
1427     char *str;
1428     symchar *sym;
1429    
1430     setinstval = CreateEmptySet();
1431     len = gl_length(rhslist);
1432     if (intset!=0) {
1433     /* create subscripts 1..rhslistlen */
1434     for (c=1;c<=len; c++) {
1435     AppendIntegerElement(setinstval,c);
1436     }
1437     return CreateSetValue(setinstval);
1438     }
1439     /* create string subscripts */
1440     for (c=1; c<= len; c++) {
1441     str = WriteInstanceNameString((struct Instance *)gl_fetch(rhslist,c),iref);
1442     str = DeSingleQuote(str); /* transmogrify for length and ' marks */
1443     sym = UniquifyString(str,setinstval); /* convert to symbol and free str */
1444     AppendStringElement(setinstval,sym);
1445     }
1446     return CreateSetValue(setinstval);
1447     }
1448    
1449     static
1450     void DestroyArrayElements(struct gl_list_t *rhslist)
1451     {
1452     unsigned long c,len;
1453     if (rhslist==NULL){
1454     return;
1455     }
1456     for (c=1, len = gl_length(rhslist); c <= len; c++) {
1457     FREEPOOLAC(gl_fetch(rhslist,c));
1458     }
1459     gl_destroy(rhslist);
1460     }
1461    
1462 johnpye 707 /**
1463     this function computes the subscript set (or generates it if
1464     needed) and checks it for matching against the instance list
1465     and whines when things aren't kosher.
1466     When things are kosher, creates a gl_list of array children.
1467     This list is returned through rhslist.
1468     */
1469 aw0a 1 static
1470     struct value_t ComputeArrayElements(struct Instance *inst,
1471     struct Statement *statement,
1472     struct gl_list_t *rhsinstlist,
1473     struct gl_list_t **rhslist)
1474     {
1475     struct value_t subslist;
1476     struct value_t subscripts;
1477     struct value_t result; /* return value is the expanded subscript set */
1478     CONST struct Set *setp;
1479     struct set_t *sip;
1480     int intset;
1481     unsigned long c, len;
1482     struct ArrayChild *ptr;
1483    
1484     assert((*rhslist)==NULL && rhsinstlist != NULL && rhslist != NULL);
1485    
1486     intset = ArrayStatIntSet(statement);
1487     len = gl_length(rhsinstlist);
1488     setp = ArrayStatSetValues(statement);
1489     if (setp==NULL) {
1490     /* value generated is a set and automatically is of correct CARD() */
1491     result = GenerateSubscripts(inst,rhsinstlist,intset);
1492     /* fill up rhslist and return */
1493     *rhslist = gl_create(len);
1494     sip = SetValue(result);
1495     if (intset != 0) {
1496     for (c = 1; c <= len; c++) {
1497     ptr = MALLOCPOOLAC;
1498     ptr->inst = gl_fetch(rhsinstlist,c);
1499     ptr->name.index = FetchIntMember(sip,c);
1500     gl_append_ptr(*rhslist,(VOIDPTR)ptr);
1501     }
1502     } else {
1503     for (c = 1; c <= len; c++) {
1504     ptr = MALLOCPOOLAC;
1505     ptr->inst = gl_fetch(rhsinstlist,c);
1506     ptr->name.str = FetchStrMember(sip,c);
1507     gl_append_ptr(*rhslist,(VOIDPTR)ptr);
1508     }
1509     }
1510     return result;
1511     } else {
1512     /* cook up the users list */
1513     assert(GetEvaluationContext()==NULL);
1514     SetEvaluationContext(inst);
1515     subslist = EvaluateSet(setp,InstanceEvaluateName);
1516     SetEvaluationContext(NULL);
1517     /* check that it evaluates */
1518     if (ValueKind(subslist)==error_value) {
1519     switch(ErrorValue(subslist)) {
1520     case name_unfound:
1521     case undefined_value:
1522     DestroyValue(&subslist);
1523     WriteUnexecutedMessage(ASCERR,statement,
1524     "Undefined values in WITH_VALUE () list");
1525     return CreateErrorValue(undefined_value);
1526     default:
1527 johnpye 529 STATEMENT_ERROR(statement,"Bad result in evaluating WITH_VALUE list\n");
1528 aw0a 1 MarkStatContext(statement,context_WRONG);
1529     WSS(ASCERR,statement);
1530     DestroyValue(&subslist);
1531     }
1532     }
1533     /* collect sets to assign later */
1534     result = CreateSetFromList(subslist); /* unique list */
1535     ListMode=1;
1536     subscripts = CreateOrderedSetFromList(subslist); /* as ordered to insts */
1537     ListMode=0;
1538     DestroyValue(&subslist); /* done with it */
1539     /* check everything dumb that can happen */
1540     if ( ValueKind(result) != set_value ||
1541     Cardinality(SetValue(subscripts)) != Cardinality(SetValue(result))
1542     ) {
1543     DestroyValue(&result);
1544     DestroyValue(&subscripts);
1545 johnpye 529 STATEMENT_ERROR(statement,
1546 aw0a 1 "WITH_VALUE list does not form a proper subscript set.\n");
1547     MarkStatContext(statement,context_WRONG);
1548     WSS(ASCERR,statement);
1549     return CreateErrorValue(type_conflict);
1550     }
1551     /* check sanity of values. may need fixing around empty set. */
1552     if ( (SetKind(SetValue(subscripts))==integer_set) != (intset!=0)) {
1553 johnpye 529 STATEMENT_ERROR(statement,
1554 aw0a 1 "Unable to construct set. Values and set type mismatched\n");
1555     DestroyValue(&result);
1556     DestroyValue(&subscripts);
1557     MarkStatContext(statement,context_WRONG);
1558     WSS(ASCERR,statement);
1559     return CreateErrorValue(type_conflict);
1560     }
1561     /* check set size == instances to alias */
1562     if (Cardinality(SetValue(subscripts)) != len) {
1563 johnpye 529 STATEMENT_ERROR(statement,"In: ");
1564 aw0a 1 FPRINTF(ASCERR,
1565     "WITH_VALUE list length (%lu) != number of instances given (%lu)\n",
1566     Cardinality(SetValue(subscripts)),len);
1567     DestroyValue(&result);
1568     DestroyValue(&subscripts);
1569     MarkStatContext(statement,context_WRONG);
1570     WSS(ASCERR,statement);
1571     return CreateErrorValue(type_conflict);
1572     }
1573     /* fill up rhslist and return */
1574     *rhslist = gl_create(len);
1575     sip = SetValue(subscripts);
1576     if (intset != 0) {
1577     for (c = 1; c <= len; c++) {
1578     ptr = MALLOCPOOLAC;
1579     ptr->inst = gl_fetch(rhsinstlist,c);
1580     ptr->name.index = FetchIntMember(sip,c);
1581     gl_append_ptr(*rhslist,(VOIDPTR)ptr);
1582     }
1583     } else {
1584     for (c = 1; c <= len; c++) {
1585     ptr = MALLOCPOOLAC;
1586     ptr->inst = gl_fetch(rhsinstlist,c);
1587     ptr->name.str = FetchStrMember(sip,c);
1588     gl_append_ptr(*rhslist,(VOIDPTR)ptr);
1589     }
1590     }
1591     DestroyValue(&subscripts);
1592     return result;
1593     }
1594     }
1595    
1596 johnpye 707 /**
1597     @return 1 if concluded with statement, 0 if might try later.
1598     */
1599 aw0a 1 static
1600     int ExecuteARR(struct Instance *inst, struct Statement *statement)
1601     {
1602     CONST struct VariableList *vlist;
1603     struct gl_list_t *rhsinstlist; /* list of instances found to alias */
1604     struct gl_list_t *setinstl; /* instance found searching for IS_A'd set */
1605     struct gl_list_t *rhslist=NULL; /* list of arraychild structures */
1606     struct value_t subsset;
1607     #ifndef NDEBUG
1608     struct Instance *rhsinst;
1609     #endif
1610     struct Instance *setinst;
1611     enum find_errors ferr;
1612     CONST struct TypeDescription *basedef;
1613     ChildListPtr icl;
1614     int intset;
1615    
1616     assert(StatementType(statement)==ARR);
1617     if (StatWrong(statement)) {
1618     /* incorrect statements should be warned about when they are
1619     * marked wrong, so we just ignore them here.
1620     */
1621     return 1;
1622     }
1623     if (!CheckARR(inst,statement)) {
1624     WriteUnexecutedMessage(ASCERR,statement,
1625     "Possibly undefined instances/sets/ranges in ALIASES-IS_A statement.");
1626     return 0;
1627     }
1628     rhsinstlist = FindInsts(inst,GetStatVarList(statement),&ferr);
1629     if (rhsinstlist == NULL) {
1630     MissingInsts(inst,GetStatVarList(statement),0);
1631     WriteUnexecutedMessage(ASCERR,statement,
1632     "Incompletely defined source instance list in ALIASES-IS_A statement.");
1633     return 0; /* rhs's not compiled yet */
1634     }
1635     /* check for illegal rhs types. parser normally bars this. */
1636     #ifndef NDEBUG
1637     if (gl_length(rhsinstlist) >0) {
1638     rhsinst = (struct Instance *)gl_fetch(rhsinstlist,1);
1639     if (BaseTypeIsEquation(InstanceTypeDesc(rhsinst))) {
1640 johnpye 529 STATEMENT_ERROR(statement,
1641 aw0a 1 "Direct ALIASES of rels/lrels/whens are not permitted");
1642     MarkStatContext(statement,context_WRONG);
1643     WSS(ASCERR,statement);
1644     gl_destroy(rhsinstlist);
1645     return 1; /* (log)relations/whens only aliased through models */
1646     }
1647     }
1648     #endif
1649     /* evaluate name list, if given, OTHERWISE generate it, and check CARD.
1650     * issues warnings as needed
1651     */
1652     subsset = ComputeArrayElements(inst,statement,rhsinstlist,&rhslist);
1653     gl_destroy(rhsinstlist);
1654     /* check return values of subsset and rhslist here */
1655     if (ValueKind(subsset)== error_value) {
1656     if (ErrorValue(subsset) == undefined_value) {
1657     DestroyValue(&subsset);
1658     return 0;
1659     } else {
1660     DestroyValue(&subsset);
1661     return 1;
1662     }
1663     }
1664     assert(rhslist!=NULL); /* might be empty, but not NULL */
1665     /* make set ATOM */
1666     vlist = ArrayStatSetName(statement);
1667     intset = ArrayStatIntSet(statement);
1668     MakeInstance(NamePointer(vlist),FindSetType(),intset,inst,statement,NULL);
1669     /* get instance and assign. */
1670     setinstl = FindInstances(inst,NamePointer(vlist),&ferr);
1671     if (setinstl == NULL || gl_length(setinstl) != 1L) {
1672     FPRINTF(ASCERR,"Unable to construct set.\n");
1673     FPRINTF(ASCERR,"Bizarre error in ALIASES-IS_A. Please report it to:\n%s",
1674     ASC_BIG_BUGMAIL);
1675     if (setinstl!=NULL) {
1676     gl_destroy(setinstl);
1677     }
1678     DestroyArrayElements(rhslist);
1679     DestroyValue(&subsset);
1680     MarkStatContext(statement,context_WRONG);
1681     WSS(ASCERR,statement);
1682     /* should nuke entire compound ALIASES/IS_A array pair already built */
1683     return 1;
1684     } else {
1685     setinst = (struct Instance *)gl_fetch(setinstl,1);
1686     gl_destroy(setinstl);
1687     AssignSetAtomList(setinst,CopySet(SetValue(subsset)));
1688     DestroyValue(&subsset);
1689     }
1690    
1691     /* create ALIASES-IS_A array */
1692     /* recycle the local pointer to our set ATOM to check base type of rhslist */
1693     setinst = CAC(gl_fetch(rhslist,1))->inst;
1694     intset = ( InstanceKind(setinst)==SET_ATOM_INST &&
1695     IntegerSetInstance(setinst)!=0 );
1696     /* the real question is does anyone downstream care if intset correct?
1697     * probably not since its an alias anyway.
1698     */
1699     vlist = ArrayStatAvlNames(statement);
1700     icl = GetChildList(InstanceTypeDesc(inst));
1701     basedef = ChildBaseTypePtr(icl,ChildPos(icl,NameIdPtr(NamePointer(vlist))));
1702     while (vlist!=NULL){
1703     /* fix me for sparse case. dense ok. */
1704     MakeAliasInstance(NamePointer(vlist), basedef,NULL,
1705     rhslist, intset, inst, statement);
1706     vlist = NextVariableNode(vlist);
1707     }
1708     /* clean up memory */
1709     DestroyArrayElements(rhslist);
1710    
1711     return 1;
1712     }
1713    
1714 johnpye 707 /*------------------------------------------------------------------------------
1715     ...
1716     */
1717     /**
1718     Makes a single instance of the type given,which must not be array
1719     or relation of any kind or when.
1720    
1721     If type is a MODEL, adds the MODEL to pending list.
1722    
1723     The argument intset is only used if type is set, then
1724     if intset==1, set ATOM made will be integer set.
1725    
1726     Attempts to find a UNIVERSAL before making the instance.
1727    
1728     @param statement only used for error messages.
1729     */
1730 aw0a 1 static
1731     struct Instance *MakeSimpleInstance(struct TypeDescription *def,
1732     int intset,
1733     struct Statement *statement,
1734     struct Instance *arginst)
1735     {
1736     struct Instance *inst;
1737    
1738     inst = ShortCutMakeUniversalInstance(def);
1739     if (inst==NULL) {
1740     switch(GetBaseType(def)){
1741     case model_type:
1742     inst = CreateModelInstance(def); /* if we are here - build one */
1743     if (!GetUniversalFlag(def)||!InstanceInList(inst)) {
1744     /* add PENDING model if not UNIVERSAL, or UNIVERSAL and
1745     * this is the very first time seen - don't ever want an instance
1746     * in the pending list twice.
1747     */
1748     /*
1749     * here we need to shuffle in info from arginst.
1750     * note that because this is inside the UNIVERSAL check,
1751     * only the first set of arguments to a UNIVERSAL type will
1752     * ever apply.
1753     */
1754     ConfigureInstFromArgs(inst,arginst);
1755     AddBelow(NULL,inst);
1756     }
1757     break;
1758     case real_type:
1759     case real_constant_type:
1760     inst = CreateRealInstance(def);
1761     break;
1762     case boolean_type:
1763     case boolean_constant_type:
1764     inst = CreateBooleanInstance(def);
1765     break;
1766     case integer_type:
1767     case integer_constant_type:
1768     inst = CreateIntegerInstance(def);
1769     break;
1770     case set_type:
1771     inst = CreateSetInstance(def,intset);
1772     break;
1773     case symbol_type:
1774     case symbol_constant_type:
1775     inst = CreateSymbolInstance(def);
1776     break;
1777     case relation_type:
1778     inst = NULL;
1779 johnpye 190 FPRINTF(ASCERR,"Type '%s' is not allowed in IS_A.\n",
1780 aw0a 1 SCP(GetBaseTypeName(relation_type)));
1781     case logrel_type:
1782     inst = NULL;
1783     FPRINTF(ASCERR,"Type '%s' is not allowed in IS_A.\n",
1784     SCP(GetBaseTypeName(logrel_type)));
1785     break;
1786     case when_type:
1787     inst = NULL;
1788     FPRINTF(ASCERR,"Type '%s' is not allowed in IS_A.\n",
1789     SCP(GetBaseTypeName(when_type)));
1790     break;
1791     case array_type:
1792     default: /* picks up patch_type */
1793 johnpye 529 STATEMENT_ERROR(statement, "MakeSimpleInstance error. PATCH/ARRAY found.\n");
1794 aw0a 1 Asc_Panic(2, NULL, "MakeSimpleInstance error. PATCH/ARRAY found.\n");
1795     }
1796     }
1797     return inst;
1798     }
1799    
1800     static unsigned long g_unasscon_count = 0L;
1801     /* counter for the following functions */
1802     static
1803     void CountUnassignedConst(struct Instance *i)
1804     {
1805     if (i!=NULL && (IsConstantInstance(i) || InstanceKind(i)==SET_ATOM_INST) ) {
1806     if (AtomAssigned(i)==0) {
1807     g_unasscon_count++;
1808     }
1809     }
1810     }
1811 johnpye 707 /**
1812     Returns 0 if all constant scalars in ipass are assigned,
1813     for ipass that are of set/scalar array/scalar type.
1814     Handles null input gracefully, as if there is something
1815     unassigned in it.
1816     Variable types are considered permanently assigned, since
1817     we are checking for constants being unassigned.
1818     Assumes arrays, if passed in, are fully expanded.
1819     */
1820 aw0a 1 static
1821     int ArgValuesUnassigned(struct Instance *ipass)
1822     {
1823     struct TypeDescription *abd;
1824     if (ipass==NULL) return 1;
1825     switch (InstanceKind(ipass)) {
1826     case ERROR_INST:
1827     return 1;
1828     case SIM_INST:
1829     case MODEL_INST:
1830     case REL_INST:
1831     case LREL_INST:
1832     case WHEN_INST:
1833     return 0;
1834     case ARRAY_INT_INST:
1835     case ARRAY_ENUM_INST:
1836     abd = GetArrayBaseType(InstanceTypeDesc(ipass));
1837     if (BaseTypeIsConstant(abd)==0 && BaseTypeIsSet(abd)==0) {
1838     return 0;
1839     }
1840     g_unasscon_count = 0;
1841     SilentVisitInstanceTree(ipass,CountUnassignedConst,0,0);
1842     if (g_unasscon_count != 0) {
1843     return 1;
1844     } else {
1845     return 0;
1846     }
1847     case REAL_INST:
1848     case INTEGER_INST:
1849     case BOOLEAN_INST:
1850     case SYMBOL_INST:
1851     case SET_INST:
1852     case REAL_ATOM_INST:
1853     case INTEGER_ATOM_INST:
1854     case BOOLEAN_ATOM_INST:
1855     case SYMBOL_ATOM_INST:
1856     return 0;
1857     case SET_ATOM_INST:
1858     case REAL_CONSTANT_INST:
1859     case BOOLEAN_CONSTANT_INST:
1860     case INTEGER_CONSTANT_INST:
1861     case SYMBOL_CONSTANT_INST:
1862     return (AtomAssigned(ipass)==0); /* return 0 if assigned, 1 not */
1863     default:
1864     return 1; /* NOTREACHED */
1865     }
1866     }
1867 johnpye 707 /**
1868     Appends the pointers in the set chain s
1869     into the list given args. args must not be NULL unless s is.
1870    
1871     If needed, args will be expanded, but if you know the length
1872     to expect, make args of that size before calling and this
1873     will be faster.
1874    
1875     This does not go into the expressions (which may contain other
1876     sets themselves) of the set nodes and disassemble them.
1877     The list may be safely destroyed, but its contents should not
1878     be destroyed with it as they belong to something else in all
1879     likelihood.
1880    
1881     @TODO This function should be moved into a set header someplace.
1882     */
1883 aw0a 1 static
1884     void SplitArgumentSet(CONST struct Set *s, struct gl_list_t *args)
1885     {
1886     struct Set *sp;
1887     if (s==NULL) return;
1888     assert(args !=NULL); /* debug WriteSet(ASCERR,s); FPRINTF(ASCERR,"\n"); */
1889     while (s!=NULL) {
1890     sp = CopySetNode(s);
1891     gl_append_ptr(args,(VOIDPTR)sp);
1892     s = NextSet(s);
1893     }
1894     }
1895    
1896     #define GETARG(l,n) ((struct Set *)gl_fetch((l),(n)))
1897    
1898 johnpye 707 /**
1899     Check compatibility of array elements? -- JP
1900    
1901     @return 1 if all ok, 0 if any array child is < type required,
1902     -1 if some array child is type incompatible with ptype/stype.
1903    
1904     Does some optimization around arrays of sets and array basetypes.
1905     Doesn't check names.
1906     */
1907 aw0a 1 static
1908     int ArrayElementsTypeCompatible(CONST struct Instance *ipass,
1909     CONST struct TypeDescription *ptype,
1910     symchar *stype)
1911     {
1912     struct gl_list_t *achildren=NULL;
1913     CONST struct TypeDescription *atype;
1914     CONST struct TypeDescription *mrtype;
1915     unsigned long c,len,lessrefined=0L;
1916     struct Instance *i;
1917    
1918     if (ipass==NULL || ptype == NULL) {
1919     return -1; /* hosed input */
1920     }
1921     assert(IsArrayInstance(ipass) != 0);
1922     atype = GetArrayBaseType(InstanceTypeDesc(ipass));
1923     if (BaseTypeIsSet(atype)==0 && MoreRefined(atype,ptype)==atype) {
1924     /* if not set and if array base is good enough */
1925     return 1;
1926     }
1927     achildren = CollectArrayInstances(ipass,NULL);
1928     len = gl_length(achildren);
1929     for (c = 1; c <= len; c++) {
1930     i = (struct Instance *)gl_fetch(achildren,c);
1931     atype = InstanceTypeDesc(i);
1932     if (InstanceKind(i) == SET_ATOM_INST) {
1933     /* both should be of same type "set" */
1934     if (atype!=ptype ||
1935 johnpye 190 (IntegerSetInstance(i)==0 &&
1936 aw0a 1 stype == GetBaseTypeName(integer_constant_type))
1937 johnpye 190 || (IntegerSetInstance(i)==1 &&
1938 aw0a 1 stype == GetBaseTypeName(symbol_constant_type))
1939     ) {
1940     /* set type mismatch */
1941     gl_destroy(achildren);
1942     return -1;
1943     } else {
1944     /* assumption about arrays of sets being sane, if 1 element is. */
1945     gl_destroy(achildren);
1946     return 1;
1947     }
1948     }
1949     if (ptype==atype) {
1950     continue;
1951     }
1952     mrtype = MoreRefined(ptype,atype);
1953     if (mrtype == NULL) {
1954     gl_destroy(achildren);
1955     return -1;
1956     }
1957     if (mrtype == ptype) {
1958     lessrefined++;
1959     }
1960     }
1961     gl_destroy(achildren);
1962     return (lessrefined==0L); /* if any elements are inadequately refined, 0 */
1963     }
1964    
1965 johnpye 707 /**
1966     returns a value_t, but the real result is learned by consulting err.
1967     err == 0 means some interesting value found.
1968     err == 1 means try again later
1969     err == -1 means things are hopeless.
1970     */
1971 aw0a 1 static
1972     struct value_t FindArgValue(struct Instance *parent,
1973     struct Set *argset,
1974     int *err)
1975     {
1976     int previous_context;
1977     struct value_t value;
1978    
1979     assert(err!=NULL);
1980     *err=0;
1981     previous_context = GetDeclarativeContext();
1982     SetDeclarativeContext(0);
1983     assert(GetEvaluationContext()==NULL);
1984     SetEvaluationContext(parent);
1985     value = EvaluateExpr(GetSingleExpr(argset),
1986     NULL,
1987     InstanceEvaluateName);
1988     SetEvaluationContext(NULL);
1989     SetDeclarativeContext(previous_context);
1990     if (ValueKind(value)==error_value) {
1991     switch(ErrorValue(value)){
1992     case name_unfound:
1993     *err = 1;
1994     DestroyValue(&value);
1995     return CreateErrorValue(undefined_value);
1996     case undefined_value:
1997     *err = 1;
1998     return value;
1999     default:
2000     *err = -1;
2001     }
2002     }
2003     if (IsConstantValue(value)==0){
2004     *err = -1;
2005     DestroyValue(&value);
2006     return CreateErrorValue(type_conflict);
2007     }
2008     return value;
2009     }
2010    
2011     /* return codes and message handling for MakeParameterInst */
2012     #define MPIOK 1
2013     #define MPIWAIT 0
2014     #define MPIINPUT -1
2015     #define MPIARGTYPE -2
2016     #define MPIARRINC -3
2017     #define MPIBADASS -4
2018     #define MPIARRRNG -5
2019     #define MPIINSMEM -6
2020     #define MPIBADARG -7
2021     #define MPIMULTI -8
2022     #define MPIBADVAL -9
2023     #define MPIWEIRD -10
2024     #define MPIUNMADE -11
2025     #define MPIWEAKTYPE -12
2026     #define MPIUNASSD -13
2027     #define MPIARGVAL -14
2028     #define MPIARGSIZ -15
2029     #define MPIBADWBTS -16
2030     #define MPIBADWNBTS -17
2031     #define MPIBADMERGE -18
2032     #define MPIREASGN -19
2033     #define MPIREDEF -20
2034     #define MPIFOR -21
2035     #define MPIBADREL -22
2036     #define MPIEXCEP -23
2037     #define MPIVARREL -24
2038     #define MPINOTBOOL -25
2039     static
2040     char *g_mpi_message[] = {
2041     /* 0 */ "Nothing wrong with parameter",
2042     /* -1 */ "Bad input statement or parent or arginstptr.",
2043     /* -2 */ "Incompatible argument type.",
2044     /* -3 */ "Incomplete assignment of absorbed pass-by-value array.",
2045     /* -4 */ "Error in absorbed assignment RHS.",
2046     /* -5 */ "Mismatch in range of array subscripts.",
2047     /* -6 */ "Insufficient memory - crashing soon",
2048     /* -7 */ "Nonexistent argument. (bad set in array expression, probably)",
2049     /* -8 */ "Too many instances named for 1 parameter slot",
2050     /* -9 */ "Bad expression passed to IS_A",
2051     /* -10 */ "Something rotten in lint",
2052     /* -11 */ "Instance doesn't yet exist",
2053     /* -12 */ "Instance not sufficiently refined",
2054     /* -13 */ "Argument value not assigned",
2055     /* -14 */ "Argument value != required value",
2056     /* -15 */ "Array object given has with too many/too few subscripts.",
2057     /* -16 */ "Incorrect instance named in WILL_BE_THE_SAME.",
2058     /* -17 */ "Nonexistent instance named in WILL_NOT_BE_THE_SAME.",
2059     /* -18 */ "Merged instances found in WILL_NOT_BE_THE_SAME.",
2060     /* -19 */ "Refinement cannot reassign constant value.",
2061     /* -20 */ "Refinement must pass in same objects used in IS_A.",
2062     /* -21 */ "Improper FOR loop in WHERE statements",
2063     /* -22 */ "WHERE condition unsatisfied",
2064     /* -23 */ "WHERE condition incorrect (system exception occurred)",
2065     /* -24 */ "WHERE condition incorrect (nonconstant value)",
2066     /* -25 */ "WHERE condition incorrect (nonboolean value)"
2067     };
2068    
2069 johnpye 707 /**
2070     Returns MPIOK if value in ipass matches WITH_VALUE field of
2071     statement, or if the test is silly beacause ipass isn't
2072     a set/constant or if statement does not constrain value.
2073     Returns MPIWAIT if statement truth cannot be tested because
2074     WITH_VALUE clause is not yet evaluatable.
2075     Returns MPIARGVAL if WITH_VALUE is provably unsatisfied.
2076     On truly garbage input, unlikely to return.
2077     */
2078 aw0a 1 static
2079     int ArgValueCorrect(struct Instance *inst,
2080     struct Instance *tmpinst,
2081     CONST struct Statement *statement)
2082     {
2083     CONST struct Expr *check;
2084     int previous_context;
2085     struct value_t value;
2086    
2087     assert (inst!=NULL);
2088     assert (tmpinst!=NULL);
2089     assert (statement!=NULL);
2090    
2091     if ( StatementType(statement)!= WILLBE ||
2092     (check = GetStatCheckValue(statement)) == NULL ||
2093     ( IsConstantInstance(inst) ==0 &&
2094     InstanceKind(inst) != SET_ATOM_INST)
2095     ) {
2096     return MPIOK;
2097     }
2098     if (!AtomAssigned(inst)) {
2099     return MPIWAIT;
2100     }
2101     previous_context = GetDeclarativeContext();
2102     SetDeclarativeContext(0);
2103     assert(GetEvaluationContext()==NULL);
2104     SetEvaluationContext(tmpinst);
2105     value = EvaluateExpr(check, NULL, InstanceEvaluateName);
2106     SetEvaluationContext(NULL);
2107     SetDeclarativeContext(previous_context);
2108     if (ValueKind(value)==error_value) {
2109     switch(ErrorValue(value)){
2110     case name_unfound:
2111     case undefined_value:
2112     DestroyValue(&value);
2113     return MPIWAIT;
2114     default:
2115     DestroyValue(&value);
2116     return MPIARGVAL;
2117     }
2118     }
2119     if (IsConstantValue(value)==0){
2120     DestroyValue(&value);
2121     FPRINTF(ASCERR,"Variable value found where constant required\n");
2122     return MPIARGVAL;
2123     }
2124     /* ok, so we have a reasonable inst type and a constant value */
2125     switch(InstanceKind(inst)){
2126     case REAL_CONSTANT_INST:
2127     switch(ValueKind(value)){
2128     case real_value:
2129     if ( ( RealValue(value) != RealAtomValue(inst) ||
2130     !SameDimen(RealValueDimensions(value),RealAtomDims(inst)) )
2131     ) {
2132     DestroyValue(&value);
2133     return MPIARGVAL;
2134     }
2135     break;
2136     case integer_value:
2137     if ( ( (double)IntegerValue(value) != RealAtomValue(inst) ||
2138     !SameDimen(Dimensionless(),RealAtomDims(inst)) )
2139     ) {
2140     DestroyValue(&value);
2141     return MPIARGVAL;
2142     }
2143     break;
2144     default:
2145     DestroyValue(&value);
2146     return MPIARGVAL;
2147     }
2148     break;
2149     case BOOLEAN_CONSTANT_INST:
2150     if (ValueKind(value)!=boolean_value ||
2151     BooleanValue(value) != GetBooleanAtomValue(inst) ) {
2152     DestroyValue(&value);
2153     return MPIARGVAL;
2154     }
2155     break;
2156     case INTEGER_CONSTANT_INST:
2157     switch(ValueKind(value)){
2158     case integer_value:
2159     if (GetIntegerAtomValue(inst)!=IntegerValue(value)) {
2160     DestroyValue(&value);
2161     return MPIARGVAL;
2162     }
2163     break;
2164     case real_value: /* case which is parser artifact: real, wild 0 */
2165     if ( RealValue(value)==0.0 &&
2166     IsWild(RealValueDimensions(value)) &&
2167     GetIntegerAtomValue(inst) != 0) {
2168     DestroyValue(&value);
2169     return MPIARGVAL;
2170     }
2171     break;
2172     default:
2173     DestroyValue(&value);
2174     return MPIARGVAL;
2175     }
2176     break;
2177     case SET_ATOM_INST:
2178     if (ValueKind(value)!=set_value ||
2179     !SetsEqual(SetValue(value),SetAtomList(inst))) {
2180     DestroyValue(&value);
2181     return MPIARGVAL;
2182     }
2183     break;
2184     case SYMBOL_CONSTANT_INST:
2185     if (ValueKind(value) != symbol_value ||
2186     SymbolValue(value) != GetSymbolAtomValue(inst)) {
2187     assert(AscFindSymbol(SymbolValue(value))!=NULL);
2188     DestroyValue(&value);
2189     return MPIARGVAL;
2190     }
2191     break;
2192     default:
2193     DestroyValue(&value);
2194     return MPIARGVAL;
2195     }
2196     DestroyValue(&value);
2197     return MPIOK;
2198     }
2199    
2200 johnpye 707 /**
2201     evaluate a logical or real relation and see that it is satisfied.
2202    
2203     @BUG baa. needs to be exception safe and is not.
2204    
2205     returns MPIOK (satisfied)
2206     returns MPIBADREL (dissatisified)
2207     returns MPIVARREL (dissatisified - variable result)
2208     returns MPIWAIT (not yet determinable)
2209     returns MPIEXCEP (evaluation is impossible due to float/other error)
2210     returns MPINOTBOOL (dissatisfied- nonboolean result)
2211    
2212     @param statement should be a rel or logrel.
2213     */
2214 aw0a 1 static
2215     int MPICheckConstraint(struct Instance *tmpinst, struct Statement *statement)
2216     {
2217     struct value_t value;
2218    
2219     IVAL(value);
2220    
2221     assert(GetEvaluationContext()==NULL);
2222     SetEvaluationContext(tmpinst);
2223     switch (StatementType(statement)){
2224     case REL:
2225     value = EvaluateExpr(RelationStatExpr(statement),NULL,
2226     InstanceEvaluateName);
2227     break;
2228     case LOGREL:
2229     value = EvaluateExpr(LogicalRelStatExpr(statement),NULL,
2230     InstanceEvaluateName);
2231     break;
2232     default:
2233     SetEvaluationContext(NULL);
2234     return MPIWEIRD;
2235     }
2236     SetEvaluationContext(NULL);
2237     switch (ValueKind(value)){
2238     case error_value:
2239     switch(ErrorValue(value)){
2240     case undefined_value:
2241     DestroyValue(&value);
2242     WriteUnexecutedMessage(ASCERR,statement,
2243     "Incomplete expression (value undefined) in argument condition.");
2244     return MPIWAIT;
2245     case name_unfound:
2246     DestroyValue(&value);
2247     WriteUnexecutedMessage(ASCERR,statement,
2248     "Incomplete expression (name unfound) in argument condition.");
2249     return MPIWAIT;
2250     default:
2251     /* it questionable whether this is a correct action in all cases*/
2252     /* we could probably turn out more useful error messages here */
2253 johnpye 529 STATEMENT_ERROR(statement, "Condition doesn't make sense.");
2254 aw0a 1 DestroyValue(&value);
2255     return MPIBADREL;
2256     }
2257     case boolean_value:
2258     if (IsConstantValue(value)!=0) {
2259     if (BooleanValue(value) != FALSE) {
2260     DestroyValue(&value);
2261     return MPIOK;
2262     } else {
2263     DestroyValue(&value);
2264 johnpye 529 STATEMENT_ERROR(statement, "Arguments do not conform to requirements");
2265 aw0a 1 return MPIBADREL;
2266     }
2267     } else {
2268     DestroyValue(&value);
2269 johnpye 529 STATEMENT_ERROR(statement, "Requirements cannot be satisfied by variables");
2270 aw0a 1 return MPIVARREL;
2271     }
2272     default:
2273     DestroyValue(&value);
2274 johnpye 529 STATEMENT_ERROR(statement, "Constraint does not evaluate to boolean result.");
2275 aw0a 1 return MPINOTBOOL;
2276     }
2277     }
2278    
2279 johnpye 707 /**
2280     returns MPIOK if subscripts match declarations,
2281     MPIWAIT if declarations cannot yet be interpretted,
2282     or some other error if there is a mismatch.
2283    
2284     So far only the square version. Should have a forvar
2285     capable recursive version sometime when we allow
2286     passage of sparse arrays.
2287    
2288     Assumes the array given has proper number of
2289     subscripts to match name and is fully expanded.
2290     */
2291 aw0a 1 static
2292     int MPICheckSubscripts(struct Instance *tmpinst,
2293     struct Instance *aryinst,
2294     struct Statement *s)
2295     {
2296     CONST struct Name *nptr;
2297    
2298     nptr = NextName(NamePointer(GetStatVarList(s)));
2299     switch (RectangleSubscriptsMatch(tmpinst,aryinst,nptr)) {
2300     case -2:
2301     return MPIWAIT;
2302     case 1:
2303     return MPIOK;
2304     case 0:
2305     default:
2306     return MPIARRRNG;
2307     }
2308     }
2309    
2310     #define NOIPICHECK 0
2311     #define IPICHECK 1
2312 johnpye 707 /**
2313     links parent and child. if checkdup != 0,
2314     it will check child to see if it already has this parent.
2315     */
2316 aw0a 1 static
2317     int InsertParameterInst(struct Instance *parent,
2318     struct Instance *child,
2319     CONST struct Name *name,
2320     CONST struct Statement *statement,
2321     int checkdup)
2322     {
2323     symchar *childname;
2324     struct InstanceName rec;
2325     unsigned long pos;
2326    
2327     childname = NameIdPtr(name);
2328     SetInstanceNameType(rec,StrName);
2329     SetInstanceNameStrPtr(rec,childname);
2330     pos = ChildSearch(parent,&rec);
2331     if (pos>0) {
2332     if (InstanceChild(parent,pos)==NULL) {
2333     StoreChildPtr(parent,pos,child);
2334     if (checkdup == 0 || SearchForParent(child,parent)==0) {
2335     /* case where we don't already have it at this scope */
2336     AddParent(child,parent);
2337     }
2338     return 1;
2339     } else { /* redefining instance */
2340 johnpye 709 char *msg = ASC_NEW_ARRAY(char,SCLEN(childname)+strlen(REDEFINE_CHILD_MESG)+1);
2341 aw0a 1 strcpy(msg,REDEFINE_CHILD_MESG);
2342     strcat(msg,SCP(childname));
2343 johnpye 529 STATEMENT_ERROR(statement,msg);
2344 aw0a 1 ascfree(msg);
2345     return 0;
2346     }
2347     } else { /* unknown name */
2348 johnpye 529 STATEMENT_ERROR(statement, "Unknown parameter name. Never should happen");
2349 aw0a 1 Asc_Panic(2, NULL, "Unknown parameter name. Never should happen");
2350 johnpye 709
2351 aw0a 1 }
2352     }
2353    
2354 johnpye 707 /**
2355     The instance this is called with should not have
2356     any parents whatsoever. The instance this is called
2357     with will be completely destroyed including any parts
2358     of the instance that do not have other parents.
2359     */
2360 aw0a 1 static
2361     void DestroyParameterInst(struct Instance *i)
2362     {
2363     DestroyInstance(i,NULL);
2364     }
2365 johnpye 707
2366     /**
2367     destroys everything you send it. If you send some arguments in
2368     as null, we don't mind.
2369     */
2370 aw0a 1 static
2371     void ClearMPImem(
2372     struct gl_list_t *args,
2373     struct gl_list_t *il,
2374     struct Instance *tmpinst,
2375     struct Instance *ipass,
2376     struct value_t *valp
2377     )
2378     {
2379     if (args!=NULL) {
2380     gl_iterate(args,(void (*)(VOIDPTR))DestroySetNode);
2381     gl_destroy(args);
2382     }
2383     if (il!=NULL) {
2384     gl_destroy(il);
2385     }
2386     if (tmpinst!=NULL) {
2387     DestroyParameterInst(tmpinst);
2388     }
2389     if (ipass!=NULL) {
2390     DestroyParameterInst(ipass);
2391     }
2392     if (valp!=NULL) {
2393     DestroyValue(valp);
2394     }
2395     }
2396    
2397 johnpye 707 /**
2398     What is MPI? parallel computing stuff?? -- JP
2399     */
2400 aw0a 1 static
2401     void mpierror(struct Set *argset,
2402     unsigned long argn,
2403     struct Statement *statement,
2404     int errcode)
2405     {
2406     int arrloc;
2407     if (errcode<0) {
2408     arrloc = (-errcode);
2409     } else {
2410     return;
2411     /* why are we here? */
2412     }
2413     FPRINTF(ASCERR,"Parameter passing error: %s\n",g_mpi_message[arrloc]);
2414     if (argset !=NULL && argn >0) {
2415     FPRINTF(ASCERR," Argument %lu:",argn);
2416     WriteSet(ASCERR,argset);
2417     FPRINTF(ASCERR,"\n");
2418     }
2419 johnpye 529 STATEMENT_ERROR(statement,"Error in executing statement:");
2420 aw0a 1 MarkStatContext(statement,context_WRONG);
2421     WSS(ASCERR,statement);
2422     }
2423    
2424     static
2425     void MPIwum(struct Set *argset,
2426     unsigned long argn,
2427     struct Statement *statement,
2428     int msgcode)
2429     {
2430     int arrloc;
2431     if (g_iteration < MAXNUMBER) {
2432     return;
2433     }
2434     if (msgcode<0) {
2435     arrloc = (-msgcode);
2436     } else {
2437     return;
2438     /* why are we here? */
2439     }
2440     FPRINTF(ASCERR,"Parameter list waiting on sufficient type or value of:\n");
2441     if (argset !=NULL && argn >0) {
2442     FPRINTF(ASCERR," Argument %lu:",argn);
2443     WriteSetNode(ASCERR,argset);
2444     FPRINTF(ASCERR,"\n");
2445     }
2446     WriteUnexecutedMessage(ASCERR,statement,g_mpi_message[arrloc]);
2447     }
2448    
2449 johnpye 707 /**
2450     process pass by value scalar: evaluate and make it, or return
2451     appropriate whine if not possible.
2452     If this returns anything other than mpiok, the user may
2453     wish to dispose of tmpinst, args as we do not here.
2454     We do issue whines here, however.
2455     */
2456 aw0a 1 static
2457     int MPIMakeSimple(struct Instance *parent,
2458     struct Instance *tmpinst,
2459     struct Set *argset,
2460     unsigned long argn,
2461     CONST struct Name *nptr,
2462     struct TypeDescription *ptype,
2463     int intset,
2464     struct Statement *ps,
2465     struct Statement *statement
2466     )
2467     {
2468     int tverr; /* error return from checking array elt type, or value */
2469     struct Instance *ipass;
2470     struct value_t vpass;
2471    
2472     vpass = FindArgValue(parent,argset,&tverr);
2473     if (tverr != 0) {
2474     if (tverr == 1) { /* try later */
2475     MPIwum(argset,argn,statement,MPIUNASSD);
2476     return MPIWAIT;
2477     } else { /* hopeless */
2478     mpierror(argset,argn,statement,MPIBADVAL);
2479     return MPIBADVAL;
2480     }
2481     }
2482     /* don't forget to dispose of vpass if exiting err after here */
2483     ipass = MakeSimpleInstance(ptype,intset,ps,NULL);
2484     if (ipass==NULL) {
2485     DestroyValue(&vpass);
2486     return MPIINSMEM;
2487     }
2488     /* don't forget to dispose of vpass if exiting err after here */
2489     if (AssignStructuralValue(ipass,vpass,statement)!=1) {
2490     mpierror(argset,argn,statement,MPIARGTYPE);
2491     DestroyParameterInst(ipass);
2492     DestroyValue(&vpass);
2493     return MPIARGTYPE;
2494     }
2495     DestroyValue(&vpass);
2496     /* install ipass in tmpinst */
2497     if ( InsertParameterInst(tmpinst,ipass,nptr,ps,IPICHECK) != 1) {
2498     /* noipicheck because var just created has no parents at all,
2499     * unless of course var is UNIVERSAL... so ipicheck */
2500     mpierror(argset,argn,statement,MPIMULTI);
2501     DestroyParameterInst(ipass);
2502     return MPIMULTI;
2503     }
2504     return MPIOK;
2505     }
2506     #define NOKEEPARGINST 0
2507     #define KEEPARGINST 1
2508 johnpye 707 /**
2509     Check and assemble the arguments of the parameterized type referenced in
2510     statement, using information derived from the parent instance.
2511    
2512     If the type found in the statement given is not a MODEL type,
2513     we will immediately return 1 and *arginstptr will be set NULL.
2514    
2515     In general, we are trying to check and assemble enough information
2516     to prove that a parameterized IS_A can be executed or proved wrong
2517     once ExecuteISA sees it.
2518    
2519     If keepargs ==KEEPARGINST, then on a successful return,
2520     *arginstptr will be to a MODEL instance (with no parents)
2521     with its children derived via parameter list filled in and
2522     all other children NULL.
2523     If there are NO children derived via parameter list or
2524     the reductions list, then *arginstptr will be NULL.
2525     If keepargs != KEEPARGINST, then arginstptr will not be
2526     used/set in any way, OTHERWISE it should be NULL on entry.
2527     If keepargs != KEEPARGINST, then we will do only the minimal
2528     necessary work to check that the arginst could be created.
2529     At present, we can't tell what this last ambition amounts to -
2530     we do the same amount of work regardless, though we try to put
2531     the more likely to fail steps first.
2532    
2533     A successful return value is 1.
2534    
2535     A failure possibly to succeed later is 0.
2536     Possible causes will be detailed via the WriteUnexecutedMessage
2537     facility.
2538    
2539     A permanent failure is any value < 0.
2540     Causes will be detailed via the WSEM facility, in addition return
2541     values < 0 have the interpretations given in g_mpi_message[-value]
2542     above.
2543    
2544     @NOTE assumes statement is well formed, in terms of
2545     arglist of IS_A/IS_REFINED_TO (if there is one) being of correct length.
2546     returns fairly quickly for nonmodel and nonparametric
2547     MODEL types.
2548     */
2549 aw0a 1 static
2550     int MakeParameterInst(struct Instance *parent,
2551     struct Statement *statement,
2552     struct Instance **arginstptr,
2553     int keepargs)
2554     {
2555     struct TypeDescription *d; /* the type we are constructing or checking */
2556     struct TypeDescription *atype; /* the type we are being passed */
2557     struct TypeDescription *ptype; /* the type we are expecting */
2558     struct TypeDescription *mrtype; /* the more refined of two types */
2559     symchar *stype; /* the set type we are expecting */
2560     struct gl_list_t *args; /* parameter Set given split for easy access */
2561     struct gl_list_t *il; /* instance(s) required to digest a parameter */
2562     struct Instance *ipass; /* instance being passed into type */
2563     struct Instance *tmpinst; /* holding instance for derivation work. */
2564     struct StatementList *psl; /* list of parameters the type requires */
2565     struct StatementList *absorbed; /* list of absorbed isas and casgns */
2566     struct Statement *ps; /* a statement from psl */
2567     struct Set *argset; /* set element extracted from arglist */
2568     CONST struct VariableList *vl;
2569     struct for_table_t *SavedForTable;
2570     unsigned long slen,c,argn;
2571     int tverr; /* error return from checking array elt type, or value */
2572     int suberr; /* error return from other routine */
2573     int intset;
2574     enum find_errors ferr;
2575     unsigned int pc; /* number of parameters the type requires */
2576    
2577     if (StatWrong(statement)) {
2578     /* incorrect statements should be warned about when they are
2579     * marked wrong, so we just ignore them here.
2580     */
2581     return MPIOK;
2582     }
2583     d = FindType(GetStatType(statement));
2584     if (d==NULL) {
2585     /* lint should make this impossible */
2586     mpierror(NULL,0L,statement,MPIINPUT);
2587     return MPIINPUT;
2588     }
2589     if (keepargs == KEEPARGINST && arginstptr == NULL) {
2590     /* someone screwed up the call, but maybe they get it right later. */
2591     FPRINTF(ASCERR," *** MakeParameterInst miscalled *** \n");
2592     return MPIWAIT;
2593     }
2594     if (keepargs == KEEPARGINST) {
2595     /* init arginstptr */
2596     *arginstptr = NULL;
2597     }
2598     if ( GetBaseType(d)!=model_type) {
2599     return MPIOK;
2600     }
2601     pc = GetModelParameterCount(d);
2602     absorbed = GetModelAbsorbedParameters(d);
2603     if (pc==0 && StatementListLength(absorbed)==0L) {
2604     /* no parameters in this type or its ancestors */
2605     return MPIOK;
2606     }
2607     /* init tmpinst, which we must remember to punt before
2608     * error returns or nokeep returns.
2609     */
2610     /* may want an SCMUI here, not sure. */
2611     tmpinst = CreateModelInstance(d);
2612     if (tmpinst==NULL) {
2613     mpierror(NULL,0L,statement,MPIINPUT);
2614     return MPIINSMEM;
2615     }
2616     args = gl_create((unsigned long)pc);
2617     if (args == NULL) {
2618     mpierror(NULL,0L,statement,MPIINPUT);
2619     ClearMPImem(NULL,NULL,tmpinst,NULL,NULL);
2620     return MPIINSMEM;
2621     }
2622     SplitArgumentSet(GetStatTypeArgs(statement),args);
2623     /* due to typelint, the following assertion should pass. fix lint if not. */
2624     assert(gl_length(args)==(unsigned long)pc);
2625     psl = GetModelParameterList(d);
2626     slen = StatementListLength(psl);
2627     argn = 1L;
2628     for (c = 1; c <= slen; c++) {
2629     ps = GetStatement(psl,c);
2630     vl = GetStatVarList(ps); /* move inside switch if allow FOR later */
2631     ptype = FindType(GetStatType(ps));
2632     stype = GetStatSetType(ps);
2633     intset = CalcSetType(stype,ps);
2634     if (intset <0 || intset >1) {
2635     /* shouldn't be possible -- typelint trapped */
2636     mpierror(NULL,0L,statement,MPIARGTYPE);
2637     ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2638     return MPIARGTYPE;
2639     }
2640     switch (StatementType(ps)) {
2641     case WILLBE:
2642     while (vl != NULL) {
2643     argset = GETARG(args,argn);
2644     il = FindArgInsts(parent,argset,&ferr);
2645     if (il == NULL) {
2646     switch(ferr) {
2647     case unmade_instance:
2648     case undefined_instance: /* this case ought to be separable */
2649     MPIwum(argset,argn,statement,MPIUNMADE);
2650     ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2651     return MPIWAIT;
2652     case impossible_instance:
2653     mpierror(argset,argn,statement,MPIBADARG);
2654     ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2655     return MPIBADARG;
2656     case correct_instance:
2657     mpierror(argset,argn,statement,MPIWEIRD);
2658     ClearMPImem(args,NULL,tmpinst,NULL,NULL);
2659     return MPIWEIRD;
2660     }
2661     }
2662     if (gl_length(il)!=1L) {
2663     mpierror(argset,