Infinity Calculator implementation for Assignment 2 in Computer Organization.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.0 KiB

2 years ago
2 years ago
  1. #include "eval.h"
  2. infint_t *evaluate(expr_t *e) {
  3. infint_t *iil, *iir;
  4. iil = NULL;
  5. if (e->flags & EXFLAG_REXP) {
  6. iir = evaluate(e->right.expr);
  7. } else {
  8. iir = infint_new(2);
  9. iir->data[0] = e->right.data;
  10. }
  11. iir->sign ^= !!(e->flags & EXFLAG_RNEG);
  12. if (e->flags & EXFLAG_LEXP) {
  13. iil = evaluate(e->left.expr);
  14. iil->sign ^= !!(e->flags & EXFLAG_LNEG);
  15. }
  16. switch(e->opcode) {
  17. case EXPR_ADD:
  18. if (e->flags & EXFLAG_MOD) { // Concatination
  19. infint_shift_right(iir, 1);
  20. iir->data[0] = e->left.data;
  21. } else { // Addition and Subtraction
  22. if (iil) {
  23. infint_add2(iir, iil);
  24. } else if (e->flags & EXFLAG_LNEG) {
  25. infint_sub(iir, e->left.data);
  26. } else {
  27. infint_add(iir, e->left.data);
  28. }
  29. }
  30. break;
  31. case EXPR_MULT:
  32. if (e->flags & EXFLAG_MOD) { // Division
  33. // Not fully supported yet. No-op for now.
  34. } else {
  35. if (iil) {
  36. infint_mult2(iir, iil);
  37. } else {
  38. infint_mult(iir, e->left.data);
  39. iir->sign ^= !!(e->flags & EXFLAG_LNEG);
  40. }
  41. }
  42. break;
  43. case EXPR_IPOW:
  44. if (!iil) {
  45. iil = infint_new(2);
  46. iil->data[0] = e->left.data;
  47. }
  48. if (iir->size == 1 && iir->data[0] == 0) {
  49. memset(iil->data + 1, 0, iil->size - 1);
  50. iil->data[0]= 1;
  51. iil->size = 1;
  52. } else if (iir->sign) {
  53. memset(iil->data, 0, iil->size);
  54. iil->size = 1;
  55. } else if (iil->size == 1 && (iil->data[0] < 2)) {
  56. iil->sign ^= iir->data[0] & 1;
  57. } else if (!infint_abs_less_than(iir, 2)) {
  58. iil->sign ^= iir->data[0] & 1;
  59. infint_t *acci = infint_new(1);
  60. acci->data[0] = 1;
  61. while (iir->size > 1 || iir->data[0] > 0) {
  62. if (infint_div(iir, 2)) infint_mult2(acci, iil);
  63. infint_mult2(iil, iil);
  64. }
  65. free(iir->data);
  66. iir->data = acci->data;
  67. iir->size = acci->size;
  68. iir->capacity = acci->capacity;
  69. free(acci);
  70. }
  71. }
  72. if (iil) infint_free(iil);
  73. return iir;
  74. }
  75. #ifdef UNIT_TESTS
  76. void test_evaluate() {
  77. expr_t *e;
  78. infint_t *ii;
  79. input_str = "-12321\0";
  80. e = parse(0);
  81. ii = evaluate(e);
  82. assert(ii->size == 3);
  83. assert(ii->sign == 1);
  84. assert(ii->data[0] == 21);
  85. assert(ii->data[1] == 23);
  86. assert(ii->data[2] == 1);
  87. infint_free(ii);
  88. destroy_expr(e);
  89. input_str = "4*5+2*-3-1*6\0";
  90. e = parse(0);
  91. ii = evaluate(e);
  92. assert(ii->size == 1);
  93. assert(ii->sign == 0);
  94. assert(ii->data[0] == 8);
  95. infint_free(ii);
  96. destroy_expr(e);
  97. input_str = "1000000-200*400\0";
  98. e = parse(0);
  99. ii = evaluate(e);
  100. assert(ii->size == 3);
  101. assert(ii->sign == 0);
  102. assert(ii->data[0] == 0);
  103. assert(ii->data[1] == 0);
  104. assert(ii->data[2] == 92);
  105. infint_free(ii);
  106. destroy_expr(e);
  107. input_str = "2^8\0";
  108. e = parse(0);
  109. ii = evaluate(e);
  110. assert(ii->size == 2);
  111. assert(ii->sign == 0);
  112. assert(ii->data[0] == 56);
  113. assert(ii->data[1] == 2);
  114. infint_free(ii);
  115. destroy_expr(e);
  116. char *output_str;
  117. input_str = "2^128\0";
  118. e = parse(0);
  119. ii = evaluate(e);
  120. assert(ii->sign == 0);
  121. output_str = infint_to_string(ii);
  122. assert(strcmp(output_str, "340282366920938463463374607431768211456") == 0);
  123. free(output_str);
  124. infint_free(ii);
  125. destroy_expr(e);
  126. }
  127. #endif