clearm@comcast.net writes:>I am trying to understand why the C stack is used in interpreters>rather than an explicity built stack on the heap?

You mean, for calling? I cannot tell you why they do it, because I
have used an explicit stack in all the interpreters I have written,
and I recommend that to everyone. My guess as to why they do it is:

It looks natural and obvious to map a call in the source language to a
C call (just like they usually map an addition in the source language
to an addition in C) rather than to decompose it into its parts. I
guess that in many cases not that much thought goes into that
decision.

The only possible advantage that I can see to this method is that it
may make the combination of callbacks and longjmps more
straightforward to implement.

The disadvantages to using C calls are:

- It restricts you in the kind of control flow you can implement.
Tail-call optimization? Backtracking? Coroutines? First-class
continuations? No. Well, maybe you can cobble something together,
but it will certainly be harder than with an explicit implementation
of calls. Essentially, using the C call restricts your source
langauge to C-like control flow.

- It is slower. In addition to the call overhead of your language,
you have to pay for the C call overhead, and that might be
considerable depending on the amount of state that your interpreter
has. Moreover, this choice may also have indirect costs, like putting
some virtual machine registers in global variables (i.e., in memory)
instead of in locals (typically registers), in order to be able to
access them across calls. However, I have not measured these
performance effects (and I don't know that anyone has).