I've been thinking along these same lines as well. Here are some
ideas to kick around.

1. Have a C/C++ front-end compile to an intermediate language so you
could do all types of optimizations (see Dragon book, etc.). After
optimization, compile that to Forth code and run. Then again,
the intermediate code could be Forth words. I might not want
the intermediate code part to be *native* Forth words, though.
I'm hesitant here for lack of experience in this area.
I've read many compiler books and feel comfortable with the notion of
going from intermediate code (IC), (i.e. three-address code, dags, etc.)
to assembly because:

a. The methods of dealing with IC in optimization are well-documented.

b. Optimization of native Forth words *as* IC does not strike me
as being nearly as easy...if you need help (and you will), there's
little, to my knowledge, in compiler/interpreter research papers
to turn to. That is, Forth is probably too rich a language and using
too many Forth words as IC can hinder rather than help optimization
strategies (I would like for somebody in the know to prove me
dead wrong here...)

This could be a good starting point for a C/C++ compiler whose
initial stages of development is more interpretive. I can see
this strategy as very effective in the actual testing (of the
correctness of the interpreter/compiler) process (i.e. code fragments).

2. I would like to think of the Forth engine as the virtual machine
language part. After optimization of whatever the
intermediate code representation (ICR) is (i.e. three-address code,
dags, etc.) you could either use Forth to interpret the ICR or go
to assembly code and have your assembler, written in Forth, run it.
Also, you can get into the techniques that Forth systems use such as
F-PC or C-Forth to generate object code or executables.

I think using Forth or some other threaded-interpretive environment
for C/C++ (and other imperative languages) is a novel approach. Not
only can you have an interpreter, but a good portion of the compiler
part is there to boot (i.e. when you generate the assembly code that
Forth interprets).

If I had to implement something like this for a C++ interpreter, I
probably wouldn't do a mapping of C++ to the types of things Dick Pountain
did in his Object-oriented Forth book. My main reason would be that I'd
want both a C++ interpreter *and* a good quality C++ compiler to come from
the work. Forth would help me to achieve this goal. I'd take the
dependency of having to generate different assembly code for each machine
rather than a "C++ to Forth translator" that wouldn't be well-optimized
and left me totally dependent on the Forth engine part. I'd want the
Forth engine to be "plug and play" so I could pull it out of the process
and be able to use an independent assembler if I so choosed. Allowing for
these different approaches up front in the design stage will make it less
likely that I'll have to rewrite large portions of the program to get it
started in a different direction (i.e. { C++ -> ICR -> Optimize -> Forth
interprets ICR} *or* {C++ -> ICR -> Optimize -> assembler code ->
Assembler in Forth interprets}) .

All of the above are just ideas (I claim no expertise in the field). I'd
be very interested in hearing others' opinions / implementation
experiences / horror stories ;-). IMHO, it's a fascinating subject.

Did Microsoft use a similar concept in their QuickBasic product line
(Visual Basic as well?). ?

P.S. I would STRONGLY suggest that anyone considering taking on a
C++ interpreter/compiler from scratch would be wise to use Jim Roskind's
freely available (I didn't say PD ;-)) C++ Yacc-able grammer.
If you don't, then I would then suggest you buy a *second* case of
of Tylenol (you'll need the first one just for attempting to write
a C++ interpreter or compiler ;-))