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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 709 - (hide annotations) (download) (as text)
Wed Jun 28 16:28:57 2006 UTC (14 years, 1 month ago) by johnpye
File MIME type: text/x-csrc
File size: 45198 byte(s)
Monster commit!
Lots of recommenting and reorganising of external relations-related stuff.
Replaced a lot of ascmalloc and asccalloc calls with the new ASC_NEW* macros.
Fixed (?) the problem Art is having with icons in PyGTK.
Turned on -Wall in SConstruct and fixed up a stack of warnings.
Removed the redundant exit(2) from after Asc_Panic calls and added __attribute__((noreturn)).
Set doxygen to create callgraphs to level 2, updated doxyfile to version 1.4.7.
Fixed up building of extfntest.c.
1 aw0a 1 /*
2     * Logical Relation construction routines
3     * by Vicente Rico-Ramirez
4     * Version: $Revision: 1.18 $
5     * Version control file: $RCSfile: logrelation.c,v $
6     * Date last modified: $Date: 1998/02/20 02:10:24 $
7     * Last modified by: $Author: ballan $
8     *
9     * This file is part of the Ascend Language Interpreter.
10     *
11     * Copyright 1997, Carnegie Mellon University
12     *
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 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 <general/stack.h>
39     #include "compiler.h"
40     #include "fractions.h"
41     #include "dimen.h"
42     #include "functype.h"
43 johnpye 669 #include "expr_types.h"
44 johnpye 399 #include "name.h"
45     #include "exprs.h"
46     #include "sets.h"
47     #include "value_type.h"
48     #include "evaluate.h"
49     #include "forvars.h"
50     #include "find.h"
51     #include "relation_type.h"
52     #include "logical_relation.h"
53     #include "relation_util.h"
54     #include "logrelation.h"
55     #include "logrel_util.h"
56     #include "rel_common.h"
57     #include "temp.h"
58     #include "instance_enum.h"
59     #include "instquery.h"
60     #include "mathinst.h"
61     #include "atomvalue.h"
62     #include "instance_io.h"
63 aw0a 1
64    
65     /*
66     * Some global and exported variables. */
67    
68     /* boolean variables in the lofical relation */
69     struct gl_list_t *g_logrelation_bvar_list = NULL;
70     /* relations or logrelations in satisfied's exprssions */
71     struct gl_list_t *g_logrelation_satrel_list = NULL;
72    
73    
74     /*
75     * Simplification of Logical Equations not implemented yet
76     * We have to create
77     * the function SimplifyLogTermBuf (and subsidiary functions)
78     */
79     int g_simplify_logrelations = 0;
80    
81     /*********************************************************************\
82     Section for creation and management of logical relation terms.
83     It is cheaper to create logical relation terms in arrays the size of
84     the union than individually because of operating system overhead.
85     Lookout, the tokens have unionized: next they'll want a raise.
86     \*********************************************************************/
87     /*
88     * The define POOL_ALLOCLOGTERM is for people who are pulling terms out
89     * of a pool and promise to return them immediately.
90     */
91    
92     static pool_store_t g_logterm_pool = NULL;
93     /* A pool_store for 1 expression.
94     * Each time an expression is completed, it will be copied
95     * into an array which can be created already knowing
96     * its proper size. The array will be naturally in postfix.
97     */
98    
99     #define POOL_ALLOCLOGTERM LOGA_TERM(pool_get_element(g_logterm_pool))
100     /* get a token. Token is the size of the LogRelTermUnion. */
101     #define POOL_LOGRESET pool_clear_store(g_logterm_pool)
102     /* reset the pool for next expression */
103    
104     static struct {
105     long startcheck;
106     size_t len;
107     size_t cap;
108     struct logrel_term **buf;
109     unsigned long *termstack;
110     unsigned long termstackcap;
111     long endcheck;
112     } g_logterm_ptrs = {1234567890,0,0,NULL,NULL,0,987654321};
113    
114     #define TPBUF_LOGRESET (g_logterm_ptrs.len=0)
115     /* forget about all the logical terms in the buffer */
116    
117    
118     /*
119     * The pool has a good growth mechanism and can handle tokens.
120     * Tradeoff: it is slower to copy the final token data into a
121     * fixed array from pool pointers than from a buffer monolith.
122     */
123     #define TPBUF_LOGINITSIZE 1000
124     /* initial token buffer capacity */
125     #define TPBUF_LOGGROW 1000
126     /* token buffer growth rate */
127    
128     #define LOGRP_LEN 5
129     #if (SIZEOF_VOID_P == 8)
130     #define LOGRP_WID 41
131     #else
132     #define LOGRP_WID 63
133     #endif
134     /* retune rpwid if the size of tokens changes dramatically */
135     #define LOGRP_ELT_SIZE (sizeof(union LogRelTermUnion))
136     #define LOGRP_MORE_ELTS 5
137     /* Number of slots filled if more elements needed.
138     So if the pool grows, it grows by LOGRP_MORE_ELTS*LOGRP_WID elements
139     at a time. */
140     #define LOGRP_MORE_BARS 508
141     /* This is the number of pool bar slots to add during expansion.
142     not all the slots will be filled immediately. */
143    
144     /* This function is called at compiler startup time and destroy at shutdown.
145     One could also recall these every time there is a delete all types. */
146     void InitLogRelInstantiator(void) {
147     if (g_logterm_pool != NULL || g_logterm_ptrs.buf != NULL) {
148     Asc_Panic(2, NULL, "ERROR: InitLogRelInstantiator called twice.\n");
149     }
150     g_logterm_pool =
151     pool_create_store(LOGRP_LEN, LOGRP_WID, LOGRP_ELT_SIZE, LOGRP_MORE_ELTS,
152     LOGRP_MORE_BARS);
153     if (g_logterm_pool == NULL) {
154     Asc_Panic(2, "InitLogRelInstantiator",
155     "ERROR: InitLogRelInstantiator unable to allocate pool.\n");
156     }
157     g_logterm_ptrs.buf = (struct logrel_term **)
158 johnpye 709 ASC_NEW_ARRAY_CLEAR(union LogRelTermUnion *,TPBUF_LOGINITSIZE);
159 aw0a 1 if (g_logterm_ptrs.buf == NULL) {
160     Asc_Panic(2, "InitLogRelInstantiator",
161     "ERROR: InitLogRelInstantiator unable to allocate memory.\n");
162     }
163     g_logterm_ptrs.len = 0;
164     g_logterm_ptrs.cap = TPBUF_LOGINITSIZE;
165     g_logterm_ptrs.termstackcap = 200;
166 johnpye 709 g_logterm_ptrs.termstack = ASC_NEW_ARRAY(unsigned long,200);
167 aw0a 1 if (g_logterm_ptrs.termstack == NULL) {
168     Asc_Panic(2, "InitLogRelInstantiator",
169     "ERROR: InitLogRelInstantiator unable to allocate memory.\n");
170     }
171     }
172    
173     /* this function returns NULL when newcap is 0 or when
174     * it is unable to allocate the space requested.
175     */
176     static unsigned long *realloc_term_stack(unsigned long newcap){
177     if (!newcap) {
178     if (g_logterm_ptrs.termstackcap !=0) {
179     ascfree(g_logterm_ptrs.termstack);
180     g_logterm_ptrs.termstack = NULL;
181     g_logterm_ptrs.termstackcap = 0;
182     }
183     } else { /* less than means currently ok */
184     if (newcap >= g_logterm_ptrs.termstackcap) {
185     unsigned long *newbuf;
186     newbuf = (unsigned long *)
187     ascrealloc(g_logterm_ptrs.termstack,(sizeof(unsigned long)*newcap));
188     if (newbuf!=NULL) {
189     g_logterm_ptrs.termstack = newbuf;
190     g_logterm_ptrs.termstackcap = newcap;
191     } else {
192     FPRINTF(ASCERR,"Insufficient memory in logical relation processor\n");
193     return NULL;
194     }
195     }
196     }
197     return g_logterm_ptrs.termstack;
198     }
199    
200     void DestroyLogRelInstantiator(void) {
201     assert(g_logterm_ptrs.buf!=NULL);
202     assert(g_logterm_pool!=NULL);
203     ascfree(g_logterm_ptrs.buf);
204     g_logterm_ptrs.buf = NULL;
205     g_logterm_ptrs.cap = g_logterm_ptrs.len = (size_t)0;
206     if (g_logterm_ptrs.termstackcap != 0) {
207     ascfree(g_logterm_ptrs.termstack);
208     g_logterm_ptrs.termstack = NULL;
209     g_logterm_ptrs.termstackcap = 0;
210     }
211     pool_destroy_store(g_logterm_pool);
212     g_logterm_pool = NULL;
213     }
214    
215     void ReportLogRelInstantiator(FILE *f)
216     {
217     assert(g_logterm_pool!=NULL);
218     FPRINTF(f,"LogRelInstantiator ");
219     pool_print_store(f,g_logterm_pool,0);
220     FPRINTF(f,"LogRelInstantiator buffer capacity: %lu\n",
221     (unsigned long)g_logterm_ptrs.cap);
222     }
223    
224     /* The slower expansion process. */
225     static void ExpandLogTermBuf(struct logrel_term *t) {
226     struct logrel_term **newbuf;
227     newbuf = (struct logrel_term **)ascrealloc(g_logterm_ptrs.buf,
228     (sizeof(struct logrel_term *)*(g_logterm_ptrs.cap+TPBUF_LOGGROW)));
229     if (newbuf!=NULL) {
230     g_logterm_ptrs.buf = newbuf;
231     g_logterm_ptrs.cap += TPBUF_LOGGROW;
232     g_logterm_ptrs.buf[g_logterm_ptrs.len] = t;
233     g_logterm_ptrs.len++;
234     } else {
235     FPRINTF(ASCERR,
236     "ERROR: LogicalRelation Instantiator unable to allocate memory.\n");
237     /* we have ignored the term pointer, but somebody else still has it: pool */
238     }
239     return;
240     }
241    
242     /* Appends term to buffer. if buffer full and can't expand, forgets term.*/
243     static void AppendLogTermBuf(struct logrel_term *t) {
244     if (g_logterm_ptrs.len < g_logterm_ptrs.cap) {
245     g_logterm_ptrs.buf[g_logterm_ptrs.len++] = t;
246     } else {
247     ExpandLogTermBuf(t);
248     }
249     return;
250     }
251    
252    
253     struct logrel_side_temp {
254     unsigned long length;
255     union LogRelTermUnion *side;
256     };
257    
258    
259     /* forward declaration */
260     static struct logrel_term
261     *InfixArr_MakeLogSide(CONST struct logrel_side_temp *, int *);
262    
263    
264     /*
265     * returns 1 if converting buf is successful
266     * returns 0 if buf empty or insufficient memory.
267     * The structure tmp given is filled with an array of terms
268     * and its length. You must free the array if you decide you
269     * don't want it. We don't care how the structure is initialized.
270     */
271     static int ConvertLogTermBuf(struct logrel_side_temp *tmp)
272     {
273     union LogRelTermUnion *arr = NULL;
274     unsigned long len,c;
275    
276     realloc_term_stack(0);
277     len = g_logterm_ptrs.len;
278     if (len < 1) return 0;
279 johnpye 709 arr = ASC_NEW(union LogRelTermUnion);
280 aw0a 1 if (arr==NULL) {
281     FPRINTF(ASCERR,"Create Logical Relation: Insufficient memory :-(.\n");
282     return 0;
283     }
284     for (c=0; c<len; c++) {
285     arr[c] = *(LOGUNION_TERM(g_logterm_ptrs.buf[c]));
286     }
287     tmp->side = arr;
288     tmp->length = len;
289     return 1;
290     }
291    
292     /* usually we want to reset both simultaneously. reset our
293     pooling and buffering data. */
294     static
295     void DestroyLogTermList(void) {
296     POOL_LOGRESET;
297     TPBUF_LOGRESET;
298     }
299    
300    
301     /* create a term from the pool */
302     static struct logrel_term *CreateLogOpTerm(enum Expr_enum t)
303     {
304     struct logrel_term *term;
305     term = POOL_ALLOCLOGTERM;
306     assert(term!=NULL);
307     term->t = t;
308     if (t==e_not) {
309     LOGU_TERM(term)->left = NULL;
310     } else {
311     LOGB_TERM(term)->left = NULL;
312     LOGB_TERM(term)->right = NULL;
313     }
314     return term;
315     }
316    
317     /* create a term from the pool */
318     static struct logrel_term *CreateBoolVarTerm(CONST struct Instance *i)
319     {
320     struct logrel_term *term;
321     unsigned long pos;
322 jds 97 if (0 != (pos = gl_search(g_logrelation_bvar_list,i,(CmpFunc)CmpP))){
323 aw0a 1 /* find boolean var if already on logical relations var list */
324     term = POOL_ALLOCLOGTERM;
325     assert(term!=NULL);
326     term->t = e_var;
327     LOGBV_TERM(term) -> varnum = pos;
328     }
329     else{
330     /* or add it to the var list */
331     gl_append_ptr(g_logrelation_bvar_list,(VOIDPTR)i);
332     term = POOL_ALLOCLOGTERM;
333     term->t = e_var;
334     LOGBV_TERM(term) -> varnum = gl_length(g_logrelation_bvar_list);
335     }
336     return term;
337     }
338    
339    
340     static struct logrel_term *CreateBooleanTerm( int val )
341     {
342     struct logrel_term *term;
343     term = POOL_ALLOCLOGTERM;
344     assert(term!=NULL);
345     term->t = e_boolean;
346     LOGBC_TERM(term) -> bvalue = val;
347     return term;
348     }
349    
350     static struct logrel_term *CreateLogIntegerTerm( int val )
351     {
352     struct logrel_term *term;
353     term = POOL_ALLOCLOGTERM;
354     assert(term!=NULL);
355     term->t = e_int;
356     LOGI_TERM(term) -> ivalue = val;
357     return term;
358     }
359    
360     /* create a term from the pool */
361     static struct logrel_term *CreateSatisfiedTerm(CONST struct Name *n,
362     struct Instance *inst,
363     double value,
364     CONST dim_type *dimensions)
365     {
366     struct logrel_term *term;
367     unsigned long pos;
368 jds 97 if (0 != (pos = gl_search(g_logrelation_satrel_list,inst,(CmpFunc)CmpP))){
369 aw0a 1 /* find log/relation if already on logical relations satrel list */
370     term = POOL_ALLOCLOGTERM;
371     assert(term!=NULL);
372     term->t = e_satisfied;
373     LOGS_TERM(term) ->ncond = n;
374     LOGS_TERM(term) ->relnum = pos;
375     LOGS_TERM(term) ->rtol = value;
376     LOGS_TERM(term) ->dim = dimensions;
377     }
378     else{
379     /* or add it to the satrel list */
380     gl_append_ptr(g_logrelation_satrel_list,(VOIDPTR)inst);
381     term = POOL_ALLOCLOGTERM;
382     term->t = e_satisfied;
383     LOGS_TERM(term) ->ncond = n;
384     LOGS_TERM(term) ->relnum = gl_length(g_logrelation_satrel_list);
385     LOGS_TERM(term) ->rtol = value;
386     LOGS_TERM(term) ->dim = dimensions;
387     }
388     return term;
389     }
390    
391    
392     /*
393     * This function create and *must* create the memory
394     * for the structure and for the union that the stucuture
395     * points to. Too much code depends on the pre-existent
396     * of a properly initialized union.
397     */
398     struct logrelation *CreateLogRelStructure(enum Expr_enum t)
399     {
400     struct logrelation *result;
401 johnpye 709 result = ASC_NEW(struct logrelation);
402 aw0a 1 assert(result!=NULL);
403     memset((char *)&(result->token),0,sizeof(struct TokenLogRel));
404     result->logresidual = 0;
405     result->logiscond = 0;
406     result->lognominal = 1;
407     result->bvars = NULL;
408     result->satrels = NULL;
409     result->ref_count = 0;
410     result->relop = t;
411     return result;
412     }
413    
414    
415     /**************************************************************************\
416     Logical Relation processing and general logical relation check routines.
417     \**************************************************************************/
418    
419     /*
420     * Here we give up if boolean vars are not well defined.
421     * At present e_var acceptable ARE:
422     * BOOLEAN_ATOM_INSTANCE
423     * Well defined boolean constants.
424     * Everything else is trash.
425     * CreateLogTermFromInst() and CheckLogExpr() must have matching semantics.
426     */
427     static
428     struct logrel_term *CreateLogTermFromInst(struct Instance *inst,
429     struct Instance *lrel,
430     enum logrelation_errors *err)
431     {
432     struct logrel_term *term;
433     switch(InstanceKind(inst)){
434     case BOOLEAN_ATOM_INST:
435     term = CreateBoolVarTerm(inst);
436     AddLogRel(inst,lrel);
437     return term;
438     case BOOLEAN_CONSTANT_INST:
439     if ( AtomAssigned(inst) ){
440     term = CreateBooleanTerm(GetBooleanAtomValue(inst));
441     return term;
442     }
443     else{
444     *err = boolean_value_undefined;
445     return NULL;
446     }
447     case BOOLEAN_INST:
448     *err = incorrect_boolean_linst_type;
449     return NULL;
450     case INTEGER_CONSTANT_INST:
451     case INTEGER_ATOM_INST:
452     case INTEGER_INST:
453     *err = incorrect_integer_linst_type;
454     return NULL;
455     case SYMBOL_ATOM_INST:
456     case SYMBOL_CONSTANT_INST:
457     case SYMBOL_INST:
458     *err = incorrect_symbol_linst_type;
459     return NULL;
460     case REAL_ATOM_INST:
461     case REAL_CONSTANT_INST:
462     case REAL_INST:
463     *err = incorrect_real_linst_type;
464     return NULL;
465     default:
466     *err = incorrect_linst_type;
467     return NULL;
468     }
469     }
470    
471    
472    
473    
474     /* nonrecursive, but may call recursive things. returns 1 if ok. 0 if not
475     * On a return of 1, newside->arr will be filled and should be deallocated
476     * if the user does not want it. a return of 0 means that newside data is
477     * invalid.
478     * This is the ONLY function that should call DestroyLogTermList.
479     */
480     static int ConvertLogExpr(CONST struct Expr *start,
481     CONST struct Expr *stop,
482     struct Instance *ref,
483     struct Instance *lrel,
484     enum logrelation_errors *err,
485     enum find_errors *ferr,
486     struct logrel_side_temp *newside)
487     {
488     struct gl_list_t *instances;
489     struct logrel_term *term;
490     struct Instance *inst;
491     CONST struct relation *rel;
492     CONST struct logrelation *logrel;
493     enum Expr_enum type;
494     int result;
495     symchar *str;
496     struct for_var_t *fvp;
497     if (newside==NULL) {
498     Asc_Panic(2, NULL, "newside == NULL");
499     }
500     while(start!=stop){
501     switch(ExprType(start)){
502     case e_and:
503     case e_or:
504     case e_not:
505     term = CreateLogOpTerm(ExprType(start));
506     AppendLogTermBuf(term);
507     break;
508     case e_var:
509     if (GetEvaluationForTable()!= NULL &&
510 jds 97 (NULL != (str = SimpleNameIdPtr(ExprName(start)))) &&
511     (NULL != (fvp=FindForVar(GetEvaluationForTable(),str)))){
512 aw0a 1 if (GetForKind(fvp)==f_integer){
513     term = CreateLogIntegerTerm(GetForInteger(fvp));
514     AppendLogTermBuf(term);
515     }
516     else{
517     *err = incorrect_linst_type;
518     DestroyLogTermList();
519     return 0;
520     }
521     }
522     else{
523     instances = FindInstances(ref,ExprName(start),ferr);
524     if (instances!=NULL){
525     if (gl_length(instances)==1){
526     inst = (struct Instance *)gl_fetch(instances,1);
527     gl_destroy(instances);
528     if ((term = CreateLogTermFromInst(inst,lrel,err))!=NULL){
529     AppendLogTermBuf(term);
530     }
531     else{
532     DestroyLogTermList();
533     return 0;
534     }
535     }
536     else{
537     *err=incorrect_logstructure;
538     gl_destroy(instances);
539     DestroyLogTermList();
540     return 0;
541     }
542     }
543     else{
544     *err = find_logerror;
545     DestroyLogTermList();
546     return 0;
547     }
548     }
549     break;
550     case e_boolean:
551     term = CreateBooleanTerm(ExprBValue(start));
552     AppendLogTermBuf(term);
553     break;
554     case e_satisfied:
555     instances = FindInstances(ref,SatisfiedExprName(start),ferr);
556     if (instances == NULL){
557     *err = find_logerror;
558     gl_destroy(instances);
559     DestroyLogTermList();
560     return 0;
561     }
562     else{
563     if (gl_length(instances)==1) {
564     inst = (struct Instance *)gl_fetch(instances,1);
565     gl_destroy(instances);
566     switch(InstanceKind(inst)){
567     case REL_INST:
568     rel = GetInstanceRelation(inst,&type);
569     if (!RelationIsCond(rel)){
570     *err = incorrect_linst_type;
571     DestroyLogTermList();
572     return 0;
573     }
574     break;
575     case LREL_INST:
576     logrel = GetInstanceLogRel(inst);
577     if (!LogRelIsCond(logrel)){
578     *err = incorrect_linst_type;
579     DestroyLogTermList();
580     return 0;
581     }
582     break;
583     default:
584     *err = incorrect_linst_type;
585     DestroyLogTermList();
586     return 0;
587     }
588     }
589     else {
590     gl_destroy(instances);
591     *err=incorrect_logstructure;
592     return 0;
593     }
594     }
595     term = CreateSatisfiedTerm(SatisfiedExprName(start),
596     inst,
597     SatisfiedExprRValue(start),
598     SatisfiedExprRDimensions(start));
599     AddLogRel(inst,lrel);
600     AppendLogTermBuf(term);
601     break;
602     default:
603     *err = incorrect_logstructure;
604     DestroyLogTermList();
605     return 0;
606     }
607     start = NextExpr(start);
608     }
609     result = ConvertLogTermBuf(newside);
610     DestroyLogTermList();
611     return result;
612     /* we do not check result here. that is the callers job */
613     }
614    
615     static
616     CONST struct Expr *FindLogRHS(CONST struct Expr *ex)
617     {
618 johnpye 89 CONST struct Expr *rhs = NULL,*previous=NULL;
619 aw0a 1 unsigned depth=0;
620     while(ex!=NULL){
621     switch(ExprType(ex)){
622     case e_zero:
623     case e_var:
624     case e_int:
625     case e_real:
626     case e_boolean:
627     case e_set:
628     case e_symbol:
629     case e_card:
630     case e_choice:
631     case e_sum:
632     case e_prod:
633     case e_union:
634     case e_satisfied:
635     if ((++depth)==1) rhs = ex;
636     break;
637     /* binary operators */
638     case e_plus:
639     case e_minus:
640     case e_times:
641     case e_divide:
642     case e_power:
643     case e_ipower:
644     case e_or:
645     case e_and:
646     case e_in:
647     if ((--depth)==1) rhs = ex;
648     break;
649     case e_equal:
650     case e_notequal:
651     case e_boolean_eq:
652     case e_boolean_neq:
653     case e_less:
654     case e_greater:
655     case e_lesseq:
656     case e_greatereq:
657     if (NextExpr(ex)==NULL) {
658 johnpye 89 return NextExpr(rhs);
659 aw0a 1 } else {
660 johnpye 89 return NULL;
661 aw0a 1 }
662     case e_func:
663     case e_uminus:
664     case e_not:
665     if (depth==1) {
666     rhs = ex;
667     }
668     break;
669     case e_st:
670     Asc_Panic(2, NULL, "Such that expressions are not allowed.\n");
671     break;
672     case e_minimize:
673     case e_maximize:
674     Asc_Panic(2, NULL,
675     "Maximize and minimize are not allowed in expression.\n"
676     "They are only allowed in relations.\n");
677     break;
678     default:
679     Asc_Panic(2, NULL, "Unknown expression node type.\n");
680     break;
681     }
682     previous = ex;
683     ex = NextExpr(ex);
684     }
685     return NULL;
686     }
687    
688     /*********************************************************************\
689     This code is to support the conversion from postfix to infix.
690     \*********************************************************************/
691    
692     static void DoBreakPoint(void)
693     {
694     FPRINTF(ASCERR,"Something screwy with Infix_MakeLogSide\n");
695     return;
696     }
697    
698     #define PopLogTermStack(stack) \
699     ((struct logrel_term *)gs_stack_pop((stack)))
700     #define PushLogTermStack(stack,term) \
701     (gs_stack_push((stack),(char*)(term)))
702    
703     #if 0 /* defunct code. should be deleted? */
704     struct logrel_term *Infix_MakeLogSide(struct gl_list_t *term_list)
705     {
706     struct logrel_term *term = NULL;
707     struct logrel_term *left;
708     unsigned long len,count=1;
709     struct gs_stack_t *stack;
710     enum Expr_enum t;
711    
712     len = gl_length(term_list);
713     stack = gs_stack_create(len);
714     while(count <= len) {
715     term = (struct logrel_term *)gl_fetch(term_list,count);
716     switch(t = LogRelTermType(term)) {
717     case e_boolean:
718     case e_var:
719     gs_stack_push(stack,(char *)term);
720     break;
721     case e_satisfied:
722     gs_stack_push(stack,(char *)term);
723     break;
724     case e_not:
725     left = LOGA_TERM(gs_stack_pop(stack));
726     LOGU_TERM(term)-> left = left;
727     gs_stack_push(stack,(char *)term);
728     break;
729     case e_and:
730     case e_or:
731     LOGB_TERM(term) -> right = LOGA_TERM(gs_stack_pop(stack));
732     LOGB_TERM(term) -> left = LOGA_TERM(gs_stack_pop(stack));
733     gs_stack_push(stack,(char *)term);
734     break;
735     default:
736     Asc_Panic(2, NULL,
737     "Dont know this type of logical relation term in MakeInfix\n");
738     break;
739     }
740     count++;
741     }
742     term = LOGA_TERM(gs_stack_pop(stack));
743     if (!gs_stack_empty(stack)) /* ensure that the stack is empty */
744     DoBreakPoint();
745     gs_stack_destroy(stack,0);
746     return term;
747     }
748     #endif
749    
750     /*
751     * *err = 0 if ok, 1 otherwise. Sets up infix pointers.
752     */
753     static struct logrel_term
754     *InfixArr_MakeLogSide(CONST struct logrel_side_temp *tmp, int *err)
755     {
756     struct logrel_term *term = NULL;
757     struct logrel_term *left;
758     long len,count=0;
759     struct gs_stack_t *stack;
760     enum Expr_enum t;
761    
762     *err = 0;
763     len = tmp->length;
764     stack = gs_stack_create(len);
765     while(count < len) {
766     term = LOGA_TERM(&(tmp->side[count])); /* aka tmp->side+count */
767     switch(t = LogRelTermType(term)) {
768     case e_boolean:
769     case e_var:
770     gs_stack_push(stack,(char *)term);
771     break;
772     case e_satisfied:
773     gs_stack_push(stack,(char *)term);
774     break;
775     case e_not:
776     left = LOGA_TERM(gs_stack_pop(stack));
777     LOGU_TERM(term)->left = left;
778     gs_stack_push(stack,(char *)term);
779     break;
780     case e_and:
781     case e_or:
782     LOGB_TERM(term)->right = LOGA_TERM(gs_stack_pop(stack));
783     LOGB_TERM(term)->left = LOGA_TERM(gs_stack_pop(stack));
784     gs_stack_push(stack,(char *)term);
785     break;
786     default:
787     Asc_Panic(2, NULL,
788     "Dont know this type of logical relation term in MakeInfix\n");
789     break;
790     }
791     count++;
792     }
793     term = LOGA_TERM(gs_stack_pop(stack));
794     if (!gs_stack_empty(stack)) {
795     /* ensure that the stack is empty */
796     FPRINTF(ASCERR,"stacksize %ld\n",stack->size);
797     DoBreakPoint();
798     *err = 1;
799     }
800     gs_stack_destroy(stack,0);
801     return term;
802     }
803    
804     void DoInOrderLogRelVisit(struct logrel_term *term,
805     struct logrelation *r,
806     void (*func)(struct logrel_term *,
807     struct logrelation *))
808     {
809     if (term) {
810     switch(LogRelTermType(term)) {
811     case e_boolean:
812     case e_var:
813     (*func)(term,r);
814     break;
815     case e_satisfied:
816     (*func)(term,r);
817     break;
818     case e_not:
819     DoInOrderLogRelVisit(LOGU_TERM(term)->left,r,func);
820     (*func)(term,r);
821     break;
822     case e_and:
823     case e_or:
824     DoInOrderLogRelVisit(LOGB_TERM(term)->left,r,func);
825     (*func)(term,r);
826     DoInOrderLogRelVisit(LOGB_TERM(term)->right,r,func);
827     break;
828     default:
829     return;
830     }
831     }
832     }
833    
834     #if 0
835     /* This is a recursive deallocation of a term tree.
836     It presupposes all terms are independently allocated,
837     which at present is true nowhere in the compiler.
838     It's a nice little function, though so we'll keep it in case,
839     but not compile it in the meantime.
840     Token of logrelations term lists are not independently allocated.
841     */
842     void DestroyLogTermTree(struct logrel_term *term)
843     {
844     if (term) {
845     switch(term->t) {
846     case e_and:
847     case e_or:
848     DestroyLogTermTree(LOGB_TERM(term)->left);
849     DestroyLogTermTree(LOGB_TERM(term)->right);
850     ascfree((char *)term);
851     term = NULL;
852     break;
853     case e_satisfied:
854     ascfree((char *)term);
855     term = NULL;
856     break;
857     case e_not:
858     DestroyLogTermTree(LOGU_TERM(term)->left);
859     break;
860     case e_boolean:
861     case e_var:
862     ascfree((char *)term);
863     term = NULL;
864     break;
865     default:
866     FPRINTF(ASCERR,"DestroyLogTermTree called with unexpected term type\n");
867     break;
868     }
869     }
870     }
871     #endif
872    
873    
874     /*********************************************************************\
875     Relation Processing for Instantiation.
876     \*********************************************************************/
877     static void DestroyLogTermSide(struct logrel_side_temp *);
878     void DestroyBVarList(struct gl_list_t *, struct Instance *);
879     void DestroySatRelList(struct gl_list_t *, struct Instance *);
880    
881     struct logrelation *CreateLogicalRelation(struct Instance *reference,
882     struct Instance *lrelinst,
883     CONST struct Expr *ex,
884     enum logrelation_errors *err,
885     enum find_errors *ferr)
886     {
887     struct logrelation *result;
888     CONST struct Expr *rhs_ex,*last_ex;
889     int lhs,rhs;
890     enum Expr_enum type;
891     struct logrel_side_temp leftside,rightside;
892     assert(reference&&lrelinst&&ex&&err&&ferr);
893     g_logrelation_bvar_list = gl_create(20l);
894     g_logrelation_satrel_list = gl_create(2l);
895     *err = lokay;
896     *ferr = correct_instance;
897     last_ex = FindLastExpr(ex);
898     switch(ExprType(last_ex)){
899     case e_boolean_eq:
900     case e_boolean_neq:
901     type = ExprType(last_ex);
902     rhs_ex = FindLogRHS(ex);
903     if (rhs_ex!=NULL){
904     lhs = ConvertLogExpr(ex,rhs_ex,reference,lrelinst,err,ferr,&leftside);
905     if(!lhs) {
906     if (g_logrelation_bvar_list!=NULL) {
907     DestroyBVarList(g_logrelation_bvar_list,lrelinst);
908     }
909     g_logrelation_bvar_list = NULL;
910     if (g_logrelation_satrel_list!=NULL) {
911     DestroySatRelList(g_logrelation_satrel_list,lrelinst);
912     }
913     g_logrelation_satrel_list = NULL;
914     return NULL;
915     }
916     rhs = ConvertLogExpr(rhs_ex,last_ex,reference,lrelinst,err,
917     ferr,&rightside);
918     if(!rhs) {
919     DestroyLogTermSide(&leftside);
920     if (g_logrelation_bvar_list!=NULL) {
921     DestroyBVarList(g_logrelation_bvar_list,lrelinst);
922     }
923     g_logrelation_bvar_list = NULL;
924     if (g_logrelation_satrel_list!=NULL) {
925     DestroySatRelList(g_logrelation_satrel_list,lrelinst);
926     }
927     g_logrelation_satrel_list = NULL;
928     return NULL;
929     }
930     }
931     else{
932     *err = incorrect_logstructure;
933     FPRINTF(ASCERR,"Error finding logical relation operator.\n");
934     if (g_logrelation_bvar_list!=NULL) {
935     DestroyBVarList(g_logrelation_bvar_list,lrelinst);
936     }
937     g_logrelation_bvar_list = NULL;
938     if (g_logrelation_satrel_list!=NULL) {
939     DestroySatRelList(g_logrelation_satrel_list,lrelinst);
940     }
941     g_logrelation_satrel_list = NULL;
942     return NULL;
943     }
944     break;
945     default:
946     *err = incorrect_logstructure;
947 johnpye 190 ERROR_REPORTER_NOLINE(ASC_USER_ERROR,"Expression missing logical relation operator.");
948 aw0a 1 if (g_logrelation_bvar_list!=NULL) {
949     DestroyBVarList(g_logrelation_bvar_list,lrelinst);
950     }
951     g_logrelation_bvar_list = NULL;
952     if (g_logrelation_satrel_list!=NULL) {
953     DestroySatRelList(g_logrelation_satrel_list,lrelinst);
954     }
955     g_logrelation_satrel_list = NULL;
956     return NULL;
957     }
958     result = CreateLogRelStructure(type);
959     result->ref_count = 1;
960     if (lhs) {
961     int status;
962     result->token.lhs_len = leftside.length;
963     result->token.lhs = leftside.side;
964     result->token.lhs_term = InfixArr_MakeLogSide(&leftside,&status);
965     #ifndef NDEBUG
966     if (status) {
967     FPRINTF(ASCERR,"Anomaly in ");
968     WriteInstanceName(ASCERR,lrelinst,NULL);
969     FPRINTF(ASCERR," LHS.\n");
970     }
971     #endif
972     }
973     if (rhs) { /* sometimes true */
974     int status;
975     result->token.rhs_len = rightside.length;
976     result->token.rhs = rightside.side;
977     result->token.rhs_term = InfixArr_MakeLogSide(&rightside,&status);
978     #ifndef NDEBUG
979     if (status) {
980     FPRINTF(ASCERR,"Anomaly in ");
981     WriteInstanceName(ASCERR,lrelinst,NULL);
982     FPRINTF(ASCERR," RHS.\n");
983     }
984     #endif
985     }
986     result->bvars = g_logrelation_bvar_list;
987     result->satrels = g_logrelation_satrel_list;
988     g_logrelation_bvar_list = NULL;
989     g_logrelation_satrel_list = NULL;
990     return result;
991     }
992    
993    
994     /*
995     **************************************************************************
996     * Destroy Code.
997     *
998     * This takes care of destroying the parts of logical relations.
999     * It ensures that any variables that are
1000     * incident upon the logical relations have their logrelation references
1001     * removed. This is done using the RemoveLogRel function.
1002     * It also ensures that all the relations or logrelations referenced
1003     * (from SATISFIED operator) have their logrelation references
1004     * removed, using the RemoveLogRel function too.
1005     **************************************************************************
1006     */
1007    
1008     static void DestroyLogTermSide(struct logrel_side_temp *temp)
1009     {
1010     if (temp!=NULL){
1011     if (temp->side !=NULL) ascfree(temp->side);
1012     }
1013     temp->side=NULL;
1014     temp->length=0L;
1015     }
1016    
1017     void DestroyBVarList(struct gl_list_t *l, struct Instance *inst)
1018     {
1019     register struct Instance *ptr;
1020     register unsigned long c;
1021     for(c=gl_length(l);c>=1;c--)
1022 jds 97 if (NULL != (ptr = (struct Instance *)gl_fetch(l,c)))
1023 aw0a 1 RemoveLogRel(ptr,inst);
1024     gl_destroy(l);
1025     }
1026    
1027     void DestroySatRelList(struct gl_list_t *l, struct Instance *inst)
1028     {
1029     register struct Instance *ptr;
1030     register unsigned long c;
1031     for(c=gl_length(l);c>=1;c--)
1032 jds 97 if (NULL != (ptr = (struct Instance *)gl_fetch(l,c)))
1033 aw0a 1 RemoveLogRel(ptr,inst);
1034     gl_destroy(l);
1035     }
1036    
1037     void DestroyLogRelation(struct logrelation *lrel, struct Instance *lrelinst)
1038     {
1039     if (!lrel) return;
1040     assert(lrel->ref_count);
1041     if (--(lrel->ref_count)==0) {
1042     if (lrel->token.lhs!=NULL) ascfree(lrel->token.lhs);
1043     if (lrel->token.rhs!=NULL) ascfree(lrel->token.rhs);
1044     }
1045     if (lrel->bvars) DestroyBVarList(lrel->bvars,lrelinst);
1046     if (lrel->satrels) DestroySatRelList(lrel->satrels,lrelinst);
1047     ascfree((char *)lrel);
1048     }
1049    
1050    
1051     /*
1052     **************************************************************************
1053     * Variable Maintenance.
1054     *
1055     * Logical Relations need to keep a *unique* list of variables incident
1056     * upon them. However variables move around and also disappear,
1057     * in particular when being ARE_THE_SAME'd. This code does that variable
1058     * maintenance.
1059     *
1060     * This requires some explanation. There are a number of cases
1061     * to consider.
1062     *
1063     * 1) the old instance does not exist in the bvar list -- do nothing.
1064     *
1065     * 2) the old instance exists, but the new does not -- store the
1066     * the new instance in the slot where the old instance was and
1067     * return.
1068     *
1069     * 3) the old instance exists, *and* the new instance also exists in
1070     * the bvarlist. This can happen in the case when 2 variables
1071     * incident upon a logical relation are going to be ATS'ed (not wise
1072     * but possible.) We need to run down the entire list in the case
1073     * of logical relations. This is expensive and uses the
1074     * DeleteAndChange function.
1075     *
1076     * 4) the new instance is NULL, which can happen transiently during some
1077     * operations. This defaults to case 2).
1078     **************************************************************************
1079     */
1080    
1081    
1082     static
1083     void ChangeLogVarTermSide(union LogRelTermUnion *side,
1084     unsigned long int len,
1085     unsigned long int old,
1086     unsigned long int new)
1087     {
1088     register long c;
1089     register struct logrel_term *term;
1090     for(c=len-1;c>=0;c--){
1091     term = LOGA_TERM(&(side[c]));
1092     switch (term->t){
1093     case e_var:
1094     if (LOGBV_TERM(term)->varnum == old)
1095     LOGBV_TERM(term)->varnum = new;
1096     else
1097     if (LOGBV_TERM(term)->varnum > old) LOGBV_TERM(term)->varnum--;
1098     break;
1099     default:
1100     break;
1101     }
1102     }
1103     }
1104    
1105    
1106     static
1107     void ChangeLogSatTermSide(union LogRelTermUnion *side,
1108     unsigned long int len,
1109     unsigned long int old,
1110     unsigned long int new)
1111     {
1112     register long c;
1113     register struct logrel_term *term;
1114     for(c=len-1;c>=0;c--){
1115     term = LOGA_TERM(&(side[c]));
1116     switch (term->t){
1117     case e_satisfied:
1118     if (LOGS_TERM(term)->relnum == old)
1119     LOGS_TERM(term)->relnum = new;
1120     else
1121     if (LOGS_TERM(term)->relnum > old) LOGS_TERM(term)->relnum--;
1122     break;
1123     default:
1124     break;
1125     }
1126     }
1127     }
1128    
1129    
1130     static
1131     void LogDeleteAndChange(struct gl_list_t *relorvar, struct logrelation *lrel,
1132     unsigned long int pos1, unsigned long int pos2,
1133     int varflag)
1134     {
1135     if (pos1 < pos2) Swap(&pos1,&pos2);
1136     /* pos1 > pos2 now */
1137     gl_delete(relorvar,pos1,0);
1138     if (varflag) {
1139     if (lrel->token.rhs)
1140     ChangeLogVarTermSide(lrel->token.rhs,lrel->token.rhs_len,pos1,pos2);
1141     if (lrel->token.lhs)
1142     ChangeLogVarTermSide(lrel->token.lhs,lrel->token.lhs_len,pos1,pos2);
1143     }
1144     else {
1145     if (lrel->token.rhs)
1146     ChangeLogSatTermSide(lrel->token.rhs,lrel->token.rhs_len,pos1,pos2);
1147     if (lrel->token.lhs)
1148     ChangeLogSatTermSide(lrel->token.lhs,lrel->token.lhs_len,pos1,pos2);
1149     }
1150     }
1151    
1152     void ModifyLogRelPointers(struct gl_list_t *relorvar,
1153     struct logrelation *lrel,
1154     CONST struct Instance *old,
1155     CONST struct Instance *new)
1156     {
1157     unsigned long pos,other;
1158     CONST struct Instance *inst;
1159     int varflag;
1160     assert(lrel!=NULL);
1161    
1162     if (old==new) return;
1163    
1164     if (new){
1165 jds 97 if (0 != (pos = gl_search(relorvar,old,(CmpFunc)CmpP))) {
1166     if (0 != (other = gl_search(relorvar,new,(CmpFunc)CmpP))){
1167 aw0a 1 gl_store(relorvar,pos,(VOIDPTR)new); /* case 3 */
1168     if (new == NULL) {
1169     inst = old;
1170     }
1171     else {
1172     inst = new;
1173     }
1174     switch (inst->t) {
1175     case BOOLEAN_ATOM_INST:
1176     varflag = 1;
1177     LogDeleteAndChange(relorvar,lrel,pos,other,varflag);
1178     break;
1179     case REL_INST:
1180     case LREL_INST:
1181     varflag = 0;
1182     LogDeleteAndChange(relorvar,lrel,pos,other,varflag);
1183     break;
1184     default:
1185     Asc_Panic(2, NULL,
1186     "Wrong instance type passed to ChangeLogRelPointers\n");
1187     break;
1188     }
1189     }
1190     else
1191     gl_store(relorvar,pos,(char *)new); /* case 2 */
1192     }
1193     else{ /* case 1 */
1194     FPRINTF(ASCERR,"Warning ModifiyLogRelPointers not found.\n");
1195     FPRINTF(ASCERR,"This shouldn't effect your usage at all.\n");
1196     }
1197     }
1198     else /* case 4 */
1199 jds 97 if (0 != (pos = gl_search(relorvar,old,(CmpFunc)CmpP)))
1200 aw0a 1 gl_store(relorvar,pos,(VOIDPTR)new);
1201     }
1202    
1203    
1204     /* forward declaration for recursing Check functions of logical relation */
1205     static int
1206     CheckLogExpr(CONST struct Instance *ref, CONST struct Expr *start,
1207     CONST struct Expr *stop, int list);
1208    
1209    
1210     /**********************************************************************\
1211     Here we check that vars are well defined, a precondition to FOR
1212     statements being executed.
1213     If lists of vars are acceptable (don't know why they would be)
1214     list should be passed in as 1, otherwise 0.
1215     At present e_var acceptable ARE:
1216     BOOLEAN_ATOM_INSTANCE
1217     Well defined Boolean constants.
1218     CreateLogTermFromInst() and CheckLogExpr() must have matching semantics.
1219    
1220     Returns: 1 --> OK,
1221     0 --> BAD (undefined/unassigned) try again later
1222     -1 --> incurably BAD
1223     \**********************************************************************/
1224     static int CheckExprBVar(CONST struct Instance *ref, CONST struct Name *name,
1225     int list)
1226     {
1227     struct gl_list_t *instances;
1228     symchar *str;
1229     struct Instance *inst;
1230     struct for_var_t *fvp;
1231     enum find_errors err;
1232 jds 97 if(NULL != (str = SimpleNameIdPtr(name))){
1233 ben.allan 14 if (TempExists(str)) {
1234     if (ValueKind(TempValue(str))==integer_value) {
1235 aw0a 1 return 1;
1236 ben.allan 14 } else {
1237 aw0a 1 return -1;
1238 ben.allan 14 }
1239     }
1240 aw0a 1 if (GetEvaluationForTable() != NULL &&
1241 jds 97 (NULL != (fvp=FindForVar(GetEvaluationForTable(),str))) ) {
1242 ben.allan 14 if (GetForKind(fvp)==f_integer) {
1243 aw0a 1 return 1;
1244 ben.allan 14 } else {
1245 aw0a 1 return -1;
1246 ben.allan 14 }
1247     }
1248 aw0a 1 }
1249     instances = FindInstances(ref,name,&err); /* need noisy version of Find */
1250     if (instances == NULL){
1251     switch(err){
1252     case unmade_instance:
1253     case undefined_instance:
1254     return 0;
1255     default:
1256     return -1;
1257     }
1258     }
1259     else{
1260     if (gl_length(instances)==1) {
1261     inst = (struct Instance *)gl_fetch(instances,1);
1262     gl_destroy(instances);
1263     switch(InstanceKind(inst)){
1264     case BOOLEAN_ATOM_INST:
1265     return 1;
1266     case DUMMY_INST:
1267     return 1;
1268     case BOOLEAN_CONSTANT_INST:
1269     if (AtomAssigned(inst)) {
1270     return 1;
1271     }
1272     return 0;
1273     default: return -1; /* bogus var type found */
1274     }
1275     }
1276     else if (list){
1277     /* this part of the code is most peculiar, and semantics may not
1278     match it. We need to find out what is the semantics of list. */
1279     unsigned long c,len;
1280     len = gl_length(instances);
1281     for(c=1;c<=len;c++){
1282     inst = (struct Instance *)gl_fetch(instances,1);
1283     switch(InstanceKind(inst)){
1284     case BOOLEAN_ATOM_INST:
1285     break;
1286     case DUMMY_INST:
1287     break;
1288     case BOOLEAN_CONSTANT_INST:
1289     if (!AtomAssigned(inst)){
1290     gl_destroy(instances);
1291     return -1;
1292     }
1293     default:
1294     gl_destroy(instances);
1295     return 0;
1296     }
1297     }
1298     gl_destroy(instances);
1299     return 1;
1300     }
1301     else {
1302     gl_destroy(instances);
1303     return -1;
1304     }
1305     }
1306     }
1307    
1308    
1309     static int CheckExprSatisfied(CONST struct Instance *ref,
1310     CONST struct Name *name)
1311     {
1312     struct gl_list_t *instances;
1313     struct Instance *inst;
1314     enum find_errors err;
1315    
1316     instances = FindInstances(ref,name,&err);
1317     if (instances == NULL){
1318     gl_destroy(instances);
1319     FPRINTF(ASCERR,
1320     "Name of an unmade instance (Relation) in Satisfied Expr \n");
1321     return 0;
1322     }
1323     else{
1324     if (gl_length(instances)==1) {
1325     inst = (struct Instance *)gl_fetch(instances,1);
1326     gl_destroy(instances);
1327     switch(InstanceKind(inst)){
1328     case REL_INST:
1329     return 1;
1330     case LREL_INST:
1331     return 1;
1332     case DUMMY_INST:
1333     return 1;
1334     default:
1335     FPRINTF(ASCERR,
1336     "Incorrect instance name (No Log/Relation)"
1337     " inside a Satisfied Expr\n");
1338     return 0;
1339     }
1340     }
1341     else {
1342     gl_destroy(instances);
1343     FPRINTF(ASCERR,
1344     "Error in Satisfied Expr Name assigned to more than one instance\n");
1345     return 0;
1346     }
1347     }
1348     }
1349    
1350    
1351     /**********************************************************************\
1352     CheckLogExpr(ref, start, stop, list)
1353     struct Instance *ref; context of the logical relation instance, ie
1354     parent. int list; boolean whether list of instances are acceptable
1355     struct Expr *start, *stop; pointers to the portion of relation this
1356     checks.
1357     \**********************************************************************/
1358     static int CheckLogExpr(CONST struct Instance *ref,
1359     CONST struct Expr *start,
1360     CONST struct Expr *stop,
1361     int list)
1362     {
1363     while (start!=stop){
1364     switch(ExprType(start)){
1365     case e_not:
1366     case e_and:
1367     case e_or:
1368     case e_boolean:
1369     break; /* automatically okay! */
1370     case e_satisfied:
1371     if(!CheckExprSatisfied(ref,SatisfiedExprName(start))) {
1372     return 0 ;
1373     }
1374     break;
1375     case e_var:
1376     switch(CheckExprBVar(ref,ExprName(start),list)){
1377     case 0:
1378     case -1:
1379     return 0;
1380     }
1381     break;
1382     default:
1383     return 0;
1384     }
1385     start = NextExpr(start);
1386     }
1387     return 1;
1388     }
1389    
1390     /* see header. returns 1 if relation expression is fully instantiable
1391     ie all vars exist, and, if need be, properly initialized. */
1392     int CheckLogRel(CONST struct Instance *reference, CONST struct Expr *ex)
1393     {
1394     CONST struct Expr *last_ex,*rhs_ex;
1395     last_ex = FindLastExpr(ex);
1396     switch(ExprType(last_ex)){
1397     case e_boolean_eq:
1398     case e_boolean_neq:
1399     rhs_ex = FindLogRHS(ex);
1400     if (!CheckLogExpr(reference,rhs_ex,last_ex,0)) return 0;
1401     return CheckLogExpr(reference,ex,rhs_ex,0);
1402     default:
1403     return 0;
1404     }
1405     }
1406    
1407    
1408     /*
1409     * We can now just do a memcopy and the infix pointers
1410     * all adjust by the difference between the token
1411     * arrays that the gl_lists are hiding. Cool, eh?
1412     * Note, if any turkey ever tries to delete an individual
1413     * token from these gl_lists AND deallocate it,
1414     * they will get a severe headache.
1415     *
1416     * This is a full blown copy and not copy by reference.
1417     * You do not need to remake the infix pointers after
1418     * calling this function.
1419     */
1420     static union LogRelTermUnion
1421     *CopyLogRelSide(union LogRelTermUnion *old, unsigned long len)
1422     {
1423     struct logrel_term *term;
1424     union LogRelTermUnion *arr;
1425     unsigned long c;
1426     long int delta;
1427    
1428     if (!old || !len) return NULL;
1429 johnpye 709 arr = ASC_NEW_ARRAY(union LogRelTermUnion,len);
1430 aw0a 1 if (arr==NULL) {
1431     FPRINTF(ASCERR,"Copy Logical Relation: Insufficient memory :-(.\n");
1432     return NULL;
1433     }
1434     memcpy( (VOIDPTR)arr, (VOIDPTR)old, len*sizeof(union LogRelTermUnion));
1435     /*
1436     * Difference in chars between old and arr ptrs. It should me a multiple
1437     * of sizeof(double) but may not be a multiple of sizeof(union LRTU).
1438     * Delta may easily be negative.
1439     * Normally, though arr > old.
1440     */
1441     delta = (char *)arr - (char *)old;
1442     #ifdef ADJLOGPTR
1443     #undef ADJLOGPTR
1444     #endif
1445     #define ADJLOGPTR(p) ( (p) = LOGA_TERM((char *)(p)+delta) )
1446     for (c=0;c<len;c++) {
1447     term = LOGA_TERM(&(arr[c]));
1448     switch (term->t) {
1449     /* unary terms */
1450     case e_not:
1451     ADJLOGPTR(LOGU_TERM(term)->left);
1452     break;
1453     /* binary terms */
1454     case e_and:
1455     case e_or:
1456     ADJLOGPTR(LOGB_TERM(term)->left);
1457     ADJLOGPTR(LOGB_TERM(term)->right);
1458     break;
1459     case e_boolean:
1460     case e_var: /* the var number will be correct */
1461     break;
1462     case e_satisfied:
1463     break;
1464     /* don't know how to deal with the following relation operators.
1465     they may be binary or unary, but InfixArr_MakeLogSide never set them. */
1466     case e_boolean_eq: case e_boolean_neq:
1467     default:
1468     Asc_Panic(2, NULL, "Unknown term type in CopyLogRelSide\n");
1469     break;
1470     }
1471     }
1472     #undef ADJLOGPTR
1473    
1474     return arr;
1475     }
1476    
1477    
1478     /*
1479     * This function will always create a new instance list, from
1480     * the instance list provided. The instances will be copied
1481     * and made aware of the destination logrelation instance.
1482     */
1483     static
1484     struct gl_list_t *CopyLogRelInstList(struct Instance *dest_inst,
1485     struct gl_list_t *instlist)
1486     {
1487     struct Instance *inst;
1488     struct gl_list_t *newinstlist = NULL;
1489     unsigned long len,c,pos;
1490    
1491     if (instlist) {
1492     len = gl_length(instlist);
1493     newinstlist = gl_create(len);
1494     for (c=1;c<=len;c++) {
1495     inst = (struct Instance *)gl_fetch(instlist,c);
1496     pos = gl_search(newinstlist,inst,(CmpFunc)CmpP);
1497     if (pos) {
1498     Asc_Panic(2, NULL, "Corrupted instance list in CopyLogRelation\n");
1499     }
1500     gl_append_ptr(newinstlist,(VOIDPTR)inst);
1501     AddLogRel(inst,dest_inst);
1502     }
1503     }
1504     else{ /* we will always return a newinstlist, even if empty */
1505     newinstlist = gl_create(1L);
1506     }
1507     return newinstlist;
1508     }
1509    
1510    
1511     static
1512     struct logrelation *CopyLogRelation(CONST struct Instance *src_inst,
1513     struct Instance *dest_inst,
1514     struct gl_list_t *varlist,
1515     struct gl_list_t *rellist)
1516     {
1517     CONST struct logrelation *src;
1518     struct logrelation *result;
1519     long int delta;
1520    
1521     src = GetInstanceLogRel(src_inst);
1522     if (!src) return NULL;
1523    
1524     result = CreateLogRelStructure(e_bol_token);
1525    
1526     result->ref_count = 1;
1527    
1528     result->token.lhs =
1529     CopyLogRelSide(src->token.lhs,src->token.lhs_len);
1530     if(result->token.lhs != NULL) {
1531     delta = LOGUNION_TERM(src->token.lhs_term) - src->token.lhs;
1532     result->token.lhs_term = LOGA_TERM(result->token.lhs+delta);
1533     result->token.lhs_len = src->token.lhs_len;
1534     } else {
1535     result->token.lhs_term = NULL;
1536     result->token.lhs_len = 0;
1537     }
1538    
1539     result->token.rhs =
1540     CopyLogRelSide(src->token.rhs,src->token.rhs_len);
1541     if(result->token.rhs != NULL) {
1542     delta = LOGUNION_TERM(src->token.rhs_term) - src->token.rhs;
1543     result->token.rhs_term = LOGA_TERM(result->token.rhs+delta);
1544     result->token.rhs_len = src->token.rhs_len;
1545     } else {
1546     result->token.rhs_term = NULL;
1547     result->token.rhs_len = 0;
1548     }
1549    
1550     result->bvars = CopyLogRelInstList(dest_inst,varlist);
1551     result->satrels = CopyLogRelInstList(dest_inst,rellist);
1552     result->logresidual = src->logresidual;
1553     result->lognominal = src->lognominal;
1554     return result;
1555     }
1556    
1557    
1558     struct logrelation *CopyLogRelByReference(CONST struct Instance *src_inst,
1559     struct Instance *dest_inst,
1560     struct gl_list_t *varlist,
1561     struct gl_list_t *rellist)
1562     {
1563     struct logrelation *src;
1564     struct logrelation *result;
1565     unsigned size;
1566    
1567     src = (struct logrelation *)GetInstanceLogRel(src_inst);
1568     if (!src) return NULL;
1569    
1570     result = CreateLogRelStructure(e_bol_token);
1571     size = sizeof(struct logrelation);
1572     ascbcopy(src,result,sizeof(struct logrelation));
1573     /* copy everything. */
1574     /*
1575     * We now have a verbatim copy. We now need to patch the public
1576     * stuff.
1577     */
1578     result->bvars = CopyLogRelInstList(dest_inst,varlist);
1579     result->satrels = CopyLogRelInstList(dest_inst,rellist);
1580     (src->ref_count)++;
1581     return result;
1582     }
1583    
1584     struct logrelation *CopyLogRelToModify(CONST struct Instance *src_inst,
1585     struct Instance *dest_inst,
1586     struct gl_list_t *varlist,
1587     struct gl_list_t *rellist)
1588     {
1589     CONST struct logrelation *src;
1590     struct logrelation *result;
1591     src = GetInstanceLogRel(src_inst);
1592     if (!src) return NULL;
1593     result = CopyLogRelation(src_inst,dest_inst,varlist,rellist);
1594     return result;
1595     }
1596    
1597    

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