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

#include "eval.h"
infint_t *evaluate(expr_t *e) {
infint_t *iil, *iir;
iil = NULL;
if (e->flags & EXFLAG_REXP) {
iir = evaluate(e->right.expr);
} else {
iir = infint_new(2);
iir->data[0] = e->right.data;
}
iir->sign ^= !!(e->flags & EXFLAG_RNEG);
if (e->flags & EXFLAG_LEXP) {
iil = evaluate(e->left.expr);
iil->sign ^= !!(e->flags & EXFLAG_LNEG);
}
switch(e->opcode) {
case EXPR_ADD:
if (e->flags & EXFLAG_MOD) { // Concatination
infint_shift_right(iir, 1);
iir->data[0] = e->left.data;
} else { // Addition and Subtraction
if (iil) {
infint_add2(iir, iil);
} else if (e->flags & EXFLAG_LNEG) {
infint_sub(iir, e->left.data);
} else {
infint_add(iir, e->left.data);
}
}
break;
case EXPR_MULT:
if (e->flags & EXFLAG_MOD) { // Division
// Not fully supported yet. No-op for now.
} else {
if (iil) {
infint_mult2(iir, iil);
} else {
infint_mult(iir, e->left.data);
iir->sign ^= !!(e->flags & EXFLAG_LNEG);
}
}
break;
case EXPR_IPOW:
if (!iil) {
iil = infint_new(2);
iil->data[0] = e->left.data;
}
if (iir->size == 1 && iir->data[0] == 0) {
memset(iil->data + 1, 0, iil->size - 1);
iil->data[0]= 1;
iil->size = 1;
} else if (iir->sign) {
memset(iil->data, 0, iil->size);
iil->size = 1;
} else if (iil->size == 1 && (iil->data[0] < 2)) {
iil->sign ^= iir->data[0] & 1;
} else if (!infint_abs_less_than(iir, 2)) {
iil->sign ^= iir->data[0] & 1;
infint_t *acci = infint_new(1);
acci->data[0] = 1;
while (iir->size > 1 || iir->data[0] > 0) {
if (infint_div(iir, 2)) infint_mult2(acci, iil);
infint_mult2(iil, iil);
}
free(iir->data);
iir->data = acci->data;
iir->size = acci->size;
iir->capacity = acci->capacity;
free(acci);
}
}
if (iil) infint_free(iil);
return iir;
}
#ifdef UNIT_TESTS
void test_evaluate() {
expr_t *e;
infint_t *ii;
input_str = "-12321\0";
e = parse(0);
ii = evaluate(e);
assert(ii->size == 3);
assert(ii->sign == 1);
assert(ii->data[0] == 21);
assert(ii->data[1] == 23);
assert(ii->data[2] == 1);
infint_free(ii);
destroy_expr(e);
input_str = "4*5+2*-3-1*6\0";
e = parse(0);
ii = evaluate(e);
assert(ii->size == 1);
assert(ii->sign == 0);
assert(ii->data[0] == 8);
infint_free(ii);
destroy_expr(e);
input_str = "1000000-200*400\0";
e = parse(0);
ii = evaluate(e);
assert(ii->size == 3);
assert(ii->sign == 0);
assert(ii->data[0] == 0);
assert(ii->data[1] == 0);
assert(ii->data[2] == 92);
infint_free(ii);
destroy_expr(e);
input_str = "2^8\0";
e = parse(0);
ii = evaluate(e);
assert(ii->size == 2);
assert(ii->sign == 0);
assert(ii->data[0] == 56);
assert(ii->data[1] == 2);
infint_free(ii);
destroy_expr(e);
char *output_str;
input_str = "2^128\0";
e = parse(0);
ii = evaluate(e);
assert(ii->sign == 0);
output_str = infint_to_string(ii);
assert(strcmp(output_str, "340282366920938463463374607431768211456") == 0);
free(output_str);
infint_free(ii);
destroy_expr(e);
}
#endif