Release 0.9.0 NEWS With 1287 commits since 0.8.4 this release is the biggest one in the history of Viua so far. And not only in terms of commit count, but also functionality. CLOSURES Closures were reworkerd. The `enclose*` family of instructions was renamed to `capture*`, and closures got their own assembly directive - `.closure:`. Functions declared as closures are not directly callable and must be instantiated first using `closure` instruction. CONCURRENCY Concurrency-related aspects of the VM also got some love. Blocking operations (`join` and `receive`) can now specify a timeout for how long they should block a process. The timeout may be specified in seconds, milliseconds, or as the `infinity` token. DEFAULT VALUES Some instructions now can be written in a shortened form and the assembler will inset default values for omitted tokens. These include for example `join`, `receive`, `istore`, and `fstore`. DEFAULT COMPILE-TIME KEYWORD The new compile-time `default` keyword can be used wherever it is legal to omit a token. The assembler will change the `default` keyword into the default value for that place. It is useful when usage of the default value should be stated explicitly. IOTA COMPILE-TIME KEYWORD The new compile-time `iota` keyword generated an ever-increasing integer starting from 1. It can be used to automatically assign register indexes: .name: %iota answer istore %answer local 42 print %answer local It is especially useful when code is changed, as the assembler will reindex the registers automatically and free the programmer from this task. WATCHDOG PROCESSES CANNIBALISE TIME OF CRASHED PROCESSES Previously, when a process crashed, the VM spawned a watchdog and run it to completion. This is now fixed, and crashed processes become their own watchdogs on failure - so watchdogs are now on the same level as all other processes, and may be preempted to prevent starvation of "normal" processes. Before the crashed process becomes a watchdog its stack is unwound. VOID TARGET REGISTER The new `void` keyword can be used as a target register. Using void register as the target register will drop the value that would by normally produced by the instruction. Some examples: ; drop the result of function call (if any) call void foo/0 ; delete the value move void %1 local EXPLICIT REGISTER SET SPECIFIERS The `tmpri` and `tmpro` instructions are no longer needed as the VM supports explicit register set specifiers for register operands. This means that to move a value from local register set to the static register set the following instruction can be used: ; move <target> <source> move %1 static %1 local ...instead of this sequence: ress local tmpri %1 ress static tmpro %1 Explicit register set specifiers make code shorted and more efficient. ATOMS Atoms are unique values whose only property is that they may be checked for equality. Useful as tags. Supported in Viua by `atom` and `atomeq` instructions. TEXT AND UTF-8 Starting with this release, Viua uses UTF-8 as its internal character set for text values. What is more, a special text type was added to the VM's list of primitive types. Text values must always be valid UTF-8. A `text*` family of instructions was introduced to distinguish text values from a "string of bytes" values produced by `strstore` instruction. As an additional feature, all values can be casted to text using the `text` instruction: istore %1 local 42 text %2 local %1 local ; register 2 will contain text "42" DEFERRED CALLS A very useful feature. Deferred calls may be registered to be called when the frame they were registered in is popped off the stack (during unwinding, normal returns, or tail calls). They are useful as a debugging aid, and can be used to implement resource management schemes. More information about deferred calls can be found on the weekly.viuavm.org blog. ADDITIONAL NOTES This release also introduces one very useful and important feature: processes can now contain many stacks, and switch execution between them. Such an additionl will make implementation of several new functionalities much easier and more intuitive. For example: - interrupts: they must be run in the context of a specified process, but are in no relation to what the process is currently executing so they are a prime candidate to be run on a different stack - message filtering: a function could be provided to filter messages available in a process' mailbox, and as this function's execution is is only a tool to achieve some other goal, it would be a good idea to run the function on another stack - stackful coroutines: coroutines that can yield from frames at arbitrary depth of the stack, not only from the top-most frame and possibly more. A style guide has been introduced with the help of the `clang-format` tool. VM got a basic static analyser that is able to catch errors at compile time.