state-macro 0.1.1

Syntax sugar for stateful functions
Documentation
# State Macro

A rust macro for decluttering mutable state computations.
Suppose you want to write this:

```rust
// some type like this
type State<S> = Rc<RefCell<S>>

fn dense(state: State<S>, x: Var) -> Var {
    // this expression is messy!
    let x = mat_mul(state, param(state), x) + param(state);
    let y = param(state);
```

This library lets you instead write

```rust
#[stateful(State<S>)]
fn dense(x: Var) -> (Var, Var) {
    let x = ::mat_mul(::param(), x) + ::param();
    let y = ::param();
    (x, y)
}
```

The idea is to make functions stateful by abusing Rust's syntax for the root namespace.
This means you cannot directly refer to the root namespace inside a `#stateful` annotated function.
You can use the `with_state!` macro to work around this problem if necessary.

Writing `::f` is analogous to `!f` with
Haskell's [Monadic Bang](https://hackage.haskell.org/package/monadic-bang)
notation.

# How it works

`#[stateful(T)]` transforms the function by:

1. Adding a state parameter of type T as the function's first argument
2. Wrapping the whole function body in `with_state!`.

So the example above becomes:

```rust
fn dense(state: State<S>, x: Var) -> (Var, Var) {
    with_state! { state;
        let x = ::mat_mul(::param(), x) + ::param();
        let y = ::param();
        (x, y)
    }
}
```

Of course, you can also write stateful computations inline using the
`with_state!` macro directly, which works by:

1. Parsing an expression (the state - here a variable "state") terminated by a `;` token
2. Replacing all function calls for a name starting with :: with ones taking the expression from (1)

NOTE: the contents of `with_state!` after the first `;` can be arbitrary lines
of rust code; essentially the 'innards' of a block.
But when inlining the macro, these will *not* be wrapped in a block.
So the code above inlines as follows:

```rust
fn dense(state: State<S>, x: Var) -> (Var, Var) {
    // hijack :: prefix to mean "inject a state param".
    let x = mat_mul(state, param(state), x) + param(state);
    let y = param(state);
    (x, y)
}
```