I'm working on an interpreter in Rust, following along with the Crafting Interpreters book. This is my second Rust project, and it's still very much a work in progress.
I don't want to take up too much of your time, but if anyone has a moment to take a look and share some feedback, I'd really appreciate it.
Thanks
A few notes:
I'm a hobbyist programmer. I had a brief period of professional experience, but I realized it was taking the joy out of programming for me, so I stepped back and kept it as a hobby instead. My goal is simply to get as good as I can at Rust and compilers.
This is also actually my first real experience with Git I'm still learning things like CI/CD as I go, so please bear with me if anything looks unconventional.
On the name: "buhran" means "crisis" (or "depression" in the emotional sense) in Turkish. I chose it because it has personal significance to me from this period of my life. I'm not sure how much it matters to anyone else, but it means something to me.
I've also tried to keep AI assistance to a minimum throughout this project mainly using it for feedback and discussions on how to make the code more idiomatic, rather than having it write the code for me.
One more thing the tool that helped me the most throughout this project was honestly just Clippy.
I looked over your project. I'm not versed in interpreters, so I won't review the functionality part. I just focused on the Rust code style. Here are a couple of notes, which I hope won't be too overwhelming.
The project is quite well structured, especially for second Rust project. One advice I would give is to use library crates (so make lib.rs the root of the project). Binary then will just import everything, set up environment, load configuration and run library's entrypoint.
You are unwraping in many random places. While it may seam nice for prototyping, it definitely won't be nice for debugging. I encourage you to design structure of code with returning errors early on. It is usually easier to change the error type later, than to introduce them later.
Currently you don't use any dependencies. While it's nice to write everything yourself, there are some very standard crates, which you should know about, if only to understand other people's code. Some crates you might look at are: clap (for parsing CLI arguments), anyhow and thiserror for managing error types, log/tracing for logging structured data (invaluable for debugging in my opinion). I'm not saying that they will be correct choices for your project, but they should give you solid starting position and let you focus on your main logic.
For anything serious operating on UTF-8 "characters" I would suggest adding fuzzing harness. It's very easy to make a silly mistake when slicing UTF-8 bytes, and fuzzers can easily catch many bugs of this nature.
Overall you have a really nice starting point. If you have any questions in the future how to achieve something, or how to best design an API, please feel encouraged to ask them here.
I sadly don't have the time to give an in-depth review at the time, but feel free to take a look at what we do in uutils awk. Our project already follows many of the suggestions from the other comment, so feel free to take some inspiration
It might be too much to handle, but it'd be cool to have a Rust tracing JIT with a Cranelift backend. Just sayin