From 6ed5b9f6d3fdeeed8ecd43b18bae642ec1ec24b1 Mon Sep 17 00:00:00 2001 From: Peter Mikkelsen Date: Wed, 9 Feb 2022 01:16:03 +0000 Subject: Add much better memory handling (We now track and free Datum * structs) --- eval.c | 364 ++++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 182 insertions(+), 182 deletions(-) (limited to 'eval.c') diff --git a/eval.c b/eval.c index 1d54e42..b7515b1 100644 --- a/eval.c +++ b/eval.c @@ -8,19 +8,19 @@ int traceeval; -typedef Datum (*evalfn)(Datum, Datum); - -Datum strand(Datum, Datum); -Datum monadfun(Datum, Datum); -Datum dyadfun(Datum, Datum); -Datum parens(Datum, Datum); -Datum nameis(Datum, Datum); -Datum namesis(Datum, Datum); -Datum assign(Datum, Datum); -Datum monadop(Datum, Datum); -Datum dyadop(Datum, Datum); -Datum train(Datum, Datum); -Datum *lookup(Datum); +typedef Datum *(*evalfn)(Datum *, Datum *); + +Datum *strand(Datum *, Datum *); +Datum *monadfun(Datum *, Datum *); +Datum *dyadfun(Datum *, Datum *); +Datum *parens(Datum *, Datum *); +Datum *nameis(Datum *, Datum *); +Datum *namesis(Datum *, Datum *); +Datum *assign(Datum *, Datum *); +Datum *monadop(Datum *, Datum *); +Datum *dyadop(Datum *, Datum *); +Datum *train(Datum *, Datum *); +Datum *lookup(Datum *); int bindingstrengths[11][11] = { /* A F H MO DO AF ( ) ← IS N */ @@ -56,8 +56,11 @@ Datum * eval(Statement *stmt, int toplevel) { /* start by looking up first variable if needed */ - if(stmt->ntoks > 0 && stmt->toks[stmt->ntoks-1].tag == NameTag) - stmt->toks[stmt->ntoks-1] = *lookup(stmt->toks[stmt->ntoks-1]);; + if(stmt->ntoks > 0 && stmt->toks[stmt->ntoks-1]->tag == NameTag){ + Datum *var = stmt->toks[stmt->ntoks-1]; + stmt->toks[stmt->ntoks-1] = lookup(var); + freedatum(var); + } while(stmt->ntoks > 1){ int maxlevel = 0; @@ -70,18 +73,20 @@ retry: if(offset == 0) level = 0; else{ - Datum left = stmt->toks[offset-1]; - Datum right = stmt->toks[offset]; - level = bindingstrengths[left.tag][right.tag]; + Datum *left = stmt->toks[offset-1]; + Datum *right = stmt->toks[offset]; + level = bindingstrengths[left->tag][right->tag]; } - if(level == 0 && stmt->toks[offset-1].tag == NameTag){ - stmt->toks[offset-1] = *lookup(stmt->toks[offset-1]); + if(level == 0 && offset > 0 && stmt->toks[offset-1]->tag == NameTag){ + Datum *var = stmt->toks[offset-1]; + stmt->toks[offset-1] = lookup(var); + freedatum(var); goto retry; }else if(level < maxlevel){ - Datum left = stmt->toks[offset]; - Datum right = stmt->toks[offset+1]; - fn = evalfns[left.tag][right.tag]; + Datum *left = stmt->toks[offset]; + Datum *right = stmt->toks[offset+1]; + fn = evalfns[left->tag][right->tag]; traceprint("Reducing %S and %S (fn=%p, level=%d, max=%d)\n", ppdatum(left), ppdatum(right), fn, level, maxlevel); break; }else if(level > maxlevel) @@ -90,13 +95,10 @@ retry: if(maxlevel == 0) throwerror(L"No reduce rule", EParse); else{ - Datum new = fn(stmt->toks[offset],stmt->toks[offset+1]); + Datum *new = fn(stmt->toks[offset], stmt->toks[offset+1]); traceprint("handler fn done\n"); - if(stmt->toks[offset].tag == ArrayTag) - freearray(stmt->toks[offset].array); - if(stmt->toks[offset+1].tag == ArrayTag) - freearray(stmt->toks[offset+1].array); - + freedatum(stmt->toks[offset]); + freedatum(stmt->toks[offset+1]); stmt->toks[offset] = new; for(int i = offset+1; i < stmt->ntoks-1; i++) stmt->toks[i] = stmt->toks[i+1]; @@ -105,42 +107,42 @@ retry: } if(stmt->ntoks == 1){ int stop = 0; - if(toplevel == 0 && !stmt->toks[0].shy) + if(toplevel == 0 && !stmt->toks[0]->shy) stop = 1; if(stmt->guard){ int guardOK = 1; - if(stmt->toks[0].tag != ArrayTag) + if(stmt->toks[0]->tag != ArrayTag) guardOK = 0; - else if(stmt->toks[0].array->size != 1) + else if(stmt->toks[0]->array->size != 1) guardOK = 0; - else if(stmt->toks[0].array->type != AtypeInt) + else if(stmt->toks[0]->array->type != AtypeInt) guardOK = 0; - else if(stmt->toks[0].array->intdata[0] != 0 && stmt->toks[0].array->intdata[0] != 1) + else if(stmt->toks[0]->array->intdata[0] != 0 && stmt->toks[0]->array->intdata[0] != 1) guardOK = 0; if(!guardOK) throwerror(L"Guard expected single valued boolean", EDomain); else{ stop = 0; - if(stmt->toks[0].array->intdata[0] == 1) + if(stmt->toks[0]->array->intdata[0] == 1) return eval(stmt->guard, toplevel); } } if(stmt->next && !stop) return eval(stmt->next, toplevel); else - return stmt->toks; + return stmt->toks[0]; }else return nil; } Datum * -lookup(Datum var) +lookup(Datum *var) { - traceprint("VAR LOOKUP %S\n", var.name); - Symbol *symbol = getsym(var.name, 0); + traceprint("VAR LOOKUP %S\n", var->name); + Symbol *symbol = getsym(var->name, 0); if(symbol->undefined){ - Rune *msg = runesmprint("Undefined name: %S", var.name); + Rune *msg = runesmprint("Undefined name: %S", var->name); throwerror(msg, EValue); } @@ -148,236 +150,234 @@ lookup(Datum var) if(symbol->getfn != nil) val = symbol->getfn(); else{ - val = &symbol->value; - if(val->tag == ArrayTag) - incarrayref(val->array); /* since the value is now in the var AND in the code */ + val = symbol->value; + incdatumref(val); } val->shy = 0; - traceprint("VAR %S = %S\n", var.name, ppdatum(*val)); + traceprint("VAR %S = %S\n", var->name, ppdatum(val)); return val; } -Datum -strand(Datum left, Datum right) +Datum * +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 ? fnSame(left.array) : fnEnclose(left.array); - Array *rightarr = right.array->stranded ? fnSame(right.array) : fnEnclose(right.array); + traceprint("Stranding (%d %d)\n", left->array->stranded, right->array->stranded); + Datum *result = allocdatum(ArrayTag, 0); + Array *leftarr = left->array->stranded ? fnSame(left->array) : fnEnclose(left->array); + Array *rightarr = right->array->stranded ? fnSame(right->array) : fnEnclose(right->array); Array *tmp = fnCatenateFirst(leftarr, rightarr); - result.tag = ArrayTag; - result.array = simplifyarray(tmp); - result.array->stranded = 1; + result->array = simplifyarray(tmp); + result->array->stranded = 1; freearray(tmp); freearray(leftarr); freearray(rightarr); return result; } -Datum -monadfun(Datum left, Datum right) +Datum * +monadfun(Datum *left, Datum *right) { traceprint("Monadic function application\n"); - Datum result; - result.tag = ArrayTag; - result.shy = 0; - result.array = runfunc(left.func, left.func.left, right.array); + Datum *result = allocdatum(ArrayTag, 0); + result->array = runfunc(left->func, left->func.left, right->array); return result; } -Datum -dyadfun(Datum left, Datum right) +Datum * +dyadfun(Datum *left, Datum *right) { traceprint("Applying left argument to function\n"); - Datum result; - result.shy = 0; - result.tag = BoundFunctionTag; - if(right.tag == FunctionTag) - result.func = right.func; - else if(right.tag == HybridTag){ - result.func.type = FunctypeHybrid; - result.func.code = right.hybrid; + Datum *result = allocdatum(BoundFunctionTag, 0); + if(right->tag == FunctionTag) + result->func = dupfunction(right->func); + else if(right->tag == HybridTag){ + result->func.type = FunctypeHybrid; + result->func.code = right->hybrid; } - result.func.left = left.array; - incarrayref(left.array); + result->func.left = fnSame(left->array); return result; } -Datum -parens(Datum left, Datum right) +Datum * +parens(Datum *left, Datum *right) { /* evaluate a parenthesis expression and return the result */ USED(right); - traceprint("PARENS: %S\n", ppdatums(left.stmt.toks, left.stmt.ntoks)); - Datum *result = eval(&left.stmt, 1); - if(result[0].tag == ArrayTag) - result[0].array->stranded = 0; - result[0].shy = 0; - return result[0]; /* TODO handle error if ntoks != 1 */ + traceprint("PARENS: %S\n", ppdatums(left->stmt.toks, left->stmt.ntoks)); + Datum *result = eval(&left->stmt, 1); + incdatumref(result); + if(result->tag == ArrayTag) + result->array->stranded = 0; + result->shy = 0; + return result; /* TODO handle error if ntoks != 1 */ } -Datum -nameis(Datum left, Datum right) +Datum * +nameis(Datum *left, Datum *right) { - traceprint("NAMEIS %S←\n", left.name); - right.tag = AssignmentTag; - right.names.ntoks = 1; - right.names.toks = malloc(sizeof(Datum)); - right.names.toks[0] = left; - return right; + USED(right); + traceprint("NAMEIS %S←\n", left->name); + Datum *result = allocdatum(AssignmentTag, 0); + result->names.ntoks = 1; + result->names.toks = emalloc(sizeof(Datum*)); + result->names.toks[0] = left; + incdatumref(left); + return result; } -Datum -namesis(Datum left, Datum right) +Datum * +namesis(Datum *left, Datum *right) { - if(left.tag == RParTag) + if(left->tag == RParTag){ + incdatumref(right); return right; + } traceprint("NAMES IS %S %S\n", ppdatum(left), ppdatum(right)); - right.tag = AssignmentTag; - right.names = left.stmt; - return right; + Datum *result = allocdatum(AssignmentTag, 0); + result->names.ntoks = left->stmt.ntoks; + result->names.toks = emalloc(sizeof(Datum*) * result->names.ntoks); + for(int i = 0; i < result->names.ntoks; i++){ + result->names.toks[i] = left->stmt.toks[i]; + incdatumref(result->names.toks[i]); + } + return result; } -Datum -assign(Datum left, Datum right) +Datum * +assign(Datum *left, Datum *right) { traceprint("ASSIGN %S %S\n", ppdatum(left), ppdatum(right)); - if(left.names.ntoks == 1){ - if(left.names.toks[0].tag != NameTag) + if(left->names.ntoks == 1){ + traceprint("Assign single\n"); + if(left->names.toks[0]->tag != NameTag) throwerror(nil, ESyntax); - Symbol *symbol = getsym(left.names.toks[0].name, 0); + Symbol *symbol = getsym(left->names.toks[0]->name, 0); if(symbol->setfn != nil) symbol->setfn(right); else{ /* re-assign the symbol to one that is sure to be local. This enables shadowing */ symbol = getsym(symbol->name, 1); - if(symbol->undefined == 0 && symbol->value.tag == ArrayTag) - freearray(symbol->value.array); + if(symbol->undefined == 0) + freedatum(symbol->value); symbol->value = right; + incdatumref(right); symbol->undefined = 0; - if(symbol->value.tag == ArrayTag){ - symbol->value.array->stranded = 0; - incarrayref(right.array); /* for the binding */ - } + if(symbol->value->tag == ArrayTag) + symbol->value->array->stranded = 0; } }else{ - if(right.tag != ArrayTag) + if(right->tag != ArrayTag) throwerror(nil, ESyntax); - if(right.array->rank != 1 && right.array->rank != 0) + if(right->array->rank != 1 && right->array->rank != 0) throwerror(nil, ERank); int nlocs = 0; - Datum *locations = nil; - for(int i = 0; i < left.names.ntoks; i++){ - Datum loc = left.names.toks[i]; - if(loc.tag == NameTag){ + Datum **locations = nil; + for(int i = 0; i < left->names.ntoks; i++){ + Datum *loc = left->names.toks[i]; + if(loc->tag == NameTag){ nlocs++; - locations = realloc(locations, sizeof(Datum) * nlocs); - locations[nlocs-1].tag = AssignmentTag; - locations[nlocs-1].names.ntoks = 1; - locations[nlocs-1].names.toks = malloc(sizeof(Datum)); - locations[nlocs-1].names.toks[0] = loc; - }else if(loc.tag == LParTag){ + locations = erealloc(locations, sizeof(Datum*) * nlocs); + locations[nlocs-1] = allocdatum(AssignmentTag, 0); + locations[nlocs-1]->names.ntoks = 1; + locations[nlocs-1]->names.toks = emalloc(sizeof(Datum*)); + locations[nlocs-1]->names.toks[0] = loc; + incdatumref(loc); + }else if(loc->tag == LParTag){ i++; nlocs++; - locations = realloc(locations, sizeof(Datum) * nlocs); - locations[nlocs-1].tag = AssignmentTag; - locations[nlocs-1].names = loc.stmt; + locations = erealloc(locations, sizeof(Datum*) * nlocs); + locations[nlocs-1] = allocdatum(AssignmentTag, 0); + locations[nlocs-1]->names.ntoks = loc->stmt.ntoks; + locations[nlocs-1]->names.toks = emalloc(sizeof(Datum*) * loc->stmt.ntoks); + for(int j = 0; j < loc->stmt.ntoks; j++){ + locations[nlocs-1]->names.toks[j] = loc->stmt.toks[j]; + incdatumref(loc->stmt.toks[j]); + } } } - if(right.array->rank == 1 && right.array->size != nlocs) + if(right->array->rank == 1 && right->array->size != nlocs) throwerror(nil, ELength); for(int i = 0; i < nlocs; i++){ - if(right.array->rank == 0) - assign(locations[i], right); + Datum *item; + if(right->array->rank == 0) + item = right; else{ - Datum item; - item.tag = ArrayTag; - item.array = arrayitem(right.array, i); - assign(locations[i], item); - freearray(item.array); + item = allocdatum(ArrayTag, 0); + item->array = arrayitem(right->array, i); } + assign(locations[i], item); + freedatum(item); /* free the returned item */ + if(item != right) + freedatum(item); + freedatum(locations[i]); } } - right.shy = 1; - if(right.tag == ArrayTag) - incarrayref(right.array); /* for the returned array */ - return right; + Datum *result = right; + incdatumref(right); + result->shy = 1; + return result; } -Datum -monadop(Datum left, Datum right) +Datum * +monadop(Datum *left, Datum *right) { traceprint("Applying left argument to operator\n"); - Datum *arg = emalloc(sizeof(Datum)); - *arg = left; - - Datum result; - result.shy = 0; - result.tag = FunctionTag, - result.func.type = FunctypeOp; - if(right.tag == MonadicOpTag || right.tag == DyadicOpTag) - result.func.operator = right.operator; + Datum *result = allocdatum(FunctionTag, 0); + result->func.type = FunctypeOp; + if(right->tag == MonadicOpTag || right->tag == DyadicOpTag) + result->func.operator = dupoperator(right->operator); else{ - result.func.operator.type = OperatortypeHybrid; - result.func.operator.code = right.hybrid; + result->func.operator.type = OperatortypeHybrid; + result->func.operator.code = right->hybrid; } - result.func.operator.left = arg; - result.func.left = nil; - if(arg->tag == ArrayTag) - incarrayref(arg->array); + result->func.operator.left = left; + incdatumref(left); + result->func.left = nil; return result; } -Datum -dyadop(Datum left, Datum right) +Datum * +dyadop(Datum *left, Datum *right) { traceprint("Applying right argument to operator\n"); - Datum *arg = emalloc(sizeof(Datum)); - *arg = right; - - Datum result; - result.shy = 0; - result.tag = MonadicOpTag, - result.operator = left.operator; - result.operator.right = arg; - if(arg->tag == ArrayTag) - incarrayref(arg->array); + Datum *result = allocdatum(MonadicOpTag, 0); + result->operator = dupoperator(left->operator); + result->operator.right = right; + incdatumref(right); return result; } -Datum -train(Datum left, Datum right) +Datum * +train(Datum *left, Datum *right) { - Datum result; - result.shy = 0; - result.tag = FunctionTag; - result.func.type = FunctypeTrain; - result.func.left = nil; - if(left.func.type == FunctypeTrain) - result.func = left.func; + traceprint("Creating train from %S and %S\n", ppdatum(left), ppdatum(right)); + Datum *result = allocdatum(FunctionTag, 0); + result->func.type = FunctypeTrain; + result->func.left = nil; + if(left->func.type == FunctypeTrain) + result->func = left->func; else{ - result.func.train.nfuncs = 1; - result.func.train.funcs = malloc(sizeof(Function)); - result.func.train.funcs[0] = left.func; + result->func.train.nfuncs = 1; + result->func.train.funcs = emalloc(sizeof(Function)); + result->func.train.funcs[0] = dupfunction(left->func); } - if(right.func.type == FunctypeTrain){ - int oldn = result.func.train.nfuncs; - result.func.train.nfuncs = oldn + right.func.train.nfuncs; - result.func.train.funcs = realloc(result.func.train.funcs, sizeof(Function) * result.func.train.nfuncs); - for(int i = 0; i < right.func.train.nfuncs; i++) - result.func.train.funcs[oldn + i] = right.func.train.funcs[i]; + if(right->func.type == FunctypeTrain){ + int oldn = result->func.train.nfuncs; + result->func.train.nfuncs = oldn + right->func.train.nfuncs; + result->func.train.funcs = erealloc(result->func.train.funcs, sizeof(Function) * result->func.train.nfuncs); + for(int i = 0; i < right->func.train.nfuncs; i++) + result->func.train.funcs[oldn + i] = dupfunction(right->func.train.funcs[i]); }else{ - result.func.train.nfuncs++; - result.func.train.funcs = realloc(result.func.train.funcs, sizeof(Function) * result.func.train.nfuncs); - result.func.train.funcs[result.func.train.nfuncs-1] = right.func; + result->func.train.nfuncs++; + result->func.train.funcs = erealloc(result->func.train.funcs, sizeof(Function) * result->func.train.nfuncs); + result->func.train.funcs[result->func.train.nfuncs-1] = dupfunction(right->func); } return result; } \ No newline at end of file -- cgit v1.2.3