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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 669 - (show annotations) (download) (as text)
Wed Jun 21 07:00:45 2006 UTC (13 years, 3 months ago) by johnpye
File MIME type: text/x-csrc
File size: 17794 byte(s)
Merged changes from DAE branch (revisions 702 to 819) back into trunk.
This adds the Integration API to the ASCEND solver (in base/generic).
Also provides pre-alpha support for 'IDA' from the SUNDIALS suite, a DAE solver.
Many other minor code clean-ups, including adoption of new 'ASC_NEW' and friends (to replace 'ascmalloc')
Added some very sketchy stuff providing 'DIFF(...)' syntax, although it is anticipated that this will be removed.
1 /* ASCEND modelling environment
2 Copyright (C) 2006 Carnegie Mellon University
3 Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly
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 Expression Module
22
23 Requires:
24 #include "utilities/ascConfig.h"
25 #include "fractions.h"
26 #include "compiler.h"
27 #include "dimen.h"
28 #include "expr_types.h"
29 *//*
30 by Tom Epperly
31 Last in CVS: $Revision: 1.13 $ $Date: 1998/02/05 16:35:58 $ $Author: ballan $
32 */
33
34 #include <stdio.h>
35 #include <assert.h>
36
37 #include <utilities/ascConfig.h>
38 #include <utilities/ascPanic.h>
39 #include "compiler.h"
40 #include <utilities/ascMalloc.h>
41 #include <general/list.h>
42 #include <general/pool.h>
43 #include "symtab.h"
44 #include "fractions.h"
45 #include "dimen.h"
46 #include "functype.h"
47 #include "expr_types.h"
48 #include "func.h"
49 #include "name.h"
50 #include "sets.h"
51 #include "instance_enum.h"
52 #include "cmpfunc.h"
53 #include "exprs.h"
54
55
56 #ifndef lint
57 static CONST char ExpressionID[] = "$Id: exprs.c,v 1.13 1998/02/05 16:35:58 ballan Exp $";
58 #endif
59
60 /*------------------------------------------------------------------------------
61 MEMORY USAGE
62
63 Using 'pool' or else regular malloc...
64 */
65
66 #ifdef ASC_NO_POOL
67 #define EXPRSUSESPOOL FALSE
68 #else
69 #define EXPRSUSESPOOL TRUE
70 #endif
71
72 #if EXPRSUSESPOOL /* using 'g_exprs_pool' for memory management */
73 /** global for our memory manager */
74 static pool_store_t g_exprs_pool = NULL;
75 /* aim for 4096 chunks including malloc overhead */
76 # define EMP_LEN 10
77 # if (SIZEOF_VOID_P == 8)
78 # define EMP_WID 63
79 # else
80 # define EMP_WID 127
81 # endif
82 /* retune rpwid if the size of struct name changes */
83 # define EMP_ELT_SIZE (sizeof(struct Expr))
84 # define EMP_MORE_ELTS 10
85 /**< Number of slots filled if more elements needed.
86 So if the pool grows, it grows by EMP_MORE_ELTS*EMP_WID elements at a time. */
87 # define EMP_MORE_BARS 500
88 /**< This is the number of pool bar slots to add during expansion.
89 not all the slots will be filled immediately. */
90
91 /**
92 This function is called at compiler startup time and destroy at shutdown.
93 */
94 void exprs_init_pool(void) {
95 if (g_exprs_pool != NULL ) {
96 Asc_Panic(2, NULL, "ERROR: exprs_init_pool called twice.\n");
97 }
98 g_exprs_pool = pool_create_store(EMP_LEN, EMP_WID, EMP_ELT_SIZE,
99 EMP_MORE_ELTS, EMP_MORE_BARS);
100 if (g_exprs_pool == NULL) {
101 Asc_Panic(2, NULL, "ERROR: exprs_init_pool unable to allocate pool.\n");
102 }
103 }
104
105 void exprs_destroy_pool(void) {
106 if (g_exprs_pool==NULL) return;
107 pool_clear_store(g_exprs_pool);
108 pool_destroy_store(g_exprs_pool);
109 g_exprs_pool = NULL;
110 }
111
112 void exprs_report_pool()
113 {
114 if (g_exprs_pool==NULL) {
115 FPRINTF(ASCERR,"ExprsPool is empty\n");
116 }
117 FPRINTF(ASCERR,"ExprsPool ");
118 pool_print_store(ASCERR,g_exprs_pool,0);
119 }
120
121 # define EPMALLOC \
122 ((struct Expr *)(pool_get_element(g_exprs_pool)))
123 /**< get a token. Token is the size of the struct struct Expr */
124
125 # define EPFREE(p) \
126 (pool_free_element(g_exprs_pool,((void *)p)))
127 /**< return a struct Expr */
128
129 # define EXPR_CHECK_MEMORY(VAR) \
130 AssertMemory(VAR)
131
132 #else /* not using 'g_exprs_pool'... */
133
134 void exprs_init_pool(void) {}
135 void exprs_destroy_pool(void) {}
136 void exprs_report_pool(void){
137 FPRINTF(ASCERR,"ExprsPool not used at all\n");
138 }
139
140 # define EPFREE(p) \
141 ASC_FREE(p)
142
143 # define EPMALLOC \
144 ASC_NEW(struct Expr)
145
146 # define EXPR_CHECK_MEMORY(VAR) \
147 AssertAllocatedMemory(result,sizeof(struct Expr))
148
149 #endif
150
151
152 # define EXPR_NEW(VAR,TYPE) \
153 VAR = EPMALLOC; \
154 VAR->t = TYPE; \
155 VAR->next = NULL
156
157 /*------------------------------------------------------------------------------
158 CREATION ROUTINES
159 */
160
161 struct Expr *CreateVarExpr(struct Name *n)
162 {
163 register struct Expr *result;
164 assert(n!=NULL);
165 AssertMemory(n);
166 EXPR_NEW(result,e_var);
167 result->v.nptr = n;
168 EXPR_CHECK_MEMORY(result);
169
170 return result;
171 }
172
173 /*
174 As with var, store pointer to the name, but give it a special type 'e_diff'.
175 */
176 struct Expr *CreateDiffExpr(struct Name *n){
177 register struct Expr *result;
178 ERROR_REPORTER_HERE(ASC_PROG_ERR,"not yet implemented");
179 EXPR_NEW(result,e_diff);
180 result->v.nptr = n;
181 EXPR_CHECK_MEMORY(result);
182 return result;
183 }
184
185 void InitVarExpr(struct Expr *result,CONST struct Name *n)
186 {
187 assert(n!=NULL);
188 AssertMemory(n);
189 result->t = e_var;
190 result->v.nptr = (struct Name *)n;
191 result->next = NULL;
192 }
193
194 struct Expr *CreateOpExpr(enum Expr_enum t)
195 {
196 register struct Expr *result;
197 assert((t!=e_var)&&(t!=e_func)&&(t!=e_int)&&(t!=e_real)&&(t!=e_zero));
198 EXPR_NEW(result,t);
199 #if EXPRSUSESPOOL
200 AssertMemory(result);
201 #else
202 AssertAllocatedMemory(result,sizeof(enum Expr_enum)+sizeof(struct Expr *));
203 #endif
204 return result;
205 }
206
207 struct Expr *CreateSatisfiedExpr(struct Name *n, double tol,
208 CONST dim_type *dims)
209 {
210 register struct Expr *result;
211 EXPR_NEW(result,e_satisfied);
212 result->v.se.sen = n;
213 result->v.se.ser.rvalue = tol;
214 result->v.se.ser.dimensions = dims;
215 EXPR_CHECK_MEMORY(result);
216 return result;
217 }
218
219 struct Expr *CreateFuncExpr(CONST struct Func *f)
220 {
221 register struct Expr *result;
222 EXPR_NEW(result,e_func);
223 result->v.fptr = f;
224 EXPR_CHECK_MEMORY(result);
225 return result;
226 }
227
228 struct Expr *CreateIntExpr(long int i)
229 {
230 register struct Expr *result;
231 EXPR_NEW(result,e_int);
232 result->v.ivalue = i;
233 EXPR_CHECK_MEMORY(result);
234 return result;
235 }
236
237 struct Expr *CreateRealExpr(double r, CONST dim_type *dims)
238 {
239 register struct Expr *result;
240 EXPR_NEW(result,e_real);
241 result->v.r.rvalue = r;
242 result->v.r.dimensions = dims;
243 EXPR_CHECK_MEMORY(result);
244 return result;
245 }
246
247 struct Expr *CreateTrueExpr(void)
248 {
249 register struct Expr *result;
250 EXPR_NEW(result,e_boolean);
251 result->v.bvalue = 1;
252 EXPR_CHECK_MEMORY(result);
253 return result;
254 }
255
256 struct Expr *CreateFalseExpr(void)
257 {
258 register struct Expr *result;
259 EXPR_NEW(result,e_boolean);
260 result->v.bvalue = 0;
261 EXPR_CHECK_MEMORY(result);
262 return result;
263 }
264
265 struct Expr *CreateAnyExpr(void)
266 {
267 register struct Expr *result;
268 EXPR_NEW(result,e_boolean);
269 result->v.bvalue = 2;
270 EXPR_CHECK_MEMORY(result);
271 return result;
272 }
273
274 struct Expr *CreateSetExpr(struct Set *set)
275 {
276 register struct Expr *result;
277 EXPR_NEW(result,e_set);
278 result->v.s = set;
279 EXPR_CHECK_MEMORY(result);
280 return result;
281 }
282
283
284 struct Expr *CreateSymbolExpr(symchar *sym)
285 {
286 register struct Expr *result;
287 assert(AscFindSymbol(sym)!=NULL);
288 EXPR_NEW(result,e_symbol);
289 result->v.sym_ptr = sym;
290 EXPR_CHECK_MEMORY(result);
291 return result;
292 }
293
294 struct Expr *CreateQStringExpr(CONST char *qstr)
295 {
296 register struct Expr *result;
297 EXPR_NEW(result,e_qstring);
298 result->v.sym_ptr = (symchar *)qstr; /* qstr really not symbol */
299 EXPR_CHECK_MEMORY(result);
300 return result;
301 }
302
303 struct Expr *CreateBuiltin(enum Expr_enum t, struct Set *set)
304 {
305 register struct Expr *result;
306 EXPR_NEW(result,t);
307 result->v.s = set;
308 EXPR_CHECK_MEMORY(result);
309 return result;
310 }
311
312 /*------------------------------------------------------------------------------
313 MANIPULATION ROUTINES
314 */
315
316 void LinkExprs(struct Expr *cur, struct Expr *next)
317 {
318 assert(cur!=NULL);
319 AssertMemory(cur);
320 cur->next = next;
321 }
322
323 struct Expr *NextExprF(CONST struct Expr *e)
324 {
325 assert(e!=NULL);
326 AssertMemory(e);
327 return e->next;
328 }
329
330 enum Expr_enum ExprTypeF(CONST struct Expr *e)
331 {
332 assert(e!=NULL);
333 AssertMemory(e);
334 return e->t;
335 }
336
337 CONST struct Name *ExprNameF(CONST struct Expr *e)
338 {
339 assert(e!=NULL);
340 AssertMemory(e);
341 return e->v.nptr;
342 }
343
344 CONST struct Func *ExprFuncF(CONST struct Expr *e)
345 {
346 assert(e!=NULL);
347 AssertMemory(e);
348 return e->v.fptr;
349 }
350
351 long ExprIValueF(CONST struct Expr *e)
352 {
353 assert(e!=NULL);
354 AssertMemory(e);
355 return e->v.ivalue;
356 }
357
358 double ExprRValueF(CONST struct Expr *e)
359 {
360 assert(e!=NULL);
361 AssertMemory(e);
362 return e->v.r.rvalue;
363 }
364
365 CONST dim_type *ExprRDimensionsF(CONST struct Expr *e)
366 {
367 assert(e!=NULL);
368 AssertMemory(e);
369 return e->v.r.dimensions;
370 }
371
372 CONST struct Name *SatisfiedExprNameF(CONST struct Expr *e)
373 {
374 assert(e!=NULL);
375 AssertMemory(e);
376 return e->v.se.sen ;
377 }
378
379 double SatisfiedExprRValueF(CONST struct Expr *e)
380 {
381 assert(e!=NULL);
382 AssertMemory(e);
383 return e->v.se.ser.rvalue;
384 }
385
386 CONST dim_type *SatisfiedExprRDimensionsF(CONST struct Expr *e)
387 {
388 assert(e!=NULL);
389 AssertMemory(e);
390 return e->v.se.ser.dimensions;
391 }
392
393 /* This function can be made HALF as long by being a little
394 * smarter about how we return the head of the list.
395 */
396 struct Expr *CopyExprList(CONST struct Expr *e)
397 {
398 register struct Expr *result, *p;
399 register CONST struct Expr *ep;
400 if (e==NULL) return NULL;
401 AssertMemory(e);
402 ep = e;
403 switch(ep->t){
404 case e_func:
405 result = EPMALLOC;
406 result->v.fptr = ep->v.fptr;
407 break;
408 case e_var:
409 result = EPMALLOC;
410 result->v.nptr = CopyName(ep->v.nptr);
411 break;
412 case e_int:
413 result = EPMALLOC;
414 result->v.ivalue = ep->v.ivalue;
415 break;
416 case e_zero:
417 case e_real:
418 result = EPMALLOC;
419 result->v.r.rvalue = ep->v.r.rvalue;
420 result->v.r.dimensions = ep->v.r.dimensions;
421 break;
422 case e_boolean:
423 result = EPMALLOC;
424 result->v.bvalue = ep->v.bvalue;
425 break;
426 case e_set:
427 result = EPMALLOC;
428 result->v.s = CopySetList(ep->v.s);
429 break;
430 case e_symbol:
431 result = EPMALLOC;
432 result->v.sym_ptr = ep->v.sym_ptr;
433 break;
434 case e_card:
435 case e_choice:
436 case e_sum:
437 case e_prod:
438 case e_union:
439 case e_inter:
440 result = EPMALLOC;
441 result->v.s = CopySetList(ep->v.s);
442 break;
443 default:
444 result = EPMALLOC;
445 break;
446 }
447 result->t = ep->t;
448 AssertMemory(result);
449 p = result;
450 while (ep->next != NULL) {
451 ep = ep->next;
452 AssertMemory(ep);
453 switch(ep->t) {
454 case e_func:
455 p->next = EPMALLOC;
456 p = p->next;
457 p->v.fptr = ep->v.fptr;
458 break;
459 case e_var:
460 p->next = EPMALLOC;
461 p = p->next;
462 p->v.nptr = CopyName(ep->v.nptr);
463 break;
464 case e_int:
465 p->next = EPMALLOC;
466 p = p->next;
467 p->v.ivalue = ep->v.ivalue;
468 break;
469 case e_real:
470 case e_zero:
471 p->next = EPMALLOC;
472 p = p->next;
473 p->v.r.rvalue = ep->v.r.rvalue;
474 p->v.r.dimensions = ep->v.r.dimensions;
475 break;
476 case e_boolean:
477 p->next = EPMALLOC;
478 p = p->next;
479 p->v.bvalue = ep->v.bvalue;
480 break;
481 case e_set:
482 p->next = EPMALLOC;
483 p = p->next;
484 p->v.s = CopySetList(ep->v.s);
485 break;
486 case e_symbol:
487 p->next = EPMALLOC;
488 p = p->next;
489 p->v.sym_ptr = ep->v.sym_ptr;
490 break;
491 case e_card:
492 case e_choice:
493 case e_sum:
494 case e_prod:
495 case e_union:
496 case e_inter:
497 p->next = EPMALLOC;
498 p = p->next;
499 p->v.s = CopySetList(ep->v.s);
500 break;
501 default:
502 p->next = EPMALLOC;
503 p = p->next;
504 break;
505 }
506 p->t = ep->t;
507 AssertMemory(p);
508 }
509 p->next = NULL;
510 AssertMemory(result);
511 return result;
512 }
513
514 void DestroyExprList(struct Expr *e)
515 {
516 register struct Expr *next,*ep;
517 ep = e;
518 while(ep!=NULL) {
519 AssertMemory(ep);
520 next = ep->next;
521 switch(ep->t) {
522 case e_var:
523 DestroyName(ep->v.nptr);
524 break;
525 case e_set:
526 case e_card:
527 case e_choice:
528 case e_sum:
529 case e_prod:
530 case e_union:
531 case e_inter:
532 DestroySetList(ep->v.s);
533 break;
534 default:
535 break;
536 }
537 EPFREE((char *)ep);
538 ep = next;
539 }
540 }
541
542 struct Expr *JoinExprLists(struct Expr *e1, struct Expr *e2)
543 {
544 register struct Expr *e;
545 if (e1 == NULL) return e2;
546 AssertMemory(e1);
547 e = e1;
548 /* find end of expr list */
549 while(e->next) e = e->next;
550 /* link to e2 */
551 e->next = e2;
552 AssertMemory(e1);
553 return e1;
554 }
555
556 unsigned long ExprListLength(CONST struct Expr *e)
557 {
558 register CONST struct Expr *ptr;
559 unsigned long len = 0L;
560
561 AssertMemory(e);
562 ptr = e;
563 while (ptr) {
564 ptr = ptr->next;
565 len++;
566 }
567 return len;
568 }
569
570
571 int ExprBValueF(CONST struct Expr *e)
572 {
573 assert(e&&(e->t==e_boolean));
574 AssertMemory(e);
575 return e->v.bvalue;
576 }
577
578 struct Set *ExprSValueF(CONST struct Expr *e)
579 {
580 assert(e&&(e->t==e_set));
581 AssertMemory(e);
582 return e->v.s;
583 }
584
585 symchar *ExprSymValueF(CONST struct Expr *e)
586 {
587 assert(e&&(e->t==e_symbol));
588 AssertMemory(e);
589 return e->v.sym_ptr;
590 }
591
592 CONST char *ExprQStrValueF(CONST struct Expr *e)
593 {
594 assert(e&&(e->t==e_qstring));
595 AssertMemory(e);
596 return (CONST char *)(e->v.sym_ptr); /* remember not a symbol */
597 }
598
599 CONST struct Set *ExprBuiltinSetF(CONST struct Expr *e)
600 {
601 assert(e!=NULL);
602 AssertMemory(e);
603 return e->v.s;
604 }
605
606 int ExprsEqual(CONST struct Expr *e1, CONST struct Expr *e2)
607 {
608 if (e1==e2) return 1;
609 while ((e1!=NULL)&&(e2!=NULL)){
610 AssertMemory(e1);
611 AssertMemory(e2);
612 if (ExprType(e1)!=ExprType(e2)) return 0;
613 switch(ExprType(e1)){
614 case e_var:
615 if (!NamesEqual(ExprName(e1),ExprName(e2))) return 0;
616 break;
617 case e_func:
618 if (ExprFunc(e1)!=ExprFunc(e2)) return 0;
619 break;
620 case e_int:
621 if (ExprIValue(e1)!=ExprIValue(e2)) return 0;
622 break;
623 case e_real:
624 if ((ExprRValue(e1)!=ExprRValue(e2))||
625 (!SameDimen(ExprRDimensions(e1),ExprRDimensions(e2)))) return 0;
626 break;
627 case e_boolean:
628 if (ExprBValue(e1)!=ExprBValue(e2)) return 0;
629 break;
630 case e_set:
631 if (!SetStructuresEqual(ExprSValue(e1),ExprSValue(e2))) return 0;
632 break;
633 case e_symbol:
634 if (CmpSymchar(ExprSymValue(e1),ExprSymValue(e2))!=0) return 0;
635 break;
636 default: break;
637 }
638 e1 = NextExpr(e1);
639 e2 = NextExpr(e2);
640 }
641 return ((e1==NULL)&&(e2==NULL));
642 }
643
644 int CompareExprs(CONST struct Expr *e1, CONST struct Expr *e2)
645 {
646 int ctmp;
647 long int ltmp;
648 double rtmp;
649 if (e1==e2) return 0;
650 if (e1==NULL) return 1;
651 if (e2==NULL) return -1;
652 while ((e1!=NULL)&&(e2!=NULL)){
653 AssertMemory(e1);
654 AssertMemory(e2);
655 ctmp = ExprType(e1) - ExprType(e2);
656 if (ctmp != 0) {
657 if (ctmp >0) {
658 return 1;
659 } else {
660 return -1;
661 }
662 }
663 switch(ExprType(e1)){
664 case e_var:
665 ctmp = CompareNames(ExprName(e1),ExprName(e2));
666 if (ctmp != 0) return ctmp;
667 break;
668 case e_func:
669 ctmp = strcmp(FuncName(ExprFunc(e1)),FuncName(ExprFunc(e2)));
670 if (ctmp != 0) return ctmp;
671 break;
672 case e_int:
673 ltmp = ExprIValue(e1) - ExprIValue(e2);
674 if (ltmp != 0L) {
675 if (ltmp > 0L) {
676 return 1;
677 } else {
678 return -1;
679 }
680 }
681 break;
682 case e_real:
683 rtmp = ExprRValue(e1) - ExprRValue(e2);
684 if (rtmp != 0.0) {
685 if (rtmp > 0.0) {
686 return 1;
687 } else {
688 return -1;
689 }
690 }
691 ctmp = CmpDimen(ExprRDimensions(e1),ExprRDimensions(e2));
692 if (ctmp != 0) return ctmp;
693 break;
694 case e_boolean:
695 if (ExprBValue(e1)!=ExprBValue(e2)) {
696 if (ExprBValue(e1) >0) {
697 return 1;
698 } else {
699 return -1;
700 }
701 }
702 break;
703 case e_set:
704 ctmp = CompareSetStructures(ExprSValue(e1),ExprSValue(e2));
705 if (ctmp != 0) return ctmp;
706 break;
707 case e_symbol:
708 ctmp = CmpSymchar(ExprSymValue(e1),ExprSymValue(e2));
709 if (ctmp != 0) return ctmp;
710 break;
711
712 case e_nop: /* fallthru */
713 case e_undefined: /* fallthru */
714 case e_glassbox: /* fallthru */
715 case e_blackbox: /* fallthru */
716 case e_opcode: /* fallthru */
717 case e_token: /* fallthru */
718 case e_zero: /* fallthru */
719 case e_uminus: /* fallthru */
720 case e_plus: /* fallthru */
721 case e_minus: /* fallthru */
722 case e_times: /* fallthru */
723 case e_divide: /* fallthru */
724 case e_power: /* fallthru */
725 case e_ipower: /* fallthru */
726 case e_bol_token: /* fallthru */
727 case e_notequal: /* fallthru */
728 case e_equal: /* fallthru */
729 case e_less: /* fallthru */
730 case e_greater: /* fallthru */
731 case e_lesseq: /* fallthru */
732 case e_greatereq: /* fallthru */
733 case e_maximize: /* fallthru */
734 case e_minimize: /* fallthru */
735 case e_boolean_eq: /* fallthru */
736 case e_boolean_neq: /* fallthru */
737 case e_or: /* fallthru */
738 case e_and: /* fallthru */
739 case e_not:
740 break;
741 case e_satisfied:
742 ctmp = CompareNames(SatisfiedExprName(e1),SatisfiedExprName(e2));
743 if (ctmp != 0) return ctmp;
744 rtmp = SatisfiedExprRValue(e1) - SatisfiedExprRValue(e2);
745 if (rtmp != 0.0) {
746 if (rtmp > 0.0) {
747 return 1;
748 } else {
749 return -1;
750 }
751 }
752 ctmp = CmpDimen(SatisfiedExprRDimensions(e1),
753 SatisfiedExprRDimensions(e2));
754 if (ctmp != 0) return ctmp;
755 break;
756 case e_subexpr:
757 case e_const:
758 case e_par:
759 case e_in:
760 case e_st:
761 break;
762 case e_qstring:
763 ctmp = strcmp(ExprQStrValue(e1),ExprQStrValue(e2));
764 if (ctmp != 0) return ctmp;
765 break;
766 case e_sum: /* fall thru */
767 case e_prod: /* fall thru */
768 case e_card: /* fall thru */
769 case e_choice: /* fall thru */
770 case e_union: /* fall thru */
771 case e_inter:
772 ctmp = CompareSetStructures(ExprBuiltinSet(e1),ExprBuiltinSet(e2));
773 if (ctmp != 0) return ctmp;
774 break;
775 }
776 e1 = NextExpr(e1);
777 e2 = NextExpr(e2);
778 }
779 /* shorter is < longer */
780 if (e2!=NULL) return 1;
781 if (e1!=NULL) return -1;
782 return 0;
783 }

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