From 63be291b59fb049539d9c79fe02308ff8baf7ab2 Mon Sep 17 00:00:00 2001 From: Elijah Cohen Date: Sat, 17 Aug 2024 04:17:22 +0000 Subject: [PATCH] plugged memory leaks in all current builtins --- src/builtins/core.c | 79 +++++++++++++++++++++++++++++++++------------ src/sexpr.c | 9 ++++-- src/test.c | 15 +++++++++ 3 files changed, 81 insertions(+), 22 deletions(-) diff --git a/src/builtins/core.c b/src/builtins/core.c index 5565c33..d7b97e1 100644 --- a/src/builtins/core.c +++ b/src/builtins/core.c @@ -26,50 +26,78 @@ Sexpr* c_cons(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); // big problem: need to rewrite to wiggle around quotes Sexpr* args = b->value.b.args; - Sexpr* _cdr = eval(car(args), env); + Sexpr* raw_cdr = eval(clone(car(args)), env); + Sexpr* _cdr = raw_cdr; if(_cdr->type == QUOTE) _cdr = _cdr->value.q; - Sexpr* _car = eval(car(cdr(args)), env); + Sexpr* raw_car = eval(clone(car(cdr(args))), env); + Sexpr* _car = raw_car; if(_car->type == QUOTE) _car = _car->value.q; - return cons(from_quote(cons(_car, _cdr)), rest); + Sexpr* ret = cons(from_quote(cons(clone(_car),clone(_cdr))), rest); + //return cons(from_quote(cons(_car, _cdr)), rest); + sexpr_free(raw_car); + sexpr_free(raw_cdr); + sexpr_free(b); + return ret; } Sexpr* c_car(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_CAR_ARGS != u64_get_num_args(b)) return cons(b, rest); Sexpr* args = b->value.b.args; - Sexpr* arg = unquote(eval(car(args), env)); - return cons(from_quote(car(arg)), rest); + Sexpr* unqargev = eval(clone(car(args)), env); + Sexpr* ret = cons(from_quote(clone(car(unquote(unqargev)))), rest); + sexpr_free(unqargev); + sexpr_free(b); + return ret; } Sexpr* c_cdr(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_CDR_ARGS != u64_get_num_args(b)) return cons(b, rest); Sexpr* args = b->value.b.args; - Sexpr* arg = unquote(eval(car(args), env)); - return cons(from_quote(cdr(arg)), rest); + Sexpr* unqargev = eval(clone(car(args)), env); + Sexpr* ret = cons(from_quote(clone(cdr(unquote(unqargev)))), rest); + //Sexpr* arg = unquote(eval(car(args), env)); + //return cons(from_quote(cdr(arg)), rest); + sexpr_free(unqargev); + sexpr_free(b); + return ret; } Sexpr* c_if(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_IF_ARGS != u64_get_num_args(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(unquote(eval(cond, env))->type != NIL) + //Sexpr* falsy = car(args); + //Sexpr* truthy = car(cdr(args)); + Sexpr* cond = eval(clone(car(cdr(cdr(args)))), env); + if(unquote(cond)->type != NIL) { + Sexpr* truthy = clone(car(cdr(args))); + sexpr_free(cond); + sexpr_free(b); return cons(truthy, rest); - else + } + else { + Sexpr* falsy = clone(car(args)); + sexpr_free(cond); + sexpr_free(b); return cons(falsy, rest); + } } Sexpr* c_eq(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_EQ_ARGS != u64_get_num_args(b)) return cons(b, rest); Sexpr* args = b->value.b.args; // yeah eval is kinda necessary for this one I'd say - Sexpr* lh = unquote(eval(car(args), env)); - Sexpr* rh = unquote(eval(car(cdr(args)), env)); - - if(equal(lh, rh)->type == T) + Sexpr* lh = eval(clone(car(args)), env); + Sexpr* rh = eval(clone(car(cdr(args))), env); + Sexpr* eq_b = equal(unquote(lh), unquote(rh)); + bool equality = eq_b->type == T; + sexpr_free(eq_b); + sexpr_free(lh); + sexpr_free(rh); + sexpr_free(b); + if(equality) return cons(from_t(), rest); return cons(from_nil(), rest); } @@ -78,7 +106,11 @@ Sexpr* c_not(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); Sexpr* args = b->value.b.args; // I guess I would need the eval to check if eventually is nil - if(unquote(eval(car(args), env))->type == NIL) + Sexpr* crux = eval(clone(car(args)), env); + bool isnil = unquote(crux)->type == NIL; + sexpr_free(crux); + sexpr_free(b); + if(isnil) return cons(from_t(), rest); return cons(from_nil(), rest); } @@ -86,13 +118,18 @@ Sexpr* c_atom(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_ATOM_ARGS != u64_get_num_args(b)) return cons(b, rest); Sexpr* args = b->value.b.args; - Sexpr* argeval = eval(car(args), env); + Sexpr* argevalhead = eval(clone(car(args)), env); + Sexpr* argeval = argevalhead; while(argeval->type == QUOTE) { argeval = argeval->value.q; } if(argeval->type != CONS) { + sexpr_free(argevalhead); + sexpr_free(b); return cons(from_t(), rest); } + sexpr_free(argevalhead); + sexpr_free(b); return cons(from_nil(), rest); } @@ -101,9 +138,11 @@ Sexpr* c_def(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_DEF_ARGS != u64_get_num_args(b)) return cons(b, rest); Sexpr* args = b->value.b.args; - Sexpr* val = eval(car(args), env); - Sexpr* key = car(cdr(args)); + Sexpr* val = eval(clone(car(args)), env); + Sexpr* key = clone(car(cdr(args))); append_to_dict(env, key, val); + sexpr_free(key); + sexpr_free(b); return cons(val, rest); } Sexpr* c_exit(Sexpr* b, Sexpr* rest, Sexpr* env) { diff --git a/src/sexpr.c b/src/sexpr.c index 8eb7d6a..8902555 100644 --- a/src/sexpr.c +++ b/src/sexpr.c @@ -99,9 +99,14 @@ Sexpr* equal(Sexpr* a, Sexpr* b) { return equal(a->value.b.args, b->value.b.args); if(t == QUOTE) return equal(a->value.q, b->value.q); - if(t == CONS) - if(equal(car(a), car(b))->type == T) + if(t == CONS) { + Sexpr* careq = equal(car(a), car(b)); + bool ist = careq->type == T; + sexpr_free(careq); + if(ist) { return equal(cdr(a), cdr(b)); + } + } // leaving everything else off for... reasons return from_nil(); } diff --git a/src/test.c b/src/test.c index 8a5b965..6eabb6d 100644 --- a/src/test.c +++ b/src/test.c @@ -273,6 +273,21 @@ void eval_tests() { run_eval_test("(quote abcd)"); run_eval_test("(+ 3 6)"); run_eval_test("((+ 3) 7)"); + run_eval_test("(atom 55)"); + run_eval_test("(atom (quote (1 2 3)))"); + run_eval_test("(cons 1 2)"); + run_eval_test("(car (cons 1 2))"); + run_eval_test("(cdr (cons 1 2))"); + run_eval_test("(if t (cons 1 2) (cons 2 1))"); + run_eval_test("(if nil (cons 1 2) (cons 2 1))"); + run_eval_test("(eq 1 1)"); + run_eval_test("(eq 1 2)"); + run_eval_test("(eq 1 (quote 1))"); + run_eval_test("(eq (cons 1 2) (cons 1 3))"); + run_eval_test("(eq (quote (1 2)) (cons 1 (cons 2 nil)))"); + run_eval_test("(not 4326)"); + run_eval_test("(not nil)"); + run_eval_test("(def asdf 545)"); } -- 2.39.2