1 |
/* ASCEND modelling environment |
2 |
Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly |
3 |
Copyright (C) 2006 Carnegie Mellon University |
4 |
|
5 |
This program is free software; you can redistribute it and/or modify |
6 |
it under the terms of the GNU General Public License as published by |
7 |
the Free Software Foundation; either version 2, or (at your option) |
8 |
any later version. |
9 |
|
10 |
This program is distributed in the hope that it will be useful, |
11 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
GNU General Public License for more details. |
14 |
|
15 |
You should have received a copy of the GNU General Public License |
16 |
along with this program; if not, write to the Free Software |
17 |
Foundation, Inc., 59 Temple Place - Suite 330, |
18 |
Boston, MA 02111-1307, USA. |
19 |
*//* |
20 |
@file |
21 |
Evaluation Routines |
22 |
*//* |
23 |
* by Tom Epperly |
24 |
* Created: 1/16/90 |
25 |
* Last in CVS: $Revision: 1.23 $ $Date: 1998/03/17 22:08:30 $ $Author: ballan $ |
26 |
*/ |
27 |
|
28 |
#include <stdio.h> |
29 |
#include <assert.h> |
30 |
#include <stdarg.h> |
31 |
#include <utilities/ascConfig.h> |
32 |
#include <utilities/ascMalloc.h> |
33 |
#include <utilities/ascPanic.h> |
34 |
#include <general/dstring.h> |
35 |
#include <general/list.h> |
36 |
#include "compiler.h" |
37 |
#include "fractions.h" |
38 |
#include "dimen.h" |
39 |
#include "functype.h" |
40 |
#include "expr_types.h" |
41 |
#include "setinstval.h" |
42 |
#include "value_type.h" |
43 |
#include "name.h" |
44 |
#include "temp.h" |
45 |
#include "sets.h" |
46 |
#include "exprs.h" |
47 |
#include "find.h" |
48 |
#include "exprio.h" |
49 |
#include "evaluate.h" |
50 |
|
51 |
#ifndef lint |
52 |
static CONST char EvaluationRoutineRCSid[] = "$Id: evaluate.c,v 1.23 1998/03/17 22:08:30 ballan Exp $"; |
53 |
#endif |
54 |
|
55 |
static struct gl_list_t *g_names_needed = NULL; |
56 |
/* global var so we are not passing nlist everywhere |
57 |
* that we used to pass *EvaluateName. |
58 |
*/ |
59 |
#define GNN g_names_needed |
60 |
|
61 |
/*------------------------------------------------------------------------------ |
62 |
STACK ROUTINES |
63 |
|
64 |
small, fast, and local. Do not export. BAA. 2/96 |
65 |
changed from longs to ints for size and capacity, |
66 |
particularly because expression stacks just don't get that deep. |
67 |
*/ |
68 |
struct stack_t { |
69 |
struct value_t *ptr; /* data pointer */ |
70 |
unsigned capacity; /* length of data */ |
71 |
unsigned long size; /* pointer while recycled and data while in use */ |
72 |
}; |
73 |
|
74 |
#define SMALLOC(x) x=ASC_NEW(struct stack_t); |
75 |
#define DMALLOC(x,n) x = ASC_NEW_ARRAY(struct value_t,(unsigned)n) |
76 |
|
77 |
static struct stack_t *AllocStack(unsigned int capacity) |
78 |
{ |
79 |
struct stack_t *result; |
80 |
SMALLOC(result); |
81 |
result->size =0; |
82 |
DMALLOC(result->ptr,capacity); |
83 |
result->capacity = capacity; |
84 |
return result; |
85 |
} |
86 |
|
87 |
static void DeAllocStack(struct stack_t *stack) |
88 |
{ |
89 |
if (stack!=NULL){ |
90 |
ascfree((char *)stack->ptr); |
91 |
stack->ptr = NULL; |
92 |
ascfree((char *)stack); |
93 |
} |
94 |
} |
95 |
|
96 |
#define RECYCLESTACKSIZE 20 /* largest stack we will attempt to recycle */ |
97 |
static struct stack_t * g_recycle_expreval_stacks[RECYCLESTACKSIZE]; |
98 |
/* ANSI ASSUMPTION: this array is initialize to NULL values */ |
99 |
/* Assumption about client: |
100 |
* It will never try to free any element of the stack, nor |
101 |
* will it ever put the stack inside a struct value_t managed |
102 |
* (created and therefore destroyed) by value_type.c. |
103 |
* Nor will the client ever give the stack to someone else to |
104 |
* deallocate later. |
105 |
*/ |
106 |
static struct stack_t *CreateStack(unsigned int cap) |
107 |
{ |
108 |
struct stack_t *result; |
109 |
if (cap < RECYCLESTACKSIZE && g_recycle_expreval_stacks[cap] !=NULL) { |
110 |
result = g_recycle_expreval_stacks[cap]; |
111 |
/* move the NEXT recycled pointer into recycle array */ |
112 |
g_recycle_expreval_stacks[cap] = (struct stack_t *)result->size; |
113 |
result->size =0; /* ptr and capacity valid from initial allocation */ |
114 |
return result; |
115 |
} else { |
116 |
return AllocStack(cap); |
117 |
} |
118 |
} |
119 |
|
120 |
static void DestroyStack(struct stack_t *stack) |
121 |
{ |
122 |
if (stack==NULL) return; |
123 |
if (stack->capacity < RECYCLESTACKSIZE) { |
124 |
/* the recycle list NEXT pointer has to be cast into the size slot */ |
125 |
stack->size =(unsigned long)(g_recycle_expreval_stacks[stack->capacity]); |
126 |
/* push stack on LIFO recycle list */ |
127 |
g_recycle_expreval_stacks[stack->capacity] = stack; |
128 |
return; |
129 |
} else { |
130 |
DeAllocStack(stack); |
131 |
} |
132 |
} |
133 |
|
134 |
/* Clear and reinit expression stack recycler */ |
135 |
#define PRINTSTACKSTATS 0 |
136 |
void ClearRecycleStack(void) { |
137 |
unsigned int i,cnt; |
138 |
struct stack_t *stp; /* pointer to a recycled stack */ |
139 |
#if PRINTSTACKSTATS |
140 |
PRINTF("Stack cap.\tRecycle\n"); |
141 |
#endif |
142 |
for (i=0; i < RECYCLESTACKSIZE; i++) { |
143 |
cnt=0; |
144 |
while( (stp = g_recycle_expreval_stacks[i]) != NULL) { |
145 |
g_recycle_expreval_stacks[i] = (struct stack_t *)stp->size; |
146 |
DeAllocStack(stp); |
147 |
cnt++; |
148 |
} |
149 |
#if PRINTSTACKSTATS |
150 |
PRINTF("%d\t\t%d\n",i,cnt); |
151 |
#endif |
152 |
} |
153 |
} |
154 |
|
155 |
#ifndef NDEBUG |
156 |
static |
157 |
unsigned long StackSize(struct stack_t *stack) |
158 |
{ |
159 |
assert(stack&&stack->ptr); |
160 |
return stack->size; |
161 |
} |
162 |
#endif |
163 |
|
164 |
static |
165 |
struct value_t StackPopTop(struct stack_t *stack) |
166 |
{ |
167 |
assert(stack&&stack->ptr&&stack->size); |
168 |
return stack->ptr[--(stack->size)]; |
169 |
} |
170 |
|
171 |
static |
172 |
void StackPush(struct stack_t *stack, struct value_t value) |
173 |
{ |
174 |
assert(stack&&stack->ptr&&(stack->size<stack->capacity)); |
175 |
stack->ptr[(stack->size)++] = value; |
176 |
} |
177 |
|
178 |
/*------------------------------------------------------------------------------ |
179 |
EXPRESSION EVALUATION ROUTINES |
180 |
*/ |
181 |
|
182 |
/** |
183 |
@TODO What is this? |
184 |
*/ |
185 |
static |
186 |
unsigned int ExprStackDepth(CONST struct Expr *ex, |
187 |
CONST struct Expr *stop) |
188 |
{ |
189 |
register unsigned int maxdepth=0,depth=0; |
190 |
while (ex!=stop){ |
191 |
AssertMemory(ex); |
192 |
switch(ExprType(ex)){ |
193 |
case e_var: |
194 |
case e_diff: |
195 |
case e_zero: |
196 |
case e_int: |
197 |
case e_satisfied: |
198 |
case e_real: |
199 |
case e_boolean: |
200 |
case e_set: |
201 |
case e_symbol: |
202 |
case e_card: |
203 |
case e_choice: |
204 |
case e_sum: |
205 |
case e_prod: |
206 |
case e_union: |
207 |
case e_inter: |
208 |
if ((++depth)>maxdepth) maxdepth=depth; |
209 |
break; |
210 |
/* binary operators */ |
211 |
case e_plus: |
212 |
case e_minus: |
213 |
case e_times: |
214 |
case e_divide: |
215 |
case e_power: |
216 |
case e_ipower: |
217 |
case e_or: |
218 |
case e_and: |
219 |
case e_in: |
220 |
case e_equal: |
221 |
case e_notequal: |
222 |
case e_less: |
223 |
case e_greater: |
224 |
case e_lesseq: |
225 |
case e_greatereq: |
226 |
case e_boolean_eq: |
227 |
case e_boolean_neq: |
228 |
depth--; |
229 |
break; |
230 |
case e_st: |
231 |
Asc_Panic(2, NULL, |
232 |
"Such that in atoms is unsupported for the time being.\n"); |
233 |
break; |
234 |
/* no change*/ |
235 |
case e_func: |
236 |
case e_uminus: |
237 |
case e_not: |
238 |
break; |
239 |
case e_minimize: |
240 |
case e_maximize: |
241 |
Asc_Panic(2, NULL, |
242 |
"Maximize and minimize aren't allowed in expressions.\n" |
243 |
"They are only allowed in relations.\n"); |
244 |
break; |
245 |
default: |
246 |
Asc_Panic(2, NULL, "Unknown expression node type.\n"); |
247 |
break; |
248 |
} |
249 |
ex = NextExpr(ex); |
250 |
} |
251 |
return maxdepth; |
252 |
} |
253 |
|
254 |
/** |
255 |
@TODO What is this? |
256 |
*/ |
257 |
static |
258 |
CONST struct Expr *ContainsSuchThat(CONST struct Expr *expr, |
259 |
CONST struct Expr *stop) |
260 |
{ |
261 |
while (expr!=stop){ |
262 |
AssertMemory(expr); |
263 |
if (ExprType(expr)==e_st) return expr; |
264 |
expr = NextExpr(expr); |
265 |
} |
266 |
return 0; |
267 |
} |
268 |
|
269 |
/** |
270 |
@TODO What is this? |
271 |
*/ |
272 |
static |
273 |
unsigned SuchThatForm(CONST struct Expr *expr, |
274 |
CONST struct Expr *stop, |
275 |
CONST struct Expr **depth_one) |
276 |
{ |
277 |
unsigned depth=0; |
278 |
CONST struct Expr *previous=NULL; |
279 |
*depth_one = NULL; |
280 |
while (expr!=stop){ |
281 |
AssertMemory(expr); |
282 |
switch(ExprType(expr)){ |
283 |
case e_var: |
284 |
case e_diff: |
285 |
case e_zero: |
286 |
case e_int: |
287 |
case e_satisfied: |
288 |
case e_real: |
289 |
case e_boolean: |
290 |
case e_set: |
291 |
case e_symbol: |
292 |
case e_card: |
293 |
case e_choice: |
294 |
case e_sum: |
295 |
case e_prod: |
296 |
case e_union: |
297 |
case e_inter: |
298 |
if ((++depth)==1) *depth_one = expr; |
299 |
break; |
300 |
/* binary operators */ |
301 |
case e_plus: |
302 |
case e_minus: |
303 |
case e_times: |
304 |
case e_divide: |
305 |
case e_power: |
306 |
case e_ipower: |
307 |
case e_or: |
308 |
case e_and: |
309 |
case e_in: |
310 |
case e_equal: |
311 |
case e_notequal: |
312 |
case e_less: |
313 |
case e_greater: |
314 |
case e_lesseq: |
315 |
case e_greatereq: |
316 |
case e_boolean_eq: |
317 |
case e_boolean_neq: |
318 |
if ((--depth)==1) *depth_one = expr; |
319 |
break; |
320 |
case e_func: |
321 |
case e_uminus: |
322 |
case e_not: |
323 |
if (depth==1) *depth_one = expr; |
324 |
break; |
325 |
case e_st: |
326 |
if (previous==NULL) return 2; /* error */ |
327 |
if (NextExpr(expr)!=stop) return 2; /* error */ |
328 |
if (ExprType(*depth_one)==e_in) return 0; /* set definition */ |
329 |
if (ExprType(previous)==e_in) return 1; /* list of values */ |
330 |
return 2; /* error */ |
331 |
case e_minimize: |
332 |
case e_maximize: |
333 |
Asc_Panic(2, NULL, |
334 |
"Maximize and minimize are not allowed in expression.\n" |
335 |
"They are only allowed in relations.\n"); |
336 |
break; |
337 |
default: |
338 |
Asc_Panic(2, NULL, "%s: Unknown expression node type.\n",__FUNCTION__); |
339 |
break; |
340 |
} |
341 |
previous = expr; |
342 |
expr = NextExpr(expr); |
343 |
} |
344 |
return 2; |
345 |
} |
346 |
|
347 |
/** |
348 |
Evaluate the name of and contents of a set-valued expression. |
349 |
@TODO more detail on this. |
350 |
|
351 |
Expr must be a e_var type, and be named. Then, the expr is evaluated and if |
352 |
its type is set_value, then 0 returned. |
353 |
|
354 |
@return 0 if evaluation yeilds a set, else 1. |
355 |
*/ |
356 |
static |
357 |
int GetNameAndSet(CONST struct Expr *ex, CONST struct Expr *stop, |
358 |
symchar **name, struct value_t *value, |
359 |
struct value_t (*EvaluateName) (/* ??? */)) |
360 |
{ |
361 |
/* NAME SET IN */ |
362 |
if (ExprType(ex)==e_var){ |
363 |
if ((*name = SimpleNameIdPtr(ExprName(ex)))!=NULL){ |
364 |
*value = EvaluateExpr(NextExpr(ex),stop,EvaluateName); |
365 |
|
366 |
if (ValueKind(*value)==set_value){ |
367 |
return 0; |
368 |
} |
369 |
|
370 |
if (ValueKind(*value)==error_value){ |
371 |
return 1; |
372 |
} |
373 |
|
374 |
if(ValueKind(*value)==integer_value){ |
375 |
ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR); |
376 |
FPRINTF(ASCERR,"Found integer constant where set expected: "); |
377 |
WriteExprNode(ASCERR,NextExpr(ex)); |
378 |
FPRINTF(ASCERR,"\n"); |
379 |
error_reporter_end_flush(); |
380 |
}else if (ValueKind(*value)==symbol_value){ |
381 |
ERROR_REPORTER_START_NOLINE(ASC_USER_ERROR); |
382 |
FPRINTF(ASCERR,"Found symbol constant where set expected: "); |
383 |
WriteExprNode(ASCERR,NextExpr(ex)); |
384 |
FPRINTF(ASCERR,"\n"); |
385 |
error_reporter_end_flush(); |
386 |
} |
387 |
|
388 |
DestroyValue(value); |
389 |
*value = CreateErrorValue(type_conflict); |
390 |
return 1; |
391 |
} |
392 |
} |
393 |
*value = CreateErrorValue(incorrect_such_that); |
394 |
return 1; |
395 |
} |
396 |
|
397 |
/** |
398 |
@TODO what is this? |
399 |
*/ |
400 |
static |
401 |
int GetNameAndSetNamesNeeded(CONST struct Expr *ex, |
402 |
CONST struct Expr *stop, |
403 |
symchar **name) |
404 |
{ |
405 |
/* NAME SET IN */ |
406 |
if (ExprType(ex)==e_var){ |
407 |
*name = SimpleNameIdPtr(ExprName(ex)); |
408 |
if (*name != NULL){ |
409 |
EvaluateNamesNeeded(NextExpr(ex),stop,GNN); |
410 |
} |
411 |
return 0; |
412 |
} |
413 |
return 1; |
414 |
} |
415 |
|
416 |
/** |
417 |
@TODO what is this? |
418 |
*/ |
419 |
static |
420 |
struct value_t EvaluateLeftIteration(CONST struct Expr *expr, |
421 |
CONST struct Expr *stop, |
422 |
CONST struct Expr *depth_one, |
423 |
struct value_t (*EvaluateName)(/* ??? */)) |
424 |
{ |
425 |
CONST struct Expr *st_node,*rhs; |
426 |
struct set_t *sptr; |
427 |
symchar *tmp_name; /* name of temporary variable */ |
428 |
struct value_t iteration_set,tmp_value,l_value,rhs_value; |
429 |
unsigned long c,len; |
430 |
IVAL(iteration_set); |
431 |
IVAL(tmp_value); |
432 |
IVAL(l_value); |
433 |
IVAL(rhs_value); |
434 |
if (GetNameAndSet(expr,depth_one,&tmp_name,&iteration_set,EvaluateName)) { |
435 |
return iteration_set; |
436 |
} |
437 |
sptr = SetValue(iteration_set); |
438 |
rhs = NextExpr(depth_one); |
439 |
st_node = ContainsSuchThat(rhs,stop); |
440 |
switch(SetKind(sptr)){ |
441 |
case empty_set: |
442 |
DestroyValue(&iteration_set); |
443 |
return CreateVacantListValue(); |
444 |
case integer_set: |
445 |
case string_set: |
446 |
if (TempExists(tmp_name)){ |
447 |
FPRINTF(ASCERR,"Reused temporary variable %s.\n",SCP(tmp_name)); |
448 |
DestroyValue(&iteration_set); |
449 |
return CreateErrorValue(temporary_variable_reused); |
450 |
} |
451 |
l_value = CreateEmptyListValue(); |
452 |
AddTemp(tmp_name); |
453 |
len = Cardinality(sptr); |
454 |
for(c=1;c<=len;c++){ |
455 |
if (SetKind(sptr)==string_set) { |
456 |
tmp_value = CreateSymbolValue(FetchStrMember(sptr,c),1); |
457 |
} else { |
458 |
tmp_value = CreateIntegerValue(FetchIntMember(sptr,c),1); |
459 |
} |
460 |
SetTemp(tmp_name,tmp_value); |
461 |
rhs_value =EvaluateExpr(rhs,st_node,EvaluateName); |
462 |
if (ValueKind(rhs_value)!=boolean_value){ |
463 |
DestroyValue(&tmp_value); |
464 |
RemoveTemp(tmp_name); |
465 |
DestroyValue(&iteration_set); |
466 |
DestroyValue(&l_value); |
467 |
if (ValueKind(rhs_value)==error_value) { |
468 |
return rhs_value; |
469 |
} else { |
470 |
DestroyValue(&rhs_value); |
471 |
return CreateErrorValue(incorrect_such_that); |
472 |
} |
473 |
} |
474 |
if (BooleanValue(rhs_value)) { |
475 |
AppendToListValue(l_value,tmp_value); |
476 |
} |
477 |
DestroyValue(&tmp_value); |
478 |
DestroyValue(&rhs_value); |
479 |
} |
480 |
RemoveTemp(tmp_name); |
481 |
DestroyValue(&iteration_set); |
482 |
return l_value; |
483 |
} |
484 |
/*NOTREACHED*/ |
485 |
FPRINTF(ASCERR,"EvaluateLeftIteration returning erroneous value\n"); |
486 |
return tmp_value; |
487 |
} |
488 |
|
489 |
/** |
490 |
@TODO what is this? |
491 |
*/ |
492 |
static |
493 |
void EvaluateLeftIterationNamesNeeded(CONST struct Expr *expr, |
494 |
CONST struct Expr *stop, |
495 |
CONST struct Expr *depth_one) |
496 |
{ |
497 |
CONST struct Expr *st_node,*rhs; |
498 |
symchar *tmp_name; /* name of temporary variable */ |
499 |
if (GetNameAndSetNamesNeeded(expr,depth_one,&tmp_name)) { |
500 |
return; |
501 |
} |
502 |
rhs = NextExpr(depth_one); |
503 |
st_node = ContainsSuchThat(rhs,stop); |
504 |
if (tmp_name !=NULL && TempExists(tmp_name)){ |
505 |
FPRINTF(ASCERR,"Reused temporary variable %s.\n",SCP(tmp_name)); |
506 |
} |
507 |
AddTemp(tmp_name); |
508 |
GNN = EvaluateNamesNeeded(rhs,st_node,GNN); |
509 |
RemoveTemp(tmp_name); |
510 |
return; |
511 |
} |
512 |
|
513 |
/** |
514 |
@TODO what is this? |
515 |
Seems to be returning the *next* expression following a 'such that', although |
516 |
the function is named 'before such that'... |
517 |
*/ |
518 |
static |
519 |
CONST struct Expr *NodeBeforeSuchThat(CONST struct Expr *ex) |
520 |
{ |
521 |
while(ExprType(NextExpr(ex))!=e_st) { |
522 |
ex = NextExpr(ex); |
523 |
} |
524 |
return ex; |
525 |
} |
526 |
|
527 |
/** |
528 |
@TODO what is this? |
529 |
*/ |
530 |
static |
531 |
struct value_t EvaluateRightIteration(CONST struct Expr *expr, |
532 |
CONST struct Expr *stop, |
533 |
CONST struct Expr *depth_one, |
534 |
struct value_t (*EvaluateName)(/*???*/)) |
535 |
{ |
536 |
symchar *tmp_name; |
537 |
CONST struct Expr *node; |
538 |
struct value_t iteration_set,l_value,tmp_value,lhs_value; |
539 |
struct set_t *sptr; |
540 |
unsigned long c,len; |
541 |
|
542 |
(void)stop; /* stop gcc whine about unused parameter */ |
543 |
|
544 |
IVAL(iteration_set); |
545 |
IVAL(tmp_value); |
546 |
IVAL(l_value); |
547 |
IVAL(lhs_value); |
548 |
node = NodeBeforeSuchThat(depth_one); |
549 |
if (GetNameAndSet(NextExpr(depth_one),node, |
550 |
&tmp_name,&iteration_set,EvaluateName)) |
551 |
return iteration_set; |
552 |
node = NextExpr(depth_one); |
553 |
sptr = SetValue(iteration_set); |
554 |
switch(SetKind(sptr)){ |
555 |
case empty_set: |
556 |
DestroyValue(&iteration_set); |
557 |
return CreateVacantListValue(); |
558 |
case integer_set: |
559 |
case string_set: |
560 |
if (TempExists(tmp_name)){ |
561 |
FPRINTF(ASCERR,"Reused temporary variable %s.\n",SCP(tmp_name)); |
562 |
DestroyValue(&iteration_set); |
563 |
return CreateErrorValue(temporary_variable_reused); |
564 |
} |
565 |
l_value = CreateEmptyListValue(); |
566 |
AddTemp(tmp_name); |
567 |
len = Cardinality(sptr); |
568 |
for(c=1;c<=len;c++){ |
569 |
if (SetKind(sptr)==string_set) { |
570 |
tmp_value = CreateSymbolValue(FetchStrMember(sptr,c),1); |
571 |
} else { |
572 |
tmp_value = CreateIntegerValue(FetchIntMember(sptr,c),1); |
573 |
} |
574 |
SetTemp(tmp_name,tmp_value); |
575 |
lhs_value=EvaluateExpr(expr,node,EvaluateName); |
576 |
if (ValueKind(lhs_value)==error_value){ |
577 |
DestroyValue(&tmp_value); |
578 |
RemoveTemp(tmp_name); |
579 |
DestroyValue(&iteration_set); |
580 |
DestroyValue(&l_value); |
581 |
return lhs_value; |
582 |
} |
583 |
AppendToListValue(l_value,lhs_value); |
584 |
DestroyValue(&tmp_value); |
585 |
} |
586 |
RemoveTemp(tmp_name); |
587 |
DestroyValue(&iteration_set); |
588 |
return l_value; |
589 |
} |
590 |
/*NOTREACHED*/ |
591 |
FPRINTF(ASCERR,"EvaluateRightIteration returning erroneous value\n"); |
592 |
return tmp_value; |
593 |
} |
594 |
|
595 |
static |
596 |
void EvaluateRightIterationNamesNeeded(CONST struct Expr *expr, |
597 |
CONST struct Expr *stop, |
598 |
CONST struct Expr *depth_one) |
599 |
{ |
600 |
symchar *tmp_name; |
601 |
CONST struct Expr *node; |
602 |
|
603 |
(void)stop; /* stop gcc whine about unused parameter */ |
604 |
|
605 |
node = NodeBeforeSuchThat(depth_one); |
606 |
if (GetNameAndSetNamesNeeded(NextExpr(depth_one),node,&tmp_name)) { |
607 |
return; |
608 |
} |
609 |
node = NextExpr(depth_one); |
610 |
if (tmp_name !=NULL && TempExists(tmp_name)){ |
611 |
FPRINTF(ASCERR,"Reused temporary variable %s.\n",SCP(tmp_name)); |
612 |
return; |
613 |
} |
614 |
AddTemp(tmp_name); |
615 |
GNN = EvaluateNamesNeeded(expr,node,GNN); |
616 |
RemoveTemp(tmp_name); |
617 |
return; |
618 |
} |
619 |
|
620 |
static |
621 |
struct value_t EvaluateSuchThat(CONST struct Expr *expr, |
622 |
CONST struct Expr *stop, |
623 |
struct value_t (*EvaluateName) (/* ??? */)) |
624 |
{ |
625 |
CONST struct Expr *depth_one; |
626 |
switch(SuchThatForm(expr,stop,&depth_one)){ |
627 |
case 0: |
628 |
return EvaluateLeftIteration(expr,stop,depth_one,EvaluateName); |
629 |
case 1: |
630 |
return EvaluateRightIteration(expr,stop,depth_one,EvaluateName); |
631 |
default: |
632 |
return CreateErrorValue(incorrect_such_that); |
633 |
} |
634 |
} |
635 |
|
636 |
static |
637 |
void EvaluateSuchThatNamesNeeded(CONST struct Expr *expr, |
638 |
CONST struct Expr *stop) |
639 |
|
640 |
{ |
641 |
CONST struct Expr *depth_one; |
642 |
switch(SuchThatForm(expr,stop,&depth_one)){ |
643 |
case 0: |
644 |
EvaluateLeftIterationNamesNeeded(expr,stop,depth_one); |
645 |
return; |
646 |
case 1: |
647 |
EvaluateRightIterationNamesNeeded(expr,stop,depth_one); |
648 |
return; |
649 |
default: |
650 |
break; |
651 |
} |
652 |
} |
653 |
|
654 |
/** |
655 |
The main expression-evaluation routine for the ASCEND compiler? |
656 |
|
657 |
@TODO document this |
658 |
*/ |
659 |
struct value_t EvaluateExpr(CONST struct Expr *expr, CONST struct Expr *stop, |
660 |
struct value_t (*EvaluateName) (/* ? */)) |
661 |
{ |
662 |
struct value_t top,next; |
663 |
symchar *cptr; |
664 |
register struct stack_t *stack; |
665 |
IVAL(top); |
666 |
IVAL(next); |
667 |
if (ContainsSuchThat(expr,stop)!=NULL) { |
668 |
return EvaluateSuchThat(expr,stop,EvaluateName); |
669 |
} |
670 |
stack = CreateStack(ExprStackDepth(expr,stop)); |
671 |
while(expr!=stop){ |
672 |
AssertMemory(expr); |
673 |
switch(ExprType(expr)){ |
674 |
case e_var: /* variable */ |
675 |
cptr = SimpleNameIdPtr(ExprName(expr)); |
676 |
if ((cptr != NULL)&&TempExists(cptr)) { |
677 |
top = TempValue(cptr); |
678 |
} else { |
679 |
top = (*EvaluateName)(ExprName(expr)); |
680 |
} |
681 |
StackPush(stack,top); |
682 |
break; |
683 |
case e_func: /* function evaluation */ |
684 |
top = ApplyFunction(StackPopTop(stack),ExprFunc(expr)); |
685 |
StackPush(stack,top); |
686 |
break; |
687 |
case e_satisfied: /* satisfied evaluation */ |
688 |
top = InstanceEvaluateSatisfiedName(SatisfiedExprName(expr), |
689 |
SatisfiedExprRValue(expr)); |
690 |
StackPush(stack,top); |
691 |
break; |
692 |
case e_int: /* integer constant */ |
693 |
top = CreateIntegerValue(ExprIValue(expr),1); |
694 |
StackPush(stack,top); |
695 |
break; |
696 |
case e_zero: /* ambiguous 0 */ |
697 |
top = CreateRealValue(0.0,WildDimension(),1); |
698 |
StackPush(stack,top); |
699 |
break; |
700 |
case e_real: /* real constant */ |
701 |
top = CreateRealValue(ExprRValue(expr),ExprRDimensions(expr),1); |
702 |
StackPush(stack,top); |
703 |
break; |
704 |
case e_boolean: /* boolean constant */ |
705 |
top = CreateBooleanValue(ExprBValue(expr),1); |
706 |
StackPush(stack,top); |
707 |
break; |
708 |
case e_set: /* set */ |
709 |
top = EvaluateSet(ExprSValue(expr),EvaluateName); |
710 |
StackPush(stack,CreateSetFromList(top)); |
711 |
DestroyValue(&top); |
712 |
break; |
713 |
case e_symbol: /* symbol constant */ |
714 |
top = CreateSymbolValue(ExprSymValue(expr),1); |
715 |
StackPush(stack,top); |
716 |
break; |
717 |
case e_plus: /* binary plus operator */ |
718 |
top = StackPopTop(stack); |
719 |
next = StackPopTop(stack); |
720 |
StackPush(stack,AddValues(next,top)); |
721 |
DestroyValue(&top); |
722 |
DestroyValue(&next); |
723 |
break; |
724 |
case e_minus: /* binary minus operator */ |
725 |
top = StackPopTop(stack); |
726 |
next = StackPopTop(stack); |
727 |
StackPush(stack,SubtractValues(next,top)); |
728 |
DestroyValue(&top); |
729 |
DestroyValue(&next); |
730 |
break; |
731 |
case e_times: /* binary multiplication operator */ |
732 |
top = StackPopTop(stack); |
733 |
next = StackPopTop(stack); |
734 |
StackPush(stack,MultiplyValues(next,top)); |
735 |
DestroyValue(&top); |
736 |
DestroyValue(&next); |
737 |
break; |
738 |
case e_divide: /* binary division operator */ |
739 |
top = StackPopTop(stack); |
740 |
next = StackPopTop(stack); |
741 |
StackPush(stack,DivideValues(next,top)); |
742 |
DestroyValue(&top); |
743 |
DestroyValue(&next); |
744 |
break; |
745 |
case e_power: /* binary exponentiation operator */ |
746 |
case e_ipower: /* binary exponentiation operator */ |
747 |
top = StackPopTop(stack); |
748 |
next = StackPopTop(stack); |
749 |
StackPush(stack,PowerValues(next,top)); |
750 |
DestroyValue(&top); |
751 |
DestroyValue(&next); |
752 |
break; |
753 |
case e_card: /* cardinality operator */ |
754 |
top = EvaluateSet(ExprBuiltinSet(expr),EvaluateName); |
755 |
next = CreateSetFromList(top); |
756 |
StackPush(stack,CardValues(next)); |
757 |
DestroyValue(&top); |
758 |
DestroyValue(&next); |
759 |
break; |
760 |
case e_choice: /* choice operator */ |
761 |
top = EvaluateSet(ExprBuiltinSet(expr),EvaluateName); |
762 |
next = CreateSetFromList(top); |
763 |
StackPush(stack,ChoiceValues(next)); |
764 |
DestroyValue(&top); |
765 |
DestroyValue(&next); |
766 |
break; |
767 |
case e_sum: /* summation operator */ |
768 |
top = EvaluateSet(ExprBuiltinSet(expr),EvaluateName); |
769 |
StackPush(stack,SumValues(top)); |
770 |
DestroyValue(&top); |
771 |
break; |
772 |
case e_prod: /* product operator */ |
773 |
top = EvaluateSet(ExprBuiltinSet(expr),EvaluateName); |
774 |
StackPush(stack,ProdValues(top)); |
775 |
DestroyValue(&top); |
776 |
break; |
777 |
case e_union: /* union operator */ |
778 |
top = EvaluateSet(ExprBuiltinSet(expr),EvaluateName); |
779 |
StackPush(stack,UnionValues(top)); |
780 |
DestroyValue(&top); |
781 |
break; |
782 |
case e_inter: /* intersection operator */ |
783 |
top = EvaluateSet(ExprBuiltinSet(expr),EvaluateName); |
784 |
StackPush(stack,IntersectionValues(top)); |
785 |
DestroyValue(&top); |
786 |
break; |
787 |
case e_or: /* binary logical OR operator */ |
788 |
top = StackPopTop(stack); |
789 |
next = StackPopTop(stack); |
790 |
StackPush(stack,OrValues(next,top)); |
791 |
DestroyValue(&top); |
792 |
DestroyValue(&next); |
793 |
break; |
794 |
case e_and: /* binary logical AND operator */ |
795 |
top = StackPopTop(stack); |
796 |
next = StackPopTop(stack); |
797 |
StackPush(stack,AndValues(next,top)); |
798 |
DestroyValue(&top); |
799 |
DestroyValue(&next); |
800 |
break; |
801 |
case e_in: /* set membership test */ |
802 |
top = StackPopTop(stack); |
803 |
next = StackPopTop(stack); |
804 |
StackPush(stack,InValues(next,top)); |
805 |
DestroyValue(&top); |
806 |
DestroyValue(&next); |
807 |
break; |
808 |
case e_equal: /* equality test */ |
809 |
case e_boolean_eq: /* these two ought to be separated */ |
810 |
/* = should bind more tightly than == */ |
811 |
top = StackPopTop(stack); |
812 |
next = StackPopTop(stack); |
813 |
StackPush(stack,EqualValues(next,top)); |
814 |
DestroyValue(&top); |
815 |
DestroyValue(&next); |
816 |
break; |
817 |
case e_notequal: /* non-equality test */ |
818 |
case e_boolean_neq: /* these two ought to be separated */ |
819 |
/* <> should bind more tightly than != */ |
820 |
top = StackPopTop(stack); |
821 |
next = StackPopTop(stack); |
822 |
StackPush(stack,NotEqualValues(next,top)); |
823 |
DestroyValue(&top); |
824 |
DestroyValue(&next); |
825 |
break; |
826 |
case e_less: /* less than test */ |
827 |
top = StackPopTop(stack); |
828 |
next = StackPopTop(stack); |
829 |
StackPush(stack,LessValues(next,top)); |
830 |
DestroyValue(&top); |
831 |
DestroyValue(&next); |
832 |
break; |
833 |
case e_greater: /* greater than test */ |
834 |
top = StackPopTop(stack); |
835 |
next = StackPopTop(stack); |
836 |
StackPush(stack,GreaterValues(next,top)); |
837 |
DestroyValue(&top); |
838 |
DestroyValue(&next); |
839 |
break; |
840 |
case e_lesseq: /* less then or equal test */ |
841 |
top = StackPopTop(stack); |
842 |
next = StackPopTop(stack); |
843 |
StackPush(stack,LessEqValues(next,top)); |
844 |
DestroyValue(&top); |
845 |
DestroyValue(&next); |
846 |
break; |
847 |
case e_greatereq: /* greater than or equal test */ |
848 |
top = StackPopTop(stack); |
849 |
next = StackPopTop(stack); |
850 |
StackPush(stack,GreaterEqValues(next,top)); |
851 |
DestroyValue(&top); |
852 |
DestroyValue(&next); |
853 |
break; |
854 |
case e_uminus: /* unary minus operator */ |
855 |
top = StackPopTop(stack); |
856 |
StackPush(stack,NegateValue(top)); |
857 |
DestroyValue(&top); |
858 |
break; |
859 |
case e_not: /* unary logical NOT operator */ |
860 |
top = StackPopTop(stack); |
861 |
StackPush(stack,NotValue(top)); |
862 |
DestroyValue(&top); |
863 |
break; |
864 |
case e_st: /* such that */ |
865 |
Asc_Panic(2, NULL, "Something is royally wrong in EvaluateExpr.\n"); |
866 |
break; |
867 |
case e_minimize: |
868 |
case e_maximize: |
869 |
Asc_Panic(2, NULL, |
870 |
"Maximize and minimize are not allowed in expression.\n" |
871 |
"They are only allowed in relations.\n"); |
872 |
break; |
873 |
default: |
874 |
Asc_Panic(2, NULL, "Unknown expression node in EvaluateExpr.\n"); |
875 |
break; |
876 |
} |
877 |
expr = NextExpr(expr); |
878 |
} |
879 |
assert(StackSize(stack)==1); |
880 |
top = StackPopTop(stack); |
881 |
DestroyStack(stack); |
882 |
return top; |
883 |
} |
884 |
|
885 |
struct gl_list_t *EvaluateNamesNeeded(CONST struct Expr *expr, |
886 |
CONST struct Expr *stop, |
887 |
struct gl_list_t *nlist) |
888 |
{ |
889 |
symchar *cptr; |
890 |
CONST struct Name *n; |
891 |
|
892 |
if (nlist ==NULL) { |
893 |
nlist= gl_create(3L); |
894 |
} |
895 |
assert(nlist!=NULL); |
896 |
GNN = nlist; /* always done, so we don't need to set it back NULL after */ |
897 |
|
898 |
if (ContainsSuchThat(expr,stop)!=NULL) { |
899 |
EvaluateSuchThatNamesNeeded(expr,stop); |
900 |
return GNN; |
901 |
} |
902 |
while(expr!=stop){ |
903 |
AssertMemory(expr); |
904 |
switch(ExprType(expr)){ |
905 |
case e_var: /* variable */ |
906 |
case e_diff: /* derivative */ |
907 |
cptr = SimpleNameIdPtr(ExprName(expr)); |
908 |
if ( cptr == NULL || TempExists(cptr)==0 ) { |
909 |
/* append if name not already seen in list */ |
910 |
if (gl_search(nlist,(VOIDPTR)ExprName(expr), |
911 |
(CmpFunc)CompareNames) == 0L) |
912 |
{ |
913 |
gl_append_ptr(nlist,(VOIDPTR)ExprName(expr)); |
914 |
} |
915 |
} |
916 |
n = ExprName(expr); |
917 |
n = NextName(n); |
918 |
while (n != NULL) { |
919 |
if (NameId(n) == 0) { |
920 |
GNN = EvaluateSetNamesNeeded(NameSetPtr(n),GNN); |
921 |
} |
922 |
n = NextName(n); |
923 |
} |
924 |
break; |
925 |
case e_func: /* function evaluation */ |
926 |
case e_int: /* integer constant */ |
927 |
case e_zero: /* ambiguous 0 */ |
928 |
case e_real: /* real constant */ |
929 |
case e_boolean: /* boolean constant */ |
930 |
case e_satisfied: /* satisified expression */ |
931 |
break; |
932 |
case e_set: /* set */ |
933 |
GNN = EvaluateSetNamesNeeded(ExprSValue(expr),GNN); |
934 |
break; |
935 |
case e_symbol: /* symbol constant */ |
936 |
case e_plus: /* binary plus operator */ |
937 |
case e_minus: /* binary minus operator */ |
938 |
case e_times: /* binary multiplication operator */ |
939 |
case e_divide: /* binary division operator */ |
940 |
case e_power: /* binary exponentiation operator */ |
941 |
case e_ipower: /* binary exponentiation operator */ |
942 |
break; |
943 |
case e_card: /* cardinality operator */ |
944 |
case e_choice: /* choice operator */ |
945 |
case e_sum: /* summation operator */ |
946 |
case e_prod: /* product operator */ |
947 |
case e_union: /* union operator */ |
948 |
case e_inter: /* intersection operator */ |
949 |
GNN = EvaluateSetNamesNeeded(ExprBuiltinSet(expr),GNN); |
950 |
break; |
951 |
case e_or: /* binary logical OR operator */ |
952 |
case e_and: /* binary logical AND operator */ |
953 |
case e_in: /* set membership test */ |
954 |
case e_equal: /* equality test */ |
955 |
case e_bol_token: |
956 |
case e_boolean_eq: |
957 |
case e_boolean_neq: |
958 |
case e_notequal: /* non-equality test */ |
959 |
case e_less: /* less than test */ |
960 |
case e_greater: /* greater than test */ |
961 |
case e_lesseq: /* less then or equal test */ |
962 |
case e_greatereq: /* greater than or equal test */ |
963 |
case e_uminus: /* unary minus operator */ |
964 |
case e_not: /* unary logical NOT operator */ |
965 |
break; |
966 |
case e_st: /* such that */ |
967 |
Asc_Panic(2, "EvaluateNamesNeeded", |
968 |
"Something is royally wrong is EvaluateNamesNeeded.\n"); |
969 |
break; |
970 |
case e_minimize: |
971 |
case e_maximize: |
972 |
break; |
973 |
default: |
974 |
Asc_Panic(2, NULL, "Unknown expression node in EvaluateNamesNeeded.\n"); |
975 |
break; |
976 |
} |
977 |
expr = NextExpr(expr); |
978 |
} |
979 |
return GNN; |
980 |
} |
981 |
|
982 |
struct gl_list_t *EvaluateNamesNeededShallow(CONST struct Expr *expr, |
983 |
CONST struct Expr *stop, |
984 |
struct gl_list_t *nlist) |
985 |
{ |
986 |
symchar *cptr; |
987 |
|
988 |
if (nlist ==NULL) { |
989 |
nlist= gl_create(3L); |
990 |
} |
991 |
assert(nlist!=NULL); |
992 |
GNN = nlist; /* always done, so we don't need to set it back NULL after */ |
993 |
|
994 |
if (ContainsSuchThat(expr,stop)!=NULL) { |
995 |
EvaluateSuchThatNamesNeeded(expr,stop); |
996 |
return GNN; |
997 |
} |
998 |
while(expr!=stop){ |
999 |
AssertMemory(expr); |
1000 |
switch(ExprType(expr)){ |
1001 |
case e_var: /* variable */ |
1002 |
cptr = SimpleNameIdPtr(ExprName(expr)); |
1003 |
if ( cptr == NULL || TempExists(cptr)==0 ) { |
1004 |
/* append if name not already seen in list */ |
1005 |
if (gl_search(nlist,(VOIDPTR)ExprName(expr), |
1006 |
(CmpFunc)CompareNames) == 0L) |
1007 |
{ |
1008 |
gl_append_ptr(nlist,(VOIDPTR)ExprName(expr)); |
1009 |
} |
1010 |
} |
1011 |
break; |
1012 |
case e_func: /* function evaluation */ |
1013 |
case e_int: /* integer constant */ |
1014 |
case e_zero: /* ambiguous 0 */ |
1015 |
case e_real: /* real constant */ |
1016 |
case e_boolean: /* boolean constant */ |
1017 |
case e_satisfied: /* satisified expression */ |
1018 |
break; |
1019 |
case e_set: /* set */ |
1020 |
GNN = EvaluateSetNamesNeededShallow(ExprSValue(expr),GNN); |
1021 |
break; |
1022 |
case e_symbol: /* symbol constant */ |
1023 |
case e_plus: /* binary plus operator */ |
1024 |
case e_minus: /* binary minus operator */ |
1025 |
case e_times: /* binary multiplication operator */ |
1026 |
case e_divide: /* binary division operator */ |
1027 |
case e_power: /* binary exponentiation operator */ |
1028 |
case e_ipower: /* binary exponentiation operator */ |
1029 |
break; |
1030 |
case e_card: /* cardinality operator */ |
1031 |
case e_choice: /* choice operator */ |
1032 |
case e_sum: /* summation operator */ |
1033 |
case e_prod: /* product operator */ |
1034 |
case e_union: /* union operator */ |
1035 |
case e_inter: /* intersection operator */ |
1036 |
GNN = EvaluateSetNamesNeededShallow(ExprBuiltinSet(expr),GNN); |
1037 |
break; |
1038 |
case e_or: /* binary logical OR operator */ |
1039 |
case e_and: /* binary logical AND operator */ |
1040 |
case e_in: /* set membership test */ |
1041 |
case e_equal: /* equality test */ |
1042 |
case e_bol_token: |
1043 |
case e_boolean_eq: |
1044 |
case e_boolean_neq: |
1045 |
case e_notequal: /* non-equality test */ |
1046 |
case e_less: /* less than test */ |
1047 |
case e_greater: /* greater than test */ |
1048 |
case e_lesseq: /* less then or equal test */ |
1049 |
case e_greatereq: /* greater than or equal test */ |
1050 |
case e_uminus: /* unary minus operator */ |
1051 |
case e_not: /* unary logical NOT operator */ |
1052 |
break; |
1053 |
case e_st: /* such that */ |
1054 |
Asc_Panic(2, "EvaluateNamesNeededShallow", |
1055 |
"Something is wrong in EvaluateNamesNeededShallow.\n"); |
1056 |
break; |
1057 |
case e_minimize: |
1058 |
case e_maximize: |
1059 |
break; |
1060 |
default: |
1061 |
Asc_Panic(2, "EvaluateNamesNeededShallow", |
1062 |
"Unknown expression in EvaluateNamesNeededShallow.\n"); |
1063 |
break; |
1064 |
} |
1065 |
expr = NextExpr(expr); |
1066 |
} |
1067 |
return GNN; |
1068 |
} |
1069 |
|
1070 |
/* in this function we should do a bunch of logic checking before |
1071 |
* calling the CreateEmptyList; if we can he accounts for most |
1072 |
* of our memory activity |
1073 |
*/ |
1074 |
struct value_t EvaluateSet(CONST struct Set *sptr, |
1075 |
struct value_t (*EvaluateName) (/* ??? */)) |
1076 |
{ |
1077 |
struct value_t result,lower,upper; |
1078 |
long l,u,c; |
1079 |
int previous_state; |
1080 |
previous_state = EvaluatingSets; /* save the state as called recursively */ |
1081 |
EvaluatingSets = 1; |
1082 |
result = CreateEmptyListValue(); |
1083 |
while (sptr!=NULL){ |
1084 |
AssertMemory(sptr); |
1085 |
if (SetType(sptr)){ /* range */ |
1086 |
lower = EvaluateExpr(GetLowerExpr(sptr),NULL,EvaluateName); |
1087 |
if (ValueKind(lower)==error_value){ |
1088 |
DestroyValue(&result); |
1089 |
EvaluatingSets = previous_state; |
1090 |
return lower; |
1091 |
} |
1092 |
upper = EvaluateExpr(GetUpperExpr(sptr),NULL,EvaluateName); |
1093 |
if (ValueKind(upper)==error_value){ |
1094 |
DestroyValue(&lower); |
1095 |
DestroyValue(&result); |
1096 |
EvaluatingSets = previous_state; |
1097 |
return upper; |
1098 |
} |
1099 |
if((ValueKind(lower)!=integer_value)||(ValueKind(upper)!=integer_value)){ |
1100 |
DestroyValue(&lower); |
1101 |
DestroyValue(&upper); |
1102 |
DestroyValue(&result); |
1103 |
EvaluatingSets = previous_state; |
1104 |
return CreateErrorValue(type_conflict); |
1105 |
} |
1106 |
l = IntegerValue(lower); |
1107 |
u = IntegerValue(upper); |
1108 |
DestroyValue(&lower); |
1109 |
DestroyValue(&upper); |
1110 |
for(c=l;c<=u;c++) { |
1111 |
AppendToListValue(result,CreateIntegerValue(c,1)); |
1112 |
} |
1113 |
} else { /* singleton */ |
1114 |
lower = EvaluateExpr(GetSingleExpr(sptr),NULL,EvaluateName); |
1115 |
if (ValueKind(lower)==error_value){ |
1116 |
DestroyValue(&result); |
1117 |
EvaluatingSets = previous_state; |
1118 |
return lower; |
1119 |
} |
1120 |
AppendToListValue(result,lower); |
1121 |
} |
1122 |
sptr = NextSet(sptr); |
1123 |
} |
1124 |
EvaluatingSets = previous_state; |
1125 |
return result; |
1126 |
} |
1127 |
|
1128 |
/* in this function we should do a bunch of logic checking before |
1129 |
* calling the CreateEmptyList; if we can he accounts for most |
1130 |
* of our memory activity. |
1131 |
*/ |
1132 |
struct gl_list_t *EvaluateSetNamesNeeded(CONST struct Set *sptr, |
1133 |
struct gl_list_t *nlist) |
1134 |
{ |
1135 |
if (nlist ==NULL) { |
1136 |
nlist= gl_create(3L); |
1137 |
} |
1138 |
assert(nlist!=NULL); |
1139 |
GNN = nlist; /* always done, so we don't need to set it back NULL after */ |
1140 |
|
1141 |
while (sptr!=NULL){ |
1142 |
AssertMemory(sptr); |
1143 |
if (SetType(sptr)){ /* range */ |
1144 |
GNN = EvaluateNamesNeeded(GetLowerExpr(sptr),NULL,GNN); |
1145 |
GNN = EvaluateNamesNeeded(GetUpperExpr(sptr),NULL,GNN); |
1146 |
} else { /* singleton */ |
1147 |
GNN = EvaluateNamesNeeded(GetSingleExpr(sptr),NULL,GNN); |
1148 |
} |
1149 |
sptr = NextSet(sptr); |
1150 |
} |
1151 |
return GNN; |
1152 |
} |
1153 |
|
1154 |
/* in this function we should do a bunch of logic checking before |
1155 |
* calling the CreateEmptyList; if we can he accounts for most |
1156 |
* of our memory activity. |
1157 |
*/ |
1158 |
struct gl_list_t *EvaluateSetNamesNeededShallow(CONST struct Set *sptr, |
1159 |
struct gl_list_t *nlist) |
1160 |
{ |
1161 |
if (nlist ==NULL) { |
1162 |
nlist= gl_create(3L); |
1163 |
} |
1164 |
assert(nlist!=NULL); |
1165 |
GNN = nlist; /* always done, so we don't need to set it back NULL after */ |
1166 |
|
1167 |
while (sptr!=NULL){ |
1168 |
AssertMemory(sptr); |
1169 |
if (SetType(sptr)){ /* range */ |
1170 |
GNN = EvaluateNamesNeededShallow(GetLowerExpr(sptr),NULL,GNN); |
1171 |
GNN = EvaluateNamesNeededShallow(GetUpperExpr(sptr),NULL,GNN); |
1172 |
} else { /* singleton */ |
1173 |
GNN = EvaluateNamesNeededShallow(GetSingleExpr(sptr),NULL,GNN); |
1174 |
} |
1175 |
sptr = NextSet(sptr); |
1176 |
} |
1177 |
return GNN; |
1178 |
} |