| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- On the Maintenance of Classic Modula-2 Compilers
- Benjamin Kowarsch, Modula-2 Software Foundation
- arXiv:1809.07080v1 [cs.PL] 19 Sep 2018
- September 2018 (arXiv.org preprint)
- Abstract
- The classic Modula-2 language was specified in [Wir78] by N.Wirth at ETH Zürich in
- 1978. The last revision [Wir88] was published in 1988. Many computer science books of that
- era used Modula-2 in programming examples. Many of these are still valuable resources in
- computer science education today. To compile and run the examples therein, it is essential
- to have compilers available that follow the classic Modula-2 language definition and run on
- modern computer hardware and operating systems. Although most Modula-2 compilers of
- that era have disappeared, a few have since been re-released under open source licenses.
- Whilst the original authors have long ceased work on these compilers, new maintainers have
- stepped in. This paper gives recommendations for maintenance on classic Modula-2 compil-
- ers while balancing the aim to modernise with the need to maintain the capability to compile
- programming examples in the literature with minimal effort. Nevertheless, the principles,
- methods and conclusions presented are adaptable to maintenance on other languages.
- 1Methodology
- 1.1Design Principles
- The following design principles strongly influenced the recommendations in this paper:
- 1.1.1
- Single Syntax Principle (SSP)
- There should be one and only one syntax form to express any given concept [Dij78].
- 1.1.2
- Literate Syntax Principle (LSP)
- Syntax should be chosen for readability and comprehensibility by a human reader [Knu84].
- 1.1.3
- Consistency of Syntax Principle (COSP)
- Syntax should be consistent. Analogous concepts should be expressed by analogous syntax.
- 1.1.4
- Principle of Least Astonishment (POLA)
- Of any number of possible syntax forms or semantics, the one likely to cause the least astonish-
- ment for a human reader should be chosen and the alternatives should be discarded [Geo87].
- 1.1.5
- Single Responsibility Principle (SRP)
- Units of decomposition, such as modules, classes, procedures and functions should have a single
- focus and purpose [Mar09].
- 1.1.6
- Principle of Information Hiding (POIH)
- Implementation specific details should always be hidden, public access should be denied [Par72].
- 1.1.7
- Safety Perimeter Principle (SPP)
- Facilities that undermine the safety otherwise safeguarded within the language should be segre-
- gated from other facilities [Wir88, ch.29]. Their use should require an explicit expression of intent
- by the author and be syntactically recognisable so as to alert the author, maintainer and reader
- of the possible implications. This applies and extends the principle of least privilege [Sal74].
- 1On the Maintenance of Classic Modula-2 Compilers
- 1.2
- 2
- Maintenance Objectives
- The primary objectives for the recommendations in this paper are:
- (1) to remove facilities that are harmful, outdated or violate any of [1.1]
- (2) to resolve ambiguities in [Wir88] and incompatibilities between implementations
- (3) to maintain the capability to compile programming examples in the literature with
- minimal effort
- 1.2.1
- Weighing Objectives by Impact
- The objectives given above may from case to case conflict with one another. Which objective
- should be given preference in the event of a conflict depends on the following factors:
- (1) the severity of the offending facility
- (2) the estimated frequency of use of the offending facility
- (3) the effort to update sources impacted by change or removal of the offending facility
- The greater the severity of an offending facility, the stronger is the case for change or removal;
- the lower the estimated frequency of use and the less the effort to update impacted sources, the
- stronger the case for change or removal. In the event that the estimated frequency of use is
- high and the effort to update impacted sources is significant, deprecation is recommended.
- 1.3
- Mitigation Methods
- Terms of mitigation methods used in this paper have well defined meanings:
- 1.3.1
- Warning
- A warning should be issued for each and every use of the offending facility.
- 1.3.2
- Change
- The offending facility should be replaced with a proposed alternative.
- 1.3.3
- Deprecation
- A compiler switch to enable and disable the offending facility should be provided and it should
- be disabled by default. When it is enabled, a deprecation warning should be isued for each and
- every use of the offending facility.
- 1.3.4
- Removal
- Support for the offending facility should be removed altogether.
- From an educational perspective, the availability of offending facilities promotes bad habits.
- Replacement or removal is therefore generally preferable to warning or deprecation.
- 1.3.5
- Transformation
- To be used in combination with any of change, deprecation or removal. A conversion program
- should be provided that transforms source code that uses offending facilities into semantically
- equivalent source code that complies with the recommendations given in this paper.
- 2Lexis
- 2.1Octal Literals
- Support for octal literals should be removed.
- Copyright c 2018 Benjamin Kowarsch – arXiv.org preprint for non-commercial useOn the Maintenance of Classic Modula-2 Compilers
- 2.1.1
- 3
- Rationale
- The use of octal numbers has long been outdated. Further, the B and C suffixes used to denote
- octal literals are also legal digits within hexadecimal literals, which is confusing to human readers
- of the source code as it violates POLA [1.1.4] and it unnecessarily complicates lexing.
- 2.1.2
- Substitution
- The built-in CHR() function can be used instead without penalty as it is evaluated at compile time
- for constant arguments. The function accepts decimal and hexadecimal arguments. Code that
- uses the CHR() function instead of octal literals can always be compiled on any classic Modula-2
- compiler, regardless of whether octal literals are recognised or not.
- 2.1.3
- Backwards Compatibility
- Preferably, transformation should be used to replace all occurences of octal literals in existing
- Modula-2 sources. Alternatively, octal literals could be deprecated instead.
- 2.2
- Synonym Symbols
- Support for synonym symbols <>, & and ˜ should be removed.
- 2.2.1
- Rationale
- The availability of alternative symbols violates SSP (1.1.1) and they are are notably absent
- from the grammar in [Wir88, pp.156-157].
- The inequality operator symbol # is preferable to its synonym <> because it resembles the
- mathematical inequality symbol 6= and as a single character symbol it simplifies lexing. Reserved
- words AND and NOT are preferable to their respective synonyms & and ˜ because of consistency:
- While there are synonyms for AND and NOT, there is none for OR. Although | could have been used
- to denote OR, it is already used to separate case labels and would have caused ambiguity.
- 2.2.2
- Substitution
- Symbol # can be used in place of <>, while AND can be used in place of & and NOT in place of ˜.
- 2.2.3
- Backwards Compatibility
- Preferably, transformation should be used to replace all occurences of synonym symbols in
- existing Modula-2 sources. Alternatively, synonym symbols could be deprecated instead.
- 2.3
- Non-Semantic Compiler Directives
- Whilst compiler directives are implementation defined, the delimiters of non-semantic compiler
- directives should not be. They should be denoted by an opening (*$ and a closing *) delimiter.
- 2.3.1
- Rationale
- Although [Wir88, p.18] mentions (* and *) as delimiters for both comments and directives, it
- does not specify their use in any normative manner. Some compiler implementors have taken
- this to mean that the delimiters are implementation defined. Several compilers still in use today
- do not follow the convention, for example the venerable MOCKA compiler [EV94].
- As a result, source code with compiler directives is often not portable across different im-
- plementations. This is unfortunate, because non-semantic directives can safely be ignored in
- the event that they are not supported. Even where an implementation issues warnings about
- unrecognised directives, to be able to identify a directive as such in the first place, a common
- delimiter convention needs to be followed across implementations.
- 2.3.2
- Backwards Compatibility
- Non-compliant directives within existing source code should be replaceable with minimal effort
- using regular expressions and a filter program such as sed or awk.
- Copyright c 2018 Benjamin Kowarsch – arXiv.org preprint for non-commercial useOn the Maintenance of Classic Modula-2 Compilers
- 2.4
- 4
- Semantic Compiler Directives
- Semantic compiler directives should not be denoted by the same delimiters used for non-semantic
- compiler directives.
- 2.4.1
- Rationale
- Whilst non-semantic compiler directives can safely be ignored, semantic compiler directives can-
- not. A semantic compiler directive that is not supported by an implementation must be reported
- as an error. Consequently, an implementation needs to be able to distinguish between semantic
- and non-semantic directives. In order to do so, different delimiters must be used.
- 2.4.2
- Substitution
- Some Modula-2 compilers have used a % prefix to denote compiler directives, in particular for
- conditional compilation, for example the MOCKA compiler [EV94]. We recommend to follow
- that convention to denote non-semantic compiler directives if any are provided. The % symbol is
- not otherwise used in the language.
- 2.4.3
- Backwards Compatibility
- Non-compliant directives within existing source code should be replaceable with minimal effort
- using regular expressions and a filter program such as sed or awk.
- 3Syntax
- 3.1Multi-Dimensional Arrays
- Inconsistent definition or declaration of multi-dimensional arrays should trigger warnings.
- 3.1.1
- Rationale
- [Wir88, p.138] specifies alternative syntax forms for multi-dimensional array type declaration:
- TYPE Matrix = ARRAY [0 .. Cols], [0 .. Rows] OF REAL;
- is an abbreviation of and thus equivalent to
- TYPE Matrix = ARRAY [0 .. Cols] OF ARRAY [0 .. Rows] OF REAL;
- The availability of alternative syntax forms violates SSP [1.1.1] and COSP [1.1.3]. The more
- dimensions an array type has, the more preferable the abbreviated form becomes. However, it is
- more effort to remove or deprecate the long form. The impact of removal or deprecation on
- existing sources with multi-dimensional arrays would likely be high. It is less effort and sufficient
- to modify an implementation to detect and warn about mixed use in any given compilation unit.
- 3.1.2
- Backwards Compatibility
- The proposed mitigation does not impact the compatibility of legacy sources.
- 3.2
- Local Modules
- Local Modules should be deprecated.
- 3.2.1
- Rationale
- If there is sufficient reason to delegate certain responsibilities of a library module to a local
- module, then there is also sufficient reason to delegate those responsibilities to a separate library
- module. There is no reason why a local module should be chosen over a separate library.
- Furthermore, a local module within a program or library module unnecessarily increases the
- line count of the module and thus reduces its readabililty and maintainability. It runs counter
- to the very rationale of decomposing source code into separate modules in the first place.
- Copyright c 2018 Benjamin Kowarsch – arXiv.org preprint for non-commercial useOn the Maintenance of Classic Modula-2 Compilers
- 5
- Finally, a test environment for testing a local module must necessarily be provided within
- the hosting module. This further increases clutter and poses the question whether to release the
- module with or without the embedded test environment. By contrast, a proper library module
- can be imported into any number of lexically independent test environments.
- 3.2.2
- Substitution
- Local modules should be removed from their enclosing module and provided as proper library
- modules with their own definition and implementation parts.
- 3.2.3
- Backwards Compatibility
- Backwards compatibility can be provided via compiler switch.
- 3.2.4
- Private-Use Aspect
- The private-use aspect of local modules is lost when they are removed from their host modules
- and converted into library modules. However, this aspect is useful when the local module’s API is
- considered unstable and subject to frequent changes. A satisfactory solution can be implemented
- easily by introducing a non-semantic compiler directive that specifies a library’s intended client
- modules and causes the compiler to issue warnings whenever such a library is imported by a
- module other than its designated client modules. An example is given below:
- DEFINITION MODULE PrivateLib; (*$CLIENTS=FooLib, BarLib, BazLib*)
- (∗ ATTENTION !!! This module is intended for private use only.
- ∗ Its API is subject to frequent change without prior notice.
- ∗ The compiler will issue a warning when it is imported from
- ∗ any other than the designated client modules. ∗)
- ···
- END PrivateLib.
- 3.3
- Unary Minus
- Unary minus should only be permitted before a factor.
- simpleExpression :=
- ( ’+’ )? term ( addOp term )* | ’-’ factor
- ;
- instead of
- simpleExpression :=
- ( ’+’ | ’-’ )? term ( addOp term )*
- ;
- 3.3.1
- Rationale
- [Wir88] does not state the scope of the unary minus operator other than through the grammar.
- An expression of the form
- − a ∗ b + c
- could be interpreted mathematically correct
- (−a) ∗ b + c
- or grammatically correct
- −(a ∗ b + c)
- The former interpretation conforms to mathematical convention. The latter can be deduced
- from the grammar in [Wir88, pp.156-157] and is intended to be the correct interpretation1 .
- 1 The author obtained clarification on the precedence of unary minus from Prof. Wirth by email.
- Copyright c 2018 Benjamin Kowarsch – arXiv.org preprint for non-commercial useOn the Maintenance of Classic Modula-2 Compilers
- 6
- However, this violates POLA [1.1.4] and some implementations therefore follow the mathemat-
- ically correct interpretation, for example the ACK compiler [Jac85] and the MOCKA compiler
- [EV94]. Requiring a factor after a unary minus forces the use of parentheses whenever there is
- more than one factor to follow which makes programmer intent explicit.
- 3.3.2
- Backwards Compatibility
- Unary minus is an infrequently used operation. When it is used, it is usually in a form that
- is compliant with the syntax proposed in this paper. In the unlikely event that it is not in
- a compliant form, the source code is ambiguous and needed to be fixed anyway. It may well
- have been written for and tested with a compiler that uses a different interpretation than the
- compiler now used to compile the sources. The proposed mitigation will thereby help identify
- any non-compliant occurrences which can then be corrected with minimal effort.
- 4Pervasives
- 4.1Conversion
- Pervasive function VAL() should be changed to cover all numeric conversions and numeric conver-
- sions only. Pervasive functions FLOAT() and TRUNC() should then be deprecated. Any additional
- non-standard conversion functions such as INT(), CARD() and LFLOAT() should be removed.
- 4.1.1
- Rationale
- [Wir88, p.150] specifies pevasive conversion function VAL() which covers all possible use cases for
- safe type conversion between whole number types. There is no reason why VAL() could not also
- cover all possible use cases for conversions between whole and real number types. By contrast,
- CHR() and ORD() are not conversion functions2 and they should not be duplicated by VAL().
- Duplication violates SSP [1.1.1].
- Furthermore, function FLOAT() is confusingly named since the type it converts to is REAL and
- there is no type FLOAT. [Wir88] does not specify how real number types are to be implemented.
- They need not be implemented as floating point numbers but could be implemented as binary
- coded decimals, for instance. The naming of FLOAT() is thus misleading and violates COSP [1.1.3]
- and POLA [1.1.4].
- Finally, function TRUNC() violates SRP [1.1.5] as it represents both a conversion function and
- the mathematical function trunc(x). Its name is misleading as it does not suggest conversion,
- violating POLA [1.1.4]. Conversion should be the responsibility of function VAL() and truncation
- the responsibility of a math function trunc() to be provided in a library such as MathLib and
- return the same type as its argument, it should not perform any type conversion.
- 4.1.2
- Substitution
- Once function VAL() has been extended to provide type conversion between whole and real
- number types, any invocation of functions FLOAT() and TRUNC() within existing source code may
- be safely replaced with an invocation of VAL().
- 4.1.3
- Backwards Compatibility
- Backwards compatibility can be provided via compiler switch.
- 4.1.4
- Implementation
- It should be noted that function VAL() is not generally implemented as a single function, nor
- should it be. Instead, it is usually and preferably implemented as a built-in macro, resolved
- at compile time to a function internal to the compiler that is specific to the source and target
- types of its arguments, since the types are known at compile time. VAL() thereby simplifies the
- user interface without incurring the penalty of increasing the complexity of its implementation.
- The specific conversion functions need to be implemented within the compiler anyway, but they
- should not be individually exposed in the user interface.
- 2 CHR() performs a lookup while ORD() returns a property.
- Copyright c 2018 Benjamin Kowarsch – arXiv.org preprint for non-commercial useOn the Maintenance of Classic Modula-2 Compilers
- 5Semantics
- 5.1Exported Variables
- 7
- Variables defined in definition parts should be exported read-only.
- 5.1.1
- Rationale
- Allowing a client module to write to imported variables violates POIH [1.1.6]. And indeed,
- [Wir88, p.88] explicitly states that “imported variables should be treated as ‘read-only’ objects”.
- 5.1.2
- Substitution
- A setter procedure can be defined and exported by the same module if needed.
- DEFINITION MODULE Foo;
- VAR bar : Bar; (∗ read−only ∗)
- PROCEDURE SetBar ( value : Bar );
- END Foo.
- 5.1.3
- Backwards Compatibility
- Considering that Wirth explicitly stated to treat imported variables as “read-only” objects, noone
- should have written any code that treats them as mutable objects. Unfortunately, there will be
- code written by careless programmers who didn’t follow his advice. The cautious maintainer may
- therefore consider providing a compiler switch to enable and disable write-access to imported
- variables, which should then be disabled by default.
- 5.2
- Pointer Variables
- All pointer variables should be initialised to NIL and deallocation should reset them to NIL.
- 5.2.1
- Rationale
- The two primary paradigms of Modula-2 are (a) program decomposition through data encapsu-
- lation and information hiding, and (b) reliability through type safety. Opaque pointer types are
- the primary instrument through which the former is achieved. The ability to test whether an
- opaque pointer type has been allocated or deallocated is central to achieving the latter.
- 5.2.2
- Backwards Compatibility
- The proposed mitigation does not impact the compatibility of legacy sources.
- 5.3
- Unsafe Facilities
- Any facility that bypasses the type safety provided by the language should be disabled by default.
- 5.3.1
- Unsafe Facilities provided by SYSTEM
- [Wir88, p.121] defines pseudo-module SYSTEM as a container for unsafe facilities. The facilities
- provided therein are only enabled by import. This is desirable as it sensitises programmers to
- the fact that the facilities are unsafe and thereby discourages their use.
- Copyright c 2018 Benjamin Kowarsch – arXiv.org preprint for non-commercial useOn the Maintenance of Classic Modula-2 Compilers
- 5.3.2
- 8
- Unsafe Facilities NOT provided by SYSTEM
- Unfortunately, not all unsafe facilities are provided through pseudo-module SYSTEM. Two unsafe
- facilities are provided in the language core and are enabled by default without import:
- (1) Unsafe type transfers [Wir88, p.119], also known as type casts
- (2) Records with variant parts [Wir88, p.71, p.138], also known as variant records
- This is a violation of SPP [1.1.7] and given its implications for program safety it is unacceptable.
- In order to mitigate this situation, support for type casts and variant records should be disabled
- by default and require enabling by compiler switch.
- 5.3.3
- Ideal World Scenario
- In an ideal world, the type cast syntax would be replaced with a CAST() function provided by
- SYSTEM as in ISO Modula-2 [JTC96], and variant records with type safe extensible records as
- in Oberon [Wir90]. However, this would constitute a substantial language revision and as such
- go beyond the scope of the maintenance aspect of this paper. It would also run counter to the
- objective to allow the compilation of programming examples in the literature with minimal effort.
- 6Language Extensions
- 6.1Availability
- All language extensions should be disabled by default and only enabled by compiler switch.
- 6.1.1
- Rationale
- Disabling language extensions by default aids and promotes writing of portable source code.
- 6.2
- Smallest Addressable Unit
- Under no circumstances should any implementation change the definition of type SYSTEM.WORD.
- However, an implementation targeting an architecture where the smallest addressable storage
- unit is eight bits wide should provide an alias type BYTE in module SYSTEM as follows:
- TYPE BYTE = WORD;
- 6.2.1
- Rationale
- [Wir88, p.153] specifies SYSTEM.WORD as the smallest addressable unit3 . Whilst the report permits
- provision of additional facilities in SYSTEM, it does not permit alterations of SYSTEM facilities
- specified in the report.
- It would thus be permissible to provide an additional type SYSTEM.MACHINEWORD that represents
- a machine word larger than the smallest addressable unit, but it is not permissible to change
- SYSTEM.WORD to represent a machine word that is not the smallest addressable unit.
- 6.3
- Foreign Identifiers
- An implementation that provides a means to interface to foreign APIs, should also allow the
- use of foreign identifiers. Such an identifier may contain one or more dollar $ and/or lowline
- _ characters. The use of foreign identifiers for other purposes should be discouraged. Support
- should be disabled by default and enabled by compiler switch when needed.
- To avoid any collission with name mangled symbols generated by the Modula-2 compiler, no
- consecutive and no trailing dollar signs should be permitted; no leading, no consecutive and no
- trailing lowlines should be permitted. Further, dollar signs and lowlines should not be permitted
- within module identifiers.
- 3 When the first report on Modula-2 was written it was still common to call the smallest addressable storage
- unit a word. Since then the terminology has changed and it has become common to use the term byte instead.
- Copyright c 2018 Benjamin Kowarsch – arXiv.org preprint for non-commercial useOn the Maintenance of Classic Modula-2 Compilers
- 6.3.1
- 9
- Rationale
- Operating system APIs and other foreign APIs often include variables and procedures with
- identifiers that include dollar $ (predominantly on the VMS operating system) and lowline _
- (predominantly on Unix systems and C APIs in general).
- 6.4
- Foreign Definition Modules
- An implementation that provides a means to interface to foreign APIs, should use a non-semantic
- compiler directive to mark a definition module as a foreign definition module.
- 6.4.1
- Rationale
- [Wir88] does not mention foreign definition modules. As a result, implementors have invented
- their own syntax to mark a definition module as foreign, and this varies between implementations.
- However, the corresponding implementation could in principle be done in Modula-2. The
- marking of a definition module as foreign does not alter its semantics. Consequently, any such
- marking constitutes de-facto a non-semantic compiler directive.
- 6.4.2
- Proposed Syntax
- The directive should be placed after the module header, its proposed syntax is as follows:
- ffiPragma :=
- ’(*$’ ffiPragmaKey ’=’ ’"’ foreignAPI ’"’ ’*)’
- ;
- ffiPragmaKey :=
- ’F’ | /* if implementation uses single-letter keys */
- ’FFI’ /* if implementation uses multi-letter keys */
- ;
- foreignAPI :=
- ’ASM’ | ’C’ | ’Fortran’ | ’Pascal’ | ...
- ;
- 7Miscellaneous
- 7.1Filename Suffixes
- Modula-2 implementations should only recognise input files with suffixes def and mod.
- 7.1.1
- Rationale
- Neither [Wir78] nor [Wir88] mention filename suffixes for Modula-2 source files. A de-facto
- standard has been established by the compilers distributed by ETH Zürich: Suffix def is used
- for definition module files and suffix mod for implementation and program module files.
- The absence of any mentioning of filename suffixes in [Wir78] and [Wir88] has been taken by
- some implementors as an invitation to define their own non-standard filename suffixes.
- The use of non-standard suffixes leads to unnecessary effort when compiling sources across dif-
- ferent implementations. Moreover, it has led to conflicts with other notations in and inconsistent
- support for Modula-2 by various text editors and source code renderers.
- 7.2
- Pre-Revision Compilers
- An implementation that follows the original monograph [Wir78] or the second edition [Wir83]
- should be updated to follow the third [Wir85] or, preferably the fourth [Wir88] edition.
- 7.2.1
- Rationale
- Prior to [Wir85] a definition module was required to have an export list. This was unnecessary
- duplication since the purpose of a definition module is to export all its contents.
- Copyright c 2018 Benjamin Kowarsch – arXiv.org preprint for non-commercial useOn the Maintenance of Classic Modula-2 Compilers
- 10
- Definitions
- API
- Application programming interface.
- compiler directive
- A directive within the source to instruct a language processor how to process the input.
- ETH
- Eidgenössisch Technische Hochschule – Swiss Federal Institute of Technology.
- foreign API
- An API implemented in a language other than Modula-2.
- foreign definition module
- A definition module that specifies an interface to a foreign API .
- foreign identifier
- An identifier of a foreign API.
- non-semantic compiler directive
- A compiler directive that does not alter the semantics of the source code.
- offending facility
- A language facility that is (a) outdated, harmful or bad habit forming in general,
- or (b) violates any of the design principles in section 1.1 in particular.
- semantic compiler directive
- A compiler directive that alters the semantics of the source code.
- References
- [Dij78]Edsger W. Dijkstra. On the GREEN Language submitted to the DoD.
- E.W.Dijkstra Archive, originally circulated privately, 1978.
- [EV94]H. Emmelmann and J. Vollmer. GMD Modula-2 System MOCKA User Manual, 1994.
- [Geo87] James Geoffrey. The Tao of Programming. InfoBooks, 1987.
- [Jac85] Ceriel J.H. Jacobs. The ACK Modula-2 Compiler, 1985.
- [JTC96] ISO/IEC JTC1/SC22/WG13. Information Technology – Programming Languages –
- Part 1: Modula-2, Base Language. International Standard 10514-1, ISO/IEC, 1996.
- [Knu84] Donald E. Knuth. Literate Programming. The Computer Journal, 27(2), 1984.
- [Mar09] Robert C. Martin. Clean Code: A Handbook of Agile Software Craftsmanship.
- Prentice Hall, 2009.
- [Par72] David L. Parnas. On the Criteria to be Used in Decomposing Systems into Modules.
- Comunications of the ACM, 15(12), 1972.
- [Sal74]
- Jerome H. Saltzer. The Protection of Information in Computer Systems.
- Comunications of the ACM, 17(7), 1974.
- [Wir78] Niklaus Wirth. Modula-2. Technical report, ETH Zürich, 1978.
- [Wir83] Niklaus Wirth. Programming in Modula-2. Springer, Heidelberg, 2nd edition, 1983.
- [Wir85] Niklaus Wirth. Programming in Modula-2. Springer, Heidelberg, 3rd edition, 1985.
- [Wir88] Niklaus Wirth. Programming in Modula-2. Springer, Heidelberg, 4th edition, 1988.
- [Wir90] Niklaus Wirth. Oberon Language Report. Technical report, ETH Zürich, 1990.
- Copyright c 2018 Benjamin Kowarsch – arXiv.org preprint for non-commercial use
|