Mercurial > hg-old > index.cgi
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 |