comparison lwlib/lw_expr.c @ 371:9c24d9d485b9

Much bugfixing
author lost@starbug
date Wed, 21 Apr 2010 23:29:18 -0600
parents 6b33faa21a0a
children 90de73ba0cac
comparison
equal deleted inserted replaced
370:6b33faa21a0a 371:9c24d9d485b9
169 te2 = NULL; 169 te2 = NULL;
170 170
171 r -> type = lw_expr_type_oper; 171 r -> type = lw_expr_type_oper;
172 r -> value = t; 172 r -> value = t;
173 lw_expr_add_operand(r, te1); 173 lw_expr_add_operand(r, te1);
174 lw_expr_add_operand(r, te2); 174 if (te2)
175 lw_expr_add_operand(r, te2);
175 break; 176 break;
176 177
177 default: 178 default:
178 lw_error("Invalid expression type specified to lw_expr_build"); 179 lw_error("Invalid expression type specified to lw_expr_build");
179 } 180 }
204 } 205 }
205 206
206 switch (E -> type) 207 switch (E -> type)
207 { 208 {
208 case lw_expr_type_int: 209 case lw_expr_type_int:
209 fprintf(fp, "%d ", E -> value); 210 if (E -> value < 0)
211 fprintf(fp, "-%#x ", -(E -> value));
212 else
213 fprintf(fp, "%#x ", E -> value);
210 break; 214 break;
211 215
212 case lw_expr_type_var: 216 case lw_expr_type_var:
213 fprintf(fp, "V(%s) ", (char *)(E -> value2)); 217 fprintf(fp, "V(%s) ", (char *)(E -> value2));
214 break; 218 break;
335 339
336 340
337 void lw_expr_simplify_sortconstfirst(lw_expr_t E) 341 void lw_expr_simplify_sortconstfirst(lw_expr_t E)
338 { 342 {
339 struct lw_expr_opers *o; 343 struct lw_expr_opers *o;
340 344
345 if (E -> type != lw_expr_type_oper)
346 return;
347 if (E -> value != lw_expr_oper_times && E -> value != lw_expr_oper_plus)
348 return;
349
341 for (o = E -> operands; o; o = o -> next) 350 for (o = E -> operands; o; o = o -> next)
342 lw_expr_simplify_sortconstfirst(o -> p); 351 {
352 if (o -> p -> type == lw_expr_type_oper && (o -> p -> value == lw_expr_oper_times || o -> p -> value == lw_expr_oper_plus))
353 lw_expr_simplify_sortconstfirst(o -> p);
354 }
343 355
344 for (o = E -> operands; o; o = o -> next) 356 for (o = E -> operands; o; o = o -> next)
345 { 357 {
346 if (o -> p -> type == lw_expr_type_int && o != E -> operands) 358 if (o -> p -> type == lw_expr_type_int && o != E -> operands)
347 { 359 {
378 if (o1 || o2) 390 if (o1 || o2)
379 return 0; 391 return 0;
380 return 1; 392 return 1;
381 } 393 }
382 394
395 int lw_expr_simplify_isliketerm(lw_expr_t e1, lw_expr_t e2)
396 {
397 fprintf(stderr, "isliketerm in: ");
398 lw_expr_print(e1, stderr);
399 fprintf(stderr, "; ");
400 lw_expr_print(e2, stderr);
401 fprintf(stderr, "\n");
402
403 // first term is a "times"
404 if (e1 -> type == lw_expr_type_oper && e1 -> value == lw_expr_oper_times)
405 {
406 // second term is a "times"
407 if (e2 -> type == lw_expr_type_oper && e2 -> value == lw_expr_oper_times)
408 {
409 // both times - easy check
410 struct lw_expr_opers *o1, *o2;
411 for (o1 = e1 -> operands; o1; o1 = o1 -> next)
412 if (o1 -> p -> type != lw_expr_type_int)
413 break;
414
415 for (o2 = e2 -> operands; o2; o2 = o2 -> next)
416 if (o2 -> p -> type != lw_expr_type_int)
417 break;
418
419 if (lw_expr_simplify_compareoperandlist(&o1, &o2))
420 return 1;
421 return 0;
422 }
423
424 // not a times - have to assume it's the operand list
425 // with a "1 *" in front if it
426 if (e1 -> operands -> next -> next)
427 return 0;
428 if (!lw_expr_compare(e1 -> operands -> next -> p, e2))
429 return 0;
430 return 1;
431 }
432
433 // e1 is not a times
434 if (e2 -> type == lw_expr_type_oper && e2 -> value == lw_expr_oper_times)
435 {
436 // e2 is a times
437 if (e2 -> operands -> next -> next)
438 return 0;
439 if (!lw_expr_compare(e1, e2 -> operands -> next -> p))
440 return 0;
441 return 1;
442 }
443
444 // neither are times
445 if (!lw_expr_compare(e1, e2))
446 return 0;
447 return 1;
448 }
449
383 void lw_expr_simplify(lw_expr_t E, void *priv) 450 void lw_expr_simplify(lw_expr_t E, void *priv)
384 { 451 {
385 struct lw_expr_opers *o; 452 struct lw_expr_opers *o;
386 453
454 // replace subtraction with O1 + -1(O2)...
455 // needed for like term collection
456 if (E -> type == lw_expr_type_oper && E -> value == lw_expr_oper_minus)
457 {
458 for (o = E -> operands -> next; o; o = o -> next)
459 {
460 lw_expr_t e1, e2;
461
462 e2 = lw_expr_build(lw_expr_type_int, -1);
463 e1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, e2, o -> p);
464 lw_expr_destroy(o -> p);
465 lw_expr_destroy(e2);
466 o -> p = e1;
467 }
468 E -> value = lw_expr_oper_plus;
469 }
470
471 // turn "NEG" into -1(O) - needed for like term collection
472 if (E -> type == lw_expr_type_oper && E -> value == lw_expr_oper_neg)
473 {
474 lw_expr_t e1;
475
476 E -> value = lw_expr_oper_times;
477 e1 = lw_expr_build(lw_expr_type_int, -1);
478 lw_expr_add_operand(E, e1);
479 lw_expr_destroy(e1);
480 }
481
387 again: 482 again:
388 // try to resolve non-constant terms to constants here 483 // try to resolve non-constant terms to constants here
389 if (E -> type == lw_expr_type_special && evaluate_special) 484 if (E -> type == lw_expr_type_special && evaluate_special)
390 { 485 {
391 lw_expr_t te; 486 lw_expr_t te;
440 535
441 // non-operators have no simplification to do! 536 // non-operators have no simplification to do!
442 if (E -> type != lw_expr_type_oper) 537 if (E -> type != lw_expr_type_oper)
443 return; 538 return;
444 539
445 // sort "constants" to the start of each operand list for + and * 540 // merge plus operations
446 lw_expr_simplify_sortconstfirst(E); 541 if (E -> value == lw_expr_oper_plus)
542 {
543 lw_expr_t e2;
544
545 tryagainplus:
546 for (o = E -> operands; o; o = o -> next)
547 {
548 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_plus)
549 {
550 struct lw_expr_opers *o2, *o3;
551 // we have a + operation - bring operands up
552
553 for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next)
554 /* do nothing */ ;
555 if (o2)
556 o2 -> next = o -> p -> operands;
557 else
558 E -> operands = o -> p -> operands;
559 for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next)
560 /* do nothing */ ;
561 o2 -> next = o -> next;
562 o -> p -> operands = NULL;
563 lw_expr_destroy(o -> p);
564 lw_free(o);
565 goto tryagainplus;
566 }
567 }
568 }
569
570 // merge times operations
571 if (E -> value == lw_expr_oper_times)
572 {
573 lw_expr_t e2;
574
575 tryagaintimes:
576 for (o = E -> operands; o; o = o -> next)
577 {
578 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times)
579 {
580 struct lw_expr_opers *o2, *o3;
581 // we have a + operation - bring operands up
582
583 for (o2 = E -> operands; o2 && o2 -> next != o; o2 = o2 -> next)
584 /* do nothing */ ;
585 if (o2)
586 o2 -> next = o -> p -> operands;
587 else
588 E -> operands = o -> p -> operands;
589 for (o2 = o -> p -> operands; o2 -> next; o2 = o2 -> next)
590 /* do nothing */ ;
591 o2 -> next = o -> next;
592 o -> p -> operands = NULL;
593 lw_expr_destroy(o -> p);
594 lw_free(o);
595 goto tryagaintimes;
596 }
597 }
598 }
447 599
448 // simplify operands 600 // simplify operands
449 for (o = E -> operands; o; o = o -> next) 601 for (o = E -> operands; o; o = o -> next)
450 lw_expr_simplify(o -> p, priv); 602 lw_expr_simplify(o -> p, priv);
451 603
530 lw_free(o); 682 lw_free(o);
531 } 683 }
532 E -> type = lw_expr_type_int; 684 E -> type = lw_expr_type_int;
533 E -> value = tr; 685 E -> value = tr;
534 return; 686 return;
687 }
688
689 if (E -> value == lw_expr_oper_plus)
690 {
691 lw_expr_t e1;
692 int cval = 0;
693
694 e1 = lw_expr_create();
695 e1 -> operands = E -> operands;
696 E -> operands = 0;
697
698 for (o = e1 -> operands; o; o = o -> next)
699 {
700 if (o -> p -> type == lw_expr_type_int)
701 cval += o -> p -> value;
702 else
703 lw_expr_add_operand(E, o -> p);
704 }
705 lw_expr_destroy(e1);
706 if (cval)
707 {
708 e1 = lw_expr_build(lw_expr_type_int, cval);
709 lw_expr_add_operand(E, e1);
710 lw_expr_destroy(e1);
711 }
712 }
713
714 if (E -> value == lw_expr_oper_times)
715 {
716 lw_expr_t e1;
717 int cval = 1;
718
719 e1 = lw_expr_create();
720 e1 -> operands = E -> operands;
721 E -> operands = 0;
722
723 for (o = e1 -> operands; o; o = o -> next)
724 {
725 if (o -> p -> type == lw_expr_type_int)
726 cval *= o -> p -> value;
727 else
728 lw_expr_add_operand(E, o -> p);
729 }
730 lw_expr_destroy(e1);
731 if (cval != 1)
732 {
733 e1 = lw_expr_build(lw_expr_type_int, cval);
734 lw_expr_add_operand(E, e1);
735 lw_expr_destroy(e1);
736 }
535 } 737 }
536 738
537 if (E -> value == lw_expr_oper_times) 739 if (E -> value == lw_expr_oper_times)
538 { 740 {
539 for (o = E -> operands; o; o = o -> next) 741 for (o = E -> operands; o; o = o -> next)
553 return; 755 return;
554 } 756 }
555 } 757 }
556 } 758 }
557 759
760 // sort "constants" to the start of each operand list for + and *
761 if (E -> value == lw_expr_oper_plus || E -> value == lw_expr_oper_times)
762 lw_expr_simplify_sortconstfirst(E);
763
558 // look for like terms and collect them together 764 // look for like terms and collect them together
559 if (E -> value == lw_expr_oper_plus) 765 if (E -> value == lw_expr_oper_plus)
560 { 766 {
767 struct lw_expr_opers *o2;
561 for (o = E -> operands; o; o = o -> next) 768 for (o = E -> operands; o; o = o -> next)
562 { 769 {
563 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times) 770 // skip constants
771 if (o -> p -> type == lw_expr_type_int)
772 continue;
773
774 // we have a term to match
775 // (o -> p) is first term
776 for (o2 = o -> next; o2; o2 = o2 -> next)
564 { 777 {
565 // we have a "times" here 778 lw_expr_t e1, e2;
566 // find first non-const operand
567 struct lw_expr_opers *op1, *op2, *o2;
568 for (op1 = o -> p -> operands; op1; op1 = op1 -> next)
569 if (op1 -> p -> type != lw_expr_type_int)
570 break;
571 779
572 for (o2 = o -> next; o2; o2 = o2 -> next) 780 if (o2 -> p -> type == lw_expr_type_int)
781 continue;
782
783 if (lw_expr_simplify_isliketerm(o -> p, o2 -> p))
573 { 784 {
785 int coef, coef2;
786
787 // we have a like term here
788 // do something about it
789 if (o -> p -> type == lw_expr_type_oper && o -> p -> value == lw_expr_oper_times)
790 {
791 if (o -> p -> operands -> p -> type == lw_expr_type_int)
792 coef = o -> p -> operands -> p -> value;
793 else
794 coef = 1;
795 }
796 else
797 coef = 1;
574 if (o2 -> p -> type == lw_expr_type_oper && o2 -> p -> value == lw_expr_oper_times) 798 if (o2 -> p -> type == lw_expr_type_oper && o2 -> p -> value == lw_expr_oper_times)
575 { 799 {
576 // another "times" 800 if (o2 -> p -> operands -> p -> type == lw_expr_type_int)
577 for (op2 = o2 -> p -> operands; op2; op2 = op2 -> next) 801 coef2 = o2 -> p -> operands -> p -> value;
578 if (op2 -> p -> type != lw_expr_type_int) 802 else
579 break; 803 coef2 = 1;
580
581 if (lw_expr_simplify_compareoperandlist(&op1, &op2))
582 {
583 // we have like terms here
584 // do something about it
585 }
586 } 804 }
805 else
806 coef2 = 1;
807 coef += coef2;
808 e1 = lw_expr_create();
809 e1 -> type = lw_expr_type_oper;
810 e1 -> value = lw_expr_oper_times;
811 if (coef != 1)
812 {
813 e2 = lw_expr_build(lw_expr_type_int, coef);
814 lw_expr_add_operand(e1, e2);
815 lw_expr_destroy(e2);
816 }
817 lw_expr_destroy(o -> p);
818 o -> p = e1;
819 for (o = o2 -> p -> operands; o; o = o -> next)
820 {
821 if (o -> p -> type == lw_expr_type_int)
822 continue;
823 lw_expr_add_operand(e1, o -> p);
824 }
825 lw_expr_destroy(o2 -> p);
826 o2 -> p = lw_expr_build(lw_expr_type_int, 0);
827 goto again;
587 } 828 }
588 } 829 }
589 } 830 }
590 } 831 }
591 832