mjj@acornrc.UUCP (Mick Jordan) (10/13/88)
Modula-3 Announcement The following (long) message contains the Acknowledgments, Overview and References from the Modula-3 Report (hence the copyright notice). It should provide adequate information on what Modula-3 is and how it came about. Copies of the report are available from either DEC Systems Research Center, 130 Lytton Ave, Palo Alto California 93401 or Olivetti Research Center, 2882 Sand Hill Road, Menlo Park California 94025. E-mail requests are acceptable to src-reports@decwrl or librarian@orc.olivetti.com. Olivetti Research Center is currently doing an exploratory implementation of the language. This comprises a compiler front-end, AST-based interpreter and debugger, and a code-generator which generates C. This is implemented in a mixture of Modula-2+, C and IDL and runs on a Sun-3. We expect to finish this phase in a month or so. There are no plans for distribution at present (it would be strictly for evaluation and on an as-is basis) but we are interested in measuring the level of interest. --Mick Jordan (mjj@orc.olivetti.com, mjj@acornrc.uucp) ----------------------------cut here---------------------------------------- Copyright 1988 Digital Equipment Corporation, Ing. C. Olivetti and C., SpA. This work may not be copied or reproduced in whole or in part for any commercial purpose. Permission to photocopy in whole or in part without payment of fee is granted for nonprofit educational and research purposes provided that all such copies include the following: a notice that such copying is by permission of the Systems Research Center of Digital Equipment Corporation in Palo Alto, California and the Olivetti Research Center of Ing. C. Olivetti and C., SpA in Menlo Park, California; an acknowledgment of the authors and individual contributors to the work; and all applicable portions of the copyright notice. All rights reserved. The right to implement or use the Modula-3 language is unrestricted. Acknowledgments Modula-3 was designed by Luca Cardelli, Jim Donahue, Mick Jordan, Bill Kalsow, and Greg Nelson, as a joint project by the Digital Systems Research Center and the Olivetti Research Center. Paul Rovner made many contributions as a founding member of the design committee, but cannot be held responsible for the final product. Our starting point was Modula-2+, which was designed by Paul Rovner, Roy Levin, John Wick, Andrew Birrell, Butler Lampson, and Garret Swart. We benefited from the ruthlessly complete description of Modula-2+ provided in Mary-Claire van Leunen's Modula-2+ User's Manual. Niklaus Wirth made valuable suggestions and inspired us with the courage to throw things out. He also designed Modula-2, the starting point of our starting point. We thank the following people for their helpful feedback: Bob Ayers, Andrew Black, David Chase, Dan Craft, Hans Eberle, John Ellis, Jim Horning, Mike Kupfer, Butler Lampson, Lyle Ramshaw, Eric Roberts, Ed Satterthwaite, Jorge Stolfi, and Garret Swart. This report was written by Lucille Glassman and Greg Nelson, under the watchful supervision of the whole committee. 1. Overview Modula-3 descends from Mesa [8], Modula-2 [12], Cedar [5], and Modula-2+ [9, 10]. It also resembles its cousins Object Pascal [11], Oberon [13], and Euclid [6]. Since these languages already have more raw material than fits comfortably into a readable fifty-page language definition, which we were determined to produce, we didn't need to be inventive. On the contrary, we had to leave many good ideas out. One of our main goals was to provide safety from unchecked runtime errors---forbidden operations that invalidate an invariant of the runtime system and lead to an unpredictable computation. A classic unchecked runtime error is to free a record to which active references remain. To avoid this danger, Modula-3 follows Cedar, Modula-2+, and Oberon by automatically freeing unreachable records. To allow both garbage collection and low-level systems programming, Modula-3 provides both traced and untraced references. Another well-known unchecked runtime error is to assign to the tag of a variant record in a way that subverts the type system. Distinguishing subversive assignments from benign assignments in the language definition is error-prone and arbitrary. The objects and classes first introduced by Simula [2] and adopted in Oberon and Object Pascal are more general than variant records, and they are safe, so we have discarded variant records and adopted objects. In Modula-3, all objects are references. Generally the lowest levels of a system cannot be programmed with complete safety. Neither the compiler nor the runtime system can check the validity of a bus address for an IO controller, nor can they limit the ensuing havoc if it is invalid. This presents the language designer with a dilemma. If he holds out for safety, then low level code will have to be programmed in another language. But if he adopts unsafe features, then his safety guarantee becomes void everywhere. In this area we have followed the lead of Cedar and Modula-2+ by adopting a small number of unsafe features that are allowed only in modules that are explicitly labeled unsafe. In a safe module, the compiler guarantees the absence of unchecked runtime errors; in an unsafe module, it is the programmer's responsibility to avoid them. From Mesa and Modula-2 we adopted modules, which are separate program units with explicit interfaces, and abstract (or opaque) types, which hide the representation of a type from client modules that use the type. In Modula-3, as in some implementations of Modula-2, variables with opaque types must be references. If the hidden representation changes but the interface remains the same, client modules will not need to be reprogrammed, or even recompiled. From Modula-2+ we adopted exceptions and threads. An exception exits all procedure call levels between the point at which it is "raised" and the point at which it is "handled". Exceptions are a good way to handle any runtime error that is not necessarily fatal. The alternative is to use error return codes, but this has the drawback that programmers don't consistently test for them. In the Unix/C world, the frequency with which programs omit tests for error returns has become something of a standing joke. Instead of breaking at an error, too many programs continue on their unpredictable way. Raising an exception is a better approach, since it will stop the computation unless there is an explicit handler for it. A thread is a "light-weight process". The threads interface provides a simplified version of the Mesa extensions to Hoare's monitors [1, 3, 7]. Waiting, signaling, and locking a monitor have Hoare's semantics, but the requirement that a monitored data structure be an entire module is relaxed: it can be an individual record or any set of variables instead. The programmer is responsible for acquiring the appropriate lock before accessing the monitored data. 1.1. Common notions A Modula-3 program specifies a computation that acts on a sequence of digital components called locations. A variable is a set of locations that represents a mathematical value according to a convention determined by the variable's type. If a value can be represented by some variable of type T, then we say that the value is a member of T and T contains the value. Assignability and type compatibility are defined in terms of a single syntactically-specified subtype relation with the property that if T is a subtype of U, then every member T is a member of U. An identifier is a symbol declared as a name for a variable, type, procedure, etc. The region of the program over which a declaration applies is called the scope of the declaration. Scopes can be nested. The meaning of an identifier is determined by the smallest enclosing scope in which the identifier is declared. An expression specifies a computation that produces a value or variable. Every expression has a statically-determined type, which contains every value that can be produced by the expression. In particular, literals have types; for example, the type of "6" is INTEGER (not [6..6]). Expressions whose values can be determined statically are called constant expressions. Expressions that produce variables are called designators. The type of a designator is the type of the variable it produces. A designator is writable if it can be used in contexts that require mutable variables and readonly otherwise. Every expression has a unique type, but a value can be a member of many types. For example, 6 is a member of both [0 .. 9] and INTEGER. Thus the phrase "type of x" means "type of the expression x", while "x is a member of T" means "the value of x is a member of T". But there is one case in which one of the types that contain a value is distinguished: when a traced reference or object is allocated it is tagged with a type, which we call the allocated type of the reference value. The type denoted by a type name never changes at runtime, and is usually determined at compile time. But a type name can be opaque in a scope, which means that it denotes a reference type with an unknown referent type. A type name that is not opaque is concrete. A concrete type is determined at compile time (except for the referent types of opaque types that occur within it). Types are distinct until proven identical. For example, variables with types T and U would not be assignable in a scope where T and U are both opaque, but would be assignable in any scope where T and U are identified with the same concrete type. A type is empty if it contains no values. For example, [1..0] is an empty type. Empty types can be used to build non-empty types (for example, SET OF [1..0], which is not empty because it contains the empty set). It is illegal to declare a variable of an empty type. A static error is an error that the implementation must detect before program execution. Violations of the language definition are static errors unless they are explicitly classified as runtime errors. A checked runtime error is an error that the implementation must detect and report at runtime. The method for reporting such errors is implementation-dependent. (If the implementation maps them into exceptions, then a program could handle these exceptions and continue.) An unchecked runtime error is an error that is not guaranteed to be detected, and can cause the subsequent behavior of the computation to be arbitrary. Unchecked runtime errors can occur only in unsafe modules. 1.2. Required interfaces An implementation of Modula-3 must include implementations of the interfaces Text, Thread, Word, and Fmt. The first three provide elementary operations on text strings, concurrent threads of control, and "words", which represent bit vectors or unsigned integers. The Fmt interface provides procedures for formatting numbers and other data as text. The full name of an entity is the name of its interface followed by a dot and its name in that interface. The principal type in an interface is usually named T. Thus Text.T is the type for text strings, Thread.T is the type for threads, and Word.T is the type for words. References [1] A.D. Birrell, J.V. Guttag, J.J. Horning, R. Levin. Synchronization Primitives for a Multiprocessor: A Formal Specification. Operating Systems Review 21(5), November 1987. Also published as SRC Research Report 20, August 1987. [2] Graham M. Birtwistle, Ole-Johan Dahl, Bjorn Myhrhaug, and Kristen Nygaard. Simula Begin. Auerbach, Philadelphia PA, 1973. [3] C.A.R. Hoare. Monitors: An Operating System Structuring Concept. Communications of the ACM 17(10), October 1974. [4] Daniel Jackson and Jim Horning. The Modula-2+ Text Interface. Unpublished manuscript available from Jim Horning at SRC. [5] Butler W. Lampson. A Description of the Cedar Language. Technical Report CSL-83-15, Xerox Palo Alto Research Center, December 1983. [6] Butler W. Lampson, James J. Horning, Ralph L. London, James G. Mitchell, and Gerald J. Popek. Report on the Programming Language Euclid. Technical Report CSL-81-12, Xerox Palo Alto Research Center, October 1981. [7] Butler W. Lampson and David D. Redell. Experience with Processes and Monitors in Mesa. Communications of the ACM 23(2), February 1980. [8] James G. Mitchell, William Maybury, and Richard Sweet. Mesa Language Manual. Technical Report CSL-78-1, Xerox Palo Alto Research Center, February 1978. [9] Paul Rovner, Roy Levin, and John Wick. On Extending Modula-2 For Building Large, Integrated Systems. Technical Report 3, Digital Systems Research Center, January 1985. [10] Paul Rovner. Extending Modula-2 to Build Large, Integrated Systems. IEEE Software 3(6), November 1986. [11] Larry Tesler, Apple Computers. Object Pascal Report. Structured Language World 9(3), 1985. [12] Niklaus Wirth. Programming in Modula-2. Springer-Verlag, Third Edition, 1985. [13] N. Wirth. From Modula to Oberon and The Programming Language Oberon. Technical Report 82, Institut fur Informatik, ETH Zurich, September 1987.