Parent Directory
|
Revision Log
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, |