Busted `map` with less malloc
This commit is contained in:
parent
4bc3337dcd
commit
a286943984
|
@ -3,3 +3,6 @@ all:
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
gcc -g -O0 -o pebblisp -D STANDALONE -D DEBUG pebblisp.c tokens.c object.c
|
gcc -g -O0 -o pebblisp -D STANDALONE -D DEBUG pebblisp.c tokens.c object.c
|
||||||
|
|
||||||
|
phrase:
|
||||||
|
gcc -g -O0 -o pebblisp -D STANDALONE -D DEBUG -D NO_REPL pebblisp.c tokens.c object.c
|
||||||
|
|
13
src/calc.c
13
src/calc.c
|
@ -1,6 +1,5 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
//#include "fixed.h"
|
|
||||||
#include "calc.h"
|
#include "calc.h"
|
||||||
|
|
||||||
static inline int8_t tokenCount() {
|
static inline int8_t tokenCount() {
|
||||||
|
@ -71,10 +70,10 @@ static void enter(){
|
||||||
// Calculate result, display it and reset
|
// Calculate result, display it and reset
|
||||||
static void calculate(){
|
static void calculate(){
|
||||||
Object obj = parseEval(mytext, &env);
|
Object obj = parseEval(mytext, &env);
|
||||||
char temp[MAX_LENGTH-2] = "";
|
char temp[RESULT_LENGTH-2] = "";
|
||||||
|
|
||||||
stringObj(temp, &obj);
|
stringObj(temp, &obj);
|
||||||
snprintf(resulttext, MAX_LENGTH, "R:%s", temp);
|
snprintf(resulttext, RESULT_LENGTH, "R:%s", temp);
|
||||||
selected_token = 0;
|
selected_token = 0;
|
||||||
text_layer_set_text(s_result_text_layer, resulttext);
|
text_layer_set_text(s_result_text_layer, resulttext);
|
||||||
}
|
}
|
||||||
|
@ -191,6 +190,14 @@ 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) (+ 1 a)))", &env);
|
||||||
|
Object obj2 = parseEval("(map ad (1 2 3))", &env);
|
||||||
|
printObj(&obj);
|
||||||
|
printObj(&obj2);
|
||||||
|
cleanObject(&obj);
|
||||||
|
cleanObject(&obj2);
|
||||||
|
if(1)
|
||||||
|
return;
|
||||||
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);
|
||||||
updateText();
|
updateText();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "pebblisp.h"
|
#include "pebblisp.h"
|
||||||
|
|
||||||
#define SMAX_LENGTH 256
|
#define SMAX_LENGTH 256
|
||||||
#define MAX_LENGTH 11
|
#define RESULT_LENGTH 20
|
||||||
#define END_PHRASE "END"
|
#define END_PHRASE "END"
|
||||||
|
|
||||||
#define NUM_ROWS 5
|
#define NUM_ROWS 5
|
||||||
|
@ -33,7 +33,7 @@ char mytext[SMAX_LENGTH] = "";
|
||||||
char temptext[SMAX_LENGTH] = "";
|
char temptext[SMAX_LENGTH] = "";
|
||||||
|
|
||||||
// The result of execution
|
// The result of execution
|
||||||
char resulttext[MAX_LENGTH] = "";
|
char resulttext[RESULT_LENGTH] = "";
|
||||||
|
|
||||||
char *tokens[] = {
|
char *tokens[] = {
|
||||||
" ", "(", ")",
|
" ", "(", ")",
|
||||||
|
@ -43,7 +43,7 @@ char *tokens[] = {
|
||||||
"7","8","9", "0",
|
"7","8","9", "0",
|
||||||
"a", "b", "c", "d", "e",
|
"a", "b", "c", "d", "e",
|
||||||
"= ", "< ", "> ",
|
"= ", "< ", "> ",
|
||||||
"fn", "def", "if", "\n",
|
"map", "fn", "def", "if", "\n",
|
||||||
END_PHRASE
|
END_PHRASE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
87
src/object.c
87
src/object.c
|
@ -3,6 +3,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define RESULT_LENGTH 20
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define printd(...) printf(__VA_ARGS__)
|
#define printd(...) printf(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
|
@ -10,7 +12,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
#define printf(...) stringObj(NULL, NULL)
|
#include <pebble.h>
|
||||||
|
#undef printf
|
||||||
|
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int listLength(const Object *listObj)
|
int listLength(const Object *listObj)
|
||||||
|
@ -126,8 +130,16 @@ void insertIntoList(Object *dest, int ind, const Object src)
|
||||||
march->forward->forward = oldForward;
|
march->forward->forward = oldForward;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void replaceListing(Object *list, int i, const Object src)
|
||||||
|
{
|
||||||
|
if(!list)
|
||||||
|
return;
|
||||||
|
list[i] = src;
|
||||||
|
list[i].forward = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Adds an object to the end of a list object
|
// Adds an object to the end of a list object
|
||||||
void addToList(Object *dest, const Object src)
|
void nf_addToList(Object *dest, const Object src)
|
||||||
{
|
{
|
||||||
if(!dest || dest->type != TYPE_LIST)
|
if(!dest || dest->type != TYPE_LIST)
|
||||||
return;
|
return;
|
||||||
|
@ -143,38 +155,57 @@ void addToList(Object *dest, const Object src)
|
||||||
|
|
||||||
void printErr(const Object *obj)
|
void printErr(const Object *obj)
|
||||||
{
|
{
|
||||||
#ifdef STANDALONE
|
//#ifdef STANDALONE
|
||||||
if(!obj || obj->type != TYPE_ERROR)
|
if(!obj || obj->type != TYPE_ERROR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printf("%s\n", errorText[(int)(obj->err)]);
|
printf("%s\n", errorText[(int)(obj->err)]);
|
||||||
#endif
|
//#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stringList(char *dest, const Object *obj)
|
||||||
|
{
|
||||||
|
dest[0] = '(';
|
||||||
|
dest[1] = '\0';
|
||||||
|
|
||||||
|
const Object *tail = obj->list;
|
||||||
|
while(tail != NULL) {
|
||||||
|
printf("%s\n", dest);
|
||||||
|
strcat(dest, " ");
|
||||||
|
char tok[90] = "";
|
||||||
|
stringObj(tok, tail);
|
||||||
|
strcat(dest, tok);
|
||||||
|
tail = tail->forward;
|
||||||
|
}
|
||||||
|
strcat(dest, " )");
|
||||||
|
}
|
||||||
|
|
||||||
// Puts a string version of the given object into a given string
|
// Puts a string version of the given object into a given string
|
||||||
char* stringObj(char *dest, const Object *obj)
|
char* stringObj(char *dest, const Object *obj)
|
||||||
{
|
{
|
||||||
if(!dest || !obj)
|
if(!dest || !obj)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if(obj->type == TYPE_NUMBER) {
|
const Type t = obj->type;
|
||||||
snprintf(dest, MAX_TOK_LEN, "%d", obj->number);
|
|
||||||
} else if(obj->type == TYPE_SYMBOL) {
|
if(t == TYPE_NUMBER) {
|
||||||
snprintf(dest, MAX_TOK_LEN, "%s", obj->name);
|
snprintf(dest, RESULT_LENGTH, "%d", obj->number);
|
||||||
} else if(obj->type == TYPE_BOOL) {
|
} else if(t == TYPE_SYMBOL) {
|
||||||
snprintf(dest, MAX_TOK_LEN, "%s", obj->number ? "T" : "F");
|
snprintf(dest, RESULT_LENGTH, "%s", obj->name);
|
||||||
} else if(obj->type == TYPE_ERROR) {
|
} else if(t == TYPE_BOOL) {
|
||||||
snprintf(dest, MAX_TOK_LEN, "E%d", obj->err);
|
snprintf(dest, RESULT_LENGTH, "%s", obj->number ? "T" : "F");
|
||||||
|
} else if(t == TYPE_ERROR) {
|
||||||
|
snprintf(dest, RESULT_LENGTH, "E%d", obj->err);
|
||||||
|
} else if(t == TYPE_LIST) {
|
||||||
|
stringList(dest, obj);
|
||||||
} else {
|
} else {
|
||||||
snprintf(dest, MAX_TOK_LEN, "%d", obj->number);
|
snprintf(dest, RESULT_LENGTH, "%d", obj->number);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
int depth = 0;
|
|
||||||
|
|
||||||
void debugObj(const Object *obj)
|
void debugObj(const Object *obj)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -186,38 +217,28 @@ void debugObj(const Object *obj)
|
||||||
void _printList(const Object *list, int newline);
|
void _printList(const Object *list, int newline);
|
||||||
void _printObj(const Object *obj, int newline)
|
void _printObj(const Object *obj, int newline)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < depth; i++)
|
|
||||||
printd(" ");
|
|
||||||
depth++;
|
|
||||||
|
|
||||||
if(obj->type == TYPE_NUMBER) {
|
if(obj->type == TYPE_NUMBER) {
|
||||||
printd("TYPE_NUMBER");
|
printd("TYPE_NUMBER");
|
||||||
} else if(obj->type == TYPE_BOOL) {
|
} else if(obj->type == TYPE_BOOL) {
|
||||||
printd("TYPE_BOOL");
|
printd("TYPE_BOOL");
|
||||||
} else if(obj->type == TYPE_LIST) {
|
} else if(obj->type == TYPE_LIST) {
|
||||||
printd("TYPE_LIST\n");
|
printd("TYPE_LIST\n");
|
||||||
_printList(obj, newline);
|
|
||||||
depth--;
|
|
||||||
return;
|
|
||||||
} else if(obj->type == TYPE_FUNC) {
|
} else if(obj->type == TYPE_FUNC) {
|
||||||
printd("TYPE_FUNC");
|
printd("TYPE_FUNC");
|
||||||
} else if(obj->type == TYPE_SYMBOL) {
|
} else if(obj->type == TYPE_SYMBOL) {
|
||||||
printd("TYPE_SYMBOL");
|
printd("TYPE_SYMBOL");
|
||||||
} else if(obj->type == TYPE_LAMBDA) {
|
} else if(obj->type == TYPE_LAMBDA) {
|
||||||
printd("TYPE_LAMBDA Params:\n");
|
printd("TYPE_LAMBDA Params:\n");
|
||||||
depth++;
|
|
||||||
printObj(&obj->lambda->params);
|
printObj(&obj->lambda->params);
|
||||||
for(int i = 1; i < depth; i++)
|
|
||||||
printf(" ");
|
|
||||||
printd("Lambda Body: \n");
|
printd("Lambda Body: \n");
|
||||||
printObj(&obj->lambda->body);
|
printObj(&obj->lambda->body);
|
||||||
|
return;
|
||||||
} else if(obj->type == TYPE_ERROR) {
|
} else if(obj->type == TYPE_ERROR) {
|
||||||
printd("TYPE_ERROR: ");
|
printd("TYPE_ERROR: ");
|
||||||
} else {
|
} else {
|
||||||
printd("TYPE_OTHER (as int)");
|
printd("TYPE_OTHER (as int)");
|
||||||
}
|
}
|
||||||
depth--;
|
char temp[100] = "";
|
||||||
char temp[20] = "";
|
|
||||||
stringObj(temp, obj);
|
stringObj(temp, obj);
|
||||||
if(newline)
|
if(newline)
|
||||||
printf("%s\n", temp);
|
printf("%s\n", temp);
|
||||||
|
@ -238,9 +259,7 @@ void _printList(const Object *list, int newline)
|
||||||
const Object *tail = list->list;
|
const Object *tail = list->list;
|
||||||
while(tail != NULL) {
|
while(tail != NULL) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
depth++;
|
|
||||||
_printObj(tail, 0);
|
_printObj(tail, 0);
|
||||||
depth--;
|
|
||||||
tail = tail->forward;
|
tail = tail->forward;
|
||||||
}
|
}
|
||||||
printf(" )");
|
printf(" )");
|
||||||
|
@ -261,12 +280,20 @@ void cleanObject(Object *target)
|
||||||
|
|
||||||
const Type t = target->type;
|
const Type t = target->type;
|
||||||
if(t == TYPE_LAMBDA) {
|
if(t == TYPE_LAMBDA) {
|
||||||
|
cleanObject(&target->lambda->params);
|
||||||
|
cleanObject(&target->lambda->body);
|
||||||
free(target->lambda);
|
free(target->lambda);
|
||||||
} else if(t == TYPE_LIST) {
|
} else if(t == TYPE_LIST) {
|
||||||
deleteList(target);
|
deleteList(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printAndClean(Object *target)
|
||||||
|
{
|
||||||
|
printObj(target);
|
||||||
|
cleanObject(target);
|
||||||
|
}
|
||||||
|
|
||||||
// Frees all objects in a list
|
// Frees all objects in a list
|
||||||
void deleteList(const Object *dest)
|
void deleteList(const Object *dest)
|
||||||
{
|
{
|
||||||
|
@ -297,7 +324,7 @@ void copyList(Object *dest, const Object *src)
|
||||||
deleteList(dest);
|
deleteList(dest);
|
||||||
const Object *march = src->list;
|
const Object *march = src->list;
|
||||||
while(march != NULL) {
|
while(march != NULL) {
|
||||||
addToList(dest, *march);
|
nf_addToList(dest, *march);
|
||||||
march = march->forward;
|
march = march->forward;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
41
src/object.h
41
src/object.h
|
@ -12,24 +12,30 @@ enum errorCode {
|
||||||
BUILT_IN_NOT_FOUND,
|
BUILT_IN_NOT_FOUND,
|
||||||
NULL_PARSE,
|
NULL_PARSE,
|
||||||
NULL_LAMBDA_LIST,
|
NULL_LAMBDA_LIST,
|
||||||
|
NULL_MAP_ARGS,
|
||||||
LAMBDA_ARGS_NOT_LIST,
|
LAMBDA_ARGS_NOT_LIST,
|
||||||
DID_NOT_FIND_SYMBOL,
|
DID_NOT_FIND_SYMBOL,
|
||||||
|
BAD_TYPE,
|
||||||
UNEXPECTED_FORM
|
UNEXPECTED_FORM
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef STANDALONE
|
//#ifdef STANDALONE
|
||||||
static const char *errorText[] = {
|
static const char *errorText[] = {
|
||||||
"BAD_LIST_OF_SYMBOL_STRINGS",
|
"BAD_LIST_OF_SYMBOL_STRINGS",
|
||||||
"TYPE_LIST_NOT_CAUGHT",
|
"TYPE_LIST_NOT_CAUGHT",
|
||||||
"NULL_ENV",
|
"NULL_ENV",
|
||||||
"BUILT_IN_NOT_FOUND",
|
"BUILT_IN_NOT_FOUND",
|
||||||
"NULL_PARSE",
|
"NULL_PARSE",
|
||||||
"NULL_LAMBDA_LIST",
|
"NULL_LAMBDA_LIST",
|
||||||
"LAMBDA_ARGS_NOT_LIST",
|
"NULL_MAP_ARGS",
|
||||||
"DID_NOT_FIND_SYMBOL",
|
"LAMBDA_ARGS_NOT_LIST",
|
||||||
"UNEXPECTED_FORM"
|
"DID_NOT_FIND_SYMBOL",
|
||||||
};
|
"BAD_TYPE",
|
||||||
#endif
|
"UNEXPECTED_FORM"
|
||||||
|
};
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
#define MALLOC_FLAG 64
|
||||||
|
|
||||||
typedef enum Type {
|
typedef enum Type {
|
||||||
TYPE_NUMBER,
|
TYPE_NUMBER,
|
||||||
|
@ -38,7 +44,7 @@ typedef enum Type {
|
||||||
TYPE_FUNC,
|
TYPE_FUNC,
|
||||||
TYPE_SYMBOL,
|
TYPE_SYMBOL,
|
||||||
TYPE_LAMBDA,
|
TYPE_LAMBDA,
|
||||||
TYPE_ERROR // Currently unused
|
TYPE_ERROR
|
||||||
} Type;
|
} Type;
|
||||||
|
|
||||||
typedef struct Object Object;
|
typedef struct Object Object;
|
||||||
|
@ -67,16 +73,21 @@ char* stringObj(char *dest, const Object *obj);
|
||||||
void printList(const Object *list);
|
void printList(const Object *list);
|
||||||
void printObj(const Object *obj);
|
void printObj(const Object *obj);
|
||||||
void debugObj(const Object *obj);
|
void debugObj(const Object *obj);
|
||||||
|
void printErr(const Object *obj);
|
||||||
|
int wasMalloc(const Object *obj);
|
||||||
|
int getType(const Object *obj);
|
||||||
|
|
||||||
int isEmpty(const Object *obj);
|
int isEmpty(const Object *obj);
|
||||||
Object *tail(const Object *listObj);
|
Object *tail(const Object *listObj);
|
||||||
void addToList(Object *dest, Object src);
|
void replaceListing(Object *list, int i, const Object src);
|
||||||
|
void nf_addToList(Object *dest, Object src);
|
||||||
void deleteList(const Object *dest);
|
void deleteList(const Object *dest);
|
||||||
int listLength(const Object *listObj);
|
int listLength(const Object *listObj);
|
||||||
Object *itemAt(const Object *listObj, int n);
|
Object *itemAt(const Object *listObj, int n);
|
||||||
void copyList(Object *dest, const Object *src);
|
void copyList(Object *dest, const Object *src);
|
||||||
|
|
||||||
void cleanObject(Object *target);
|
void cleanObject(Object *target);
|
||||||
|
void printAndClean(Object *target);
|
||||||
void allocObject(Object **spot, const Object src);
|
void allocObject(Object **spot, const Object src);
|
||||||
|
|
||||||
Object newObject(Type type);
|
Object newObject(Type type);
|
||||||
|
|
197
src/pebblisp.c
197
src/pebblisp.c
|
@ -4,6 +4,11 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef STANDALONE
|
||||||
|
#undef printf
|
||||||
|
#define printf(...) APP_LOG(APP_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
void copySlice(char * dest, struct Slice *src)
|
void copySlice(char * dest, struct Slice *src)
|
||||||
{
|
{
|
||||||
if(!dest || !src)
|
if(!dest || !src)
|
||||||
|
@ -29,14 +34,12 @@ Object fetchFromEnvironment(const char *name, struct Environment *env)
|
||||||
|
|
||||||
printd("Fetching '%s' from env\n", name);
|
printd("Fetching '%s' from env\n", name);
|
||||||
printEnv(env);
|
printEnv(env);
|
||||||
int i = 0;
|
for(int i = 0; i < env->size; i++) {
|
||||||
const char *next = env->strings[i];
|
if(strcmp(name, env->strings[i]) == 0) {
|
||||||
while(next != NULL) {
|
|
||||||
if(strcmp(name, next) == 0) {
|
|
||||||
return env->objects[i];
|
return env->objects[i];
|
||||||
}
|
}
|
||||||
next = env->strings[++i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printd("Trying outer\n");
|
printd("Trying outer\n");
|
||||||
if(env->outer) {
|
if(env->outer) {
|
||||||
return fetchFromEnvironment(name, env->outer);
|
return fetchFromEnvironment(name, env->outer);
|
||||||
|
@ -52,14 +55,14 @@ Result parse(struct Slice *slices)
|
||||||
if(token->text != NULL) {
|
if(token->text != NULL) {
|
||||||
rest = &slices[1];
|
rest = &slices[1];
|
||||||
} else {
|
} else {
|
||||||
return R(errorObject(NULL_PARSE), NULL);
|
return result(errorObject(NULL_PARSE), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(token->text[0] == '(') {
|
if(token->text[0] == '(') {
|
||||||
// todo check for null rest
|
// todo check for null rest
|
||||||
return readSeq(rest);
|
return readSeq(rest);
|
||||||
} else { // todo error on closed paren
|
} else { // todo error on closed paren
|
||||||
return R(parseAtom(token), rest);
|
return result(parseAtom(token), rest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,10 +73,10 @@ Result readSeq(struct Slice *tokens)
|
||||||
struct Slice *next = &tokens[0];
|
struct Slice *next = &tokens[0];
|
||||||
struct Slice *rest = next->text? &next[1] : NULL;
|
struct Slice *rest = next->text? &next[1] : NULL;
|
||||||
if(next->text[0] == ')') {
|
if(next->text[0] == ')') {
|
||||||
return R(res, rest);
|
return result(res, rest);
|
||||||
}
|
}
|
||||||
Result r = parse(tokens);
|
Result r = parse(tokens);
|
||||||
addToList(&res, r.obj);
|
nf_addToList(&res, r.obj);
|
||||||
tokens = r.slices;
|
tokens = r.slices;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,37 +129,100 @@ Object evalLambdaArgs(const Object *arg_forms)
|
||||||
return constructLambda(arg_forms, arg_forms->forward);
|
return constructLambda(arg_forms, arg_forms->forward);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object evalMapArgs(const Object *arg_forms)
|
//Object evalMapArgs(Object *newList, const Object *arg_forms,
|
||||||
|
void evalMapArgs(Object *newList, const Object *arg_forms,
|
||||||
|
struct Environment *env)
|
||||||
{
|
{
|
||||||
return listObject();
|
if(!arg_forms)
|
||||||
|
return; // errorObject(NULL_MAP_ARGS);
|
||||||
|
|
||||||
|
const Object lambda = eval(&arg_forms[0], env);
|
||||||
|
Object *oldList = (&arg_forms[0])->forward;
|
||||||
|
printf("lambda\n");
|
||||||
|
printObj(&lambda);
|
||||||
|
printf("oldList\n");
|
||||||
|
printObj(oldList);
|
||||||
|
printf("END oldList\n");
|
||||||
|
|
||||||
|
if(lambda.type != TYPE_LAMBDA || oldList->type != TYPE_LIST) {
|
||||||
|
return; // errorObject(BAD_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object list = listObject();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
Object *oldElement = oldList->list;
|
||||||
|
while(oldElement != NULL) {
|
||||||
|
// Create a new list for each element in the list,
|
||||||
|
// since lambda evaluation looks for a list
|
||||||
|
Object tempList = listObject();
|
||||||
|
Object listBack[1] = {*oldElement};
|
||||||
|
listBack[0].forward = NULL;
|
||||||
|
tempList.list = listBack;
|
||||||
|
printObj(&tempList);
|
||||||
|
printf("END &tempList\n");
|
||||||
|
|
||||||
|
//nf_addToList(&tempList, *oldElement);
|
||||||
|
|
||||||
|
struct Environment newEnv =
|
||||||
|
envForLambda(&lambda.lambda->params, &tempList, env);
|
||||||
|
const Object evalLambda = eval(&lambda.lambda->body, &newEnv);
|
||||||
|
// cleanObject(&tempList); // Don't let tempList linger
|
||||||
|
|
||||||
|
//nf_addToList(&list, evalLambda);
|
||||||
|
newList[i++] = evalLambda;
|
||||||
|
printf("VVVVVVnewList[%d]\n", i - 1);
|
||||||
|
printObj(&newList[i-1]);
|
||||||
|
printf("^^^^^^newList[%d]\n", i - 1);
|
||||||
|
oldElement = oldElement->forward;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j = 0; j < i - 1; j++) {
|
||||||
|
newList[j].forward = &newList[j+1];
|
||||||
|
}
|
||||||
|
newList[i-1].forward = NULL;
|
||||||
|
|
||||||
|
//printf("return list\n");
|
||||||
|
//return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Environment envForLambda(const Object *params, const Object *arg_forms,
|
struct Environment envForLambda(const Object *params, const Object *arg_forms,
|
||||||
struct Environment *outer)
|
struct Environment *outer)
|
||||||
{
|
{
|
||||||
printd("\n#####################\nenvForLambda()\n");
|
printd("\n#####################");
|
||||||
|
printf("envForLambda()\n");
|
||||||
debugObj(arg_forms);
|
debugObj(arg_forms);
|
||||||
|
|
||||||
|
int length = listLength(params);
|
||||||
|
|
||||||
struct Environment env;
|
struct Environment env;
|
||||||
env.outer = outer;
|
env.outer = outer;
|
||||||
env.strings = NULL;
|
env.strings = NULL;
|
||||||
env.objects = NULL;
|
env.objects = NULL;
|
||||||
|
env.size = length;
|
||||||
int length = listLength(params);
|
|
||||||
|
|
||||||
if(length == 0)
|
if(length == 0)
|
||||||
return env;
|
return env;
|
||||||
|
|
||||||
env.strings = calloc(sizeof(char*), length);
|
env.strings = calloc(sizeof(char*), length + 1);
|
||||||
env.objects = malloc(sizeof(Object) * length);
|
env.objects = malloc(sizeof(Object) * length + 1);
|
||||||
|
|
||||||
Object vs[length];
|
Object vs[length];
|
||||||
eval_forms(vs, arg_forms, outer);
|
eval_forms(vs, arg_forms, outer);
|
||||||
|
printf("WHICH/ONE\n");
|
||||||
|
for(int i = 0; i < length; i++) {
|
||||||
|
//printObj(&vs[i]);
|
||||||
|
printObj(&arg_forms[i]);
|
||||||
|
}
|
||||||
|
printf("END WHICH/ONE\n");
|
||||||
|
|
||||||
for(int i = 0; i < length; i++) {
|
for(int i = 0; i < length; i++) {
|
||||||
const char *n = itemAt(params, i)->name;
|
const char *n = itemAt(params, i)->name;
|
||||||
addToEnv(&env, n, eval(&arg_forms[i], outer)); // May not need eval?
|
addToEnv(&env, n, eval(&arg_forms[i], outer)); // May not need eval?
|
||||||
|
// SHOULD BE `vs` not arg_forms???
|
||||||
|
|
||||||
} // Something is segfaulting, anyway
|
} // Something is segfaulting, anyway
|
||||||
env.strings[length] = NULL;
|
// env.strings[length] = NULL;
|
||||||
|
|
||||||
printd("envForLambda env IT BROKE HERE()\n");
|
printd("envForLambda env IT BROKE HERE()\n");
|
||||||
printd("envForLambda length=%d\n", length);
|
printd("envForLambda length=%d\n", length);
|
||||||
|
@ -174,8 +240,17 @@ Object evalBuiltIns(const Object *first, const Object *rest,
|
||||||
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);
|
||||||
} else if(strcmp(first->name, "mp") == 0) {
|
} else if(strcmp(first->name, "map") == 0) {
|
||||||
return evalMapArgs(rest);
|
printf("MAP BUILT-IN\n");
|
||||||
|
int length = listLength(rest->forward);
|
||||||
|
Object newList = listObject();
|
||||||
|
//Object listBack[length];
|
||||||
|
//newList.list = listBack;
|
||||||
|
evalMapArgs(listBack, rest, env);
|
||||||
|
printf("print evalMapArgs() obj\n");
|
||||||
|
printObj(&newList);
|
||||||
|
printf("MAP BUILT-IN\n");
|
||||||
|
return newList;
|
||||||
}
|
}
|
||||||
|
|
||||||
return errorObject(BUILT_IN_NOT_FOUND);
|
return errorObject(BUILT_IN_NOT_FOUND);
|
||||||
|
@ -191,7 +266,7 @@ void eval_forms(Object *destList, const Object *src, struct Environment *env)
|
||||||
|
|
||||||
Object eval(const Object *obj, struct Environment *env)
|
Object eval(const Object *obj, struct Environment *env)
|
||||||
{
|
{
|
||||||
printd("eval():\n");
|
printf("eval():\n");
|
||||||
debugObj(obj);
|
debugObj(obj);
|
||||||
switch(obj->type) {
|
switch(obj->type) {
|
||||||
case TYPE_NUMBER:
|
case TYPE_NUMBER:
|
||||||
|
@ -214,10 +289,11 @@ Object eval(const Object *obj, struct Environment *env)
|
||||||
{ // Try to eval built-ins
|
{ // Try to eval built-ins
|
||||||
Object built_in =
|
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
|
||||||
if(built_in.type != TYPE_ERROR)
|
if(built_in.type != TYPE_ERROR) {
|
||||||
return built_in;
|
return built_in;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object first_eval = eval(first_form, env);
|
Object first_eval = eval(first_form, env);
|
||||||
|
@ -236,7 +312,9 @@ Object eval(const Object *obj, struct Environment *env)
|
||||||
} else if (first_eval.type == TYPE_LAMBDA) {
|
} else if (first_eval.type == TYPE_LAMBDA) {
|
||||||
struct Environment newEnv =
|
struct Environment newEnv =
|
||||||
envForLambda(&first_eval.lambda->params, first_form->forward, env);
|
envForLambda(&first_eval.lambda->params, first_form->forward, env);
|
||||||
return eval(&first_eval.lambda->body, &newEnv);
|
Object ret = eval(&first_eval.lambda->body, &newEnv);
|
||||||
|
deleteEnv(&newEnv);
|
||||||
|
return ret;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return *obj;
|
return *obj;
|
||||||
|
@ -251,31 +329,47 @@ Object eval(const Object *obj, struct Environment *env)
|
||||||
return *obj;
|
return *obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result resultFromObjAndSlices(Object obj, struct Slice *slices)
|
Result result(Object obj, struct Slice *slices)
|
||||||
{
|
{
|
||||||
Result r;
|
return (Result) {
|
||||||
r.obj = obj;
|
.obj = obj,
|
||||||
r.slices = slices;
|
.slices = slices
|
||||||
return r;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo could include and return a starting index for faster multi-adds
|
// todo could include and return a starting index for faster multi-adds
|
||||||
|
// Maybe extend existing environment using a malloc'd outer, instead of realloc
|
||||||
void addToEnv(struct Environment *env, const char *name, const Object obj)
|
void addToEnv(struct Environment *env, const char *name, const Object obj)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < MAX_ENV_ELM; i++) {
|
//printf("sizeof(char)=%d * strlen(name)=%d\n", (int)sizeof(char), (int)strlen(name));
|
||||||
|
for(i = 0; i < env->size ; i++) {
|
||||||
if(env->strings[i] == NULL) {
|
if(env->strings[i] == NULL) {
|
||||||
env->strings[i] = malloc(sizeof(name));
|
env->strings[i] = malloc(strlen(name) + 1);
|
||||||
strncpy(env->strings[i], name, MAX_TOK_LEN);
|
strncpy(env->strings[i], name, strlen(name));
|
||||||
env->objects[i] = obj;
|
env->objects[i] = obj;
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
if(strcmp(env->strings[i], name) == 0) {
|
if(strcmp(env->strings[i], name) == 0) {
|
||||||
cleanObject(&env->objects[i]);
|
cleanObject(&env->objects[i]);
|
||||||
env->objects[i] = obj;
|
env->objects[i] = obj;
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printd("Reallocating environment\n");
|
||||||
|
const int inc = 5;
|
||||||
|
env->size += inc;
|
||||||
|
env->strings = realloc(env->strings, sizeof(char*) * env->size);
|
||||||
|
env->objects = realloc(env->objects, sizeof(Object) * env->size);
|
||||||
|
|
||||||
|
for(int j = 0; j < inc; j++) {
|
||||||
|
env->strings[i + j] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
env->strings[i] = malloc(strlen(name) + 1);
|
||||||
|
strncpy(env->strings[i], name, strlen(name));
|
||||||
|
env->objects[i] = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printEnv(struct Environment *env)
|
void printEnv(struct Environment *env)
|
||||||
|
@ -284,7 +378,7 @@ void printEnv(struct Environment *env)
|
||||||
printd("NULL env\n");
|
printd("NULL env\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for(int i = 0; i < MAX_ENV_ELM; i++) {
|
for(int i = 0; i < env->size; i++) {
|
||||||
if(env->strings[i] == NULL)
|
if(env->strings[i] == NULL)
|
||||||
return;
|
return;
|
||||||
printd("env[%d]: '%s'\n ", i, env->strings[i]);
|
printd("env[%d]: '%s'\n ", i, env->strings[i]);
|
||||||
|
@ -345,6 +439,7 @@ void deleteEnv(struct Environment *e)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(e->strings[i]) {
|
while(e->strings[i]) {
|
||||||
free(e->strings[i]);
|
free(e->strings[i]);
|
||||||
|
cleanObject(&e->objects[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
free(e->strings);
|
free(e->strings);
|
||||||
|
@ -357,10 +452,11 @@ void deleteEnv(struct Environment *e)
|
||||||
struct Environment defaultEnv() {
|
struct Environment defaultEnv() {
|
||||||
struct Environment e;
|
struct Environment e;
|
||||||
e.outer = NULL;
|
e.outer = NULL;
|
||||||
e.strings = malloc(sizeof(char*) * MAX_ENV_ELM);
|
e.strings = calloc(sizeof(char*), MAX_ENV_ELM);
|
||||||
for(int i = 0; i < MAX_ENV_ELM; i++) {
|
e.size = MAX_ENV_ELM;
|
||||||
e.strings[i] = NULL;
|
// for(int i = 0; i < MAX_ENV_ELM; i++) {
|
||||||
}
|
// e.strings[i] = NULL;
|
||||||
|
// }
|
||||||
|
|
||||||
e.objects = malloc(sizeof(Object) * MAX_ENV_ELM);
|
e.objects = malloc(sizeof(Object) * MAX_ENV_ELM);
|
||||||
|
|
||||||
|
@ -391,7 +487,9 @@ Object parseEval(const char *input, struct Environment *env)
|
||||||
#endif
|
#endif
|
||||||
Object parsed = parse(tokens).obj;
|
Object parsed = parse(tokens).obj;
|
||||||
free(tokens);
|
free(tokens);
|
||||||
return eval(&parsed, env);
|
Object ret = eval(&parsed, env);
|
||||||
|
cleanObject(&parsed);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
|
@ -402,6 +500,7 @@ int repl(struct Environment *env)
|
||||||
printf("pebblisp>> ");
|
printf("pebblisp>> ");
|
||||||
fgets(input, 100, stdin);
|
fgets(input, 100, stdin);
|
||||||
Object obj = parseEval(input, env);
|
Object obj = parseEval(input, env);
|
||||||
|
// printAndClean(&obj);
|
||||||
printObj(&obj);
|
printObj(&obj);
|
||||||
// printEnv(env);
|
// printEnv(env);
|
||||||
}
|
}
|
||||||
|
@ -413,22 +512,10 @@ int main(void)
|
||||||
#ifndef NO_REPL
|
#ifndef NO_REPL
|
||||||
repl(&env);
|
repl(&env);
|
||||||
#else
|
#else
|
||||||
struct Slice *tokens = nf_tokenize("(+ 10 5)");
|
Object r = parseEval("(def ad (fn (a) (+ 1 a)))", &env);
|
||||||
struct Slice *debug = tokens;
|
printAndClean(&r);
|
||||||
|
r = parseEval("(map ad (1 2 3))", &env);
|
||||||
if(debug) {
|
//printAndClean(&r);
|
||||||
while(debug->text) {
|
|
||||||
char tok[10];
|
|
||||||
copySlice(tok, debug);
|
|
||||||
printf("'%s', ", tok);
|
|
||||||
debug++;
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
} else {
|
|
||||||
printf("parse error\n");
|
|
||||||
}
|
|
||||||
parse(tokens);
|
|
||||||
free(tokens);
|
|
||||||
#endif
|
#endif
|
||||||
deleteEnv(&env);
|
deleteEnv(&env);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#ifndef STANDALONE
|
#ifndef STANDALONE
|
||||||
#include <pebble.h>
|
#include <pebble.h>
|
||||||
// #define printf(...) copySlice(NULL, NULL)
|
|
||||||
#define printd(...) copySlice(NULL, NULL)
|
#define printd(...) copySlice(NULL, NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -29,6 +28,7 @@ struct Environment {
|
||||||
char **strings;
|
char **strings;
|
||||||
Object *objects;
|
Object *objects;
|
||||||
struct Environment *outer;
|
struct Environment *outer;
|
||||||
|
char size;
|
||||||
};
|
};
|
||||||
|
|
||||||
Object eval(const Object *obj, struct Environment *env);
|
Object eval(const Object *obj, struct Environment *env);
|
||||||
|
@ -46,14 +46,14 @@ void deleteEnv(struct Environment *e);
|
||||||
void addToEnv(struct Environment *env, const char *name, const Object obj);
|
void addToEnv(struct Environment *env, const char *name, const Object obj);
|
||||||
Object fetchFromEnvironment(const char *name, struct Environment *env);
|
Object fetchFromEnvironment(const char *name, struct Environment *env);
|
||||||
void printEnv(struct Environment *env);
|
void printEnv(struct Environment *env);
|
||||||
|
struct Environment envForLambda(const Object *params, const Object *arg_forms,
|
||||||
|
struct Environment *outer);
|
||||||
|
|
||||||
Result resultFromObjAndSlices(Object obj, struct Slice *slices);
|
Result result(Object obj, struct Slice *slices);
|
||||||
Object add(Object obj1, Object obj2);
|
Object add(Object obj1, Object obj2);
|
||||||
|
|
||||||
// Slices
|
// Slices
|
||||||
void copySlice(char * dest, struct Slice *src);
|
void copySlice(char * dest, struct Slice *src);
|
||||||
void debugSlice(struct Slice *s);
|
void debugSlice(struct Slice *s);
|
||||||
|
|
||||||
#define R(_obj, _slices) resultFromObjAndSlices(_obj, _slices)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue