> but the tail calls are integral to the function of the interpreter

Not really, a trampoline could emulate them effectively where the stack won't keep growing at the cost of a function call for every opcode dispatch. Tail calls just optimize out this dispatch loop (or tail call back to the trampoline, however you want to set it up).

Yup, standard practice for interpreters in languages that don't have tail call optimization.