I am working on a simple Lisp -> Bytecode compiler in Rust. I am running into a design issue with bytecode design.
Consider the problem of mutually recursive functions f & g.
f compiles to
g compiles to
One 'solution' would be double indirection. We have a
code: Vec<Rc[Instr]> so what happens is that for f to call g, it looks up
code[g_idx] (one indirection to address the Vec, a second to follow the Rc) and runs the code.
A second approach is to hard code the corresponding Rc[Instr] of
f/g into each other (avoiding the Vec lookup). But this creates circular references. In AOT systems this would not matter, but with REPL support, I'd prefer unused + unaccessible (due to shadowing) funcs to be dropped over time.
Question: I'm sure others have run into the mutual recursive bytecode problem. What are the typical strategies used to solve this problem ?