Login
You're viewing the discuss.systems public feed.
  • Oct 10, 2026, 2:02 AM

    Nobody asked, but having now done some work in the WAST/WAT/Wasm Textual format, here's how I would change it if I got the opportunity:

    - Keep the S-expression structure, but stop pretending it's "a LISP", describe it as the Wasm S-Expression Syntax or something

    - Put the operator at the *end*; parenthesis are now *only* hints to the typechecker.

    So (i32.const 10 (i32.const 3 i32.const 8 i32.add) i32.mul) is legal

    (i32.const 10 (i32.const 3 i32.mul)) is an error because mul wants 2 i32 args

    💬 1🔄 1⭐ 0

Replies

  • Oct 10, 2026, 2:07 AM

    Also, if I could go a little further…

    - Put the i32.const and local.get arguments *before*, like

    10 i32.const

    $varname local.get

    You could even integrate this with the stack type system; "(40 10 i32.add)" could error like "expected [i32, i32], got [literal, literal]". Whereas 10 i32.const $varname i32.add would be "expected [i32,i32], got [i32, variable].

    - Let us use type names as a shorthand for "type.const", i.e.

    (10 i32 40 i32 i32.add)

    This should be unambiguous, so why not allow it?

    💬 3🔄 0⭐ 1
  • Oct 10, 2026, 2:09 AM

    …and if I could go COMPLETELY off the deep end…

    - Add the special syntax : where symbol:symbol is implicitly (symbol symbol). This would allow the clearer:

    10:i32 40:i32 i32.add

    - Have mild type inference on the instructions. Why not? Allow either of

    10:i32 40:i32 add

    or

    10 40 i32.add

    There's only one instruction that fits the constants in the former example, and only one interpretation of the literals that fits the instruction in the latter example.

    💬 1🔄 0⭐ 0
  • Oct 10, 2026, 2:09 AM

    …I could implement all of this if I wanted. Maybe I will, if I wind up in a situation I'm ever writing textual wasm in the future. Which may not actually be likely come to think of it.

    💬 1🔄 0⭐ 0
  • Oct 10, 2026, 2:40 AM

    Essentially the goal above is that I view the "forward, then backward, then forward again, then also sometimes forward within the backward" structure of wast fundamentally confusing ( mastodon.social/@mcc/117386721 ) and I don't think it adds anything. When I saw it described I was like "oh that's SMART" but when I tried to use it it was just frustrating. I'm trying to recover the spirit of what they were *trying* to do without actively fighting the spirit of a stack language.

    💬 1🔄 0⭐ 2
  • Oct 10, 2026, 4:16 AM

    @mcc Yeah it's very odd. FORTH is a thing that has existed for a long time, and brains take maybe 10 minutes to get used to reading it fluently. And as you say - unambiguous. This just seems like a mess.

    💬 1🔄 0⭐ 1
  • Oct 10, 2026, 4:21 AM

    @TomF i find forth hard to adjust to, but— in order to write WAST, you have to adjust to it? so once you've adjusted to it, why go back and forth? maybe the person on the standards committee who got the LISP mode in actually does write WAST code where all stackiness is done via "unrolling". but, i found myself writing code like

    global.get $var ;; return value

    local.tee $v2
    global.get $var
    i32.mul
    local.get $v2
    i32.add
    global.set $var

    ;; end of function

    you can't LISP that!!

    💬 0🔄 0⭐ 1
  • 💬 1🔄 0⭐ 0
  • Oct 10, 2026, 3:00 AM

    @chrisamaphone The closest analogue is forth but yeah

    The people designing WAST wound up writing things in RPN because that was what was most convenient for their register allocation algorithm. But they decided they didn't like RPN. So they allow you to embed snippets of "RPN, but backward" into your code. Additionally, within the RPN there are some operations that are treated as one RPN symbol, but contain a space. It turns out real weird. So I am like "why not just make it actually RPN"

    💬 1🔄 0⭐ 0
  • Oct 10, 2026, 3:01 AM

    @mcc uhh relatedly (mild spoiler), have you played message from deep space?

    💬 1🔄 0⭐ 0
  • 💬 1🔄 0⭐ 0
  • 💬 1🔄 0⭐ 0
  • 💬 0🔄 0⭐ 0
  • 💬 1🔄 0⭐ 0
  • 💬 0🔄 0⭐ 1