Adjusted func types to account for possible eval

Basic ops work with lists. For example (+ 5 (10 15)) => (15 20)
This commit is contained in:
= 2020-05-10 04:51:55 +01:00
parent d9c860805f
commit 874420b3d5
6 changed files with 61 additions and 22 deletions

View File

@ -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);

View File

@ -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)); }
/**

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);