News for hackers. Stuff that matters.
Re:My experience crafting an interpreter with Rust (2021) by nsajko on Saturday March 25, 2023 @07:27PM (#35308687)
A downside of Rust for applications like virtual machines is that it doesn't have a goto statement. Ideally, both a labelled and a computed goto would be available in the language.
Re:My experience crafting an interpreter with Rust (2021) by chc4 on Saturday March 25, 2023 @07:30PM (#35308706)
Not only does it not have computed goto (almost no languages do, tbh), it also doesn't have guaranteed tall-call elimination or allow you to use the GHC calling convention. Which are more egregious, imo.
Re:My experience crafting an interpreter with Rust (2021) by LoganDark on Saturday March 25, 2023 @07:43PM (#35308797)
Why is the lack of "GHC calling convention" egregious? I've never heard this before as an argument against Rust.
Re:My experience crafting an interpreter with Rust (2021) by margorczynski on Saturday March 25, 2023 @08:32PM (#35309208)
I was looking for that (tail recursion) and it seems the story and feature request goes back years ago and still hasn't been added. Somewhere someone wrote that the issue is with LLVM but can't the tail call be transformed to an iteration before that?
Re:My experience crafting an interpreter with Rust (2021) by shadowofneptune on Saturday March 25, 2023 @08:55PM (#35309388)
The most practical uses of recursive functions are those that cannot be easily eliminated. For an interpreter, it could mean dozens of functions all calling each other in a pattern determined at runtime.

The issue used to be with LLVM, yes, but that appears to be solved (see Clang's 'musttail' attribute). Instead it's more about language design. Constructors, destructors, and all of the fancy language features Rust has must work with this new feature, with no changes being visible elsewhere.

Re:My experience crafting an interpreter with Rust (2021) by User23 on Saturday March 25, 2023 @11:42PM (#35310621)
Tail call optimization isn’t just for recursive functions. Any tail call can be optimized to little more than a jump, which makes implementing threaded code or similar much nicer. Your compiled code will just push the instruction pointer along an array of opcodes in a tight loop with no function call overhead.
Re:My experience crafting an interpreter with Rust (2021) by shadowofneptune on Sunday March 26, 2023 @01:21AM (#35311271)
Exactly, though I do not see how it is not an example of recursion.
Re:My experience crafting an interpreter with Rust (2021) by bmitc on Saturday March 25, 2023 @08:54PM (#35309375)
> it also doesn't have guaranteed tall-call elimination

I had no idea about that. Is there a specific reason why that choice was made?

Re:My experience crafting an interpreter with Rust (2021) by pornel on Saturday March 25, 2023 @09:02PM (#35309447)
AFAIK guaranteed TCE wasn't supported in LLVM at all when Rust was still being designed and considered adding it. Support for musttail in LLVM has been added relatively recently.

WASM doesn't support guaranteed TCE yet (it's a proposal), and that's an important target for Rust.

https://github.com/rust-lang/rfcs/issues/2691

Re:My experience crafting an interpreter with Rust (2021) by kzrdude on Sunday March 26, 2023 @07:38AM (#35313363)
`become` is still a reserved keyword for this in Rust, so there's that.
Re:My experience crafting an interpreter with Rust (2021) by ufo on Saturday March 25, 2023 @08:33PM (#35309212)
In what situations do you miss goto the most, when implementing a VM?
Re:My experience crafting an interpreter with Rust (2021) by mughinn on Saturday March 25, 2023 @08:34PM (#35309222)
As someone not versed in Virtual Machine development, is goto so important? What do you gain by using it?
Re:My experience crafting an interpreter with Rust (2021) by c0balt on Saturday March 25, 2023 @09:12PM (#35309549)
Goto is quite a powerful tool for having a full, imperative grip on control flow. It is quite often useful due it's simple yet powerful ability to "just" work. Virtual machines may often encounter situations where a tight control over the flow can be advantagous for performance etc. reasons.

Goto has been iirc a point of discussion from the language design pov for Rust. I don't think it promotes good design for most applications but ymmv.

Re:My experience crafting an interpreter with Rust (2021) by nsajko on Sunday March 26, 2023 @01:39AM (#35311381)
> What do you gain by using it?

Performance, although this possibly depends on your compiler, whether you use PGO, and similar finicky issues.

Example: https://eli.thegreenplace.net/2012/07/12/computed-goto-for-e...

Some prior HN discussion: https://news.ycombinator.com/item?id=18678920

Another example where goto is relevant is implementing finite automata. A (very short) paper from 1988 that discusses three different ways of implementing a finite state machine is "How (Not) to Code a Finite State Machine". The documentation of RE2C may be even more interesting: https://re2c.org

RE2C is a program that compiles finite automata into C, Go, or Rust code. It provides many implementation strategies: it can make use of computed or labelled gotos when the language provides them.

Implementing pushdown automata comes with similar issues.

Re:My experience crafting an interpreter with Rust (2021) by mamcx on Saturday March 25, 2023 @10:19PM (#35310038)
I think a bigger one from what I have looked is the complexity of (en^de)code bytes around.

I suspect if you could use UNION better and be the same as Enum in Rust you could do us a favor! Also I wish I could do this easily:

    enum Tag {
        Int,
        Bool
    }

    enum Data {
        Int(Vec<i32>),
        Bool(Vec<bool>)
    }

    struct Val {
        tag:Tag,
        data:Data
    }

    let n = val.as_i32::<Tag::Int>(&self) -> Vec<i32>
Re:My experience crafting an interpreter with Rust (2021) by celeritascelery on Saturday March 25, 2023 @11:05PM (#35310368)
There are some crates that let you do that. For example enum-ptr

https://crates.io/crates/enum-ptr

Re:My experience crafting an interpreter with Rust (2021) by kaba0 on Sunday March 26, 2023 @03:20AM (#35311933)
I solved it in case of an interpreter with

  outer: loop {
    loop {
      let res = self.interpreter_loop(…);
      match res {
        Continue => {}
        Return => { break 'outer; }
        Exception => { break; }
      }
   }
I also made sure that the interpreter_loop call had an inline pragma, but that was otherwise a naive switch-case for the instructions. I didn’t find a way to make a template interpreter with safe Rust.