6 ms·
The article has fair points, but after trying OCaml and Rust... I chose Rust. Without going into huge amounts of detail, a compiler is more than simply a parser
by nu11ptr 3y ago
The article has fair points, but after trying OCaml and Rust... I chose Rust. Without going into huge amounts of detail, a compiler is more than simply a parser/ast/code generator and there are other aspects to consider such as the richness of the ecosystem, editor support, etc. Also, I suspect the author is more familiar with OCaml than Rust as you wouldn't typically box everything but likely use an arena for the AST. In the same way, I am more familiar with Rust than OCaml, so some of the warts I observed may be to lack of familiarity. As such I suspect the authors perspective is biased...as is mine. Nothing wrong with that.
- ecshafer 3y agoCan you write an equivalent piece of code that shows why Rust wins here with more familiarity and leveraging the ecosystem? With compilers I don't think there is a huge amount of using the ecosystem. I think what TFA does is a good case study in trying to be objective: write it both ways and compare.
- nu11ptr 3y agoI'm just saying a compiler is a program, and while the more important things are heavy algorithm related, supporting libraries like those for error handling, etc. all still matter and add up. No problem if you disagree - just my perspective. This isn't so much an objective thing as it is a personal opinion.
- brmgb 3y agoPersonally, it’s not so much that I disagree. It’s more that Ocaml has a top notch ecosystem for compiler writing. That’s probably by far its strongest point with library like Menhir having few equivalent in different ecosystem. Not that there is anything wrong with Rust if you are ready to pay the price of having so much low level things to deal with.
- hardwaregeek 3y agoCan you explain what Menhir does better than other parser frameworks? For what it's worth, I'm not a huge fan of parser frameworks. I tend to prefer hand written parsers, either via a combinator library or fully manually. Rust has a pretty darn good ecosystem too btw. chumsky for parsing, rowan for syntax trees, salsa for incremental computation, miette for errors, inkwell/walrus for code generation.
- brmgb 3y agoIt can generate elegant and efficient parsers for LR(1) grammars. > I tend to prefer hand written parsers, either via a combinator library or fully manually. That’s common with people used to languages which provide poor parser generators.
- hardwaregeek 3y agoWhat makes them more elegant than the average parser? How’s the error recovery? Can you parse into high fidelity syntax trees efficiently? I don’t know of many production compilers that use parser generators
- klodolph 3y agoYou use the generated parser as a platform for experimentation. If you know the language, and you have a bunch of users, and you are writing a parser for it, by all means, write a parser by hand and give it the best error recovery that you can muster. If you are developing a language and want to do a bunch of experiments, it pays dividends to use a parser generator. And then there is the whole space of DSLs and mini-languages you encounter, where beautiful error messages are a nice-to-have, but you would rather ship a generated parser and move on to more important work. It’s easy to focus on compilers from the perspective of familiar languages like writing compilers for Rust or for OCaml, but you may end up writing a compiler that gets used by a much smaller number of people, for smaller tasks.
- 3y ago
- wredue 3y agoThere was nothing objective about the article. The moment I saw seemingly random new lines in the rust for no reason, I knew there was going to be a “line counts!!!!” Sentence. When there was, I stopped reading because it was apparent that all matter of objectivity is completely missing. I don’t even like rust.
- reikonomusha 3y agoIt would be nice if somebody could offer what they consider to be an idiomatic Rust solution to this very routine problem in compilation if they believe the author is being intentionally deceiving. The Rust and OCaml code from the article looked decent to me. m
- deleted 3y ago[deleted]
- timeon 3y ago> The Rust and OCaml code from the article looked decent to me > RefCell<u32> I'm not sure.
- stouset 3y agoFor the uninitiated, this is a completely harmless choice. But it suggests a potential lack of understanding of some pretty fundamental parts of Rust.
- foldr 3y agoAlthough I think the implementation of the gensym function is broken, the article does explain that it wasn’t possible to use &mut u32 because multiple references to the value were required. It would be more idiomatic to use Cell rather than RefCell, but there’s nothing really wrong with using RefCell as far as I can see.
- tyg13 3y agoI don't think anyone was claiming the author was being intentionally deceiving, just that they're not very good at writing idiomatic Rust. The first thing I'd suggest, as someone who's done their fair share of Rust compiler dev, is to stop using `Box` and `Ref` everywhere. Terms should not own their child terms; the idiomatic way to handle this is to use an arena and typed IDs, and pass a reference to the arena when you need access to the underlying data from the ID.
- deleted 3y ago[deleted]
- hurril 3y agoI've been seriously at it with Rust for about six months now and really loving it. What do you mean by "use an arena for the AST?" What is an arena in this context?
- remexre 3y agohttps://docs.rs/bumpalo/latest/bumpalo/ https://docs.rs/bumpalo/latest/bumpalo/
- mughinn 3y agoi assume they're talking about an Arena Allocator https://blog.logrocket.com/guide-using-arenas-rust/ https://blog.logrocket.com/guide-using-arenas-rust/
- hurril 3y agoI figured as much but was unsure. So the gain is that you still take heap allocations, but you do it in a "novelty" heap allocator that you will probably dipose of entirely at some point?
- vidarh 3y agoAllocation happens roughly like this: If current top of heap + allocation size > buffer size, allocate an extra buffer for the arena. Save the current top in a temp variable. Add the allocation size to the top Return the temp variable. It's fast, and the amortized memory overhead per allocation is near zero because you don't need to track allocation sizes or free lists, since you only free the whole arena at once (one or more buffers). It's ideal for anything where the lifetime of allocations is known to be roughly the same. E.g. a data structure you'll free all at once.
- deleted 3y ago[deleted]
- fuklief 3y agoI believe it means flattening the AST, here is a nice blog post about this technique https://www.cs.cornell.edu/~asampson/blog/flattening.html https://www.cs.cornell.edu/~asampson/blog/flattening.html