Skip to content
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.