TRAIN!

TRAIN! is an esoteric programming language designed by Jonathan Brouwer, Jonathan Dönszelmann, Julius de Jeu and Noah Jadoenathmisier created as part of the first LangJam. 
In TRAIN!, computation is based on trains driving around tracks between stations. Stations represent operations applied to a train or pair of trains which enter the station. Data is contained within trains as a list
of passengers holding a number. Generally operations apply to the top number in this list working like a stack.
== Instructions ==
Instructions are encoded as stations. Stations can have either one or two input and one or two output tracks. As an example: add has two input tracks and two output tracks. 
The add station waits until two trains have entered the station (one on each input track). The first number of the train on track 1 is added to the first number of the train on track 2, 
and the result replaces the top number of the train on track 1. The train on track 2 is not modified (and keeps its number) (note: all binary operations work like this). Now both trains
leave their respective track again to another (different or the same) station. Traveling from one station to another takes 1 timestep. 
It is possible that a station expecting two trains for its operation, only receives one train that timestep. This train now waits on the station until the station receives a second train on the other track.
However, if in that time another train arrives on the same track this new train is queued but not deleted. It is unspecified behaviour to send two trains to the same track of the same station in the same timestep.
Stations can apply one of the following operations to trains entering it:
 Instructions
Name 	Use
nothing 	Do nothing.
print string	Prints the contents of a train as a string. Each number in the list passengers in the train is converted into an ascii character.
print number	Prints the contents of a train as a list of decimal numbers.
Input 	Ask for a single integer of input, which is added to the top of a train
switch eq 	Trains come in on track 1. If their first number is equal to zero, they leave on track 1. Otherwise they leave on track 2.
switch gt 	Trains come in on track 1. If their first number is equal to zero or positive, they leave on track 1. Otherwise they leave on track 2.
switch empty	Trains come in on track 1. If the train has no passengers, leave on track 1. Otherwise they leave on track 2.
transfer 	Two trains are accepted. The first passenger in train 1 is transferred to the train on track 2. This passenger now becomes the first passenger in train 2.
rotate 	Trains come in on track 1 and leave again on track 1. The first passenger is rotated and becomes the last passenger on that train. The second becomes the first, the third the second, etc.
duplicate 	Trains come in on track 1. A copy of the train is outputted on track 1 and track 2 (yes, trains can magically clone).
delete top 	Deletes the first number from the train on track 1. The train is sent out again on track 1.
add 	Binary operation adding the value of the first person in train 1 to the value of the first person in train 2. Both trains continue out of the station, train 2 unmodified and train 1 with the top value modified to be the sum.
sub 	Binary operation subtracting the value of the first person in train 1 to the value of the first person in train 2. Both trains continue out of the station, train 2 unmodified and train 1 with the top value modified to be the difference.
div 	Binary operation dividing the value of the first person in train 1 to the value of the first person in train 2. Both trains continue out of the station, train 2 unmodified and train 1 with the top value modified to be the quotient.
mul 	Binary operation multiplying the value of the first person in train 1 to the value of the first person in train 2. Both trains continue out of the station, train 2 unmodified and train 1 with the top value modified to be the product.
mod 	Binary operation taking the modulo of value of the first person in train 1 and the value of the first person in train 2. Both trains continue out of the station, train 2 unmodified and train 1 with the top value modified to be the remainder.
delete 	All trains entering this station (even in the same timestep) are deleted from the world.
== Programs ==
Programs in TRAIN! have a very specific structure:
First come the trains. There can be an infinite number of trains. Trains are specified as follows:
 [LOCOMOTIVE]
 start at Eindhoven track 1
 [FIRST CLASS]
 Gerrit: This train has a very pretty yellow colour!
 Robbin: I like the blue detail.
 Sara: The train is very short though...
 [SECOND CLASS]
 Marijke: 102
 Peter: 105
 Layla: 122
 Tom: 122
 Jonathan: 98
 Laura: 117
 Julius: 122
 Jasmine: 122
Trains start with the word [LOCOMOTIVE] after which the starting station and track is specified.
Folliowing that are the first and second class passengers. First class passengers are comments and can contain (after a name and colon) arbitrary text. However, the text is interpreted (looking for the words
"long", "medium" or "short" and colours in the format "<colourname> color", "<colourname> locomotive", "<colourname> colour", "<colourname> accent", "<colourname> detail", "<colourname> line" or "<colourname> stripe" where the colourname can be one of:
* "light red"
* "dark red"
* "light green"
* "dark green"
* "light blue"
* "dark blue"
* "water blue"
* "brown"
* "yellow"
* "orange"
Comments are in first class as per the theme of the LangJam which was "First class comments".
After the first class, the second class is defined with people holding integer (64 bit signed) data. There can be an arbitrary number of passengers.
The train definitions are followed by a number of station definitions:
 {Utrecht}
 operation: add
 track 1: go to Utrecht track 2
 track 2: go to Amsterdam track 1
 
 {Amsterdam}
 operation: print number
 track 1: go to Utrecht track 1
(the above is a simple Fibonacci program, given the right train setup). 
Utrecht has the add operation. The add operation has two tracks. Numbers on trains on track 1 are added to numbers on trains on track 2. After addition, the train on track 1 moves to Utrecht again, but now on track 2. While the train which was on track 2 now goes to Amsterdam. The train in Utrecht waits until the train is back from Amsterdam after the contents of the Amsterdam train were printed, continuing the cycle.
Considerations:
* Station names can not contain spaces
* Operation names are to be written as in the table with instruction names above
* Trains and stations may not contain empty lines within their definition
* Stations may not define more or fewer tracks than the operation dictates
== Implementation ==
The reference implementation of TRAIN! can be found here: https://github.com/jonay2000/jam0001/tree/main/Boole. The reference implementation also has a visual execution which simulates the trains moving from
station to station. Train stations and tracks are automatically layed out using a combination of pathfinding and physics simulation.
== Sample programs ==
Apart from the samples which can be found on the reference implementation's github repository, the following is an example of a full fibonacci program in TRAIN!
 [LOCOMOTIVE]
 start at Amsterdam track 1
 [FIRST CLASS]
 Jan: this is a nice long lime green train!
 Pieter: It has some blue accents as well!
 [SECOND CLASS]
 Julius: 1
 
 [LOCOMOTIVE]
 start at Utrecht track 2
 [FIRST CLASS]
 Gerrit: This train has a very pretty yellow colour!
 Marijke: I like the blue detail.
 Sara: The train is very short though...
 [SECOND CLASS]
 Jonathan: 1
 
 {Utrecht}
 operation: add
 track 1: go to Utrecht track 2
 track 2: go to Amsterdam track 1
 
 {Amsterdam}
 operation: print number
 track 1: go to Utrecht track 1
Category:2021
Category:Concurrent programming
Category:Turing complete
Category:Finite state automata
Category:Implemented
Category:Thematic
Category:Languages