Hacker Newsnew | past | comments | ask | show | jobs | submit | asibahi's commentslogin

This `dup` seems entirely useless it actually supports the case for omitting it fron the instruction set.

The only reason it is useless in this (arguably ill-chosen) example is because the result of “new Object()” is not used (hence the pop), which is an uncommon case. If test() instead returned the new object, or would use it in some other way after the initialization, then the dup would be needed. Invokespecial consumes the object reference on the stack, hence if you want to use it after invokespecial, you have to copy or duplicate it before.

I dont really disagree with the main premise of the article, which is that WASM is not really a stack language, but this part just gave me pause:

> In textual Wasm, for example, they are instead represented in a LISP-like notation – not any less or more efficient

The Text format, at least when it comes to instructions, it 1 to 1 with the binary format. The LISP-like syntax is mainly just syntax sugar[1].

    ‘(’ plaininstr  instrs ‘)’ ≡  instrs plaininstr
So (in theory, as far as I understand it) you can just do `(local.get 2 local.get 0 local.get 1)` to mean `local.get 0 local.get 1 local.get 2`, and it works for (almost) any instruction.

Unfortunately, in my limited testing, tools like `wat2wasm` and Binaryen's `wasm-as` don't seem to adhere to (my perhaps faulty understanding of) the spec, and demand all instructions in a folded block be folded and have the "correct" amount of arguments, which makes Binaryen do weird things like

    (return
      (tuple.make     ;; Binaryen only pseudoinstruction
        (local.get 0) ;; or w/e expression
        (local.get 1) ;; or w/e expression
      )
    )

when this is perfectly valid

    local.get 0
    local.get 1
    return

tl;dr: the LISP syntax is just syntax sugar. The textual format is as "stack-like" as the binary format.

Edit: An example that is easily done with the stack syntax and not with lisp syntax is the following:

    call function_that_returns_multivalue
    local.set 2 ;; last return
    local.set 1 ;;
    local.set 0 ;; first return
In LISP syntax this would be

    (local.set 0
      (local.set 1
        (local.set 2
          (call function_that_returns_multivalue
            ( ;; whatever input paramters 
            )))))
I have not yet tried this with Binaryen but I doubt it flies.

[1]: https://webassembly.github.io/spec/core/text/instructions.ht...


FWIW if you are looking for examples of WebAssembly written in the textual format, take a look at:

https://raw.githubusercontent.com/soegaard/webracket/refs/he...

As a small example, here is a definition of `$car` which extracts the first value from a pair.

    (func $car (type $Prim1) 
               (param $v (ref eq)) 
               (result (ref eq))
      (if (result (ref eq)) 
          (ref.test (ref $Pair) (local.get $v))
          (then (struct.get $Pair $a (ref.cast (ref $Pair) (local.get $v))))
          (else (call $raise-pair-expected (local.get $v))
                (unreachable))))

I can't speak to Binaryen, but afaik WABT's wat2wasm and wasm-tools's wat2wasm (aka wasm-tools parse) are both 100% spec-correct in this respect. Parsing the Wasm text format doesn't require any knowledge of the type of each instruction. If you have a counterexample would love to see it!

There are some cool edge cases if you want to print a mismatched multi-value instruction sequence in the folded form (which WABT and wasm-tools again handle "correctly," but not identically to each other, and not particularly meaningfully).


This is the wat2wasm tool I have been playing with: https://webassembly.github.io/wabt/demo/wat2wasm/

It refuses to accept the following

    (module
      (func (export "addTwo") (param i32 i32) (result i32)
        (i32.add 
          local.get 0
          local.get 1
        )
      )
    )
which based on my reading should be accepted.

I will try the tools you mentioned but I personally settled on generating the unfolded ones for my experiments as they just seem easier.


Don't you need parens here?

    (local.get 0)
    (local.get 1)

I do, but where does it say so in the spec?

> tl;dr: the LISP syntax is just syntax sugar. The textual format is as "stack-like" as the binary format.

Not that you're technically wrong, but I think you're begging the question.

Stack-based languages/encodings, in a colloquial sense, are equated to postfix notation, e.g. `a b +` instead of the infix `a + b`. Both LISP and textual Wasm use prefix notation, e.g. `(+ a b)`. Neither of the three is any more foundational than the other -- all notations can encode all expression trees, and postfix and prefix notations in particular have the same coding efficiency.

So sure, the LISP syntax is sugar, but for what? It's not sugar for a stack program, because prefix notation in general can't represent an arbitrary stack program; it's sugar for a mathematical expression. Which is encoded in postfix notation in binary, sure, but that's just an implementation detail, and prefix notation could've been selected when Wasm was born with little adversarial consequences.


I am saying that textual wasm uses `a b +` (justl ike binary wasm) and `(+ a b)` is just a nicety.

It is explicity sugar for the stack operations, per my reading of the spec.


My brain does not understand how one can see `(+ a b)` in text and read it as `a b +`. I suppose you can argue that moving operators to the right and removing all parentheses converts `(+ a b)` to `a b +`, sure, but that applies to pretty much any language -- next thing you'll tell me is the JavaScript expression `f(1, g(2), h(3))` actually uses stack and is just syntactic sugar for `1 2 g 3 h f`.

> It is explicity sugar for the stack operations, per my reading of the spec.

The entire Wasm text format is syntax sugar for binary Wasm, so this is kind of a vacuous truth -- if Wasm's spec says it's a stack machine, of course everything is sugar for a stack machine. But if you weren't aware of Wasm and just saw a program in textual Wasm for the first time, I don't think the idea that it's stack-based would cross your mind.


I have reread this several times but might be missing so I am begging the question, what exactly makes the LISP syntax sugar for something that isn't a stack machine? Or did I misread that?

If not, I think the OP is making the same point we all are, any program can be translated for execution on any machine - so bringing it up in the blog seems weak, which I agree with.


`local.tee` doesn't duplicate. it just doesn't remove the value from the stack. (so it is "just" `local.set` followed by `local.get`)

Sure. But it does save you one instruction: "tee", "get" instead of "set", "get", "get".

When I read this article a few days ago it inspired me to create my own hex viewer : https://ar-ms.me/thoughts/3sl-a-sweet-hex-utility/

The cool thing about it imo (outside of colors) is a `--windows` flag. Which separates the hex view into partitions: so `-w 2:-3:5` shows the first two bytes on a line, then skips three bytes, then shows the next 5 bytes on a line, then the rest of the file. Easy to use combined with a terminal's up arrow.


Previously: https://news.ycombinator.com/item?id=45248558. Switched domains since then.

Slightly related: I am an Arab who speaks Arabic and reads Arabic and the only place I ever see the unicode character ﷽ is by programmers giving an example of "unicode is too hard".

Perhaps as a graphical element at the beginning of books, too.

It is a part of the Arabic Presentation Forms block which explicitly is for supporting legacy encodings and should not be used.


The whole phrase is one character?

It's one codepoint, U+FDFD, with the name "Arabic Ligature Bismillah Ar-Rahman Ar-Raheem".

https://www.compart.com/en/unicode/U+FDFD


It’s one code point that’s (in theory) meant to hold the ligature of the whole phrase. As it stands it’s only used as a demonstration of Unicode difficulty.

﷽ translates to "In the name of Allah, the Most Gracious, the Most Merciful."

But it is indeed just the single character (U+FDFD)


Doesn’t it just call `less`?


Yes. It calls the default pager (or whatever you specify).

Inspired by Ghuloum's book is this really nice book by Nora Sandler: Writing a C Compiler https://norasandler.com/book/


Another recent book inspired by Ghuloum is Essentials of Compilation: An Incremental Approach (which publishes Python and Racket versions) https://github.com/IUCompilerCourse/Essentials-of-Compilatio...


How does the application apply the same lighting setting to all photos if applying the same lighting settings in Lightroom is not suitable for all images? What magic is being done here?

(and what advantage does it have over using `magick`?)


I too am interested in these questions. also how do you deal with culling photos?


Because that’s the rule. There doesn’t have to be a rational reason.


... and if it weren't the rule, it'd make a lot of mid- and late-game play much safer for the player with the advantage. As it is, it's something they have to watch out for, which constrains them somewhat. You have to win, but not the wrong way, and your opponent can attempt to force you to "win" the "wrong way" (resulting in a stalemate).


Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: