From: Elijah Cohen Date: Fri, 19 Sep 2025 06:47:32 +0000 (+0000) Subject: reworking towards full proper reference counting implementation X-Git-Url: https://git.eli173.com/?a=commitdiff_plain;h=HEAD;p=klapaucius reworking towards full proper reference counting implementation --- diff --git a/src/builtins/arithmetic.c b/src/builtins/arithmetic.c index 1fb7f60..89e716a 100644 --- a/src/builtins/arithmetic.c +++ b/src/builtins/arithmetic.c @@ -16,22 +16,22 @@ Sexpr* a_plus(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* i = eval(clone(car(args)), env); - Sexpr* j = eval(clone(car(cdr(args))), env); + Sexpr* i = eval(add_ref(car(args)), env); + Sexpr* j = eval(add_ref(car(cdr(args))), env); #ifdef TYPECHECK if((unquote(i)->type != UINT) || (unquote(j)->type != UINT)) { ERR("+: ", "arguments not uints"); - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_nil(), rest); } #endif // typecheck K_UINT_TYPE m = unquote(i)->value.u; K_UINT_TYPE n = unquote(j)->value.u; - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_uint(m + n), rest); } @@ -40,22 +40,22 @@ Sexpr* a_minus(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* i = eval(clone(car(args)), env); - Sexpr* j = eval(clone(car(cdr(args))), env); + Sexpr* i = eval(add_ref(car(args)), env); + Sexpr* j = eval(add_ref(car(cdr(args))), env); #ifdef TYPECHECK if((unquote(i)->type != UINT) || (unquote(j)->type != UINT)) { ERR("-: ", "arguments not uints"); - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_nil(), rest); } #endif // typecheck K_UINT_TYPE m = unquote(i)->value.u; K_UINT_TYPE n = unquote(j)->value.u; - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_uint(n - m), rest); } @@ -64,22 +64,22 @@ Sexpr* a_mul(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* i = eval(clone(car(args)), env); - Sexpr* j = eval(clone(car(cdr(args))), env); + Sexpr* i = eval(add_ref(car(args)), env); + Sexpr* j = eval(add_ref(car(cdr(args))), env); #ifdef TYPECHECK if((unquote(i)->type != UINT) || (unquote(j)->type != UINT)) { ERR("*: ", "arguments not uints"); - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_nil(), rest); } #endif // typecheck K_UINT_TYPE m = unquote(i)->value.u; K_UINT_TYPE n = unquote(j)->value.u; - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_uint(m * n), rest); } @@ -88,22 +88,22 @@ Sexpr* a_div(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* i = eval(clone(car(args)), env); - Sexpr* j = eval(clone(car(cdr(args))), env); + Sexpr* i = eval(add_ref(car(args)), env); + Sexpr* j = eval(add_ref(car(cdr(args))), env); #ifdef TYPECHECK if((unquote(i)->type != UINT) || (unquote(j)->type != UINT)) { ERR("/: ", "arguments not uints"); - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_nil(), rest); } #endif // typecheck K_UINT_TYPE m = unquote(i)->value.u; K_UINT_TYPE n = unquote(j)->value.u; - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_uint(n / m), rest); } @@ -112,22 +112,22 @@ Sexpr* a_mod(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* i = eval(clone(car(args)), env); - Sexpr* j = eval(clone(car(cdr(args))), env); + Sexpr* i = eval(add_ref(car(args)), env); + Sexpr* j = eval(add_ref(car(cdr(args))), env); #ifdef TYPECHECK if((unquote(i)->type != UINT) || (unquote(j)->type != UINT)) { ERR("%: ", "arguments not uints"); - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_nil(), rest); } #endif // typecheck K_UINT_TYPE m = unquote(i)->value.u; K_UINT_TYPE n = unquote(j)->value.u; - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_uint(n % m), rest); } @@ -136,22 +136,22 @@ Sexpr* a_mod(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* i = eval(clone(car(args)), env); - Sexpr* j = eval(clone(car(cdr(args))), env); + Sexpr* i = eval(add_ref(car(args)), env); + Sexpr* j = eval(add_ref(car(cdr(args))), env); #ifdef TYPECHECK if((unquote(i)->type != UINT) || (unquote(j)->type != UINT)) { ERR("%: ", "arguments not uints"); - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_nil(), rest); } #endif K_UINT_TYPE m = unquote(i)->value.u; K_UINT_TYPE n = unquote(j)->value.u; - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(m < n ? from_t(): from_nil(), rest); } @@ -160,22 +160,22 @@ Sexpr* a_lt(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* i = eval(clone(car(args)), env); - Sexpr* j = eval(clone(car(cdr(args))), env); + Sexpr* i = eval(add_ref(car(args)), env); + Sexpr* j = eval(add_ref(car(cdr(args))), env); #ifdef TYPECHECK if((unquote(i)->type != UINT) || (unquote(j)->type != UINT)) { ERR("%: ", "arguments not uints"); - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(from_nil(), rest); } #endif K_UINT_TYPE m = unquote(i)->value.u; K_UINT_TYPE n = unquote(j)->value.u; - sexpr_free(b); - sexpr_free(i); - sexpr_free(j); + dec_ref(b); + dec_ref(i); + dec_ref(j); return cons(m > n ? from_t() : from_nil(), rest); } diff --git a/src/builtins/combinators.c b/src/builtins/combinators.c index 7a0741d..e773e8a 100644 --- a/src/builtins/combinators.c +++ b/src/builtins/combinators.c @@ -15,8 +15,8 @@ Sexpr* c_i(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* arg = clone(car(args)); - sexpr_free(b); + Sexpr* arg = add_ref(car(args)); + dec_ref(b); return cons(arg, rest); } @@ -25,11 +25,11 @@ Sexpr* c_s(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* x = clone(car(cdr(cdr(args)))); - Sexpr* y = clone(car(cdr(args))); - Sexpr* z = clone(car(args)); - Sexpr* zclone = clone(z); - sexpr_free(b); + Sexpr* x = add_ref(car(cdr(cdr(args)))); + Sexpr* y = add_ref(car(cdr(args))); + Sexpr* z = add_ref(car(args)); + Sexpr* zclone = add_ref(z); + dec_ref(b); Sexpr* ret = cons(cons(y, cons(zclone, from_nil())), rest); ret = cons(z, ret); ret = cons(x, ret); @@ -42,8 +42,8 @@ Sexpr* c_k(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* x = clone(car(cdr(args))); - sexpr_free(b); + Sexpr* x = add_ref(car(cdr(args))); + dec_ref(b); return cons(x, rest); } @@ -52,10 +52,10 @@ Sexpr* c_b(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* x = clone(car(cdr(cdr(args)))); - Sexpr* y = clone(car(cdr(args))); - Sexpr* z = clone(car(args)); - sexpr_free(b); + Sexpr* x = add_ref(car(cdr(cdr(args)))); + Sexpr* y = add_ref(car(cdr(args))); + Sexpr* z = add_ref(car(args)); + dec_ref(b); Sexpr* ret = cons(x, cons(cons(y, cons(z, from_nil())), rest)); return ret; @@ -66,10 +66,10 @@ Sexpr* c_c(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* x = clone(car(cdr(cdr(args)))); - Sexpr* y = clone(car(cdr(args))); - Sexpr* z = clone(car(args)); - sexpr_free(b); + Sexpr* x = add_ref(car(cdr(cdr(args)))); + Sexpr* y = add_ref(car(cdr(args))); + Sexpr* z = add_ref(car(args)); + dec_ref(b); Sexpr* ret = cons(x, cons(z, cons(y, rest))); return ret; @@ -80,10 +80,10 @@ Sexpr* c_w(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* x = clone(car(cdr(args))); - Sexpr* y = clone(car(args)); - Sexpr* y2 = clone(y); - sexpr_free(b); + Sexpr* x = add_ref(car(cdr(args))); + Sexpr* y = add_ref(car(args)); + Sexpr* y2 = add_ref(y); + dec_ref(b); Sexpr* ret = cons(x, cons(y, cons(y2, rest))); return ret; } @@ -93,15 +93,15 @@ Sexpr* c_phi(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* d = clone(car(args)); - Sexpr* c = clone(car(cdr(args))); - Sexpr* bee = clone(car(cdr(cdr(args)))); - Sexpr* a = clone(car(cdr(cdr(cdr(args))))); - Sexpr* d2 = clone(d); + Sexpr* d = add_ref(car(args)); + Sexpr* c = add_ref(car(cdr(args))); + Sexpr* bee = add_ref(car(cdr(cdr(args)))); + Sexpr* a = add_ref(car(cdr(cdr(cdr(args))))); + Sexpr* d2 = add_ref(d); Sexpr* bd = cons(bee, cons(d, from_nil())); Sexpr* cd = cons(c, cons(d2, from_nil())); Sexpr* ret = cons(a, cons(bd, cons(cd, rest))); - sexpr_free(b); + dec_ref(b); return ret; } @@ -110,15 +110,15 @@ Sexpr* c_psi(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* d = clone(car(args)); - Sexpr* c = clone(car(cdr(args))); - Sexpr* bee = clone(car(cdr(cdr(args)))); - Sexpr* a = clone(car(cdr(cdr(cdr(args))))); - Sexpr* bee2 = clone(bee); + Sexpr* d = add_ref(car(args)); + Sexpr* c = add_ref(car(cdr(args))); + Sexpr* bee = add_ref(car(cdr(cdr(args)))); + Sexpr* a = add_ref(car(cdr(cdr(cdr(args))))); + Sexpr* bee2 = add_ref(bee); Sexpr* bd = cons(bee, cons(d, from_nil())); Sexpr* bc = cons(bee2, cons(c, from_nil())); Sexpr* ret = cons(a, cons(bc, cons(bd, rest))); - sexpr_free(b); + dec_ref(b); return ret; } @@ -128,12 +128,12 @@ Sexpr* c_z(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* g = clone(car(cdr(args))); - Sexpr* v = eval(clone(car(args)), env); + Sexpr* g = add_ref(car(cdr(args))); + Sexpr* v = eval(add_ref(car(args)), env); // man that eval does a /lot/ for computation, // need to think about what this implies - sexpr_free(b); - Sexpr* g2 = clone(g); + dec_ref(b); + Sexpr* g2 = add_ref(g); Sexpr* z = from_opcode((COMB_PREFIX << 8) | COMB_Z); Sexpr* zg = cons(z, cons(g2, from_nil())); //return cons(g, rest); diff --git a/src/builtins/core.c b/src/builtins/core.c index 6caf7ab..8e43291 100644 --- a/src/builtins/core.c +++ b/src/builtins/core.c @@ -14,8 +14,8 @@ Sexpr* c_quote(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_QUOTE_ARGS != u64_get_num_args(b)) return cons(b, rest); - Sexpr* arg = clone(car(b->value.b.args)); - sexpr_free(b); + Sexpr* arg = add_ref(car(b->value.b.args)); + dec_ref(b); return cons(from_quote(arg), rest); } @@ -25,54 +25,54 @@ 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* raw_cdr = eval(clone(car(args)), env); + Sexpr* raw_cdr = eval(add_ref(car(args)), env); Sexpr* _cdr = raw_cdr; if(_cdr->type == QUOTE) _cdr = _cdr->value.q; - Sexpr* raw_car = eval(clone(car(cdr(args))), env); + Sexpr* raw_car = eval(add_ref(car(cdr(args))), env); Sexpr* _car = raw_car; if(_car->type == QUOTE) _car = _car->value.q; - Sexpr* ret = cons(from_quote(cons(clone(_car),clone(_cdr))), rest); - sexpr_free(raw_car); - sexpr_free(raw_cdr); - sexpr_free(b); + Sexpr* ret = cons(from_quote(cons(add_ref(_car),add_ref(_cdr))), rest); + dec_ref(raw_car); + dec_ref(raw_cdr); + dec_ref(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* unqargev = eval(clone(car(args)), env); + Sexpr* unqargev = eval(add_ref(car(args)), env); #ifdef TYPECHECK if(unquote(unqargev)->type != CONS) { ERR(CORE_CAR_STR ": ", "argument not cons cell"); - sexpr_free(b); - sexpr_free(unqargev); + dec_ref(b); + dec_ref(unqargev); return cons(from_nil(), rest); } #endif // typecheck - Sexpr* ret = cons(from_quote(clone(car(unquote(unqargev)))), rest); - sexpr_free(unqargev); - sexpr_free(b); + Sexpr* ret = cons(from_quote(add_ref(car(unquote(unqargev)))), rest); + dec_ref(unqargev); + dec_ref(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* unqargev = eval(clone(car(args)), env); + Sexpr* unqargev = eval(add_ref(car(args)), env); #ifdef TYPECHECK if(unquote(unqargev)->type != CONS) { ERR(CORE_CDR_STR ": ", "argument not cons cell"); - sexpr_free(b); - sexpr_free(unqargev); + dec_ref(b); + dec_ref(unqargev); return cons(from_nil(), rest); } #endif // typecheck - Sexpr* ret = cons(from_quote(clone(cdr(unquote(unqargev)))), rest); - sexpr_free(unqargev); - sexpr_free(b); + Sexpr* ret = cons(from_quote(add_ref(cdr(unquote(unqargev)))), rest); + dec_ref(unqargev); + dec_ref(b); return ret; } Sexpr* c_eq(Sexpr* b, Sexpr* rest, Sexpr* env) { @@ -80,14 +80,14 @@ Sexpr* c_eq(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); Sexpr* args = b->value.b.args; // yeah eval is kinda necessary for this one I'd say - Sexpr* lh = eval(clone(car(args)), env); - Sexpr* rh = eval(clone(car(cdr(args))), env); + Sexpr* lh = eval(add_ref(car(args)), env); + Sexpr* rh = eval(add_ref(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); + dec_ref(eq_b); + dec_ref(lh); + dec_ref(rh); + dec_ref(b); if(equality) return cons(from_t(), rest); return cons(from_nil(), rest); @@ -97,10 +97,10 @@ 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 - Sexpr* crux = eval(clone(car(args)), env); + Sexpr* crux = eval(add_ref(car(args)), env); bool isnil = unquote(crux)->type == NIL; - sexpr_free(crux); - sexpr_free(b); + dec_ref(crux); + dec_ref(b); if(isnil) return cons(from_t(), rest); return cons(from_nil(), rest); @@ -109,18 +109,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* argevalhead = eval(clone(car(args)), env); + Sexpr* argevalhead = eval(add_ref(car(args)), env); Sexpr* argeval = argevalhead; while(argeval->type == QUOTE) { argeval = argeval->value.q; } if(argeval->type != CONS) { - sexpr_free(argevalhead); - sexpr_free(b); + dec_ref(argevalhead); + dec_ref(b); return cons(from_t(), rest); } - sexpr_free(argevalhead); - sexpr_free(b); + dec_ref(argevalhead); + dec_ref(b); return cons(from_nil(), rest); } @@ -135,10 +135,10 @@ Sexpr* c_rest(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_REST_ARGS != u64_get_num_args(b)) return cons(b, rest); Sexpr* args = b->value.b.args; - Sexpr* first_arg = eval(clone(car(cdr(args))), env); - Sexpr* second_arg = clone(car(args)); // uhh no eval? nah don't think so + Sexpr* first_arg = eval(add_ref(car(cdr(args))), env); + Sexpr* second_arg = add_ref(car(args)); // uhh no eval? nah don't think so Sexpr* newrest = cons(second_arg, rest); - sexpr_free(b); + dec_ref(b); return cons(first_arg, cons(from_quote(newrest), from_nil())); } @@ -149,9 +149,9 @@ Sexpr* c_unquote(Sexpr* b, Sexpr* rest, Sexpr* env) { // huh this might need a weird cursed double-eval if(CORE_UNQUOTE_ARGS != u64_get_num_args(b)) return cons(b, rest); - Sexpr* first_arg = eval(clone(car(b->value.b.args)), env); + Sexpr* first_arg = eval(add_ref(car(b->value.b.args)), env); Sexpr* newthing = eval(unquote(first_arg), env); - sexpr_free(b); + dec_ref(b); return cons(newthing, rest); } @@ -164,20 +164,20 @@ Sexpr* c_applyn(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_APPLYN_ARGS != u64_get_num_args(b)) return cons(b, rest); Sexpr* args = b->value.b.args; - Sexpr* arg = clone(car(args)); + Sexpr* arg = add_ref(car(args)); Sexpr* fun = car(cdr(args)); - Sexpr* snum = eval(clone(car(cdr(cdr(args)))), env); + Sexpr* snum = eval(add_ref(car(cdr(cdr(args)))), env); // uh yeah i'm not typechecking lol K_UINT_TYPE num = snum->value.u; - sexpr_free(snum); + dec_ref(snum); // fun not cloned due since i'll be cloning it in the loop Sexpr* ret = cons(arg, from_nil()); while(num > 0) { - ret = cons(clone(fun), cons(ret, from_nil())); + ret = cons(add_ref(fun), cons(ret, from_nil())); ret = eval(ret, env); num--; } - sexpr_free(b); + dec_ref(b); return cons(ret, rest); } @@ -185,9 +185,9 @@ Sexpr* c_evalarg(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_EVALARG_ARGS != u64_get_num_args(b)) return cons(b, rest); Sexpr* args = b->value.b.args; - Sexpr* argeval = eval(clone(car(args)), env); - Sexpr* fn = clone(car(cdr(args))); - sexpr_free(b); + Sexpr* argeval = eval(add_ref(car(args)), env); + Sexpr* fn = add_ref(car(cdr(args))); + dec_ref(b); return cons(fn, cons(argeval, rest)); } @@ -196,10 +196,10 @@ Sexpr* c_type(Sexpr* b, Sexpr* rest, Sexpr* env) { if(CORE_TYPE_ARGS != u64_get_num_args(b)) return cons(b, rest); Sexpr* args = b->value.b.args; - Sexpr* argev = eval(clone(car(args)), env); + Sexpr* argev = eval(add_ref(car(args)), env); Sexpr_Type t = argev->type; - sexpr_free(b); - sexpr_free(argev); + dec_ref(b); + dec_ref(argev); switch(t) { case UINT: return cons(from_string("uint"), rest); @@ -228,11 +228,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(clone(car(args)), env); - Sexpr* key = clone(car(cdr(args))); + Sexpr* val = eval(add_ref(car(args)), env); + Sexpr* key = add_ref(car(cdr(args))); append_to_dict(env, key, val); - sexpr_free(key); - sexpr_free(b); + dec_ref(key); + dec_ref(b); return cons(val, rest); } Sexpr* c_exit(Sexpr* b, Sexpr* rest, Sexpr* env) { @@ -240,9 +240,9 @@ Sexpr* c_exit(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); Sexpr* args = b->value.b.args; K_UINT_TYPE value = car(args)->value.u; - sexpr_free(b); - sexpr_free(rest); - sexpr_free(env); + dec_ref(b); + dec_ref(rest); + dec_ref(env); exit(value); return NULL; } diff --git a/src/builtins/io.c b/src/builtins/io.c index 3531add..57ebc5d 100644 --- a/src/builtins/io.c +++ b/src/builtins/io.c @@ -14,10 +14,10 @@ Sexpr* io_print(Sexpr* b, Sexpr* rest, Sexpr* env) { if(IO_PRINT_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = eval(clone(car(b->value.b.args)), env); - sexpr_free(b); + Sexpr* arg = eval(add_ref(car(b->value.b.args)), env); + dec_ref(b); char* out = sprint_sexpr(arg); - sexpr_free(arg); + dec_ref(arg); PRINT(out); free(out); return cons(from_t(), rest); @@ -27,15 +27,15 @@ Sexpr* io_printstr(Sexpr* b, Sexpr* rest, Sexpr* env) { if(IO_PRINTSTR_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = eval(clone(car(b->value.b.args)), env); + Sexpr* arg = eval(add_ref(car(b->value.b.args)), env); if(arg->type != STR) { - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_nil(), rest); } PRINT(arg->value.str); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_t(), rest); } @@ -43,11 +43,11 @@ Sexpr* io_print_b(Sexpr* b, Sexpr* rest, Sexpr* env) { if(IO_PB_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = clone(car(b->value.b.args)); - sexpr_free(b); + Sexpr* arg = add_ref(car(b->value.b.args)); + dec_ref(b); Sexpr* argeval = eval(arg, env); char* out = sprint_sexpr_builtin(argeval); - sexpr_free(argeval); + dec_ref(argeval); // uhh do i free arg? don't think so... PRINT(out); free(out); @@ -58,24 +58,24 @@ Sexpr* io_readfile(Sexpr* b, Sexpr* rest, Sexpr* env) { if(IO_READFILE_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* firstarg = eval(clone(car(b->value.b.args)), env); + Sexpr* firstarg = eval(add_ref(car(b->value.b.args)), env); #ifdef TYPECHECK if(firstarg->type != STR) { ERR(IO_READFILE_STR ": ", "argument not a string"); - sexpr_free(firstarg); - sexpr_free(b); + dec_ref(firstarg); + dec_ref(b); return cons(from_nil(), rest); } #endif FILE* thefile = fopen(firstarg->value.str, "r"); if(!thefile) { ERR(IO_READFILE_STR ": file not found: ", firstarg->value.str); - sexpr_free(firstarg); - sexpr_free(b); + dec_ref(firstarg); + dec_ref(b); return cons(from_nil(), rest); } - sexpr_free(firstarg); - sexpr_free(b); + dec_ref(firstarg); + dec_ref(b); fseek(thefile, 0, SEEK_END); size_t fsz = ftell(thefile); fseek(thefile, 0, SEEK_SET); @@ -97,14 +97,14 @@ Sexpr* io_writefile(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* filearg = eval(clone(car(cdr(args))), env); - Sexpr* strarg = eval(clone(car(args)), env); + Sexpr* filearg = eval(add_ref(car(cdr(args))), env); + Sexpr* strarg = eval(add_ref(car(args)), env); #ifdef TYPECHECK if(filearg->type != STR || strarg->type != STR) { ERR(IO_WRITEFILE_STR ": ", "arguments not strings"); - sexpr_free(filearg); - sexpr_free(strarg); - sexpr_free(b); + dec_ref(filearg); + dec_ref(strarg); + dec_ref(b); return cons(from_nil(), rest); } #endif @@ -112,16 +112,16 @@ Sexpr* io_writefile(Sexpr* b, Sexpr* rest, Sexpr* env) { FILE* thefile = fopen(filestring, "w"); if(!thefile) { ERR(IO_WRITEFILE_STR ": file not found: ", filestring); - sexpr_free(filearg); - sexpr_free(strarg); - sexpr_free(b); + dec_ref(filearg); + dec_ref(strarg); + dec_ref(b); return cons(from_nil(), rest); } size_t num_written = fwrite(strarg->value.str, sizeof(char), strlen(strarg->value.str), thefile); fclose(thefile); - sexpr_free(filearg); - sexpr_free(strarg); - sexpr_free(b); + dec_ref(filearg); + dec_ref(strarg); + dec_ref(b); return cons(from_uint(num_written), rest); } @@ -130,18 +130,18 @@ Sexpr* io_rand(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* arg = eval(clone(car(args)), env); + Sexpr* arg = eval(add_ref(car(args)), env); #ifdef TYPECHECK if(arg->type != UINT) { ERR(IO_RAND_STR ": ", "argument not uint"); - sexpr_free(arg); - sexpr_free(b); + dec_ref(arg); + dec_ref(b); return cons(from_nil(), rest); } #endif K_UINT_TYPE m = unquote(arg)->value.u; - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_uint(rand() % m), rest); } diff --git a/src/builtins/meta.c b/src/builtins/meta.c index 15ce7d7..19d8d51 100644 --- a/src/builtins/meta.c +++ b/src/builtins/meta.c @@ -14,18 +14,18 @@ Sexpr* m_utob(Sexpr* b, Sexpr* rest, Sexpr* env) { if(META_UTOB_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = eval(clone(car(b->value.b.args)), env); + Sexpr* arg = eval(add_ref(car(b->value.b.args)), env); #ifdef TYPECHECK if(unquote(arg)->type != UINT) { ERR(META_UTOB_STR ": ", "argument not uint"); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_nil(), rest); } #endif // typecheck Sexpr* out = from_opcode(unquote(arg)->value.u); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(out, rest); } @@ -33,18 +33,18 @@ Sexpr* m_btou(Sexpr* b, Sexpr* rest, Sexpr* env) { if(META_BTOU_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = eval(clone(car(b->value.b.args)), env); + Sexpr* arg = eval(add_ref(car(b->value.b.args)), env); #ifdef TYPECHECK if(unquote(arg)->type != BUILTIN) { ERR(META_BTOU_STR ": ", "argument not builtin"); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_nil(), rest); } #endif // typecheck Sexpr* out = from_uint(unquote(arg)->value.b.opcode); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(out, rest); } @@ -52,18 +52,18 @@ Sexpr* m_parse(Sexpr* b, Sexpr* rest, Sexpr* env) { if(META_PARSE_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = eval(clone(car(b->value.b.args)), env); + Sexpr* arg = eval(add_ref(car(b->value.b.args)), env); #ifdef TYPECHECK if(unquote(arg)->type != STR) { ERR(META_PARSE_STR ": ", "argument not string"); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_nil(), rest); } #endif Sexpr* out = parse(unquote(arg)->value.str); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); if(out == NULL) { ERR(META_PARSE_STR ": ", "bad input"); return cons(from_nil(), rest); @@ -75,18 +75,18 @@ Sexpr* m_getargs(Sexpr* b, Sexpr* rest, Sexpr* env) { if(META_GETARGS_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = eval(clone(car(b->value.b.args)), env); + Sexpr* arg = eval(add_ref(car(b->value.b.args)), env); #ifdef TYPECHECK if(unquote(arg)->type != BUILTIN) { ERR(META_GETARGS_STR ": ", "argument not builtin"); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_nil(), rest); } #endif - Sexpr* args = clone(unquote(arg)->value.b.args); // poorly named variable? - sexpr_free(arg); - sexpr_free(b); + Sexpr* args = add_ref(unquote(arg)->value.b.args); // poorly named variable? + dec_ref(arg); + dec_ref(b); return cons(from_quote(args), rest); } @@ -96,7 +96,7 @@ Sexpr* m_lookup(Sexpr* b, Sexpr* rest, Sexpr* env) { } Sexpr* args = b->value.b.args; Sexpr* lookedup = lookup(env, car(args)); - sexpr_free(b); + dec_ref(b); return cons(from_quote(lookedup), rest); } @@ -106,16 +106,16 @@ Sexpr* m_getenv(Sexpr* b, Sexpr* rest, Sexpr* env) { if(META_GETENV_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = eval(clone(car(b->value.b.args)), env); + Sexpr* arg = eval(add_ref(car(b->value.b.args)), env); if(arg->type != T) { ERR(META_GETENV_STR ": ", "incorrect call"); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_nil(), rest); } - sexpr_free(b); - sexpr_free(arg); - Sexpr* outpart = cons(from_quote(clone(env)), rest); + dec_ref(b); + dec_ref(arg); + Sexpr* outpart = cons(from_quote(add_ref(env)), rest); return outpart; } @@ -124,19 +124,19 @@ Sexpr* m_setenv(Sexpr* b, Sexpr* rest, Sexpr* env) { if(META_SETENV_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = eval(clone(car(b->value.b.args)), env); + Sexpr* arg = eval(add_ref(car(b->value.b.args)), env); if(unquote(arg)->type != CONS && cdr(unquote(arg))->type != NIL) { ERR(META_SETENV_STR ": ", "not well-formed"); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_nil(), rest); } - Sexpr* newenvbody = clone(car(unquote(arg))); - sexpr_free(car(env)); + Sexpr* newenvbody = add_ref(car(unquote(arg))); + dec_ref(car(env)); env->value.c->car = newenvbody; // todo - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_t(), rest); } diff --git a/src/builtins/strings.c b/src/builtins/strings.c index e94d67b..d3a0f7e 100644 --- a/src/builtins/strings.c +++ b/src/builtins/strings.c @@ -15,18 +15,18 @@ Sexpr* s_strlen(Sexpr* b, Sexpr* rest, Sexpr* env) { if(STRINGS_STRLEN_ARGS != u64_get_num_args(b)) { return cons(b, rest); } - Sexpr* arg = eval(clone(car(b->value.b.args)), env); + Sexpr* arg = eval(add_ref(car(b->value.b.args)), env); #ifdef TYPECHECK if(unquote(arg)->type != STR) { ERR(STRINGS_STRLEN_STR ": ", "argument not string"); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons(from_nil(), rest); } #endif // typecheck size_t sl = strlen(unquote(arg)->value.str); - sexpr_free(b); - sexpr_free(arg); + dec_ref(b); + dec_ref(arg); return cons (from_uint(sl), rest); } @@ -35,14 +35,14 @@ Sexpr* s_strcat(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* snd = eval(clone(car(args)), env); - Sexpr* fst = eval(clone(car(cdr(args))), env); + Sexpr* snd = eval(add_ref(car(args)), env); + Sexpr* fst = eval(add_ref(car(cdr(args))), env); #ifdef TYPECHECK if(unquote(snd)->type != STR || unquote(fst)->type != STR) { ERR(STRINGS_STRCAT_STR ": ", "arguments not string"); - sexpr_free(snd); - sexpr_free(fst); - sexpr_free(b); + dec_ref(snd); + dec_ref(fst); + dec_ref(b); return cons(from_nil(), rest); } #endif // typecheck @@ -51,9 +51,9 @@ Sexpr* s_strcat(Sexpr* b, Sexpr* rest, Sexpr* env) { char* out = malloc(sizeof(char)*(strlen(fs)+strlen(ss)+1)); strcpy(out, fs); strcat(out, ss); - sexpr_free(snd); - sexpr_free(fst); - sexpr_free(b); + dec_ref(snd); + dec_ref(fst); + dec_ref(b); Sexpr* outval = cons(from_string(out), rest); free(out); return outval; @@ -65,14 +65,14 @@ Sexpr* s_strat(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* index = eval(clone(car(cdr(args))), env); - Sexpr* str = eval(clone(car(args)), env); + Sexpr* index = eval(add_ref(car(cdr(args))), env); + Sexpr* str = eval(add_ref(car(args)), env); #ifdef TYPECHECK if(unquote(str)->type != STR || unquote(index)->type != UINT) { ERR(STRINGS_STRAT_STR ": ", "arguments not string"); - sexpr_free(index); - sexpr_free(str); - sexpr_free(b); + dec_ref(index); + dec_ref(str); + dec_ref(b); return cons(from_nil(), rest); } #endif // typecheck @@ -84,9 +84,9 @@ Sexpr* s_strat(Sexpr* b, Sexpr* rest, Sexpr* env) { } char at[] = { '\0', '\0'}; // for uh string stuff? at[0] = str->value.str[idx-1]; - sexpr_free(b); - sexpr_free(index); - sexpr_free(str); + dec_ref(b); + dec_ref(index); + dec_ref(str); return cons(from_string(at), rest); } @@ -95,12 +95,12 @@ Sexpr* s_strexpand(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* arg = eval(clone(car(args)), env); + Sexpr* arg = eval(add_ref(car(args)), env); #ifdef TYPECHECK if(unquote(arg)->type != STR) { ERR(STRINGS_STREXPAND_STR ": ", "argument not string"); - sexpr_free(arg); - sexpr_free(b); + dec_ref(arg); + dec_ref(b); return cons(from_nil(), rest); } #endif // typecheck @@ -112,8 +112,8 @@ Sexpr* s_strexpand(Sexpr* b, Sexpr* rest, Sexpr* env) { toret = cons(from_string(arr), toret); len--; } - sexpr_free(arg); - sexpr_free(b); + dec_ref(arg); + dec_ref(b); return cons(from_quote(toret), rest); } @@ -122,14 +122,14 @@ Sexpr* s_substr(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* subex = eval(clone(car(cdr(args))), env); - Sexpr* strex = eval(clone(car(args)), env); + Sexpr* subex = eval(add_ref(car(cdr(args))), env); + Sexpr* strex = eval(add_ref(car(args)), env); #ifdef TYPECHECK if(unquote(subex)->type != STR || unquote(strex)->type != STR) { ERR(STRINGS_SUBSTR_STR ": ", "arguments not strings"); - sexpr_free(subex); - sexpr_free(strex); - sexpr_free(b); + dec_ref(subex); + dec_ref(strex); + dec_ref(b); return cons(from_nil(), rest); } #endif @@ -146,11 +146,11 @@ Sexpr* s_substr(Sexpr* b, Sexpr* rest, Sexpr* env) { // not decided if that's how I want it to be though currstr = res + 1; } - sexpr_free(subex); - sexpr_free(strex); - sexpr_free(b); + dec_ref(subex); + dec_ref(strex); + dec_ref(b); Sexpr* newres = reverse(result); - sexpr_free(result); + dec_ref(result); return cons(from_quote(newres), rest); } @@ -159,14 +159,14 @@ Sexpr* s_strtok(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* delimex = eval(clone(car(cdr(args))), env); - Sexpr* strex = eval(clone(car(args)), env); + Sexpr* delimex = eval(add_ref(car(cdr(args))), env); + Sexpr* strex = eval(add_ref(car(args)), env); #ifdef TYPECHECK if(unquote(delimex)->type != STR || unquote(strex)->type != STR) { ERR(STRINGS_STRTOK_STR ": ", "arguments not strings"); - sexpr_free(delimex); - sexpr_free(strex); - sexpr_free(b); + dec_ref(delimex); + dec_ref(strex); + dec_ref(b); return cons(from_nil(), rest); } #endif @@ -179,10 +179,10 @@ Sexpr* s_strtok(Sexpr* b, Sexpr* rest, Sexpr* env) { out = strtok(NULL, delim); } Sexpr* newres = reverse(result); - sexpr_free(b); - sexpr_free(delimex); - sexpr_free(strex); - sexpr_free(result); + dec_ref(b); + dec_ref(delimex); + dec_ref(strex); + dec_ref(result); return cons(from_quote(newres), rest); } @@ -191,12 +191,12 @@ Sexpr* s_tostr(Sexpr* b, Sexpr* rest, Sexpr* env) { return cons(b, rest); } Sexpr* args = b->value.b.args; - Sexpr* arg = eval(clone(car(args)), env); + Sexpr* arg = eval(add_ref(car(args)), env); char* thestr = sprint_sexpr(arg); Sexpr* out = cons(from_string(thestr), rest); free(thestr); - sexpr_free(arg); - sexpr_free(b); + dec_ref(arg); + dec_ref(b); return out; } diff --git a/src/sexpr.c b/src/sexpr.c index bac1d11..ad592e2 100644 --- a/src/sexpr.c +++ b/src/sexpr.c @@ -162,6 +162,18 @@ void sexpr_free(Sexpr* s) { free(s); } +Sexpr* add_ref(Sexpr* s) { + s->refcount++; + return s; +} + +void dec_ref(Sexpr* s) { + s->refcount--; + if(s->refcount == 0) { + sexpr_free(s); + } +} + Sexpr* clone(Sexpr* s) { s->refcount++; return s; diff --git a/src/sexpr.h b/src/sexpr.h index b67788a..165cae3 100644 --- a/src/sexpr.h +++ b/src/sexpr.h @@ -15,6 +15,8 @@ Sexpr* unquote(Sexpr* s); void sexpr_free(Sexpr* s); Sexpr* clone(Sexpr* s); +Sexpr* add_ref(Sexpr* s); +void dec_ref(Sexpr* s); Sexpr* cons(Sexpr* car, Sexpr* cdr); Sexpr* car(Sexpr* s); diff --git a/src/test.c b/src/test.c index 8f91df0..3d78ec6 100644 --- a/src/test.c +++ b/src/test.c @@ -397,7 +397,7 @@ void many_asserts() { // copy-paste this thing as needed assert_eq(env, "", ""); - printf("basics\n"); + printf("> basics\n"); assert_eq(env, "(+ 4 4)", "8"); assert_eq(env, "(* 3 4)", "12"); assert_eq(env, "((+ 3) 7)", "10"); @@ -421,7 +421,7 @@ void many_asserts() { assert_eq(env, "- 100 20", "* 10 8"); assert_eq(env, "/ 100 19", "% 13 8"); - printf("combinators\n"); + printf("> combinators\n"); assert_eq(env, "I + 4 5", "9"); assert_eq(env, "S + (+ 4) 3", "10"); assert_eq(env, "K 5 6", "5"); @@ -440,7 +440,7 @@ void many_asserts() { assert_eq(env, "(Z (B B S (C (eq 0) 1) (B B S * (C B (C - 1)))) 6)", "720"); - printf("strings\n"); + printf("> strings\n"); assert_eq(env, "strlen \"hi\"", "2"); assert_eq(env, "strcat \"hi \" \"there\"", "\"hi there\""); assert_eq(env, "strat 5 \"hello world\"", "\"o\""); @@ -450,14 +450,14 @@ void many_asserts() { assert_eq(env, "strlen \"hey\"", "3"); assert_eq(env, "strcat \"hey \" \"there\"", "\"hey there\""); - printf("meta\n"); + printf("> meta\n"); assert_eq(env, "utob 512", "+"); assert_eq(env, "btou +", "512"); assert_eq(env, "parse \"cons 4 5\"", "quote (cons 4 5)"); // PROBLEM assert_eq(env, "getargs +", "B car list nil"); // PROBLEM assert_eq(env, "getargs (+ 5)", "list 5"); - printf("with demos\n"); + printf("> with demos\n"); assert_eq(env, "fac 5", "120"); assert_eq(env, "range 5", "list 1 2 3 4 5"); assert_eq(env, "reverse (range 3)", "(list 3 2 1)");