Inverted Ports

The inverse of a port type is written as ~P. On an inverted port, mutable wires are non-mutable and immutable wires are mutable. This is useful when a consumer and a producer of a port both expect that port to be passed as an argument, rather than returned by one of the ports.

The port expression

The only way to construct an inverted port is via the port expression which creates a (P, ~P) tuple as shown below:

entity top() {
    let (p, p_inv) = port;

    let _ = inst consumer(p);
    let _ = inst producer(p_inv)
}

entity consumer(p: P) -> bool {
    // ...
}

entity producer(p: ~P) -> bool {
    // ...
}

Using Inverted Ports

Inverted ports work like their non-inverted counterparts. They are linear types, so their mutable wires must be set exactly once and their non-mutable wires can be read freely.

Accessing a field of an inverted port returns an inverted port if the field is a struct port.

struct port Inner<T> {
    i: &mut T
    o: &T
}

struct port Outer<T> {
    inner: Inner<T>
    raw: &mut T
}

entity inverse_user<bool>(p: ~Outer<bool>) {
    let _: &bool = p.raw;
    let _: ~Inner<bool> = p.inner;
    let _: &bool = p.inner.i;
    let _: &mut bool = p.inner.o;
}