Hubbry Logo
MAD (programming language)MAD (programming language)Main
Open search
MAD (programming language)
Community hub
MAD (programming language)
logo
7 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
MAD (programming language)
MAD (programming language)
from Wikipedia

MAD
Paradigmprocedural, imperative, structured
FamilyALGOL
Designed byBernard Galler, Bruce Arden, Robert M. Graham
DeveloperUniversity of Michigan
First appeared1959; 66 years ago (1959)
Typing disciplineStatic, strong
ScopeLexical
OSUMES, MTS, CTSS, others
Major implementations
IBM 704, 7090, S/360, S/370; UNIVAC 1108; Philco 210-211
Dialects
MAD, MAD/I, GOM
Influenced by
IAL, ALGOL 58

MAD (Michigan Algorithm Decoder) is a programming language and compiler for the IBM 704 and later the IBM 709, IBM 7090, IBM 7040, UNIVAC 1107, UNIVAC 1108, Philco 210-211, and eventually IBM System/370 mainframe computers. Developed in 1959 at the University of Michigan by Bernard Galler, Bruce Arden and Robert M. Graham, MAD is a variant of the ALGOL language. It was widely used to teach programming at colleges and universities during the 1960s and played a minor role in the development of Compatible Time-Sharing System (CTSS), Multics, and the Michigan Terminal System computer operating systems.[1] The original version of the chatbot ELIZA was written in MAD-SLIP.[2]

The archives at the Bentley Historical Library of the University of Michigan contain reference materials on the development of MAD and MAD/I, including three linear feet of printouts with hand-written notations and original printed manuals.[3][4][5][6]

MAD, MAD/I, and GOM

[edit]

Three MAD compilers exist:

  1. Original MAD, the compiler developed in 1959 at the University of Michigan for the IBM 704 and later the IBM 709 and IBM 7090 mainframe computers running the University of Michigan Executive System (UMES) and the Compatible Time-Sharing System (CTSS) operating systems.[7][8] In the mid-1960s MAD was ported at the University of Maryland to the UNIVAC 1108.[9] Versions of MAD were also available for the Philco 210-211 and UNIVAC 1107.[9]
  2. MAD/I, an "extended" version of MAD for the IBM System/360 series of computers running under the Michigan Terminal System (MTS). Work on the new compiler started in 1965 as part of the ARPA sponsored CONCOMP project at the University of Michigan. As work progressed it gradually became clear that MAD/I was a new language independent of the original 7090 version of MAD.[10]
  3. GOM (Good Old MAD), a reimplementation of the original 7090 MAD for the IBM System/370 series of mainframe computers running the Michigan Terminal System (MTS). GOM was created in the early 1980s by Don Boettner at the University of Michigan Computing Center.[11][12]

History

[edit]

While MAD was motivated by ALGOL 58, it does not resemble ALGOL 58 in any significant way.[13][14]

Programs written in MAD included MAIL,[15] RUNOFF,[16] one of the first text processing systems, and several other utilities all under Compatible Time-Sharing System (CTSS).[17] Work was done on a design for a MAD compiler for Multics, but it was never implemented.[18]

The following is an interesting quote from An Interview with Brian Kernighan[19] when he was asked "What hooked you on programming?":

I think that the most fun I had programming was a summer job at Project MAC at MIT in the summer of 1966, where I worked on a program that created a job tape for the brand new GE 645 in the earliest days of Multics. I was writing in MAD, which was much easier and more pleasant than the FORTRAN and COBOL that I had written earlier, and I was using CTSS, the first time-sharing system, which was infinitely easier and more pleasant than punch cards.

MAD was quite fast compared to some of the other compilers of its day. Because a number of people were interested in using the FORTRAN language and yet wanted to obtain the speed of the MAD compiler, a system called MADTRAN (written in MAD) was developed. MADTRAN was simply a translator from FORTRAN to MAD, which then produced machine code. MADTRAN was distributed through SHARE.[13]

MAD/I has a syntactic structure similar to ALGOL 60 together with important features from the original MAD and from PL/I.[10] MAD/I was designed as an extensible language. It was available for use under MTS and provided many new ideas which made their way into other languages, but MAD/I compilations were slow and MAD/I never extended itself into widespread use when compared to the original 7090 MAD.[12]

GOM is essentially the 7090 MAD language modified and extended for the 360/370 architecture with some judicious tailoring to better fit current programming practices and problems.[12] The MTS Message System was written in GOM.

MAD, Mad magazine, and Alfred E. Neuman

[edit]
Line printer output following a MAD compiler error on an IBM 704 computer at the University of Michigan, c. 1960

In a pre-release version of the original MAD, as a reference to MAD's namesake, Mad magazine, when a program contained too many compile time errors the compiler would print a full-page picture of Alfred E. Neuman using ASCII art. The caption read, "See this man about your program--He might want to publish it. He never worries--but from the looks of your program, you should."[9] This feature was not included in the final official version.[20] However, it was included in the production version for the IBM 7040.

And Bernie Galler remembers:

By the time we designed the language that we thought would be worth doing and for which we could do a compiler, we couldn't call it Algol anymore; it really was different. That's when we adopted the name MAD, for the Michigan Algorithm Decoder. We had some funny interaction with the Mad magazine people, when we asked for permission to use the name MAD. In a very funny letter, they told us that they would take us to court and everything else, but ended the threat with a P.S. at the bottom - "Sure, go ahead." Unfortunately, that letter is lost.[21]

"Hello, world" example

[edit]

The "hello, world" example program prints the string "Hello, world" to a terminal or screen display.

PRINT FORMAT HELLOW
VECTOR VALUES HELLOW=$13h0Hello, world*$
END OF PROGRAM

The first character of the line is treated as logical carriage control, in this example the character "0" which causes a double-spaced line to be printed.

Alternatively, contractions can be used, and the compiler will expand them in the listing:

P'T HELLOW
V'S HELLOW=$13h0Hello, world*$
E'M

Language elements

[edit]

MAD and GOM, but not MAD/I, are composed of the following elements:[8][12][13]

Input format

[edit]

MAD programs are a series of statements written on punched cards, generally one statement per card, although a statement can be continued to multiple cards. Columns 1-10 contains an optional statement label, comments or remarks are flagged using the letter "R" in column 11, and columns 73-80 are unused and could contain a sequence identifier. Spaces are not significant anywhere other than within character constants. For GOM input is free form with no sequence field and lines may be up to 255 characters long; lines that start with an asterisk (*) are comments; and lines that start with a plus-sign (+) are continuation lines.

Names

[edit]

Variable names, function names, and statement labels have the same form, a letter followed by zero to five letters or digits. Function names end with a period. All names can be subscripted (the name followed by parentheses, with multiple subscripts separated by commas). For GOM names may be up to 24 characters long and may include the underscore (_) character.

Few keywords in the language are reserved words since most are longer than six letters or are surrounded by periods. There is a standard set of abbreviations which can be used to replace the longer words. These consist of the first and last letters of the keywords with an apostrophe between them, such as W'R for WHENEVER and D'N for DIMENSION.

Data types

[edit]

MAD uses the term "mode" for its data types. Five basic modes are supported:

  • Integer written with or without a scale factor (1, +1, -1, 1K10, 1K) or as octal constants (to 7777777777777K);
  • Floating Point written with or without an exponent (0., 1.5, -0.05, +100.4, -4., .05E-2, -.05E2, 5E02, 5.E2);
  • Boolean (1B for true and 0B for false);
  • Statement Label, and
  • Function Name written as a name followed by a period (SQRT.).

The mode of a constant can be redefined by adding the character M followed by a single digit at the end of the constant, where 0 indicates floating point, 1 integer, 2 boolean, 3 function name, and 4 statement label.

For GOM six additional modes are added: CHARACTER, SHORT INTEGER, BYTE INTEGER, LONG INTEGER, POINTER, and DYNAMIC RECORD.

Alphabetic or character constants are stored as integers and written using the dollar sign as a delimiter ($ABCDEF$) with double dollar-signs used to enter a true dollar sign ($$$.56$ is 56 cents). Strings longer than six characters are represented using arrays.

Arrays and matrices

[edit]
  • There is no limit on the number of dimensions.
  • Negative and zero as well as floating-point subscripts are allowed.
  • Matrices are storied in consecutive memory locations in the order determined by varying the rightmost subscript first.
  • Matrices may be referenced using a subscript for each dimension, NAME(s1,s2,s3), or using a single subscript, NAME(s1).
  • Input-output lists, VECTOR VALUES statements, and some subroutines allow the use of block notation, which has the form A,...,B or A...B, which is a reference to the entire region from A to B. inclusive. In terms of a vector, A(1)...A(N) would be A(1), A(2), A(3), ..., A(N).
  • There are facilities that allow changing dimensions at run-time; permitting the programmer to vary the location of the initial element in an array within the overall block which has been set aside for the array; and allowing an arbitrary storage mapping to be specified.
List of operators, statements, and functions

Operators

[edit]

Declaration statements

[edit]

Variables may be implicitly or explicitly declared. By default all implicitly declared variables are assumed to be floating point. The NORMAL MODE IS statement may be used to change this default.

Executable statements

[edit]

Input and output statements

[edit]

Functions

[edit]

Function names end with a period. Internal and external functions are supported. Internal functions are compiled as part of the program in which they are used and share declarations and variables with the main program. External functions are compiled separately and do not share declarations and variables. A one statement definition of internal functions is permitted. Recursive functions are permitted, although the function must do some of the required saving and restoring work itself.

Operator definition and redefinition

[edit]

One of the most interesting features in MAD is the ability to extend the language by redefining existing operators, defining new operators, or defining new data types (modes). The definitions are made using MAD declaration statements and assembly language mnemonics included following the declaration up to the END pseudo-instruction that implement the operation.

  • DEFINE BINARY OPERATOR defined-op, PRECEDENCE rank existing-op MODE STRUCTURE mode-options
  • DEFINE UNARY OPERATOR defined-op, PRECEDENCE rank existing-op MODE STRUCTURE mode-options
  • MODE STRUCTURE mode-no = mode-no existing-op mode-no
  • MODE STRUCTURE mode-no = mode-no existing-op mode-no SAME SEQUENCE AS mode-no existing-op mode-no

where:

  • rank is one of SAME AS, LOWER THAN, or HIGHER THAN; and
  • mode-options are the options that appear on the MODE STRUCTURE statement.

Three pre-defined packages of definitions (MATRIX, DOUBLE PRECISION, and COMPLEX) are available for inclusion in MAD source programs using the INCLUDE statement.

  • INCLUDE package

See also

[edit]

Notes

[edit]

References

[edit]
[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
MAD (Michigan Algorithm Decoder) is an early and system designed for expressing algorithms in a structured, algebraic form and translating them into machine instructions for execution on mainframe computers. Developed in 1959 at the Computing Center by Bernard Galler, Bruce Arden, and Robert M. Graham, it served as a variant of the International Algebraic Language (IAL), which itself influenced the later standard. Initially targeted at the computer, MAD was subsequently adapted for a range of mainframes including the , 7090, 7040, 1107 and 1108, 2000 series, and even later architectures. The language emphasized scientific and numerical computation, supporting data types such as integers, floating-point numbers, Booleans, alphabetic strings, and octal constants, along with control structures like conditional statements, iteration loops, and subroutine definitions. Its input-output facilities allowed formatted data handling, making it suitable for both academic research and tasks. MAD gained prominence in educational settings during the 1960s, where it was widely adopted for teaching introductory programming concepts at universities across the United States due to its readability and similarity to mathematical notation. Beyond education, it played a supporting role in the development of influential early operating systems, including contributions to the Compatible Time-Sharing System (CTSS), Multics, and the Michigan Terminal System (MTS). Variants such as MAD/I (for IBM 360/370) and GOM (a dialect for MTS) extended its usability into the 1970s and beyond, though it gradually declined with the rise of more portable languages like FORTRAN and Pascal.

Overview and Variants

Core MAD Language

The Michigan Algorithm Decoder (MAD) is a procedural, imperative, and language developed in 1959 at the Computing Center as a variant of , designed specifically for expressing algorithms in a clear and precise manner suitable for early digital computers. It functions as both a language and a that translates high-level algorithmic descriptions into equivalent instructions, emphasizing and ease of use for scientific and computational tasks. Key designers of the original MAD included Bernard Galler, Bruce Arden, and Robert M. Graham, who collaborated to create its foundational structure. The language primarily targeted mainframes such as the 704, 709, and 7090, leveraging their capabilities for numerical computations in academic and research environments. MAD's core goals centered on facilitating programming education by providing an intuitive syntax akin to for describing algorithms, while enabling direct translation to to support efficient scientific computing on limited hardware. Among its initial features, MAD introduced extensibility through user-defined operators and data types, allowing programmers to customize the language for specific needs, and it supported multi-dimensional arrays with flexible indexing, including up to seven dimensions, dynamic sizing, and even negative or zero subscripts for advanced data handling. Later adaptations, such as MAD/I and GOM, built upon this baseline for newer systems.

MAD/I

MAD/I is a variant of the MAD programming language, conceived in 1965 at the University of Michigan Computing Center as an adaptation for the IBM System/360 architecture and sponsored by the Advanced Research Projects Agency (ARPA) under the CONCOMP project. This development aimed to extend MAD's capabilities to the new third-generation computers, with the compiler becoming operational by late 1968. The original MAD, designed for earlier IBM 704/709 systems, provided the foundational concepts but required significant updates for System/360 compatibility. Key differences from the core MAD include a syntactic structure more closely aligned with , incorporating block structures and elements from while retaining algebraic features from MAD. MAD/I introduced expanded definitional facilities, new data types such as dynamic storage, and extensibility through user-defined macros and statement structures, making it less compatible with the 7090-era MAD but better suited for modern applications. These changes improved portability across models, particularly the Model 67 with support, though the language remained somewhat machine-dependent due to System/360-specific features like data set handling. Implementation details include the MAD/I compiler, which produces object modules compatible with the (MTS), a timesharing extension for System/360. A translation tool, MADTRAN, facilitated converting programs to MAD/I equivalents, yielding performance gains through MAD/I's efficient compilation and execution on System/360 hardware. The language's definitional facilities further supported custom translators for integrating code from other languages. In usage contexts, MAD/I integrated with operating environments like MTS on System/360 Model 67, enabling conversational and modes that extended beyond . It found application in larger-scale scientific computing, including algebraic manipulations, symbol processing, and graphical data structures, benefiting from System/360's increased capacity for complex simulations and research programs.

GOM

GOM, also known as Good Old MAD, represents an early 1980s reimplementation and extension of the original MAD language for the architecture under the (MTS). Developed by Don Boettner at the Computing Center, it adapted the 7090-era MAD dialect to support machine-dependent programming and operating system components on the 360/370 family. This variant built briefly on structural influences from earlier adaptations like MAD/I, enhancing portability and expressiveness for mainframe environments. Key improvements included free-form input supporting lines up to 255 characters, allowing greater flexibility in code formatting compared to fixed-column predecessors. Identifier handling was expanded to permit names up to 24 characters, including underscores after an initial letter, facilitating more descriptive variable and function naming. Additional types were introduced, such as CHARACTER for string manipulation and SHORT for compact numeric storage, alongside variants like BYTE and LONG to align with System/370's addressing capabilities. Exclusive to GOM were specialized operators for advanced operations: pointer operators including .LOC. for location addressing and .IND. for indirect referencing, as well as bit-level operators like .SETBIT. and .RESETBIT. for direct manipulation of . These features enabled low-level programming tasks integral to MTS development. The definitive reference is the GOM Manual (June 1989), authored by Donald Boettner and archived in the University of Michigan's Deep Blue repository, which details its full syntax, extensions, and implementation guidelines.

History

Development Origins

The development of MAD (Michigan Algorithm Decoder) originated at the Computing Center, where it was conceived between 1958 and 1959 as a response to the need for a more practical algorithmic programming language. The project was led by a team of researchers including Bruce W. Arden, Bernard A. Galler, and Robert M. Graham, who divided responsibilities across the compiler's components: Graham handled the initial parser in the front end, Arden developed the back end for code generation, and Galler contributed to the overall language design and subsequent parts of the . The first implementation of MAD was completed on the in 1959, with the system becoming fully operational by early 1960. This timeline reflected the rapid evolution from design to deployment, driven by the team's dissatisfaction with the theoretical complexities of emerging standards. Primarily influenced by —the International Algebraic Language proposed in 1958—MAD adopted its block-structured syntax and expression-oriented approach but diverged substantially to prioritize ease of implementation on IBM hardware, avoiding features deemed too abstract or inefficient for practical computing environments. As Bernard Galler later recalled, "We decided to do an compiler... by the time we designed the language... we said we couldn’t call it ALGOL any more; it really was different." MAD was envisioned as one of the earliest languages, incorporating mechanisms that allowed users to define custom operators and notations, setting it apart from rigid contemporaries like . Its core purpose centered on translating high-level algorithms directly into , with a strong emphasis on supporting educational instruction in programming concepts and facilitating scientific computations at academic institutions. This focus made MAD particularly valuable for teaching and research, where flexibility and readability were essential for non-expert users exploring numerical and algorithmic problems.

Implementations and Adoption

MAD was initially implemented for the and 7090 computers in 1960, serving as a for algorithmic descriptions on these early mainframes. Ports followed to other systems, including the 1108 in the mid-1960s at the University of Maryland, and versions for the 210-211 (part of the Philco 2000 series) and 1107. An extended variant, MAD/I, was developed for the architecture around 1965, providing enhanced features like definitional facilities for user-defined operators and data types, and was integrated into the (MTS). By the 1980s, the GOM implementation extended MAD compatibility to the , adapting the original 7090 syntax for the newer architecture while maintaining procedural elements. The language played a role in developing key early operating systems, including portions of the (CTSS) at MIT, where it was used for system programming due to its block structure and fast compilation. It contributed minor elements to design efforts, though ultimately prevailed, and supported core components of MTS at the . Notable applications included the , implemented in using the MAD-SLIP library for list processing on CTSS, enabling pattern-matching conversations. Utilities like the program for CTSS, written by Tom Van Vleck in , and RUNOFF, a text formatting tool by J. H. Saltzer for thesis preparation, were also coded in MAD, influencing later tools like . Adoption peaked in the 1960s and 1970s, with MAD widely taught in university curricula for its accessibility in scientific computing, gaining broad use at institutions like the , MIT, and the University of Maryland, as well as industry sites such as . To facilitate migration of existing code, MADTRAN, a developed at MIT, translated II programs to MAD for faster execution and easier maintenance. By the late 1970s, MAD's prominence declined as FORTRAN, PL/I, and emerging languages like C offered broader support and portability on evolving hardware, leading to its gradual obsolescence outside niche academic environments. Archival materials, including development records and manuals, are preserved at the University of Michigan's Bentley Historical Library.

Cultural References

Mad Magazine Connection

The acronym MAD, standing for Michigan Algorithm Decoder, was selected by its developers at the in 1959 as a backronym for their ALGOL-inspired language, independent of the contemporaneous humor magazine Mad. To ensure legal clearance, the team sought permission from the magazine's publishers, receiving a humorous response letter that initially threatened litigation but concluded with a postscript granting approval. This exchange highlighted the serendipitous naming overlap, which the developers embraced by incorporating playful references to the magazine in the language's ecosystem. A notable cultural tie-in appeared in the early MAD compiler's error handling, where severe compilation failures triggered output of an ASCII art depiction of , the iconic Mad mascot, accompanied by the phrase "What, Me Worry?" printed on line printers like those connected to the 704. This whimsical diagnostic, an early example of programmer humor in , was featured in developmental versions around 1960. These elements infused levity into the often frustrating process of programming, particularly in settings where MAD was a staple for teaching algorithmic concepts during the . Despite the fun nods, there was no direct influence from the magazine on the language's technical design, which remained focused on computational efficiency and accessibility.

Example Programs

Hello World Implementation

A canonical "Hello, world" program in the core MAD language demonstrates basic output using format declarations and vector presetting for data. This simple program declares a format for printing and presets a vector containing the , including control, before ending execution.

PRINT FORMAT HELLOW VECTOR VALUES HELLOW=$13H0Hello, world*$ END OF PROGRAM

PRINT FORMAT HELLOW VECTOR VALUES HELLOW=$13H0Hello, world*$ END OF PROGRAM

The PRINT FORMAT statement specifies the output format named HELLOW, which is then populated via the VECTOR VALUES declaration. This assigns a Hollerith to the vector, using Hollerith notation (13H to indicate 13 characters, including the carriage control '0' and the 12-character "Hello, world"), delimited by $ and terminated by *. Upon execution, the program outputs the "Hello, world" to the printer or terminal with double spacing, as interpreted by the system's I/O handler. This example executes on original MAD implementations for IBM 704, 709, and 7090 systems, typically compiled from punched card input and producing direct textual output without further processing.

Syntax Fundamentals

Input Format

The input format for the MAD programming language was designed around the punched card technology prevalent in early computing environments, enforcing a rigid columnar structure to facilitate mechanical reading and processing by compilers on systems like the and 709. Each statement typically occupied one 80-column punched card, with columns 1 through 10 reserved for optional statement labels, column 11 used to indicate continuations (via digits 1 through 9 for subsequent cards of a multi-card statement, up to a maximum of 10 cards) or remarks (marked with an "R" for comments ignored by the compiler), columns 12 through 72 dedicated to the statement text itself, and columns 73 through 80 for optional sequence numbers or identification not processed by the computer. This fixed format ensured compatibility with card readers, where blanks were generally ignored except within specific contexts like Hollerith strings, and statements could not split fields across cards without proper continuation markers. Within this columnar layout, MAD statements followed a semi-free-form approach in columns 12-72, allowing flexible spacing for readability while keywords—such as READ, PRINT, or —were conventionally entered in uppercase letters, as shown in examples. Labels, when present, adhered to the rules for identifiers but were positioned anywhere within columns 1-10 without affecting the statement's execution. The compiler's error diagnostics were directly tied to these card positions, referencing specific columns in output messages to aid , with remarks in column 11 associating explanatory notes to the preceding statement for contextual reference during compilation. Subsequent implementations, such as GOM (Good Old MAD), evolved the input format away from punched cards toward a more flexible, free-form structure suitable for terminal-based entry on and later systems, permitting lines up to 255 characters long without a sequence field, where statements begin after the first non-blank character if column 1 is empty, and continuations are marked by a "+" in column 1 of the following line. In GOM, comments are initiated by an asterisk (*) in column 1, extending to the end of the line, while the core MAD format retained its card-based columnar rigidity in earlier ports and . This shift in GOM enhanced usability for interactive environments but preserved with MAD's foundational syntax rules.

Identifiers and Names

In the MAD programming language, identifiers for variables, functions, and statement labels consist of one to six alphanumeric characters, with the first character required to be a letter from A to Z. This structure ensures compatibility with the punched-card input format prevalent on early systems like the 7090, where names were limited to fit within fixed column constraints. Digits may follow the initial letter, but the total length cannot exceed six characters to maintain parseability by the compiler. Function names in MAD follow the same alphanumeric rules but must terminate with a period to distinguish them from variables, such as . or COS.(X). Statement labels adhere to identical naming conventions and are placed in specific card columns (1-10) for transfer statements like GO TO. Certain keywords are reserved and cannot be repurposed as identifiers, including PRINT for output operations and VECTOR for array declarations, as they are integral to the language's syntax and would cause compilation errors if redefined. The GOM implementation of MAD, designed for and later systems, extends these rules to support longer identifiers of up to 24 characters, incorporating underscores as valid components alongside letters and digits, while still requiring the first character to be a letter. This enhancement improves for larger programs without breaking . Reserved words remain prohibited for use as identifiers in GOM, preserving keywords like PRINT and VECTOR to avoid conflicts with core language features. Regarding scope, identifiers in MAD and GOM are local by default to the block or function in which they are declared, limiting accessibility to that unless explicitly designated as global via PROGRAM COMMON statements. This scoping mechanism influences how names are resolved during compilation, ensuring no unintended overlaps, and ties directly into declaration statements where identifiers are assigned modes like or FLOATING POINT.

Data Structures

Data Types

The MAD programming language supports a set of built-in data types designed for algorithmic and scientific computing on early mainframe systems, primarily the , 709, and 7090. These types include for , FLOATING POINT for real numbers, for logical values, STATEMENT LABEL for , and FUNCTION NAME for subroutine references. Variables are declared using mode statements such as or FLOATING POINT, which specify the type and ensure type-appropriate operations; undeclared variables default to FLOATING POINT mode. INTEGER represents whole numbers without fractional parts, suitable for indices, counters, and efficient integer arithmetic. Constants are digits up to 10 in length, optionally with an prefix (e.g., 127K2) or scale factor (e.g., 1K10), ranging from -2^35 to 2^35 - 1. Declaration example: INTEGER J, N. Operations include integer division, which truncates toward zero (e.g., 16 / 20 yields 0). FLOATING POINT handles real numbers with points or (e.g., 1.5 or .05E-2), supporting exponents from -38 to +38 for scientific computations. It is the default mode, declared as FLOATING POINT X, and used for most arithmetic unless specified otherwise. BOOLEAN encapsulates logical true (1B) or false (0B) values, employed in conditional expressions with operators like .AND. and .OR. Declared via BOOLEAN P, Q, it supports relational comparisons and is convertible to for indexing. STATEMENT identifies jump targets in control statements like TRANSFER TO, using alphanumeric identifiers (1-6 characters, starting with a letter) placed in the label field (e.g., IN:). Declared as STATEMENT [LABEL](/page/Label) ALPHA. FUNCTION NAME denotes user-defined or built-in functions, suffixed with a period when invoked (e.g., SIN.(X)), and declared as FUNCTION NAME FACTO for custom subroutines. Alphabetic constants, treated as a form of CHARACTER data, use dollar-delimited strings up to 6 characters (e.g., ABCDABCD), stored as padded integer codes for output formatting. The GOM dialect, an extension of MAD for the , introduces additional types including CHARACTER for strings and for reduced-precision integers. CHARACTER stores case-sensitive text as 1-byte elements, declared as CHARACTER NAME(3), with constants delimited by or"(e.g.,or " (e.g.,ABB or "ABC"), supporting substring access like NAME(0...3). uses 2 bytes for values from -32768 to +32767, declared as SHORT INTEGER VAR or with qualifiers like 1@SI for constants, and automatically promotes to full in expressions for compatibility. Type conversions in MAD occur implicitly during expression evaluation: INTEGER values promote to FLOATING POINT in mixed arithmetic, while FLOATING POINT to INTEGER truncates the fractional part. BOOLEAN converts to INTEGER (1 or 0) for use in formats or indices. Explicit conversions use functions or qualifiers like .AS. INTEGER for casting without arithmetic adjustment. These mechanisms ensure flexibility while preserving precision where declared.

Arrays and Matrices

MAD supports multi-dimensional through declarations in mode statements that specify the and , allowing for flexible storage of collections of elements. are declared by including in parentheses after the array name in the mode declaration, such as INTEGER A(10,20), which allocates space for a two-dimensional with 10 rows and 20 columns of elements. The statement can be used separately to specify or adjust sizes, e.g., DIMENSION A(10,20). Dimensions can include ranges with lower and upper bounds using double dots (..), supporting negative indices; for example, FLOATING B(-5..5, 0..10) creates an 11-by-11 floating-point indexed from -5 to 5 in the first and 0 to 10 in the second. For one-dimensional arrays (vectors), the lower bound defaults to 0 if not specified (e.g., A(10) indexes 0 to 10); for multi-dimensional arrays, it defaults to 1. The total storage is computed as the product of the dimension sizes, with each element occupying space based on the type (e.g., one word for integers, two for floating-point). Indexing in MAD provides significant flexibility, permitting subscripts that are , negative numbers, zero, or even floating-point values truncated to . Elements are accessed using parentheses with comma-separated subscripts, as in A(I,J) where I and J are expressions evaluating to valid indices within the declared bounds; out-of-bounds access may lead to or program halt depending on the implementation. For arrays of dimension three or greater, subscripts must be mode. Additionally, block notation enables range specifications for operations like or , such as A(3..5, 10) to refer to a subarray or C(1)..C(10) for a sequence of one-dimensional elements, which is particularly useful for efficient data handling without explicit loops. Multi-dimensional arrays are stored in a linear fashion, with the last subscript varying fastest (row-major order), computed via a linear index formula like r = n*(i-1) + (j-1) + base for a 2D array, allowing equivalent access with a single subscript if needed. For matrix-specific operations, MAD includes a MATRIX package accessed via the INCLUDE statement, which provides functions for linear algebra tasks such as transposition, inversion, and multiplication on declared arrays treated as matrices. For instance, after INCLUDE MATRIX, a statement like D = TRANS.(A, N) computes the transpose of an N-by-N matrix A into D, assuming A is suitably dimensioned. This package supports symmetric and sparse matrices through specialized subscription functions like SYMM for symmetric storage, reducing memory usage by storing only upper or lower triangles. Storage for arrays and matrices is dynamically allocated at based on the declaration dimensions, with the total size determining the block of reserved in the program's data area. The SETDIM statement allows runtime modification of dimensions for certain arrays, such as SETDIM(A, M, N) to resize an array A to M rows and N columns, though this requires careful management to avoid overwriting other data. Elements within arrays can reference base data types like or FLOATING, ensuring type consistency across the structure.

Operators and Expressions

Arithmetic and Relational Operators

The MAD programming language supports a set of predefined arithmetic operators for performing numerical computations within expressions. These include (+), (-), (*), division (/), and (.P.). The operator computes the sum of two operands, as in X + Y. yields the difference, for example X - Y. performs the product X * Y, while division X / Y produces a result that is truncated toward zero if both operands are integers; otherwise, it yields a floating-point quotient. raises the left operand to the power of the right, denoted as X .P. Y. Additionally, unary negation (-X) and the function (.ABS.(X)) are available for arithmetic manipulation. Relational operators in MAD facilitate comparisons between operands, producing Boolean results for use in conditional expressions. These operators are equality (.E.), inequality (.NE.), less than (.L.), greater than (.G.), less than or equal to (.LE.), and greater than or equal to (.GE.). For instance, X .E. Y evaluates to true if X equals Y, while X .G. Y checks if X is greater than Y. These operators apply to numeric types and follow standard comparison semantics, with relational expressions yielding values that can be combined in conditions. Arithmetic and relational operators are integral to MAD expressions, which combine variables, constants, and function calls according to operator precedence and associativity rules. Expressions support implicit where necessary, such as promoting integers to floating-point during mixed operations. A representative arithmetic expression is A = B * C + 5, which assigns the value of (B * C) + 5 to A. For relational usage, an example is IF X .LE. 0 THEN ..., testing if X is less than or equal to zero. Parentheses can override precedence to enforce desired evaluation order, such as (A + B) * C. Operator precedence in MAD determines the order of expressions, with higher precedence operators binding tighter. The .ABS. has the highest precedence among arithmetic functions (level 14, right-associative), followed by .P. (level 11, right-associative), then multiplicative operators * and / (level 9, left-associative), additive operators + and - (binary, level 8, left-associative), and unary (-, level 10, right-associative). Relational operators have the lowest precedence among these (level 7, left-associative). The hierarchy for core arithmetic operators is summarized below:
Precedence LevelOperatorsAssociativityDescription
14 (highest).ABS.Right
11.P.Right
10unary -Right
9*, /Left, division
8 (lowest for arithmetic)+, - (binary)Left,
Relational operators, evaluated after arithmetic, form the basis for Boolean expressions without internal precedence distinctions among themselves.

Boolean and Bit Operators

MAD supports boolean operators for performing logical operations on boolean values, which are represented as 1B for true and 0B for false. The primary boolean operators are .AND. for logical conjunction, .OR. for logical disjunction, and .NOT. for logical negation. These operators take boolean operands and produce a boolean result. Additional operators include .EXOR. for exclusive or (true if operands differ) and .EQV. for equivalence (true if operands are the same). Boolean expressions are evaluated from right to left, with applied to chains of .AND. and .OR.: in a conjunction, evaluation stops if any is 0B; in a disjunction, it stops if any is 1B. Relational operators (such as .G. for greater than) produce results, allowing seamless integration into expressions, such as (X .G. 3 .AND. Y .LE. 2) .OR. (GAMMA .L. [EPSILON](/page/Epsilon)). The truth tables for the core boolean operators are as follows:
Operand 1Operand 2.AND..OR..EXOR..EQV.
0B0B0B0B0B1B
0B1B0B1B1B0B
1B0B0B1B1B0B
1B1B1B1B0B1B
For unary .NOT., it inverts the operand: .NOT. 0B yields 1B, and .NOT. 1B yields 0B. Bitwise operators in MAD enable manipulation of integer bit patterns, applicable to integer modes. These include .A. for bitwise AND, .V. for bitwise OR, .EV. for bitwise , and .N. for bitwise (one's complement). MAD also provides .LS. for left shift and .RS. for right shift by a non-negative amount. In the GOM , additional operators .SETBIT. and .RESETBIT. allow setting or clearing specific bits (e.g., ABC .SETBIT. 24 sets the 24th bit of ABC to 1). Bitwise operations follow the same right-to-left evaluation as expressions but without short-circuiting, producing an result. For example, if I = 17 (binary ...00010001) and J = 9 (binary ...00001001), then I .A. J yields 1 (binary ...00000001), I .V. J yields 25 (binary ...00011001), I .EV. J yields 24 (binary ...00011000), and .N. I performs bitwise inversion across the full word (36 bits on IBM 7090), resulting in a large negative value in one's complement representation. These operators are useful for low-level in MAD and GOM programs. Boolean expressions, including those incorporating relational results, are commonly used in control structures such as IF statements for conditional execution.

Control and Execution

Declaration Statements

Declaration statements in the MAD programming language, particularly in its MAD/I variant, are used to define variables, arrays, labels, and functions, specifying their types, scopes, and storage attributes before they can be used in a program. These statements ensure that identifiers are properly allocated in the symbol table at compile time, preventing runtime ambiguities and enabling type checking. The primary form is the DECLARE statement, which allows explicit assignment of modes and qualifiers to one or more identifiers. The syntax for a basic variable declaration is DECLARE identifier mode, where mode specifies the , such as for whole numbers or FLOATING for real numbers. For example, DECLARE X FLOATING POINT declares a variable X as a floating-point number, defaulting to short precision unless specified otherwise (e.g., FLOATING LONG). Multiple identifiers can be declared together, as in DECLARE A, B [INTEGER](/page/Integer). An alternative "inverted" syntax places the mode first, followed by the identifier list, such as [INTEGER](/page/Integer) A, B, which is equivalent to the explicit DECLARE form and provides a more concise notation for simple cases. Array declarations extend this by including bounds, using DECLARE identifier FIXED [ARRAY](/page/Array) (bounds) mode, for instance DECLARE ARR FIXED [ARRAY](/page/Array) (1..10) [INTEGER](/page/Integer) to create a fixed-size integer array with indices from 1 to 10. Varying arrays, which allow runtime dimension changes, follow a similar syntax but with VARYING ARRAY, though their implementation was limited in early versions. Labels and functions are declared using specialized modes like TRANSFER POINT for statement labels or for callable functions. A label declaration might appear as DECLARE LBL TRANSFER POINT, allowing LBL to be used as a goto target, while functions are declared as DECLARE FUNC [ENTRY POINT](/page/Entry_point) mode, specifying the return type if applicable, such as DECLARE FACT [ENTRY POINT](/page/Entry_point) INTEGER. These declarations can include additional attributes like storage class (e.g., STATIC for fixed memory allocation or BASED for dynamic addressing). Scope is primarily block-level, meaning declarations are visible only within the enclosing block (delimited by structures like BLOCK or PROCEDURE), but qualifiers such as GLOBAL or EXTERNAL extend visibility across blocks or programs, enabling shared access in multi-module setups. For example, DECLARE VAR GLOBAL INTEGER makes VAR accessible throughout the program. Undeclared identifiers trigger compile-time errors, as the requires all variables and functions to be defined with a mode and storage class before use; failure to do so results in no symbol table entry, leading to diagnostics like "undefined identifier" and potential program rejection. Defaults may apply in some cases (e.g., undeclared variables assuming FLOATING SHORT mode), but explicit declarations are mandatory for correctness and to avoid incomplete type information. This strict enforcement supports robust code verification during compilation.

Executable Statements

Executable statements in the MAD programming language form the core of program execution, enabling assignments, conditional branching, , and unstructured jumps. These statements are processed sequentially unless altered by control mechanisms, with expressions evaluated left-to-right and supporting implicit type conversions during assignments, such as from to floating-point. The assignment statement assigns the value of an expression to a variable, using the syntax variable = expression. For example, Y = 1 assigns the value 1 to the floating-point variable Y, performing conversion. Expressions in assignments may include arithmetic operations and are evaluated without side effects unless involving function calls, though MAD emphasizes deterministic evaluation to avoid unintended behaviors. Conditional execution is handled primarily through the WHENEVER statement, which executes an associated statement if a evaluates to true. The simple form is WHENEVER boolean_expression, statement, such as WHENEVER X .LE. 0, TRANSFER TO END, which jumps to a label if X is less than or equal to zero. For multi-way branching, compound conditionals use WHENEVER B1, S1 OR WHENEVER B2, S2 ... END OF CONDITIONAL, executing the first true branch and skipping others; an example is WHENEVER X .LE. 0, Y = 0 OR WHENEVER X .GE. 3, Y = 1 END OF CONDITIONAL. These structures promote readable while allowing ELSE-like behavior via an OTHERWISE clause in extended forms. Iteration is achieved using the THROUGH statement combined with FOR, defining a loop scope from the THROUGH to a labeled endpoint. The syntax is THROUGH label, FOR variable = start, increment, boolean_condition, repeating the enclosed statements until the condition holds; for instance, THROUGH BACK, FOR J = 1, 1, J .G. N iterates J from 1 to N in steps of 1, executing until J > N, then continuing at the BACK . This integrates loop control with statement labeling, supporting nested iterations without explicit DO keywords. Unstructured control transfer is provided by TRANSFER TO label, enabling jumps to any labeled statement for flexibility in early algorithmic coding, though MAD documentation encourages structured alternatives like WHENEVER and THROUGH to minimize reliance on GOTOs. Labels are defined by placing them before statements, such as SUMX: Z = A + B. To group multiple statements into a compound unit, MAD uses BEGIN-END blocks, which delimit scopes for conditionals, loops, or sequences, supporting lexical scoping and as in influences. An example is BEGIN X = 1; Y = X + 2 END, treating the enclosed assignments as a single executable unit. This facilitates modular execution without unstructured jumps, aligning with MAD's emphasis on algorithmic clarity.

Input Output and Functions

Input and Output Statements

In the MAD programming language, output operations are primarily handled through the PRINT statement, which directs data to printers or other output devices according to predefined formats. The basic syntax is PRINT FORMAT J, A, where J is the name of a format vector and A is a list of variables or expressions to be printed. For instance, PRINT RESULTS A, X, EPS outputs the values of variables A, X, and EPS using the format specified in RESULTS. Formats themselves are defined using vector declarations enclosed in dollar-sign delimiters, such as VECTOR VALUES RESULT = $9H(C MATRIX//1H0,8F13.4)*$, which specifies a layout including Hollerith constants for labels and floating-point fields. Input operations utilize the READ statement, which retrieves data from input sources like punched cards or files into specified variables. The syntax mirrors output with READ FORMAT J, A, reading values into list A based on format J; a simplified form READ DATA processes cards containing variable-value pairs until an end marker like /- is encountered. For example, READ FORMAT $3F10.4*$ A, B, C inputs three floating-point numbers with 10-character fields and 4 decimal places each from sequential cards, scanning left-to-right. This supports from card decks or tape files, with the handling device-specific details. Format specifications in MAD consist of a sequence of field descriptors, each indicating , width, and precision, terminated by an within the delimiters. Common descriptors include I for s (e.g., I2 for a 2-column field), F for fixed-point decimals (e.g., F10.3 for 10 columns with 3 decimals), E for (e.g., E22.9), K for constants, and C for characters. Hollerith notation embeds fixed strings, such as 6HBETA = for a 6-character followed by an equal sign, while S skips columns (e.g., S16 for 16 spaces). field lengths are supported via modifiers like B for base specification, as in 16BI12 for a 12-digit , allowing precise control over non-decimal outputs. Additional features include scale factors with E, right-justification with R, and zero-filling with Z. The GOM variant of MAD, a reimplementation for and 370 architectures, enhances input and output with improved string handling and more flexible format specifications. While retaining core PRINT and READ syntax, GOM introduces refined notation for field lengths to better accommodate varying data sizes and extends string processing for embedded Hollerith fields, reducing parsing overhead in large-scale scientific applications. These changes, detailed in the GOM manual, facilitate porting legacy MAD code while optimizing for modern hardware I/O channels.

Function Definitions

In the MAD programming language, user-defined functions are created to encapsulate reusable computations, supporting both internal and external definitions to facilitate . Internal functions are defined within the main program body and share the program's variable scope unless specified otherwise, while external functions are defined in separate compilation units for independent and linkage. The syntax for defining an internal function begins with INTERNAL FUNCTION followed by the function name (1-6 characters ending in a period), a parameter list in parentheses, and either a single expression assignment or a block of statements. For a single-statement definition, the form is INTERNAL FUNCTION name.(param1, param2, ...) = expression;, where the expression's value implicitly serves as the return value. For multi-statement definitions, the body follows after the parameter list, enclosed implicitly by subsequent statements until the end of the function, with an explicit return via FUNCTION RETURN expression;. An example of a single-statement internal function is INTERNAL FUNCTION SUMSQ.(X, Y, Z) = X*X + Y*Y + Z*Z - T*T;, which computes the sum of squares adjusted by a global variable T. External functions use EXTERNAL FUNCTION name.(param1, param2, ...) followed by declarations (e.g., INTEGER J, N) and a sequence of executable statements, terminated by END OF FUNCTION. A representative external function for finding the maximum in an array is EXTERNAL FUNCTION MAX.(N, A) INTEGER J, N Z = A(0) THROUGH BACK, FOR J = 1, 1, J .G. N BACK WHENEVER Z .L. A(J), Z = A(J) FUNCTION RETURN Z END OF FUNCTION;. Parameters in MAD functions are specified as dummy variables in the parameter list and are typed through mode declarations such as INTEGER, FLOATING POINT, BOOLEAN, or SWITCH preceding the variable names, with floating-point as the default mode if undeclared. Arguments are passed to these dummies during invocation, where scalars are passed by value (copying the argument's value) and arrays by reference (allowing in-place modifications), ensuring type compatibility between actual arguments and dummies without runtime checks by the compiler. For instance, in the MAX function, the array A is passed by reference, enabling updates to its elements if needed within the function body. Functions support recursion, with temporary storage managed via SAVE DATA and RESTORE DATA statements to preserve state across calls. Functions are invoked by placing the name followed by actual arguments in parentheses within an expression, such as result = MAX.(6, [Q](/page/Q));, where the returned value replaces the call and can be assigned to a variable or used in further computations. For procedures (void functions), invocation uses EXECUTE name.(args); as a standalone statement. The return value's mode must align with the function's implicit or declared mode, explicitly provided via FUNCTION RETURN expression; at the desired exit point, or implicitly via the last expression in single-statement forms; an ERROR RETURN variant handles exceptions by transferring control to a specified label. Invocation integrates seamlessly into executable statements, enhancing without altering the main program's flow. MAD provides a limited set of built-in functions, such as COS., SIN., and ELOG. for trigonometric and logarithmic operations, which follow the same invocation syntax as user-defined functions but cannot be redefined directly. These built-ins establish foundational mathematical capabilities, with extensibility achieved through user-defined alternatives where needed.

Extensibility Features

Operator Definition and Redefinition

MAD's extensibility allows programmers to define new operators or redefine existing ones for specific data modes, enabling the creation of domain-specific notations that integrate seamlessly into expressions. This feature, introduced in early versions of the , permits users to extend the operator set beyond built-ins, such as arithmetic operators, by specifying custom behaviors through assembly-like instruction sequences. The primary mechanism for operator definition involves the DEFINE statement, which declares unary or binary operators with user-specified precedence relative to existing operators. For a binary operator, the syntax is DEFINE BINARY OPERATOR <operator>, PRECEDENCE <SAME AS | LOWER THAN | HIGHER THAN> <existing operator>, where <operator> is typically an extended symbol enclosed in periods (e.g., .EV.), limited to six alphabetic characters. Precedence is assigned hierarchically; for instance, built-in operators like (+) have lower precedence than (*), allowing new operators to be positioned accordingly using relational comparisons. Once defined, the operator's implementation is specified per data mode using MODE STRUCTURE <mode> = <left mode> <operator> <right mode>, followed by a defining sequence of machine instructions written in mnemonic form without location fields. These sequences utilize pseudo-instructions like JMP for , OUT to terminate interpretation, and temporary storage locations such as T (single cell) or DT (double cell). Operators must be defined in before their first use. Redefinition of built-in operators is supported for specific modes without altering their global precedence, allowing customized behaviors for user-defined data types. For example, an existing operator like .P. () can be redefined for mode 6 (a custom floating-point mode) by providing a new instruction sequence, while retaining the original for other modes. This is achieved by reissuing the MODE STRUCTURE statement for the target mode, optionally referencing prior sequences with SAME SEQUENCE AS to reuse code. Such redefinitions enable overriding built-in semantics in domain-specific contexts, like optimizing operations for specialized numeric types. A representative example is defining a new operator .EV. for bitwise exclusive-or on integers (mode 1), which integrates into arithmetic expressions:

DEFINE BINARY OPERATOR .EV., PRECEDENCE SAME AS .V. MODE [STRUCTURE](/page/Structure) 1 = 1 .EV. 1 CLA A1 /* Clear accumulator, load left [operand](/page/Operand) */ TSX T /* Transfer to temporary */ CLA A2 /* Load right [operand](/page/Operand) */ ANA T /* Logical AND with temporary (for XOR simulation) */ STA TEMP /* Store intermediate */ ... /* Additional instructions for full XOR */ OUT /* End sequence */ END /* End [definition](/page/Definition) */

DEFINE BINARY OPERATOR .EV., PRECEDENCE SAME AS .V. MODE [STRUCTURE](/page/Structure) 1 = 1 .EV. 1 CLA A1 /* Clear accumulator, load left [operand](/page/Operand) */ TSX T /* Transfer to temporary */ CLA A2 /* Load right [operand](/page/Operand) */ ANA T /* Logical AND with temporary (for XOR simulation) */ STA TEMP /* Store intermediate */ ... /* Additional instructions for full XOR */ OUT /* End sequence */ END /* End [definition](/page/Definition) */

This operator can then be used as X .EV. Y in expressions, mimicking built-in bitwise operations but with custom assembly for efficiency. Another example redefines for double-precision mode 5 by calling a subroutine DPM:

MODE [STRUCTURE](/page/Structure) 5 = 5 * 5 TSX DPM /* Transfer to double-precision multiply subroutine */ OUT END

MODE [STRUCTURE](/page/Structure) 5 = 5 * 5 TSX DPM /* Transfer to double-precision multiply subroutine */ OUT END

These capabilities highlight MAD's design for mathematical extensibility, allowing users to tailor operators for scientific tasks.

Built-in Packages

MAD's built-in packages provide predefined extensions for advanced numerical computations, allowing programmers to incorporate specialized types, operators, and functions without manual implementation. These packages are included in a program using the INCLUDE statement (abbreviated as I'E), which loads definitions from secondary storage into the source code. The three primary built-in packages—MATRIX, DOUBLE PRECISION, and COMPLEX—address common needs in scientific and applications, extending the language's core capabilities for matrices, high-precision arithmetic, and complex numbers. The MATRIX package enables vector and matrix arithmetic, introducing matrix variables as a specialized type built on two-dimensional arrays (e.g., declared as MATRIX A(10,10)). Upon inclusion, it adds operators for , subtraction, , and transposition, along with built-in functions such as DET for computing the and INVERSE for matrix inversion. These features simplify linear algebra tasks, such as solving systems of equations, by treating matrices as first-class objects with dedicated syntax (e.g., C = A * B for ). Arrays in general benefit from MATRIX by gaining support for higher-dimensional operations when matrix types are activated. The DOUBLE PRECISION package supports extended through mode 5 declarations, doubling the storage precision for numeric variables (e.g., DOUBLE PRECISION X). It introduces a binary operator (*) implemented via a subroutine (DPM) that operates on accumulator (AC) and multiplier-quotient (MQ) registers, ensuring accurate computations for applications requiring more than single-precision resolution. This package effectively extends the language's numeric modes (0-7) by allocating additional storage, as in DOUBLE STORAGE MODE 5. The COMPLEX package facilitates handling of imaginary and complex numbers using modes 6 and 7, allowing declarations like COMPLEX Z. It adds arithmetic operators for complex addition, subtraction, multiplication, and division, treating complex values as pairs of real and imaginary components. Inclusion activates these modes and associated functions, enabling computations in fields like and physics without custom subroutines. These built-in packages are implemented at an assembly level using MAD's definition facility, which compiles user-like definitions into machine instructions for efficiency. They are user-extensible, as programmers can create and include custom packages following the same INCLUDE mechanism, building on the predefined ones for further specialization. Limitations include fixed operator precedence in certain implementations (e.g., IBM 7090 MAD), preventing redefinition of unary/binary symbols or subscription operations due to constraints.
Add your contribution
Related Hubs
User Avatar
No comments yet.