#include "object.h" #include #include #include #ifndef STANDALONE #define printf(...) stringObj(NULL, NULL) #endif int listLength(const Object *listObj) { if(!listObj || listObj->type != TYPE_LIST) return -1; Object *t = listObj->list; if(t == NULL) return 0; int len = 1; while(t->forward != NULL) { t = t->forward; len++; } return len; } Object *itemAt(const Object *listObj, int n) { if(!listObj || listObj->type != TYPE_LIST) return NULL; Object *march = listObj->list; for(int i = 0; i < n; i++) { march = march->forward; if(march == NULL) return NULL; } return march; } // Returns last object in list (->forward == NULL) Object *tail(const Object *listObj) { if(!listObj || listObj->type != TYPE_LIST) return NULL; Object *t = listObj->list; while(t->forward != NULL) { t = t->forward; } return t; } // Adds an object to the end of a list object void addToList(Object *dest, const Object src) { if(!dest || dest->type != TYPE_LIST) return; if(dest->list == NULL) { dest->list = malloc(sizeof(struct Object)); *dest->list = src; dest->list->forward = NULL; return; } Object *end = tail(dest); end->forward = malloc(sizeof(struct Object)); *end->forward = src; end->forward->forward = NULL; } void printErr(const Object *obj) { #ifdef STANDALONE if(!obj || obj->type != TYPE_ERROR) return; printf("%s\n", errorText[(int)(obj->err)]); #endif return; } // Puts a string version of the given object into a given string char* stringObj(char *dest, const Object *obj) { if(!dest || !obj) return NULL; if(obj->type == TYPE_NUMBER) { snprintf(dest, MAX_TOK_LEN, "%d", obj->number); } else if(obj->type == TYPE_SYMBOL) { snprintf(dest, MAX_TOK_LEN, "%s", obj->name); } else if(obj->type == TYPE_BOOL) { snprintf(dest, MAX_TOK_LEN, "%s", obj->number ? "T" : "F"); } else if(obj->type == TYPE_ERROR) { snprintf(dest, MAX_TOK_LEN, "E%d", obj->err); } else { snprintf(dest, MAX_TOK_LEN, "%d", obj->number); } return dest; } int depth = 0; // Prints the given object void printObj(const Object *obj) { for(int i = 0; i < depth; i++) printf(" "); depth++; if(obj->type == TYPE_NUMBER) { printf("TYPE_NUMBER"); } else if(obj->type == TYPE_BOOL) { printf("TYPE_BOOL"); } else if(obj->type == TYPE_LIST) { printf("TYPE_LIST\n"); printList(obj); depth--; return; } else if(obj->type == TYPE_FUNC) { printf("TYPE_FUNC"); } else if(obj->type == TYPE_SYMBOL) { printf("TYPE_SYMBOL"); } else if(obj->type == TYPE_LAMBDA) { printf("TYPE_LAMBDA Params:\n"); depth++; printObj(&obj->lambda->params); for(int i = 1; i < depth; i++) printf(" "); printf("Lambda Body: \n"); printObj(&obj->lambda->body); } else if(obj->type == TYPE_ERROR) { printf("TYPE_ERROR: "); } else { printf("TYPE_OTHER (as int)"); } depth--; char temp[20] = ""; stringObj(temp, obj); printf(": %s\n", temp); printErr(obj); } void printList(const Object *list) { const Object *tail = list->list; if(tail == NULL) { for(int i = 0; i < depth; i++) printf(" "); printf("EMPTY LIST\n"); return; } while(tail != NULL) { depth++; printObj(tail); depth--; tail = tail->forward; } } void cleanObject(Object *target) { if(target == NULL) return; const Type t = target->type; if(t == TYPE_LAMBDA) { free(target->lambda); } else if(t == TYPE_LIST) { deleteList(target); } } // Frees all objects in a list void deleteList(const Object *dest) { if(dest->type != TYPE_LIST) { printf("Tried to delete something other than a list\n"); return; } Object *tail = dest->list; while(tail != NULL) { Object *prevTail = tail; tail = tail->forward; cleanObject(prevTail); free(prevTail); } } void copyList(Object *dest, const Object *src) { if(!dest || !src || dest->type != TYPE_LIST || src->type != TYPE_LIST) return; deleteList(dest); const Object *march = src->list; while(march != NULL) { addToList(dest, *march); march = march->forward; } } inline Object newObject(Type type) { Object no; no.forward = NULL; no.type = type; return no; } inline Object listObject() { Object list = newObject(TYPE_LIST); list.list = NULL; return list; } inline Object numberObject(int num) { Object o = newObject(TYPE_NUMBER); o.number = num; return o; } inline Object symbolObject() { Object o = newObject(TYPE_SYMBOL); return o; } inline Object lambdaObject() { Object o = newObject(TYPE_LAMBDA); o.lambda = malloc(sizeof(struct Lambda)); return o; } inline Object constructLambda(const Object *params, const Object *body) { if(!params || !body) return errorObject(NULL_LAMBDA_LIST); if(params->type != TYPE_LIST || body->type != TYPE_LIST) return errorObject(LAMBDA_ARGS_NOT_LIST); Object o = lambdaObject(); o.lambda->params = listObject(); o.lambda->body = listObject(); copyList(&o.lambda->params, params); copyList(&o.lambda->body, body); return o; } inline Object errorObject(enum errorCode err) { Object o = newObject(TYPE_ERROR); o.err = err; return o; }