Filth
Filth (a recursive acronym meaning Filth is [a] Lame Turing Hack) is a lame Turing hack. It is a concept esoteric programming language created by Brandon Zimmerman (User:Dev squid) in 2010, and is inspired by Befunge and Forth. It is based around a hypothetical stack machine (called a 'Filth Machine'). An interpreter was created by User:Madk in July 2010.
Style
Filth is a language with somewhat of a personality; that is, it hates you, your mother, your future and/or existing posterity, your cat, and your guts. It forces you, the Filth programmer, to construct arithmetic and bitwise logic statements with only NOR logic. A healthy Filth Machine uses a Harvard architecture; that is, code and data are contained in two separate memory spaces. There is an additional stack called the 'command stack' which can be used to store commands for later execution. What makes Filth unique is that both command and data spaces are stack-based, allowing command-space code to be operated upon exactly like normal stack data. The Filth stacks are LIFO stacks. A Filth Machine's native word size is 8-bits wide; however, to simplify its design, the command stack is based on units of commands, not any particular length of data, much in the same way the base unit in Redcode is a line, not a specific unit of data like a byte. It should also be noted here that the actual code space is not a stack, but is a linear array of read-only instructions.
Syntax
As the result of a syntactical indecision by the author, Filth can have one of two syntaxes: one with a mnemonic-and-operand syntax à la Assembly, and one with single-character operators à la Brainfuck. With the former, code structure is a bit more imposed, whereas with the latter, there are no syntactical rules and foreign characters are ignored, making it easier to write a parser for. For the sake of simplicity, only the latter syntax will be explained here.
Operators
First, to help defining the operators, the notation X has to be defined.
- X will always denote one hexadecimal character* denoting its hexadecimal value (e.g. A will denote 10).
- XX will always denote two hexadecimal characters* denoting their hexadecimal value (A0 will denote 160).
- D denotes a non-zero decimal character denoting its decimal value (e.g. 5 denoting 5).
- AAA denotes a string of up-to-three alphanumeric characters (a-z, A-Z and 0-9). Case insensitive.
* Both uppercase and lowercase hexadecimal characters can be used
When operators evaluate booleans, by definition any non-zero byte is considered true, and zero is considered false. When operators push booleans to stack, 01(hex) is used as the value for true.
_ - (nop) no operation. XX - (push) pushes the literal constant XX or onto the data stack. [push xx] + - (dup) duplicates the top byte on the data stack, pushing a copy of the top byte onto the data stack. [pop a, push a, push a] :D - (swap) swaps the top two units of size D bytes on the data stack; [pop a, pop b, push a, push b] ;D - (conditional swap) pops a Boolean value, then swaps the top two units of size D bytes on the data stack if the Boolean value is true. [pop a, if a { pop b, pop c, push b, push c }] $ - (del) discards the top byte from the data stack. [pop a] @ - (rot) rotates the top three bytes on the data stack, shifting the third-to-last byte to the top of the stack and shifting the top two bytes on the data stack down. [pop a, pop b, pop c, push b, push a, push c] ~ - (nor) performs bitwise nor of the top two bytes on the data stack and pushes the result onto the data stack. [pop a, pop b, push (a nor b)] ! - (absolute comp) compares the top two bytes on the data stack; if equal, push Boolean true onto the data stack, otherwise false. [pop a, pop b, push (a == b)] ? - (relative comp) compares the top two bytes on the data stack; if the second-to-last byte is less than the last byte, push Boolean true onto the data stack, otherwise false. [pop a, pop b, push (b < a)] /C - (cmd push) pushes the command 'C' onto the command stack. \D - (cmd pop) first pops the top D commands from the command stack and then executes them in order. -C - (cmd do) executes the command 'C', but operates on the command stack rather than the data stack; valid operands are '_', '+', ':D', ';D', '$', and '@'; any control Booleans are still pushed to and popped from the data stack. *AAA - (def label) defines the label AAA, holding the current place in the code stream. If label is already defined, it overwrites the existing definition. ^AAA - (jump label) pops a Boolean value, then jumps to the defined label AAA if the Boolean value is true. Labels are defined runtime when passing *AAA. If the boolean value is false, the program should not crash if the label does not exist yet. . - (output) pop an ASCII value from the data stack and prints it to standard output. [pop a, stdout a] , - (input) waits for an ASCII value from standard input and pushes on onto the stack. [stdin a, push a] # - (terminate) terminates the program. If it is popped from the command stack using \D, where D > 1 and it would be followed by any operations, do not execute the operations after. # must terminate the program immediately. q - (quine-ify) print 'q#'.
Furthermore, all listed implementations also support comments that are enclosed by two '|' (pipe) characters.
Computational Class
Currently, no tests have been conducted to test whether or not Filth is Turing-complete, and so will be considered non-computable until further research proves otherwise. Since stack machines and NOR logic can be proven to be Turing-complete, it can be hypothesized that Filth may be Turing-complete.
Examples
Cat:
*lp,.FF^lp#
0021646C726F77202C6F6C+6548*lp+.^lp#
q#
Programming in Filth
The notation (x => y) when used in this section means that the code defined here takes x from the stack, and puts y on the stack. x and y may be replaced by a more descriptive label.
Swap organization
Reflect top n (abc...yz becomes zy...cba)
n | Filth code |
---|---|
2 | :1 |
3 | :1@ |
4 | :1:2:1 |
5 | 00:1@@:3:1:2:1$ |
6 | :1@:3:1@ |
7 | 00@@:1:2:400:1@@:3:1:2:1$$ |
Swap top with n-th from top (e.g. if n=4 abcd becomes dbca)
n | Filth code |
---|---|
2 | :1 |
3 | :1@ |
4 | @:2:1 |
5 | 00:3@:3@@:1:2:3@@:3$ |
6 | :3@:3@:2:1:3@@:3 |
7 | 00:4@:2:1:4@@00:3@:3@@:1:2:3@@:3$@:4@:2:1:4$ |
Boolean operations
00 is false, all other is true; This is how this section handles input. Output will be 00 for false, 01 for true.
If the stack contains a 00, it stays a 00. If not, it becomes a 01. (Not a boolean op, just a pattern important to recognize.
00!FE~
Boolean NOT
00!FE~FE~FE~FE~
Boolean OR
00!FE~:100!FE~~FE~FE~FE~
Boolean AND
00!FE~:100!FE~FE~:1FE~~FE~FE~
Boolean NOR
00!FE~:100!FE~~FE~FE~
Using generator to generate Filth code
Generator is a very uniquely named tool that can help with writing code in a subset of esolang types, including Filth. Get generator from Gitea (right now, you'll need to build from source, so you need nim and a c compiler installed, and build with "nim c main.nim"). You can find a "stdlib" - many filth "procedures" to make your life easier in the stdlib folder on Gitea next to the newer interpreter.
All operations and examples are included, and more. Read the readme of generator on git to learn more about generator, and read the contents of the .gen files to learn more about what is provided.
External resources
Interpreters:
Download interpreter Specifics:
- Written in a variant of BlitzBasic
- Source-available, binary available for Microsoft Windows
- Supports comments