|Memory organisation of the Z80 Turbo Pascal compiler email@example.com (Lasse =?iso-8859-1?q?Hiller=F8e?= Petersen) (2021-09-29)|
|Re: Memory organisation of the Z80 Turbo Pascal compiler DrDiettrich1@netscape.net (Hans-Peter Diettrich) (2021-09-30)|
|Re: Memory organisation of the Z80 Turbo Pascal compiler firstname.lastname@example.org (Lasse =?iso-8859-1?q?Hiller=F8e?= Petersen) (2021-10-02)|
|Re: Memory organisation of the Z80 Turbo Pascal compiler email@example.com (gah4) (2021-10-02)|
|Re: Memory organisation of the Z80 Turbo Pascal compiler firstname.lastname@example.org (2021-10-02)|
|Re: Memory organisation of the Z80 Turbo Pascal compiler DrDiettrich1@netscape.net (Hans-Peter Diettrich) (2021-10-03)|
|From:||email@example.com (Anton Ertl)|
|Date:||Sat, 02 Oct 2021 20:45:43 GMT|
|Organization:||Institut fuer Computersprachen, Technische Universitaet Wien|
|Injection-Info:||gal.iecc.com; posting-host="news.iecc.com:2001:470:1f07:1126:0:676f:7373:6970"; logging-data="99799"; mail-complaints-to="firstname.lastname@example.org"|
|Posted-Date:||02 Oct 2021 21:02:59 EDT|
Lasse =?iso-8859-1?q?Hiller=F8e?= Petersen <email@example.com> writes:
>I have been thinking about the old TurboPascal compiler (actually about
>its predecessor COMPAS Pascal, which I used long ago, but I believe the
>original Z80 CP/M TurboPascal was exactly the same in this regard.)
>In the TP 2.0 manual it says:
> "The recursion stack is used only by recursive procedures and
> functions, i.e. procedures and functions compiled with the
> A compiler directive passive (~A-}). On entry to a recursive
> subprogram it copies its workspace onto the recursion stack,
> and on exit the entire workspace is restored to its original
> state. The default initial value of RecurPtr at the beginning
> of a program, is 1 K ($400) bytes below the CPU stack pointer."
>In other words, all procedures in a program have their own statically
>located "workspace", and when recursive calls are made, the previously
>activation's local variables are saved away. I suppose this was practical
>on the Z80, because indexed operations were rather expensive and not
>relative to SP, using the separate IX and IY registers, whereas an LDIR
>instruction was reasonably efficient.
>As far as I can tell, this works great even for a language with nested
>lexical scope like Pascal.
No, it does not give you lexical scoping. Try the man-or-boy test
<http://rosettacode.org/wiki/Man_or_boy_test#Pascal>, or the following
testr[x,p,f,u] <- if p[x] then f[x]
else if atom[x] then u
This is M-expression syntax for Lisp 2.0, which did not catch on;
McCarthy gave this example (written by James R. Slagle) as the case
that showed that Lisp's implementation of the time did not implement
lexical scoping, which McCarthy had intended, and which this program
>When an inner procedure refers to a containing
>procedure's local variable, it will get the currently active instance.
Which can be the wrong one.
>However, I think there would be an issue when passing procedure local
>variables as VAR parameters in combination with some forms of mutual and/
>or nested recursion, as the address passed would refer to the right
>workspace, but the workspace might contain the wrong activation instance.
That is another problem, but note that the Lisp routine above uses
>In any case, I have never found any description of this style of scope
>management, since I actually used this compiler back in the 80es, and I
>don't know if it even has a name?
My guess is that in the early days many compilers used similar
techniques, because many compilers failed the man-or-boy test. But
given that it is incorrect as implementation technique for lexical
scoping, I doubt that these techniques have been given names.
>Other than the copying (which may be considered inefficient, but only
>applies to recursive procedures) and the possible issue with passing
>references ending up pointing to the wrong variable, what would be the
>pros and cons of this method?
Apart from the lexical scoping problem, it is also not particularly
efficient in data memory: It consumes space for all local variables of
all functions at all times (plus the recursion stack), whereas
implementations using activation frames only keep as many as are alive
at the same time.
M. Anton Ertl
Return to the
Search the comp.compilers archives again.