←back to thread

200 points ibobev | 8 comments | | HN request time: 0s | source | bottom
Show context
derefr ◴[] No.44465643[source]
Would anyone here assert that there's any particular programming language that's better for writing emulators, virtual machines, bytecode interpreters, etc?

Where, when I say "better", I'm not so much talking about getting results that are particularly efficient/performant; nor in making fewer implementation errors... but more in terms of the experience of implementing an emulator in this particular language, being more rewarding, intuitive, and/or teaching you more about both emulators and the language.

I ask because I know that this sort of language exists in other domains. Erlang, for example, is particularly rewarding to implement a "soft-realtime nine-nines-of-uptime distributed system" in. The language, its execution semantics, its runtime, and its core libraries, were all co-designed to address this particular problem domain. Using Erlang "for what it's for" can thus teach you a lot about distributed systems (due to the language/runtime/etc guiding your hand toward its own idiomatic answers to distributed-systems problems — which usually are "best practice" solutions in theory as well); and can lead you to a much-deeper understanding of Erlang (exploring all its corners, discovering all the places where the language designers considered the problems you'd be having and set you up for success) than you'd get by trying to use it to solve problems in some other domain.

Is there a language like that... but where the "problem domain" that the language's designers were targeting, was "describing machines in code"?

replies(10): >>44465651 #>>44465842 #>>44465906 #>>44465934 #>>44466249 #>>44466377 #>>44466464 #>>44466501 #>>44467885 #>>44468314 #
grg0 ◴[] No.44466464[source]
Haskell excels at DSLs and the sort of data manipulation needed in compilers. OCaml, Lisp, and really any language with support for ADTs and such things do the trick as well. You can even try hard with modern C++ and variant types and such, but it won't be as pretty.

Of course, if you actually want to run games on the emulator, C or C++ is where the game is. I suppose Rust would work too, but I can't speak much for its low-level memory manipulation.

replies(1): >>44466557 #
1. wk_end ◴[] No.44466557[source]
Haskell and OCaml are excellent for compilers, because - as you suggest - you end up building, walking, and transforming tree data structures where sum types are really useful. Lisp is an odd suggestion there, as it doesn’t really have any built-in support for this sort of thing.

At any rate, that’s not really the case when building an emulator or bytecode interpreter. And Haskell ends up being mostly a liability here, because most work is just going to be imperatively modifying your virtual machine’s state.

replies(3): >>44466970 #>>44467056 #>>44467723 #
2. materielle ◴[] No.44466970[source]
I’d also point out, that even in the compiler space, there are basically no production compilers written in Haskell and OCaml.

I believe those two languages themselves self-host. So not saying it’s impossible. And I have no clue about the technical merits.

But if you look around programming forums, there’s this ideas that”Ocaml is one of the leading languages for compiler writers”, which seems to be a completely made up statistic.

replies(1): >>44466998 #
3. runevault ◴[] No.44466998[source]
I don't know that many production compilers are in them, but how much of that is compilers tending towards self hosting once they get far enough along these days? My understanding is early Rust compilers were written in Ocaml, but they transitioned to Rust to self-host.
4. kqr ◴[] No.44467056[source]
> And Haskell ends up being mostly a liability here, because most work is just going to be imperatively modifying your virtual machine’s state.

That sounds odd to me. Haskell is great for managing state, since it makes it possible to do so in a much more controlled manner than non-pure languages.

replies(1): >>44467098 #
5. grg0 ◴[] No.44467098[source]
Yeah, I don't understand what the "liability" here is. I never claimed it was going to be optimal, and I already pointed out C/C++ as the only reasonable choice if you actually want to run games on the thing and get as much performance as possible. But manipulating the machine state in Haskell is otherwise perfect. Code will look like equations, everything becomes trivially testable and REPLable, and you'd even get a free time machine from the immutability of the data, which makes debugging easy.
replies(1): >>44467688 #
6. wk_end ◴[] No.44467688{3}[source]
If you're effectively always in a stateful monad, Haskell's purity offers nothing. Code doesn't look like equations, things aren't trivially testable and REPLable, you don't get a free time machine, and there's syntactic overhead from things like lifting or writes to deeply nested structures and arrays, since the language doesn't have built-in syntactic support for them.
replies(1): >>44467793 #
7. whateveracct ◴[] No.44467723[source]
Haskell isn't a liability for that lol
8. kqr ◴[] No.44467793{4}[source]
On the other hand, it does have support for things like side-effectful traversals, folds, side effects conditional on value existing, etc. In most other languages you have to write lower-level code to accomplish the same thing.