Modules

Hans-Dieter Dreier Ursula.Dreier@ruhr-uni-bochum.de
Wed, 07 Apr 1999 23:55:11 +0200



Matthew Tuck schrieb:

> Hans-Dieter.Dreier@materna.de wrote:
>
> > #ifs should never be neccessary because the compiler can evaluate the
> > expression and remove the code that is inaccessible. IMO the only good thing
> > concerning #ifs is that one can see at first glance that they are there for
> > conditional compilation.
>
> Not really.  Ifs can't handle situations where one branch won't compile
> since required code is not present because it only works in the presence
> of a certain library, etc.

Yes. I didn't think of this.

> Why would you want to know that something is conditionally compiled?  If
> I use a normal if, it can optimise it out or not, it doesn't affect me
> for the most part.

If I see an #if (and know its value) I know definitely which way control will
flow.If it is a normal if, I can't be so sure - I first have to check whether its
value
is constant and known.

> >> Modules are a collection of top-level elements, which will usually be
> >> classes/singular objects/etc.  Hence modules are thrown together into
> >> one program, none having a priveleged status over another.  You can
> >> imagine this as concatenating text files, if the merging were text
> >> files.  Since we are editing ASTs, there is no need for rules
> >> prohibiting forward references.
> > Agree to all. One remark however: I would allow to include not only
> > toplevel elements but also class members and other nested elements as
> > long as the path from root to the element in question touches only
> > classes and name spaces.
>
> I'm not sure what you mean by "only classes and namespaces".

You can't add another parameter (or variable) to a method by adding in a
module,for example.
Here the function (a non-class non-namespace element) would have to be visited in
the
path from root to insertion point.

> The essential difference is that there is only one instatiation of
> classes.  Also, classes can usually not contain other classes, although
> in Java's case, it is allowed.  Hence the need for the distinction is
> disappearing.  A "unified containment hierachy language" only uses
> classes (or types/impls), and considers packages to be "singular
> objects", that is a special sort of combined class/object.  Therefore
> there is only one mechanism for information hiding rather than two.  Ada
> is a mess in this respect.

I wouldn't misuse packages for information hiding.Classes can already provide
everything that is needed.
Modules should be transparent is this respect.
An interesting discussion on the purpose of modules and their relation to classes
can be found at:

http://www.oma.com/Publications/publications.html

Keyword: Granularity

> One possible difference though, is that packages often do have "I use
> this package" declaration, whereas classes don't.  This is because
> packages usually correspond to files.  Therefore is "I use this" a class
> or module concept?  It could be either.

It _is_ both.

> I don't want it to be a module concept since I want to make modules at
> least semi-implicit.  It's an option though.
>
> As a class concept?  It could result in a lot of declarations.  Does a
> method have to specify what it uses as well as a class?

Oh no! Just display a cross reference for information purposes if wanted.Let the
editor/compiler take care of uses.

>  I prefer to
> think of methods as nested singular objects, although it's not certain
> it's possible to do this.  Hence methods and classes would have the same
> nesting mechanisms, simplifying and making the language more flexible.
> But this would carry large syntactic overhead.
>
> An intelligent editor could take some of this away, but it's not certain
> that's any different from letting the editor work out dependencies on
> its own.  What is the point of these dependencies?
>
> (a) To work out dependencies?  Should be done by the editor.

Yes.

> (b) To require the programmer to specify redundant information about
> what they intend to use?

No, too much hassle. What would be gained?

> (c) To make it readable as to what other elements are used without
> looking at the body?

Can be provided on demand by the editor.

> (d) If included in types, could be used to restrict what elements a
> defined method can implicitly access.

What should that be good for?

> (b) & (c) are possible reasons, and (d) is more radical.  I'm not sure
> what the best solution would be.
>
> >> My view of the way the editor should handle this, is to normally not
> >> show the modules at the top of the hierachy, although it could allow
> >> this.  Hence the modules would normally might be transparent, except for
> >> perhaps something to indicate you don't have write access to that code.
> >> Some facility must exist to move top-level elements between modules.
> > Agreed. Centura does it exactly as you sketch here. They have a "refresh"
> > facility to re-load a module in case the user has switched off the
> > automatic detection of file changes, and a "merge" facility that merges
> > all included files.
>
> That's a good point - the code may change outside of the editor.  If
> it's read-only, it's OK, but if you can write to the code, we could get
> problems.  If we have a lock facility to make it read-only if someone
> else is editing it, that would work, but what about if not?
>
> We probably should attempt to ensure files are not saved if they aren't
> edited, although this might not be easy given my desire to make them
> kind of implicit.  Or it might be dead easy.

Every decent editor does it.

> > They also have an "includes" section where you can see what you included
> > (and also, what was indirectly included) as well as edit/insert/delete
> > the file specs. Included parts are always noneditable, but you may spawn
> > another instance of Centura on that include file with a single keystroke
> > and that will open the include's outline at the current position.
>
> What do you mean by include here?  #includes?  Other accessed packages?

What's the difference?

I'll try to elaborate a little bit:
You can *see* everything that has been included (used, if you like) from other
packages,
as well as from the packages that are included indirectly.
If a package is included multiple times (package dependency being a DAG rather
than a tree),
it is shown only once, nevertheless.
If you want to include another package, you name it in the includes section at the
top
of the outline. The included parts will be shown in their appropriate places in
the outline
(new classes in the classes section, globals in the globals section and so on).
If the newly included package needs other includes not yet present, those will be
added
automatically.

I'd like to emphasize that the names of all include files are in one place
and are not scattered about like it is in C.
You'll never have to search for things that have been included.
To the user, it looks as if everything is in one big file, which has some
read-only parts.

Actually, the standard file format (binary) saves a copy of all the included parts
along
with the top-level module. This results in extremely fast load/save cycles
(and in huge files as well, but who cares?) and has the added benefit that you
need only
transfer one file if you wish to copy a project. If the included files are not
present
at the copy location, the load function will simply complain and continue to use
the existing copy. Otherwise it would have checked the file dates to see whether a
refresh
was due.

I always found this very convenient. In comparison the multifile approach of
Visual Studio
or Delphi looks clumsy, slow and cumbersome to use.

> > You would make a separate class / name space of the separated part
> > and use delegation ("stub") to access it, and a back pointer to the
> > surrounding class to access that from within the separated part?
> > (Please forgive my insisting on "how do you" questions, but I need
> > to know how it works, to see what it can do and where its limits are
> > :).
>
> No, nothing as complicated as that.  Every detached element will act
> exactly as if it was attached at run-time.  You would essentially just
> compile the detached element in the namespace of the other element, then
> later reattach it at linking stage.

How can you attach a feature to a *class* at link time?Isn't that VERY
complicated? You need to recompile all derived classes because
the instance layout may change.

> >>(3) Being able to see a top-level element no longer implies you can
> >>access it.
> > Don't you mean "access it no longer"? Otherwise please explain.
>
> I was talking about having a private element of an impl detached to the
> top-level.  Hence we might have a "phantom" element (private method)
> which is at the top-level but which we can't call.  I don't really see
> that as a problem though.

I see.

> --
>      Matthew Tuck - Software Developer & All-Round Nice Guy

--

Regards,

Hans-Dieter Dreier
(Hans-Dieter.Dreier@materna.de)