[comp.lang.modula2] 'One-pass' Compilation Issues

randy@oresoft.UUCP (Randy Bush) (09/25/87)

                        One-pass Compilation Issues
                                25 Sep 87

This is not complete, and comes to no clear conclusion.  The intent is to
provoke and focus discussion.  This is excerpted from an internal paper of 28
September 86, with some small additions.


Overview

A Modula-2 compiler, given the language defined in PIM-2.3, requires more
than one pass, as Modula-2 allows declaration after use in a procedure body. 
Pascal's approach of adding FORWARD procedure declarations solves the worst
of the problems, but mutually importing internal modules would be the major
loss.  A number of popular current compilers have the one-pass restriction,
including that of Professor Wirth.

It is worth noting that multi-pass compilers may have the one-pass
restrictions.  The real question is not how many passes the compiler makes
(whatever a 'pass' may be), but how it resolves forward references.  Thus,
'one-pass restrictions' may be a misnomer, but, for lack of a clearer term,
it will be used here.


Use of a Variable Before Declaration

PIM-2.3 does not allow a declaration of a variable (except of a pointer) to
require forward resolution.  On the other hand, a statement may use a
variable or constant before it is declared. Thus

   PROCEDURE p ();
     VAR  x : T;
     BEGIN
       x := 42
       END p;
   TYPE T = CARDINAL

is not legal, while the following is.

   PROCEDURE p ();
     BEGIN
       x := 42
       END p;
   TYPE T = CARDINAL;
   VAR  x : T

Worse, the following is legal.

   VAR x : INTEGER;
   PROCEDURE p ();
     PROCEDURE q ();
       BEGIN
         x := 42
         END q;
     VAR  x : CARDINAL;
     BEGIN END p;

As use before declaration is not kind to the reader of a program (one
net.@hole has called it abomination :-), its loss may be considered of little
consequence.


Forward Reference to Procedures

PIM-2.3 would allow forward reference to procedures, thereby allowing mutual
recursion of procedures, e.g.

   PROCEDURE p ();
   BEGIN
     q ()
     END p;
   PROCEDURE q ();
   BEGIN
     p ()
     END q;

This was allowed in early specifications of Pascal, but was not implemented
by any compilers to my knowledge.  The common work-around for one-pass
restrictions in Pascal is predeclaration using the FORWARD directive, e.g.

   PROCEDURE q (); FORWARD;
   PROCEDURE p ();
   BEGIN
     q ()
     END p;
   PROCEDURE q ();
   BEGIN
     p ()
     END q;

Don Baccus reminds me that Wirth's Pascal "Report" does not mention FORWARD,
but leaves it for Jensen's "User Manual".


Mutually Importing Internal Modules

What one-pass compilation can not provide is mutually importing internal
modules.  E.g.

   MODULE a;
      MODULE b;
        IMPORT x;
        EXPORT y;
        CONST  y = 42;
        END b;
      MODULE c;
        IMPORT y;
        EXPORT x;
        CONST  x = 77;
        END c;
      END a.

The above is actually quite useful, and lack of the ability forces formation
of library modules to circumvent the restriction.  Mutually importing
internal modules have been used in the ETH multi-pass compiler, as well as
some code in the real world.

This also includes the case where code wishes to use objects exported from a
following internal module, and that module wishes to use objects declared
above.  E.g.

   VAR s,t : CARDINAL;
   PROCEDURE p ();
   BEGIN
     Init (t)
     END p;
   MODULE m;
     EXPORT Init;
     PROCEDURE Init ( VAR c : CARDINAL );
     BEGIN
       IF s = 0 THEN
         c := s
         END
       END Init;
     END m;


Wirth's One-pass Compiler

In his recent one-pass compiler for the MC68000, NSC32000, and 8x8y family,
Professor Wirth adds FORWARD to procedure declarations.  At first he tried to
move mutually recursive procedures to the definition module, but received
very negative feedback.  The one-pass restrictions seem to be acceptable to
his user community for the moment.  Many current implementations are derived
from Professor Wirth's one-pass compiler.


Volition's Implementations

Volition's p-code system (they also did a completely different MC68000
native system) was derived from the one-pass P2 compiler, and therefore
could not implement the language as specified in PIM-2.3.  They added
FORWARD to procedure declaration, disallowed use before declaration, and
did not support mutually importing internal modules.

There was no negative user feedback on these restrictions.  As the p-code
compiler was quite fast for an interpretive implementation (2,000 lpm on
a floppy based 68000 at 8MHz), the users seemed to feel the trade was worth
it.  This was in '81.

Volition's native code compiler for the 68000 was written with the same
restrictions.  This product has been acquired and developed further by
Masthaven, and their impressions of user feedback would be useful in
evaluating the impact of one-pass restrictions.


The Modula-2 Validation Suite

When writing the M2VS, PSG had serious qualms and questions about this issue.
As it could not be clearly resolved, it was decided that the suite as a whole
should not rely on either mode, but specific tests would be included which
determined whether or not the implementation had one-pass restrictions. 
These tests were classified as quality tests, rather than conformance or
deviance.  This may be a reasonable compromise.


The BSI

One-pass restrictions have been discussed in committee, and were generally
received positively.  Many small changes in recent drafts indicate someone
has an eye on one-pass compilation.  The question is will they add FORWARD,
disallow declaration after use, and disallow mutually importing internal
modules?


Conclusion

I come to none (and you had to read all this!?!).  All in all, it's a tough
issue.  Existing implementions of both sorts exist, and, presumably,
considerable user code exists that relies on both styles of implementation.
Maybe the PSG M2VS decision, that it is a quality issue not a conformance
issue, was correct.
-- 
randy%oresoft.UUCP@tektronix.tek.com   Fidonet:1:105/6   1+(503) 245-2202