Lambdas begin to work!

This commit is contained in:
Sage Vaillancourt 2020-05-05 18:42:28 +01:00 committed by =
parent a3bf8ab864
commit 359d8ed439
6 changed files with 450 additions and 38 deletions

Binary file not shown.

215
src/object.c Normal file
View File

@ -0,0 +1,215 @@
#include "object.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#ifndef STANDALONE
#define printf(...) stringObj(NULL, NULL)
#endif
int listLength(const Object *listObj)
{
if(!listObj || listObj->type != TYPE_LIST)
return -1;
Object *t = listObj->list;
if(t == NULL)
return 0;
int len = 1;
while(t->forward != NULL) {
t = t->forward;
len++;
}
return len;
}
Object *itemAt(const Object *listObj, int n)
{
if(!listObj || listObj->type != TYPE_LIST)
return NULL;
Object *march = listObj->list;
for(int i = 0; i < n; i++) {
march = march->forward;
if(march == NULL)
return NULL;
}
return march;
}
// Returns last object in list (->forward == NULL)
Object *tail(const Object *listObj)
{
if(!listObj || listObj->type != TYPE_LIST)
return NULL;
Object *t = listObj->list;
while(t->forward != NULL) {
t = t->forward;
}
return t;
}
// Adds an object to the end of a list object
void addToList(Object *dest, const Object src)
{
if(!dest || dest->type != TYPE_LIST)
return;
if(dest->list == NULL) {
dest->list = malloc(sizeof(struct Object));
*dest->list = src;
dest->list->forward = NULL;
return;
}
Object *end = tail(dest);
end->forward = malloc(sizeof(struct Object));
*end->forward = src;
end->forward->forward = NULL;
}
// Puts a string version of the given object into a given string
char* stringObj(char *dest, const Object *obj)
{
if(!dest || !obj)
return NULL;
if(obj->type == TYPE_NUMBER) {
snprintf(dest, MAX_TOK_LEN, "%d", obj->number);
} else if(obj->type == TYPE_SYMBOL) {
snprintf(dest, MAX_TOK_LEN, "%s", obj->name);
} else if(obj->type == TYPE_BOOL) {
snprintf(dest, MAX_TOK_LEN, "%s", obj->number ? "T" : "F");
} else if(obj->type == TYPE_ERROR) {
snprintf(dest, MAX_TOK_LEN, "E%d", obj->err);
} else {
snprintf(dest, MAX_TOK_LEN, "%d", obj->number);
}
return dest;
}
int depth = 0;
// Prints the given object
void printObj(const Object *obj)
{
for(int i = 0; i < depth; i++)
printf(" ");
depth++;
if(obj->type == TYPE_NUMBER) {
printf("TYPE_NUMBER");
} else if(obj->type == TYPE_BOOL) {
printf("TYPE_BOOL");
} else if(obj->type == TYPE_LIST) {
printf("TYPE_LIST\n");
printList(obj);
depth--;
return;
} else if(obj->type == TYPE_FUNC) {
printf("TYPE_FUNC");
} else if(obj->type == TYPE_SYMBOL) {
printf("TYPE_SYMBOL");
} else if(obj->type == TYPE_LAMBDA) {
printf("TYPE_LAMBDA Params:\n");
depth++;
printObj(&obj->lambda->params);
for(int i = 1; i < depth; i++)
printf(" ");
printf("Lambda Body: \n");
printObj(&obj->lambda->body);
} else if(obj->type == TYPE_ERROR) {
printf("TYPE_ERROR: ");
} else {
printf("TYPE_OTHER (as int)");
}
depth--;
char temp[20] = "";
stringObj(temp, obj);
printf(": %s\n", temp);
}
void printList(const Object *list)
{
const Object *tail = list->list;
if(tail == NULL) {
for(int i = 0; i < depth; i++)
printf(" ");
printf("EMPTY LIST\n");
return;
}
while(tail != NULL) {
depth++;
printObj(tail);
depth--;
tail = tail->forward;
}
}
// Frees all objects in a list
void deleteList(const Object *dest)
{
if(dest->type != TYPE_LIST) {
printf("Tried to delete something other than a list\n");
return;
}
Object *tail = dest->list;
while(tail != NULL) {
Object *prevTail = tail;
tail = tail->forward;
free(prevTail);
}
}
inline Object listObject()
{
Object list;
list.forward = NULL;
list.type = TYPE_LIST;
list.list = NULL;
return list;
}
void copyList(Object *dest, const Object *src)
{
if(!dest || !src || dest->type != TYPE_LIST || src->type != TYPE_LIST)
return;
// deleteList(dest);
const Object *march = src->list;
while(march != NULL) {
addToList(dest, *march);
march = march->forward;
}
}
inline Object numberObject(int num)
{
Object o;
o.forward = NULL;
o.type = TYPE_NUMBER;
return o;
}
inline Object lambdaObject()
{
Object o;
o.forward = NULL;
o.type = TYPE_LAMBDA;
o.lambda = malloc(sizeof(struct Lambda));
return o;
}
inline Object errorObject(enum errorCode err)
{
Object o;
o.forward = NULL;
o.type = TYPE_ERROR;
o.err = err;
return o;
}

64
src/object.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef OBJECT_H
#define OBJECT_H
#define MAX_TOK_LEN 4 // 11
#define MAX_TOK_CNT 128 // 128
#define MAX_ENV_ELM 15 // 50
enum errorCode {
BAD_LIST_OF_SYMBOL_STRINGS,
TYPE_LIST_NOT_CAUGHT,
NULL_ENV,
BUILT_IN_NOT_FOUND,
NULL_PARSE
};
typedef enum Type {
TYPE_NUMBER,
TYPE_BOOL,
TYPE_LIST,
TYPE_FUNC,
TYPE_SYMBOL,
TYPE_LAMBDA,
TYPE_ERROR // Currently unused
} Type;
typedef struct Object Object;
struct Lambda;
struct Object {
Type type;
Object *forward;
union {
int number;
Object *list;
char name[MAX_TOK_LEN];
Object (*func)(Object, Object);
struct Lambda *lambda; // Maybe better as not a pointer
enum errorCode err;
};
};
// Maybe better as pointers
struct Lambda {
Object params;
Object body;
};
char* stringObj(char *dest, const Object *obj);
void printList(const Object *list);
void printObj(const Object *obj);
Object *tail(const Object *listObj);
void addToList(Object *dest, Object src);
void deleteList(const Object *dest);
int listLength(const Object *listObj);
Object *itemAt(const Object *listObj, int n);
void copyList(Object *dest, const Object *src);
Object listObject();
Object numberObject(int num);
Object lambdaObject();
Object errorObject();
#endif

View File

@ -28,7 +28,11 @@ void debugSlice(struct Slice *s)
Object fetchFromEnvironment(const char *name, struct Environment *env)
{
if(!env)
return errorObject(NULL_ENV);
printf("Fetching '%s' from env\n", name);
printEnv(env);
int i = 0;
const char *next = env->strings[i];
while(next != NULL) {
@ -37,6 +41,10 @@ Object fetchFromEnvironment(const char *name, struct Environment *env)
}
next = env->strings[++i];
}
printf("Trying outer\n");
if(env->outer) {
return fetchFromEnvironment(name, env->outer);
}
printf("DID NOT FIND SYMBOL\n");
Object o;
o.type = TYPE_ERROR;
@ -51,7 +59,7 @@ Result parse(struct Slice *slices)
rest = &slices[1];
} else {
printf("Assigning null...\n");
rest = NULL;
return R(errorObject(NULL_PARSE), NULL);
}
if(token->text[0] == '(') {
@ -103,8 +111,6 @@ Object parseAtom(struct Slice *s)
Object evalDefArgs(const Object *arg_forms, struct Environment *env)
{
printf("evalDefArgs()\n");
const Object *first_form = &arg_forms[0];
const char *name = first_form->name;
@ -122,69 +128,151 @@ Object evalIfArgs(const Object *arg_forms, struct Environment *env)
eval(arg_forms->forward->forward, env);
}
Object evalBuiltIns(const Object *first, const Object *rest, int *found,
Object evalLambdaArgs(const Object *arg_forms)
{
const Object *params_expr = &arg_forms[0];
const Object *body_expr = &arg_forms[1];
Object o = lambdaObject();
o.lambda->params = listObject();
copyList(&o.lambda->params, params_expr);
o.lambda->body = listObject();
copyList(&o.lambda->body, arg_forms->forward);
return o;
}
void parseListOfSymbolStrings(const Object *form, const char **symbolStrings,
int len)
{
if(!form || form->type != TYPE_LIST)
return;
for(int i = 0; i < len; i++)
symbolStrings[i] = itemAt(form, i)->name;
}
struct Environment envForLambda(const Object *params, const Object *arg_forms,
struct Environment *outer)
{
printf("\n#####################\nenvForLambda()\n");
printObj(arg_forms);
struct Environment env;
env.outer = outer;
env.strings = NULL;
env.objects = NULL;
int length = listLength(params);
if(length == 0)
return env;
env.strings = calloc(sizeof(char*), length);
env.objects = malloc(sizeof(Object) * length);
Object vs[length];
eval_forms(vs, arg_forms, outer);
for(int i = 0; i < length; i++) {
const char *n = itemAt(params, i)->name;
addToEnv(&env, n, eval(&arg_forms[i], outer)); // May not need eval?
} // Something is segfaulting, anyway
env.strings[length] = NULL;
printf("envForLambda env IT BROKE HERE()\n");
printf("envForLambda length=%d\n", length);
printEnv(&env);
printf("END envForLambda()\n\n");
return env;
}
Object evalBuiltIns(const Object *first, const Object *rest,
struct Environment *env)
{
if(strcmp(first->name, "def") == 0) {
*found = 0;
return evalDefArgs(rest, env);
}else if(strcmp(first->name, "if") == 0) {
*found = 0;
return evalIfArgs(rest, env);
}else if(strcmp(first->name, "fn") == 0) {
// printf("EVALBUILTINS first:\n");
// printObj(first);
// printf("\nEVALBUILTINS rest:\n");
// printObj(rest);
return evalLambdaArgs(rest);
}
Object o;
*found = -1;
return o;
return errorObject(BUILT_IN_NOT_FOUND);
}
void eval_forms(Object *destList, const Object *src, struct Environment *env)
{
int length = listLength(src) - 1; // Not counting first_form
for(int i = 0; i < length; i++) { // Evaluates all in list
destList[i] = eval(itemAt(src, i + 1), env); // Skip the first
}
}
Object eval(const Object *obj, struct Environment *env)
{
// printf("eval(): ");
// printObj(obj);
Object o = *obj;
printf("eval():\n");
printObj(obj);
switch(obj->type) {
case TYPE_NUMBER:
case TYPE_BOOL:
return o;
return *obj;
case TYPE_SYMBOL:
o = fetchFromEnvironment(obj->name, env);
printf("fetched object '%s':\n", obj->name);
printObj(&o);
return o;
return fetchFromEnvironment(obj->name, env);
case TYPE_LIST:
{
if(listLength(obj) == 1) {
o = *obj->list;
return o;
if(listLength(obj) == 0) {
printf("empty list\n"); return *obj;
}
Object first_form = *obj->list;
if(listLength(obj) == 1)
return eval(obj->list, env);
Object *first_form = obj->list;
{ // Try to eval built-ins
int i = -1;
Object built_in =
evalBuiltIns(&first_form, first_form.forward, &i, env);
evalBuiltIns(first_form, first_form->forward, env);
if(i == 0)
if(built_in.type != TYPE_ERROR)
return built_in;
}
printf("\nNo built-ins found\n");
Object first_eval = eval(&first_form, env);
Object arg1 = eval(first_form.forward, env);
Object arg2 = eval(first_form.forward->forward, env);
Object first_eval = eval(first_form, env);
if(first_eval.type == TYPE_FUNC) {
int length = listLength(obj) - 1; // Not counting first_form
Object rest[length];
eval_forms(rest, obj, env);
printf("Evaluating func\n");
Object func_eval = first_eval.func(arg1, arg2);
deleteList(obj);
return func_eval;
printf("Evaluating func\n");
Object func_eval = first_eval.func(rest[0], rest[1]);
// deleteList(obj);
return func_eval;
} else if (first_eval.type == TYPE_LAMBDA) {
printf("lammy\n");
struct Environment newEnv =
envForLambda(&first_eval.lambda->params, first_form->forward, env);
return eval(&first_eval.lambda->body, &newEnv);
} else {
return errorObject(TYPE_LIST_NOT_CAUGHT);
}
}
case TYPE_LAMBDA:
{
Object o;
o.type = TYPE_ERROR;
printf("UNEXPECTED FORM\n");
return o;
}
default:
;
}
return o;
return *obj;
}
Result resultFromObjAndSlices(Object obj, struct Slice *slices)
@ -206,6 +294,20 @@ void addToEnv(struct Environment *env, const char *name, const Object obj)
env->objects[i] = obj;
break;
}
if(strcmp(env->strings[i], name) == 0) {
env->objects[i] = obj;
break;
}
}
}
void printEnv(struct Environment *env)
{
for(int i = 0; i < MAX_ENV_ELM; i++) {
if(env->strings[i] == NULL)
return;
printf("env[%d]: '%s'\n ", i, env->strings[i]);
printObj(&env->objects[i]);
}
}
@ -290,6 +392,7 @@ void deleteEnv(struct Environment *e)
struct Environment defaultEnv() {
struct Environment e;
e.outer = NULL;
e.strings = malloc(sizeof(char*) * MAX_ENV_ELM);
for(int i = 0; i < MAX_ENV_ELM; i++) {
e.strings[i] = NULL;
@ -317,11 +420,15 @@ Object parseEval(const char *input, struct Environment *env)
while(debug->text) {
char tok[MAX_TOK_LEN];
copySlice(tok, debug);
//printf("slice: '%s'\n", tok);
debug++;
}
}
#endif
Object parsed = parse(tokens).obj;
// printf("PARSEEVAL() PRINTLIST():\n");
// printObj(&parsed);
// printf("end PARSEEVAL() PRINTLIST():\n\n");
free(tokens);
return eval(&parsed, env);
}
@ -335,7 +442,7 @@ int repl(struct Environment *env)
fgets(input, 100, stdin);
Object obj = parseEval(input, env);
printObj(&obj);
//break;
// printEnv(env);
}
}

View File

@ -19,6 +19,7 @@ typedef struct Result {
struct Environment {
char **strings;
Object *objects;
struct Environment *outer;
};
Object eval(const Object *obj, struct Environment *env);
@ -27,9 +28,13 @@ Result readSeq(struct Slice *slices);
Object parseAtom(struct Slice *slice);
void copySlice(char * dest, struct Slice *src);
Object parseEval(const char *input, struct Environment *env);
void eval_forms(Object *destList, const Object *src, struct Environment *env);
struct Environment defaultEnv();
void deleteEnv(struct Environment *e);
void addToEnv(struct Environment *env, const char *name, const Object obj);
Object fetchFromEnvironment(const char *name, struct Environment *env);
void printEnv(struct Environment *env);
Result resultFromObjAndSlices(Object obj, struct Slice *slices);
Object add(Object obj1, Object obj2);

View File

@ -4,19 +4,23 @@
!_TAG_PROGRAM_NAME Exuberant Ctags //
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION 5.9~svn20110310 //
BAD_LIST_OF_SYMBOL_STRINGS object.h /^ BAD_LIST_OF_SYMBOL_STRINGS,$/;" e enum:errorCode
BUILT_IN_NOT_FOUND object.h /^ BUILT_IN_NOT_FOUND$/;" e enum:errorCode
CALC_H calc.h 2;" d
CODE_PKEY calc.h 11;" d
END_PHRASE calc.h 9;" d
Environment pebblisp.h /^struct Environment {$/;" s
Lambda object.h /^struct Lambda {$/;" s
MAX_ENV_ELM object.h 6;" d
MAX_LENGTH calc.h 8;" d
MAX_TOK_CNT object.h 5;" d
MAX_TOK_LEN object.h 4;" d
NULL_ENV object.h /^ NULL_ENV,$/;" e enum:errorCode
OBJECT_H object.h 2;" d
Object object.h /^struct Object {$/;" s
Object object.h /^typedef struct Object Object;$/;" t typeref:struct:Object
PEBBLISP_H pebblisp.h 2;" d
R pebblisp.h 41;" d
R pebblisp.h 45;" d
Result pebblisp.h /^typedef struct Result {$/;" s
Result pebblisp.h /^} Result;$/;" t typeref:struct:Result
SMAX_LENGTH calc.h 7;" d
@ -24,9 +28,11 @@ Slice pebblisp.h /^struct Slice {$/;" s
TOKENS_H tokens.h 2;" d
TOKEN_END calc.h 42;" d
TYPE_BOOL object.h /^ TYPE_BOOL,$/;" e enum:Type
TYPE_ERROR object.h /^ TYPE_ERROR$/;" e enum:Type
TYPE_ERROR object.h /^ TYPE_ERROR \/\/ Currently unused$/;" e enum:Type
TYPE_FUNC object.h /^ TYPE_FUNC,$/;" e enum:Type
TYPE_LAMBDA object.h /^ TYPE_LAMBDA,$/;" e enum:Type
TYPE_LIST object.h /^ TYPE_LIST,$/;" e enum:Type
TYPE_LIST_NOT_CAUGHT object.h /^ TYPE_LIST_NOT_CAUGHT,$/;" e enum:errorCode
TYPE_NUMBER object.h /^ TYPE_NUMBER,$/;" e enum:Type
TYPE_SYMBOL object.h /^ TYPE_SYMBOL,$/;" e enum:Type
Type object.h /^typedef enum Type {$/;" g
@ -36,9 +42,11 @@ addToEnv pebblisp.c /^void addToEnv(struct Environment *env, const char *name, c
addToList object.c /^void addToList(Object *dest, const Object src)$/;" f
back_handler calc.c /^static void back_handler(ClickRecognizerRef recognizer, void *context) {$/;" f file:
basicOp pebblisp.c /^Object basicOp(Object *obj1, Object *obj2, const char op)$/;" f
bopf pebblisp.c 264;" d file:
body object.h /^ Object body;$/;" m struct:Lambda
bopf pebblisp.c 365;" d file:
calculate calc.c /^static void calculate(){$/;" f file:
click_config_provider calc.c /^static void click_config_provider(void *context) {$/;" f file:
copyList object.c /^void copyList(Object *dest, const Object *src)$/;" f
copySlice pebblisp.c /^void copySlice(char * dest, struct Slice *src)$/;" f
debugSlice pebblisp.c /^void debugSlice(struct Slice *s)$/;" f
defaultEnv pebblisp.c /^struct Environment defaultEnv() {$/;" f
@ -47,10 +55,16 @@ deleteEnv pebblisp.c /^void deleteEnv(struct Environment *e)$/;" f
deleteList object.c /^void deleteList(const Object *dest)$/;" f
enter calc.c /^static void enter(){$/;" f file:
env calc.h /^static struct Environment env;$/;" v typeref:struct:Environment
envForLambda pebblisp.c /^struct Environment envForLambda(const Object *params, const Object *arg_forms,$/;" f
err object.h /^ enum errorCode err;$/;" m union:Object::__anon1 typeref:enum:Object::__anon1::errorCode
errorCode object.h /^enum errorCode {$/;" g
errorObject object.c /^inline Object errorObject(enum errorCode err)$/;" f
eval pebblisp.c /^Object eval(const Object *obj, struct Environment *env)$/;" f
evalBuiltIns pebblisp.c /^Object evalBuiltIns(const Object *first, const Object *rest, int *found,$/;" f
evalBuiltIns pebblisp.c /^Object evalBuiltIns(const Object *first, const Object *rest,$/;" f
evalDefArgs pebblisp.c /^Object evalDefArgs(const Object *arg_forms, struct Environment *env)$/;" f
evalIfArgs pebblisp.c /^Object evalIfArgs(const Object *arg_forms, struct Environment *env)$/;" f
evalLambdaArgs pebblisp.c /^Object evalLambdaArgs(const Object *arg_forms, struct Environment *env)$/;" f
eval_forms pebblisp.c /^void eval_forms(Object *destList, const Object *src, struct Environment *env)$/;" f
fetchFromEnvironment pebblisp.c /^Object fetchFromEnvironment(const char *name, struct Environment *env)$/;" f
forward object.h /^ Object *forward;$/;" m struct:Object
func object.h /^ Object (*func)(Object, Object);$/;" m union:Object::__anon1
@ -59,6 +73,9 @@ init calc.c /^static void init(void) {$/;" f file:
isDigit tokens.c /^int isDigit(const char c) {$/;" f
isSingle tokens.c /^int isSingle(const char c) {$/;" f
isWhitespace tokens.c /^int isWhitespace(const char c) {$/;" f
itemAt object.c /^Object *itemAt(const Object *listObj, int n)$/;" f
lambda object.h /^ struct Lambda *lambda; \/\/ Maybe better as not a pointer$/;" m union:Object::__anon1 typeref:struct:Object::__anon1::Lambda
lambdaObject object.c /^inline Object lambdaObject()$/;" f
length pebblisp.h /^ char length;$/;" m struct:Slice
list object.h /^ Object *list;$/;" m union:Object::__anon1
listLength object.c /^int listLength(const Object *listObj)$/;" f
@ -73,9 +90,13 @@ number object.h /^ int number;$/;" m union:Object::__anon1
numberObject object.c /^inline Object numberObject(int num)$/;" f
obj pebblisp.h /^ Object obj;$/;" m struct:Result
objects pebblisp.h /^ Object *objects;$/;" m struct:Environment
outer pebblisp.h /^ struct Environment *outer;$/;" m struct:Environment typeref:struct:Environment::Environment
params object.h /^ Object params;$/;" m struct:Lambda
parse pebblisp.c /^Result parse(struct Slice *slices)$/;" f
parseAtom pebblisp.c /^Object parseAtom(struct Slice *s)$/;" f
parseEval pebblisp.c /^Object parseEval(const char *input, struct Environment *env)$/;" f
parseListOfSymbolStrings pebblisp.c /^void parseListOfSymbolStrings(const Object *form, const char **symbolStrings,$/;" f
printEnv pebblisp.c /^void printEnv(struct Environment *env)$/;" f
printList object.c /^void printList(const Object *list)$/;" f
printObj object.c /^void printObj(const Object *obj)$/;" f
printf object.c 7;" d file: