Mornington Crescent
Mornington Crescent, named after Mornington Crescent tube station in London and invented by Timwi in 2013 as somewhat of a tribute to the game of Mornington Crescent, is an esoteric programming language in which the data pointer moves through the London Underground by traveling by tube from station to station, starting and ending at Mornington Crescent.
Syntax
Mornington Crescent programs consist of a series of transitions from the current tube station to another, using one of the tube lines available at the current station. For example:
Take Northern Line to Leicester Square Take Piccadilly Line to King's Cross St. Pancras Take Circle Line to Westminster
etc.
Only lines matching ^Take (.*) Line to (.*)$
are valid, and the capturing groups must match a valid tube line name and tube station name, respectively.
An optional extra newline at the end of the program is acceptable.
Environment
- During execution, every tube station on the London Underground has a current value, which is either an arbitrary-size integer or a string. Unless otherwise noted below, every station’s value starts out as a string containing that station’s name, for example Waterloo starts out with the value
"Waterloo"
. - There is an accumulator which is also either an arbitrary-size integer or a string. This starts out with the contents of STDIN as a string.
- The data pointer points at a current station. Execution begins at Mornington Crescent.
- There is also a “jumpstack”, a stack of program locations, which is initially empty.
Valid Mornington Crescent programs must end at Mornington Crescent tube station. If execution moves beyond the last instruction in the program and that instruction does not validly take the data pointer to Mornington Crescent, a runtime error occurs.
Execution
Each instruction is executed as follows:
- If the specified line or tube station doesn’t exist, or the line doesn’t connect the current station with the destination, a runtime error occurs.
- Otherwise:
- the data pointer is moved to the destination station;
- the accumulator and the destination station’s value are swapped.
For example, if the first instruction in the program is
Take Northern Line to Leicester Square
then Leicester Square’s value becomes the string read from STDIN and the accumulator’s value becomes "Leicester Square"
.
However, some of the stations have special behaviour as described below.
Station | Short | Special meaning |
---|---|---|
Upminster | add | The accumulator’s value is set to the sum of its current value and the station’s current value, if both are integers (otherwise, standard swap). |
Chalfont & Latimer | multiply | The accumulator’s value is set to the product of its current value and the station’s current value, if both are integers (otherwise, standard swap). |
Cannon Street | integer division | The accumulator’s value is set to the quotient (rounded towards 0) of the station’s current value divided by the accumulator’s current value (or the empty string if the accumulator is 0) if both are integers (otherwise, standard swap). |
Preston Road | remainder | The accumulator’s value is set to the remainder of the station’s current value divided by the accumulator’s current value (or the empty string if the accumulator is 0) if both are integers (otherwise, standard swap). |
Bounds Green | max | The accumulator’s value is set to the station’s current value only if it is larger, if both are integers (otherwise, standard swap). |
Manor House | bitwise NOR (OR+NOT) | Just like the above arithmetic operators, but with bitwise operations. The shift operations only trigger if the shift amount is positive. |
Holland Park | bitwise AND | |
Turnham Green | bitwise shift-right | |
Stepney Green | bitwise shift-left | |
Russell Square | square | The accumulator’s value is set to the square of the station’s current value if it is an integer (otherwise, standard swap). |
Notting Hill Gate | bitwise NOT | The accumulator’s value is set to the bitwise NOT of the station’s current value if it is an integer (otherwise, standard swap). |
Parsons Green | parse string to integer | If the accumulator contains a string, attempts finding and parsing an integer in it. The accumulator is set to the first integer found (or 0 if none), and the station’s value is set to the rest of the string (or "" ). (If the accumulator is an integer, standard swap occurs. Note that this condition is inconsistent with other instructions, which decide this based on their current value rather than the accumulator.)
Example: If the accumulator value is |
Seven Sisters | 7 | This station’s value is always 7. The accumulator’s value is set to 7 and its previous value discarded. |
Charing Cross | character ↔ codepoint | If the station’s value is a non-empty string, the accumulator is set to the Unicode codepoint of the first character; if it’s the empty string, to 0; if it is an integer, the accumulator is set to the Unicode character with this codepoint. |
Paddington | string concatenation | The accumulator is set to the concatenation of the station’s value followed by the accumulator’s previous value, if both are strings (otherwise, standard swap). |
Gunnersbury | left substring | If one of the two values is a string s and the other an integer i, the accumulator is set to the string containing the first i characters of s. If i is negative or out of range, a runtime error occurs. If they are both strings or both integers, standard swap occurs. |
Mile End | right substring | Like Gunnersbury, but the accumulator is set to the last i characters. |
Upney | upper-case | Sets the accumulator to the upper-case of the station’s value if it is a string (otherwise, standard swap). |
Hounslow Central | lower-case | Sets the accumulator to the lower-case of the station’s value if it is a string (otherwise, standard swap). |
Turnpike Lane | reverse string | Sets the accumulator to the reverse of the station’s value if it is a string (otherwise, standard swap). |
Bank | When a value is stored in Bank, Hammersmith is also set to the same value. | |
Hammersmith | Always retains its current value. The value of the accumulator is discarded and replaced. | |
Temple | continuation | This station does not have a current value. The accumulator remains unaltered. Landing on this station pushes the current instruction pointer onto the jumpstack. |
Angel | if | This station does not have a current value. The accumulator remains unaltered. If the accumulator is the integer 0, nothing happens. Otherwise, execution continues at the instruction stored at the top of the jumpstack (without popping it) and the data pointer is teleported to Temple. |
Marble Arch | pop | This station does not have a current value. The accumulator remains unaltered. Landing on this station pops the topmost value off the jumpstack. Nothing else happens. |
Mornington Crescent | output/exit | The value of the accumulator is printed and the program is terminated. |
Computational class
Likely Turing complete because strings and integers can be any size and the jumpstack allows arbitrarily nested flow control. Not proven, however.
Forward compatibility
As the validity and the semantics of a program depend on the structure of the London underground system, which is administered by London Underground Ltd, a subsidiary of Transport for London, who are likely unaware of the existence of this programming language, its future compatibility is uncertain. Programs may become invalid or subtly wrong as the transport company expands or retires some of the network, reroutes lines or renames stations. Features may be removed with no prior consultation with the programming community. For all we know, Mornington Crescent itself may at some point be closed, at which point this programming language will cease to exist.
Example
Hello, World!
This program was written by Martin Büttner and is only half the length of the language creator’s original version.
Take Northern Line to Hendon Central Take Northern Line to Bank Take Northern Line to Bank Take District Line to Gunnersbury Take District Line to Victoria Take Victoria Line to Seven Sisters Take Victoria Line to Victoria Take Victoria Line to Victoria Take District Line to Bank Take District Line to Hammersmith Take District Line to Cannon Street Take District Line to Hammersmith Take District Line to Cannon Street Take District Line to Bank Take District Line to Hammersmith Take District Line to Upminster Take District Line to Hammersmith Take District Line to Upminster Take District Line to Gunnersbury Take District Line to Paddington Take District Line to Acton Town Take Piccadilly Line to Holloway Road Take Piccadilly Line to Acton Town Take Piccadilly Line to Acton Town Take District Line to Gunnersbury Take District Line to Hammersmith Take District Line to Notting Hill Gate Take District Line to Upminster Take District Line to Notting Hill Gate Take District Line to Upminster Take District Line to Victoria Take Victoria Line to Seven Sisters Take Victoria Line to Victoria Take Victoria Line to Victoria Take District Line to Upminster Take District Line to Gunnersbury Take District Line to Mile End Take District Line to Hammersmith Take District Line to Notting Hill Gate Take District Line to Upminster Take District Line to Upminster Take District Line to Mile End Take District Line to Paddington Take District Line to Paddington Take District Line to Acton Town Take Piccadilly Line to Heathrow Terminals 1, 2, 3 Take Piccadilly Line to Holborn Take Central Line to Holborn Take Central Line to Mile End Take District Line to Upminster Take District Line to Hammersmith Take District Line to Upminster Take District Line to Barking Take District Line to Hammersmith Take District Line to Upminster Take District Line to Gunnersbury Take District Line to Barking Take District Line to Gunnersbury Take District Line to Paddington Take District Line to Paddington Take Circle Line to Wood Lane Take Circle Line to Victoria Take Circle Line to Victoria Take District Line to Gunnersbury Take District Line to Hammersmith Take District Line to Upminster Take District Line to Gunnersbury Take District Line to Paddington Take District Line to Paddington Take District Line to Mile End Take Central Line to Fairlop Take Central Line to Mile End Take District Line to Barking Take District Line to Upminster Take District Line to Upminster Take District Line to Hammersmith Take District Line to Notting Hill Gate Take District Line to Upminster Take District Line to Mile End Take District Line to Gunnersbury Take District Line to Paddington Take District Line to Paddington Take District Line to Hammersmith Take District Line to Mile End Take District Line to Richmond Take District Line to Mile End Take District Line to Paddington Take District Line to Paddington Take District Line to Richmond Take District Line to Bank Take District Line to Hammersmith Take District Line to Upminster Take District Line to Stepney Green Take District Line to Hammersmith Take District Line to Stepney Green Take District Line to Upney Take District Line to Notting Hill Gate Take District Line to Notting Hill Gate Take District Line to Notting Hill Gate Take District Line to Upminster Take District Line to Upney Take District Line to Upminster Take District Line to Bank Take Circle Line to Bank Take Northern Line to Charing Cross Take Bakerloo Line to Charing Cross Take Bakerloo Line to Paddington Take Circle Line to Bank Take Circle Line to Bank Take Northern Line to Mornington Crescent
Interpreters
Esoteric IDE
Interpreter and debugger for many esoteric languages (including Mornington Crescent), written by the author of Mornington Crescent. The sources can be found at GitHub.
Esoterpret
Multi-language interpreter written in Python, as of 2015-10-06 only supporting Mornington Crescent. Open Source and available at GitHub.