1 |
/* |
2 |
* Logical Relation Output Routines |
3 |
* by Vicente Rico-Ramirez |
4 |
* Version: $Revision: 1.13 $ |
5 |
* Version control file: $RCSfile: logrel_io.c,v $ |
6 |
* Date last modified: $Date: 1997/10/28 19:20:39 $ |
7 |
* Last modified by: $Author: mthomas $ |
8 |
* |
9 |
* This file is part of the Ascend Language Interpreter. |
10 |
* |
11 |
* The Ascend Language Interpreter is free software; you can redistribute |
12 |
* it and/or modify it under the terms of the GNU General Public License as |
13 |
* published by the Free Software Foundation; either version 2 of the |
14 |
* License, or (at your option) any later version. |
15 |
* |
16 |
* The Ascend Language Interpreter is distributed in hope that it will be |
17 |
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 |
* General Public License for more details. |
20 |
* |
21 |
* You should have received a copy of the GNU General Public License |
22 |
* along with the program; if not, write to the Free Software Foundation, |
23 |
* Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check the file named |
24 |
* COPYING. |
25 |
* |
26 |
*/ |
27 |
|
28 |
#include <stdarg.h> |
29 |
#include <utilities/ascConfig.h> |
30 |
#include <utilities/ascMalloc.h> |
31 |
#include <utilities/ascPanic.h> |
32 |
#include <general/list.h> |
33 |
#include <general/dstring.h> |
34 |
#include "compiler.h" |
35 |
#include "fractions.h" |
36 |
#include "dimen.h" |
37 |
#include "functype.h" |
38 |
#include "expr_types.h" |
39 |
#include "find.h" |
40 |
#include "instance_enum.h" |
41 |
#include "instance_io.h" |
42 |
#include "logical_relation.h" |
43 |
#include "logrelation.h" |
44 |
#include "logrel_util.h" |
45 |
#include "logrel_io.h" |
46 |
#include "instquery.h" |
47 |
#include "parentchild.h" |
48 |
#include "mathinst.h" |
49 |
#include "visitinst.h" |
50 |
#include "tmpnum.h" |
51 |
|
52 |
|
53 |
static char g_log_shortbuf[256]; |
54 |
#define SBL255 g_log_shortbuf |
55 |
|
56 |
/* Logical Operators */ |
57 |
static |
58 |
void WriteLogOp(FILE *f, enum Expr_enum t) |
59 |
{ |
60 |
switch(t){ |
61 |
case e_and: FPRINTF(f,"AND"); break; |
62 |
case e_not: FPRINTF(f,"NOT"); break; |
63 |
case e_or: FPRINTF(f,"OR"); break; |
64 |
case e_boolean_eq: FPRINTF(f,"=="); break; |
65 |
case e_boolean_neq: FPRINTF(f,"!="); break; |
66 |
default: |
67 |
Asc_Panic(2, NULL, "Unknown term in WriteLogOp.\n");/*NOTREACHED*/ |
68 |
} |
69 |
} |
70 |
|
71 |
/* appends operators to dynamic symbol */ |
72 |
static void WriteLogOpDS(Asc_DString *dsPtr, enum Expr_enum t) |
73 |
{ |
74 |
assert(dsPtr!=NULL); |
75 |
switch(t){ |
76 |
case e_and: |
77 |
Asc_DStringAppend(dsPtr,"AND",3); |
78 |
break; |
79 |
case e_not: |
80 |
Asc_DStringAppend(dsPtr,"NOT",3); |
81 |
break; |
82 |
case e_or: |
83 |
Asc_DStringAppend(dsPtr,"OR",2); |
84 |
break; |
85 |
case e_boolean_eq: |
86 |
Asc_DStringAppend(dsPtr,"==",2); |
87 |
break; |
88 |
case e_boolean_neq: |
89 |
Asc_DStringAppend(dsPtr,"!=",2); |
90 |
break; |
91 |
default: |
92 |
FPRINTF(ASCERR,"Unknown term in WriteLogOpDS.\n"); |
93 |
Asc_DStringAppend(dsPtr,"ERROR",5); |
94 |
break; |
95 |
} |
96 |
} |
97 |
|
98 |
|
99 |
static |
100 |
void WriteLogTerm(FILE *f, |
101 |
CONST struct logrelation *lrel, |
102 |
CONST struct logrel_term *term, |
103 |
CONST struct Instance *inst) |
104 |
{ |
105 |
struct Instance *cur_var; |
106 |
struct Instance *rel; |
107 |
int bvalue; |
108 |
|
109 |
switch(LogRelTermType(term)){ |
110 |
case e_var: |
111 |
cur_var = LogRelBoolVar(lrel,LogTermBoolVarNumber(term)); |
112 |
WriteInstanceName(f,cur_var,inst); |
113 |
break; |
114 |
case e_satisfied: |
115 |
FPRINTF(f,"SATISFIED("); |
116 |
rel = LogRelRelation(lrel,LogTermSatRelNumber(term)); |
117 |
WriteInstanceName(f,rel,inst); |
118 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
119 |
FPRINTF(f,","); |
120 |
FPRINTF(f,"%g",LogTermSatTolerance(term)); |
121 |
} |
122 |
FPRINTF(f,")"); |
123 |
break; |
124 |
case e_int: |
125 |
FPRINTF(f,"%d",LogTermInteger(term)); |
126 |
break; |
127 |
case e_boolean: |
128 |
bvalue = LogTermBoolean(term); |
129 |
if (bvalue){ |
130 |
FPRINTF(f,"TRUE"); |
131 |
} |
132 |
else { |
133 |
FPRINTF(f,"FALSE"); |
134 |
} |
135 |
break; |
136 |
case e_and: |
137 |
case e_or: |
138 |
WriteLogOp(f,LogRelTermType(term)); |
139 |
break; |
140 |
case e_not: FPRINTF(f,"NOT"); break; |
141 |
default: |
142 |
Asc_Panic(2, NULL, "Unknown term type in WriteLogTerm.\n");/*NOTREACHED*/ |
143 |
} |
144 |
} |
145 |
|
146 |
static |
147 |
void WriteLogTermDS(Asc_DString *dsPtr, |
148 |
CONST struct logrelation *lrel, |
149 |
CONST struct logrel_term *term, |
150 |
CONST struct Instance *inst) |
151 |
{ |
152 |
struct Instance *cur_var; |
153 |
struct Instance *rel; |
154 |
int bvalue; |
155 |
switch(LogRelTermType(term)){ |
156 |
case e_var: |
157 |
cur_var = LogRelBoolVar(lrel,LogTermBoolVarNumber(term)); |
158 |
WriteInstanceNameDS(dsPtr,cur_var,inst); |
159 |
break; |
160 |
case e_satisfied: |
161 |
Asc_DStringAppend(dsPtr,"SATISFIED(",10); |
162 |
rel = LogRelRelation(lrel,LogTermSatRelNumber(term)); |
163 |
WriteInstanceNameDS(dsPtr,rel,inst); |
164 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
165 |
Asc_DStringAppend(dsPtr,",",1); |
166 |
sprintf(SBL255,"%g",LogTermSatTolerance(term)); |
167 |
Asc_DStringAppend(dsPtr,SBL255,-1); |
168 |
} |
169 |
Asc_DStringAppend(dsPtr,")",1); |
170 |
break; |
171 |
case e_int: |
172 |
sprintf(SBL255,"%d",LogTermInteger(term)); |
173 |
Asc_DStringAppend(dsPtr,SBL255,-1); |
174 |
break; |
175 |
case e_boolean: |
176 |
bvalue = LogTermBoolean(term); |
177 |
if (bvalue){ |
178 |
Asc_DStringAppend(dsPtr,"TRUE",4); |
179 |
} |
180 |
else { |
181 |
Asc_DStringAppend(dsPtr,"FALSE",5); |
182 |
} |
183 |
break; |
184 |
case e_and: |
185 |
case e_or: |
186 |
WriteLogOpDS(dsPtr,LogRelTermType(term)); |
187 |
break; |
188 |
case e_not: |
189 |
Asc_DStringAppend(dsPtr,"NOT",3); |
190 |
break; |
191 |
default: |
192 |
FPRINTF(ASCERR,"Unknown term in WriteLogTermDS.\n"); |
193 |
Asc_DStringAppend(dsPtr,"ERROR",5); |
194 |
break; |
195 |
} |
196 |
} |
197 |
|
198 |
static |
199 |
void WriteLogSidePostfix(FILE *f, |
200 |
CONST struct logrelation *lr, |
201 |
int side, |
202 |
CONST struct Instance *ref) |
203 |
{ |
204 |
unsigned c,len; |
205 |
CONST struct logrel_term *term; |
206 |
len = LogRelLength(lr,side); |
207 |
for(c=1;c<=len;c++){ |
208 |
term = LogRelTerm(lr,c,side); |
209 |
WriteLogTerm(f,lr,term,ref); |
210 |
if(c<len) PUTC(' ',f); |
211 |
} |
212 |
} |
213 |
|
214 |
static |
215 |
void WriteLogSidePostfixDS(Asc_DString *dsPtr, |
216 |
CONST struct logrelation *lr, |
217 |
int side, |
218 |
CONST struct Instance *ref) |
219 |
{ |
220 |
unsigned c,len; |
221 |
CONST struct logrel_term *term; |
222 |
len = LogRelLength(lr,side); |
223 |
for(c=1;c<=len;c++){ |
224 |
term = LogRelTerm(lr,c,side); |
225 |
WriteLogTermDS(dsPtr,lr,term,ref); |
226 |
if(c<len) Asc_DStringAppend(dsPtr," ",1); |
227 |
} |
228 |
} |
229 |
|
230 |
void WriteLogRelPostfix(FILE *f, |
231 |
CONST struct Instance *lrelinst, |
232 |
CONST struct Instance *ref) |
233 |
{ |
234 |
CONST struct logrelation *lr; |
235 |
|
236 |
lr = GetInstanceLogRel(lrelinst); |
237 |
switch(LogRelRelop(lr)){ |
238 |
case e_boolean_eq: |
239 |
case e_boolean_neq: |
240 |
WriteLogSidePostfix(f,lr,1,ref); |
241 |
PUTC(' ',f); |
242 |
WriteLogSidePostfix(f,lr,0,ref); |
243 |
PUTC(' ',f); |
244 |
WriteLogOp(f,LogRelRelop(lr)); |
245 |
break; |
246 |
default: |
247 |
FPRINTF(ASCERR,"Unexpected boolean Relop in WriteLogRelPostfix\n"); |
248 |
break; |
249 |
} |
250 |
} |
251 |
|
252 |
char *WriteLogRelPostfixToString( CONST struct Instance *lrelinst, |
253 |
CONST struct Instance *ref) |
254 |
{ |
255 |
CONST struct logrelation *lr; |
256 |
char *result; |
257 |
static Asc_DString ds; |
258 |
Asc_DString *dsPtr; |
259 |
|
260 |
lr = GetInstanceLogRel(lrelinst); |
261 |
dsPtr = &ds; |
262 |
Asc_DStringInit(dsPtr); |
263 |
|
264 |
switch(LogRelRelop(lr)){ |
265 |
case e_boolean_eq: |
266 |
case e_boolean_neq: |
267 |
WriteLogSidePostfixDS(dsPtr,lr,1,ref); |
268 |
Asc_DStringAppend(dsPtr," ",1); |
269 |
WriteLogSidePostfixDS(dsPtr,lr,0,ref); |
270 |
Asc_DStringAppend(dsPtr," ",1); |
271 |
WriteLogOpDS(dsPtr,LogRelRelop(lr)); |
272 |
break; |
273 |
default: |
274 |
FPRINTF(ASCERR,"Unexpected boolean Relop in WriteLogRelPostfixToString\n"); |
275 |
break; |
276 |
} |
277 |
result = Asc_DStringResult(dsPtr); |
278 |
Asc_DStringFree(dsPtr); |
279 |
return result; |
280 |
} |
281 |
|
282 |
struct logrel_stack { |
283 |
struct logrel_stack *next; |
284 |
unsigned long pos; |
285 |
int first; |
286 |
}; |
287 |
|
288 |
static struct logrel_stack *g_logrel_stack=NULL; |
289 |
|
290 |
static |
291 |
void ClearLogRelStack(void) |
292 |
{ |
293 |
struct logrel_stack *next; |
294 |
while(g_logrel_stack!=NULL){ |
295 |
next =g_logrel_stack->next; |
296 |
ascfree((char *)g_logrel_stack); |
297 |
g_logrel_stack = next; |
298 |
} |
299 |
} |
300 |
|
301 |
static |
302 |
void PushLogRel(unsigned long int pos, int first) |
303 |
{ |
304 |
struct logrel_stack *next; |
305 |
next = g_logrel_stack; |
306 |
g_logrel_stack = (struct logrel_stack *) |
307 |
ascmalloc(sizeof(struct logrel_stack)); |
308 |
g_logrel_stack->next = next; |
309 |
g_logrel_stack->pos = pos; |
310 |
g_logrel_stack->first = first; |
311 |
} |
312 |
|
313 |
static |
314 |
int LogRelNotEmptyStack(void) |
315 |
{ |
316 |
return g_logrel_stack!=NULL; |
317 |
} |
318 |
|
319 |
static |
320 |
int LogrelFirstTop(void) |
321 |
{ |
322 |
assert(g_logrel_stack!=NULL); |
323 |
return g_logrel_stack->first; |
324 |
} |
325 |
|
326 |
static |
327 |
unsigned long PopLogRel(void) |
328 |
{ |
329 |
struct logrel_stack *next; |
330 |
unsigned long result; |
331 |
assert(g_logrel_stack!=NULL); |
332 |
next = g_logrel_stack->next; |
333 |
result = g_logrel_stack->pos; |
334 |
ascfree((char *)g_logrel_stack); |
335 |
g_logrel_stack = next; |
336 |
return result; |
337 |
} |
338 |
|
339 |
static |
340 |
unsigned long LogRelLeftHandSide(CONST struct logrelation *lr, |
341 |
unsigned long int pos, |
342 |
int side) |
343 |
{ |
344 |
unsigned long depth=1; |
345 |
CONST struct logrel_term *term; |
346 |
pos--; |
347 |
while(depth){ |
348 |
term = LogRelTerm(lr,pos,side); |
349 |
switch(LogRelTermType(term)){ |
350 |
case e_int: |
351 |
case e_boolean: |
352 |
case e_satisfied: |
353 |
case e_var: |
354 |
depth--; |
355 |
break; |
356 |
case e_not: |
357 |
break; |
358 |
case e_and: |
359 |
case e_or: |
360 |
depth++; |
361 |
break; |
362 |
default: |
363 |
Asc_Panic(2, NULL, |
364 |
"Don't know this type of logical relation type.\n" |
365 |
"(%d) in function LogRelLeftHandSide\n", |
366 |
LogRelTermType(term)); |
367 |
} |
368 |
pos--; |
369 |
} |
370 |
return pos; |
371 |
} |
372 |
|
373 |
/* a little function to tell us about precedence */ |
374 |
static |
375 |
unsigned LogPriority(enum Expr_enum t) |
376 |
{ |
377 |
switch(t){ |
378 |
case e_var: |
379 |
case e_int: |
380 |
case e_satisfied: |
381 |
return 0; |
382 |
|
383 |
case e_and: |
384 |
return 1; |
385 |
|
386 |
case e_or: |
387 |
return 2; |
388 |
|
389 |
case e_not: |
390 |
return 3; |
391 |
|
392 |
default: |
393 |
return 0; /* 0=good idea? */ |
394 |
} |
395 |
/*NOTREACHED*/ |
396 |
} |
397 |
|
398 |
int LogExprNeedParentheses(enum Expr_enum parent_op, enum Expr_enum child_op, int rhs) |
399 |
{ |
400 |
unsigned parent_p,child_p; |
401 |
switch(child_op){ |
402 |
case e_var: |
403 |
case e_int: |
404 |
case e_boolean: |
405 |
case e_satisfied: |
406 |
return 0; |
407 |
default: |
408 |
parent_p = LogPriority(parent_op); |
409 |
child_p = LogPriority(child_op); |
410 |
if (parent_p > child_p) return 1; |
411 |
if (parent_p < child_p) return 0; |
412 |
if ((parent_op == e_not)&&rhs) return 1; |
413 |
return 0; |
414 |
} |
415 |
} |
416 |
|
417 |
static |
418 |
void WriteLogSide(FILE *f, |
419 |
CONST struct logrelation *lr, |
420 |
int side, |
421 |
CONST struct Instance *ref) |
422 |
{ |
423 |
unsigned long pos,lhs; |
424 |
int first; |
425 |
enum Expr_enum t; |
426 |
CONST struct logrel_term *term; |
427 |
struct Instance *cur_var; |
428 |
struct Instance *rel; |
429 |
int bvalue; |
430 |
ClearLogRelStack(); |
431 |
PushLogRel(LogRelLength(lr,side),1); |
432 |
while(LogRelNotEmptyStack()){ |
433 |
first = LogrelFirstTop(); /* check if this is the first visit */ |
434 |
pos = PopLogRel(); /* check the top */ |
435 |
term = LogRelTerm(lr,pos,side); |
436 |
switch(t = LogRelTermType(term)){ |
437 |
case e_var: |
438 |
cur_var = LogRelBoolVar(lr,LogTermBoolVarNumber(term)); |
439 |
WriteInstanceName(f,cur_var,ref); |
440 |
break; |
441 |
case e_int: |
442 |
FPRINTF(f,"%d",LogTermInteger(term)); |
443 |
break; |
444 |
case e_boolean: |
445 |
bvalue = LogTermBoolean(term); |
446 |
if (bvalue){ |
447 |
FPRINTF(f,"TRUE"); |
448 |
} |
449 |
else { |
450 |
FPRINTF(f,"FALSE"); |
451 |
} |
452 |
break; |
453 |
case e_satisfied: |
454 |
if(first) { |
455 |
FPRINTF(f,"SATISFIED("); |
456 |
rel = LogRelRelation(lr,LogTermSatRelNumber(term)); |
457 |
WriteInstanceName(f,rel,ref); |
458 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
459 |
FPRINTF(f,","); |
460 |
FPRINTF(f,"%g",LogTermSatTolerance(term)); |
461 |
} |
462 |
FPRINTF(f,")"); |
463 |
} |
464 |
else{ |
465 |
PUTC(')',f); |
466 |
} |
467 |
break; |
468 |
case e_and: |
469 |
case e_or: |
470 |
switch(first){ |
471 |
case 1: |
472 |
PushLogRel(pos,2); |
473 |
lhs = LogRelLeftHandSide(lr,pos,side); |
474 |
term = LogRelTerm(lr,lhs,side); |
475 |
if (LogExprNeedParentheses(t,LogRelTermType(term),0)) |
476 |
PUTC('(',f); |
477 |
PushLogRel(lhs,1); |
478 |
break; |
479 |
case 2: |
480 |
term = LogRelTerm(lr,LogRelLeftHandSide(lr,pos,side),side); |
481 |
if (LogExprNeedParentheses(t,LogRelTermType(term),0)) |
482 |
PUTC(')',f); |
483 |
PUTC(' ',f); |
484 |
WriteLogOp(f,t); |
485 |
PUTC(' ',f); |
486 |
PushLogRel(pos,0); |
487 |
term = LogRelTerm(lr,pos-1,side); |
488 |
if (LogExprNeedParentheses(t,LogRelTermType(term),1)) |
489 |
PUTC('(',f); |
490 |
PushLogRel(pos-1,1); |
491 |
break; |
492 |
case 0: |
493 |
term = LogRelTerm(lr,pos-1,side); |
494 |
if (LogExprNeedParentheses(t,LogRelTermType(term),1)) |
495 |
PUTC(')',f); |
496 |
break; |
497 |
} |
498 |
break; |
499 |
case e_not: |
500 |
if (first){ |
501 |
FPRINTF(f,"NOT"); |
502 |
PushLogRel(pos,0); |
503 |
PUTC('(',f); |
504 |
PushLogRel(pos-1,1); |
505 |
} |
506 |
else{ |
507 |
PUTC(')',f); |
508 |
} |
509 |
break; |
510 |
default: |
511 |
Asc_Panic(2, NULL, |
512 |
"Don't know this type of logical relation type.\n" |
513 |
"function WriteLogSide\n");; |
514 |
} |
515 |
} |
516 |
} |
517 |
|
518 |
static |
519 |
void WriteLogSideDS(Asc_DString *dsPtr, CONST struct logrelation *lr, int side, |
520 |
CONST struct Instance *ref) |
521 |
{ |
522 |
unsigned long pos,lhs; |
523 |
int first; |
524 |
enum Expr_enum t; |
525 |
CONST struct logrel_term *term; |
526 |
struct Instance *cur_var; |
527 |
struct Instance *rel; |
528 |
int bvalue; |
529 |
ClearLogRelStack(); |
530 |
PushLogRel(LogRelLength(lr,side),1); |
531 |
while(LogRelNotEmptyStack()){ |
532 |
first = LogrelFirstTop(); /* check if this is the first visit */ |
533 |
pos = PopLogRel(); /* check the top */ |
534 |
term = LogRelTerm(lr,pos,side); |
535 |
switch(t = LogRelTermType(term)){ |
536 |
case e_var: |
537 |
cur_var = LogRelBoolVar(lr,LogTermBoolVarNumber(term)); |
538 |
WriteInstanceNameDS(dsPtr,cur_var,ref); |
539 |
break; |
540 |
case e_int: |
541 |
sprintf(SBL255,"%d",LogTermInteger(term)); |
542 |
Asc_DStringAppend(dsPtr,SBL255,-1); |
543 |
break; |
544 |
case e_boolean: |
545 |
bvalue = LogTermBoolean(term); |
546 |
if (bvalue){ |
547 |
Asc_DStringAppend(dsPtr,"TRUE",4); |
548 |
} |
549 |
else { |
550 |
Asc_DStringAppend(dsPtr,"FALSE",5); |
551 |
} |
552 |
break; |
553 |
case e_satisfied: |
554 |
if(first) { |
555 |
Asc_DStringAppend(dsPtr,"SATISFIED(",10); |
556 |
rel = LogRelRelation(lr,LogTermSatRelNumber(term)); |
557 |
WriteInstanceNameDS(dsPtr,rel,ref); |
558 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
559 |
Asc_DStringAppend(dsPtr,",",1); |
560 |
sprintf(SBL255,"%g",LogTermSatTolerance(term)); |
561 |
Asc_DStringAppend(dsPtr,SBL255,-1); |
562 |
} |
563 |
Asc_DStringAppend(dsPtr,")",1); |
564 |
} |
565 |
else{ |
566 |
Asc_DStringAppend(dsPtr,")",1); |
567 |
} |
568 |
break; |
569 |
case e_and: |
570 |
case e_or: |
571 |
switch(first){ |
572 |
case 1: |
573 |
PushLogRel(pos,2); |
574 |
lhs = LogRelLeftHandSide(lr,pos,side); |
575 |
term = LogRelTerm(lr,lhs,side); |
576 |
if (LogExprNeedParentheses(t,LogRelTermType(term),0)) |
577 |
Asc_DStringAppend(dsPtr,"(",1); |
578 |
PushLogRel(lhs,1); |
579 |
break; |
580 |
case 2: |
581 |
term = LogRelTerm(lr,LogRelLeftHandSide(lr,pos,side),side); |
582 |
if (LogExprNeedParentheses(t,LogRelTermType(term),0)) { |
583 |
Asc_DStringAppend(dsPtr,")",1); |
584 |
} |
585 |
Asc_DStringAppend(dsPtr," ",1); |
586 |
WriteLogOpDS(dsPtr,t); |
587 |
Asc_DStringAppend(dsPtr," ",1); |
588 |
PushLogRel(pos,0); |
589 |
term = LogRelTerm(lr,pos-1,side); |
590 |
if (LogExprNeedParentheses(t,LogRelTermType(term),1)) { |
591 |
Asc_DStringAppend(dsPtr,"(",1); |
592 |
} |
593 |
PushLogRel(pos-1,1); |
594 |
break; |
595 |
case 0: |
596 |
term = LogRelTerm(lr,pos-1,side); |
597 |
if (LogExprNeedParentheses(t,LogRelTermType(term),1)) |
598 |
Asc_DStringAppend(dsPtr,")",1); |
599 |
break; |
600 |
} |
601 |
break; |
602 |
case e_not: |
603 |
if (first){ |
604 |
Asc_DStringAppend(dsPtr,"NOT",3); |
605 |
PushLogRel(pos,0); |
606 |
Asc_DStringAppend(dsPtr,"(",1); |
607 |
PushLogRel(pos-1,1); |
608 |
} |
609 |
else{ |
610 |
Asc_DStringAppend(dsPtr,")",1); |
611 |
} |
612 |
break; |
613 |
default: |
614 |
Asc_Panic(2, NULL, |
615 |
"Don't know this type of logical relation type.\n" |
616 |
"function WriteLogSide\n"); |
617 |
} |
618 |
} |
619 |
} |
620 |
|
621 |
static |
622 |
void WriteLogicalRelation(FILE *f, |
623 |
CONST struct logrelation *lr, |
624 |
CONST struct Instance *ref) |
625 |
{ |
626 |
switch(LogRelRelop(lr)){ |
627 |
case e_boolean_eq: |
628 |
case e_boolean_neq: |
629 |
WriteLogSide(f,lr,1,ref); |
630 |
PUTC(' ',f); |
631 |
WriteLogOp(f,LogRelRelop(lr)); |
632 |
PUTC(' ',f); |
633 |
WriteLogSide(f,lr,0,ref); |
634 |
break; |
635 |
default: |
636 |
FPRINTF(ASCERR,"Unexpected Relop in WriteLogicalRelation\n"); |
637 |
break; |
638 |
} |
639 |
} |
640 |
|
641 |
static |
642 |
void WriteLogRelDS(Asc_DString *dsPtr, |
643 |
CONST struct logrelation *lr, |
644 |
CONST struct Instance *ref) |
645 |
{ |
646 |
switch(LogRelRelop(lr)){ |
647 |
case e_boolean_eq: |
648 |
case e_boolean_neq: |
649 |
WriteLogSideDS(dsPtr,lr,1,ref); |
650 |
Asc_DStringAppend(dsPtr," ",1); |
651 |
WriteLogOpDS(dsPtr,LogRelRelop(lr)); |
652 |
Asc_DStringAppend(dsPtr," ",1); |
653 |
WriteLogSideDS(dsPtr,lr,0,ref); |
654 |
break; |
655 |
default: |
656 |
FPRINTF(ASCERR,"Unexpected Relop in WriteLogRelDS\n"); |
657 |
Asc_DStringAppend(dsPtr,"BADRELOPR ",9); |
658 |
break; |
659 |
} |
660 |
} |
661 |
|
662 |
static |
663 |
void WriteLogSideInfix(FILE *f, |
664 |
CONST struct logrelation *lr, |
665 |
struct logrel_term *term, |
666 |
CONST struct Instance *ref) |
667 |
{ |
668 |
enum Expr_enum t; |
669 |
struct Instance *cur_var; |
670 |
struct Instance *rel; |
671 |
int bvalue; |
672 |
int parens; |
673 |
|
674 |
switch(t = LogRelTermType(term)) { |
675 |
case e_var: |
676 |
cur_var = LogRelBoolVar(lr,LogTermBoolVarNumber(term)); |
677 |
WriteInstanceName(f,cur_var,ref); |
678 |
break; |
679 |
case e_int: |
680 |
FPRINTF(f,"%d",LogTermInteger(term)); |
681 |
break; |
682 |
case e_boolean: |
683 |
bvalue = LogTermBoolean(term); |
684 |
if (bvalue){ |
685 |
FPRINTF(f,"TRUE"); |
686 |
} |
687 |
else { |
688 |
FPRINTF(f,"FALSE"); |
689 |
} |
690 |
break; |
691 |
case e_satisfied: |
692 |
FPRINTF(f,"SATISFIED("); |
693 |
rel = LogRelRelation(lr,LogTermSatRelNumber(term)); |
694 |
WriteInstanceName(f,rel,ref); |
695 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
696 |
FPRINTF(f,","); |
697 |
FPRINTF(f,"%g",LogTermSatTolerance(term)); |
698 |
} |
699 |
FPRINTF(f,")"); |
700 |
break; |
701 |
case e_not: |
702 |
FPRINTF(f,"NOT("); |
703 |
WriteLogSideInfix(f,lr,LogTermUniLeft(term),ref); |
704 |
FPRINTF(f,")"); |
705 |
break; |
706 |
case e_and: |
707 |
case e_or: |
708 |
parens = LogExprNeedParentheses(LogRelTermType(term), |
709 |
LogRelTermType(LogTermBinLeft(term)),0); |
710 |
if (parens) PUTC('(',f); |
711 |
WriteLogSideInfix(f,lr,LogTermBinLeft(term),ref); |
712 |
if (parens) PUTC(')',f); |
713 |
PUTC(' ',f); |
714 |
WriteLogOp(f,t); |
715 |
PUTC(' ',f); |
716 |
parens = LogExprNeedParentheses(LogRelTermType(term), |
717 |
LogRelTermType(LogTermBinRight(term)),1); |
718 |
if (parens) PUTC('(',f); |
719 |
WriteLogSideInfix(f,lr,LogTermBinRight(term),ref); |
720 |
if (parens) PUTC('(',f); |
721 |
break; |
722 |
default: |
723 |
FPRINTF(f,"***"); |
724 |
break; |
725 |
} |
726 |
} |
727 |
|
728 |
void WriteLogRelInfix(FILE *f, |
729 |
CONST struct Instance *lrelinst, |
730 |
CONST struct Instance *ref) |
731 |
{ |
732 |
CONST struct logrelation *lr; |
733 |
|
734 |
lr = GetInstanceLogRel(lrelinst); |
735 |
switch(LogRelRelop(lr)){ |
736 |
case e_boolean_eq: |
737 |
case e_boolean_neq: |
738 |
WriteLogSideInfix(f,lr,Infix_Log_LhsSide(lr),ref); |
739 |
PUTC(' ',f); |
740 |
WriteLogOp(f,LogRelRelop(lr)); |
741 |
PUTC(' ',f); |
742 |
WriteLogSideInfix(f,lr,Infix_Log_RhsSide(lr),ref); |
743 |
break; |
744 |
default: |
745 |
FPRINTF(ASCERR,"Unexpected Relop in WriteLogRelInfix\n"); |
746 |
} |
747 |
} |
748 |
|
749 |
|
750 |
|
751 |
void WriteLogRel(FILE *f, CONST struct Instance *lrelinst, |
752 |
CONST struct Instance *ref) |
753 |
{ |
754 |
CONST struct logrelation *lreln; |
755 |
|
756 |
lreln = GetInstanceLogRel(lrelinst); |
757 |
if (!lreln) { |
758 |
FPRINTF(f,"NULL logical relation\n"); |
759 |
return; |
760 |
} |
761 |
WriteLogicalRelation(f,lreln,ref); |
762 |
return; |
763 |
} |
764 |
|
765 |
char *WriteLogRelToString(CONST struct Instance *lrelinst, |
766 |
CONST struct Instance *ref) |
767 |
{ |
768 |
CONST struct logrelation *lreln; |
769 |
static Asc_DString ds; |
770 |
Asc_DString *dsPtr; |
771 |
char *result; |
772 |
|
773 |
lreln = GetInstanceLogRel(lrelinst); |
774 |
if (!lreln) { |
775 |
result = (char *) ascmalloc(15); |
776 |
if (result == NULL) return result; |
777 |
sprintf(result,"NULL logical relation\n"); |
778 |
return result; |
779 |
} |
780 |
|
781 |
dsPtr = &ds; |
782 |
Asc_DStringInit(dsPtr); |
783 |
WriteLogRelDS(dsPtr,lreln,ref); |
784 |
result = Asc_DStringResult(dsPtr); |
785 |
Asc_DStringFree(dsPtr); |
786 |
return result; |
787 |
} |
788 |
|
789 |
|
790 |
/* |
791 |
* some io to help in debugging logical relation manipulators. |
792 |
*/ |
793 |
static FILE *g_logwritfp = NULL; |
794 |
static void WriteIfLogRel(struct Instance *i) |
795 |
{ |
796 |
struct Instance *p; |
797 |
if (!i) { |
798 |
FPRINTF(ASCERR,"null child pointer in WriteIfLogRel\n"); |
799 |
return; |
800 |
} |
801 |
if (InstanceKind(i)==LREL_INST) { |
802 |
FPRINTF(g_logwritfp,"\n"); |
803 |
WriteInstanceName(g_logwritfp,i,NULL); |
804 |
FPRINTF(g_logwritfp,"\n"); |
805 |
p = InstanceParent(i,1); |
806 |
while (InstanceKind(p)!= MODEL_INST && InstanceKind(p) != SIM_INST) { |
807 |
p = InstanceParent(p,1); |
808 |
} |
809 |
WriteLogRel(g_logwritfp,i,p); |
810 |
FPRINTF(g_logwritfp,"\n"); |
811 |
FPRINTF(g_logwritfp,"\n"); |
812 |
WriteLogRelPostfix(g_logwritfp,i,p); |
813 |
FPRINTF(g_logwritfp,"\n"); |
814 |
} |
815 |
return; |
816 |
} |
817 |
|
818 |
void WriteLogRelationsInTree(FILE *fp,struct Instance *i) |
819 |
{ |
820 |
if (i==NULL || fp==NULL) return; |
821 |
g_logwritfp = fp; |
822 |
SlowVisitInstanceTree(i,WriteIfLogRel,0,0); |
823 |
} |
824 |
|
825 |
|
826 |
/* |
827 |
********************************************************************* |
828 |
* Save Logical Relation Code |
829 |
* |
830 |
* The below code is concerned with saving relations in a persistent |
831 |
* format. It writes out the code in a condensed format to allow |
832 |
* restoration to the original representation. |
833 |
* |
834 |
* The grammar will follow later once it has stabilized. |
835 |
* In the mean time, the following keywords are used. |
836 |
* $LRELOP INTEGER - the relational operator - e_boolean_eq etc. |
837 |
* $LOPCODES INTEGER ':' (INTEGER *) |
838 |
* $LCOUNT INTEGER - the number of variables. |
839 |
* $BVARIABLES ':' (INTEGER)* - global varindex |
840 |
* $BCONSTANTS ':' (BOOLEAN)* |
841 |
********************************************************************* |
842 |
*/ |
843 |
|
844 |
#undef LogLHS |
845 |
#undef LogRHS |
846 |
#define LogLHS 0 |
847 |
#define LogRHS 1 |
848 |
#define LBREAKLINES 65 |
849 |
#define SATID 23 |
850 |
static |
851 |
void SaveLogRelSide(FILE *fp,CONST struct logrelation *lr, |
852 |
int side, struct gl_list_t *constants) |
853 |
{ |
854 |
CONST struct logrel_term *term; |
855 |
struct Instance *rel; |
856 |
enum Expr_enum t; |
857 |
unsigned c,len; |
858 |
int count; |
859 |
|
860 |
len = LogRelLength(lr,side); |
861 |
if (!len) return; |
862 |
|
863 |
count = 16; |
864 |
FPRINTF(fp,"\t$LOPCODES %d : ",side); |
865 |
for (c=1;c<=len;c++) { |
866 |
term = LogRelTerm(lr,c,side); |
867 |
t = LogRelTermType(term); |
868 |
count += FPRINTF(fp," %d ",(int)t); |
869 |
switch (t) { |
870 |
case e_var: |
871 |
count += FPRINTF(fp,"%lu",LogTermBoolVarNumber(term)); |
872 |
break; |
873 |
case e_satisfied: |
874 |
count += FPRINTF(fp,"%d",SATID); |
875 |
rel = LogRelRelation(lr,LogTermSatRelNumber(term)); |
876 |
count += FPRINTF(fp," %lu ",GetTmpNum(rel)); |
877 |
if (LogTermSatTolerance(term) != DBL_MAX) { |
878 |
count += FPRINTF(fp,"%12.8e",LogTermSatTolerance(term)); |
879 |
} |
880 |
break; |
881 |
case e_int: |
882 |
case e_boolean: |
883 |
gl_append_ptr(constants,(VOIDPTR)term); |
884 |
count += FPRINTF(fp,"%lu",gl_length(constants)); |
885 |
break; |
886 |
case e_not: |
887 |
case e_and: |
888 |
case e_or: |
889 |
break; |
890 |
default: |
891 |
count += FPRINTF(fp,"%d",(int)e_nop); |
892 |
break; |
893 |
} |
894 |
if (count >= LBREAKLINES) { |
895 |
PUTC('\n',fp); PUTC('\t',fp); |
896 |
count = 8; |
897 |
} |
898 |
} |
899 |
FPRINTF(fp,";\n"); |
900 |
} |
901 |
|
902 |
|
903 |
static |
904 |
void SaveTokenLogConstants(FILE *fp, struct gl_list_t *constants) |
905 |
{ |
906 |
CONST struct logrel_term *term; |
907 |
unsigned long len,c; |
908 |
|
909 |
len = gl_length(constants); |
910 |
if (!len) return; |
911 |
|
912 |
FPRINTF(fp,"\t$BCONSTANTS : "); |
913 |
for (c=1;c<=len;c++) { |
914 |
term = (CONST struct logrel_term *)gl_fetch(constants,c); |
915 |
switch (LogRelTermType(term)) { |
916 |
case e_boolean: |
917 |
FPRINTF(fp,"%d",LogTermBoolean(term)); |
918 |
break; |
919 |
case e_int: |
920 |
FPRINTF(fp,"%d",LogTermInteger(term)); |
921 |
break; |
922 |
default: |
923 |
Asc_Panic(2, NULL, "Illegal term in SaveTokenLogConstants\n"); |
924 |
} |
925 |
PUTC(' ',fp); |
926 |
} |
927 |
FPRINTF(fp,";\n"); |
928 |
} |
929 |
|
930 |
/* |
931 |
********************************************************************* |
932 |
* Save Logical Relation Boolean Variables |
933 |
********************************************************************* |
934 |
*/ |
935 |
void SaveLogRelBoolVars(FILE *fp, CONST struct logrelation *lr) |
936 |
{ |
937 |
struct Instance *bvar; |
938 |
unsigned long len,c; |
939 |
int count; |
940 |
len = NumberBoolVars(lr); |
941 |
if (!len) return; |
942 |
|
943 |
count = 16; |
944 |
FPRINTF(fp,"\t$BVARIABLES : "); |
945 |
for (c=1;c<=len;c++) { |
946 |
bvar = LogRelBoolVar(lr,c); |
947 |
count += FPRINTF(fp," %lu ",GetTmpNum(bvar)); |
948 |
if (count >= LBREAKLINES) { |
949 |
PUTC('\n',fp); PUTC('\t',fp); |
950 |
count = 8; |
951 |
} |
952 |
} |
953 |
FPRINTF(fp,";\n"); |
954 |
} |
955 |
|
956 |
/* |
957 |
********************************************************************* |
958 |
* SaveLogRel |
959 |
* Save a logical relation in condensed opcode format. |
960 |
********************************************************************* |
961 |
*/ |
962 |
void SaveLogRel(FILE *fp, CONST struct Instance *lrelinst) |
963 |
{ |
964 |
CONST struct logrelation *lreln; |
965 |
struct gl_list_t *constants = NULL; |
966 |
|
967 |
lreln = GetInstanceLogRel(lrelinst); |
968 |
constants = gl_create(50L); |
969 |
|
970 |
FPRINTF(fp,"$LOGRELATION %lu {\n",GetTmpNum(lrelinst)); |
971 |
FPRINTF(fp,"\t$COUNT %lu;\n",NumberBoolVars(lreln)); |
972 |
|
973 |
SaveLogRelSide(fp,lreln,LogLHS,constants); |
974 |
SaveLogRelSide(fp,lreln,LogRHS,constants); |
975 |
SaveTokenLogConstants(fp,constants); |
976 |
SaveLogRelBoolVars(fp,lreln); |
977 |
FPRINTF(fp,"}\n\n"); |
978 |
|
979 |
gl_destroy(constants); |
980 |
} |
981 |
|
982 |
|