v0.2.0-next
v0.2.0-next
v0.2.0-next
Prerelease
This release is still in development and has not been tagged yet.
A Zirric program still runs one thing at a time. What it can now do is wait on more than one of them: a key and a timer, a slow job and a user who presses q, several files handled as they become ready.
Implemented Proposals
- ZE-025 Routines and Channels — the
comodule: routines, the scopes that own them, and channels between them. No new syntax, no new keyword, no new operator.
Notable Changes
- One routine runs at a time, and only gives way at a switch point —
co.send,co.receive,co.select,co.wait,co.sleep, iterating a channel, the end of aco.scopebody, and every stdlib call that waits on the outside world. Between two switch points, code runs as if it were alone, so a sharedvaror array needs no lock. - New
io.read(reader, length)andio.write(writer, buf), wrapping the@Readerand@Writerattributes the waylenwraps@Countable.io.read(stdin, 1)replacesio.Reader(stdin).read(stdin, 1), which is shorter whether or not a program has routines. - The functions of
fs,io.read,io.writeand thereforefmt.fprint*are switch points, whatever reader, writer or filesystem they are given. A fake that answers instantly interleaves exactly where the host’s own would, and cannot run a whole loop while the other routines never start. With the host’s own filesystem or streams, the run lock is released for the length of the call, so a routine blocked on standard input does not stop the rest of the program. Withfs.memory()nothing really waits, but the calling routine still goes to the back of the queue, so a test sees the same places to interleave as production does. - A
Channelcarries@Iterable, sofor value <- channelreceives until the channel is closed and drained, andco.produceturns a function into a generator with nothing new. os.timer()hands out the timer that really waits.co.immediateTimer()andco.neverTimer()are the two a test uses instead, which is how a timeout is checked in both directions without waiting for either.- A program where every routine is waiting stops with a deadlock message naming each blocked routine and what it was waiting on, rather than hanging.
cancelreturns at once even when the routine it stops is waiting for standard input, and loses none of that input: a host stream owns its reads, so bytes that arrive for a routine which is no longer waiting stay there for whoever reads next. A write already handed to the host still completes — see Cancelling for what cancellation does and does not take back.
Bug Fixes
- A closure written inside a
forexpression body can reach a variable of the enclosing function. The loop body has a symbol table of its own while running in the same frame, so such a reference was resolved against the frame’s own captures — reporting an internal error, or silently reading an unrelated captured value when the indices happened to line up.