Awesome
motorway-lang
An esoteric programming language based around the British motorway network.
The Language
A Motorway program is a description of a route along the British (mainland) motorway network. Only motorways that form the main interconnected network are allowed. Any non-existent or unconnected motorway (e.g. M2) is a syntax error. Anything not of the form Mx or AxM (where x is a number) is ignored as a comment.
Certain motorways have special meanings, called commands. Other motorways merely serve to connect these commands.
A program is valid only if the route it describes is physically possible (i.e. each motorway visited must connect to
the next). The directionality of junctions is not considered when testing the validity of a route, nor is motorway
status (or lack thereof) of connections at junctions between two motorways (e.g. you can change between the M1 and M69,
even though in real life, this would involve leaving motorway restrictions and negotiating a roundabout before getting
onto the M69). A motorway corresponding to a command can be visited without invoking its effect by placing the route
number in brackets (e.g. M6 (M1) M69
visits the M1 with no side effects).
A program has access to a data stack, which most of the commands manipulate. The stack comprises an unbounded number of 8-bit unsigned cells, which wrap on overflow. Note that in practice, there will be an upper bound on the size of the stack, but this is not defined by the language.
Commands
- M1 – increment top of stack.
- M4 – pop current character and print it to stdout.
- M5 – pop top of stack and discard the value.
- M6 – push new cell to stack, initialized to zero.
- M20 – read a single character from stdin and push it to top of stack.
- M25 – if top of stack is zero, skip past matching
M62
token, else, continue to next motorway (i.e. loop start). - M26 – jump back to matching
M25
token (i.e. loop end). - M40 – duplicate top of stack.
- M42 – swap top two elements of stack.
- M48 – add top of stack to next element.
- M49 – subtract top of stack from next element.
- M60 – rotate top three elements of stack like so:
... c b a
->... b a c
(ellipsis represents rest of stack).
Other Motorways
- M3 – connects to M25, M27.
- M8 – connects to M9, M73, M74, M77, M80, M898, A8M.
- M9 – connects to M8, M80, M90, M876.
- M11 – connects to M25.
- M18 – connects to M1, M62, M180, A1M.
- M23 – connects to M25.
- M27 – connects to M3.
- M32 – connects to M4.
- M45 – connects to M1.
- M50 – connects to M5.
- M53 – connects to M56.
- M54 – connects to M6.
- M55 – connects to M6.
- M56 – connects to M6, M53, M60.
- M57 – connects to M58, M62.
- M58 – connects to M6, M57.
- M61 – connects to M6, M60, M65, A666M.
- M62 – connects to M1, M6, M18, M57, M60, M621, M602, M606, A1M, A627M.
- M65 – connects to M6, M61.
- M66 – connects to M60, M62.
- M67 – connects to M60.
- M69 – connects to M1, M6.
- M73 – connects to M8, M74, M80, A8M.
- M74 – connects to M8, M73, M77, A74M.
- M77 – connects to M8.
- M80 – connects to M8, M9, M73, M876.
- M90 – connects to M9, A823M.
- M180 – connects to M18, M181.
- M181 – connects to M180, A1077M.
- M271 – connects to M27.
- M275 – connects to M27.
- M602 – connects to M60, M62.
- M606 – connects to M62.
- M621 – connects to M1, M62.
- M876 – connects to M9, M80.
- M898 – connects to M8.
- A1M – connects to M1, M18, M25, M62, A66M, A194M, A195M.
- A8M – connects to M8, M73.
- A38M – connects to M6.
- A48M – connects to M4.
- A66M – connects to A1M.
- A74M – connects to M6, M74.
- A194M – connects to A1M.
- A195M – connects to A1M.
- A308M – connects to M4, A404M.
- A329M – connects to M4.
- A404M – connects to M4, A308M.
- A601M – connects to M6.
- A627M – connects to M62.
- A666M – connects to M61.
- A823M – connects to M90.
- A1077 – connects to M181.
The Interpreter
This repository contains a Python implementation of the language. This relies on the third-party package
fixedint which must be installed before using the interpreter (e.g. using pip
).
Of course, Python (3.9+) must also be installed on the system to use the interpreter.
With fixedint installed, you can run the interpreter by running the script motorway.py
:
python motorway.py [file]
The argument file
, if provided, determines the source code file to be interpreted. Alternatively, you can omit it to
enter an interactive REPL session. The recommended filename extension for Motorway files is *.mway
, although any
extension may be used. The extension must be included when invoking the interpreter.
Project Structure
Source code is (mainly) found in the src
directory. A single script motorway.py
is provided in the project root to
make it easier to use as a command line tool.
The network used to validate routes can be found in data/network.json
.
The tools
directory contains scripts used to automatically generate various parts of the project. These should not
need to be invoked in normal running of the interpreter (although running them shouldn't break anything either).
The contents of these subdirectories are described in more detail in their individual READMEs.