Braingolf

From Esolang
Jump to navigation Jump to search

Braingolf is a stack-based esoteric language designed by Programming Puzzles and Code-Golf user, Mayube. The name originates from brainfuck, as it was the original inspiration for the language, however the language differs greatly to brainfuck and is more comparable to Fish, despite not being a two-dimensional language.

Braingolf's parser is written in Python 3, and can be found on Braingolf's GitHub page.

Description

The language, like many stack-based golfing languages, consists of a series of single-symbol instructions which manipulate the stack.

Every symbol in Braingolf falls into one of 3 categories: Operators, Modifiers and Literals.

Operators perform a function, usually involving manipulating the stack in some way.

Modifiers alter the functionality of the next Operator.

Literals act as they do in most languages, simply pushing the value of the literal to the stack.

There are also a subset of Operators known as Functions. There are no clearly defined rules on what separates Functions from other Operators, other than the symbol used. Functions use a-z and A-Z, whilst Operators use non-alphabetic symbols.

Mayube himself has pointed out on the readme for Braingolf that Functions are officially no different to Operators, stating:

   Functions are essentially fancy operators that do slightly more complex things
   but I like to give them a different name so they can be special snowflakes

Braingolf also includes several Flow-Control symbols, used for conditionals and loops.

Tutorial

Braingolf stores all data on a single, integer-based stack. It actively attempts to convert any data pushed to the stack to an integer format, which can cause TypeErrors when attempting to work with non-numeric data.

In most cases, when Braingolf attempts to push a string to the stack, it will convert each character to it's corresponding Unicode char code, and push each char code to the stack separately.

Upon reaching the end of the code, Braingolf will implicitly print the last item of the stack.

In Braingolf's documentation, unlike in most stack-based languages, the stack is referred to as a horizontal list, rather than a vertical stack. As such end or last refers to the top of the stack, while start or first refers to the bottom of the stack.

Operators

Braingolf, as of v0.4, includes 15 Operators, some of these Operators have slightly different functionality. Depending on the number of items in the stack they will either be Niladic (empty stack), Monadic (one item in stack) or Diadic (more than one item in stack)

Niladic

This is the behaviour of each operator when the stack is empty.

   +    - Throws an IndexError
   -    - Throws an IndexError
   *    - Throws an IndexError
   /    - Throws an IndexError
   ^    - Throws an IndexError
   %    - Throws an IndexError
   _    - Throws an IndexError
   =    - Prints the stack
   @    - Throws an IndexError
   <    - Does nothing
   >    - Does nothing
   .    - Throws an IndexError
   ,    - Does nothing
   {    - Waits for input from STDIN, pushes input to the end of the stack
   ;    - Prevents Braingolf implicitly printing on termination

Functions:

   l    - Pushes 0 to the stack
   d    - Throws an IndexError
   s    - Throws an IndexError
   r    - Pushes 0 to the stack
   V    - Creates a new stack and switches to it
   v    - Switches to the next stack
   c    - Collapses the current stack into the 0th stack
   M    - Move the top of the current stack to the top of the next stack
   m    - Move the bottom of the current stack to the top of the next stack
   R    - Make the 0th (main) stack the current stack
   p    - Pop the top and push all of its prime factors
   u    - Convert the current stack to a set by discarding all but the first occurrence of each item
   X    - Push max(stack)
   x    - Push min(stack)

Monadic

This is the behaviour of each operator when the stack contains a single item.

   +    - Pops the item from the stack and pushes the item doubled
   -    - Pops the item from the stack and pushes 0
   *    - Pops the item from the stack and pushes the item ^2
   /    - Pops the item from the stack and pushes 1
   ^    - Pops the item from the stack and pushes the item ^ the item
   %    - Pops the item from the stack and pushes 0
   _    - Pops the item from the stack and prints it
   =    - Prints the stack
   @    - Pops the item from the stack, converts it to a character, and prints it
   <    - Does nothing
   >    - Does nothing
   .    - Duplicates the item in the stack
   ,    - Does nothing
   {    - Waits for input from STDIN, pushes input to the end of the stack
   ;    - Prevents Braingolf implicitly printing on termination

Functions:

   l    - Pushes 1 to the stack
   d    - Pops the last item of the stack, splits it into its separate digits, and pushes each digit back to the stack
   s    - Pops the last item of the stack, pushes 1 to the stack if the popped item is positive, -1 if it's negative, and 0 if it's 0
   r    - Pops the last item of the stack, pushes a random positive integer lower than the popped item to the stack
   V    - Creates a new stack and switches to it
   v    - Switches to the next stack
   c    - Collapses the current stack into the 0th stack

Diadic

This is the behaviour of each operator when the stack contains more than 1 item.

   +    - Pops the last 2 items from the stack and pushes the sum
   -    - Pops the last 2 items from the stack and pushes the last item subtracted from the 2nd to last
   *    - Pops the last 2 items from the stack and pushes the product
   /    - Pops the last 2 items from the stack and pushes the last item divided by the 2nd to last item, floored
   ^    - Pops the last 2 items from the stack and pushes the last item to the power of the 2nd to last item
   %    - Pops the last 2 items from the stack and pushes the last item modulo the 2nd to last item
   _    - Pops the last item from the stack and prints it
   =    - Prints the stack
   @    - Pops the last item from the stack, converts it to a character, and prints it
          If this operator is followed by a number, that many characters will be popped and printed.
   <    - Moves the first item in the stack to the end
   >    - Moves the last item in the stack to the start
   .    - Duplicates the last item in the stack
   ,    - Swaps the last 2 items in the stack
   {    - Waits for input from STDIN, pushes input to stack
   ;    - Prevents Braingolf implicitly printing on termination

Functions:

   l    - Pushes the current length of the stack to the stack
   d    - Pops the last item of the stack, splits it into its separate digits, and pushes each digit back to the stack
   s    - Pops the last item of the stack, pushes 1 to the stack if the popped item is positive, -1 if it's negative, and 0 if it's 0
   r    - Pops the last item of the stack, pushes a random positive integer lower than the popped item to the stack
   V    - Creates a new stack and switches to it
   v    - Switches to the next stack
   c    - Collapses the current stack into the 0th stack

Modifiers

Modifiers are symbols that alter the behaviour of the next valid operator. Not every modifier affects every operator, and a modifier once found will be "held" until a valid operator is reached, at which point the modifier will be applied to that operator.

   !    - Prevents the next operator from removing items it reads from the stack, known as "Safe" modifier
   &    - Causes the next operator to consume and process the entire stack, known as "Greedy" modifier
   $    - Prevents the next operator from printing to STDOUT, known as "Silent" modifier
   ~    - Causes the next operator to read from the start of the stack, not the end, known as "Reverse" modifier

In most cases, which modifiers work on which operators is a matter of common sense. For example the $ will not apply to an operator that does not print any output, and ! will not apply to an operator that does not pop items from the stack.

Below is a table showing every operator and what modifiers are valid for them:

X + - * / ^ % _ = @ < > . , { ; l d
! Y Y Y Y Y Y Y N Y N N N N N N N Y
& Y Y Y Y Y Y Y N Y N N N Y N N N N
$ N N N N N N Y N Y N N N N N N N N
~ Y Y Y Y Y Y Y N Y N N N N N N N Y

Literals

Any numerical symbol 0-9 in Braingolf is treated as a 1 digit integer literal, and pushed to the end of the stack, unless the number follows a @ symbol.

Due to Braingolf not supporting multi-digit integer literals, these must be inserted either by performing math functions on single-digit integers, or by finding a single unicode character with the desired char code, and using the # symbol to insert it.

For example:

91+ is a valid 10 literal (9 + 1), while 291+^ is a valid 100 literal ((9 + 1) ^ 2). #! is a valid 33 literal, and #!2* is a valid 66 literal.

Any character that follows a # is treated as a 1 character string literal, and it's unicode char code is pushed to the end of the stack.

Any characters contained within double quotes " " are treated as string literals, and each char code is pushed to the stack.

Flow Control

Braingolf has only very rudimentary flow control, in the form of simple conditionals, and simple loops.

Conditionals are formatted as follows:

   ?true code:false code|

The condition to be checked is always whether the last item in the stack is greater than 0

If you wish to do nothing when the condition is false, you may omit the else clause:

   ?true code|

If you wish to only act when the condition is false, you may omit contents to the if clause:

   ?:false code|

By default, the ? conditional will pop the last item from the stack when checking it's value, this can be negated with the ! operator.

While loops are also very simplistic in Braingolf, and are created using the [ and ] characters.

Everything within these characters is the body of the while loop, and will always run at least once.

Upon reaching the end of the loop, Braingolf will check the value of the first item of the stack. If the value is <= 0, the item will be popped and the loop exited. Otherwise the item will be decremented by 1, and the loop will run again.

Note: Braingolf does not support nested conditionals or nested loops, and "escaping" a : ], or | by placing it within a string literal (using # or " ") will not prevent the character from ending the conditional or loop. This can lead to unexpected behaviour.

Sample Code

Hello World

   "Hello World"&@

Prints Hello World

FizzBuzz

   #d[.#d-3,%?1:"Fizz"@4 0|<.#d,-5,%?>1:"Buzz"@4>0|+>1<-?.#d-_|#
   @];

Iterates through every number up to 100, prints Fizz if n % 3 == 0, Buzz if n % 5 == 0, FizzBuzz if both, and n if neither.

Fibonacci Sequence

   10!_1!_[!+!_#,@<1+>];

Endlessly prints comma separated Fibonacci numbers

Finite Fibonacci

   01[!+]=;

Takes an integer n input, fills the stack with fibonacci sequence up to the nth number, then prints the stack.

Quine

   "V#!1+!@R!@18v@R@18"V#!1+!@R!@18v@R@18

Outputs "V#!1+!@R!@18v@R@18"V#!1+!@R!@18v@R@18 by pushing the latter half of the program to the main stack as a string, switching to a new stack to print a quotation mark, returning to the main stack to print 18 characters from it (the entire string), switching back to the other stack to print another quotation mark, then back to the first stack to print the entire 18 character string again.