From 3bb0ec5e0017c3c24bd70234a1e55e98568a0ff2 Mon Sep 17 00:00:00 2001 From: Elijah Cohen Date: Mon, 12 Aug 2024 00:52:02 -0500 Subject: [PATCH] made dubious changes to eval structure --- ideas.org | 6 +++ src/builtins.c | 6 +-- src/builtins.h | 2 +- src/builtins/arithmetic.c | 10 ++--- src/builtins/arithmetic.h | 2 +- src/builtins/core.c | 94 +++++++++++++++++++-------------------- src/builtins/core.h | 2 +- src/dict.c | 6 ++- src/eval.c | 20 +++++---- src/eval.h | 2 +- 10 files changed, 80 insertions(+), 70 deletions(-) diff --git a/ideas.org b/ideas.org index c8b9514..9690f46 100644 --- a/ideas.org +++ b/ideas.org @@ -1,3 +1,9 @@ + +so i'm redoing the basic eval to not pass an arg, but pass the rest of the list... yeah? +then the builtins just harvest the rest one at a time to get all their args, +and when executed can modify the rest? cool sounds good and worthwhile + + GARBAGE COLLECTION my grand design is that I will allocate and deallocate all the time, that is, if I 'def' something I keep it, but dereferencing something clones the thing, and then any call using it frees it again. is that too slow? yeah probably diff --git a/src/builtins.c b/src/builtins.c index f7a5761..90cf1c1 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -14,13 +14,13 @@ #include -Sexpr* dispatch(Sexpr* b, Sexpr* env) { +Sexpr* dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) { uint64_t prefix = (b->value.b.opcode) >> 8; switch(prefix) { case CORE_PREFIX: - return x_core_dispatch(b, env); + return x_core_dispatch(b, rest, env); case ARITH_PREFIX: - return x_arith_dispatch(b, env); + return x_arith_dispatch(b, rest, env); default: return from_nil(); } diff --git a/src/builtins.h b/src/builtins.h index 51b1aab..c20e829 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -5,7 +5,7 @@ #include "builtins/core.h" -Sexpr* dispatch(Sexpr* b, Sexpr* env); +Sexpr* dispatch(Sexpr* b, Sexpr* rest, Sexpr* env); uint64_t u64_get_num_args(Sexpr* b); Sexpr* load_env(Sexpr* env); diff --git a/src/builtins/arithmetic.c b/src/builtins/arithmetic.c index c612272..8a04be5 100644 --- a/src/builtins/arithmetic.c +++ b/src/builtins/arithmetic.c @@ -10,22 +10,22 @@ #include -Sexpr* a_plus(Sexpr* b, Sexpr* env) { +Sexpr* a_plus(Sexpr* b, Sexpr* rest, Sexpr* env) { if(ARITH_PLUS_ARGS != u64_get_num_args(b)) { - return b; + return cons(b, rest); } Sexpr* args = b->value.b.args; uint64_t m = eval(car(args), env)->value.u; uint64_t n = eval(car(cdr(args)), env)->value.u; - return from_uint(m + n); + return cons(from_uint(m + n), rest); } -Sexpr* x_arith_dispatch(Sexpr* b, Sexpr* env) { +Sexpr* x_arith_dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) { uint64_t code = b->value.b.opcode & 0xff; switch(code) { case ARITH_PLUS: - return a_plus(b, env); + return a_plus(b, rest, env); default: return from_nil(); } diff --git a/src/builtins/arithmetic.h b/src/builtins/arithmetic.h index 6c3fa8f..bbfa4f0 100644 --- a/src/builtins/arithmetic.h +++ b/src/builtins/arithmetic.h @@ -9,7 +9,7 @@ #define ARITH_PLUS 0x00 #define ARITH_PLUS_ARGS 2 -Sexpr* x_arith_dispatch(Sexpr* s, Sexpr* env); +Sexpr* x_arith_dispatch(Sexpr* s, Sexpr* rest, Sexpr* env); Sexpr* load_arith_env(Sexpr* env); #endif diff --git a/src/builtins/core.c b/src/builtins/core.c index 244ba49..99eb17c 100644 --- a/src/builtins/core.c +++ b/src/builtins/core.c @@ -12,126 +12,126 @@ #include -Sexpr* c_quote(Sexpr* b, Sexpr* env) { +Sexpr* c_quote(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_QUOTE_ARGS != u64_get_num_args(b)) - return b; + return cons(b, rest); //return car(b->value.b.args); - return from_quote(car(b->value.b.args)); + return cons(from_quote(car(b->value.b.args)), rest); } // redo the rest of these... -Sexpr* c_cons(Sexpr* b, Sexpr* env) { +Sexpr* c_cons(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_CONS_ARGS != u64_get_num_args(b)) - return b; + return cons(b, rest); Sexpr* args = b->value.b.args; Sexpr* _cdr = eval(car(args), env); Sexpr* _car = eval(car(cdr(args)), env); - return cons(_car, _cdr); + return cons(cons(_car, _cdr), rest); } -Sexpr* c_car(Sexpr* b, Sexpr* env) { +Sexpr* c_car(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_CAR_ARGS != u64_get_num_args(b)) - return b; + return cons(b, rest); Sexpr* args = b->value.b.args; - return car(eval(car(args), env)); + // huh okay, can i ditch the eval now that i'm doing the 'rest' thing? + return cons(car(eval(car(args), env)), rest); } -Sexpr* c_cdr(Sexpr* b, Sexpr* env) { +Sexpr* c_cdr(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_CDR_ARGS != u64_get_num_args(b)) - return b; + return cons(b, rest); Sexpr* args = b->value.b.args; - return cdr(eval(car(args), env)); + // see above + return cons(cdr(eval(car(args), env)), rest); } -Sexpr* c_if(Sexpr* b, Sexpr* env) { +Sexpr* c_if(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_IF_ARGS != u64_get_num_args(b)) - return b; + return cons(b, rest); Sexpr* args = b->value.b.args; Sexpr* falsy = car(args); Sexpr* truthy = car(cdr(args)); Sexpr* cond = car(cdr(cdr(args))); if(eval(cond, env)->type != NIL) - return truthy; + return cons(truthy, rest); else - return falsy; - // uhhh am I sure about this one? - // the lack of evals is perhaps a little suspect... + return cons(falsy, rest); } -Sexpr* c_eq(Sexpr* b, Sexpr* env) { +Sexpr* c_eq(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_EQ_ARGS != u64_get_num_args(b)) - return b; + return cons(b, rest); Sexpr* args = b->value.b.args; // yeah eval is kinda necessary for this one I'd say Sexpr* lh = eval(car(args), env); Sexpr* rh = eval(car(cdr(args)), env); if(equal(lh, rh)->type == T) - return from_t(); - return from_nil(); + return cons(from_t(), rest); + return cons(from_nil(), rest); } -Sexpr* c_not(Sexpr* b, Sexpr* env) { - if(CORE_NOT_ARGS != u64_get_num_args(b)) - return b; +Sexpr* c_not(Sexpr* b, Sexpr* rest, Sexpr* env) { + if(CORE_NOT_ARGS != u64_get_num_args(b)) + return cons(b, rest); Sexpr* args = b->value.b.args; // I guess I would need the eval to check if eventually is nil if(eval(car(args), env)->type == NIL) - return from_t(); - return from_nil(); + return cons(from_t(), rest); + return cons(from_nil(), rest); } -Sexpr* c_atom(Sexpr* b, Sexpr* env) { +Sexpr* c_atom(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_ATOM_ARGS != u64_get_num_args(b)) - return b; + return cons(b, rest); Sexpr* args = b->value.b.args; Sexpr* argeval = eval(car(args), env); while(argeval->type == QUOTE) { argeval = argeval->value.q; } if(argeval->type != CONS) { - return from_t(); + return cons(from_t(), rest); } - return from_nil(); + return cons(from_nil(), rest); } -Sexpr* c_def(Sexpr* b, Sexpr* env) { +Sexpr* c_def(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_DEF_ARGS != u64_get_num_args(b)) - return b; + return cons(b, rest); Sexpr* args = b->value.b.args; Sexpr* val = eval(car(args), env); Sexpr* key = car(cdr(args)); append_to_dict(env, key, val); - return val; + return cons(val, rest); } -Sexpr* c_exit(Sexpr* b, Sexpr* env) { +Sexpr* c_exit(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_EXIT_ARGS != u64_get_num_args(b)) - return b; + return cons(b, rest); Sexpr* args = b->value.b.args; uint64_t value = car(args)->value.u; exit(value); return NULL; } -Sexpr* x_core_dispatch(Sexpr* b, Sexpr* env) { +Sexpr* x_core_dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) { uint64_t code = b->value.b.opcode & 0xff; switch(code) { case CORE_QUOTE: - return c_quote(b, env); + return c_quote(b, rest, env); case CORE_CONS: - return c_cons(b, env); + return c_cons(b, rest, env); case CORE_CAR: - return c_car(b, env); + return c_car(b, rest, env); case CORE_CDR: - return c_cdr(b, env); + return c_cdr(b, rest, env); case CORE_IF: - return c_if(b, env); + return c_if(b, rest, env); case CORE_EQ: - return c_eq(b, env); + return c_eq(b, rest, env); case CORE_NOT: - return c_not(b, env); + return c_not(b, rest, env); case CORE_ATOM: - return c_atom(b, env); + return c_atom(b, rest, env); case CORE_DEF: - return c_def(b, env); + return c_def(b, rest, env); case CORE_EXIT: - return c_exit(b, env); + return c_exit(b, rest, env); default: return from_nil(); } diff --git a/src/builtins/core.h b/src/builtins/core.h index c85342e..72cb421 100644 --- a/src/builtins/core.h +++ b/src/builtins/core.h @@ -30,7 +30,7 @@ #define CORE_EXIT 0xff #define CORE_EXIT_ARGS 1 -Sexpr* x_core_dispatch(Sexpr* s, Sexpr* env); +Sexpr* x_core_dispatch(Sexpr* s, Sexpr* rest, Sexpr* env); Sexpr* load_core_env(Sexpr* env); #endif diff --git a/src/dict.c b/src/dict.c index 92c088d..c28498e 100644 --- a/src/dict.c +++ b/src/dict.c @@ -23,7 +23,8 @@ Sexpr* init_dict() { Sexpr* append_to_dict(Sexpr* dict, Sexpr* key, Sexpr* value) { // assumes dict well-formed, returns new dict // puts new things on the front of the dict, makes it so looking up gets the newest stuff first - Sexpr* new = cons(key, value); + Sexpr* new = cons(key, clone(value)); + // not yet sure if the above 'clone' is needed, or where the call should take place Sexpr* head = cons(new, car(dict)); dict->value.c->car = head; //return cons(new, dict); @@ -36,7 +37,8 @@ Sexpr* lookup(Sexpr* dict, Sexpr* key) { Sexpr* node = car(dict); while(node->type != NIL) { if(equal(key, car(car(node)))->type == T) { - return cons(cdr(car(node)), from_nil()); + Sexpr* value = clone(cdr(car(node))); + return cons(value, from_nil()); } node = cdr(node); } diff --git a/src/eval.c b/src/eval.c index 031fb25..cb99014 100644 --- a/src/eval.c +++ b/src/eval.c @@ -10,7 +10,7 @@ Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env); Sexpr* eval(Sexpr* s, Sexpr* dict) { - //printf("s: %s\n", sprint_sexpr(s)); + printf("s: %s\n", sprint_sexpr(s)); // non-null s // generally assumes that a sexpr passed to this is well-formed (ie no inapt NULLS) // question: does a completed builtin get evaluated here? @@ -29,23 +29,25 @@ Sexpr* eval(Sexpr* s, Sexpr* dict) { } // from now on: type is cons Sexpr* curr = s; while(curr->type == CONS) { - if(cdr(curr)->type == NIL) + if(cdr(curr)->type == NIL) // this is okay to keep, yeah return eval(car(curr), dict); if(cdr(curr)->type != CONS) // need to redo, how do i eval "(f . x)" ? // ^ easy, just return (f . x) return curr; // now i need to apply actually - Sexpr* arg = car(cdr(curr)); + //Sexpr* arg = car(cdr(curr)); + Sexpr* rest = cdr(curr); Sexpr* func = eval(car(curr), dict); - Sexpr* newcar = apply_builtin(func, arg, dict); - Sexpr* newcdr = cdr(cdr(curr)); - curr = cons(newcar, newcdr); + //Sexpr* newcar = apply_builtin(func, arg, dict); + //Sexpr* newcdr = cdr(cdr(curr)); + curr = apply_builtin(func, rest, dict); // is this ok? + //curr = cons(newcar, newcdr); } return curr; } -Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env) { +Sexpr* apply_builtin(Sexpr* func, Sexpr* rest, Sexpr* env) { if(func->type != BUILTIN) { printf("uh oh\n"); return from_nil(); // uhh this /should/ actually be impossible... @@ -53,8 +55,8 @@ Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env) { Sexpr* ret = malloc(sizeof(Sexpr)); ret->type = BUILTIN; ret->value.b.opcode = func->value.b.opcode; - ret->value.b.args = cons(arg, func->value.b.args); + ret->value.b.args = cons(car(rest), func->value.b.args); - return dispatch(ret, env); + return dispatch(ret, cdr(rest), env); // applies if correct no of args, just returns self otherwise } diff --git a/src/eval.h b/src/eval.h index db625cc..358df08 100644 --- a/src/eval.h +++ b/src/eval.h @@ -10,7 +10,7 @@ // key type is string, value type is sexpr, hash range is uint64_t Sexpr* eval(Sexpr* s, Sexpr* env); -Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env); +Sexpr* apply_builtin(Sexpr* func, Sexpr* rest, Sexpr* env); -- 2.39.2