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:
parent
d9c860805f
commit
874420b3d5
|
@ -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);
|
||||
|
|
|
@ -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)); }
|
||||
|
||||
/**
|
||||
|
|
25
src/object.h
25
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue