RoyalIcing / Orb

Write WebAssembly with Elixir
https://useorb.dev
BSD 3-Clause "New" or "Revised" License
198 stars 1 forks source link

Disallow implicit push #31

Open RoyalIcing opened 3 months ago

RoyalIcing commented 3 months ago

Now that we can return tuples (e.g. {1, 2, 3}) I think we should disallow implicit pushing of values onto the stack.

e.g.

  defw abc(), {I32, I32, I32} do
    1
    2
    3
  end

It’s definitely a unique feature of WebAssembly that at first I thought was nifty — I still do!

But it’s quite subtle. Over time I’ve added explicit DSL for working with the stack: Orb.Stack.push/1 / Orb.Stack.drop/1 / Orb.Stack.pop/1. The explicitness means the programmer is intentionally working with the stack.

It’s too easy to call a function that returns a value and have it be invisibly be pushing onto the stack.

  defw example() do
    call_func_returning_i32()
    # Oops, now stack is [i32]

    # Correct code is:
    # _ = call_func_returning_i32()
  end

We still want implicit returns just like Elixir: having a value on the last line of a function should be the result of the function.

But other implicit pushing onto the stack should be removed. The DSL for explicitly working with the stack will still allow access to this, which I think it’s reasonably important as it is a feature of WebAssembly (which Orb aims to provide the entire featureset of) and the stack can provide optimization patterns that can’t be achieved in other ways, like pushing values onto the stack early before a set of work and then have them resurface later.