From 50d6dd8b50958271bf1ff13f99dc21d4cd8431f7 Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Thu, 13 Jan 2022 19:45:22 +0000 Subject: Implement basic reference counting for arrays, which so they get freed when not in use anymore. --- eval.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'eval.c') diff --git a/eval.c b/eval.c index ae7dbd7..2eb5abd 100644 --- a/eval.c +++ b/eval.c @@ -104,7 +104,13 @@ retry: errormsg = L"No reduce rule. Syntax error."; return nil; }else{ - stmt->toks[offset] = fn(stmt->toks[offset],stmt->toks[offset+1]); + Datum new = fn(stmt->toks[offset],stmt->toks[offset+1]); + if(stmt->toks[offset].tag == ArrayTag) + freearray(stmt->toks[offset].array); + if(stmt->toks[offset+1].tag == ArrayTag) + freearray(stmt->toks[offset+1].array); + + stmt->toks[offset] = new; for(int i = offset+1; i < stmt->ntoks-1; i++) stmt->toks[i] = stmt->toks[i+1]; stmt->ntoks--; @@ -126,8 +132,13 @@ lookup(Datum var) if(var.symbol->undefined){ errormsg = runesmprint("Variable undefined: %S\n", var.symbol->name); return nil; - }else - return &var.symbol->value; + }else{ + Datum *val = &var.symbol->value; + val->shy = 0; + if(val->tag == ArrayTag) + incref(val->array); /* since the value is now in the var AND in the code */ + return val; + } } Datum @@ -136,11 +147,13 @@ strand(Datum left, Datum right) traceprint("Stranding (%d %d)\n", left.array->stranded, right.array->stranded); Datum result; result.shy = 0; - Array *leftarr = left.array->stranded ? left.array : fnEnclose(left.array); - Array *rightarr = right.array->stranded ? right.array : fnEnclose(right.array); + Array *leftarr = left.array->stranded ? fnSame(left.array) : fnEnclose(left.array); + Array *rightarr = right.array->stranded ? fnSame(right.array) : fnEnclose(right.array); result.tag = ArrayTag; result.array = fnCatenateFirst(leftarr, rightarr); result.array->stranded = 1; + freearray(leftarr); + freearray(rightarr); return result; } @@ -159,14 +172,17 @@ monadfun(Datum left, Datum right) Symbol *alpha = getsym(currentsymtab, L"⍺"); alpha->value.tag = ArrayTag; alpha->value.array = left.func.left; + /* no need to increment refs, since it was done on binding the arg */ alpha->undefined = 0; } Symbol *omega = getsym(currentsymtab, L"⍵"); omega->value = right; omega->undefined = 0; + incref(right.array); Datum *dfnres = evalline(left.func.dfn); + freesymtab(currentsymtab); currentsymtab = tmpsymtab; return *dfnres; /* TODO what if the evaluation failed */ }else{ @@ -176,6 +192,10 @@ monadfun(Datum left, Datum right) else result.array = monadfunctiondefs[left.func.code](right.array); } + + if(left.func.left) + freearray(left.func.left); + return result; } @@ -188,6 +208,7 @@ dyadfun(Datum left, Datum right) result.tag = BoundFunctionTag, result.func = right.func; result.func.left = left.array; + incref(left.array); return result; } @@ -219,8 +240,11 @@ assign(Datum left, Datum right) { left.symbol->value = right; /* TODO think about this*/ left.symbol->undefined = 0; - if(left.symbol->value.tag == ArrayTag) + if(left.symbol->value.tag == ArrayTag){ left.symbol->value.array->stranded = 0; + incref(right.array); /* for the binding */ + incref(right.array); /* for the returned array */ + } right.shy = 1; return right; } \ No newline at end of file -- cgit v1.2.3