From a286943984675675f0a4a29c3e9ff283490d5d60 Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 8 May 2020 01:32:01 +0100 Subject: [PATCH] Busted `map` with less malloc --- src/Makefile | 3 + src/calc.c | 13 +++- src/calc.h | 6 +- src/object.c | 87 ++++++++++++++-------- src/object.h | 41 ++++++---- src/pebblisp.c | 197 +++++++++++++++++++++++++++++++++++-------------- src/pebblisp.h | 8 +- 7 files changed, 245 insertions(+), 110 deletions(-) diff --git a/src/Makefile b/src/Makefile index 4437453..95badf3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,3 +3,6 @@ all: debug: gcc -g -O0 -o pebblisp -D STANDALONE -D DEBUG pebblisp.c tokens.c object.c + +phrase: + gcc -g -O0 -o pebblisp -D STANDALONE -D DEBUG -D NO_REPL pebblisp.c tokens.c object.c diff --git a/src/calc.c b/src/calc.c index 0d379bd..8299c72 100644 --- a/src/calc.c +++ b/src/calc.c @@ -1,6 +1,5 @@ #include #include -//#include "fixed.h" #include "calc.h" static inline int8_t tokenCount() { @@ -71,10 +70,10 @@ static void enter(){ // Calculate result, display it and reset static void calculate(){ Object obj = parseEval(mytext, &env); - char temp[MAX_LENGTH-2] = ""; + char temp[RESULT_LENGTH-2] = ""; stringObj(temp, &obj); - snprintf(resulttext, MAX_LENGTH, "R:%s", temp); + snprintf(resulttext, RESULT_LENGTH, "R:%s", temp); selected_token = 0; text_layer_set_text(s_result_text_layer, resulttext); } @@ -191,6 +190,14 @@ void code_window_load(Window *window) window_stack_push(s_code_window, true); // If possible, load the previous code text + Object obj = parseEval("(def ad (fn (a) (+ 1 a)))", &env); + Object obj2 = parseEval("(map ad (1 2 3))", &env); + printObj(&obj); + printObj(&obj2); + cleanObject(&obj); + cleanObject(&obj2); + if(1) + return; if(persist_exists(current_code)) { persist_read_string(current_code, mytext, SMAX_LENGTH); updateText(); diff --git a/src/calc.h b/src/calc.h index a9c0fc0..0b82dca 100644 --- a/src/calc.h +++ b/src/calc.h @@ -5,7 +5,7 @@ #include "pebblisp.h" #define SMAX_LENGTH 256 -#define MAX_LENGTH 11 +#define RESULT_LENGTH 20 #define END_PHRASE "END" #define NUM_ROWS 5 @@ -33,7 +33,7 @@ char mytext[SMAX_LENGTH] = ""; char temptext[SMAX_LENGTH] = ""; // The result of execution -char resulttext[MAX_LENGTH] = ""; +char resulttext[RESULT_LENGTH] = ""; char *tokens[] = { " ", "(", ")", @@ -43,7 +43,7 @@ char *tokens[] = { "7","8","9", "0", "a", "b", "c", "d", "e", "= ", "< ", "> ", - "fn", "def", "if", "\n", + "map", "fn", "def", "if", "\n", END_PHRASE }; diff --git a/src/object.c b/src/object.c index 5a7c226..ec30b2f 100644 --- a/src/object.c +++ b/src/object.c @@ -3,6 +3,8 @@ #include #include +#define RESULT_LENGTH 20 + #ifdef DEBUG #define printd(...) printf(__VA_ARGS__) #else @@ -10,7 +12,9 @@ #endif #ifndef STANDALONE -#define printf(...) stringObj(NULL, NULL) +#include +#undef printf +#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__) #endif int listLength(const Object *listObj) @@ -126,8 +130,16 @@ void insertIntoList(Object *dest, int ind, const Object src) march->forward->forward = oldForward; } +void replaceListing(Object *list, int i, const Object src) +{ + if(!list) + return; + list[i] = src; + list[i].forward = NULL; +} + // Adds an object to the end of a list object -void addToList(Object *dest, const Object src) +void nf_addToList(Object *dest, const Object src) { if(!dest || dest->type != TYPE_LIST) return; @@ -143,38 +155,57 @@ void addToList(Object *dest, const Object src) void printErr(const Object *obj) { -#ifdef STANDALONE +//#ifdef STANDALONE if(!obj || obj->type != TYPE_ERROR) return; printf("%s\n", errorText[(int)(obj->err)]); -#endif +//#endif return; } +void stringList(char *dest, const Object *obj) +{ + dest[0] = '('; + dest[1] = '\0'; + + const Object *tail = obj->list; + while(tail != NULL) { + printf("%s\n", dest); + strcat(dest, " "); + char tok[90] = ""; + stringObj(tok, tail); + strcat(dest, tok); + tail = tail->forward; + } + strcat(dest, " )"); +} + // 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); + const Type t = obj->type; + + if(t == TYPE_NUMBER) { + snprintf(dest, RESULT_LENGTH, "%d", obj->number); + } else if(t == TYPE_SYMBOL) { + snprintf(dest, RESULT_LENGTH, "%s", obj->name); + } else if(t == TYPE_BOOL) { + snprintf(dest, RESULT_LENGTH, "%s", obj->number ? "T" : "F"); + } else if(t == TYPE_ERROR) { + snprintf(dest, RESULT_LENGTH, "E%d", obj->err); + } else if(t == TYPE_LIST) { + stringList(dest, obj); } else { - snprintf(dest, MAX_TOK_LEN, "%d", obj->number); + snprintf(dest, RESULT_LENGTH, "%d", obj->number); } return dest; } -int depth = 0; - void debugObj(const Object *obj) { #ifdef DEBUG @@ -186,38 +217,28 @@ void debugObj(const Object *obj) void _printList(const Object *list, int newline); void _printObj(const Object *obj, int newline) { - for(int i = 0; i < depth; i++) - printd(" "); - depth++; - if(obj->type == TYPE_NUMBER) { printd("TYPE_NUMBER"); } else if(obj->type == TYPE_BOOL) { printd("TYPE_BOOL"); } else if(obj->type == TYPE_LIST) { printd("TYPE_LIST\n"); - _printList(obj, newline); - depth--; - return; } else if(obj->type == TYPE_FUNC) { printd("TYPE_FUNC"); } else if(obj->type == TYPE_SYMBOL) { printd("TYPE_SYMBOL"); } else if(obj->type == TYPE_LAMBDA) { printd("TYPE_LAMBDA Params:\n"); - depth++; printObj(&obj->lambda->params); - for(int i = 1; i < depth; i++) - printf(" "); printd("Lambda Body: \n"); printObj(&obj->lambda->body); + return; } else if(obj->type == TYPE_ERROR) { printd("TYPE_ERROR: "); } else { printd("TYPE_OTHER (as int)"); } - depth--; - char temp[20] = ""; + char temp[100] = ""; stringObj(temp, obj); if(newline) printf("%s\n", temp); @@ -238,9 +259,7 @@ void _printList(const Object *list, int newline) const Object *tail = list->list; while(tail != NULL) { printf(" "); - depth++; _printObj(tail, 0); - depth--; tail = tail->forward; } printf(" )"); @@ -261,12 +280,20 @@ void cleanObject(Object *target) const Type t = target->type; if(t == TYPE_LAMBDA) { + cleanObject(&target->lambda->params); + cleanObject(&target->lambda->body); free(target->lambda); } else if(t == TYPE_LIST) { deleteList(target); } } +void printAndClean(Object *target) +{ + printObj(target); + cleanObject(target); +} + // Frees all objects in a list void deleteList(const Object *dest) { @@ -297,7 +324,7 @@ void copyList(Object *dest, const Object *src) deleteList(dest); const Object *march = src->list; while(march != NULL) { - addToList(dest, *march); + nf_addToList(dest, *march); march = march->forward; } } diff --git a/src/object.h b/src/object.h index ad2dc14..137dfb3 100644 --- a/src/object.h +++ b/src/object.h @@ -12,24 +12,30 @@ enum errorCode { BUILT_IN_NOT_FOUND, NULL_PARSE, NULL_LAMBDA_LIST, + NULL_MAP_ARGS, LAMBDA_ARGS_NOT_LIST, DID_NOT_FIND_SYMBOL, + BAD_TYPE, UNEXPECTED_FORM }; -#ifdef STANDALONE - static const char *errorText[] = { - "BAD_LIST_OF_SYMBOL_STRINGS", - "TYPE_LIST_NOT_CAUGHT", - "NULL_ENV", - "BUILT_IN_NOT_FOUND", - "NULL_PARSE", - "NULL_LAMBDA_LIST", - "LAMBDA_ARGS_NOT_LIST", - "DID_NOT_FIND_SYMBOL", - "UNEXPECTED_FORM" - }; -#endif +//#ifdef STANDALONE +static const char *errorText[] = { + "BAD_LIST_OF_SYMBOL_STRINGS", + "TYPE_LIST_NOT_CAUGHT", + "NULL_ENV", + "BUILT_IN_NOT_FOUND", + "NULL_PARSE", + "NULL_LAMBDA_LIST", + "NULL_MAP_ARGS", + "LAMBDA_ARGS_NOT_LIST", + "DID_NOT_FIND_SYMBOL", + "BAD_TYPE", + "UNEXPECTED_FORM" +}; +//#endif + +#define MALLOC_FLAG 64 typedef enum Type { TYPE_NUMBER, @@ -38,7 +44,7 @@ typedef enum Type { TYPE_FUNC, TYPE_SYMBOL, TYPE_LAMBDA, - TYPE_ERROR // Currently unused + TYPE_ERROR } Type; typedef struct Object Object; @@ -67,16 +73,21 @@ char* stringObj(char *dest, const Object *obj); void printList(const Object *list); void printObj(const Object *obj); void debugObj(const Object *obj); +void printErr(const Object *obj); +int wasMalloc(const Object *obj); +int getType(const Object *obj); int isEmpty(const Object *obj); Object *tail(const Object *listObj); -void addToList(Object *dest, Object src); +void replaceListing(Object *list, int i, const Object src); +void nf_addToList(Object *dest, Object src); void deleteList(const Object *dest); int listLength(const Object *listObj); Object *itemAt(const Object *listObj, int n); void copyList(Object *dest, const Object *src); void cleanObject(Object *target); +void printAndClean(Object *target); void allocObject(Object **spot, const Object src); Object newObject(Type type); diff --git a/src/pebblisp.c b/src/pebblisp.c index 051f64c..76933de 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -4,6 +4,11 @@ #include #include +#ifndef STANDALONE +#undef printf +#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__) +#endif + void copySlice(char * dest, struct Slice *src) { if(!dest || !src) @@ -29,14 +34,12 @@ Object fetchFromEnvironment(const char *name, struct Environment *env) printd("Fetching '%s' from env\n", name); printEnv(env); - int i = 0; - const char *next = env->strings[i]; - while(next != NULL) { - if(strcmp(name, next) == 0) { + for(int i = 0; i < env->size; i++) { + if(strcmp(name, env->strings[i]) == 0) { return env->objects[i]; } - next = env->strings[++i]; } + printd("Trying outer\n"); if(env->outer) { return fetchFromEnvironment(name, env->outer); @@ -52,14 +55,14 @@ Result parse(struct Slice *slices) if(token->text != NULL) { rest = &slices[1]; } else { - return R(errorObject(NULL_PARSE), NULL); + return result(errorObject(NULL_PARSE), NULL); } if(token->text[0] == '(') { // todo check for null rest return readSeq(rest); } else { // todo error on closed paren - return R(parseAtom(token), rest); + return result(parseAtom(token), rest); } } @@ -70,10 +73,10 @@ Result readSeq(struct Slice *tokens) struct Slice *next = &tokens[0]; struct Slice *rest = next->text? &next[1] : NULL; if(next->text[0] == ')') { - return R(res, rest); + return result(res, rest); } Result r = parse(tokens); - addToList(&res, r.obj); + nf_addToList(&res, r.obj); tokens = r.slices; } } @@ -126,37 +129,100 @@ Object evalLambdaArgs(const Object *arg_forms) return constructLambda(arg_forms, arg_forms->forward); } -Object evalMapArgs(const Object *arg_forms) +//Object evalMapArgs(Object *newList, const Object *arg_forms, +void evalMapArgs(Object *newList, const Object *arg_forms, + struct Environment *env) { - return listObject(); + if(!arg_forms) + return; // errorObject(NULL_MAP_ARGS); + + const Object lambda = eval(&arg_forms[0], env); + Object *oldList = (&arg_forms[0])->forward; + printf("lambda\n"); + printObj(&lambda); + printf("oldList\n"); + printObj(oldList); + printf("END oldList\n"); + + if(lambda.type != TYPE_LAMBDA || oldList->type != TYPE_LIST) { + return; // errorObject(BAD_TYPE); + } + + // Object list = listObject(); + + int i = 0; + Object *oldElement = oldList->list; + while(oldElement != NULL) { + // Create a new list for each element in the list, + // since lambda evaluation looks for a list + Object tempList = listObject(); + Object listBack[1] = {*oldElement}; + listBack[0].forward = NULL; + tempList.list = listBack; + printObj(&tempList); + printf("END &tempList\n"); + + //nf_addToList(&tempList, *oldElement); + + struct Environment newEnv = + envForLambda(&lambda.lambda->params, &tempList, env); + const Object evalLambda = eval(&lambda.lambda->body, &newEnv); + // cleanObject(&tempList); // Don't let tempList linger + + //nf_addToList(&list, evalLambda); + newList[i++] = evalLambda; + printf("VVVVVVnewList[%d]\n", i - 1); + printObj(&newList[i-1]); + printf("^^^^^^newList[%d]\n", i - 1); + oldElement = oldElement->forward; + } + + for(int j = 0; j < i - 1; j++) { + newList[j].forward = &newList[j+1]; + } + newList[i-1].forward = NULL; + + //printf("return list\n"); + //return list; } struct Environment envForLambda(const Object *params, const Object *arg_forms, struct Environment *outer) { - printd("\n#####################\nenvForLambda()\n"); + printd("\n#####################"); + printf("envForLambda()\n"); debugObj(arg_forms); + + int length = listLength(params); + struct Environment env; env.outer = outer; env.strings = NULL; env.objects = NULL; - - int length = listLength(params); + env.size = length; if(length == 0) return env; - env.strings = calloc(sizeof(char*), length); - env.objects = malloc(sizeof(Object) * length); + env.strings = calloc(sizeof(char*), length + 1); + env.objects = malloc(sizeof(Object) * length + 1); Object vs[length]; eval_forms(vs, arg_forms, outer); + printf("WHICH/ONE\n"); + for(int i = 0; i < length; i++) { + //printObj(&vs[i]); + printObj(&arg_forms[i]); + } + printf("END WHICH/ONE\n"); for(int i = 0; i < length; i++) { const char *n = itemAt(params, i)->name; addToEnv(&env, n, eval(&arg_forms[i], outer)); // May not need eval? + // SHOULD BE `vs` not arg_forms??? + } // Something is segfaulting, anyway - env.strings[length] = NULL; + // env.strings[length] = NULL; printd("envForLambda env IT BROKE HERE()\n"); printd("envForLambda length=%d\n", length); @@ -174,8 +240,17 @@ Object evalBuiltIns(const Object *first, const Object *rest, return evalIfArgs(rest, env); } else if(strcmp(first->name, "fn") == 0) { return evalLambdaArgs(rest); - } else if(strcmp(first->name, "mp") == 0) { - return evalMapArgs(rest); + } else if(strcmp(first->name, "map") == 0) { + printf("MAP BUILT-IN\n"); + int length = listLength(rest->forward); + Object newList = listObject(); + //Object listBack[length]; + //newList.list = listBack; + evalMapArgs(listBack, rest, env); + printf("print evalMapArgs() obj\n"); + printObj(&newList); + printf("MAP BUILT-IN\n"); + return newList; } return errorObject(BUILT_IN_NOT_FOUND); @@ -191,7 +266,7 @@ void eval_forms(Object *destList, const Object *src, struct Environment *env) Object eval(const Object *obj, struct Environment *env) { - printd("eval():\n"); + printf("eval():\n"); debugObj(obj); switch(obj->type) { case TYPE_NUMBER: @@ -214,10 +289,11 @@ Object eval(const Object *obj, struct Environment *env) { // Try to eval built-ins Object built_in = evalBuiltIns(first_form, first_form->forward, env); - + // deleteList(obj); // Decreases indirectly lost memory, but fails on Pebble - if(built_in.type != TYPE_ERROR) + if(built_in.type != TYPE_ERROR) { return built_in; + } } Object first_eval = eval(first_form, env); @@ -236,7 +312,9 @@ Object eval(const Object *obj, struct Environment *env) } else if (first_eval.type == TYPE_LAMBDA) { struct Environment newEnv = envForLambda(&first_eval.lambda->params, first_form->forward, env); - return eval(&first_eval.lambda->body, &newEnv); + Object ret = eval(&first_eval.lambda->body, &newEnv); + deleteEnv(&newEnv); + return ret; } else { return *obj; @@ -251,31 +329,47 @@ Object eval(const Object *obj, struct Environment *env) return *obj; } -Result resultFromObjAndSlices(Object obj, struct Slice *slices) +Result result(Object obj, struct Slice *slices) { - Result r; - r.obj = obj; - r.slices = slices; - return r; + return (Result) { + .obj = obj, + .slices = slices + }; } // todo could include and return a starting index for faster multi-adds +// Maybe extend existing environment using a malloc'd outer, instead of realloc void addToEnv(struct Environment *env, const char *name, const Object obj) { int i; - for(i = 0; i < MAX_ENV_ELM; i++) { + //printf("sizeof(char)=%d * strlen(name)=%d\n", (int)sizeof(char), (int)strlen(name)); + for(i = 0; i < env->size ; i++) { if(env->strings[i] == NULL) { - env->strings[i] = malloc(sizeof(name)); - strncpy(env->strings[i], name, MAX_TOK_LEN); + env->strings[i] = malloc(strlen(name) + 1); + strncpy(env->strings[i], name, strlen(name)); env->objects[i] = obj; - break; + return; } if(strcmp(env->strings[i], name) == 0) { cleanObject(&env->objects[i]); env->objects[i] = obj; - break; + return; } } + + printd("Reallocating environment\n"); + const int inc = 5; + env->size += inc; + env->strings = realloc(env->strings, sizeof(char*) * env->size); + env->objects = realloc(env->objects, sizeof(Object) * env->size); + + for(int j = 0; j < inc; j++) { + env->strings[i + j] = NULL; + } + + env->strings[i] = malloc(strlen(name) + 1); + strncpy(env->strings[i], name, strlen(name)); + env->objects[i] = obj; } void printEnv(struct Environment *env) @@ -284,7 +378,7 @@ void printEnv(struct Environment *env) printd("NULL env\n"); return; } - for(int i = 0; i < MAX_ENV_ELM; i++) { + for(int i = 0; i < env->size; i++) { if(env->strings[i] == NULL) return; printd("env[%d]: '%s'\n ", i, env->strings[i]); @@ -345,6 +439,7 @@ void deleteEnv(struct Environment *e) int i = 0; while(e->strings[i]) { free(e->strings[i]); + cleanObject(&e->objects[i]); i++; } free(e->strings); @@ -357,10 +452,11 @@ void deleteEnv(struct Environment *e) struct Environment defaultEnv() { struct Environment e; e.outer = NULL; - e.strings = malloc(sizeof(char*) * MAX_ENV_ELM); - for(int i = 0; i < MAX_ENV_ELM; i++) { - e.strings[i] = NULL; - } + e.strings = calloc(sizeof(char*), MAX_ENV_ELM); + e.size = MAX_ENV_ELM; + // for(int i = 0; i < MAX_ENV_ELM; i++) { + // e.strings[i] = NULL; + // } e.objects = malloc(sizeof(Object) * MAX_ENV_ELM); @@ -391,7 +487,9 @@ Object parseEval(const char *input, struct Environment *env) #endif Object parsed = parse(tokens).obj; free(tokens); - return eval(&parsed, env); + Object ret = eval(&parsed, env); + cleanObject(&parsed); + return ret; } #ifdef STANDALONE @@ -402,6 +500,7 @@ int repl(struct Environment *env) printf("pebblisp>> "); fgets(input, 100, stdin); Object obj = parseEval(input, env); + // printAndClean(&obj); printObj(&obj); // printEnv(env); } @@ -413,22 +512,10 @@ int main(void) #ifndef NO_REPL repl(&env); #else - struct Slice *tokens = nf_tokenize("(+ 10 5)"); - struct Slice *debug = tokens; - - if(debug) { - while(debug->text) { - char tok[10]; - copySlice(tok, debug); - printf("'%s', ", tok); - debug++; - } - printf("\n"); - } else { - printf("parse error\n"); - } - parse(tokens); - free(tokens); + Object r = parseEval("(def ad (fn (a) (+ 1 a)))", &env); + printAndClean(&r); + r = parseEval("(map ad (1 2 3))", &env); + //printAndClean(&r); #endif deleteEnv(&env); } diff --git a/src/pebblisp.h b/src/pebblisp.h index dcd29cd..1edf284 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -5,7 +5,6 @@ #ifndef STANDALONE #include -// #define printf(...) copySlice(NULL, NULL) #define printd(...) copySlice(NULL, NULL) #endif @@ -29,6 +28,7 @@ struct Environment { char **strings; Object *objects; struct Environment *outer; + char size; }; Object eval(const Object *obj, struct Environment *env); @@ -46,14 +46,14 @@ void deleteEnv(struct Environment *e); void addToEnv(struct Environment *env, const char *name, const Object obj); Object fetchFromEnvironment(const char *name, struct Environment *env); void printEnv(struct Environment *env); +struct Environment envForLambda(const Object *params, const Object *arg_forms, + struct Environment *outer); -Result resultFromObjAndSlices(Object obj, struct Slice *slices); +Result result(Object obj, struct Slice *slices); Object add(Object obj1, Object obj2); // Slices void copySlice(char * dest, struct Slice *src); void debugSlice(struct Slice *s); -#define R(_obj, _slices) resultFromObjAndSlices(_obj, _slices) - #endif