diff --git a/src/.pebblisp.c.swp b/src/.pebblisp.c.swp index 30bc5b0..95b393d 100644 Binary files a/src/.pebblisp.c.swp and b/src/.pebblisp.c.swp differ diff --git a/src/object.c b/src/object.c new file mode 100644 index 0000000..a0ca4e2 --- /dev/null +++ b/src/object.c @@ -0,0 +1,215 @@ +#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; +} + +// 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); +} + +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; + } +} + +// 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; + free(prevTail); + } +} + +inline Object listObject() +{ + Object list; + list.forward = NULL; + list.type = TYPE_LIST; + list.list = NULL; + return list; +} + +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 numberObject(int num) +{ + Object o; + o.forward = NULL; + o.type = TYPE_NUMBER; + return o; +} + +inline Object lambdaObject() +{ + Object o; + o.forward = NULL; + o.type = TYPE_LAMBDA; + o.lambda = malloc(sizeof(struct Lambda)); + return o; +} + +inline Object errorObject(enum errorCode err) +{ + Object o; + o.forward = NULL; + o.type = TYPE_ERROR; + o.err = err; + return o; +} diff --git a/src/object.h b/src/object.h new file mode 100644 index 0000000..4821bf8 --- /dev/null +++ b/src/object.h @@ -0,0 +1,64 @@ +#ifndef OBJECT_H +#define OBJECT_H + +#define MAX_TOK_LEN 4 // 11 +#define MAX_TOK_CNT 128 // 128 +#define MAX_ENV_ELM 15 // 50 + +enum errorCode { + BAD_LIST_OF_SYMBOL_STRINGS, + TYPE_LIST_NOT_CAUGHT, + NULL_ENV, + BUILT_IN_NOT_FOUND, + NULL_PARSE +}; + +typedef enum Type { + TYPE_NUMBER, + TYPE_BOOL, + TYPE_LIST, + TYPE_FUNC, + TYPE_SYMBOL, + TYPE_LAMBDA, + TYPE_ERROR // Currently unused +} Type; + +typedef struct Object Object; +struct Lambda; + +struct Object { + Type type; + Object *forward; + union { + int number; + Object *list; + char name[MAX_TOK_LEN]; + Object (*func)(Object, Object); + struct Lambda *lambda; // Maybe better as not a pointer + enum errorCode err; + }; +}; + +// Maybe better as pointers +struct Lambda { + Object params; + Object body; +}; + +char* stringObj(char *dest, const Object *obj); +void printList(const Object *list); +void printObj(const Object *obj); + +Object *tail(const Object *listObj); +void 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); + +Object listObject(); +Object numberObject(int num); +Object lambdaObject(); +Object errorObject(); + +#endif diff --git a/src/pebblisp.c b/src/pebblisp.c index 4a7f91f..518f105 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -28,7 +28,11 @@ void debugSlice(struct Slice *s) Object fetchFromEnvironment(const char *name, struct Environment *env) { + if(!env) + return errorObject(NULL_ENV); + printf("Fetching '%s' from env\n", name); + printEnv(env); int i = 0; const char *next = env->strings[i]; while(next != NULL) { @@ -37,6 +41,10 @@ Object fetchFromEnvironment(const char *name, struct Environment *env) } next = env->strings[++i]; } + printf("Trying outer\n"); + if(env->outer) { + return fetchFromEnvironment(name, env->outer); + } printf("DID NOT FIND SYMBOL\n"); Object o; o.type = TYPE_ERROR; @@ -51,7 +59,7 @@ Result parse(struct Slice *slices) rest = &slices[1]; } else { printf("Assigning null...\n"); - rest = NULL; + return R(errorObject(NULL_PARSE), NULL); } if(token->text[0] == '(') { @@ -103,8 +111,6 @@ Object parseAtom(struct Slice *s) Object evalDefArgs(const Object *arg_forms, struct Environment *env) { - printf("evalDefArgs()\n"); - const Object *first_form = &arg_forms[0]; const char *name = first_form->name; @@ -122,69 +128,151 @@ Object evalIfArgs(const Object *arg_forms, struct Environment *env) eval(arg_forms->forward->forward, env); } -Object evalBuiltIns(const Object *first, const Object *rest, int *found, +Object evalLambdaArgs(const Object *arg_forms) +{ + const Object *params_expr = &arg_forms[0]; + const Object *body_expr = &arg_forms[1]; + + Object o = lambdaObject(); + o.lambda->params = listObject(); + copyList(&o.lambda->params, params_expr); + + o.lambda->body = listObject(); + copyList(&o.lambda->body, arg_forms->forward); + return o; +} + +void parseListOfSymbolStrings(const Object *form, const char **symbolStrings, + int len) +{ + if(!form || form->type != TYPE_LIST) + return; + + for(int i = 0; i < len; i++) + symbolStrings[i] = itemAt(form, i)->name; +} + +struct Environment envForLambda(const Object *params, const Object *arg_forms, + struct Environment *outer) +{ + printf("\n#####################\nenvForLambda()\n"); + printObj(arg_forms); + struct Environment env; + env.outer = outer; + env.strings = NULL; + env.objects = NULL; + + int length = listLength(params); + + if(length == 0) + return env; + + env.strings = calloc(sizeof(char*), length); + env.objects = malloc(sizeof(Object) * length); + + Object vs[length]; + eval_forms(vs, arg_forms, outer); + + 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? + } // Something is segfaulting, anyway + env.strings[length] = NULL; + + printf("envForLambda env IT BROKE HERE()\n"); + printf("envForLambda length=%d\n", length); + printEnv(&env); + printf("END envForLambda()\n\n"); + return env; +} + +Object evalBuiltIns(const Object *first, const Object *rest, struct Environment *env) { if(strcmp(first->name, "def") == 0) { - *found = 0; return evalDefArgs(rest, env); }else if(strcmp(first->name, "if") == 0) { - *found = 0; return evalIfArgs(rest, env); + }else if(strcmp(first->name, "fn") == 0) { + // printf("EVALBUILTINS first:\n"); + // printObj(first); + // printf("\nEVALBUILTINS rest:\n"); + // printObj(rest); + return evalLambdaArgs(rest); } - Object o; - *found = -1; - return o; + return errorObject(BUILT_IN_NOT_FOUND); +} + +void eval_forms(Object *destList, const Object *src, struct Environment *env) +{ + int length = listLength(src) - 1; // Not counting first_form + for(int i = 0; i < length; i++) { // Evaluates all in list + destList[i] = eval(itemAt(src, i + 1), env); // Skip the first + } } Object eval(const Object *obj, struct Environment *env) { - // printf("eval(): "); - // printObj(obj); - Object o = *obj; + printf("eval():\n"); + printObj(obj); switch(obj->type) { case TYPE_NUMBER: case TYPE_BOOL: - return o; + return *obj; case TYPE_SYMBOL: - o = fetchFromEnvironment(obj->name, env); - printf("fetched object '%s':\n", obj->name); - printObj(&o); - return o; + return fetchFromEnvironment(obj->name, env); case TYPE_LIST: { - if(listLength(obj) == 1) { - o = *obj->list; - return o; + if(listLength(obj) == 0) { + printf("empty list\n"); return *obj; } - Object first_form = *obj->list; + + if(listLength(obj) == 1) + return eval(obj->list, env); + + Object *first_form = obj->list; { // Try to eval built-ins - int i = -1; Object built_in = - evalBuiltIns(&first_form, first_form.forward, &i, env); + evalBuiltIns(first_form, first_form->forward, env); - if(i == 0) + if(built_in.type != TYPE_ERROR) return built_in; } - printf("\nNo built-ins found\n"); - Object first_eval = eval(&first_form, env); - Object arg1 = eval(first_form.forward, env); - Object arg2 = eval(first_form.forward->forward, env); + Object first_eval = eval(first_form, env); + if(first_eval.type == TYPE_FUNC) { + int length = listLength(obj) - 1; // Not counting first_form + Object rest[length]; + eval_forms(rest, obj, env); - printf("Evaluating func\n"); - Object func_eval = first_eval.func(arg1, arg2); - deleteList(obj); - return func_eval; + printf("Evaluating func\n"); + Object func_eval = first_eval.func(rest[0], rest[1]); + // deleteList(obj); + return func_eval; + } else if (first_eval.type == TYPE_LAMBDA) { + printf("lammy\n"); + struct Environment newEnv = + envForLambda(&first_eval.lambda->params, first_form->forward, env); + return eval(&first_eval.lambda->body, &newEnv); + } else { + return errorObject(TYPE_LIST_NOT_CAUGHT); + } + } + case TYPE_LAMBDA: + { + Object o; + o.type = TYPE_ERROR; + printf("UNEXPECTED FORM\n"); + return o; } default: ; } - return o; + return *obj; } Result resultFromObjAndSlices(Object obj, struct Slice *slices) @@ -206,6 +294,20 @@ void addToEnv(struct Environment *env, const char *name, const Object obj) env->objects[i] = obj; break; } + if(strcmp(env->strings[i], name) == 0) { + env->objects[i] = obj; + break; + } + } +} + +void printEnv(struct Environment *env) +{ + for(int i = 0; i < MAX_ENV_ELM; i++) { + if(env->strings[i] == NULL) + return; + printf("env[%d]: '%s'\n ", i, env->strings[i]); + printObj(&env->objects[i]); } } @@ -290,6 +392,7 @@ 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; @@ -317,11 +420,15 @@ Object parseEval(const char *input, struct Environment *env) while(debug->text) { char tok[MAX_TOK_LEN]; copySlice(tok, debug); + //printf("slice: '%s'\n", tok); debug++; } } #endif Object parsed = parse(tokens).obj; + // printf("PARSEEVAL() PRINTLIST():\n"); + // printObj(&parsed); + // printf("end PARSEEVAL() PRINTLIST():\n\n"); free(tokens); return eval(&parsed, env); } @@ -335,7 +442,7 @@ int repl(struct Environment *env) fgets(input, 100, stdin); Object obj = parseEval(input, env); printObj(&obj); - //break; + // printEnv(env); } } diff --git a/src/pebblisp.h b/src/pebblisp.h index ffd575e..59ffdb9 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -19,6 +19,7 @@ typedef struct Result { struct Environment { char **strings; Object *objects; + struct Environment *outer; }; Object eval(const Object *obj, struct Environment *env); @@ -27,9 +28,13 @@ Result readSeq(struct Slice *slices); Object parseAtom(struct Slice *slice); void copySlice(char * dest, struct Slice *src); Object parseEval(const char *input, struct Environment *env); +void eval_forms(Object *destList, const Object *src, struct Environment *env); + struct Environment defaultEnv(); 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); Result resultFromObjAndSlices(Object obj, struct Slice *slices); Object add(Object obj1, Object obj2); diff --git a/src/tags b/src/tags index 09ae243..bf39104 100644 --- a/src/tags +++ b/src/tags @@ -4,19 +4,23 @@ !_TAG_PROGRAM_NAME Exuberant Ctags // !_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ !_TAG_PROGRAM_VERSION 5.9~svn20110310 // +BAD_LIST_OF_SYMBOL_STRINGS object.h /^ BAD_LIST_OF_SYMBOL_STRINGS,$/;" e enum:errorCode +BUILT_IN_NOT_FOUND object.h /^ BUILT_IN_NOT_FOUND$/;" e enum:errorCode CALC_H calc.h 2;" d CODE_PKEY calc.h 11;" d END_PHRASE calc.h 9;" d Environment pebblisp.h /^struct Environment {$/;" s +Lambda object.h /^struct Lambda {$/;" s MAX_ENV_ELM object.h 6;" d MAX_LENGTH calc.h 8;" d MAX_TOK_CNT object.h 5;" d MAX_TOK_LEN object.h 4;" d +NULL_ENV object.h /^ NULL_ENV,$/;" e enum:errorCode OBJECT_H object.h 2;" d Object object.h /^struct Object {$/;" s Object object.h /^typedef struct Object Object;$/;" t typeref:struct:Object PEBBLISP_H pebblisp.h 2;" d -R pebblisp.h 41;" d +R pebblisp.h 45;" d Result pebblisp.h /^typedef struct Result {$/;" s Result pebblisp.h /^} Result;$/;" t typeref:struct:Result SMAX_LENGTH calc.h 7;" d @@ -24,9 +28,11 @@ Slice pebblisp.h /^struct Slice {$/;" s TOKENS_H tokens.h 2;" d TOKEN_END calc.h 42;" d TYPE_BOOL object.h /^ TYPE_BOOL,$/;" e enum:Type -TYPE_ERROR object.h /^ TYPE_ERROR$/;" e enum:Type +TYPE_ERROR object.h /^ TYPE_ERROR \/\/ Currently unused$/;" e enum:Type TYPE_FUNC object.h /^ TYPE_FUNC,$/;" e enum:Type +TYPE_LAMBDA object.h /^ TYPE_LAMBDA,$/;" e enum:Type TYPE_LIST object.h /^ TYPE_LIST,$/;" e enum:Type +TYPE_LIST_NOT_CAUGHT object.h /^ TYPE_LIST_NOT_CAUGHT,$/;" e enum:errorCode TYPE_NUMBER object.h /^ TYPE_NUMBER,$/;" e enum:Type TYPE_SYMBOL object.h /^ TYPE_SYMBOL,$/;" e enum:Type Type object.h /^typedef enum Type {$/;" g @@ -36,9 +42,11 @@ addToEnv pebblisp.c /^void addToEnv(struct Environment *env, const char *name, c addToList object.c /^void addToList(Object *dest, const Object src)$/;" f back_handler calc.c /^static void back_handler(ClickRecognizerRef recognizer, void *context) {$/;" f file: basicOp pebblisp.c /^Object basicOp(Object *obj1, Object *obj2, const char op)$/;" f -bopf pebblisp.c 264;" d file: +body object.h /^ Object body;$/;" m struct:Lambda +bopf pebblisp.c 365;" d file: calculate calc.c /^static void calculate(){$/;" f file: click_config_provider calc.c /^static void click_config_provider(void *context) {$/;" f file: +copyList object.c /^void copyList(Object *dest, const Object *src)$/;" f copySlice pebblisp.c /^void copySlice(char * dest, struct Slice *src)$/;" f debugSlice pebblisp.c /^void debugSlice(struct Slice *s)$/;" f defaultEnv pebblisp.c /^struct Environment defaultEnv() {$/;" f @@ -47,10 +55,16 @@ deleteEnv pebblisp.c /^void deleteEnv(struct Environment *e)$/;" f deleteList object.c /^void deleteList(const Object *dest)$/;" f enter calc.c /^static void enter(){$/;" f file: env calc.h /^static struct Environment env;$/;" v typeref:struct:Environment +envForLambda pebblisp.c /^struct Environment envForLambda(const Object *params, const Object *arg_forms,$/;" f +err object.h /^ enum errorCode err;$/;" m union:Object::__anon1 typeref:enum:Object::__anon1::errorCode +errorCode object.h /^enum errorCode {$/;" g +errorObject object.c /^inline Object errorObject(enum errorCode err)$/;" f eval pebblisp.c /^Object eval(const Object *obj, struct Environment *env)$/;" f -evalBuiltIns pebblisp.c /^Object evalBuiltIns(const Object *first, const Object *rest, int *found,$/;" f +evalBuiltIns pebblisp.c /^Object evalBuiltIns(const Object *first, const Object *rest,$/;" f evalDefArgs pebblisp.c /^Object evalDefArgs(const Object *arg_forms, struct Environment *env)$/;" f evalIfArgs pebblisp.c /^Object evalIfArgs(const Object *arg_forms, struct Environment *env)$/;" f +evalLambdaArgs pebblisp.c /^Object evalLambdaArgs(const Object *arg_forms, struct Environment *env)$/;" f +eval_forms pebblisp.c /^void eval_forms(Object *destList, const Object *src, struct Environment *env)$/;" f fetchFromEnvironment pebblisp.c /^Object fetchFromEnvironment(const char *name, struct Environment *env)$/;" f forward object.h /^ Object *forward;$/;" m struct:Object func object.h /^ Object (*func)(Object, Object);$/;" m union:Object::__anon1 @@ -59,6 +73,9 @@ init calc.c /^static void init(void) {$/;" f file: isDigit tokens.c /^int isDigit(const char c) {$/;" f isSingle tokens.c /^int isSingle(const char c) {$/;" f isWhitespace tokens.c /^int isWhitespace(const char c) {$/;" f +itemAt object.c /^Object *itemAt(const Object *listObj, int n)$/;" f +lambda object.h /^ struct Lambda *lambda; \/\/ Maybe better as not a pointer$/;" m union:Object::__anon1 typeref:struct:Object::__anon1::Lambda +lambdaObject object.c /^inline Object lambdaObject()$/;" f length pebblisp.h /^ char length;$/;" m struct:Slice list object.h /^ Object *list;$/;" m union:Object::__anon1 listLength object.c /^int listLength(const Object *listObj)$/;" f @@ -73,9 +90,13 @@ number object.h /^ int number;$/;" m union:Object::__anon1 numberObject object.c /^inline Object numberObject(int num)$/;" f obj pebblisp.h /^ Object obj;$/;" m struct:Result objects pebblisp.h /^ Object *objects;$/;" m struct:Environment +outer pebblisp.h /^ struct Environment *outer;$/;" m struct:Environment typeref:struct:Environment::Environment +params object.h /^ Object params;$/;" m struct:Lambda parse pebblisp.c /^Result parse(struct Slice *slices)$/;" f parseAtom pebblisp.c /^Object parseAtom(struct Slice *s)$/;" f parseEval pebblisp.c /^Object parseEval(const char *input, struct Environment *env)$/;" f +parseListOfSymbolStrings pebblisp.c /^void parseListOfSymbolStrings(const Object *form, const char **symbolStrings,$/;" f +printEnv pebblisp.c /^void printEnv(struct Environment *env)$/;" f printList object.c /^void printList(const Object *list)$/;" f printObj object.c /^void printObj(const Object *obj)$/;" f printf object.c 7;" d file: