summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--concurrency.c5
-rw-r--r--error.c2
-rw-r--r--eval.c2
-rw-r--r--lexer.c8
-rw-r--r--tests/chain.apl7
-rw-r--r--tests/demo.apl31
6 files changed, 49 insertions, 6 deletions
diff --git a/concurrency.c b/concurrency.c
index 81ff7b1..1d06a9c 100644
--- a/concurrency.c
+++ b/concurrency.c
@@ -49,7 +49,7 @@ spawnthread(Function f, Array *left, Array *right)
*/
Channel *setupdone = chancreate(sizeof(int), 0);
SpawnData *sp = emalloc(sizeof(SpawnData));
- sp->func = f;
+ sp->func = dupfunction(f);
sp->left = left ? duparray(left) : nil;
sp->right = duparray(right);
sp->setupdone = setupdone;
@@ -87,6 +87,8 @@ messagesend(Array *a, int id)
td->lastmail = newmail;
rwakeup(&td->empty);
qunlock(&td->lock);
+ }else{
+ throwerror(L"Invalid thread id", EDomain);
}
}
@@ -134,6 +136,7 @@ newprocfn(void *data)
unlock(&threadlock);
freearray(sp->left);
freearray(sp->right);
+ freefunction(sp->func);
free(sp);
free(td);
}
diff --git a/error.c b/error.c
index ee6ffe9..e12318a 100644
--- a/error.c
+++ b/error.c
@@ -37,7 +37,7 @@ throwerror(Rune *msg, int err)
td->lasterror = err;
if(td->lasterrormsg)
free(td->lasterrormsg);
- td->lasterrormsg = msg;
+ td->lasterrormsg = runestrdup(msg);
while(frame != nil){
for(ErrorGuard *eg = frame->errorguards; eg != nil; eg = eg->next){
diff --git a/eval.c b/eval.c
index 3174cd4..cfe5854 100644
--- a/eval.c
+++ b/eval.c
@@ -202,6 +202,7 @@ monadfun(Datum *left, Datum *right)
{
traceprint("Monadic function application\n");
Datum *result = allocdatum(ArrayTag, 0);
+ SetStrand(right->array, 0);
result->array = runfunc(left->func, left->func.left, right->array);
return result;
}
@@ -218,6 +219,7 @@ dyadfun(Datum *left, Datum *right)
result->func.code = right->hybrid;
}
result->func.left = fnSame(left->array);
+ SetStrand(result->func.left, 0);
return result;
}
diff --git a/lexer.c b/lexer.c
index 4e9a4e4..9ce251a 100644
--- a/lexer.c
+++ b/lexer.c
@@ -72,8 +72,14 @@ lexline(InputStream *input, int toplevel)
case L'⋄':
if(stmt->ntoks == 0)
stmt = lexline(input, toplevel);
- else
+ else{
stmt->next = lexline(input, toplevel);
+ if(stmt->next && stmt->next->ntoks == 0){ // Prevent empty statements
+ freestatement(*(stmt->next));
+ free(stmt->next);
+ stmt->next = nil;
+ }
+ }
goto end;
case L'⍝':
while(peek != '\n' && !inputEOF(input))
diff --git a/tests/chain.apl b/tests/chain.apl
index f6ab04b..aeeab52 100644
--- a/tests/chain.apl
+++ b/tests/chain.apl
@@ -1,8 +1,9 @@
worker←{
- msg←{1}⍇0
- ⎕←'Worker id ',(⍕⎕self),' got message: ',(⍕msg),' forwarding to ',⍕⍵
+ msg←1⍨⍇0
⍵≡⍬: ⎕←'DONE'
+ ⎕←'Worker id ',(⍕⎕self),' got message: ',(⍕msg)
+ ⎕←'Forwarding from ',(⍕⎕self), ' to ',⍕⍵
msg⍈⍵
}
-last←worker&⍣100⊢⍬
+last←worker&⍣10⊢⍬
'Hello there'⍈last
diff --git a/tests/demo.apl b/tests/demo.apl
new file mode 100644
index 0000000..7a6ddca
--- /dev/null
+++ b/tests/demo.apl
@@ -0,0 +1,31 @@
+⍝ The following demonstrates message passing between an 'iota sever',
+⍝ and a client (the user of the iota function). The client always initiates
+⍝ communication, and the server must be running, but the client should not
+⍝ be able to notice a difference between monadic ⍳ and the iota function,
+⍝ even though one does the computation in a different thread.
+
+iotaServer←{
+ msg←1⍨⍇0
+ msg≡'stop': ⎕←'Bye bye from indexer'
+ (from num)←msg
+ _←(⍳num)⍈from
+ ∇⍵
+}
+
+id←0 ⍝ this is an invalid thread id, so it is a sane starting point
+
+start←{
+ id=0: iotaServer&⍬
+ id
+}
+
+stop←{
+ 'stop'⍈id
+}
+
+iota←{
+ ⍝ Sending messages to a nonexisting thread throws a domain error (11)
+ 11::'Sorry, the iota server is not running'
+ _←(⎕self ⍵)⍈id
+ 1⍨⍇0
+}