!!!Batch
| Paradigm(s) | imperative, self-modifying |
|---|---|
| Designed by | Shubshub |
| Appeared in | 2012 |
| Memory system | variables |
| Dimensions | one-dimensional |
| Computational class | Turing complete |
| Reference implementation | !!!Batch/Interpreters, !Py!Batch (MediaFire) |
| Influenced by | Batch |
| Influenced | !!! |
| File extension(s) | unknown |
!!!Batch is another derivative of the Batch programming language created by Shubshub :D. !!!Batch is an encoding of Batch where each character is in the form of a question mark, followed by some amount of exclamation marks, then an optional marking character, and finally another question mark. Other characters are returned as-is. Since !!!Batch is an encoding of Batch, and Batch is Turing complete, so is !!!Batch.
Syntax
Source code for version 1.3 is formatted as set str=<code>, with <code> being the !!!Batch source code. The code is decoded into ASCII characters which are then put into a Batch file. The output file always begins with @echo off and ends with pause. Since the input file is executed as a Batch file, it has access to the entire language before being compiled, effectively making Batch its meta-language.
Further versions have code formatted plainly in a file. The file is no longer executed, and the heading @echo off and footing pause are omitted. Additionally, the official translators also execute the resulting output file.
Encoding
Each version has a different alphabet.
- Version 1.3:
abcdefghijklmnopqrstuvwxyz& ?!\/.:0123456789| - Version 1.5:
abcdefghijklmnopqrstuvwxyz& ?!%/.:0123456789=+-<>@*, upperABCDEFGHIJKLMNOPQRSTUVWXYZ - Version 2.0:
abcdefghijklmnopqrstuvwxyz, middle& ?!%/.:0123456789=+-<>@*, upperABCDEFGHIJKLMNOPQRSTUVWXYZ
The number of exclamation marks in a character's encoding corresponds to its 1-based index in its alphabet, e.g. a has 1 mark, z 26, A 1, etc. If the character in the upper alphabet a plus is appended, or if in the middle, a hyphen minus. Characters in the normal alphabet don't have a character appended. Finally, the result is surrounded by a question mark on both sides. Select encodings in version 2.0:
a:?!?b:?!!?%:?!!!!!-?A:?!+?D:?!!!!+?
Examples
Hello world (version 1.3)
Hello World In !!!Batch :D
set str=?!!!!!??!!!??!!!!!!!!??!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!!!!!!!!!!!??!!!!!!!!??!!!!!??!!!!!!!!!!!!??!!!!!!!!!!!!??!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!??!!!!!!!!!!!!??!!!!??!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?
Hello world (version 1.5)
Hello world example (because some of the code has changed). This outputs Hello World! (Because !!!Batch now supports capital lettering).
?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!??!!!!!??!!!??!!!!!!!!??!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!??!!!!!!??!!!!!!? ?!!!!!??!!!??!!!!!!!!??!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!!!!!!!!!!!??!!!!!!!!+??!!!!!??!!!!!!!!!!!!??!!!!!!!!!!!!??!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!!!!!!+??!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!??!!!!!!!!!!!!??!!!!??!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!? ?!!!!!!!!!!!!!!!!??!??!!!!!!!!!!!!!!!!!!!!!??!!!!!!!!!!!!!!!!!!!??!!!!!?
This converts to
@echo off echo hello world!
Multi version translator
This Python script supports translating the major versions of !!!Batch into ASCII. It doesn't support use of Batch as a meta-language while being translated.
import argparse
lowerbet = ('abcdefghijklmnopqrstuvwxyz', '')
middlebet13 = ('& ?!\/.:0123456789|', '')
middlebet15 = ('& ?!%/.:0123456789=+-<>@*', '-')
upperbet = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ', '+')
version_bets = {
'1.3': [(lowerbet[0] + middlebet13[0], '')],
'1.5': [(lowerbet[0] + middlebet15[0], ''), upperbet],
'2.0': [lowerbet, middlebet15, upperbet]
}
def translate(s, version='2.0'):
for bet, symbol in version_bets[version]:
for i, c in enumerate(bet):
s = s.replace('?' + '!' * (i + 1) + symbol + '?', c)
return s
def main():
parser = argparse.ArgumentParser()
parser.add_argument('source')
parser.add_argument('--output', '-o', default='runscript.bat')
parser.add_argument('--std', '-s',
choices=version_bets.keys(), default='2.0'
)
args = parser.parse_args()
with open(args.source) as f:
s = f.read()
s = translate(s, args.std)
with open(args.output, 'w') as f:
f.write(s)
if __name__ == '__main__':
main()