diff --git a/src/calc.c b/src/calc.c index 7e502ec..514b383 100644 --- a/src/calc.c +++ b/src/calc.c @@ -190,11 +190,11 @@ 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) (* 3 a)))", &env); + // Object obj = parseEval("(def ad (fn (a) (* 3 a)))", &env); // Object obj2 = parseEval("(map ad (1 50 99))", &env); // printObj(&obj); // printObj(&obj2); - cleanObject(&obj); + // cleanObject(&obj); // cleanObject(&obj2); if(persist_exists(current_code)) { persist_read_string(current_code, mytext, SMAX_LENGTH); diff --git a/src/object.c b/src/object.c index 1924b10..b26e1dc 100644 --- a/src/object.c +++ b/src/object.c @@ -17,12 +17,6 @@ #define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__) #endif -#define FOR_POINTER_IN_LIST(_list) \ - for(Object *_element = _list->list; \ - _element != NULL;\ - _element = _element->forward) -#define POINTER _element - /** * Returns the length of a given list Object * @param listObj The list to get the length of @@ -40,7 +34,7 @@ int listLength(const Object *listObj) return len; } -Object len(Object obj1, Object ignore) +Object len(Object obj1, Object o_ignore, struct Environment *e_ignore) { return numberObject(listLength(&obj1)); } /** diff --git a/src/object.h b/src/object.h index d485d27..cf2161e 100644 --- a/src/object.h +++ b/src/object.h @@ -5,6 +5,19 @@ #define MAX_TOK_CNT 128 // 128 #define MAX_ENV_ELM 15 // 50 +#define FOR_POINTER_IN_LIST(_list) \ + for(Object *_element = _list->list; \ + _element != NULL;\ + _element = _element->forward) +#define POINTER _element + +#define FOR_POINTERS_IN_LISTS(_list1, _list2) \ + for(Object *_element = _list1->list, *_element2 = _list2->list; \ + _element != NULL && _element2 != NULL; \ + _element = _element->forward, _element2 = _element2->forward) +#define P1 POINTER +#define P2 _element2 + enum errorCode { MISMATCHED_PARENS, BAD_LIST_OF_SYMBOL_STRINGS, @@ -18,7 +31,8 @@ enum errorCode { LAMBDA_ARGS_NOT_LIST, DID_NOT_FIND_SYMBOL, BAD_TYPE, - UNEXPECTED_FORM + UNEXPECTED_FORM, + LISTS_NOT_SAME_SIZE }; //#ifdef STANDALONE @@ -35,7 +49,8 @@ static const char *errorText[] = { "LAMBDA_ARGS_NOT_LIST", "DID_NOT_FIND_SYMBOL", "BAD_TYPE", - "UNEXPECTED_FORM" + "UNEXPECTED_FORM", + "LISTS_NOT_SAME_SIZE" }; //#endif @@ -54,6 +69,8 @@ typedef enum Type { typedef struct Object Object; struct Lambda; +struct Environment; + struct Object { Type type; Object *forward; @@ -61,7 +78,7 @@ struct Object { int number; Object *list; char name[MAX_TOK_LEN]; - Object (*func)(Object, Object); + Object (*func)(Object, Object, struct Environment *env); struct Lambda *lambda; // Maybe better as not a pointer? enum errorCode err; }; @@ -107,6 +124,6 @@ Object errorObject(enum errorCode err); Object constructLambda(const Object *params, const Object *body); // Object version of listLength() -Object len(Object obj1, Object ignore); +Object len(Object obj1, Object, struct Environment *); #endif diff --git a/src/pebblisp.c b/src/pebblisp.c index e875d25..7107b9f 100644 --- a/src/pebblisp.c +++ b/src/pebblisp.c @@ -118,7 +118,6 @@ Object evalDefArgs(const Object *arg_forms, struct Environment *env) const Object *first_form = arg_forms; const char *name = first_form->name; - // Immediately adding the function to the env might allow recursion? Object second_eval = eval(first_form->forward, env); addToEnv(env, name, second_eval); @@ -210,7 +209,6 @@ Object evalBuiltIns(const Object *first, const Object *rest, if(strcmp(first->name, "def") == 0) { return evalDefArgs(rest, env); } else if(strcmp(first->name, "if") == 0) { - // Seems `rest` is the next *input*, not the next list item return evalIfArgs(rest, env); } else if(strcmp(first->name, "fn") == 0) { return evalLambdaArgs(rest); @@ -252,7 +250,7 @@ Object eval(const Object *obj, struct Environment *env) Object *first_form = obj->list; { // Try to eval built-ins - Object built_in = + const Object built_in = evalBuiltIns(first_form, first_form->forward, env); // deleteList(obj); // Decreases indirectly lost memory, but fails on Pebble @@ -269,7 +267,7 @@ Object eval(const Object *obj, struct Environment *env) Object func_eval = rest[0]; for(int i = 1; i < length; i++) { - func_eval = first_eval.func(func_eval, rest[i]); + func_eval = first_eval.func(func_eval, rest[i], env); } // deleteList(obj); // Decreases indirectly lost memory, but fails on Pebble return func_eval; @@ -355,7 +353,7 @@ void printEnv(struct Environment *env) } } -Object basicOp(Object *obj1, Object *obj2, const char op) +Object _basicOp(const Object *obj1, const Object *obj2, const char op) { const int n1 = obj1->number; const int n2 = obj2->number; @@ -381,9 +379,39 @@ Object basicOp(Object *obj1, Object *obj2, const char op) return *obj1; } +Object basicOp(const Object *obj1, const Object *obj2, const char op, + struct Environment *env) +{ + int lists = (obj1->type == TYPE_LIST) + (obj2->type == TYPE_LIST); + if(lists == 0) { + return _basicOp(obj1, obj2, op); + } else if(lists == 1) { // Single operand is applied to each element in list + const Object *listObj = (obj1->type == TYPE_LIST)? obj1 : obj2; + const Object *singleObj = (obj1->type == TYPE_LIST)? obj2 : obj1; + Object newList = listObject(); + FOR_POINTER_IN_LIST(listObj) { + Object adding = eval(POINTER, env); + nf_addToList(&newList, _basicOp(&adding, singleObj, op)); + } + return newList; + } else { // 2 lists + if(listLength(obj1) == listLength(obj2)) { + Object newList = listObject(); + FOR_POINTERS_IN_LISTS(obj1, obj2) { + Object ev1 = eval(P1, env); + Object ev2 = eval(P2, env); + nf_addToList(&newList, _basicOp(&ev1, &ev2, op)); + } + return newList; + } else { + return errorObject(LISTS_NOT_SAME_SIZE); + } + } +} + #define bopf(_name, _char) \ -Object _name(Object obj1, Object obj2) \ - { return basicOp(&obj1, &obj2, _char); } +Object _name(Object obj1, Object obj2, struct Environment *env) \ + { return basicOp(&obj1, &obj2, _char, env); } bopf(add, '+'); bopf(sub, '-'); @@ -393,7 +421,7 @@ bopf(equ, '='); bopf(gth, '>'); bopf(lth, '<'); -void addFunc(const char *name, Object (*func)(Object, Object), +void addFunc(const char *name, Object (*func)(Object, Object, struct Environment*), struct Environment *env) { Object o = newObject(TYPE_FUNC); diff --git a/src/pebblisp.h b/src/pebblisp.h index 1edf284..1ce513d 100644 --- a/src/pebblisp.h +++ b/src/pebblisp.h @@ -50,7 +50,6 @@ struct Environment envForLambda(const Object *params, const Object *arg_forms, struct Environment *outer); Result result(Object obj, struct Slice *slices); -Object add(Object obj1, Object obj2); // Slices void copySlice(char * dest, struct Slice *src); diff --git a/src/tokens.h b/src/tokens.h index 03a2fe0..c73685b 100644 --- a/src/tokens.h +++ b/src/tokens.h @@ -2,6 +2,7 @@ #define TOKENS_H #include "pebblisp.h" + int isSingle(const char c); int isDigit(const char c); struct Slice *nf_tokenize(const char *input);