allanswers.org - Modula-3 Frequently Asked Questions (FAQ)

 Home >  Programming >

Modula-3 Frequently Asked Questions (FAQ)

Section 1 of 2 - Prev - Next


Archive-name: Modula-3-faq

   Michel Dagenais Michel Dagenais, GNU General Public License, 1998-2001
   
   
    michel.dagenais@polymtl.ca
    Ecole Polytechnique
    C.P. 6079, Succ. Centre-Ville
    Montreal, Quebec, H3C 3A7
    
                Modula-3 Frequently asked questions and answers
                                       
   Maintained by Michel Dagenais ([1]michel.dagenais@polymtl.ca),
   suggestions are most welcome. Last updated January 15 2002. The latest
   copy of this FAQ may be obtained from the [2]Polytechnique Montreal
   Modula-3 Home.
   
Introduction

What is Modula-3?

   Modula-3 is a systems programming language that descends from Mesa,
   Modula-2, Cedar, and Modula-2+. It also resembles its cousins Object
   Pascal, Oberon, and Euclid.
   
   The goal of Modula-3 is to be as simple and safe as it can be while
   meeting the needs of modern systems programmers. Instead of exploring
   new features, we studied the features of the Modula family of
   languages that have proven themselves in practice and tried to
   simplify them into a harmonious language. We found that most of the
   successful features were aimed at one of two main goals: greater
   robustness, and a simpler, more systematic type system.
   
   Modula-3 retains one of Modula-2's most successful features, the
   provision for explicit interfaces between modules. It adds objects and
   classes, exception handling, garbage collection, lightweight processes
   (or threads), and the isolation of unsafe features.
   
Where is Modula-3 used? Is it used in industry?

   A number of programming teams selected Modula-3 for industrial and
   research projects, and for teaching. It encourages good programming
   practices and comes with excellent libraries for distributed
   programming and graphical user interfaces. A non exhaustive list is
   available at [3][Modula-3 at Work].
   
Is commercial support available?

   Critical Mass Corporation used to offer their own version of SRC
   Modula-3, CM3, an integrated development environment for Modula-3,
   [4]Reactor, as well as training and consulting services.
   
   Olaf Wagner from [5]Elego Software Solutions is now maintaining [6]CM3
   as an open source package and offers commercial support.
   
Where can I get documents and information on Modula-3?

   A [7]concise bibliography and a more complete [8]bibliography describe
   Modula-3 related books, technical reports, and papers. The definition
   of Modula-3 is contained in: [9]"System Programming with Modula-3"
   also known as SPwM3. Sam Harbison has written a more tutorial book
   titled [10]Modula3.
   
   Three main Web servers contain Modula-3 related information:
   [11]www.m3.org, [12]DEC SRC Modula-3 home page, and [13]Ecole
   Polytechnique de Montré Modula-3 home page.
   
   The Usenet newsgroup comp.lang.modula3 is the official meeting place
   for Modula-3 related discussions.
   
Is Modula-3 a superset of Modula-2?

   No; valid Modula-2 programs are not valid Modula-3 programs. However,
   there is a tool to help convert Modula-2 programs to Modula-3.
   
Comparisons between Modula-3 and other languages?

   From: laszlo@post.ifi.uni-klu.ac.at (Laszlo BOESZOERMENYI)
   
   A Comparison of Modula-3 and Oberon-2 by myself in Structured
   Programming 1993, 14:15-22
   
   From: nayeri@gte.com
   
   Robert Henderson, Benjamin Zorn, A Comparison of Object-Oriented
   Programming in Four Modern Languages, Department of Computer Science,
   University of Colorado, Boulder, Colorado, [14]Technical Report
   CU-CS-641-93.
   
   The paper evaluates Oberon, Modula-3, Sather, and Self in the context
   of object-oriented programming. While each of these programming
   languages provide support for classes with inheritance, dynamic
   dispatch, code reuse, and information hiding, they do so in very
   different ways and with varying levels of efficiency and simplicity. A
   single application was coded in each language and the experience
   gained forms the foundation on which the subjective critique is based.
   
What implementations are available, how do they compare?

   All implementations are based on [15]DEC SRC Modula-3. [16]Critical
   Mass offered an improved version with commercial support. It features
   incremental garbage collection on NT, and a few additional packages
   like ODBC database access. This is now [17]open sourced and maintained
   by Olaf Wagner. Ecole Polytechnique de Montréal has been maintaining
   an [18]updated distribution. It features integrated documentation, and
   NT support through the gcc cygwin compiler
   
Can I contribute Modula-3 software?

   Contributions are most welcome. The primary contact to offer
   contributions is comp.lang.modula3.
   
   [19]The Ecole Polytechnique de Montréal Modula-3 distribution is the
   most regularly updated and may be a good place to submit your
   contribution.
   
Why use Modula-3?

   Here is what John Polstra, author of the popular CVSup, replied:
Subject: Re: SUP on sup.freebsd.org
Date:Wed, 06 Nov 1996 12:31:26 -0800
From:John Polstra
> Erhm, why on earth did you chose Modula3 ??

   Modula-3 really is a different language, designed specifically for
   systems programming by some extremely competent and experienced people
   who knew what they were doing.
> Oh and yes I have seen apps written in modula3, all of which was
> horrible performers, and impossible to port to new platforms, so
> the management decide a complete rewrite in, guess what, C!

   Are you sure it was Modula-3? The SRC Modula-3 compiler supports about
   25 different platforms.
   
   Plenty of real world apps (*big* ones) have been written in Modula-3,
   and they perform pretty well. There's also the SPIN OS project
   [20][SPIN] at University of Washington, in which the kernel was
   written in Modula-3. It performs well, too.
   
   Now, you can always argue that a program would be somewhat faster and
   somewhat smaller if it had been written in C. Hey, guess what? I was
   around when Unix V6 came out, and the same stuff was written about it.
   Just substitute "C" for "Modula-3" and "assembly language" for "C".
   The answer is the same in both cases: Unix would not exist as we know
   it today if it had been written in assembly language. CVSup would not
   exist as we know it today if it had been written in C (or C++, for
   that matter).
   
   OK, so why on earth did I choose Modula-3? In no particular order:
    1. I needed application level threads, and threads are an integral
       part of the Modula-3 language. About the only reasonable
       alternative was to use pthreads with C or C++. But pthreads was
       not well supported under FreeBSD at that time.
    2. I needed a graphical display during development so that I could
       monitor the 3 client threads as they were running, debug them,
       appraise their relative performance, and find the bottlenecks.
       Modula-3 has a very nice toolkit for creating GUIs quickly and
       painlessly. (OK, so the scrollbars are as ugly as sin.)
    3. Modula-3 is a compiled language that is reasonably efficient.
    4. I needed to use some low level system functions, e.g., mapping
       files into memory. Modula-3 provides good access to such
       functions, and it is quite easy to add interfaces to foreign
       libraries such as "libz".
    5. Modula-3 has good support for networking.
    6. It is a mature and stable language that has been used in a number
       of serious, large projects. The language and compiler have been
       stable for about 5 years, which is more than you can say for C++.
    7. It has nice support for object oriented programming, including a
       good type system, a nice exception model, and a modern
       high-performance garbage collector. These traits, IMHO, contribute
       powerfully to producing well-structured, maintainable programs.
       Now before you label me an unstudly OO weenie, please consider
       this. I've been programming in C professionally for 19 years. I
       made my living for many years writing C compilers and related
       tools such as assemblers, linkers, and disassemblers. I still use
       C and C++ when I feel they are appropriate for a project, not to
       mention when I have to because that's what the client wants to
       use. I have experience programming in many many different
       languages. Different languages are good for different things. I
       still like programming in C (and C++ for some things), but I'm
       glad I didn't use it for CVSup.
    8. I had just come off a huge 3+ year C++ project. During that time,
       I learned just how much C++ sucks. I did not feel like doing it
       again right away "for fun."
    9. I have spent my entire professional career getting paid to use the
       wrong tools, because, e.g., the manager read that C++ was
       "popular." For once, just once, on a _hobby_ project, I decided I
       was going to use the tool I felt was the best for the job at hand.
       I thought about it long and hard, evaluated several options (C and
       C++ among them), and eventually chose Modula-3. I have never
       regretted that decision.
       
   Any questions? :-)
John
- --
   John Polstra                                       jdp@polstra.com
   John D. Polstra & Co., Inc.                Seattle, Washington USA
   "Self-knowledge is always bad news."                 -- John Barth

Troubleshooting

Why program receives a SEGV signal under the debugger?

   The garbage collector on some platforms uses the SEGV (segmentation
   violation) signal to detect modified portions of the dynamically
   allocated space. It is possible to disable this feature or to inform
   the debugger to let these signals propagate. See the [21]m3gdb
   documentation.
   
Problems with threads, fork and VTALARM?

   The threads are implemented using the virtual timer interrupt.
   Normally, the run time environment will catch the interrupt and
   determine if thread switching is appropriate. However, if a new
   process is created with fork, it will have the virtual timer activated
   and no interrupt handler to receive it, resulting in a core dump. If
   you use the standard procedure Process.Create to fork new processes,
   this will be handled automatically for you. If you insist on using
   fork, you need to disable the timer, fork and then reenable the timer.
   
X libraries not found?

   The position of X libraries is stored, for instance for pre-compiled
   PM3 LINUXELF binaries, in the template file m3config/src/LINUXELF as
   well as in X11/LINUXELF/.M3EXPORTS (m3build/templates/LINUXELF, and
   X11R4/LINUXELF/.M3EXPORTS for SRC-M3). Thus you may want to edit these
   files if your X libraries are located in an uncommon place.
   
What means Missing RTHooks or similar messages?

   The standard library, libm3, is not included by default. You need in
   your m3makefiles to import("libm3") or to import a library which
   imports libm3. Otherwise, messages about run time procedures such as
   RTHooks not being available are produced.
   
M3build versus Make or why m3 does not work?

   The Modula-3 compiler m3 does a much finer grained dependency analysis
   than possible with make. For this reason, a very flexible front end,
   m3build, reads the program description files, m3makefile, and
   generates the commands required to compile and link Modula-3 programs
   and libraries. The m3makefile content is documented in the m3build
   documentation. Calling the m3 compiler directly is difficult and thus
   not recommended, especially on PM3 where it is now merged with
   m3build.
   
Why are exceptions raised by X or Network Objects applications?

   Graphical applications (based on Trestle/X Windows) raise the
   TrestleComm.Failure exception when the DISPLAY environment variable is
   incorrect or the X server is refusing the connection. They raise
   MachineIDPosix.Failure if the network configuration files are
   incorrectly set up, especially on LINUX; /etc/hosts must contain at
   least a loopback address (127.0.0.1) and the /etc/rc scripts an
   appropriate ifconfig command (/etc/ifconfig lo 127.0.0.1; /etc/route
   add 127.0.0.1). Applications with Network Objects may also raise
   exceptions or consume all the CPU time available when the network
   configuration files are incorrect.
   
What is the story with Trestle and OpenWindows?

   Mark Manasse says:
   
   I think that the OpenWindows release should be enough (no need to get
   the MIT X release), although there are a few things in Trestle that
   trigger devastating bugs in OpenWindows. But the only library we
   depend on is Xlib, R4 or later.
   
   The main thing I know that crashes OW 2.0 is the code where we call
   GrabKey specifying AnyKey. You can either loop over all of the keys,
   or you can just comment out the call; programs won't run exactly the
   same, but you probably won't notice the difference.
   
Why so many problems installing on Solaris?

   These notes were contributed by (simon.hood@umist.ac.uk) while
   installing PM3-1.1.14 on a Sun Ultra 5 running Solaris 2.8. They
   describe various problems and their solution or workaround.
   
   The installation of PM3 on Solaris systems is particularly prone to
   problems as these systems tend to be an unpredictable (from the point
   of view of the PM3 people) mixture of Sun and Gnu software --- Sun do
   not bundle a C compiler with the operating system.
   
   My machine has gcc version 2.95.2 installed; it has Sun's versions of
   make, ld, as and ar installed within /usr/ccs/bin; Gnu's version of
   these tools are not installed.
   
   My installation was successful, after a bit of fiddling around with
   the configuration/template files and environment variables. Some of
   the fixes are trivial (if you know what you are doing), while others
   --- for me at least --- were not --- I am a Modula 3 novice and far
   from experienced with Solaris.
   
   The issues that arose are:
     * Paths needed to be set to find tools such as make.
     * LD_LIBRARY_PATH needed to be set to ensure libstdc++.a.2.10.0
       and/or libstdc++.so.2.10.0 were found.
     * A link needed to be set so that byacc points to yacc.
     * The configuration for linking needed to be changed since only the
       Sun version of ld was installed, not Gnu's.
     * The build of m3gdb failed to build.
     * The gnuemacs package failed to build.
       
Initial Problems

   Paths
          gcc is usually installed in /usr/local/bin; on a Solaris
          machine, ar, as, make and ld are all in /usr/ccs/bin, by
          default. Hence these must both be on root's path (assuming you
          are installing as root). Neither were; I have not changed any
          paths since installation of Solaris 2.8 on a new machine a few
          days ago.
          This is in addition to /usr/local/pm3/bin, as mentioned by the
          PM3 installation instructions.
          
   byacc/yacc
          The build required byacc. yacc is installed in /usr/ccs/bin; a
          soft link:
          
     lrwxrwxrwx   1 root     other          4 Aug 11 15:45 byacc -> yacc


          solved this problem.
          
   Library Paths
          In addition to /usr/local/pm3/lib/m3 as mentioned by the PM3
          installation instructions LD_LIBRARY_PATH must include
          /usr/local/lib so that libstdc++ (part of the gcc distribution)
          can be found.
          
   CC
          In addition I found that the environment variable CC needed to
          be set to /usr/local/bin/gcc. This is of course mentioned in
          the PM3 installation instructions.
          
Miscellaneous Questions

Can I get Modula-3 other than by FTP or HTTP?

   Prime Time Freeware (PTF) includes Modula-3. PTF is a set of two
   ISO-9660 CDroms filled with 3GB of freeware, issued semi-annually. PTF
   is distributed via bookstores and mail. You can reach PTF using:
   
        Email:  ptf@cfcl.com
        Fax:    [1] (408) 738 2050
        Voice:  [1] (408) 738 4832
        Mail:   Prime Time Freeware
                415-112 N. Mary Ave., Suite 50
                Sunnyvale, CA 94086
                USA

   Many Linux CDroms include a copy of the FTP site tsx-11.mit.edu which
   has Linux binaries for Modula-3.
   
How to call Modula-3 procedures from a C program?

   Calling Modula-3 from C is tricky because M3 has a more elaborate
   run-time environment. The simplest solution is to make the main
   program M3 and then call C via EXTERNAL routines. Calling back into M3
   is then relatively straightforward.
   
   Here's an example. It calls the C code to lodge the identity of the M3
   procedure to be called back which avoids having to know the actual
   name used by the linker.
   
   First a little M3 module to be called from C (M3code), then a C module
   called by the M3 main and calling the M3 module (Ccode), and finally
   the main program (Main):
(* M3code.i3 *)

INTERFACE M3code;
IMPORT Ctypes;
PROCEDURE put (a: Ctypes.char_star);
END M3code.

(* M3code.m3 *)

UNSAFE MODULE M3code;
IMPORT Ctypes, IO, M3toC;

PROCEDURE put (a: Ctypes.char_star) =
  BEGIN
    IO.Put (M3toC.StoT (a) & "\n");
  END put;

BEGIN
END M3code.

(* Ccode.i3 *)

<*EXTERNAL*> INTERFACE Ccode;
IMPORT Ctypes;
PROCEDURE set (p: PROCEDURE (a: Ctypes.char_star));
PROCEDURE act (a: Ctypes.char_star);
END Ccode.

/* Ccode.c */

typedef void (*PROC)();
static PROC action;

void set (p)
  PROC p;
  {
    action = p; /* register the M3 procedure */
  }

void act (a)
  char *a;
  {
    action (a); /* call the M3 procedure */
  };

(* Main.m3 *)

UNSAFE MODULE Main;

IMPORT Ccode, M3code, M3toC;

BEGIN
  Ccode.set (M3code.put);
  Ccode.act (M3toC.TtoS ("Hello world"));
END Main.

(* m3makefile *)

import(libm3)

interface ("Ccode")
c_source ("Ccode")
module ("M3code")
implementation("Main")
program("mixed")

Can Modula-3 code call C++ and vice-versa?

   There is no problem to call C++ functions declared as extern C. You
   must use a C++ aware linker (e.g. the C++ compiler). A complete
   example of M3 calling C++ objects, which in turn call M3 callbacks, is
   available in [22]the sgml library.
   
   On some platforms, a call to get the static variables constructors
   called may be required:
   
   From: gwyant@cloyd.East.Sun.COM (Geoffrey Wyant - Sun Microsystems
   Labs BOS)
   
   You must use your C++ compiler as the linker, rather than /bin/cc or
   /bin/ld.
   
   You need to call the function '_main'. The easiest way to do this is
   to have the following set of interfaces and implementations:
   
        INTERFACE CXXMain;
          <*EXTERN "_main"*> CxxMain;
        END CXXMain;

        MODULE CXXMain;
        BEGIN
          CxxMain();
        END;

   and then import CXXMain into your M3 main module. This will ensure
   that the C++ function _main gets called.
   
How to copy heap objects?

   Deep copies are easily performed using Pickles. An object graph is
   Pickled to a text writer into a TEXT. Then, a copy is created by
   unpickling a new object graph from a text reader created from the
   TEXT.
   
   Shallow copies are less often needed but may be performed with the
   following procedure:
PROCEDURE Duplicate (r: REFANY): REFANY =
  VAR
    tc     := TYPECODE (r);
    n_dims : INTEGER;
    res    : REFANY;
    shape  : RTHeapRep.ArrayShape;
  BEGIN
    IF (r = NIL) THEN RETURN NIL END;

    (* allocate a new object of the same type (and shape) as the old one *)
    RTHeapRep.UnsafeGetShape (r, n_dims, shape);
    IF (n_dims <= 0)
      THEN res := RTAllocator.NewTraced (tc);
      ELSE res := RTAllocator.NewTracedArray (tc, SUBARRAY(shape^, 0, n_dims));
    END;

    (* copy the old data into the new object *)
    RTMisc.Copy (RTHeap.GetDataAdr (r), RTHeap.GetDataAdr (res),
                 RTHeap.GetDataSize (r));

    RETURN res;
  END Duplicate;

How to get output messages to appear immediately (flushing writers)?

   Modula-3 Writers are buffered. Thus, you need to issue a Wr.Flush when
   the output should appear immediately, for instance to prompt the user
   for some input. Since this can become annoying, libraries in other
   languages sometimes offer the option of unbuffered writes. In
   Modula-3, an equivalent behavior is obtained with AutoFlushWr which
   gets a background thread to flush a writer at a specified interval.
   
How to read a single character as soon as typed?

   Characters typed on the keyboard are usually buffered. They become
   visible to the reading program only when the buffer is full or after,
   for example, a carriage return is received. This is not specific to
   Modula-3. To access the characters as they are typed, single character
   commands in a full screen editor for example, the input reader must be
   configured properly.
   
   From: [23]rrw1000@cus.cam.ac.uk (Richard Watts)
   
   The POSIX way of doing it is to use tcsetattr(), and here is some code
   that does it under Solaris 2.x (this was written for serial ports, but
   the same thing applies) :
PROCEDURE Open(port : CHAR; timeout : INTEGER := 30) : T RAISES {Error} =
  VAR
    term : TcPosix.termios;
    file : TEXT;
    fd : T;
    rc : INTEGER;
  BEGIN
    (* Figure out which device we want to open : *)

    CASE port OF
      'A' => file := "/dev/ttya";
    | 'B' => file := "/dev/ttyb";
    ELSE RAISE Error("Invalid port " & Fmt.Char(port) & " specified.\n");
    END;

    (* Open it. 700 is a good default mode for serial ports. *)
    fd := Unix.open(M3toC.TtoS(file),  Unix.O_RDWR
                                            , 8_700);
    IF fd = -1 THEN
      RAISE Error("Open() on " & file & " failed.\n");
    END;

    (* Get the termios structure for it *)
    rc := TcPosix.tcgetattr(fd, ADR(term));
    IF rc # 0 THEN
      EVAL Unix.close(fd);
      RAISE Error("Couldn't get terminal attributes for " & file & ".\n");
    END;

    (* Modify the termios structure *)

    (* The default baud rate is right, but we'd better set it anyway
       in case someone left it set up wrong : *)
    rc := TcPosix.cfsetospeed(ADR(term), TcPosix.B9600);

    IF rc # 0 THEN
      EVAL Unix.close(fd);
      RAISE Error("Couldn't set output speed for " & file & "\n");
    END;

    rc := TcPosix.cfsetispeed(ADR(term), TcPosix.B9600);

    IF rc # 0 THEN
      EVAL Unix.close(fd);
      RAISE Error("Couldn't set input speed for " & file & "\n");
    END;

    (* Modify the line discipline - reset ECHO and ICANON *)
    term.c_lflag := Word.And( term.c_lflag,
                              Word.Not(
                                  Word.Or(TcPosix.ICANON,
                                          TcPosix.ECHO)));
    term.c_cc[TcPosix.VMIN] := 0;
    term.c_cc[TcPosix.VTIME] := 0; (* Set up timing right *)

    (* Now reset the terminal attributes *)
    rc := TcPosix.tcsetattr(fd, TcPosix.TCSANOW, ADR(term));

    IF rc # 0 THEN
      EVAL Unix.close(fd);
      RAISE Error("Can't set attributes for " & file & "\n");
    END;
    RETURN fd;
  END Open;

   (TcPosix.i3 is one of my interfaces, not libm3's, and I'll supply it
   if you like, but it's just a wrapper to tcgetattr and friends. The
   baud rate stuff shouldn't be necessary for terminals (or serial
   ports..) ). You should be able to somehow get an Rd.T out of this, I
   think, but it may involve a bit of hacking. The University of
   Cambridge can't have these opinions even if it wants them.
   
Why is Hello World larger in Modula-3 than in C?

   Modula-3 programs are slightly larger than C programs because the
   generated code includes runtime type information, and runtime checks
   for out-of-bound array references and NIL pointers. Many of these
   checks could be removed by a more sophisticated compiler.
   
   The fixed runtime is substantially larger (there is no runtime support
   in C). It contains a garbage collector, a thread runtime, and
   exception support. It is typically placed in a dynamically linked
   library, shared on disk and in memory between all the Modula-3
   programs.
   
What is SRC Modula-3?

   [24]SRC-Modula-3 was built by the DEC Systems Research Center and is
   freely available and redistributable, with source code. In Europe it
   is also available from ftp-i3.informatik.rwth-aachen.de in
   pub/Modula-3. The most recent version is release 3.6
   
   The DEC SRC Modula-3 contains the following:
   
     * A native code compiler: uses the GCC backend; on
       machines/operating systems that have self-describing stacks, an
       optimized exception handling mechanism is provided, on other
       architectures, setjmp/longjmp is used. A very fast integrated
       backend is available on some platforms (currently NT386 and Linux
       i386).
       The compilation system provides for minimal recompilation. Only
       those units that depend on the modified interface item will be
       recompiled.
     * m3build: tool that performs dependency analysis and builds the
       Modula-3 programs and libraries.
     * m3gdb: a Modula-3 aware version of GDB.
     * Several tools for performance and coverage analysis.
     * A large standard library (libm3) providing
          + A multithread, incremental, generational, conservative
            garbage collector
          + Text manipulation.
          + Generic Containers: Lists, Sequences, Tables, SortedLists,
            SortedTables
          + Atoms and Symbolic expressions (Lisp like lists)
          + An extensible stream IO system
          + Typesafe binary object transcription (persistent objects)
          + Operating system interfaces
          + Portable interfaces to the language runtime
       All standard libraries are thread-friendly. Modula-3 can readily
       link with existing C libraries; many libraries including X11R4 and
       various UNIX libraries are available as part of libm3.
     * Several other libraries for designing graphical user interfaces
       and distributed applications.
       
Why are there strange pragmas for Locking levels and other properties?

   The Trestle (ui library) interfaces contain Locking level pragmas. The
   base interfaces (libm3 library) contain SPEC pragmas. These are not
   processed by the compiler. Instead the Extended Static Checker,
   currently under development at DEC SRC, will report on problems
   detected based on the program content and the information specified in
   these pragmas [25][ESC]. The Extended Static Checker is not yet
   available, it may be some time in the future.
   
Design Issues

Why objects and interfaces?

   Allan Heydon on comp.lang.modula3, May 4th 1993:
   
   Modula-3 provides two separate mechanisms for data-hiding: one for
   hiding details about how interfaces are implemented, and the other for
   hiding details about how objects are implemented.
   
   The first data-hiding mechanism is realized by the distinction between
   interfaces and modules. Clients can only import interfaces, so the
   names declared in the modules implementing those interfaces are hidden
   from clients. Note that this mechanism has only two levels; a name is
   either declared in an interface, or it isn't. If a name is only
   declared in a module, it can't be used by a client.
   
   The second data-hiding mechanism is realized by opaque types and
   revelations. A Modula-3 interface may declare an object type to be
   opaque, in which case only a subset of the fields and methods of that
   object are revealed to clients importing the interface. Furthermore,
   the Modula-3 revelation mechanism allows a designer to reveal
   successively more fields and methods of an object in a series of
   interfaces. The fields and methods visible to a client then depends on
   which interfaces the client imports.
   
   The latter mechanism is quite flexible. As opposed to the
   interface/module data-hiding mechanism, opaque types allow you to
   define an arbitrary number of levels at which more and more
   information about the implementation of your object is revealed.
   
   See Sections 2.2.10, 2.4.6, and 2.4.7 of "Systems Programming with
   Modula-3" for more information about opaque types and about partial
   and complete revelations.
   
What is the purpose of BRANDED and REVEAL?

   Allan Heydon writes:
   
   These two keywords are necessary because of two quite different
   features of the language. REVEAL is necessary because Modula-3 has
   opaque types and partial revelations. BRANDED is necessary because the
   Modula-3 type system uses structural equivalence instead of name
   equivalence.
   
   In Modula-3, the concrete structure of a type can be hidden from
   clients in an interface. A common idiom is:
   
  INTERFACE I;

  TYPE
    T <: TPublic;
    TPublic = OBJECT
      (* fields *)
    METHODS
      (* methods *)
    END;

  END I.

   The line "T <: TPublic" introduces the type "I.T" as an opaque subtype
   of the type "I.TPublic". It does not reveal any of the other details
   of the concrete structure of "I.T" to clients. Hence, "I.T" is said to
   be an opaque type. Put another way, the structure of "I.T" is only
   partially revealed to clients.
   
   In addition, it is possible to reveal more of "I.T"'s structure in
   other interfaces, like this:
   
  INTERFACE IRep;

  IMPORT I;

  TYPE
    TPrivate = I.TPublic OBJECT
      (* more fields *)
    METHODS
      (* more methods *)
    END;

  REVEAL
    I.T <: TPrivate;

  END IRep.

   This interface declares a type "IRep.TPrivate" that is a subtype of
   "I.TPublic". It also asserts that "I.T" is also a subtype of
   "IRep.TPrivate". A client that imports only the interface "I" has
   access only to the fields and methods in "I.TPublic" when accessing an
   object of type "I.T", but a client that imports both "I" and "IRep"
   also has access to the fields and methods in "IRep.TPrivate" when
   accessing an object of type "I.T".
   
   The "REVEAL" statement in this module simply asserts a subtype
   relation. Unlike type declarations, revelations introduce no new
   names. Hence, we could not have used the "TYPE" keyword in this case
   because the type "I.T" has already been declared once (albeit
   opaquely) in interface "I".
   
   Every opaque type must have a complete revelation. A complete
   revelation has the form:
   
  REVEAL
    T = TConcrete;

   The revelation specifies that "TConcrete" is the concrete type for the
   opaque type "T".
   
   The Modula-3 type system uses structural equivalence instead of name
   equivalence. This means that two types are equal iff they have the
   same structure. One consequence of this rule is that two types you
   might intend to be distinct may actually be equal. This can have
   unintended effects on the run-time behavior of your program. For
   example, if both types that you expect to be distinct are actually
   structurally equivalent and the two types guard two arms of a TYPECASE
   statement, the arm for the second type will never be taken.

Section 1 of 2 - Prev - Next

Back to category Programming - Use Smart Search
Home - Smart Search - About the project - Feedback

© allanswers.org | Terms of use

LiveInternet