#include "symtable.h" #include "util.h" #include "eval.h" int allNums(object list) { object *currentCell = &list; while (TYPE(*currentCell) != nilObject) { if (TYPE(CAR(*currentCell)) != numberObject) { return 0; } currentCell = &CDR(*currentCell); } return 1; } int allSyms(object list) { object *currentCell = &list; while (TYPE(*currentCell) != nilObject) { if (TYPE(CAR(*currentCell)) != symbolObject) { return 0; } currentCell = &CDR(*currentCell); } return 1; } object add(object parameters) { object result; TYPE(result) = numberObject; if (!allNums(parameters)) { TYPE(result) = errorObject; ERR(result) = typeError; } else if (listLength(parameters) == 0) { result = longlongToNumber(0LL); } else { object first, rest; first = CAR(parameters); rest = add(CDR(parameters)); result = plusNum(first, rest); } return result; } object subtract(object parameters) { object result; TYPE(result) = numberObject; if (!allNums(parameters)) { TYPE(result) = errorObject; ERR(result) = typeError; } else if (listLength(parameters) == 0) { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } else if (listLength(parameters) == 1) { result = minusNum(CAR(parameters)); } else { result = plusNum(CAR(parameters), minusNum(add(CDR(parameters)))); } return result; } object multiply(object parameters) { object result; TYPE(result) = numberObject; if (!allNums(parameters)) { TYPE(result) = errorObject; ERR(result) = typeError; } else if (listLength(parameters) == 0) { result = longlongToNumber(1LL); } else { object first, rest; first = CAR(parameters); rest = multiply(CDR(parameters)); result = timesNum(first,rest); } return result; } object divide(object parameters) { object result; TYPE(result) = numberObject; if (!allNums(parameters)) { TYPE(result) = errorObject; ERR(result) = typeError; } else if (listLength(parameters) == 0) { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } else if (listLength(parameters) == 1) { result = inverseNum(CAR(parameters)); } else { object check = inverseNum(multiply(CDR(parameters))); if (TYPE(check) != errorObject) { result = timesNum(CAR(parameters), inverseNum(multiply(CDR(parameters)))); } else { result = check; } result = shortenFractionNum(result); } return result; } object exactToInexact(object parameters) { object result; if (listLength(parameters) != 1) { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } else if (TYPE(CAR(parameters)) != numberObject) { TYPE(result) = errorObject; ERR(result) = typeError; } else { result = exactToInexactNum(CAR(parameters)); } return result; } object inexactToExact(object parameters) { object result; if (listLength(parameters) != 1) { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } else if (TYPE(CAR(parameters)) != numberObject) { TYPE(result) = errorObject; ERR(result) = typeError; } else { result = inexactToExactNum(CAR(parameters)); } return result; } object quote(object parameters) { object result; if (listLength(parameters) != 1) { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } else { result = copyObject(CAR(parameters)); } return result; } object lambda(object parameters) { object result; if (listLength(parameters) < 2) { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } else if (!(TYPE(CAR(parameters)) == consObject && allSyms(CAR(parameters)))) { TYPE(result) = errorObject; ERR(result) = typeError; } else { TYPE(result) = procedureObject; PROC(result) = createProcedure(); PROC_TYPE(result) = compoundProc; PROC_COMP_ARGS(result) = copyObject(CAR(parameters)); PROC_COMP_BODY(result) = copyObject(CDR(parameters)); } return result; } object define(object parameters) { object result; if (listLength(parameters) == 0) { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } else if (TYPE(CAR(parameters)) == symbolObject) { if (listLength(parameters) == 2) { result = copyObject(CAR(parameters)); addSymbolVariable(SYM(result), eval(copyObject(CAR(CDR(parameters))))); } else { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } } else if (TYPE(CAR(parameters)) == consObject) { if (listLength(parameters) >= 2) { if (allSyms(CAR(parameters))) { result = copyObject(CAR(CAR(parameters))); object args = copyObject(CDR(CAR(parameters))); deleteObject(CAR(parameters)); CAR(parameters) = copyObject(args); deleteObject(args); object proc = lambda(parameters); addSymbolVariable(SYM(result), proc); } else { TYPE(result) = errorObject; ERR(result) = typeError; } } else { TYPE(result) = errorObject; ERR(result) = argumentNumberError; } } else { TYPE(result) = errorObject; ERR(result) = typeError; } return result; }