Blocks can consume values from the stack and push results back to it, which is cool, but I cannot find any detail on how this works.

The [spec for `loop`](https://webassembly.github.io/spec/core/exec/instructions.html#exec-loop) says (at 5) that the values are popped from the stack (before any code within the block gets executed), and the other block instructions (`block` and `if`) are described similarly. They all pop the params before executing the block:

loop *blocktype* *instr*\* end

1. Assert: due to validation, expand(*blocktype*) is defined.
2. Let [1]→[2]
be the function type expand(*blocktype*).
3. Let be the label whose arity is and whose continuation is the start of the loop.
4. Assert: due to validation, there are at least values on the top of the stack.
5. **Pop the values *val* from the stack.**
6. Enter the block *val* *instr*∗ with label .

Where are block params *popped to*? Blocks do not have their own locals, so I have no idea how to actually use the params (presumably they are not just thrown away).

The spec does not say anything about `loop` blocks popping params on each iteration, but I thought that was how they work.

I also struggled to establish whether `loop` blocks push results to the stack on each iteration, or only once, when the loop exits. Presumably, it's once, but with my ignorance on the other points, I'm not confident about that either.

I found this code in the proposal that may make things clearer (to somebody):

```
(func $fac (param i64) (result i64)
    (i64.const 1) (get_local 0)
    (loop $l (param i64 i64) (result i64)
        (pick 1) (pick 1) (i64.mul)
        (pick 1) (i64.const 1) (i64.sub)
        (pick 0) (i64.const 0) (i64.gt_u)
        (br_if $l)
        (pick 1) (return)
    )
)

```