5MAT

5MAT is an esolang derived from Common Lisp FORMAT strings created by User:kg583. A data string is repeatedly passed to Common Lisp's format function, whence a program made of numerous and powerful format directives processes the string.
== Execution ==
A 5MAT program is a FORMAT string which repeatedly formats a tape of characters, terminating only via runtime error. The tape is always initially nil.
Execution may be implemented in Common Lisp via
 (setq tape nil)
 (loop (setq tape (coerce (format nil *program* tape) 'list)))
where coercion to a list is required to allow the ~{~} directive to iterate over the tape.
To permit output to STDOUT, the tape is divided into output and data sections, separated by a � (0x17), a (non-printing) End of Transmission Block (ETB) character. All contents of the output section are printed each iteration, while the data section is not printed.
Output may be implemented in Common Lisp via
 (setq tape nil)
 (loop (format t "~{~v,'�^~:*~a~}" (setq tape (coerce (format nil *program* tape) 'list))))
== Writing Programs ==
Note: This guide assumes familiarity with Common Lisp FORMAT strings.
=== Initialization ===
Use ~[INIT-OUTPUT�INIT-DATA~;~]~:* at the start of your program to initialize the tape.
=== Conditionals ===
To identify a character on the tape, use the two-argument and three-argument version of ~^:
* If two parameters are given, termination occurs if they are equal.
* If three parameters are given, termination occurs if the first is less than or equal to the second and the second is less than or equal to the third.
For example:
 ; Iff the current character is not 'C'
 ~<~v,'C^STUFF~>
 
 ; Iff the current character is 'C'
 ~<~v,'B,'B^~:*~'D,'D,v^STUFF~>
Checking character ranges where possible can greatly shorten a program.
=== Looping ===
Since the tape is passed as a list, programs must use a containing ~{~} to loop over it, even if all characters are exhausted in a single iteration.
Here are some common idioms:
 ; Go to the start of the tape
 ~@*
 
 ; Go to the end of the tape
 ~@{~*~}
 
 ; Go to the start of the data section
 ~@*~@{~v,'�^~}
 
 ; Print characters until <char>
 ~@{~v,'<char>^~:*~a~}
 
 ; Print characters in reverse
 ~@{~a~2:*~}
 
 ; Check how many characters remain
 ~#[ZERO~;ONE~;...~]
 
 ; Break if no characters remain
 ~^
 
 ; Break unconditionally
 ~0^
=== Termination ===
Since 5MAT programs run forever, only a runtime error can end execution. The easiest option is ~v*, which requires an integer parameter, but ~[~], ~{~} (inside the main loop), and ~a (if no characters remain) also suffice.
=== Arithmetic ===
A succinct general approach to decimal arithmetic is to store values on the tape backwards, then increment as follows:
# Turn all trailing 9's to 0's
# Increment the first digit that isn't a 9 by checking for each digit individually
# Pad with a leading zero if there are no digits left
# Copy the digits in reverse to output
The above generalizes easily to any base and any system of digits.
=== Miscellany ===
* 5MAT programs can be made "readable" using the ~\n directive.
* Comments may be inserted via unreachable pathways, e.g. ~1[COMMENT HERE~].
== Examples ==
=== Hello, World! ===
 Hello, World!~v*
=== Truth Machine ===
 ~:[INPUT~;~]~:*~{~<~v,'1^~v*~>1~}
=== FizzBuzz ===
 ~:[�11�10~;~]~:*~{~@{~v,'�^~}~<~'1,'1,v^Fizz~>~<~'1,'1,v^Buzz~>~2:*~<~v,'0^~v,'0^~@{~*~}~2:*~@{~v,'�^~:*~a~2:*~}~>~
 ~@*~@{~v,'�^~}~%�~<~'1,'1,v^1~>~:*~<~v,'0^~:*~'2,v^2~>~:*~<~v,'1,'1^0~>~
 ~<~'1,'1,v^1~>~:*~<~v,'0^~:*~'2,'2,v^2~>~:*~<~v,'1,'1^~:*~'3,'3,v^3~>~:*~<~v,'2,'2^~:*~'4,'4,v^4~>~:*~<~v,'3,'3^0~>�~
 ~*~@{~v,'8,'8^0~}~:*~<~'1,'1,v^1~>~:*~<~v,'0^~:*~'2,'2,v^2~>~:*~<~v,'1,'1^~:*~'3,'3,v^3~>~:*~<~v,'2,'2^~:*~'4,'4,v^4~>~:*~<~v,'3,'3^~:*~'5,'5,v^5~>~
 ~:*~<~v,'4,'4^~:*~'6,'6,v^6~>~:*~<~v,'5,'5^~:*~'7,'7,v^7~>~:*~<~v,'6,'6^~:*~'8,'8,v^8~>~:*~<~v,'7,'7^~:*~'9,v^9~>~#[0~]~@{~a~}~}
=== Fibonacci ===
 ~:[�1,;1,;~^~;~]~:*~{~<~v,'�^�0,~@{~v,';^~}~@{~v,',^~:*~a~};~@*~@{~v,';^~}~@{~a~}~>~^~:*~
 ~<~'0,'0,v^~@{~v,',^~}~<~v,'1,'1^~1@*~@{~v,',^~}~@{~2:*~v,'�^~:*~a~}~
 ~%�0,;~@{~v,',^~}~*~@{~v,',^~:*~a~}~@{~v,';^~:*~a~}~@*~@{~v,';^~},~@{~v,',^~:*~a~};
 ~@{~*~}~>~:*~<~v,';^�~1@*~@{~v,'8,'8^0~}~:*~
 ~<~'1,'1,v^1~>~:*~<~v,'0,'0^~:*~'2,'2,v^2~>~:*~<~v,'1,'1^~:*~'3,'3,v^3~>~:*~<~v,'2,'2^~:*~'4,'4,v^4~>~:*~<~v,'3,'3^~:*~'5,'5,v^5~>~
 ~:*~<~v,'4,'4^~:*~'6,'6,v^6~>~:*~<~v,'5,'5^~:*~'7,'7,v^7~>~:*~<~v,'6,'6^~:*~'8,'8,v^8~>~:*~<~v,'7,'7^~:*~'9,v^9~>~
 ~:*~<~v,',^~@{~v,',^~:*~a~}~>,~>~*~@{~a~}~>~0^~}
=== Palindrome Detector ===
 ~:[��INPUT-TUPNI~;~]~:*~{~#[~;~;True~%�~:;~<~v,'�^~{~}~>~<~v,'�^~:*~<~v,v^False~%�~@{~*~}~>�~@{~a~}~>~^�~a~@{~*~}~:*~a�~3@*~@{~a~#,1^~}~]~0^~}
=== 12 Days of Christmas ===
 ~:[�~;~]~:*~{~@{~v,'�^~}On the ~#[First~;Second~;Third~;Fourth~;Fifth~;Sixth~;Seventh~;Eighth~;Ninth~;Tenth~;Eleventh~;Twelfth~] day of Christmas~
 ~%My true love sent to me~@{~%~#[~;Two~;Three~;Four~;Five~;Six~;Seven~;Eight~;Nine~;Ten~;Eleven~;Twelve~] ~
 ~#[~;Turtle Doves, and~0^~;French Hens~;Calling Birds~;Gold Rings~
 ~;Geese-a-Laying~;Swans-a-Swimming~;Maids-a-Milking~;Ladies Dancing~;Lords-a-Leaping~;Pipers Piping~;Drummers Drumming~;~v*~],~*~}~
 ~%A Partridge in a Pear Tree.~2%~@*~@{~v,'�^~}�1~@{1~*~}~0^~}
== Implementations ==
A 5MAT driver, debugger, and much of the example code provided above can be found in the 5MAT GitHub repo.
== Turing Completeness ==
A 5MAT program which interprets arbitrary Bitwise Cyclic Tags is given below (and can be found with comments in the aforementioned GitHub repo).
 ~:[~%DATA�PROGRAM~;~]~:*~{~@{~v,'�^~}~
 ~<~v,'1^~%~2@*~@{~v,'�^~:*~a~}�~*~@{~a~}0~>~^~
 ~:*~<~%~1@*~v,'0^~:*~@{~v,'�^~:*~a~}~*~a�~
 ~@{~a~}1~@*~@{~v,'�^~}~*~a~@{~*~}~>~^~%~@{~a~}~}
Compilation directly from a Turing machine or other discrete state machine is also fairly straightforward.
Category:Languages Category:Implemented Category:Esoteric subset Category:String-rewriting_paradigm Category:2024