On Jun 23, 2021, at 1:22 PM, Stan Sieler via cctalk
<cctalk at classiccmp.org> wrote:
Paul K got it right:
"Any language can be interpreted or compiled. For some languages, like
LISP and TECO, interpreting is a rather natural implementation techniques,
while for others (C, ALGOL) compilation is the obvious answer. But either
A few quick notes...
...In some cases, we emulate a 16-bit wide CISC architecture (e.g., if you use
the SPL construct "ASSEMBLE (...)", we compile it...into PA-RISC code
emulating the old architecture). It's still in use today, and can now emit
either PA-RISC code or C source code (for a form of cross-compiling).
That's a bit like the machine code translation pioneered by DEC (MIPS to ALPHA) and
subsequently used by Apple ("Rosetta") for PowerPC to Intel and now Intel to ARM
(M1). In a sense, those translators are compilers like all others, except for the rather
unusual "source code" they accept as input. Similar but somewhat different: the
DEC Alpha assembler was a compiler front end, connected to the code generator shared with
the (conventional) Alpha compilers. It was rather amusing to say
"macro/optimize" and see what the optimizer would do to your assembly code...
What HP missed, and many people miss, is that any
language can be
compiled. The main question one might ask is the degree of closeness to
machine code that's emitted :)
I think it was Dijkstra who observed, in the context of the original EL-X1 compiler, that
you're generating code for a "machine" of your choosing. When you see a
runtime library call, it makes sense to think of that as a machine operation of a
hypothetical machine different from the physical target hardware. And function calls can
be encoded as subroutine jump instructions, or in what is often more compact and nearly as
fast, threaded code or P-code words. Typical FORTH implementations are neat in that
respect, since they use a threaded code encoding that allows for fast and efficient
switching between threaded code (subroutine calls) and straight machine code.