#include #include #include #include #include "util.h" #define SPECIALFORMSNUM 2 int isSpecialForm(char *symbol) { int result = 0; char *specialForms[] = { "навод", "дефиниши" }; for (int i = 0; i < SPECIALFORMSNUM; ++i) { if (!strcmp(symbol, specialForms[i])) { result = 1; } } return result; } int properList(object list) { object *current = &list; while (TYPE(*current) == consObject) { current = &CDR(*current); } return TYPE(*current) == nilObject; } int listLength(object list) { object *current = &list; int i = 0; while (TYPE(*current) != nilObject) { current = &CDR(*current); ++i; } return i; } void deleteObject(object input) { if ((TYPE(input) == symbolObject) && SYM(input) != NULL) { free(SYM(input)); SYM(input) = NULL; } else if (TYPE(input) == consObject) { deleteObject(CAR(input)); deleteObject(CDR(input)); free(CONS(input)); CONS(input) = NULL; } TYPE(input) = nilObject; } object copyObject(object input) { object result; TYPE(result) = TYPE(input); if (TYPE(input) == errorObject) { ERR(result) = ERR(input); } else if (TYPE(input) == numberObject) { NUM(result) = NUM(input); } else if (TYPE(input) == symbolObject) { SYM(result) = malloc(sizeof(char) * (strlen(SYM(input)) + 1)); strcpy(SYM(result), SYM(input)); } else if (TYPE(input) == consObject) { CONS(result) = malloc(sizeof(cons)); CAR(result) = copyObject(CAR(input)); CDR(result) = copyObject(CDR(input)); } return result; } object longlongToNumber(long long int input) { object result; TYPE(result) = numberObject; NUM_TYPE(result) = fractionNum; NUM_NUMER(result) = input; NUM_DENOM(result) = 1LL; return result; } object exactToInexactNum(object a) { object result = copyObject(a); if (TYPE(result) == numberObject && NUM_TYPE(result) == fractionNum) { NUM_TYPE(result) = realNum; NUM_REAL(result) = (long double) NUM_NUMER(result) / (long double) NUM_DENOM(result); } return result; } object inexactToExactNum(object a) { object result = copyObject(a); if (TYPE(result) == numberObject && NUM_TYPE(result) == realNum) { long long int divisor = 1; while (NUM_REAL(result) != floorl(NUM_REAL(result)) && divisor <= INT_MAX) { NUM_REAL(result) *= 10.0L; divisor *= 10LL; } NUM_TYPE(result) = fractionNum; NUM_NUMER(result) = (long long int) floorl(NUM_REAL(result)); NUM_DENOM(result) = divisor; result = shortenFractionNum(result); } return result; } long long int gcd(long long int a, long long int b) /* највећи заједнички делилац */ { if (b == 0LL) { return a; } else { return gcd(b, a - b * (a / b)); } } long long int lcm(long long int a, long long int b) /* најмањи заједнички садржалац */ { if (a == 0LL && b == 0LL) { return 0L; } else { return llabs(a * b) / gcd(a, b); } } object shortenFractionNum(object a) /* скраћује разломак, враћа грешку ако је неправилан разломак, уколико улаз * заиста јесте дат као разломак */ { object result = copyObject(a); if (TYPE(result) == numberObject && NUM_TYPE(result) == fractionNum) { if (NUM_DENOM(result) == 0) { deleteObject(result); TYPE(result) = errorObject; ERR(result) = divisionByZeroError; } else if (NUM_NUMER(result) == 0) { NUM_DENOM(result) = 1; } else { long long int divisor = gcd(NUM_NUMER(result), NUM_DENOM(result)); NUM_NUMER(result) /= divisor; NUM_DENOM(result) /= divisor; } } return result; } object plusNum(object a, object b) { object result; TYPE(result) = numberObject; if (NUM_TYPE(a) == fractionNum && NUM_TYPE(b) == fractionNum) { NUM_TYPE(result) = fractionNum; NUM_NUMER(result) = NUM_NUMER(a) * NUM_DENOM(b) + NUM_NUMER(b) * NUM_DENOM(a); NUM_DENOM(result) = NUM_DENOM(a) * NUM_DENOM(b); /* * TODO: имплементирати оптималнији начин множења разломака long long int denominator = lcm(NUM_DENOM(a), NUM_DENOM(b)); NUM_NUMER(result) = NUM_NUMER(a) * (denominator / NUM_DENOM(a)) + NUM_NUMER(b) * (denominator / NUM_DENOM(b)); */ result = shortenFractionNum(result); } else { NUM_TYPE(result) = realNum; NUM_REAL(result) = NUM_REAL(exactToInexactNum(a)) + NUM_REAL(exactToInexactNum(b)); } return result; } object minusNum(object a) { object result; result = copyObject(a); if (NUM_TYPE(result) == fractionNum) { NUM_NUMER(result) = -NUM_NUMER(result); } else if (NUM_TYPE(result) == realNum) { NUM_REAL(result) = -NUM_REAL(result); } return result; } object timesNum(object a, object b) { object result; TYPE(result) = numberObject; if (NUM_TYPE(a) == fractionNum && NUM_TYPE(b) == fractionNum) { NUM_TYPE(result) = fractionNum; NUM_NUMER(result) = NUM_NUMER(a) * NUM_NUMER(b); NUM_DENOM(result) = NUM_DENOM(a) * NUM_DENOM(b); result = shortenFractionNum(result); } else { NUM_TYPE(result) = realNum; NUM_REAL(result) = NUM_REAL(exactToInexactNum(a)) * NUM_REAL(exactToInexactNum(b)); } return result; } object inverseNum(object a) { object result; result = copyObject(a); if (NUM_TYPE(result) == fractionNum) { if (NUM_NUMER(result) == 0) { deleteObject(result); TYPE(result) = errorObject; ERR(result) = divisionByZeroError; } else { NUM_NUMER(result) = NUM_DENOM(a); NUM_DENOM(result) = NUM_NUMER(a); } } else if (NUM_TYPE(result) == realNum) { NUM_REAL(result) = 1.0L/NUM_REAL(result); } return result; }