From VMS to UNIX

T.J.Teixeira tjt at kobold.UUCP
Thu Oct 27 00:35:14 AEST 1983


apollo!alan makes the following claims in support of BLISS:

    I. BLISS is a better systems-programming language
	than C.  The built-in features of the language
	for dealing with
    
	    o bit-fields
	    o specific registers
	    o user-defined linkage conventions
	    o user-written accessing algorithms
	      (the STRUCTURE declaration)
	    o character sequence manipulation
	    o VOLATILE memory
    
	are far superior to what C provides.  Further,
	the BLISS compile-time and macro-preprocessor
	facilities are orders of magnitude more powerful
	than what C gives you!  
    
	  In BLISS, you can write an interrupt handler without
	invoking ANY runtime support - the compiler emits the REI,
	RTI, RTT or whatever and knows where the PC and PSL or PSW
	are on the stack, etc...
    
First, a disclaimer: my knowledge of Bliss is confined to the examples
and definitions in "The Design of an Optimizing Compiler" by W. Wulf et
alia, along with glancing at bits of Bliss code used as part of the NIL
Lisp system at MIT.

Be that as it may, in rebuttal:

    o bit-fields
True, bit-fields are more pervasive in Bliss than in C.  Also, I
believe that C botched bit fields by not specifying the semantics of
bit fields declarations more precisely.  As it is, bit fields are not
useful for specifying the precise layout of external bit fields (i.e.
as interpreted by some external hardware) in a machine independent way.
They are also not usable for defining binary data structures in a
portable and machine independent way, even for communication between
consenting C programs.

However, within reasonable limits (i.e. similar word-sizes) you can
achieve what is required using machine dependent declarations.  I don't
believe that Bliss is able to magically solve the problem of converting
binary files from a 36-bit machine (e.g. PDP-10) to an 8-bit byte
machine (e.g. VAX or PDP-11) either.

It might be nice to just declare automatic variables as bit-fields
without having to dummy up a structure to contain it.  This deficiency
can be overcome using #define's, but this is not a satisfactory
solution since #define's don't obey the same scope rules as variable
declarations.

    o specific registers
    o user-defined linkage conventions

I can see no use for these except to accomodate calling conventions of
pre-existing assembly language programs and/or to exploit glitches in
hardware architecture.  Granted, Bliss may be a better language for a
VAX (I can specify that the foo routine is invoked with a jsb instead
of a call instruction), or a PDP-10 (lot's of possibilities for
subroutine linkages here).

    o user-written accessing algorithms

This is a good thing, but is very easily abused.  I will elaborate more
on the nature of this abuse later.

    o character sequence manipulation

What can I say?  Functions can get the job done, but would require a
very sophisticated compiler indeed in order to produce the same code on
a machine which actually supports character string operations.

    o VOLATILE memory

Steve Glaser at Tektronix also pointed this out to me by mail.
You obviously need some sort of declaration like this if you don't want
to hamstring your optimizer.  I'm not sure how it's implemented in
Bliss.  The problem is that this is really is run-time limitation based
on the actual addresses accessed, but would have to be declared
statically at runtime. e.g. all data accessed through a given pointer
is volatile.  Alternatively, one could tag entire structure's,
individual structure elements or variables to be volatile (the latter
two would be necessary to accomodate shared memory communication).
As it is, C can only safely consider parameters and automatic variables
to be non-volatile.  There exists compiler options to allow more scope
for an optimizer, but there should be a way of declaring this in the
language.

    o Further, the BLISS compile-time and macro-preprocessor
      facilities are orders of magnitude more powerful
      than what C gives you!

True, but C already gives you a dangerous amount!  The problem with
extensive pre-processing is that the lexical appearance of the source
code no longer gives you enough information about the semantics of the
program.

For example, in most contexts in C, a name refers to a variable.
Exceptions to this are names following "." or "->" (structure elements)
or preceeding "(" (function names).  This isn't complete information
since the storage class (static, automatic, parameter) is not directly
deducible from the name, nor is the type.

However, using the preprocessor, a name could be *anything*: a
constant, a keyword, punctuation, an entire expression (possibly
including free variables or side-effects).  Yes, you can do *amazing*
things with the C preprocessor (look at the source code for the Bourne
shell or adb, or "Modular C", Stowe Boyd, SIGPLAN Vol 18 No 4).  It may
look alot like C, but it's different enough to be considered a
different language.

To combat this, most C programmers use the convention of #define'ing
constants using UPPER CASE names, and making sure that #define'd macros
with parameters behave like a function call.  If you want to extend the
compile-time facilities, I would prefer an approach similar to PL/1
that makes it explicit what is happening at compile time and what is
happening at run-time.  If you want to extend the language, write a
pre-processor: don't kid yourself by hacking around with arcane macros
and call the result C.

    o In BLISS, you can write an interrupt handler without
      invoking ANY runtime support - the compiler emits the REI,
      RTI, RTT or whatever and knows where the PC and PSL or PSW
      are on the stack, etc...

So what?  My unix system has over 600 functions in the kernel.  Maybe
10 of them are interrupt handlers.

    o C would be the TECO of programming languages, if TECO wasn't
      already the TECO of programming languages.

Well, TECO may suffer from having many primitives that are a bit too
primitive (i.e. nearly useless by themselves), but it does have
powerful ways of combining this primitives to get something done.
However, this leads to the problem of encouraging (practically
requiring) the user to write TECO macros to get interesting things done.

Taken to its extreme (EMACS), you have a very powerful system hiding in
a ball of mud.

Yes, I like EMACS (I'm using now and it has been my editor of choice
for years).  However, what I like is *my* EMACS: anyone elses is almost
certainly different, primarily because EMACS makes it so easy to
customize.

All this sounds more like BLISS and C to me: the BLISS programs I have
seen rely heavily on macros and other compile-time facilities
(including user-written accessing algorithms).  This is fine for a text
editor, because I never have to use *your* EMACS.  However, before
someone else can understand *your* BLISS program, they not only have to
know BLISS, they have to know *your* BLISS macros and coding styles to
a much larger than someone has to know *your* C macros and coding
styles.

Note that the hazards of letting programmers get their hands on too
powerful a macro facility has been observed in other application
domains: consider nroff/troff as opposed to Scribe.  An explicit design
goal for Scribe was to not let the hackers have macros so that Scribe
could remain a document description language rather than a programming
language for putting dots on a laser printer.

Constructive Suggestions for Enhancements to C

The C "class" pre-processor ("Classes: An Abstract Data Type Facility
for the C Language", Bjarne Stroustrup, SIGPLAN Vol 17 No 1) is what I
feel to be a better approach than undisciplined (or even disciplined!)
use of macro preprocessors to fix up C.  For that matter, I don't have
many objections to ADA, as long as I can use the base language and
don't have to drag along all the "standard" packages being dreamed up
for the ADA programming environment.

More particularly, the "class" processor gives a direct way of
declaring functions that should be expanded inline.  This enforces my
expectation that "foo(bar)" in my program will behave *semantically*
like a function call and is *not* going to insert a bunch of closing
brackets or semi-colons.

Classes also provide a mechanism for solving some of C other ills (i.e.
lack of a complex data type), but not all (passing variable size two
dimensional arrays would still be a problem).

I think C would also be helped by integrating an exception handling
mechanism (a la CLU) into the language.
-- 
	Tom Teixeira,  Massachusetts Computer Corporation.  Littleton MA
	...!{harpo,decvax,ucbcad,tektronix}!masscomp!tjt   (617) 486-9581



More information about the Comp.lang.c mailing list