[comp.lang.modula2] Unsafe ADT in Modula-2

HABERNOL@DB0TUI11.arpa.UUCP (02/05/87)

>  Second, concerns the initialization problems with Modula-2 ADTs.
>  When a procedure is called with an uninitialized ADT, a test for
>  undefined is impossible, and a simple test for nil is obviously
>  insufficient.  One solution is [...]
>  [...]
>            Declaring ADT's as pointers to headers, and keeping a list of
>  pointers to these headers would help, but I'm hoping someone will post
>  a better solution (if anyone sees problems with this approach, please
>  let me know too).
>
>  Also, does anyone know of a method to provide automatic cleanup upon
>  termination of an ADT's environment?
>
>                    Bob Hathaway
>                    afd@k.cc.purdue.edu
 
It is impossible to implement a "safe" ADT in Modula-2. It would
require some modifications of the language. You would need full
control over the objects of this type. The exporting module must be
informed on allocation and deallocation of this object (i.e. at
scope entry and scope exit). Furthermore you must have control over
all operations on these objects. You may write an init, fin, assign
routine, but this is very unsafe (because it requires that the user
applies *only* your operations in the *correct* order. I haven't seen
such a user :-)  Such calls had to be generated automatically
by the compiler (block entry, block exit, explicit assignation (":="),
implicit assignation (parameter passing)). You may protect your
implementation of the ADT (by keeping a list of pointers to objects of
this type, or by magic numbers). This will result in additional overhead,
but it doesn't garuantee integrity of data.
 
Problem with list of pointers mentioned above: Because you can't catch the
assignations you have no chance to decide how many valid references to an
object exists. Another problem comes from the missing signals
on scope exit. No chance for your internal bookkeeping.
 
It wouldn't be very hard to modify Modula to allow safe implementations
of abstract data types (some procedures must be bound to the type declaration,
calls are generated by the compiler for allocation/deallocation/assignment).
I have implemented such a system for an extended Pascal dialect
several years ago.
 
After you have done these modifications you would have a nice language but
you will have to find a new name for it because it wouldn't be Modula-2
any longer.
 
  Thomas Habernoll  -  HABERNOL@DB0TUI11.BITNET  -  ...!mcvax!unido!tub!thh

nagler@seismo.CSS.GOV@olsen.UUCP (02/06/87)

    It is impossible to implement a "safe" ADT in Modula-2. 

I have been using ADTs extensively for quite a while.  I have read
lots of articles on them and I will take the liberty of inferring
that "safe" means the programmer won't be chasing bugs.  My experience
with the word "safe" is kind of funny.  For example, I was reading
about the automatic garbage collection (AGC) system in Cedar.  It seems
really spiffy except the system doesn't know how to AGC circular
data structures (e.g. doubly linked lists).  It is up to the programmer
to "do the right thing", that is, implement his own "clean up"
code to properly deallocate the structure.   Modula-2 isn't safe
and neither is Cedar.  They are close, but not perfect.

Like I said, we use ADTs.  We use both the linked list and magic
number stuff for protection.  It seems to work.  In fact, I haven't
chased a NIL pointer bug in a very long time.  We currently only
use the linked list stuff for deallocation control.  So it is just
the magic numbers (and NIL) that seems to be saving us.  Every since
we put in the linked list (or a simpler equivalent), out of memory
bugs were real easy to chase.  We do non-stop (hopefully) real time
systems.  When we do terminate, the system dumps a status of the
memory allocation by module.  Our modules aren't huge or tightly
coupled, so it easy to trace the culprit.

Where's the beef?  Well, it is the same old thing.  Modula-2 is fast,
simple and almost elegant.  It runs on a lot of computers which 
really can't have AGC.  It runs on all kinds of operating systems.
Cedar doesn't exactly fit in all these categories.   I am not
thrilled with Modula-2.  It needs a fair amount of work, but it is
livable with a few simple rules.

The rules we try to follow are: 
    0 Programmers are stupid; reviews increase their IQ.
    1 Always have "Create" and "Destroy" code for objects.
    2 Use termination procedures to clean up your act.
    3 When in doubt, get out of there.
    4 Don't trust anybody unless you know them.
    5 Clean up after yourself.

There are more, of course, but these are the ones that pertain to
the discussion.  Rule 0 is my byword and I am lucky that I have
had good reviewers.  Rule 1 is easy to enforce with rule 0.
Rule 2 is picked up by the last guy out (our ADT manager, if we 
put it in debugging mode).  Rule 3 is just a good idea, that is, 
if you find something is wrong and you don't know how to fix it
(e.g. telling the user to re-enter the number), you can't continue.
Rule 4 says, check your inputs if they aren't already type checked.
This means that you should check out opaque types which are passed
into exported procedures.

The last rule is interesting.  It is the first rule of our lives:
		"Clean up your room!"
Of course, no one ever follows it, which is why God invented mothers
(sorry, Mom).  Moms are pretty good at cleaning up except when
you make messes to quickly or the ratio of garbage generators to 
Moms is high.  I make messes to quickly.   AGC's are glorified 
mothers.  They work ok until you starting making too many messes, 
too quickly.  If the AGC continually follows you around, it can
clean up just fine.  However, you need another processor to do 
the work of one when things get busy.  The AGC can be lazy, 
but then it has a hard time figuring out where you left all 
of your trash which can be annoying in real time environments.

My mother is a smart woman, as most mothers are, and she used to say:
	"If you just put it away in the first place, you
	 wouldn't have to go back later to clean it up!"
This is my byword for software.  You open a file, read from it,
and then you close it.  1,2,3.  A,B,C.  If you set up the rythm(sp?),
anyone can learn to do it.  I haven't seen an AGC that could
"safely" manage a serial port or IP/TCP connection.  Maybe I
deal with this stuff a lot, so I think it is important to handle
real situations like cleaning up the screen upon program exit.

But wait, what about the beginning programmer!?!  Beginning 
programmers, I have found, do not use ADTs.  They don't understand
data abstractions like trees, how are they going to invent
their own?  We have a lot of students working with us.  They don't 
chase out of memory bugs or trashed pointers.  They seem to fit 
right into our environment with a bit of tutoring.  To build
large systems, you need good habits.  If you grow up with someone
cleaning up after yourself all the time, you end up being 
a messy person.  Why not just start the game out right?

ADTs are absolutely necessary to do programming these days. 
It isn't clear that AGC and operator overloading decreases 
programming time, but it may decrease hacking time.  I wonder
if the Modula-2+ guys at DEC/SRC can provide project 
development times to compare with vanilla Modula-2 environments.
It would be an interesting study.

Rob Nagler