[comp.lang.modula2] conditional compilation

mccalpin@loligo.cc.fsu.edu (John McCalpin) (01/13/89)

In article <INFO-M2%89011219330825@UCF1VM> <INFO-M2%UCF1VM.bitnet> writes:
>As was recently observed in the info-pascal mailing list, optimization ->
>conditional compilation.  Consider:
>      CONST
>        OpSys = VMS;
>      IF OpSys = VMS THEN
>        DoVMSStuff
>      ELSE
>        DoOtherOSStuff;
>All but the most inanely STUPID of compilers will completely eliminate the
>unreachable code. Anthony L Kimball : alk @ ux.acss.umn.edu / UMNACVX.bitnet

This is only true if the code in Do_VMS_Stuff is *syntactically valid*
on all machines.
Certainly not all machine-specific extensions are compilable on all
systems -- I am thinking of VMS in particular here.  In the Fortran
context, there ain't no way to make most machines compile statements
like
	call LIB$SYS_VMS_SPECIFIC_STUFF (args)
and the optimizers I know of won't remove the dead code unless they
can figure out what it is, since optimization comes long after parsing
and lexical analysis....

In the modula-2 context, I am sure that the machine-specific vector
extensions to the CDC Pascal/Modula-2 compiler (for the Cyber 205 & ETA-10)
are not syntactically valid on other machines....
-- 
----------------------   John D. McCalpin   ------------------------
Dept of Oceanography & Supercomputer Computations Research Institute
mccalpin@masig1.ocean.fsu.edu		mccalpin@nu.cs.fsu.edu
------------------------------------------------------------------

joel@WSL.DEC.COM (Joel McCormack) (01/14/89)

I was hired by DEC 4 years ago to write a Pascal compiler for a RISC
machine, the Titan.  After evaluating the options, I figured the
easiest way to go about it was to modify Mike Powell's Modula-2
compiler, which already generated code for the machine.

Since I hate fixing bugs in two places, the obvious choice was to
maintain one set of sources, conditionally compiled.  I started to set
this up by calling the C preprocessor from the Modula-2 comiler, but
that got too messy too quickly.  Including .h files is not the same as
importing modules, no matter what a C hacker tells you.

So I added conditional compilation to the compiler.  It was quite easy,
took less than a week, and I wouldn't live without it.  Conditional
compilation is not the same as dead code elimination, no matter what
a Modula-2 purist tells you.

I now have one set of sources that generates two compilers.  It is
very occasionally confusing to follow program logic, but the reduction in
maintenance effort is well worth it.


The facility looks like this:

ProgramArgument        =   "-D"Ident"="ConstantExpression.

Directive        =   "$IF" ConstantExpression "THEN" ProgramText
            {"$ELSIF" ConstantExpression "THEN" ProgramText}
            ["$ELSE" ProgramText]
            "$END" [";"]
            |   "$CONST" Ident "=" ConstantExpression. [";"]

ConstantExpression  =    SimpleConstExpr [Relation SimpleConstExpr].

Relation        =   "=" | "#" | "<>" | "<" | "<=" | ">" | ">=" | IN.

SimpleConstExpr     =   ["+" | "-"] ConstTerm {AddOperator ConstTerm}.

AddOperator        =   "+" | "-" | "OR".

ConstTerm        =   ConstFactor {MultiplyOperator ConstFactor}.

MultiplyOperator    =   "*" | "DIV" | "MOD" | "AND" | "&".

ConstFactor        =   Ident | Number | String | Set | "NOT" ConstFactor
            |   "~" ConstFactor | "(" ConstantExpression ")".

Set            =  "{" SetRange {"," SetRange} "}".

SetRange        =  Number [".." Number].

Number            =   digit {digit}.

digit            =   "0".."9".

String            =   "'" {character} "'"
            |   '"' {character} '"'.

Ident            =   letter {letter | digit}.

letter            =   "A".."Z" | "a".."z".


$ as the first non-blank character on a line indicates a directive.  This may
cause some hassles with RCS $Header declarations in comments.  Just put another
character in front of the $, and RCS will still find the $Header.

All ConstantExpressions are evaluated, and all CONST declarations enter a
name in the symbol table, including those in sections that are being skipped
due to a previous expression evaluating FALSE.  I am not sure if this will
cause problems (some identifiers may be defined with different values in
different sections, maybe?).  It can be changed if someone comes up with a
convincing case.

TRUE and FALSE are predefine boolean Idents.

Constants passed in from the command line override those defined in $CONST
definitions.

+ - * DIV MOD apply only to numbers.

AND & OR NOT ~ apply only to booleans.

Relational operators apply to number, booleans, sets, and strings.


About the only thing I'm inclined to add is a DEFINED procedure, which
would work just like the C preprocessor.

- Joel McCormack
    joel@decwrl.dec.com
    decwrl!joel