TFMG
Paradigm(s) | Declarative |
---|---|
Designed by | KSP Atlas |
Appeared in | 2024 |
Memory system | Queue-based |
Computational class | Turing complete |
Reference implementation | Unimplemented |
File extension(s) | .fctro , .tfmg |
The Factory Must Grow (also known as TFMG) is an esoteric programming language inspired by Factorio.
Overview
TFMG is a concurrent programming language based around a system of belts, which are queues of a defined length. All machines must operate on belts (with the exception of chained machines). A machine must always have either an input or an output, as a machine with neither will never run. A machine can only run a recipe if all the required items (values) are available, and if there is space on the output belt. All TFMG programs will run forever, unless they are limited in some way (for example, if the supply of a constant is limited). TFMG machines will always consume their inputs from the queue, and they have no artificial speed limit, unless one is defined (unlike Factorio).
Making Belts
Create a simple belt called main
with 10 spaces:
belt main 10
A double sided belt has double the space and acts as 2 in 1, however, only the left lane will be used unless specified otherwise.
Create a double-sided belt called append-belt
with 10 spaces (which ends up being 20)
double-belt append-belt 10
Simple belt-belt operations
(note: Machines that take multiple belts always go left-right, and only take whats available on the end of the belt)
Merge two belts into one:
(belt-1, belt-2) > id<all> > belt-3
Merge two belts into one (left-bias):
(belt-1, belt-2) > id<0> > belt-3
Evenly split a belt:
belt-1 > split<all> > (belt-2, belt-3)
Split a belt, but push all Ints to the left:
belt-1 > split<Int> > (belt-int, belt-3)
Producing constants
Produce an infinite amount of the number 42 (the recipe is the constant value in this case):
Int<42> > the-answer
Only produce 10 instances of the string "Hello", using the # operator to limit the number of times the machine runs:
String<Hello>#10 > greet-belt
Take the top value of money
, and push it to the belt free-money
:
money > repeat > free-money
Misc
Make a belt of higher-order machines (with recipe), and pass it to a machine:
Lambda<increment<2>> > fun-belt (fun-belt, arr-belt) > map > result-belt
Take a user input input of a number, check if its greater than 10 and if so, push an element from the top of congrat-belt to the result:
Int<10> > second-belt Input<YN>#1 > ask-belt (ask-belt, second-belt) > greater-than > comp-belt (comp-belt, congrat-belt) > if > result-belt
Chain two machines together using -> (only works if output and input amounts of belts match):
belt-1 > doer<thing> -> doer<other-thing> > belt-2
Making your own machines
Make a machine that squares a number or multiplies it by another and divides all by three:
machine math { // Third slot is for temporary belts made during the recipe recipe square (input: Int) (output) () { (input, input) > arithmetic<multiply> > output } recipe mulanddiv (input-1: Int, input-2: Int) (output) (multiplied = 10, divs = 10) { Int<3> > divs (input-1, input-2) > arithmetic<multiply> > multiplied (multiplied, divs) > arithmetic<divide> > output } }
Automatically choose the recipe used for a machine (only works if all recipes use different types and only have one input belt):
machine-auto stove { recipe boil (pasta: Pasta) (cooked) () { pasta > Pot<boil> > cooked } recipe fry (egg: Egg) (fried) () { egg > Pan<fry> > fried } } // Now these are both valid (assuming the belts exist) raw-eggs > stove > fried-eggs raw-pasta > stove > cooked-pasta
Example programs
Hello world:
belt hello 10 String<Hello, World!>#1 > hello hello > print<str>
Hello world (5 times):
belt hello 10 String<Hello, World!>#5 > hello hello > print<str>
Cat program:
Input<str> -> print<str>
Truth machine:
belt input 10 belt truth 10 belt output 10 Bool<true> > truth Input<YN> > input (input, truth) > if > output output > print<bool>