[comp.lang.modula2] disgust at DEC

broman@BUGS.NOSC.MIL (Vincent Broman) (05/15/87)

Said heiser@ethz.uucp --
> I had a look at the DEC [Powell] compiler when we got it and was disgusted....
> Probably the people who wrote it never programmed any Modula-2.
> ... Much worse: definition modules are not compiled (and there is no compiler
> option to fix that). Hence:
>    - no timestamping, no consistency checks when modifying definition modules.
>      Any real Modula-2 programmer estimates that as one of the most powerful
>      language features when developing large systems.
>    - identifiers imported in the definition module are not known in the
>      implementation module, they must be imported again. This will generate a
>      compile-time error in most other Modula-2 systems

Though much that DEC does could make strong men queasy, the points
mentioned above do not seem questionable.

Simply stated, mod compiles .def files by means of the identity
transformation, (saves time, you know :-) and the timestamp is
available in the file's inode.  I suppose the .o file stores the
last-mod-time for all DEFINITION MODULEs IMPORTed and compares them for
consistency at link time.  Nothing more could be required.  The _only_
reason one "compiles" DEFINITION MODULEs into binary form is to avoid
lexing/parsing/checking them _every_time_ they are IMPORTed.

As I read PIM2 ed3, identifiers IMPORTed into a DEFINITION MODULE
cannot be visible in the matching IMPLEMENTATION MODULE unless
IMPORTed.  While defs and imps come in pairs, they are distinct
MODULEs.  Perhaps the rule causing confusion was the one that makes
_objects_declared_ in the def available in the imp without IMPORT.
As a practical matter, though, it is hard to imagine a useful
instance where one IMPORTs an identifier into a DEFINITION MODULE
which is not then needed in the matching IMPLEMENTATION MODULE.

Let's not puff on the subject of who is a "real Modula-2 programmer", hey?

Vincent Broman,  code 632, Naval Ocean Systems Center, San Diego, CA 92152, USA
Phone: +1 619 225 2365    Internet: broman@nosc.mil   Uucp: sdcsvax!nosc!broman

heiser@ethz.UUCP (Gernot Heiser) (05/17/87)

In article <8705151536.AA07897@bugs.nosc.mil> broman@BUGS.NOSC.MIL (Vincent
Broman) writes:
>Said heiser@ethz.uucp --
>>...
>>    - no timestamping, no consistency checks when modifying definition modules...
>>    - identifiers imported in the definition module are not known in the
>>      implementation module, they must be imported again. This will generate a
>>      compile-time error in most other Modula-2 systems
>
>Though much that DEC does could make strong men queasy, the points
>mentioned above do not seem questionable.
>
>Simply stated, mod compiles .def files by means of the identity
>transformation, (saves time, you know :-) and the timestamp is
>available in the file's inode.  I suppose the .o file stores the
>last-mod-time for all DEFINITION MODULEs IMPORTed and compares them for
>consistency at link time.  Nothing more could be required.

This is not true, I tried the following example:

DEFINITION MODULE m1;
EXPORT a, b, c;
CONST a = 10;
TYPE b = (red, (* yellow, *) green, blue);
PROCEDURE c (VAR bb: b);
END m1.

IMPLEMENTATION MODULE m1;
PROCEDURE c (VAR bb: b);
BEGIN
   bb := blue;
END c;
END m1.

MODULE m2;
FROM m1 IMPORT a,b,c;
FROM io IMPORT Writef, output;
VAR aa: CARDINAL;
    bb: b;
BEGIN
   aa := a;
   bb := red;
   c (bb);
   IF    bb = red   THEN Writef (output, "red");
   ELSIF bb = green THEN Writef (output, "green");
   ELSIF bb = blue  THEN Writef (output, "blue");
   END;
END m2.

I compiled ("mod m1.mod m2.mod") and the result was, expectedly, "blue".
Then I edited the comments out of m1.def, thus changing the type "b" to contain
an additional literal. Re-linking the already compiled modules
("mod m1.o m2.o") worked without an error, running produced the same result,
"blue". Next I recompiled m2: "mod m1.o m2.mod". Again, no error was reported,
and running the program produced the result "green"!

Hence, THERE IS NO TIMESTAMPING, exactly as I said.

>As I read PIM2 ed3, identifiers IMPORTed into a DEFINITION MODULE
>cannot be visible in the matching IMPLEMENTATION MODULE unless
>IMPORTed.  While defs and imps come in pairs, they are distinct
>MODULEs.  Perhaps the rule causing confusion was the one that makes
>_objects_declared_ in the def available in the imp without IMPORT.

Imports ARE declarations! PIM2 ed2 p 143 (sorry, I don't have ed3 at hand, but
there should be no difference concerning this point):
"Every identifier occuring in a program must be introduced by a declaration,
unless it is a standard identifier."
This means, importing an identifier into a definition module declares this
identifier, and hence makes it "available in the corresponding implementation
module without explicit import." (PIM ed2 p 164)

The DEC compiler may be a good compiler after all, unfortunately it compiles a
language that is not Modula-2.

-- 
Gernot Heiser                      Phone:                +41 1/256 23 48
Institute for Integrated Systems   EAN/CSNET/ARPA:       heiser@ifi.ethz.chunet
ETH Zuerich                        EARN/BITNET/NETNORTH: GRIDFILE@CZHETH5A
CH-8051 Zuerich, Switzerland       EUNET/UUCP:   {seismo,...}!mcvax!ethz!heiser

broman@BUGS.NOSC.MIL (Vincent Broman) (05/18/87)

Two rejoinders to Mr. Heiser

1st.
IMPORT clauses are not declarations, they merely make identifiers
visible outside the scope surrounding their declaration.  Your quote from PIM2:
"Every identifier occuring in a program must be introduced by a declaration,
unless it is a standard identifier" does not require a declaration in each
MODULE, but rather one declaration in each program.  Also, check the syntax
diagrams (or EBNF productions) for "declaration" in the back.  Declarations
occur only in "blocks" which occur in "ProcedureDeclaration",
"ModuleDeclaration", and "ProgramModule", in the latter two _after_ the
imports and exports.

2d. about timestamping --
A reminder of a subtle point:  standard operation of the Powell compiler
is not the default, but rather requires invocation with the "-s -M" options.
It appears that you never explicitly requested the inter-module checking
that you desired.  (I don't propose to justify that argument passing
design, just remember it.)

My supposition about the contents of .o files was mostly wrong.  It appears
from experiment (without access to the sources) that the intermodule checker
does not operate by means of a time-stamping scheme, but attempts to meet
the same requirements by comparing for consistency the binary-form copies
of every DEFINITION MODULE, as found in the .o file of each MODULE that
IMPORTs it.  So, one way to view the approach is to say that the .def file
gets compiled every time a client IMPLEMENTATION MODULE is compiled.

As far as I can see, Wirth did not specify how the compiler was to organize
its object code, as long as it:
A. allows separate compilation of "compilation units"
B. guarantees independence of client MODULEs from the implementation
     of MODULEs imported
C. provides "full type compatibility checking between objects", even across
     MODULE boundaries.
Timestamping is one implementation method for ensuring consistent
type-checking, though not the only one.  Powell's compiler ensures consistency
even for cases where a time-stamping implementation would require unnecessary
recompilation, say, because of comments having been added, for example.

Mr. Heiser's code example just shows what happens when one alters a DEFINITION
MODULE and neglects to recompile the .def file.  Exactly the same thing
happens with the Cambridge compiler.  The solution to the problem of
forgetting to recompile .def files is to use make.

Come to think of it, users of make with correct makefiles would find most
of the difficulties discussed here to be of academic interest only.


Vincent Broman,  code 632, Naval Ocean Systems Center, San Diego, CA 92152, USA
Phone: +1 619 225 2365    Internet: broman@nosc.mil   Uucp: sdcsvax!nosc!broman

broman@BUGS.NOSC.MIL (Vincent Broman) (05/18/87)

Correction to my last posting -- The neglected "-M" option is the
kernel of the problem with Mr. Heiser's code example; make is a
side-issue.

Vincent Broman,  code 632, Naval Ocean Systems Center, San Diego, CA 92152, USA
Phone: +1 619 225 2365    Internet: broman@nosc.mil   Uucp: sdcsvax!nosc!broman

broman@BUGS.NOSC.MIL (Vincent Broman) (05/20/87)

About IMPORTs not being declarations--
I thought I had constructed an example for which both Powell and Cambridge
compilers agreed with me, and after deleting it I cannot reconstruct it.
(It must have been late at night. :-)  Simple experiments suggest Powell
takes IMPORTs as declarations, Cambridge not.

Since my purpose was to advance my view of the language, not defend a
particular compiler, I will cheerfully abominate Powell and laud
Cambridge on this one point.  Perhaps others will concede that Powell
is not totally depraved, then.

It would be nice if there were a _real_ m2 compiler available for unix,
but no one seems to think it's worth developing the product. Sigh.

Vincent Broman,  code 632, Naval Ocean Systems Center, San Diego, CA 92152, USA
Phone: +1 619 225 2365    Internet: broman@nosc.mil   Uucp: sdcsvax!nosc!broman