[net.lang.mod2] One Pass compiler

gbs@voder.UUCP (George Smith) (08/23/84)

[munch a bunch]

   In the article "A Portable Optimizing Compiler for Modula-2" from
SIGPLAN Notices Vol. 19, #6, June 1984 written by M. L. Powell it
mentions that Modula-2 permits statements to reference identifiers
that are defined later in the compilation and therefore requires
a multi-pass compiler.  The marketing literature that I obtained
from Volition Systems at the last West Coast Computer Faire states
that their compiler is a "fast one-pass compiler".  Would someone
in the know please comment.

George Smith
Digital Signal Processing
National Semiconductor
...!ihnp4!nsc!voder!gbs
...!ucbvax!voder!gbs

ian@loral.UUCP (Ian Kaplan) (08/24/84)

This note refers to an article posted by George Smith, reproduce below:

>>     In the article "A Portable Optimizing Compiler for Modula-2" from
>>  SIGPLAN Notices Vol. 19, #6, June 1984 written by M. L. Powell it
>>  mentions that Modula-2 permits statements to reference identifiers
>>  that are defined later in the compilation and therefore requires
>>  a multi-pass compiler.  The marketing literature that I obtained
>>  from Volition Systems at the last West Coast Computer Faire states
>>  that their compiler is a "fast one-pass compiler".  Would someone
>>  in the know please comment.

    Modula not only permits forward reference (e.g., reference to
    identifiers declared after their use) but a fully conformant Modula
    compiler must provide this feature.  Volitions compiler, now published
    by Springer-Verlag, is indeed a fast one pass compiler.  The Volition 
    compiler does not allow forward reference without a forward
    declaration.  In practice this has never proven to be a problem.

ags@pucc-i (Seaman) (08/25/84)

The Volition compiler is indeed one-pass.  Yes, a standard-conforming Modula-2
compiler cannot possibly be one-pass.  Volition did it by including 
Pascal-style "forward" declarations. [UGH!]
-- 
[This is my bugkiller line.  It may appear to be misplaced, but it works.]

Dave Seaman			My hovercraft is no longer full of 
..!pur-ee!pucc-i:ags		eels (thanks to my confused cat).

patcl@tekecs.UUCP (Pat Clancy) (08/27/84)

    >> ...The Volition 
    >> compiler does not allow forward reference without a forward
    >> declaration.  In practice this has never proven to be a problem.

Some two year old flyers I have from Volition do indeed state (in the
"fine print") that Pascal-style forward declarations are required.
I would have thought they would have fixed this by now, since this
is not really Modula-2 (in fact, I think they called it "Modula-][").
loral!ian's assertion that it is not a problem is surprising. 
First, the Pascal-style ordering requirements can be very awkward
and constraining; imposing them on Modula-2 is morally repugnant.
Second, it means that a forward declaration of an identifier may have
to be put *outside* the module in which that identifier is declared,
which certainly violates the spirit of the module syntax.

I don't know if Volition even allows forward declarations of all
identifiers, or just procedures. The Modula-2 scope rules
do not restrict the types of yet-to-be-declared identifiers that may 
be referenced in statements.

Pat Clancy
Tektronix
{ucbvax,decvax,ihnp4,allegra,uw-beaver,hplabs}!tektronix!tekecs!patcl

ian@loral.UUCP (08/28/84)

This note is in reference to the portion of Pat Clancy's article 
reproduced below:

> Some two year old flyers I have from Volition do indeed state (in the
> "fine print") that Pascal-style forward declarations are required.
> I would have thought they would have fixed this by now, since this
> is not really Modula-2 (in fact, I think they called it "Modula-][").
> loral!ian's assertion that it is not a problem is surprising. 
> First, the Pascal-style ordering requirements can be very awkward
> and constraining; imposing them on Modula-2 is morally repugnant.
> Second, it means that a forward declaration of an identifier may have
> to be put *outside* the module in which that identifier is declared,
> which certainly violates the spirit of the module syntax.

  The Volition Systems Modula compilers were designed to run on
  microcomputers, notably the Apple ][e, Apple ///, IBM PC and the Sage
  line of 68000 systems.  Microcomputers, especially the Apple ][ and ///,
  have very limited resources and a one pass compiler is best for such
  systems.  There is no way to get rid of the forward references without
  using a two pass compiler.  If this is done, the entire symbol table must
  be kept for the second pass.  There are two places to store the symbol
  table from the first pass: in memory or on disk.  Until recently
  most microcomputers had only 64 K of RAM, so the symbol table clearly could 
  not be contained in memory.  Disk space was also very limited and disk
  access was slow.  Storing the symbol table on flex disk would have
  greatly slowed the compiler and consumed an unpredictable amount of disk
  space.  People who use minicomputers with virtual memory and fixed disk
  space measured in the gigabyte sometimes forget the problems faced by
  people designing software to run in the microcomputer environment.  Given
  the costs incurred in this environment by a multipass compiler one should
  be very sure that the forward reference problem really is that much of a
  problem.

  I am a reformed Pascal programmer, so this may be why I do not find 
  Volitions restrictions a problem.  It should be noted that except for
  forward reference they still allow CONST, TYPE and VAR declarations to be
  intermixed.  

  I can tell from Mr. Clancy's comment that imposing Pascal's declaration
  order restrictions on Modula is "morally repugnant" that he is a fellow
  language zelot.  Down with the evil typeless herisy of C!

			    Ian Kaplan
			    ucbvax!sdccsu3!loral!ian

ian@loral.UUCP (09/09/84)

Mark Friedman submitted the following note in reference to my claim that
a two pass compiler on a micro could not store the symbol table in memory.

>   One has the same problem of fitting the symbol table into memory near
> the end of a one pass compilation as keeping it in memory for the second
> pass of a two pass compiler. I think that compilation speed is really the
> issue here, though it does interact with the limited space problem. Micro
> based compilers generally have to make so many concessions to compilation
> speed (mostly in order to get the largest symbol table possible) that to
> add another pass would make the compiler unreasonably slow.

Mr. Friedman is, of course, correct in saying that compiler speed a 
major consideration in the design of a micro based compiler.  

The statement that 

"One has the same problem fitting the symbol table into memory near the end 
 of a one pass compilations as keeping it in memory for the second pass of 
 a two pass compiler."

is not entirely correct.

In a one pass compiler for languages like Pascal or Modula, symbol table 
space can be recycled when the compiler finishes compiling a scope.  For
example, when the compiler finishes compiling a procedure, all information
about the procedure's local variables can be disposed of.  Using this scheme
the symbol table will only contain information about procedures, modules and
global variables when the last statement is compiled.  A two pass compiler
capable of resolving Modula's forward references will be forced to save
more information in its first pass.  Consider what must be saved to resolve
the references in the procedure shown below.

    PROCEDURE OuterScope;

      PROCEDURE InnerScope;
      BEGIN
	OuterScopeVar := -1;
      END InnerScope;

    VAR
      OuterScopeVar : INTEGER;

    BEGIN (* OuterScope *)
      InnerScope;
    END OuterScope;

In a well written Modula program most of the identifiers will be enclosed
in the scope of a module or procedure.  This will minimize the amount of
global information which must be kept on hand in a one pass compiler.  Of 
course there will also be many procedures, but some of these will also be 
nested.

                         Ian Kaplan
			 Loral Data Flow Group
			 Loral Instrumentation
			 8401 Aero Dr.
			 San Diego, CA
			 92123
			 (619) 560-5888 x4812

                         ucbvax!sdcsvax!sdcc6!loral!ian

bobo@inmet.UUCP (09/09/84)

#R:voder:-32400:inmet:16700004:000:1336
inmet!bobo    Aug 31 15:55:00 1984

   I don't accept Ian Kaplan's rationale for the use of one-pass
compilers on micro-computer based systems: i.e,

  > ...
  >     There is no way to get rid of the forward references without
  > using a two pass compiler.  If this is done, the entire symbol table must
  > be kept for the second pass.  There are two places to store the symbol
  > table from the first pass: in memory or on disk.  Until recently
  > most microcomputers had only 64 K of RAM, so the symbol table clearly could 
  > not be contained in memory.  Disk space was also very limited and disk
  > access was slow.  Storing the symbol table on flex disk would have
  > greatly slowed the compiler and consumed an unpredictable amount of disk
  > space.

  One has the same problem of fitting the symbol table into memory near
the end of a one pass compilation as keeping it in memory for the second
pass of a two pass compiler. I think that compilation speed is really the
issue here, though it does interact with the limited space problem. Micro
based compilers generally have to make so many concessions to compilation
speed (mostly in order to get the largest symbol table possible) that to
add another pass would make the compiler unreasonably slow.

				    Mark Friedman
				    ...harpo!inmet!bobo
				    ...esquire!inmet!bobo
				    ...ima!inmet!bobo

bbanerje@sjuvax.UUCP (B. Banerjee) (09/11/84)

>> ...
>>     There is no way to get rid of the forward references without
>> using a two pass compiler.  If this is done, the entire symbol table must

Scuse me.  It's been a while since the Compilers I & II, but 
isn't there a technique known as 'Back-patching' which allows
one pass compilation without requiring forward references?

Regards,
-- 
				Binayak Banerjee
		{allegra | astrovax | bpa | burdvax}!sjuvax!bbanerje
P.S.
	Send Flames, I love mail.

KURKURE@SUSHI.STANFORD.EDU (Uday Kurkure) (10/03/86)

>	Actually, you can note the fact that whatever type the symbol has
>    must be compatable with how it is being used, and check that against
>    the actual declaration when you see it.  For example, if I see a
>    function call:

>  intvar := funct( 5.0, "test", 7 );

>   I can note that funct must return a type that can be assigned to an int,
>   and accept a floating point, char array, and integer argument;  then,
>   when I see a declaration of funct, I can check against this usage, and
>   determine whether the previous usage was correct.


     What happens if the intvar is also declared forward ?

     Such things can lead to lot of bookkeeping. Consider a
     following statment and lot of occurrences of the similar
     statements.

     .
     .
     a1 := a1 * f1( x,y,z )+ a2 + a3 + f3............* x100
     .

     ..

     VAR
       x100: type;
       .
       .
       .
       .
       a1: type100


    etc etc.
    

   This could be reasonably difficult to do with one pass.

                                 ..Uday
-------

bobc@tikal.UUCP (10/06/86)

>>	Actually, you can note the fact that whatever type the symbol has
>>    must be compatable with how it is being used, and check that against
>>    the actual declaration when you see it.  For example, if I see a
>>    function call:
>
>>  intvar := funct( 5.0, "test", 7 );
>
>>   I can note that funct must return a type that can be assigned to an int,
>>   and accept a floating point, char array, and integer argument;  then,
>>   when I see a declaration of funct, I can check against this usage, and
>>   determine whether the previous usage was correct.
>
>     What happens if the intvar is also declared forward ?
>

I feel that a one pass compiler can't easily handle forward
declarations as stated in the language definition.  I also have used
the "ETHZ" one pass compiler, and feel that the limitations that Wirth
added are reasonable.  The first limitation (and not a unreasonable
one) is that variables must be declared before they are used.  Also
TYPE must be defined before they are used (with the exception of the
normal POINTER TO undefinedtype defines).  Third is that forward
declaritions of PROCEDUREs is required using the FORWARD directive.

At one point I felt that "backpatching" could solve the problem as in:

    intvar := funct( 5.0, "test", 7 );

But since I have done some work with the one pass compiler (and have
seen the source) it turns out that there are some problems.  The
first is you can't tell what type any of the arguments are.  For
example what if the parameters were all "ARRAY OF WORD" (BYTE is
another form of the same thing on the One Pass Compiler).  For example
based on what the ETHZ One Pass Compiler does:

PROCEDURE funct(v1,v2,v3:ARRAY OF BYTE):INTEGER; FORWARD;

....
    intvar := funct(5.0, "test", 7);

Expands to the following code:

    PUSH.W	#3
    PUSH.L	ADR(Const5.0)
    PUSH.W	#3
    PUSH.L	ADR(Const"test")
    PUSH.W	#1
    PUSH.L	ADR(Const7)
    CALL	funct
    POP.W	intvar

Note that arrays are passed by address, and the called function then
copies them.  This code is much different then the expected:

    PUSH.L	#5.0
    PUSH.W	#3
    PUSH.L	ADR(Const"test")
    PUSH.W	7
    CALL	funct
    POP.W	intvar

This means that you would have to do so much backpatching as to be come
almost unreasonable, (not completely impossable but almost)  It would
seem almost as reasonable to make a two pass compiler.  I do however
feel that using variables before they are defined is unreasonable, and
I also find the "FORWARD" directive a small price to pay for a very
fast compiler.

Bob Campbell
Teltone Corporation		18520 - 66th AVE NE
P.O. Box 657			Seattle, WA 98155
Kirkland, WA 98033

{amc,dataio,fluke,hplsla,sunup,uw-beaver}!tikal!bobc