From e8b1804bac493cb3dee10050247e24da499858a8 Mon Sep 17 00:00:00 2001 From: Elijah Cohen Date: Fri, 16 Aug 2024 23:45:20 +0000 Subject: [PATCH] plugged leaks in eval --- ideas.org | 5 +++ src/builtins/arithmetic.c | 9 +++-- src/builtins/core.c | 7 +++- src/eval.c | 70 +++++++++++++++++++++++++++++++-------- src/repl.c | 4 ++- src/test.c | 31 +++++++++++++---- 6 files changed, 103 insertions(+), 23 deletions(-) diff --git a/ideas.org b/ideas.org index d27dcdd..6ac79f0 100644 --- a/ideas.org +++ b/ideas.org @@ -1,6 +1,11 @@ MEMORY MANAGEMENT okay gonna start with making sure the parser is good... how? +bad thing about this: +i have to dealloc each builtin when they're called, +unless i wanna move where I figure out how many args I want + + parser checklist: tokenize ok vals_parse ok diff --git a/src/builtins/arithmetic.c b/src/builtins/arithmetic.c index 4a686c4..18327c1 100644 --- a/src/builtins/arithmetic.c +++ b/src/builtins/arithmetic.c @@ -15,8 +15,13 @@ Sexpr* a_plus(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - uint64_t m = unquote(eval(car(args), env))->value.u; - uint64_t n = unquote(eval(car(cdr(args)), env))->value.u; + Sexpr* i = eval(clone(car(args)), env); + Sexpr* j = eval(clone(car(cdr(args))), env); + uint64_t m = unquote(i)->value.u; + uint64_t n = unquote(j)->value.u; + sexpr_free(b); + sexpr_free(i); + sexpr_free(j); return cons(from_uint(m + n), rest); } diff --git a/src/builtins/core.c b/src/builtins/core.c index 7b1ff62..69aced7 100644 --- a/src/builtins/core.c +++ b/src/builtins/core.c @@ -16,7 +16,9 @@ Sexpr* c_quote(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_QUOTE_ARGS != u64_get_num_args(b)) return cons(b, rest); //return car(b->value.b.args); - return cons(from_quote(car(b->value.b.args)), rest); + Sexpr* arg = clone(car(b->value.b.args)); + sexpr_free(b); + return cons(from_quote(arg), rest); } // redo the rest of these... @@ -110,6 +112,9 @@ Sexpr* c_exit(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); Sexpr* args = b->value.b.args; uint64_t value = car(args)->value.u; + sexpr_free(b); + sexpr_free(rest); + sexpr_free(env); exit(value); return NULL; } diff --git a/src/eval.c b/src/eval.c index f5f2563..4f98b5b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -10,7 +10,15 @@ Sexpr* apply_builtin(Sexpr* func, Sexpr* arg, Sexpr* env); Sexpr* eval(Sexpr* s, Sexpr* dict) { - //printf("s: %s\n", sprint_sexpr(s)); + /* char* out = sprint_sexpr(s); + printf("s: %s\n", out); + free(out); /**/ + // okay.. important to note, + // this needs to free s + // (I think) + // that makes the most sense at this point + + // 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? @@ -20,33 +28,68 @@ Sexpr* eval(Sexpr* s, Sexpr* dict) { Sexpr* lookedup = lookup(dict, s); if(lookedup->type == NIL) { printf("%s not defined\n", s->value.s); + sexpr_free(s); return lookedup; } - return car(lookedup); + sexpr_free(s); + Sexpr* lookedupcar = clone(car(lookedup)); + sexpr_free(lookedup); + return lookedupcar; } if(s->type != CONS) { return s; } // from now on: type is cons Sexpr* curr = s; while(curr->type == CONS) { - if(cdr(curr)->type == NIL) // this is okay to keep, yeah - return eval(car(curr), dict); - if(cdr(curr)->type != CONS) + if(cdr(curr)->type == NIL) { // this is okay to keep, yeah + Sexpr* endeval = eval(clone(car(curr)), dict); + sexpr_free(curr); + return endeval; + } + 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* rest = cdr(curr); - Sexpr* func = eval(car(curr), dict); - //Sexpr* newcar = apply_builtin(func, arg, dict); - //Sexpr* newcdr = cdr(cdr(curr)); + Sexpr* rest = clone(cdr(curr)); + // wait, where does rest get freed? + Sexpr* func = eval(clone(car(curr)), dict); + sexpr_free(curr); curr = apply_builtin(func, rest, dict); // is this ok? - //curr = cons(newcar, newcdr); + //sexpr_free(rest); + sexpr_free(func); } return curr; } +Sexpr* eval2(Sexpr* s, Sexpr* env) { + if(s == NULL) return NULL; + if(s->type == SYM) { + Sexpr* lookedup = lookup(env, s); + if(lookedup->type == NIL) { + printf("%s not defined", s->value.s); + sexpr_free(s); + return lookedup; + } + sexpr_free(s); + Sexpr* lookedupval = clone(car(lookedup)); + sexpr_free(lookedup); + return lookedupval; + } + if(s->type != CONS) { + return s; + } // s must be a cons cell now + Sexpr* curr = s; + while(curr->type == CONS) { + if(cdr(curr)->type == NIL) + return eval(car(curr), env); + } + + +} + Sexpr* apply_builtin(Sexpr* func, Sexpr* rest, Sexpr* env) { if(func->type != BUILTIN) { printf("uh oh\n"); @@ -55,8 +98,9 @@ Sexpr* apply_builtin(Sexpr* func, Sexpr* rest, Sexpr* env) { Sexpr* ret = malloc(sizeof(Sexpr)); ret->type = BUILTIN; ret->value.b.opcode = func->value.b.opcode; - ret->value.b.args = cons(car(rest), func->value.b.args); - - return dispatch(ret, cdr(rest), env); + ret->value.b.args = cons(clone(car(rest)), clone(func->value.b.args)); + Sexpr* cdrrest = clone(cdr(rest)); + sexpr_free(rest); + return dispatch(ret, cdrrest, env); // applies if correct no of args, just returns self otherwise } diff --git a/src/repl.c b/src/repl.c index d722715..019c602 100644 --- a/src/repl.c +++ b/src/repl.c @@ -33,9 +33,11 @@ int main(int argc, char** argv) { } else { //printf("- -%s\n", sprint_sexpr(in)); - Sexpr* out = eval(car(in), env); + Sexpr* out = eval(clone(car(in)), env); char* outstr = sprint_sexpr(out); printf(" - %s\n", outstr); + sexpr_free(in); + sexpr_free(out); free(outstr); } free(input); diff --git a/src/test.c b/src/test.c index eb24d98..0c59b12 100644 --- a/src/test.c +++ b/src/test.c @@ -210,16 +210,35 @@ void memtest_eval() { Sexpr* env = init_dict(); load_env(env); - Sexpr* parsed = parse("(cons 1 2)"); - Sexpr* val = eval(car(parsed), env); - char* out = sprint_sexpr(val); + Sexpr* x1 = from_uint(45); + Sexpr* x2 = from_sym("+"); + //Sexpr* cc = cons(x1, x2); + Sexpr* e = eval(x1, env); + char* out = sprint_sexpr(e); + printf("e: %s\n", out); + free(out); + sexpr_free(e); + //sexpr_free(x1); + e = eval(x2, env); + out = sprint_sexpr(e); + printf("e: %s\n", out); + free(out); + sexpr_free(e); + + + //Sexpr* parsed = parse("(cons 1 (cons 2 nil))"); + Sexpr* parsed = parse("(quote abcd)"); + Sexpr* val = eval(clone(car(parsed)), env); + out = sprint_sexpr(val); printf(" - %s\n", out); free(out); - sexpr_free(val); - printf("uh\n"); + out = sprint_sexpr(parsed); + printf("idk %s\n", out); + free(out); sexpr_free(parsed); + printf("uh\n"); + sexpr_free(val); printf("um\n"); - sexpr_free(env); } -- 2.39.2