diff options
-rw-r--r-- | apl9.h | 30 | ||||
-rw-r--r-- | array.c | 5 | ||||
-rw-r--r-- | concurrency.c | 10 | ||||
-rw-r--r-- | eval.c | 364 | ||||
-rw-r--r-- | functions.c | 28 | ||||
-rw-r--r-- | lexer.c | 76 | ||||
-rw-r--r-- | main.c | 54 | ||||
-rw-r--r-- | memory.c | 223 | ||||
-rw-r--r-- | operators.c | 2 | ||||
-rw-r--r-- | print.c | 32 | ||||
-rw-r--r-- | quadnames.c | 74 | ||||
-rw-r--r-- | symbol.c | 64 | ||||
-rw-r--r-- | tests/chain.apl | 8 | ||||
-rw-r--r-- | tests/queens.apl | 5 |
14 files changed, 583 insertions, 392 deletions
@@ -104,7 +104,7 @@ struct Array struct Statement { int ntoks; - Datum *toks; + Datum **toks; Statement *guard; Statement *next; }; @@ -144,6 +144,7 @@ struct Datum { datumTag tag; int shy; + int refs; union { Array *array; Statement stmt; @@ -159,9 +160,9 @@ struct Symbol { int undefined; Rune *name; - Datum value; + Datum *value; Datum *(*getfn)(void); - void (*setfn)(Datum); + void (*setfn)(Datum *); }; struct Symtab @@ -182,7 +183,7 @@ struct QuadnameDef Rune *name; datumTag tag; Datum *(*get)(void); - void (*set)(Datum); + void (*set)(Datum *); fnmonad monadfn; fndyad dyadfn; opmonad monadop; @@ -225,11 +226,10 @@ struct Mail /* Function prototypes for the different source files */ /* main.c */ Datum *evalline(Rune *, Biobuf *, int); -Rune *prompt(Rune *); /* print.c */ -Rune *ppdatum(Datum); -Rune *ppdatums(Datum *, int); +Rune *ppdatum(Datum *); +Rune *ppdatums(Datum **, int); Rune *pparray(Array *); Rune *ppoperator(Operator); Rune *ppfunction(Function); @@ -273,11 +273,20 @@ void globalDIVset(int); /* memory.c */ void *emalloc(ulong); +void *emallocz(ulong, int); +void *erealloc(void *, ulong); void checkmem(char *); - Array *allocarray(int, int, int); void freearray(Array *); void incarrayref(Array *); +Datum *allocdatum(int, int); +void freedatum(Datum *); +void incdatumref(Datum *); +void freefunction(Function); +void freeoperator(Operator); +void freestatement(Statement); +Function dupfunction(Function); +Operator dupoperator(Operator); /* functions.c */ Array *runfunc(Function, Array *,Array *); @@ -286,7 +295,7 @@ Array *runtrain(Function *, int, Array *, Array *, Array *); /* quadnames.c */ void initquadnames(void); -Datum quadnamedatum(QuadnameDef); +Datum *quadnamedatum(QuadnameDef); /* error.c */ void throwerror(Rune *, int); @@ -442,7 +451,8 @@ extern opmonad monadoperatordefs[]; /* operators.c */ extern opdyad dyadoperatordefs[]; /* operators.c */ extern fndyad hybridfunctiondefs[]; /* hybrids.c */ extern opmonad hybridoperatordefs[]; /* hybrids.c */ -extern int alloccounts; /* memory.c */ +extern int arrayalloccounts; /* memory.c */ +extern int datumalloccounts; /* memory.c */ extern QuadnameDef quadnames[]; /* quadnames.c */ extern int printprecision; /* print.c */ extern ErrorHandler globalerror; /* error.c */ @@ -1,5 +1,6 @@ #include <u.h> #include <libc.h> +#include <thread.h> #include <bio.h> #include "apl9.h" @@ -324,7 +325,7 @@ comparearray(Array *a, Array *b, int checkshapes) break; default: print("Missing comparison code for type %d\n", a->type); - exits(nil); + threadexitsall(nil); } if(sub != 0) return sub; @@ -364,7 +365,7 @@ fillelement(Array *a) } default: print("Can't make fill element of array type %d\n", a->type); - exits(nil); + threadexitsall(nil); return 0; } } diff --git a/concurrency.c b/concurrency.c index 4af563c..c393884 100644 --- a/concurrency.c +++ b/concurrency.c @@ -4,7 +4,7 @@ #include <bio.h> #include "apl9.h" -#define STACKSIZE (8*1024*1024) /* 8 MB */ +#define STACKSIZE (8*1024*1024) /* 64 MB */ typedef struct SpawnData SpawnData; struct SpawnData @@ -48,7 +48,7 @@ spawnthread(Function f, Array *left, Array *right) exit proc */ Channel *setupdone = chancreate(sizeof(int), 0); - SpawnData *sp = malloc(sizeof(SpawnData)); + SpawnData *sp = emalloc(sizeof(SpawnData)); sp->func = f; sp->left = left ? duparray(left) : nil; sp->right = duparray(right); @@ -77,7 +77,7 @@ messagesend(Array *a, int id) unlock(&threadlock); if(td != nil){ qlock(&td->lock); - Mail *newmail = malloc(sizeof(Mail)); + Mail *newmail = emalloc(sizeof(Mail)); newmail->contents = fnSame(a); newmail->next = 0; if(td->lastmail != nil) @@ -132,7 +132,7 @@ newprocfn(void *data) static ThreadData * newthreaddata(void) { - ThreadData *td = mallocz(sizeof(ThreadData), 1); + ThreadData *td = emallocz(sizeof(ThreadData), 1); td->id = threadid(); td->currentdfn = nil; td->mail = 0; @@ -141,7 +141,7 @@ newthreaddata(void) lock(&threadlock); nthreads++; - threads = realloc(threads, sizeof(ThreadData *) * nthreads); + threads = erealloc(threads, sizeof(ThreadData *) * nthreads); threads[nthreads-1] = td; unlock(&threadlock); return td; @@ -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 diff --git a/functions.c b/functions.c index 46f9782..7c49554 100644 --- a/functions.c +++ b/functions.c @@ -145,7 +145,9 @@ runfunc(Function f, Array *left, Array *right) Datum *dfnres = evalline(code, nil, 0); popdfnframe(); - result = (*dfnres).array; /* TODO what if the evaluation failed */ + result = dfnres->array; /* TODO what if the evaluation failed */ + incarrayref(result); + freedatum(dfnres); }else if(f.type == FunctypePrim){ if(left){ fndyad d = dyadfunctiondefs[f.code]; @@ -525,7 +527,7 @@ fnMix(Array *right) for(j = 0; j < commonshape->size; j++) result->shape[i+j] = commonshape->intdata[j]; - int *index = malloc(sizeof(int) * commonrank); + int *index = emalloc(sizeof(int) * commonrank); int offset; for(i = 0; i < size/commonsize; i++){ Array *a = right->arraydata[i]; @@ -618,7 +620,7 @@ fnGradeUp(Array *right) int i,j; int len = right->shape[0]; - Array **elems = malloc(sizeof(Array *) * len); + Array **elems = emalloc(sizeof(Array *) * len); Array *index = mkscalarint(globalIO()); Array *order = allocarray(AtypeInt, 1, len); order->shape[0] = len; @@ -740,7 +742,7 @@ fnRavel(Array *right) { Array *res = duparray(right); res->rank = 1; - res->shape = realloc(res->shape, sizeof(int) * 1); + res->shape = erealloc(res->shape, sizeof(int) * 1); res->shape[0] = res->size; return res; } @@ -750,7 +752,7 @@ fnTable(Array *right) { Array *res = duparray(right); res->rank = 2; - res->shape = realloc(res->shape, sizeof(int) * 2); + res->shape = erealloc(res->shape, sizeof(int) * 2); res->shape[0] = right->rank ? res->shape[0] : 1; res->shape[1] = right->size / res->shape[0]; return res; @@ -814,8 +816,8 @@ fnTranspose(Array *right) res->shape[i] = right->shape[res->rank - 1 - i]; int from, to; - int *sizesFrom = malloc(sizeof(int) * right->rank); - int *sizesTo = malloc(sizeof(int) * right->rank); + int *sizesFrom = emalloc(sizeof(int) * right->rank); + int *sizesTo = emalloc(sizeof(int) * right->rank); int accFrom = 1, accTo = 1; for(int i = 0; i < right->rank; i++){ sizesFrom[i] = accFrom; @@ -1289,7 +1291,7 @@ fnTake(Array *left, Array *right) if(right->rank == 0){ right = duparray(right); right->rank = left->size; - right->shape = realloc(right->shape, sizeof(int) * right->rank); + right->shape = erealloc(right->shape, sizeof(int) * right->rank); for(i = 0; i < right->rank; i++) right->shape[i] = 1; }else @@ -1306,7 +1308,7 @@ fnTake(Array *left, Array *right) left->intdata[i] = old->intdata[i]; } - int *shape = malloc(sizeof(int) * left->size); + int *shape = emalloc(sizeof(int) * left->size); int size = 1; for(i = 0; i < left->size; i++){ int s = left->intdata[i]; @@ -1319,7 +1321,7 @@ fnTake(Array *left, Array *right) for(i = 0; i < right->rank; i++) result->shape[i] = shape[i]; - int *index = mallocz(sizeof(int) * left->size, 1); + int *index = emallocz(sizeof(int) * left->size, 1); int fromindex; for(i = 0; i < size; i++){ for(int j = left->size-1; index[j] == shape[j]; j--){ @@ -1378,7 +1380,7 @@ fnDrop(Array *left, Array *right) if(right->rank == 0){ right = duparray(right); right->rank = left->size; - right->shape = realloc(right->shape, sizeof(int) * right->rank); + right->shape = erealloc(right->shape, sizeof(int) * right->rank); for(i = 0; i < right->rank; i++) right->shape[i] = 1; }else @@ -1560,7 +1562,7 @@ fnIndex(Array *left, Array *right) for(i = 0; i < rank; i++) result->shape[i] = shape->intdata[i]; freearray(shape); - int *leftindex = mallocz(sizeof(int) * right->rank, 1); + int *leftindex = emallocz(sizeof(int) * right->rank, 1); for(i = 0; i < result->size; i++){ for(int j = left->size-1; leftindex[j] == left->arraydata[j]->size; j--){ leftindex[j] = 0; @@ -1925,7 +1927,7 @@ indexOfHelper(Array *left, Array *right, int interval) rightshape->intdata[rightshape->size-1-i] = right->shape[right->rank-1-i]; right = fnReshape(rightshape, right); - Array **lefts = malloc(sizeof(Array *) * n); + Array **lefts = emalloc(sizeof(Array *) * n); Array *index = mkscalarint(io); for(i = 0; i < n; i++){ index->intdata[0] = i+io; @@ -55,7 +55,7 @@ lexline(InputStream *input, int toplevel) { Statement *stmt = emalloc(sizeof(Statement)); stmt->ntoks = 0; - stmt->toks = mallocz(sizeof(Datum) * MAX_LINE_TOKENS, 1); + stmt->toks = emallocz(sizeof(Datum*) * MAX_LINE_TOKENS, 1); stmt->guard = nil; stmt->next = nil; @@ -67,7 +67,7 @@ lexline(InputStream *input, int toplevel) continue; }else if(runestrchr(L"←⋄\n⍝⍬", peek)){ switch(peek){ - case L'←': stmt->toks[stmt->ntoks].tag = ArrowTag; break; + case L'←': stmt->toks[stmt->ntoks] = allocdatum(ArrowTag, 0); break; case L'\n': case L'⋄': if(stmt->ntoks == 0) @@ -81,9 +81,9 @@ lexline(InputStream *input, int toplevel) ungetrune(input); goto end; case L'⍬': - stmt->toks[stmt->ntoks].tag = ArrayTag; - stmt->toks[stmt->ntoks].array = allocarray(AtypeInt, 1, 0); - stmt->toks[stmt->ntoks].array->shape[0] = 0; + stmt->toks[stmt->ntoks] = allocdatum(ArrayTag, 0); + stmt->toks[stmt->ntoks]->array = allocarray(AtypeInt, 1, 0); + stmt->toks[stmt->ntoks]->array->shape[0] = 0; break; } }else if(!toplevel && peek == ':'){ @@ -115,14 +115,14 @@ lexline(InputStream *input, int toplevel) goto syntax_error; *p = 0; if(oplevel == 0){ - stmt->toks[stmt->ntoks].tag = FunctionTag; - stmt->toks[stmt->ntoks].func.type = FunctypeDfn; - stmt->toks[stmt->ntoks].func.dfn = runestrdup(buf); + stmt->toks[stmt->ntoks] = allocdatum(FunctionTag, 0); + stmt->toks[stmt->ntoks]->func.type = FunctypeDfn; + stmt->toks[stmt->ntoks]->func.dfn = runestrdup(buf); }else{ - stmt->toks[stmt->ntoks].tag = oplevel == 1 ? MonadicOpTag : DyadicOpTag; - stmt->toks[stmt->ntoks].operator.type = OperatortypeDop; - stmt->toks[stmt->ntoks].operator.dyadic = oplevel == 2; - stmt->toks[stmt->ntoks].operator.dop = runestrdup(buf); + stmt->toks[stmt->ntoks] = allocdatum(oplevel == 1 ? MonadicOpTag : DyadicOpTag, 0); + stmt->toks[stmt->ntoks]->operator.type = OperatortypeDop; + stmt->toks[stmt->ntoks]->operator.dyadic = oplevel == 2; + stmt->toks[stmt->ntoks]->operator.dop = runestrdup(buf); } }else if(peek == '('){ int unclosed = 1; @@ -138,27 +138,27 @@ lexline(InputStream *input, int toplevel) if(peek != ')') goto syntax_error; *p = 0; - stmt->toks[stmt->ntoks].tag = LParTag; - stmt->toks[stmt->ntoks].stmt = *lexlinestr(buf, toplevel); + stmt->toks[stmt->ntoks] = allocdatum(LParTag, 0); + stmt->toks[stmt->ntoks]->stmt = *lexlinestr(buf, toplevel); stmt->ntoks++; - stmt->toks[stmt->ntoks].tag = RParTag; + stmt->toks[stmt->ntoks] = allocdatum(RParTag, 0); }else if(p = runestrchr(primfuncnames, peek)){ - stmt->toks[stmt->ntoks].tag = FunctionTag; - stmt->toks[stmt->ntoks].func.type = FunctypePrim; - stmt->toks[stmt->ntoks].func.code = p-primfuncnames; + stmt->toks[stmt->ntoks] = allocdatum(FunctionTag, 0); + stmt->toks[stmt->ntoks]->func.type = FunctypePrim; + stmt->toks[stmt->ntoks]->func.code = p-primfuncnames; }else if(p = runestrchr(primmonopnames, peek)){ - stmt->toks[stmt->ntoks].tag = MonadicOpTag; - stmt->toks[stmt->ntoks].operator.type = OperatortypePrim; - stmt->toks[stmt->ntoks].operator.dyadic = 0; - stmt->toks[stmt->ntoks].operator.code = p-primmonopnames; + stmt->toks[stmt->ntoks] = allocdatum(MonadicOpTag, 0); + stmt->toks[stmt->ntoks]->operator.type = OperatortypePrim; + stmt->toks[stmt->ntoks]->operator.dyadic = 0; + stmt->toks[stmt->ntoks]->operator.code = p-primmonopnames; }else if(p = runestrchr(primdyadopnames, peek)){ - stmt->toks[stmt->ntoks].tag = DyadicOpTag; - stmt->toks[stmt->ntoks].operator.type = OperatortypePrim; - stmt->toks[stmt->ntoks].operator.dyadic = 1; - stmt->toks[stmt->ntoks].operator.code = p-primdyadopnames; + stmt->toks[stmt->ntoks] = allocdatum(DyadicOpTag, 0); + stmt->toks[stmt->ntoks]->operator.type = OperatortypePrim; + stmt->toks[stmt->ntoks]->operator.dyadic = 1; + stmt->toks[stmt->ntoks]->operator.code = p-primdyadopnames; }else if(p = runestrchr(primhybridnames, peek)){ - stmt->toks[stmt->ntoks].tag = HybridTag; - stmt->toks[stmt->ntoks].hybrid = p-primhybridnames; + stmt->toks[stmt->ntoks] = allocdatum(HybridTag, 0); + stmt->toks[stmt->ntoks]->hybrid = p-primhybridnames; }else if(isdigitrune(peek) || peek == L'¯'){ char buf[64]; char *p = buf; @@ -180,12 +180,12 @@ get_digits: } *p = 0; ungetrune(input); - stmt->toks[stmt->ntoks].tag = ArrayTag; - stmt->toks[stmt->ntoks].array = floating ? mkscalarfloat(atof(buf)) : mkscalarint(atoll(buf)); + stmt->toks[stmt->ntoks] = allocdatum(ArrayTag, 0); + stmt->toks[stmt->ntoks]->array = floating ? mkscalarfloat(atof(buf)) : mkscalarint(atoll(buf)); }else if(runestrchr(L"⍺⍵⍶⍹", peek)){ Rune name[2] = {peek, 0}; - stmt->toks[stmt->ntoks].tag = NameTag; - stmt->toks[stmt->ntoks].name = runestrdup(name); + stmt->toks[stmt->ntoks] = allocdatum(NameTag, 0); + stmt->toks[stmt->ntoks]->name = runestrdup(name); }else if(isalpharune(peek) || peek == '_'){ Rune buf[64]; Rune *p = buf; @@ -195,8 +195,8 @@ get_digits: } *p = 0; ungetrune(input); - stmt->toks[stmt->ntoks].tag = NameTag; - stmt->toks[stmt->ntoks].name = runestrdup(buf); + stmt->toks[stmt->ntoks] = allocdatum(NameTag, 0); + stmt->toks[stmt->ntoks]->name = runestrdup(buf); }else if(runestrchr(L"⎕⍞", peek)){ /* quad names */ Rune buf[64]; @@ -241,11 +241,11 @@ get_digits: } if(!done) goto syntax_error; - stmt->toks[stmt->ntoks].tag = ArrayTag; + stmt->toks[stmt->ntoks] = allocdatum(ArrayTag, 0); if(runestrlen(buf) == 1) - stmt->toks[stmt->ntoks].array = mkscalarrune(buf[0]); + stmt->toks[stmt->ntoks]->array = mkscalarrune(buf[0]); else - stmt->toks[stmt->ntoks].array = mkrunearray(buf); + stmt->toks[stmt->ntoks]->array = mkrunearray(buf); }else{ Rune *err; syntax_error: @@ -259,7 +259,7 @@ syntax_error: peek = getrune(input); } end: - stmt->toks = realloc(stmt->toks, sizeof(Datum) * stmt->ntoks); + stmt->toks = erealloc(stmt->toks, sizeof(Datum) * stmt->ntoks); return stmt; } @@ -52,33 +52,15 @@ restart: } print("\t"); Datum *result = evalline(nil, stdin, 1); - if(result == nil) - continue; - else{ - if(result[0].shy == 0) - print("%S\n", ppdatum(*result)); - if(result->tag == ArrayTag) - freearray(result->array); - free(result); - } - /* print("Unfreed arrays: %d\n", alloccounts); */ + if(result && !result->shy) + print("%S\n", ppdatum(result)); + freedatum(result); +/* + print("Unfreed arrays: %d\n", arrayalloccounts); + print("Unfreed datums: %d\n", datumalloccounts); +*/ } - exits(nil); -} - -Rune * -prompt(Rune *pr) -{ - Rune line[MAX_LINE_LENGTH]; - - print("%S",pr); - - int i = 0; - line[0] = 0; - while(i == 0 || line[i-1] != '\n') - line[i++] = Bgetrune(stdin); - line[i-1] = 0; - return runestrdup(line); + threadexitsall(nil); } Datum * @@ -94,16 +76,14 @@ evalline(Rune *line, Biobuf *bio, int toplevel) Datum *result = eval(stmts, toplevel); if(result) - return result; - else{ - Statement *s = stmts; - while(s != nil){ - Statement *tmp = s; - s = s->next; - free(tmp->toks); - free(tmp); - } - - return nil; + incdatumref(result); + + Statement *s = stmts; + while(s != nil){ + Statement *tmp = s; + s = s->next; + freestatement(*tmp); + free(tmp); } + return result; }
\ No newline at end of file @@ -1,20 +1,44 @@ #include <u.h> #include <libc.h> +#include <thread.h> #include <bio.h> #include <pool.h> #include "apl9.h" -int alloccounts = 0; +int arrayalloccounts = 0; +int datumalloccounts = 0; int debugmem; void * emalloc(ulong size) { void *res = malloc(size); - if(res == nil){ + if(res == nil && size > 0){ print("Out of memory! :(\n"); - exits("emalloc"); + threadexitsall("emalloc"); + } + return res; +} + +void * +emallocz(ulong size, int clr) +{ + void *res = mallocz(size, clr); + if(res == nil && size > 0){ + print("Out of memory! :(\n"); + threadexitsall("emallocz"); + } + return res; +} + +void * +erealloc(void *ptr, ulong size) +{ + void *res = realloc(ptr, size); + if(res == nil && size > 0){ + print("Out of memory! :(\n"); + threadexitsall("erealloc"); } return res; } @@ -36,19 +60,18 @@ freearray(Array *a) a->refs--; if(a->refs == 0){ - /* print("Freeing array: %S (%p)\n", pparray(a), a); */ if(a->type == AtypeArray) for(int i = 0; i < a->size; i++) freearray(a->arraydata[i]); free(a->shape); + free(a->rawdata); free(a); - alloccounts--; - }else if(a->refs > 0){ - /* print("Not freeing (refs=%d): %S (%p)\n", a->refs, pparray(a), a); */ - }else{ - print("NEGATIVE REF COUNT! %p\n", a); - exits(nil); + arrayalloccounts--; + }else if(a->refs < 0){ + print("NEGATIVE REF COUNT (array)! %p\n", a); + threadexitsall(nil); } + } Array * @@ -63,16 +86,186 @@ allocarray(arrayDataType t, int rank, int size) a->rawdata = emalloc(datasizes[t] * size); a->type = t; a->refs = 1; - alloccounts++; + arrayalloccounts++; return a; } void incarrayref(Array *a) { - /* print("INCREF %d->%d %S\n", a->refs, a->refs+1, pparray(a)); */ a->refs++; - if(a->type == AtypeArray) - for(int i = 0; i < a->size; i++) - incarrayref(a->arraydata[i]); +} + +Datum * +allocdatum(int tag, int shy) +{ + Datum *d = emallocz(sizeof(Datum), 1); + d->refs = 1; + d->tag = tag; + d->shy = shy; + datumalloccounts++; + return d; +} + +void +freedatum(Datum *d) +{ + if(d == nil) + return; + + d->refs--; + if(d->refs == 0){ + /* print("FREE DATUM: %S\n", ppdatum(d)); */ + switch(d->tag){ + case ArrayTag: + freearray(d->array); + break; + case FunctionTag: + case BoundFunctionTag: + freefunction(d->func); + break; + case HybridTag: + break; + case MonadicOpTag: + case DyadicOpTag: + freeoperator(d->operator); + break; + case LParTag: + freestatement(d->stmt); + break; + case RParTag: + break; + case ArrowTag: + break; + case AssignmentTag: + freestatement(d->names); + break; + case NameTag: + free(d->name); + break; + default: + print("Don't know how to free datum with tag: %d\n", d->tag); + threadexitsall("freedatum"); + } + free(d); + datumalloccounts--; + }else if(d->refs < 0){ + print("NEGATIVE REF COUNT (datum)! %p\n", d); + threadexitsall(nil); + } +} + +void +incdatumref(Datum *d) +{ + d->refs++; +} + +void +freefunction(Function f) +{ + freearray(f.left); + switch(f.type){ + case FunctypeDfn: + free(f.dfn); + break; + case FunctypePrim: + break; + case FunctypeOp: + freeoperator(f.operator); + break; + case FunctypeQuad: + free(f.quad); + break; + case FunctypeHybrid: + break; + case FunctypeTrain: + for(int i = 0; i < f.train.nfuncs; i++) + freefunction(f.train.funcs[i]); + free(f.train.funcs); + break; + default: + print("Missing case in freefunction: %d\n", f.type); + threadexitsall("freefunction"); + } +} + +void +freeoperator(Operator o) +{ + freedatum(o.left); + freedatum(o.right); + switch(o.type){ + case OperatortypeDop: + free(o.dop); + break; + case OperatortypePrim: + case OperatortypeHybrid: + break; + default: + print("Missing case in freeoperator: %d\n", o.type); + threadexitsall("freeoperator"); + } +} + +void +freestatement(Statement s) +{ + for(int i = 0; i < s.ntoks; i++) + freedatum(s.toks[i]); + free(s.toks); + if(s.guard) + freestatement(*s.guard); +} + +Function +dupfunction(Function f) +{ + Function g = f; + if(g.left) + incarrayref(g.left); + + switch(f.type){ + case FunctypeDfn: + g.dfn = runestrdup(f.dfn); + break; + case FunctypePrim: + break; + case FunctypeOp: + g.operator = dupoperator(f.operator); + break; + case FunctypeQuad: + g.quad = emalloc(sizeof(QuadnameDef)); + *g.quad = *f.quad; + break; + case FunctypeHybrid: + break; + default: + print("Missing case in dupfunction: %d\n", f.type); + threadexitsall("dupfunction"); + } + return g; + +} + +Operator +dupoperator(Operator o) +{ + Operator p = o; + if(p.left) + incdatumref(p.left); + if(p.right) + incdatumref(p.right); + switch(o.type){ + case OperatortypeDop: + p.dop = runestrdup(o.dop); + break; + case OperatortypePrim: + case OperatortypeHybrid: + break; + default: + print("Missing case in dupoperator: %d\n", o.type); + threadexitsall("dupoperator"); + } + return p; }
\ No newline at end of file diff --git a/operators.c b/operators.c index a06b0d6..336588a 100644 --- a/operators.c +++ b/operators.c @@ -111,7 +111,7 @@ opOuterProduct(Datum *lefto, Array *left, Array *right) int i; int rank = left->rank + right->rank; int size = 1; - int *shape = malloc(sizeof(int) * rank); + int *shape = emalloc(sizeof(int) * rank); for(i = 0; i < left->rank; i++){ shape[i] = left->shape[i]; size *= left->shape[i]; @@ -11,28 +11,28 @@ Rune *printborder(Rune *, int *, int, int); Rune *strline(Rune *, int); Rune * -ppdatum(Datum d) +ppdatum(Datum *d) { Rune *result; - switch(d.tag){ - case ArrayTag: result = pparray(d.array); break; + switch(d->tag){ + case ArrayTag: result = pparray(d->array); break; case BoundFunctionTag: - case FunctionTag: result = ppfunction(d.func); break; - case HybridTag: result = runesmprint("%C", primhybridnames[d.func.code]); break; + case FunctionTag: result = ppfunction(d->func); break; + case HybridTag: result = runesmprint("%C", primhybridnames[d->func.code]); break; case MonadicOpTag: - case DyadicOpTag: result = ppoperator(d.operator); break; - case LParTag: result = runesmprint("(%S", ppdatums(d.stmt.toks, d.stmt.ntoks)); break; + case DyadicOpTag: result = ppoperator(d->operator); break; + case LParTag: result = runesmprint("(%S", ppdatums(d->stmt.toks, d->stmt.ntoks)); break; case RParTag: result = runestrdup(L")"); break; case ArrowTag: result = runestrdup(L"←"); break; - case AssignmentTag: result = runesmprint("(%S)←", ppdatums(d.stmt.toks, d.stmt.ntoks)); break; - case NameTag: result = runestrdup(d.name); break; - default: result = runesmprint("<not printable %d>", d.tag); + case AssignmentTag: result = runesmprint("(%S)←", ppdatums(d->stmt.toks, d->stmt.ntoks)); break; + case NameTag: result = runestrdup(d->name); break; + default: result = runesmprint("<not printable %d>", d->tag); } return result; } Rune * -ppdatums(Datum *ds, int n) +ppdatums(Datum **ds, int n) { int i; Rune *res = runesmprint(""); @@ -54,7 +54,7 @@ pparray(Array *a) for(int i = 0; i < a->rank-1; i++) rowcount *= a->shape[i]; } - Rune **rowstrs = mallocz(sizeof(Rune *) * rowcount, 1); + Rune **rowstrs = emallocz(sizeof(Rune *) * rowcount, 1); int boxing = !simplearray(a); char *align = a->type == AtypeArray ? "-" : ""; @@ -90,8 +90,8 @@ pparray(Array *a) } int lastdim = a->rank ? a->shape[a->rank-1] : 1; - int *widths = mallocz(sizeof(int) * lastdim, 1); - int *heights = mallocz(sizeof(int) * rowcount, 1); + int *widths = emallocz(sizeof(int) * lastdim, 1); + int *heights = emallocz(sizeof(int) * rowcount, 1); for(int i = 0; i < a->size; i++){ int w,h; strdims(elemstrs[i], &w, &h); @@ -179,8 +179,8 @@ pparray(Array *a) Rune * ppoperator(Operator op) { - Rune *left = op.left ? ppdatum(*op.left) : runestrdup(L""); - Rune *right = op.right ? ppdatum(*op.right) : runestrdup(L""); + Rune *left = op.left ? ppdatum(op.left) : runestrdup(L""); + Rune *right = op.right ? ppdatum(op.right) : runestrdup(L""); Rune *res; if(op.type == OperatortypeDop) res = runesmprint("(%S{%S}%S)", left, op.dop, right); diff --git a/quadnames.c b/quadnames.c index 7d5884c..57c5dbb 100644 --- a/quadnames.c +++ b/quadnames.c @@ -6,15 +6,15 @@ #include "apl9.h" Datum *getquotequad(void); -void setquotequad(Datum); +void setquotequad(Datum *); Datum *getquad(void); -void setquad(Datum); +void setquad(Datum *); Datum *getio(void); -void setio(Datum); +void setio(Datum *); Datum *getpp(void); -void setpp(Datum); +void setpp(Datum *); Datum *getdiv(void); -void setdiv(Datum); +void setdiv(Datum *); Datum *geta(void); Datum *getd(void); Datum *getself(void); @@ -66,26 +66,25 @@ initquadnames(void) } } -Datum +Datum * quadnamedatum(QuadnameDef q) { - Datum d; - d.tag = q.tag; + Datum *d = allocdatum(q.tag, 0); switch(q.tag){ case NameTag: - d.name = q.name; + d->name = runestrdup(q.name); break; case FunctionTag: - d.func.type = FunctypeQuad; - d.func.quad = malloc(sizeof(QuadnameDef)); - *d.func.quad = q; - d.func.left = nil; + d->func.type = FunctypeQuad; + d->func.quad = emalloc(sizeof(QuadnameDef)); + *d->func.quad = q; + d->func.left = nil; break; case MonadicOpTag: case DyadicOpTag: default: print("Can't use quad names with type=%d\n", q.tag); - exits(nil); + threadexitsall(nil); } return d; } @@ -104,21 +103,20 @@ getquotequad(void) sizemax = size+1; quadquotebuf = nil; }else{ - input = malloc(sizeof(Rune) * sizemax); + input = emalloc(sizeof(Rune) * sizemax); size = 0; } do{ if(size == sizemax-1){ sizemax += 512; - input = realloc(input, sizeof(Rune) * sizemax); + input = erealloc(input, sizeof(Rune) * sizemax); } input[size] = Bgetrune(stdin); size++; }while(input[size-1] != '\n'); input[size-1] = 0; - Datum *result = mallocz(sizeof(Datum), 1); - result->tag = ArrayTag; + Datum *result = allocdatum(ArrayTag, 0); result->array = mkrunearray(input); free(input); unlock(&quadlock); @@ -126,7 +124,7 @@ getquotequad(void) } void -setquotequad(Datum new) +setquotequad(Datum *new) { lock(&quadlock); Rune *str = ppdatum(new); @@ -158,7 +156,7 @@ getquad(void) } void -setquad(Datum new) +setquad(Datum *new) { lock(&quadlock); needsnewline = 0; @@ -170,65 +168,61 @@ setquad(Datum new) Datum * getio(void) { - Datum *d = mallocz(sizeof(Datum), 1); - d->tag = ArrayTag; + Datum *d = allocdatum(ArrayTag, 0); d->array = mkscalarint(globalIO()); return d; } void -setio(Datum new) +setio(Datum *new) { - if(new.tag != ArrayTag || new.array->rank != 0 || new.array->type != AtypeInt || (new.array->intdata[0] != 0 && new.array->intdata[0] != 1)) + if(new->tag != ArrayTag || new->array->rank != 0 || new->array->type != AtypeInt || (new->array->intdata[0] != 0 && new->array->intdata[0] != 1)) throwerror(nil, EDomain); else - globalIOset(new.array->intdata[0]); + globalIOset(new->array->intdata[0]); } /* ⎕PP */ Datum * getpp(void) { - Datum *d = mallocz(sizeof(Datum), 1); - d->tag = ArrayTag; + Datum *d = allocdatum(ArrayTag, 0); d->array = mkscalarint(printprecision); return d; } void -setpp(Datum new) +setpp(Datum *new) { - if(new.tag != ArrayTag || new.array->rank != 0 || new.array->type != AtypeInt || new.array->intdata[0] < 0) + if(new->tag != ArrayTag || new->array->rank != 0 || new->array->type != AtypeInt || new->array->intdata[0] < 0) throwerror(nil, EDomain); else - printprecision = new.array->intdata[0]; + printprecision = new->array->intdata[0]; } /* ⎕DIV */ Datum * getdiv(void) { - Datum *d = mallocz(sizeof(Datum), 1); - d->tag = ArrayTag; + Datum *d = allocdatum(ArrayTag, 0); d->array = mkscalarint(globalDIV()); return d; } void -setdiv(Datum new) +setdiv(Datum *new) { - if(new.tag != ArrayTag || new.array->rank != 0 || new.array->type != AtypeInt || (new.array->intdata[0] != 0 && new.array->intdata[0] != 1)) + if(new->tag != ArrayTag || new->array->rank != 0 || new->array->type != AtypeInt || (new->array->intdata[0] != 0 && new->array->intdata[0] != 1)) throwerror(nil, EDomain); else - globalDIVset(new.array->intdata[0]); + globalDIVset(new->array->intdata[0]); } /* ⎕A */ Datum * geta(void) { - Datum *d = mallocz(sizeof(Datum), 1); - d->tag = ArrayTag; + Datum *d = allocdatum(ArrayTag, 0); d->array = mkrunearray(L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"); return d; } @@ -237,8 +231,7 @@ geta(void) Datum * getd(void) { - Datum *d = mallocz(sizeof(Datum), 1); - d->tag = ArrayTag; + Datum *d = allocdatum(ArrayTag, 0); d->array = mkrunearray(L"0123456789"); return d; } @@ -247,8 +240,7 @@ getd(void) Datum * getself(void) { - Datum *d = mallocz(sizeof(Datum), 1); - d->tag = ArrayTag; + Datum *d = allocdatum(ArrayTag, 0); d->array = mkscalarint(threadid()); return d; } @@ -14,8 +14,8 @@ Datum *getalpha(void); Datum *getomega(void); Datum *getalphao(void); Datum *getomegao(void); -void setalpha(Datum); -void setsyntaxerr(Datum); +void setalpha(Datum *); +void setsyntaxerr(Datum *); Symbol * getsym(Rune *name, int fresh) @@ -44,7 +44,7 @@ getsym(Rune *name, int fresh) tab = td->currentdfn->symtab; tab->nsyms++; - tab->syms = realloc(tab->syms, sizeof(Symbol *) * tab->nsyms); + tab->syms = erealloc(tab->syms, sizeof(Symbol *) * tab->nsyms); tab->syms[tab->nsyms-1] = emalloc(sizeof(Symbol)); tab->syms[tab->nsyms-1]->name = runestrdup(name); tab->syms[tab->nsyms-1]->undefined = 1; @@ -71,8 +71,9 @@ freesymtab(Symtab *tab) int i; for(i = 0; i < tab->nsyms; i++){ Symbol *s = tab->syms[i]; - if(s->undefined == 0 && s->value.tag == ArrayTag) - freearray(s->value.array); + if(s->undefined == 0) + freedatum(s->value); + free(s->name); } free(tab->syms); free(tab); @@ -115,18 +116,23 @@ DfnFrame * pushdfnframe(Rune *code, Datum *lefto, Datum *righto, Array *left, Array *right) { ThreadData *td = getthreaddata(); - DfnFrame *new = malloc(sizeof(DfnFrame)); + DfnFrame *new = emalloc(sizeof(DfnFrame)); new->code = code; new->symtab = newsymtab(); new->lefto = lefto; new->righto = righto; + if(lefto) + incdatumref(lefto); + if(righto) + incdatumref(righto); if(left){ - new->left = mallocz(sizeof(Datum), 1); - new->left->tag = ArrayTag; + new->left = allocdatum(ArrayTag, 0); new->left->array = left; + incarrayref(left); }else new->left = nil; new->right = right; + incarrayref(right); new->prev = td->currentdfn; td->currentdfn = new; return new; @@ -139,6 +145,10 @@ popdfnframe(void) if(td->currentdfn != nil){ DfnFrame *prev = td->currentdfn->prev; freesymtab(td->currentdfn->symtab); + freedatum(td->currentdfn->lefto); + freedatum(td->currentdfn->righto); + freedatum(td->currentdfn->left); + freearray(td->currentdfn->right); free(td->currentdfn); td->currentdfn = prev; } @@ -194,14 +204,11 @@ getalpha(void) { DfnFrame *dfn = getcurrentdfn(); Datum *res = nil; - if(dfn == nil) + if(dfn == nil || dfn->left == nil) throwerror(nil, ESyntax); else{ - res = malloc(sizeof(Datum)); - *res = *dfn->left; - if(res->tag == ArrayTag) - incarrayref(res->array); - return res; + res = dfn->left; + incdatumref(res); } return res; } @@ -211,11 +218,10 @@ getomega(void) { DfnFrame *dfn = getcurrentdfn(); Datum *res = nil; - if(dfn == nil) + if(dfn == nil || dfn->right == nil) throwerror(nil, ESyntax); else{ - res = mallocz(sizeof(Datum), 1); - res->tag = ArrayTag; + res = allocdatum(ArrayTag, 0); res->array = dfn->right; incarrayref(res->array); } @@ -227,13 +233,11 @@ getalphao(void) { DfnFrame *dfn = getcurrentdfn(); Datum *res = nil; - if(dfn == nil) + if(dfn == nil || dfn->lefto == nil) throwerror(nil, ESyntax); else{ - res = malloc(sizeof(Datum)); - *res = *dfn->lefto; - if(res->tag == ArrayTag) - incarrayref(res->array); + res = dfn->lefto; + incdatumref(res); } return res; } @@ -243,31 +247,29 @@ getomegao(void) { DfnFrame *dfn = getcurrentdfn(); Datum *res = nil; - if(dfn == nil) + if(dfn == nil || dfn->righto == nil) throwerror(nil, ESyntax); else{ - res = malloc(sizeof(Datum)); - *res = *dfn->righto; - if(res->tag == ArrayTag) - incarrayref(res->array); + res = dfn->righto; + incdatumref(res); } return res; } void -setalpha(Datum new) +setalpha(Datum *new) { DfnFrame *dfn = getcurrentdfn(); if(dfn == nil) throwerror(nil, ESyntax); if(dfn->left == nil){ - dfn->left = malloc(sizeof(Datum)); - *dfn->left = new; + dfn->left = new; + incdatumref(new); } } void -setsyntaxerr(Datum) +setsyntaxerr(Datum *) { throwerror(nil, ESyntax); }
\ No newline at end of file diff --git a/tests/chain.apl b/tests/chain.apl new file mode 100644 index 0000000..c8efeb7 --- /dev/null +++ b/tests/chain.apl @@ -0,0 +1,8 @@ +worker←{ + msg←{1}⍇0 + ⎕←'Worker id ',(⍕⎕self),' got message: ',(⍕msg),' forwarding to ',⍕⍵ + ⍵≡⍬: ⎕←'DONE' + msg⍈⍵ +} +last←worker&⍣25⊢⍬ +_←'Hello there'⍈last diff --git a/tests/queens.apl b/tests/queens.apl index a2ce041..d372186 100644 --- a/tests/queens.apl +++ b/tests/queens.apl @@ -4,4 +4,7 @@ subs←{(⊂⍵)⍪¨(⍳⍴⊃⍺)~atk ⍵} accm←{⍺⍪((⍴⍵)=⍴⊃⍺)↑⊂⍵} fmt←{(⊂⎕io+⍵=⌾⍳⍴⍵)⌷'∘⎕'} queens←{fmt¨ 1↓(↓1 ⍵⍴0)accm dfs subs ⍬} -⎕←queens 5 +eightqueens←queens 8 +⎕←'Number of solutions to 8 queens: ',⍕≢eightqueens +⎕←'First five:' +⎕←5↑eightqueens
\ No newline at end of file |