summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c364
1 files changed, 182 insertions, 182 deletions
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