#include #include #include #include "util.h" object apply(object function, object parameters); object eval(object input) { object result; if (TYPE(input) == nilObject || TYPE(input) == numberObject || TYPE(input) == errorObject) result = input; else if (TYPE(input) == symbolObject) { if (!strcmp(SYM(input), "+") || !strcmp(SYM(input), "-") || !strcmp(SYM(input), "*") || !strcmp(SYM(input), "/")) { result = input; } else { deleteObject(input); TYPE(result) = errorObject; ERR(result) = unrecognizedSymbolError; } } else if (TYPE(input) == consObject) { if (!properList(input)) { deleteObject(input); TYPE(result) = errorObject; ERR(result) = improperListError; } object *currentCell = &input; int noErrors = 1; while (TYPE(*currentCell) != nilObject) { CAR(*currentCell) = eval(CAR(*currentCell)); if (TYPE(CAR(*currentCell)) == errorObject) { noErrors = 0; TYPE(result) = errorObject; ERR(result) = ERR(CAR(*currentCell)); break; } currentCell = &CDR(*currentCell); } if (noErrors) { result = apply(CAR(input), CDR(input)); } deleteObject(input); } return result; } object add(object parameters); object subtract(object parameters); object multiply(object parameters); object divide(object parameters); object apply(object function, object parameters) { object result; if (TYPE(function) != symbolObject) { deleteObject(function); TYPE(result) = errorObject; ERR(result) = notApplicableError; } /* TODO Ово налажење ће се касније извршавати кроз табелу симбола */ else if (!strcmp(SYM(function), "+")) { result = add(parameters); } else if (!strcmp(SYM(function), "-")) { result = subtract(parameters); } else if (!strcmp(SYM(function), "*")) { result = multiply(parameters); } else if (!strcmp(SYM(function), "/")) { result = divide(parameters); } else { deleteObject(function); TYPE(result) = errorObject; ERR(result) = improperListError; } return result; } int allNumbers(object list) { object *currentCell = &list; while (TYPE(*currentCell) != nilObject) { if (TYPE(CAR(*currentCell)) != numberObject) { return 0; } currentCell = &CDR(*currentCell); } return 1; } object add(object parameters) { object result; TYPE(result) = numberObject; if (!allNumbers(parameters)) { TYPE(result) = errorObject; ERR(result) = typeError; } else if (listLength(parameters) == 0) { NUM(result) = 0LL; } else { object first, rest; first = CAR(parameters); rest = add(CDR(parameters)); NUM(result) = NUM(first) + NUM(rest); } return result; } object subtract(object parameters) { object result; TYPE(result) = numberObject; if (!allNumbers(parameters)) { TYPE(result) = errorObject; ERR(result) = typeError; } else if (listLength(parameters) == 0) { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } else if (listLength(parameters) == 1) { NUM(result) = -NUM(CAR(parameters)); } else { NUM(result) = NUM(CAR(parameters)) - NUM(add(CDR(parameters))); } return result; } object multiply(object parameters) { object result; TYPE(result) = numberObject; if (!allNumbers(parameters)) { TYPE(result) = errorObject; ERR(result) = typeError; } else if (listLength(parameters) == 0) { NUM(result) = 1LL; } else { object first, rest; first = CAR(parameters); rest = multiply(CDR(parameters)); NUM(result) = NUM(first) * NUM(rest); } return result; } object divide(object parameters) { object result; TYPE(result) = numberObject; if (!allNumbers(parameters)) { TYPE(result) = errorObject; ERR(result) = typeError; } else if (listLength(parameters) == 0) { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } else if (listLength(parameters) == 1) { if (NUM(CAR(parameters)) != 0) { NUM(result) = 1/NUM(CAR(parameters)); } else { TYPE(result) = errorObject; ERR(result) = divisionByZeroError; } } else { if (NUM(add(CDR(parameters))) != 0) { NUM(result) = NUM(CAR(parameters))/NUM(add(CDR(parameters))); } else { TYPE(result) = errorObject; ERR(result) = divisionByZeroError; } } return result; }