delete more elements without overflows.

This commit is contained in:
NunoSempere 2023-05-07 22:59:07 -04:00
parent 789a48ccbc
commit 95118bc1d9
2 changed files with 23 additions and 6 deletions

BIN
mumble

Binary file not shown.

View File

@ -145,6 +145,12 @@ lispval* lispval_builtin_func(lispbuiltin func, char* builtin_func_name)
lispval* lispval_lambda_func(lispval* variables, lispval* manipulation, lispenv* env) lispval* lispval_lambda_func(lispval* variables, lispval* manipulation, lispenv* env)
{ {
/* correct idiom for calling this:
lispval* variables = clone_lispval(v->cell[0]);
lispval* manipulation = clone_lispval(v->cell[1]);
lispenv* env = NULL; // clone_lispval(blah)
lispval* lambda = lispval_lambda_func(variables, manipulation, NULL);
*/
if (VERBOSE) { if (VERBOSE) {
printfln("Allocating user-defined function"); printfln("Allocating user-defined function");
} }
@ -157,6 +163,8 @@ lispval* lispval_lambda_func(lispval* variables, lispval* manipulation, lispenv*
// Previously: unclear how to garbage-collect this. Maybe add to a list and collect at the end? // Previously: unclear how to garbage-collect this. Maybe add to a list and collect at the end?
// Now: Hah! Lambda functions are just added to the environment, so they will just // Now: Hah! Lambda functions are just added to the environment, so they will just
// be destroyed when it is destroyed. // be destroyed when it is destroyed.
// But no! in def {id} (@ {x} {x}), there is a copy of a lambda function in
// the arguments to def. Aarg!
if (VERBOSE) { if (VERBOSE) {
printfln("Allocated user-defined function"); printfln("Allocated user-defined function");
} }
@ -259,11 +267,13 @@ void delete_lispval(lispval* v)
v->env = NULL; v->env = NULL;
} }
if (v->variables != NULL) { if (v->variables != NULL) {
// not deleting these for now.
// delete_lispval(v->variables); // delete_lispval(v->variables);
// free(v->variables) // free(v->variables)
// v->variables = NULL; // v->variables = NULL;
} }
if (v->manipulation != NULL) { if (v->manipulation != NULL) {
// not deleting these for now.
// delete_lispval(v->manipulation); // delete_lispval(v->manipulation);
// free(v->manipulation); // free(v->manipulation);
// v->manipulation = NULL; // v->manipulation = NULL;
@ -631,7 +641,11 @@ lispval* clone_lispval(lispval* old)
break; break;
case LISPVAL_USER_FUNC: case LISPVAL_USER_FUNC:
if(VERBOSE) printfln("Cloning function. This generally shouldn't be happening, given that I've decided to just add functions to the environment and just clean them when the environment is cleaned. One situation where it should happen is in def {id} (@ {x} {x}), there is a lambda function in the arguments, which should get collected. "); if(VERBOSE) printfln("Cloning function. This generally shouldn't be happening, given that I've decided to just add functions to the environment and just clean them when the environment is cleaned. One situation where it should happen is in def {id} (@ {x} {x}), there is a lambda function in the arguments, which should get collected. ");
new = lispval_lambda_func(old->variables, old->manipulation, old->env); lispval* variables = clone_lispval(old->variables);
lispval* manipulation = clone_lispval(old->manipulation);
lispenv* env = clone_lispenv(old->env);
new = lispval_lambda_func(variables, manipulation, env);
// new = lispval_lambda_func(old->variables, old->manipulation, old->env);
// Also, fun to notice how these choices around implementation would determine tricky behaviour details around variable shadowing. // Also, fun to notice how these choices around implementation would determine tricky behaviour details around variable shadowing.
break; break;
case LISPVAL_SEXPR: case LISPVAL_SEXPR:
@ -805,9 +819,9 @@ lispval* builtin_define_lambda(lispval* v, lispenv* env)
// def { {plus} {{@ {x y} {+ x y}} }} // def { {plus} {{@ {x y} {+ x y}} }}
// (eval plus) 1 2 // (eval plus) 1 2
// (@ { {x y} { + x y } }) 1 2 // (@ { {x y} { + x y } }) 1 2
LISPVAL_ASSERT(v->count == 2, "Lambda definition requires two arguments; try @ { {x y} { + x y } }"); LISPVAL_ASSERT(v->count == 2, "Lambda definition requires two arguments; try (@ {x y} { + x y }) ");
LISPVAL_ASSERT(v->cell[0]->type == LISPVAL_QEXPR, "Lambda definition (@) requires that the first sub-arg be a q-expression; try @ { {x y} { + x y } }"); LISPVAL_ASSERT(v->cell[0]->type == LISPVAL_QEXPR, "Lambda definition (@) requires that the first sub-arg be a q-expression; try @ {x y} { + x y }");
LISPVAL_ASSERT(v->cell[1]->type == LISPVAL_QEXPR, "Lambda definition (@) requires that the second sub-arg be a q-expression; try @ { {x y} { + x y } }"); LISPVAL_ASSERT(v->cell[1]->type == LISPVAL_QEXPR, "Lambda definition (@) requires that the second sub-arg be a q-expression; try @ {x y} { + x y }");
lispval* variables = clone_lispval(v->cell[0]); lispval* variables = clone_lispval(v->cell[0]);
lispval* manipulation = clone_lispval(v->cell[1]); lispval* manipulation = clone_lispval(v->cell[1]);
@ -815,8 +829,9 @@ lispval* builtin_define_lambda(lispval* v, lispenv* env)
for (int i = 0; i > variables->count; i++) { for (int i = 0; i > variables->count; i++) {
LISPVAL_ASSERT(variables->cell[i]->type == LISPVAL_SYM, "First argument in function definition must only be symbols. Try @ { {x y} { + x y } }"); LISPVAL_ASSERT(variables->cell[i]->type == LISPVAL_SYM, "First argument in function definition must only be symbols. Try @ { {x y} { + x y } }");
} }
lispenv* new_env = clone_lispenv(env);
lispval* lambda = lispval_lambda_func(variables, manipulation, NULL); // So env at the time of creation!
lispval* lambda = lispval_lambda_func(variables, manipulation, new_env);
return lambda; return lambda;
} }
// Simple math ops // Simple math ops
@ -1048,6 +1063,8 @@ lispval* evaluate_lispval(lispval* l, lispenv* env)
lispval* temp_expression = clone_lispval(f->manipulation); lispval* temp_expression = clone_lispval(f->manipulation);
temp_expression->type = LISPVAL_SEXPR; temp_expression->type = LISPVAL_SEXPR;
lispval* answer = evaluate_lispval(temp_expression, evaluation_env); lispval* answer = evaluate_lispval(temp_expression, evaluation_env);
// delete_lispval(temp_expression);
// delete_lispenv(evaluation_env);
// lispval* answer = builtin_eval(f->manipulation, f->env); // lispval* answer = builtin_eval(f->manipulation, f->env);
// destroy_lispenv(f->env); // destroy_lispenv(f->env);
return answer; return answer;