1 |
/* |
2 |
* Ascend Instance Tree Search Implementation |
3 |
* by Tom Epperly |
4 |
* Created: 1/24/90 |
5 |
* Version: $Revision: 1.24 $ |
6 |
* Version control file: $RCSfile: find.c,v $ |
7 |
* Date last modified: $Date: 1998/03/26 20:39:44 $ |
8 |
* Last modified by: $Author: ballan $ |
9 |
* |
10 |
* This file is part of the Ascend Language Interpreter. |
11 |
* |
12 |
* Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly |
13 |
* |
14 |
* The Ascend Language Interpreter is free software; you can redistribute |
15 |
* it and/or modify it under the terms of the GNU General Public License as |
16 |
* published by the Free Software Foundation; either version 2 of the |
17 |
* License, or (at your option) any later version. |
18 |
* |
19 |
* The Ascend Language Interpreter is distributed in hope that it will be |
20 |
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
22 |
* General Public License for more details. |
23 |
* |
24 |
* You should have received a copy of the GNU General Public License |
25 |
* along with the program; if not, write to the Free Software Foundation, |
26 |
* Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named |
27 |
* COPYING. |
28 |
* |
29 |
*/ |
30 |
|
31 |
#include <stdarg.h> |
32 |
#include <math.h> |
33 |
#include <ascend/utilities/ascConfig.h> |
34 |
#include <ascend/utilities/ascMalloc.h> |
35 |
#include <ascend/utilities/ascPanic.h> |
36 |
#include <ascend/general/pool.h> |
37 |
#include <ascend/general/list.h> |
38 |
#include <ascend/general/dstring.h> |
39 |
|
40 |
#include "symtab.h" |
41 |
#include "functype.h" |
42 |
#include "expr_types.h" |
43 |
#include "child.h" |
44 |
#include "type_desc.h" |
45 |
#include "instance_enum.h" |
46 |
#include "instance_name.h" |
47 |
#include "instance_io.h" |
48 |
#include "mathinst.h" |
49 |
#include "name.h" |
50 |
#include "nameio.h" |
51 |
#include "evaluate.h" |
52 |
#include "atomvalue.h" |
53 |
#include "instquery.h" |
54 |
#include "arrayinst.h" |
55 |
#include "parentchild.h" |
56 |
#include "value_type.h" |
57 |
#include "forvars.h" |
58 |
#include "setinstval.h" |
59 |
#include "find.h" |
60 |
#include "safe.h" |
61 |
#include "relation_util.h" |
62 |
#include "logical_relation.h" |
63 |
#include "logrelation.h" |
64 |
#include "logrel_util.h" |
65 |
|
66 |
|
67 |
#define NAMELISTSIZE 20L |
68 |
#define DEFTOLERANCE 1e-08 |
69 |
|
70 |
#ifndef lint |
71 |
static CONST char FindRCSid[]="$Id: find.c,v 1.24 1998/03/26 20:39:44 ballan Exp $"; |
72 |
#endif /* lint */ |
73 |
|
74 |
CONST struct Instance *g_EvaluationContext=NULL; |
75 |
struct for_table_t *g_EvaluationForTable=NULL; |
76 |
int ListMode=0; /* 0 = set or normal mode; 1 = list mode */ |
77 |
int EvaluatingSets=0; /* 1 = in process of set evaluation */ |
78 |
int g_DeclarativeContext=0; /* 0 = declarative processing |
79 |
* !0 = procedural processing. |
80 |
*/ |
81 |
|
82 |
int GetDeclarativeContextF() |
83 |
{ |
84 |
return g_DeclarativeContext; |
85 |
} |
86 |
|
87 |
void SetDeclarativeContextF(int n,char *file,int line) |
88 |
{ |
89 |
g_DeclarativeContext = n; |
90 |
FPRINTF(ASCERR,"SDC=%d at %s:%d\n",n,file,line); |
91 |
} |
92 |
|
93 |
|
94 |
struct Instance *GetEvaluationContextF(void) |
95 |
{ |
96 |
return (struct Instance *)g_EvaluationContext; |
97 |
} |
98 |
void SetEvaluationContextF(CONST struct Instance *i |
99 |
#if (EVALDEBUG == 1 || EVALDEBUG == 3) |
100 |
, char *file, int line |
101 |
#endif |
102 |
) |
103 |
{ |
104 |
#if (EVALDEBUG == 1 || EVALDEBUG == 3) |
105 |
FPRINTF(ASCERR,"setEvalContext:0x%p %s:%d\n",i,file,line); |
106 |
#endif /*evaldebug*/ |
107 |
g_EvaluationContext = i; |
108 |
} |
109 |
struct for_table_t *GetEvaluationForTableF(void) |
110 |
{ |
111 |
return g_EvaluationForTable; |
112 |
} |
113 |
void SetEvaluationForTableF(struct for_table_t *ft |
114 |
#if (EVALDEBUG == 2 || EVALDEBUG == 3) |
115 |
, char *file, int line |
116 |
#endif |
117 |
) |
118 |
{ |
119 |
#if (EVALDEBUG == 2 || EVALDEBUG == 3) |
120 |
FPRINTF(ASCERR,"setEvalForTable:0x%p %s:%d\n",ft,file,line); |
121 |
#endif /* evaldebug */ |
122 |
g_EvaluationForTable = ft; |
123 |
} |
124 |
|
125 |
/* |
126 |
* checks to see whether the integer atom or integer inst |
127 |
* is a legal set index and bitches if not. |
128 |
* as currently used, will always return errors when |
129 |
* we are in the declarative section because ATOM i |
130 |
* is _always_ mutable now that we have integer constants. |
131 |
*/ |
132 |
static int ProcessIntegersInSets(CONST struct Instance *i) |
133 |
{ |
134 |
if (i!=NULL) { |
135 |
if (AtomMutable(i)&&(GetDeclarativeContext()==0)){ |
136 |
FPRINTF(ASCERR, "Error: variable integer used as set index\n"); |
137 |
WriteInstanceName(ASCERR,i,NULL); |
138 |
FPRINTF(ASCERR,"\n"); |
139 |
return 1; |
140 |
} |
141 |
else return 0; |
142 |
} |
143 |
return 2; |
144 |
} |
145 |
|
146 |
static struct gl_list_t *RealFindInstances(CONST struct Instance *i, |
147 |
CONST struct Name *n, |
148 |
enum find_errors *errval); |
149 |
|
150 |
struct value_t InstanceEvaluateName(CONST struct Name *nptr) |
151 |
{ |
152 |
struct gl_list_t *list; |
153 |
struct Instance *inst; |
154 |
struct value_t result; |
155 |
unsigned long c,len; |
156 |
enum find_errors errval; |
157 |
struct for_var_t *ptr; |
158 |
symchar *name; |
159 |
|
160 |
if (GetEvaluationForTable()!=NULL){ |
161 |
/* check FOR vars list before user vars */ |
162 |
AssertMemory(GetEvaluationForTable()); |
163 |
if ((name = SimpleNameIdPtr(nptr))!=NULL){ |
164 |
if ((ptr = FindForVar(GetEvaluationForTable(),name))!=NULL){ |
165 |
switch(GetForKind(ptr)){ |
166 |
case f_integer: |
167 |
return CreateIntegerValue(GetForInteger(ptr),1); |
168 |
case f_symbol: |
169 |
return CreateSymbolValue(GetForSymbol(ptr),1); |
170 |
case f_set: |
171 |
return CreateSetValue(CopySet(GetForSet(ptr))); |
172 |
default: |
173 |
FPRINTF(ASCERR,"Untyped for variable.\n"); |
174 |
return CreateErrorValue(undefined_value); |
175 |
} |
176 |
} |
177 |
} |
178 |
} |
179 |
/* didn't find or bomb, so must be in user vars */ |
180 |
if (GetEvaluationContext()==NULL) return CreateErrorValue(incorrect_name); |
181 |
AssertMemory(GetEvaluationContext()); |
182 |
list = RealFindInstances(GetEvaluationContext(),nptr,&errval); |
183 |
if (list==NULL){ |
184 |
assert(errval!=correct_instance); |
185 |
switch(errval){ |
186 |
case unmade_instance: |
187 |
return CreateErrorValue(name_unfound); |
188 |
case undefined_instance: |
189 |
return CreateErrorValue(undefined_value); |
190 |
case impossible_instance: |
191 |
return CreateErrorValue(incorrect_name); |
192 |
default: /*NOTREACHED*/ |
193 |
break; |
194 |
} |
195 |
/*NOTREACHED*/ |
196 |
} else{ |
197 |
/* found user's variable */ |
198 |
AssertMemory(list); |
199 |
if (gl_length(list)==1){ |
200 |
inst = (struct Instance *)gl_fetch(list,1); |
201 |
AssertMemory(inst); |
202 |
gl_destroy(list); |
203 |
switch(InstanceKind(inst)){ |
204 |
case REAL_INST: |
205 |
case REAL_ATOM_INST: |
206 |
case REAL_CONSTANT_INST: |
207 |
if (AtomAssigned(inst)) { |
208 |
return CreateRealValue(RealAtomValue(inst),RealAtomDims(inst), |
209 |
IsConstantInstance(inst)); |
210 |
} else { |
211 |
return CreateErrorValue(undefined_value); |
212 |
} |
213 |
case BOOLEAN_INST: |
214 |
case BOOLEAN_ATOM_INST: |
215 |
case BOOLEAN_CONSTANT_INST: |
216 |
if (AtomAssigned(inst)) { |
217 |
return CreateBooleanValue(GetBooleanAtomValue(inst), |
218 |
IsConstantInstance(inst)); |
219 |
} else { |
220 |
return CreateErrorValue(undefined_value); |
221 |
} |
222 |
case INTEGER_CONSTANT_INST: |
223 |
if (inst !=NULL && AtomAssigned(inst)) { |
224 |
return CreateIntegerValue(GetIntegerAtomValue(inst),1); |
225 |
} else { |
226 |
return CreateErrorValue(undefined_value); |
227 |
} |
228 |
case INTEGER_ATOM_INST: |
229 |
case INTEGER_INST: |
230 |
if (EvaluatingSets){ |
231 |
int piis; |
232 |
piis = ProcessIntegersInSets(inst); |
233 |
if(piis==1) { |
234 |
return CreateErrorValue(type_conflict); |
235 |
} |
236 |
if(piis==2) { |
237 |
return CreateErrorValue(incorrect_name); |
238 |
} |
239 |
} |
240 |
if (AtomAssigned(inst)) { |
241 |
return CreateIntegerValue(GetIntegerAtomValue(inst),0); |
242 |
} else { |
243 |
return CreateErrorValue(undefined_value); |
244 |
} |
245 |
case SET_ATOM_INST: |
246 |
if (ListMode) { |
247 |
/* more kaa-ism. client should be checking this. not us. */ |
248 |
FPRINTF(ASCERR,"Set atoms are not allowed in lists! (ListMode==1)\n"); |
249 |
return CreateErrorValue(illegal_set_use); |
250 |
} |
251 |
if (AtomAssigned(inst)) { |
252 |
return CreateSetValue(CopySet(SetAtomList(inst))); |
253 |
} else { |
254 |
return CreateErrorValue(undefined_value); |
255 |
} |
256 |
case SYMBOL_INST: |
257 |
case SYMBOL_ATOM_INST: |
258 |
case SYMBOL_CONSTANT_INST: |
259 |
if (AtomAssigned(inst)) { |
260 |
return CreateSymbolValue(GetSymbolAtomValue(inst), |
261 |
IsConstantInstance(inst)); |
262 |
} else { |
263 |
return CreateErrorValue(undefined_value); |
264 |
} |
265 |
case SET_INST: |
266 |
if (ListMode) { |
267 |
/* more kaa-ism. client should be checking this. not us. */ |
268 |
FPRINTF(ASCERR,"Sets instances are not allowed in lists! (ListMode==1)\n"); |
269 |
return CreateErrorValue(illegal_set_use); |
270 |
} |
271 |
if (AtomAssigned(inst)) { |
272 |
return CreateSetValue(CopySet(SetAtomList(inst))); |
273 |
} else { |
274 |
return CreateErrorValue(undefined_value); |
275 |
} |
276 |
default: |
277 |
return CreateErrorValue(incorrect_name); |
278 |
} |
279 |
} else { |
280 |
/* BUG BAA this block may be incorrect. what is it? Looks like kaaism*/ |
281 |
if (GetDeclarativeContext()==0) { |
282 |
/* find out if this is ever called in instantiation */ |
283 |
FPRINTF(ASCERR,"BAA debug: please tell ballan@cs.cmu.edu you saw:\n"); |
284 |
WriteName(ASCERR,nptr); |
285 |
FPRINTF(ASCERR,"\nin compiling what MODEL.\n"); |
286 |
} |
287 |
result = CreateEmptyListValue(); |
288 |
len = gl_length(list); |
289 |
for(c=1; c<=len; c++){ |
290 |
inst = (struct Instance *)gl_fetch(list,c); |
291 |
AssertMemory(inst); |
292 |
/* Don't know why only integers should be valid in lists. |
293 |
* He who introduces crap should at least be complete about it. |
294 |
* Somewhere there's probably a client not doing proper checking |
295 |
* trying to pawn it off on us to do here. That client is now broken. |
296 |
*/ |
297 |
#define OLDCRAP 0 |
298 |
#if OLDCRAP /* integer only */ |
299 |
switch(InstanceKind(inst)) { |
300 |
case INTEGER_ATOM_INST: |
301 |
if (AtomAssigned(inst)) { |
302 |
AppendToListValue(result, |
303 |
CreateIntegerValue(GetIntegerAtomValue(inst), |
304 |
IsConstantInstance(inst))); |
305 |
} else { |
306 |
return CreateErrorValue(undefined_value); |
307 |
} |
308 |
break; |
309 |
case SET_ATOM_INST: |
310 |
case SYMBOL_ATOM_INST: |
311 |
case INTEGER_INST: |
312 |
case SET_INST: |
313 |
case SYMBOL_INST: |
314 |
default: |
315 |
gl_destroy(list); |
316 |
DestroyValue(&result); |
317 |
return CreateErrorValue(incorrect_name); |
318 |
} |
319 |
#else |
320 |
/* extended oldcrap to include this. baa. 3/98 */ |
321 |
switch(InstanceKind(inst)) { |
322 |
case REAL_ATOM_INST: |
323 |
case REAL_CONSTANT_INST: |
324 |
if (AtomAssigned(inst)) { |
325 |
AppendToListValue(result, |
326 |
CreateRealValue(RealAtomValue(inst), |
327 |
RealAtomDims(inst), |
328 |
IsConstantInstance(inst))); |
329 |
} else { |
330 |
return CreateErrorValue(undefined_value); |
331 |
} |
332 |
break; |
333 |
case INTEGER_ATOM_INST: |
334 |
case INTEGER_CONSTANT_INST: |
335 |
if (AtomAssigned(inst)) { |
336 |
AppendToListValue(result, |
337 |
CreateIntegerValue(GetIntegerAtomValue(inst), |
338 |
IsConstantInstance(inst))); |
339 |
} else { |
340 |
return CreateErrorValue(undefined_value); |
341 |
} |
342 |
break; |
343 |
case SET_ATOM_INST: |
344 |
if (AtomAssigned(inst)) { |
345 |
AppendToListValue(result, |
346 |
CreateSetValue(CopySet(SetAtomList(inst)))); |
347 |
} else { |
348 |
return CreateErrorValue(undefined_value); |
349 |
} |
350 |
break; |
351 |
case SYMBOL_ATOM_INST: |
352 |
case SYMBOL_CONSTANT_INST: |
353 |
if (AtomAssigned(inst)) { |
354 |
AppendToListValue(result, |
355 |
CreateSymbolValue(GetSymbolAtomValue(inst), |
356 |
IsConstantInstance(inst))); |
357 |
} else { |
358 |
return CreateErrorValue(undefined_value); |
359 |
} |
360 |
break; |
361 |
/* ok, we will uniformly reject lists of subatomics, though |
362 |
* it is arbitrary and inconsistent to do so. |
363 |
*/ |
364 |
case INTEGER_INST: |
365 |
case SET_INST: |
366 |
case SYMBOL_INST: |
367 |
default: |
368 |
gl_destroy(list); |
369 |
DestroyValue(&result); |
370 |
return CreateErrorValue(incorrect_name); |
371 |
} |
372 |
#endif |
373 |
} |
374 |
gl_destroy(list); |
375 |
return result; |
376 |
} |
377 |
} |
378 |
/* we need to verify that this is not reached */ |
379 |
FPRINTF(ASCERR,"InstanceEvaluateName returning unexpectedly\n"); |
380 |
return CreateErrorValue(incorrect_name); |
381 |
} |
382 |
|
383 |
|
384 |
|
385 |
/* Specially to evaluate name of relations, logrelations in SATISFIED |
386 |
* expressions |
387 |
*/ |
388 |
struct value_t InstanceEvaluateSatisfiedName(CONST struct Name *nptr, |
389 |
double tol) |
390 |
{ |
391 |
struct gl_list_t *list; |
392 |
struct Instance *inst; |
393 |
enum find_errors errval; |
394 |
struct for_var_t *ptr; |
395 |
symchar *name; |
396 |
CONST struct relation *rel; |
397 |
enum Expr_enum relop; |
398 |
enum safe_err status = safe_ok; |
399 |
double res; |
400 |
int logres; |
401 |
|
402 |
if (GetEvaluationForTable()!=NULL){ |
403 |
AssertMemory(GetEvaluationForTable()); |
404 |
if ((name = SimpleNameIdPtr(nptr))!=NULL){ |
405 |
if ((ptr = FindForVar(GetEvaluationForTable(),name))!=NULL){ |
406 |
switch(GetForKind(ptr)){ |
407 |
case f_integer: |
408 |
return CreateIntegerValue(GetForInteger(ptr),1); |
409 |
case f_symbol: |
410 |
return CreateSymbolValue(GetForSymbol(ptr),1); |
411 |
case f_set: |
412 |
return CreateSetValue(CopySet(GetForSet(ptr))); |
413 |
default: |
414 |
FPRINTF(ASCERR,"Untyped for variable.\n"); |
415 |
return CreateErrorValue(undefined_value); |
416 |
} |
417 |
} |
418 |
} |
419 |
} |
420 |
if (GetEvaluationContext()==NULL) return CreateErrorValue(incorrect_name); |
421 |
AssertMemory(GetEvaluationContext()); |
422 |
list = RealFindInstances(GetEvaluationContext(),nptr,&errval); |
423 |
if (list==NULL){ |
424 |
assert(errval!=correct_instance); |
425 |
switch(errval){ |
426 |
case unmade_instance: |
427 |
return CreateErrorValue(name_unfound); |
428 |
case undefined_instance: |
429 |
return CreateErrorValue(undefined_value); |
430 |
case impossible_instance: |
431 |
return CreateErrorValue(incorrect_name); |
432 |
default: /*NOTREACHED*/ |
433 |
break; |
434 |
} |
435 |
/*NOTREACHED*/ |
436 |
} |
437 |
else{ |
438 |
AssertMemory(list); |
439 |
if (gl_length(list)==1){ |
440 |
inst = (struct Instance *)gl_fetch(list,1); |
441 |
AssertMemory(inst); |
442 |
gl_destroy(list); |
443 |
switch(InstanceKind(inst)){ |
444 |
case REL_INST: |
445 |
status = RelationCalcResidualPostfixSafe(inst,&res); |
446 |
if (status != safe_ok) { |
447 |
FPRINTF(ASCERR, |
448 |
"Something wrong while calculating a residual in Sat Expr\n"); |
449 |
return CreateErrorValue(undefined_value); |
450 |
} |
451 |
rel = GetInstanceRelationOnly(inst); |
452 |
relop = RelationRelop(rel); |
453 |
switch(relop) { |
454 |
case e_equal: |
455 |
if (tol != DBL_MAX) { |
456 |
if(fabs(tol)>fabs(res)) { |
457 |
return CreateBooleanValue(1,0); |
458 |
} |
459 |
else { |
460 |
return CreateBooleanValue(0,0); |
461 |
} |
462 |
} |
463 |
else { |
464 |
if((DEFTOLERANCE)>fabs(res)) { |
465 |
return CreateBooleanValue(1,0); |
466 |
} |
467 |
else { |
468 |
return CreateBooleanValue(0,0); |
469 |
} |
470 |
} |
471 |
case e_notequal: |
472 |
if (tol != DBL_MAX) { |
473 |
if(fabs(tol)>fabs(res)) { |
474 |
return CreateBooleanValue(0,0); |
475 |
} |
476 |
else { |
477 |
return CreateBooleanValue(1,0); |
478 |
} |
479 |
} |
480 |
else { |
481 |
if((DEFTOLERANCE)>fabs(res)) { |
482 |
return CreateBooleanValue(0,0); |
483 |
} |
484 |
else { |
485 |
return CreateBooleanValue(1,0); |
486 |
} |
487 |
} |
488 |
case e_greater: |
489 |
if (tol != DBL_MAX) { |
490 |
if(fabs(tol)<res) { |
491 |
return CreateBooleanValue(1,0); |
492 |
} |
493 |
else { |
494 |
return CreateBooleanValue(0,0); |
495 |
} |
496 |
} |
497 |
else { |
498 |
if((DEFTOLERANCE)<res) { |
499 |
return CreateBooleanValue(1,0); |
500 |
} |
501 |
else { |
502 |
return CreateBooleanValue(0,0); |
503 |
} |
504 |
} |
505 |
case e_greatereq: |
506 |
if (tol != DBL_MAX) { |
507 |
if(-fabs(tol)<res) { |
508 |
return CreateBooleanValue(1,0); |
509 |
} |
510 |
else { |
511 |
return CreateBooleanValue(0,0); |
512 |
} |
513 |
} |
514 |
else { |
515 |
if(-(DEFTOLERANCE)<res) { |
516 |
return CreateBooleanValue(1,0); |
517 |
} |
518 |
else { |
519 |
return CreateBooleanValue(0,0); |
520 |
} |
521 |
} |
522 |
case e_less: |
523 |
if (tol != DBL_MAX) { |
524 |
if(-fabs(tol)>res) { |
525 |
return CreateBooleanValue(1,0); |
526 |
} |
527 |
else { |
528 |
return CreateBooleanValue(0,0); |
529 |
} |
530 |
} |
531 |
else { |
532 |
if(-(DEFTOLERANCE)>res) { |
533 |
return CreateBooleanValue(1,0); |
534 |
} |
535 |
else { |
536 |
return CreateBooleanValue(0,0); |
537 |
} |
538 |
} |
539 |
case e_lesseq: |
540 |
if (tol != DBL_MAX) { |
541 |
if(fabs(tol)>res) { |
542 |
return CreateBooleanValue(1,0); |
543 |
} |
544 |
else { |
545 |
return CreateBooleanValue(0,0); |
546 |
} |
547 |
} |
548 |
else { |
549 |
if((DEFTOLERANCE)>res) { |
550 |
return CreateBooleanValue(1,0); |
551 |
} |
552 |
else { |
553 |
return CreateBooleanValue(0,0); |
554 |
} |
555 |
} |
556 |
default: |
557 |
FPRINTF(ASCERR, |
558 |
"Something wrong while calculating a residual in Sat Expr\n"); |
559 |
return CreateErrorValue(incorrect_name); |
560 |
} |
561 |
case LREL_INST: |
562 |
if (LogRelCalcResidual(inst,&logres)) { |
563 |
FPRINTF(ASCERR, |
564 |
"Something wrong while calculating a log residual in Sat Expr\n"); |
565 |
return CreateErrorValue(undefined_value); |
566 |
} |
567 |
return CreateBooleanValue(logres,0); |
568 |
default: |
569 |
return CreateErrorValue(incorrect_name); |
570 |
} |
571 |
} |
572 |
else { |
573 |
FPRINTF(ASCERR,"InstanceEvaluateSatisfiedName returning unexpectedly\n"); |
574 |
gl_destroy(list); |
575 |
return CreateErrorValue(undefined_value); |
576 |
} |
577 |
} |
578 |
/* we need to verify that this is not reached */ |
579 |
FPRINTF(ASCERR,"InstanceEvaluateSatisfiedName returning unexpectedly\n"); |
580 |
return CreateErrorValue(incorrect_name); |
581 |
} |
582 |
|
583 |
|
584 |
static struct gl_list_t *FindArrayChildren(struct gl_list_t *list, |
585 |
CONST struct set_t *sptr, |
586 |
enum find_errors *errval) |
587 |
{ |
588 |
struct gl_list_t *result; |
589 |
struct Instance *i,*child; |
590 |
struct InstanceName rec; |
591 |
struct TypeDescription *desc; |
592 |
unsigned long c1,len1,c2,len2,pos; |
593 |
switch(SetKind(sptr)){ |
594 |
case empty_set: return gl_create(0); |
595 |
case string_set: |
596 |
SetInstanceNameType(rec,StrArrayIndex); |
597 |
len2 = Cardinality(sptr); |
598 |
len1 = gl_length(list); |
599 |
result = gl_create(len1*len2); |
600 |
for(c1=1; c1<=len1; c1++){ |
601 |
i = (struct Instance *)gl_fetch(list,c1); |
602 |
if (InstanceKind(i)==ARRAY_ENUM_INST){ |
603 |
if (NextToExpand(i)!=1){ |
604 |
for(c2=1; c2<=len2; c2++){ |
605 |
SetInstanceNameStrIndex(rec,FetchStrMember(sptr,c2)); |
606 |
if ((pos = ChildSearch(i,&rec))==0){ |
607 |
gl_destroy(result); |
608 |
desc = InstanceTypeDesc(i); |
609 |
if ( GetArrayBaseIsRelation(desc) || GetArrayBaseIsLogRel(desc)){ |
610 |
*errval = unmade_instance; |
611 |
} else { |
612 |
*errval = impossible_instance; |
613 |
} |
614 |
return NULL; |
615 |
} else { |
616 |
child = InstanceChild(i,pos); |
617 |
if (child!=NULL){ |
618 |
gl_append_ptr(result,(VOIDPTR)child); |
619 |
} else { |
620 |
gl_destroy(result); |
621 |
*errval = unmade_instance; |
622 |
return NULL; |
623 |
} |
624 |
} |
625 |
} |
626 |
} else { |
627 |
gl_destroy(result); |
628 |
*errval = unmade_instance; |
629 |
return NULL; |
630 |
} |
631 |
} else { |
632 |
gl_destroy(result); |
633 |
*errval = impossible_instance; |
634 |
return NULL; |
635 |
} |
636 |
} |
637 |
return result; |
638 |
case integer_set: |
639 |
SetInstanceNameType(rec,IntArrayIndex); |
640 |
len2 = Cardinality(sptr); |
641 |
len1 = gl_length(list); |
642 |
result = gl_create(len1*len2); |
643 |
for(c1=1; c1<=len1; c1++){ |
644 |
i = (struct Instance *)gl_fetch(list,c1); |
645 |
if (InstanceKind(i)==ARRAY_INT_INST){ |
646 |
if (NextToExpand(i)!=1){ |
647 |
for (c2=1; c2<=len2; c2++){ |
648 |
SetInstanceNameIntIndex(rec,FetchIntMember(sptr,c2)); |
649 |
if ((pos = ChildSearch(i,&rec))==0){ |
650 |
gl_destroy(result); |
651 |
desc = InstanceTypeDesc(i); |
652 |
if (GetArrayBaseIsRelation(desc) || GetArrayBaseIsLogRel(desc)) { |
653 |
*errval = unmade_instance; |
654 |
} else { |
655 |
*errval = impossible_instance; |
656 |
} |
657 |
return NULL; |
658 |
} else { |
659 |
child = InstanceChild(i,pos); |
660 |
if (child!=NULL){ |
661 |
gl_append_ptr(result,(VOIDPTR)child); |
662 |
} else{ |
663 |
gl_destroy(result); |
664 |
*errval = unmade_instance; |
665 |
return NULL; |
666 |
} |
667 |
} |
668 |
} |
669 |
} else { |
670 |
gl_destroy(result); |
671 |
*errval = unmade_instance; |
672 |
return NULL; |
673 |
} |
674 |
} else { |
675 |
gl_destroy(result); |
676 |
*errval = impossible_instance; |
677 |
return NULL; |
678 |
} |
679 |
} |
680 |
return result; |
681 |
} |
682 |
/*NOTREACHED*/ |
683 |
return NULL; |
684 |
} |
685 |
|
686 |
static |
687 |
struct gl_list_t *FindNextNameElement(CONST struct Name *n, |
688 |
struct gl_list_t *list, |
689 |
enum find_errors *errval) |
690 |
{ |
691 |
unsigned long pos,c,len; |
692 |
struct InstanceName rec; |
693 |
struct Instance *current,*child; |
694 |
struct value_t setvalue,oldvalue; |
695 |
CONST struct Set *sptr; |
696 |
struct gl_list_t *result; |
697 |
|
698 |
*errval = correct_instance; |
699 |
if (NameId(n)){ |
700 |
result = gl_create(NAMELISTSIZE); |
701 |
SetInstanceNameType(rec,StrName); |
702 |
SetInstanceNameStrPtr(rec,NameIdPtr(n)); |
703 |
len = gl_length(list); |
704 |
for(c=1; c<=len; c++){ |
705 |
current = (struct Instance *)gl_fetch(list,c); |
706 |
pos = ChildSearch(current,&rec); |
707 |
if (pos!=0){ |
708 |
child = InstanceChild(current,pos); |
709 |
if (child!=NULL){ |
710 |
gl_append_ptr(result,(VOIDPTR)child); |
711 |
} else{ |
712 |
*errval = unmade_instance; |
713 |
gl_destroy(result); |
714 |
return NULL; |
715 |
} |
716 |
} else{ |
717 |
*errval = unmade_instance; |
718 |
/* it would seem this ought to be undefined_instance, |
719 |
* but maybe refinement causes insanity. -- in which case |
720 |
* it should be a caller policy to wait, rather than our |
721 |
* job to anticipate policy and short circuit things here. |
722 |
*/ |
723 |
gl_destroy(result); |
724 |
return NULL; |
725 |
} |
726 |
} |
727 |
return result; |
728 |
} else { |
729 |
sptr = NameSetPtr(n); |
730 |
setvalue = EvaluateSet(sptr,InstanceEvaluateName); |
731 |
switch(ValueKind(setvalue)){ |
732 |
case integer_value: |
733 |
case symbol_value: |
734 |
case list_value: |
735 |
oldvalue = setvalue; |
736 |
if (ListMode) { |
737 |
setvalue = CreateOrderedSetFromList(oldvalue); |
738 |
} else { |
739 |
setvalue = CreateSetFromList(oldvalue); |
740 |
} |
741 |
DestroyValue(&oldvalue); |
742 |
/* intended to fall through to next case */ |
743 |
case set_value: |
744 |
result = FindArrayChildren(list,SetValue(setvalue),errval); |
745 |
DestroyValue(&setvalue); |
746 |
return result; |
747 |
case error_value: |
748 |
switch(ErrorValue(setvalue)){ |
749 |
case illegal_set_use: |
750 |
*errval = impossible_instance; |
751 |
break; |
752 |
default: |
753 |
*errval = undefined_instance; |
754 |
break; |
755 |
/* more needs to be added here */ |
756 |
} |
757 |
DestroyValue(&setvalue); |
758 |
return NULL; |
759 |
default: |
760 |
ASC_PANIC("Need to add to FindNextNameElement.\n"); |
761 |
|
762 |
} |
763 |
} |
764 |
} |
765 |
|
766 |
static |
767 |
struct gl_list_t *RealFindInstances(CONST struct Instance *i, |
768 |
CONST struct Name *n, |
769 |
enum find_errors *errval) |
770 |
{ |
771 |
struct gl_list_t *result,*next; |
772 |
result = gl_create(NAMELISTSIZE); |
773 |
gl_append_ptr(result,(VOIDPTR)i); |
774 |
while(n!=NULL){ |
775 |
next = FindNextNameElement(n,result,errval); |
776 |
gl_destroy(result); |
777 |
if (next!=NULL){ |
778 |
result = next; |
779 |
n = NextName(n); |
780 |
} else { |
781 |
return NULL; |
782 |
} |
783 |
} |
784 |
return result; |
785 |
} |
786 |
|
787 |
struct gl_list_t *FindInstances(CONST struct Instance *i, |
788 |
CONST struct Name *n, |
789 |
enum find_errors *errval) |
790 |
{ |
791 |
struct gl_list_t *result; |
792 |
*errval = impossible_instance; |
793 |
if (i == NULL) return NULL; |
794 |
AssertMemory(i); |
795 |
assert(GetEvaluationContext()==NULL); |
796 |
SetEvaluationContext(i); |
797 |
*errval = correct_instance; |
798 |
result = RealFindInstances(i,n,errval); |
799 |
SetEvaluationContext(NULL); |
800 |
return result; |
801 |
} |
802 |
|
803 |
struct gl_list_t *FindInstancesFromNames(CONST struct Instance *i, |
804 |
CONST struct gl_list_t *names, |
805 |
enum find_errors *err, |
806 |
unsigned long *errpos) |
807 |
{ |
808 |
unsigned long pos, len; |
809 |
struct gl_list_t *result, *tmp; |
810 |
struct Name *n; |
811 |
|
812 |
*errpos = 0; |
813 |
len = gl_length(names); |
814 |
if (len == 0) { |
815 |
*err = correct_instance; |
816 |
return NULL; |
817 |
} |
818 |
result = gl_create(len); |
819 |
for (pos = 1; pos <= len; pos++) { |
820 |
n = (struct Name *)gl_fetch(names,pos); |
821 |
if (n == NULL) { |
822 |
gl_destroy(result); |
823 |
*err = impossible_instance; |
824 |
*errpos = pos; |
825 |
return NULL; |
826 |
} |
827 |
tmp = FindInstances(i,n,err); |
828 |
if (tmp == NULL) { |
829 |
gl_destroy(result); |
830 |
*errpos = pos; |
831 |
return NULL; |
832 |
} |
833 |
if (gl_length(tmp) != 1) { |
834 |
gl_destroy(tmp); |
835 |
gl_destroy(result); |
836 |
*err = impossible_instance; |
837 |
*errpos = pos; |
838 |
return NULL; |
839 |
} |
840 |
gl_append_ptr(result,gl_fetch(tmp,1)); |
841 |
gl_destroy(tmp); |
842 |
} |
843 |
|
844 |
return result; |
845 |
} |