Update
This commit is contained in:
parent
4bff69ec4a
commit
8e2f22bfc7
20 changed files with 1913 additions and 1808 deletions
108
brainfuck.md
108
brainfuck.md
|
@ -94,8 +94,6 @@ int main(void)
|
|||
}
|
||||
```
|
||||
|
||||
TODO: brainfuck to C translator
|
||||
|
||||
TODO: comun implementation
|
||||
|
||||
Advanced Brainfuck implementations may include [optimizations](optimization.md), for example things like `>>><<>` may be reduced to `>>` etc.
|
||||
|
@ -167,7 +165,9 @@ Read two 0-9 numbers (as ASCII digits) and add them:
|
|||
,>,[<+>-]<------------------------------------------------.
|
||||
```
|
||||
|
||||
TODO: more
|
||||
## Variants
|
||||
|
||||
TODO
|
||||
|
||||
## Making Brainfuck Usable: Defining Macrofucker
|
||||
|
||||
|
@ -180,7 +180,7 @@ Hmmm okay, what name do we give the language? Let's call it **Macrofucker**. It
|
|||
- Vanilla Brainfuck commands work normally, they'll be simply copied.
|
||||
- Additionally we introduce macros. A macro will be defined as: `:M<commands>;`. `:` and `;` are simply keywords separating the macro definition, `M` is the macro name, which we'll for simplicity sake limit to single uppercase letters only (so we won't be able to make more macros than there are letters), and `<commands>` are just commands that will be copy-pasted wherever the macro is used.
|
||||
- A macro will be used by simply writing its name, i.e. if we have macro `M` defined (anywhere in the source code), we can use it by simply writing `M`. Optionally we may call it with numeric parameter as `MX`, where `X` is a decimal number. If no parameter is given, we consider it 0. Macro may be invoked even inside another macro.
|
||||
- Inside a macro definition we may use the symbol `$` that will repeat the next character by the macro's parameter number of times.
|
||||
- Inside a macro definition we may use the symbol `$` that will make the next character be repeated the macro's argument number of times -- i.e. if the macro was called with let's argument 3, then `$>` will output `>>>`. This symbol can also be used in the same sense in front of macro invocation.
|
||||
|
||||
For example consider the following piece of code:
|
||||
|
||||
|
@ -237,9 +237,8 @@ void process(const char *c, int topLevel)
|
|||
char f = *c; // macro name to search
|
||||
unsigned int n = 0; // macro argument
|
||||
|
||||
if (!topLevel)
|
||||
if (!topLevel) // read the argument
|
||||
{
|
||||
// read argument
|
||||
c++;
|
||||
|
||||
while (*c >= '0' && *c <= '9')
|
||||
|
@ -249,13 +248,14 @@ void process(const char *c, int topLevel)
|
|||
}
|
||||
}
|
||||
|
||||
#define IS_MACRO(x) ((x) >= 'A' && (x) <= 'Z')
|
||||
c = program;
|
||||
|
||||
while (*c) // search for the macro
|
||||
while (*c) // search for the macro definition
|
||||
{
|
||||
if (topLevel || (c[0] == ':' && c[1] == f))
|
||||
{
|
||||
c += topLevel ? 0 : 2; // skip the beginning macro chars
|
||||
c += topLevel ? 0 : 2; // skip the beginning macro chars
|
||||
|
||||
while (*c && *c != ';')
|
||||
{
|
||||
|
@ -264,13 +264,13 @@ void process(const char *c, int topLevel)
|
|||
else if (*c == '+' || *c == '-' || *c == '<' || *c == '>' ||
|
||||
*c == '[' || *c == ']' || *c == '.' || *c == ',')
|
||||
putchar(*c); // normal BF commands
|
||||
else if (*c >= 'A' && *c <= 'Z')
|
||||
else if (IS_MACRO(*c))
|
||||
process(c,0); // macro
|
||||
else if (*c == '$')
|
||||
{
|
||||
c++;
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
putchar(*c);
|
||||
IS_MACRO(*c) ? process(c,0) : putchar(*c);
|
||||
}
|
||||
|
||||
c++;
|
||||
|
@ -286,19 +286,97 @@ void process(const char *c, int topLevel)
|
|||
int main(int argc, char **argv)
|
||||
{
|
||||
process(program,1);
|
||||
putchar(0); // allows separating program on stdin from program input
|
||||
// puts("013"); // program input may go here
|
||||
putchar(0); // allows separating program on stdin from program input
|
||||
//puts("013"); // program input may go here
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
The main program we have here is the example program from the [algorithm](algorithm.md) article: it reads a number, prints the number of its divisors and says if the number is [prime](prime.md). Code of the Brainfuck program will be simply printed out on standard output and it can then be run using our Brainfuck interpreter above. Unlike "hello world" this is already a pretty cool problem we've solved with Brainfuck, and we didn't even need that much code to make it happen. Improving this further could allow us to make a completely usable (though, truth be said, probably slow) language. Isn't this just beautiful? Yes, it is :)
|
||||
|
||||
## Variants
|
||||
So just for completeness, here is a Macrofucker program that prints out the first 10 [Fibonacci numbers](fibonacci_number.md):
|
||||
|
||||
TODO
|
||||
```
|
||||
:Z[-]; zero the cell
|
||||
:L$<; go left by n
|
||||
:R$>; go right by n
|
||||
:XZ$+; store constant n
|
||||
:N>Z+<[Z>-<]>[<$++>Z]<; not
|
||||
:CZ>Z<<$<[-$>>+>+<$<<]$>>>[-<$<<+>>$>]<; copy
|
||||
:F>Z<[->+<]<$<[->$>+<$<]$>>>[-<<$<+>>$>]<; flip
|
||||
:A>C1[-<+>]<; add
|
||||
:S>C1[-<->]<; subtract
|
||||
:GZ>C2>C2+<[->->CN[L3+R3Z]<<]<; greater
|
||||
:B>C1>C1<<Z>>>GN[L3+>>S>GN]<F<; divide
|
||||
:P>X100>C1BF>X48A.L3X10>BF>X48A.<F>X48A.L4; print
|
||||
|
||||
main program
|
||||
|
||||
>X10 loop counter
|
||||
>X0 first number
|
||||
>X1 second number
|
||||
<<
|
||||
|
||||
[- loop
|
||||
R3
|
||||
C1 A copy and add
|
||||
P > X10 . print number and newline
|
||||
< F < F << go back and shift numbers
|
||||
]
|
||||
```
|
||||
|
||||
which translates to:
|
||||
|
||||
```
|
||||
>[-]++++++++++>[-]>[-]+<<[->>>[-]>[-]<<<[->>+>+<<<]>>>[-<<<
|
||||
+>>>]<>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<[-<+>]<>[-]++++++
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+++++++++++++++++++++++++++++++++++>[-]>[-]<<<[->>+>+<<<]>>
|
||||
>[-<<<+>>>]<>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<>[-]>[-]<<<
|
||||
[->>+>+<<<]>>>[-<<<+>>>]<<<[-]>>>[-]>[-]>[-]<<<<[->>>+>+<<<
|
||||
<]>>>>[-<<<<+>>>>]<>[-]>[-]<<<<[->>>+>+<<<<]>>>>[-<<<<+>>>>
|
||||
]<+<[->->[-]>[-]<<[->+>+<<]>>[-<<+>>]<>[-]+<[[-]>-<]>[<+>[-
|
||||
]]<[<<<+>>>[-]]<<]<>[-]+<[[-]>-<]>[<+>[-]]<[<<<+>>>[-]>[-]<
|
||||
<<[->>+>+<<<]>>>[-<<<+>>>]<[-<->]<>[-]>[-]>[-]<<<<[->>>+>+<
|
||||
<<<]>>>>[-<<<<+>>>>]<>[-]>[-]<<<<[->>>+>+<<<<]>>>>[-<<<<+>>
|
||||
>>]<+<[->->[-]>[-]<<[->+>+<<]>>[-<<+>>]<>[-]+<[[-]>-<]>[<+>
|
||||
[-]]<[<<<+>>>[-]]<<]<>[-]+<[[-]>-<]>[<+>[-]]<]<>[-]<[->+<]<
|
||||
[->+<]>>[-<<+>>]<<>[-]<[->+<]<[->+<]>>[-<<+>>]<>[-]++++++++
|
||||
++++++++++++++++++++++++++++++++++++++++>[-]>[-]<<<[->>+>+<
|
||||
<<]>>>[-<<<+>>>]<[-<+>]<.<<<[-]++++++++++>>[-]>[-]<<<[->>+>
|
||||
+<<<]>>>[-<<<+>>>]<>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<<<[-
|
||||
]>>>[-]>[-]>[-]<<<<[->>>+>+<<<<]>>>>[-<<<<+>>>>]<>[-]>[-]<<
|
||||
<<[->>>+>+<<<<]>>>>[-<<<<+>>>>]<+<[->->[-]>[-]<<[->+>+<<]>>
|
||||
[-<<+>>]<>[-]+<[[-]>-<]>[<+>[-]]<[<<<+>>>[-]]<<]<>[-]+<[[-]
|
||||
>-<]>[<+>[-]]<[<<<+>>>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<[-
|
||||
<->]<>[-]>[-]>[-]<<<<[->>>+>+<<<<]>>>>[-<<<<+>>>>]<>[-]>[-]
|
||||
<<<<[->>>+>+<<<<]>>>>[-<<<<+>>>>]<+<[->->[-]>[-]<<[->+>+<<]
|
||||
>>[-<<+>>]<>[-]+<[[-]>-<]>[<+>[-]]<[<<<+>>>[-]]<<]<>[-]+<[[
|
||||
-]>-<]>[<+>[-]]<]<>[-]<[->+<]<[->+<]>>[-<<+>>]<<>[-]<[->+<]
|
||||
<[->+<]>>[-<<+>>]<>[-]+++++++++++++++++++++++++++++++++++++
|
||||
+++++++++++>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<[-<+>]<.<>[-
|
||||
]<[->+<]<[->+<]>>[-<<+>>]<>[-]+++++++++++++++++++++++++++++
|
||||
+++++++++++++++++++>[-]>[-]<<<[->>+>+<<<]>>>[-<<<+>>>]<[-<+
|
||||
>]<.<<<<>[-]++++++++++.<>[-]<[->+<]<[->+<]>>[-<<+>>]<<>[-]<
|
||||
[->+<]<[->+<]>>[-<<+>>]<<<]
|
||||
```
|
||||
|
||||
which outputs:
|
||||
|
||||
```
|
||||
001
|
||||
001
|
||||
002
|
||||
003
|
||||
005
|
||||
008
|
||||
013
|
||||
021
|
||||
034
|
||||
055
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [False](false.md) (a very similar esolang)
|
||||
- [comun](comun.md)
|
||||
- [comun](comun.md)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue