summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authorPeter Mikkelsen <petermikkelsen10@gmail.com>2022-01-28 14:15:17 +0000
committerPeter Mikkelsen <petermikkelsen10@gmail.com>2022-01-28 14:15:17 +0000
commita3ebefe7fbcb375c77c3b4ccb6064dabb45d8911 (patch)
treeb22eeda4e48e10f0a0c35e0140b58562a5a92e26 /eval.c
parent17e97bbed7abc59fb754cf463e825e890b16815d (diff)
Add strand assignment (a (b c) d)←1 (2 3) 4
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c101
1 files changed, 81 insertions, 20 deletions
diff --git a/eval.c b/eval.c
index e33c3b5..8829609 100644
--- a/eval.c
+++ b/eval.c
@@ -15,6 +15,7 @@ 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);
@@ -29,8 +30,8 @@ int bindingstrengths[11][11] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */
6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */
3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */
- 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, /* ( */
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* ) */
+ 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, /* ( */
+ 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, /* ) */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ← */
1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* IS */
0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, /* N */
@@ -44,10 +45,10 @@ evalfn evalfns[11][11] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MO */
dyadop, dyadop, dyadop, 0, 0, 0, 0, 0, 0, 0, 0, /* DO */
monadfun, train, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AF */
- 0, 0, 0, 0, 0, 0, 0, parens, 0, 0, 0, /* ( */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ) */
+ 0, 0, 0, 0, 0, 0, 0, parens, namesis, 0, 0, /* ( */
+ 0, 0, 0, 0, 0, 0, 0, 0, namesis, 0, 0, /* ) */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ← */
- assign, assign, assign, assign, assign, 0, 0, 0, 0, 0, 0, /* IS */
+ assign, assign, assign, assign, assign, 0, assign, 0, 0, 0, 0, /* IS */
0, 0, 0, 0, 0, 0, 0, 0, nameis, 0, 0, /* N */
};
@@ -221,27 +222,87 @@ nameis(Datum left, Datum right)
{
traceprint("NAMEIS %S←\n", left.name);
right.tag = AssignmentTag;
- right.name = left.name;
+ right.names.ntoks = 1;
+ right.names.toks = malloc(sizeof(Datum));
+ right.names.toks[0] = left;
+ return right;
+}
+
+Datum
+namesis(Datum left, Datum right)
+{
+ if(left.tag == RParTag)
+ return right;
+
+ traceprint("NAMES IS %S %S\n", ppdatum(left), ppdatum(right));
+ right.tag = AssignmentTag;
+ right.names = left.stmt;
return right;
}
Datum
assign(Datum left, Datum right)
{
- Symbol *symbol = getsym(left.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(left.name, 1);
-
- if(symbol->undefined == 0 && symbol->value.tag == ArrayTag)
- freearray(symbol->value.array);
- symbol->value = right;
- symbol->undefined = 0;
- if(symbol->value.tag == ArrayTag){
- symbol->value.array->stranded = 0;
- incref(right.array); /* for the binding */
+ traceprint("ASSIGN %S %S\n", ppdatum(left), ppdatum(right));
+ if(left.names.ntoks == 1){
+ if(left.names.toks[0].tag != NameTag)
+ throwerror(nil, ESyntax);
+
+ 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);
+ symbol->value = right;
+ symbol->undefined = 0;
+ if(symbol->value.tag == ArrayTag){
+ symbol->value.array->stranded = 0;
+ incref(right.array); /* for the binding */
+ }
+ }
+ }else{
+ if(right.tag != ArrayTag)
+ throwerror(nil, ESyntax);
+ 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){
+ 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){
+ i++;
+ nlocs++;
+ locations = realloc(locations, sizeof(Datum) * nlocs);
+ locations[nlocs-1].tag = AssignmentTag;
+ locations[nlocs-1].names = loc.stmt;
+ }
+ }
+
+ 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);
+ else{
+ Datum item;
+ item.tag = ArrayTag;
+ item.array = arrayitem(right.array, i);
+ assign(locations[i], item);
+ freearray(item.array);
+ }
}
}
right.shy = 1;