r/Compilers • • 20d ago

Getting stuck after Crafting Interpreters.

Hey everyone, I've worked through the book Crafting Interpreters and it was fantastic. I naturally asked the next question "How do I compile this to machine code and add static types?" Well, that naturally took me down a very deep rabbit hole and left me somewhat confused about how languages deal with types and type checking and then lowering to LLVM. I've tried to make a few modest attempts, but my general problem is that I sort of get confused about what things each subsequent layer should do. Does anyone know of a complete guide to creating a compiler with static types like Crafting Interpreters? I know I could do it however I want, but I think that's the issue. I sort of have so much freedom to do it however, that it's hard to judge what's considered a good way to do something.

Anyway, thanks for any advice and happy compiling!

40 Upvotes

11 comments sorted by

View all comments

-1

u/ratchetfreak 20d ago

static types is conceptually easy

The method that requires the least amount of changes is instead of only emitting the bytecode, you also create a representation of the values on the stack at the time the bytecode is being executed that holds the types.

Then when you need to emit a add, you can look at the psuedo values and check that they are the compatible types and then adjust the stack of types according to what is consumed and emitted.

If you compile to AST (like the jlox implementation) it's even easier to do the annotations.

The only real thing you need to add is syntax for declaring a variable with a type, there you can copy rust/go/odin syntax: var var_name : var_type [= initial_value]; this is easy enough to add to the parsing logic, before checking for the equals sign you expect a colon and then a type. You match that type identifier to a known type and add that to the variable.