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);
|
window_stack_push(s_code_window, true);
|
||||||
|
|
||||||
// If possible, load the previous code text
|
// 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);
|
// Object obj2 = parseEval("(map ad (1 50 99))", &env);
|
||||||
// printObj(&obj);
|
// printObj(&obj);
|
||||||
// printObj(&obj2);
|
// printObj(&obj2);
|
||||||
cleanObject(&obj);
|
// cleanObject(&obj);
|
||||||
// cleanObject(&obj2);
|
// cleanObject(&obj2);
|
||||||
if(persist_exists(current_code)) {
|
if(persist_exists(current_code)) {
|
||||||
persist_read_string(current_code, mytext, SMAX_LENGTH);
|
persist_read_string(current_code, mytext, SMAX_LENGTH);
|
||||||
|
|
|
@ -17,12 +17,6 @@
|
||||||
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||||
#endif
|
#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
|
* Returns the length of a given list Object
|
||||||
* @param listObj The list to get the length of
|
* @param listObj The list to get the length of
|
||||||
|
@ -40,7 +34,7 @@ int listLength(const Object *listObj)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object len(Object obj1, Object ignore)
|
Object len(Object obj1, Object o_ignore, struct Environment *e_ignore)
|
||||||
{ return numberObject(listLength(&obj1)); }
|
{ return numberObject(listLength(&obj1)); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
25
src/object.h
25
src/object.h
|
@ -5,6 +5,19 @@
|
||||||
#define MAX_TOK_CNT 128 // 128
|
#define MAX_TOK_CNT 128 // 128
|
||||||
#define MAX_ENV_ELM 15 // 50
|
#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 {
|
enum errorCode {
|
||||||
MISMATCHED_PARENS,
|
MISMATCHED_PARENS,
|
||||||
BAD_LIST_OF_SYMBOL_STRINGS,
|
BAD_LIST_OF_SYMBOL_STRINGS,
|
||||||
|
@ -18,7 +31,8 @@ enum errorCode {
|
||||||
LAMBDA_ARGS_NOT_LIST,
|
LAMBDA_ARGS_NOT_LIST,
|
||||||
DID_NOT_FIND_SYMBOL,
|
DID_NOT_FIND_SYMBOL,
|
||||||
BAD_TYPE,
|
BAD_TYPE,
|
||||||
UNEXPECTED_FORM
|
UNEXPECTED_FORM,
|
||||||
|
LISTS_NOT_SAME_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
//#ifdef STANDALONE
|
//#ifdef STANDALONE
|
||||||
|
@ -35,7 +49,8 @@ static const char *errorText[] = {
|
||||||
"LAMBDA_ARGS_NOT_LIST",
|
"LAMBDA_ARGS_NOT_LIST",
|
||||||
"DID_NOT_FIND_SYMBOL",
|
"DID_NOT_FIND_SYMBOL",
|
||||||
"BAD_TYPE",
|
"BAD_TYPE",
|
||||||
"UNEXPECTED_FORM"
|
"UNEXPECTED_FORM",
|
||||||
|
"LISTS_NOT_SAME_SIZE"
|
||||||
};
|
};
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
|
@ -54,6 +69,8 @@ typedef enum Type {
|
||||||
typedef struct Object Object;
|
typedef struct Object Object;
|
||||||
struct Lambda;
|
struct Lambda;
|
||||||
|
|
||||||
|
struct Environment;
|
||||||
|
|
||||||
struct Object {
|
struct Object {
|
||||||
Type type;
|
Type type;
|
||||||
Object *forward;
|
Object *forward;
|
||||||
|
@ -61,7 +78,7 @@ struct Object {
|
||||||
int number;
|
int number;
|
||||||
Object *list;
|
Object *list;
|
||||||
char name[MAX_TOK_LEN];
|
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?
|
struct Lambda *lambda; // Maybe better as not a pointer?
|
||||||
enum errorCode err;
|
enum errorCode err;
|
||||||
};
|
};
|
||||||
|
@ -107,6 +124,6 @@ Object errorObject(enum errorCode err);
|
||||||
Object constructLambda(const Object *params, const Object *body);
|
Object constructLambda(const Object *params, const Object *body);
|
||||||
|
|
||||||
// Object version of listLength()
|
// Object version of listLength()
|
||||||
Object len(Object obj1, Object ignore);
|
Object len(Object obj1, Object, struct Environment *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -118,7 +118,6 @@ Object evalDefArgs(const Object *arg_forms, struct Environment *env)
|
||||||
const Object *first_form = arg_forms;
|
const Object *first_form = arg_forms;
|
||||||
const char *name = first_form->name;
|
const char *name = first_form->name;
|
||||||
|
|
||||||
// Immediately adding the function to the env might allow recursion?
|
|
||||||
Object second_eval = eval(first_form->forward, env);
|
Object second_eval = eval(first_form->forward, env);
|
||||||
|
|
||||||
addToEnv(env, name, second_eval);
|
addToEnv(env, name, second_eval);
|
||||||
|
@ -210,7 +209,6 @@ Object evalBuiltIns(const Object *first, const Object *rest,
|
||||||
if(strcmp(first->name, "def") == 0) {
|
if(strcmp(first->name, "def") == 0) {
|
||||||
return evalDefArgs(rest, env);
|
return evalDefArgs(rest, env);
|
||||||
} else if(strcmp(first->name, "if") == 0) {
|
} else if(strcmp(first->name, "if") == 0) {
|
||||||
// Seems `rest` is the next *input*, not the next list item
|
|
||||||
return evalIfArgs(rest, env);
|
return evalIfArgs(rest, env);
|
||||||
} else if(strcmp(first->name, "fn") == 0) {
|
} else if(strcmp(first->name, "fn") == 0) {
|
||||||
return evalLambdaArgs(rest);
|
return evalLambdaArgs(rest);
|
||||||
|
@ -252,7 +250,7 @@ Object eval(const Object *obj, struct Environment *env)
|
||||||
Object *first_form = obj->list;
|
Object *first_form = obj->list;
|
||||||
|
|
||||||
{ // Try to eval built-ins
|
{ // Try to eval built-ins
|
||||||
Object built_in =
|
const Object built_in =
|
||||||
evalBuiltIns(first_form, first_form->forward, env);
|
evalBuiltIns(first_form, first_form->forward, env);
|
||||||
|
|
||||||
// deleteList(obj); // Decreases indirectly lost memory, but fails on Pebble
|
// 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];
|
Object func_eval = rest[0];
|
||||||
for(int i = 1; i < length; i++) {
|
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
|
// deleteList(obj); // Decreases indirectly lost memory, but fails on Pebble
|
||||||
return func_eval;
|
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 n1 = obj1->number;
|
||||||
const int n2 = obj2->number;
|
const int n2 = obj2->number;
|
||||||
|
@ -381,9 +379,39 @@ Object basicOp(Object *obj1, Object *obj2, const char op)
|
||||||
return *obj1;
|
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) \
|
#define bopf(_name, _char) \
|
||||||
Object _name(Object obj1, Object obj2) \
|
Object _name(Object obj1, Object obj2, struct Environment *env) \
|
||||||
{ return basicOp(&obj1, &obj2, _char); }
|
{ return basicOp(&obj1, &obj2, _char, env); }
|
||||||
|
|
||||||
bopf(add, '+');
|
bopf(add, '+');
|
||||||
bopf(sub, '-');
|
bopf(sub, '-');
|
||||||
|
@ -393,7 +421,7 @@ bopf(equ, '=');
|
||||||
bopf(gth, '>');
|
bopf(gth, '>');
|
||||||
bopf(lth, '<');
|
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)
|
struct Environment *env)
|
||||||
{
|
{
|
||||||
Object o = newObject(TYPE_FUNC);
|
Object o = newObject(TYPE_FUNC);
|
||||||
|
|
|
@ -50,7 +50,6 @@ struct Environment envForLambda(const Object *params, const Object *arg_forms,
|
||||||
struct Environment *outer);
|
struct Environment *outer);
|
||||||
|
|
||||||
Result result(Object obj, struct Slice *slices);
|
Result result(Object obj, struct Slice *slices);
|
||||||
Object add(Object obj1, Object obj2);
|
|
||||||
|
|
||||||
// Slices
|
// Slices
|
||||||
void copySlice(char * dest, struct Slice *src);
|
void copySlice(char * dest, struct Slice *src);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define TOKENS_H
|
#define TOKENS_H
|
||||||
|
|
||||||
#include "pebblisp.h"
|
#include "pebblisp.h"
|
||||||
|
|
||||||
int isSingle(const char c);
|
int isSingle(const char c);
|
||||||
int isDigit(const char c);
|
int isDigit(const char c);
|
||||||
struct Slice *nf_tokenize(const char *input);
|
struct Slice *nf_tokenize(const char *input);
|
||||||
|
|
Loading…
Reference in New Issue