TLDR Brainfuck! Mixins are a powerful collection of modular BF! code that is used via the {{mixinLabel}}
format.
A common pain point (in some ways intentional) has been doing "basic" stuff that you take for granted in higher level languages like C++.
The intent of the ABF Corp is NOT to dilute the purity of the BF! language by adding more opcodes. Instead, we take a transpilation/mixin approach.
Mixins are formatted in ABF like the following:
{{mixinLabel:param1:...:paramX}}
{{
and }}
denote the start and end of a mixin. The first string in the mixin is used to identify the mixin used. :
is used to provide optional parameters to the mixin.
Example:
{{3}}
{{eq:3}}
Transpiles to:
[-]+++
>[-]<>>[-]<<[>+<>>+<<-]>>[<<+>>-]<<>--->[-]+<[>[-]<-]>[<+>-]<
Note: If you do not need to provide any parameters to the mixin, omit :
.
The SML actually stands for Standard Mixin Library and is the default collection of mixins provided by the ABF Corp. As the Corp continues to research the nature of mixins, the SML will grow with new libraries.
The SML is composed of a few core libraries:
Sub libraries
To better allow corp members to use the SML, we will describe a few key design assumptions that the SML makes about your program design:
{{copy}}
leaves the data pointer where the value was copied to.){{add:3}}
puts the result into the cell to the right of the data pointer.)In the doc you will see "data pointer after execution: ..." this refers to where you should expect the data pointer to be after the mixin, relative to where it was right before the mixin.
Numbers is a simple library that enables easy creation of numerical constants.
This library contains 256 mixins for all values between 0-255.
Numbers mixin replaces the current data cell with the provided numerical constant.
Example:
{{3}}
{{255}}
The debug library provides helpful logging utilities.
{{log:startIndex:endIndex}}
outputs the data cells between startIndex and endIndex (inclusive).
Params
data pointer after execution: at endIndex
{{logValue:hexStr}}
logs the provided hex string.
Params
data pointer after execution: unchanged
The memory library provides a number of utility functions to easily manipulate the data tape.
{{constants:byteString}}
starting from the current data pointer, sets the bytes provided (byteString) into the data tape, shifting to the right for each byte provided.
Params
data pointer after execution: leaves you on the right most cell with the last byte from the byteString
Example
{{constants:0xFF00FF33}}
DATA TAPE:
0xff 00 ff 33 00 • (DATA PTR AT 4)
{{jump:delta}}
jumps the current data pointer to the right or left based on the provided delta value.
Params
data pointer after execution: data pointer + delta
Example
{{jump:5}}+{{jump:-4}}++
DATA TAPE:
0x00 02 00 00 00 01 • (DATA PTR AT 1)
{{move:delta}}
moves the value at the current data pointer by delta value to a new data cell.
Params
data pointer after execution: data pointer + delta
Example
{{3}}{{move:2}}
DATA TAPE:
0x00 00 03 00 • (DATA PTR AT 2)
{{copy:delta:temporaryDelta}}
copies the value at the current data pointer by delta value to a new data cell.
Params
data pointer after execution: data pointer + delta
Example
{{3}}{{copy}}
DATA TAPE:
0x03 03 00 00 • (DATA PTR AT 1)
Example with delta
{{3}}{{copy:2}}
DATA TAPE:
0x03 00 03 00 • (DATA PTR AT 2)
Example with delta + temporaryDelta
{{3}}{{copy:3:1}}
DATA TAPE:
0x03 00 00 03 • (DATA PTR AT 3)
{{skipInputs:value}}
skips the first X amount of bytes provided.
Params
data pointer after execution: unchanged
The math library provides simple integer math functions. (WIP, more functions to come)
{{add:value}}
sums the current value at data pointer with provided constant or the value to the left of the data pointer.
Params
data pointer after execution: Shifts to the right one data cell
Example with constant
{{3}}{{add:5}}
DATA TAPE:
0x03 08 00 • (DATA PTR AT 1)
Example without constant
{{3}}>{{5}}{{add}}
DATA TAPE:
0x03 05 08 00 • (DATA PTR AT 2)
{{sub:value}}
subtracts the current value at data pointer with provided constant. If no parameter is provided, gives the result of (current data cell - left shift data cell)
Params
data pointer after execution: Shifts to the right one data cell
Example with constant
{{3}}{{sub:2}}
DATA TAPE:
0x03 01 00 • (DATA PTR AT 1)
Example without constant
{{3}}>{{4}}{{sub}}
DATA TAPE:
0x03 04 01 00 • (DATA PTR AT 2)
Example with underflow
{{3}}{{sub:4}}
DATA TAPE:
0x03 ff 00 • (DATA PTR AT 1)
{{absSub:value}}
gets the absolute value difference between two values. If parameter is provided, finds the abs(data cell - value). If no parameter provided, finds the abs(data cell - left data cell).
Params
data pointer after execution: Shifts to the right one data cell
Example with constant
{{3}}{{absSub:2}}
DATA TAPE:
0x03 01 00 • (DATA PTR AT 1)
Example without constant
{{3}}>{{4}}{{sub}}
DATA TAPE:
0x03 04 01 00 • (DATA PTR AT 2)
{{flippedSub:value}}
behaves just like {{sub}}
but flips the values, i.e (instead of A - B, it is B - A). Subtracts the provided constant by value at data pointer. If no parameter is provided, gives the result of (left shift data cell - current data cell)
Params
data pointer after execution: Shifts to the right one data cell
Example with constant
{{3}}{{flippedSub:5}}
DATA TAPE:
0x03 02 00 • (DATA PTR AT 1)
Example without constant
{{3}}>{{2}}{{flippedSub}}
DATA TAPE:
0x03 02 01 00 • (DATA PTR AT 2)
Example with underflow
{{3}}{{flippedSub:2}}
DATA TAPE:
0x03 ff 00 • (DATA PTR AT 1)
The conditional library provides boolean utilities and functions.
{{true}}
sets the current data cell to the value 1.
data pointer after execution: no change
Example
{{true}}
DATA TAPE:
0x01 00 • (DATA PTR AT 0)
{{false}}
sets the current data cell to the value 0.
data pointer after execution: no change
Example
{{false}}
DATA TAPE:
0x00 00 • (DATA PTR AT 0)
{{flip}}
flips the boolean state of the current data cell.
data pointer after execution: no change
Example
{{false}}{{flip}}
DATA TAPE:
0x01 00 • (DATA PTR AT 0)
{{not}}
alias: {{!}}
behaves just like {{flip}}
, but leaves current data cell unchanged
data pointer after execution: Shifts to the right one data cell
Example
{{false}}{{not}}
DATA TAPE:
0x00 01 00 • (DATA PTR AT 1)
{{boolify}}
if current data cell is non zero, set it to {{true}}
, otherwise set it to {{false}}
.
data pointer after execution: no change
Example
{{5}}{{boolify}}
DATA TAPE:
0x01 00 00 • (DATA PTR AT 0)
Example with zero
{{0}}{{boolify}}
DATA TAPE:
0x00 00 00 • (DATA PTR AT 0)
{{and}}
AND boolean logic with the current data cell and the data cell to the left.
data pointer after execution: Shifts to the right one data cell
Example
{{true}}>{{true}}{{and}}
DATA TAPE:
0x01 01 01 • (DATA PTR AT 2)
Example with true and false
{{true}}>{{false}}{{and}}
DATA TAPE:
0x01 00 00 • (DATA PTR AT 2)
{{or}}
OR boolean logic with the current data cell and the data cell to the left.
data pointer after execution: Shifts to the right one data cell
Example
{{true}}>{{false}}{{or}}
DATA TAPE:
0x01 00 01 • (DATA PTR AT 2)
Example with false and false
{{false}}>{{false}}{{or}}
DATA TAPE:
0x00 00 00 • (DATA PTR AT 2)
{{eq:value}}
alias: {{==:value}}
equality operator. Checks if current data cell is equal to provided parameter. If no parameters provided, checks equality with data cell to the left.
Params
data pointer after execution: Shifts to the right one data cell
Example
{{5}}{{==:5}}
DATA TAPE:
0x05 01 00 • (DATA PTR AT 1)
Example with no parameters
{{5}}>{{5}}{{eq}}
DATA TAPE:
0x05 05 01 • (DATA PTR AT 2)
{{notEq:value}}
alias: {{!=:value}}
inequality operator. Checks if current data cell is not equal to provided parameter. If no parameters provided, checks inequality with data cell to the left.
Params
data pointer after execution: Shifts to the right one data cell
Example
{{5}}{{!=:6}}
DATA TAPE:
0x05 01 00 • (DATA PTR AT 1)
Example with no parameters
{{5}}>{{6}}{{notEq}}
DATA TAPE:
0x05 06 01 • (DATA PTR AT 2)
{{lessThan:value}}
less than operator. Checks if current data cell is less than provided parameter. If no parameters provided, checks if less than data cell to the left.
Params
data pointer after execution: Shifts to the right one data cell
Example
{{5}}{{lessThan:6}}
DATA TAPE:
0x05 01 00 • (DATA PTR AT 1)
Example with no parameters
{{5}}>{{6}}{{lessThan}}
DATA TAPE:
0x05 06 01 • (DATA PTR AT 2)
{{greaterThan:value}}
greater than operator. Checks if current data cell is greater than provided parameter. If no parameters provided, checks if greater than data cell to the left.
Params
data pointer after execution: Shifts to the right one data cell
Example
{{5}}{{greaterThan:4}}
DATA TAPE:
0x05 01 00 • (DATA PTR AT 1)
Example with no parameters
{{5}}>{{4}}{{greaterThan}}
DATA TAPE:
0x05 04 01 • (DATA PTR AT 2)
{{greaterThanOrEq:value}}
greater than or equal operator. Checks if current data cell is greater than or equal provided parameter. If no parameters provided, checks if greater than or equal data cell to the left.
Params
data pointer after execution: Shifts to the right one data cell
Example
{{5}}{{greaterThanOrEq:4}}
DATA TAPE:
0x05 01 00 • (DATA PTR AT 1)
Example with no parameters
{{4}}>{{4}}{{greaterThanOrEq}}
DATA TAPE:
0x04 04 01 • (DATA PTR AT 2)
{{lessThanOrEq:value}}
less than or equal operator. Checks if current data cell is less than or equal provided parameter. If no parameters provided, checks if less than or equal data cell to the left.
Params
data pointer after execution: Shifts to the right one data cell
Example
{{3}}{{lessThanOrEq:4}}
DATA TAPE:
0x03 01 00 • (DATA PTR AT 1)
Example with no parameters
{{4}}>{{4}}{{lessThanOrEq}}
DATA TAPE:
0x04 04 01 • (DATA PTR AT 2)
The control library provides basic if/conditional statement functionality.
{{if:conditionalMixin:...params}}
If {{conditionalMixin}}
is true, proceed with code block between this mixin and {{ifEnd}}
, if false, ignore logic and jump to {{ifEnd}}
.
{{if}}
reserves a data cell to track stateful logic; if condition is true, the data pointer is shifted two times to the right from where it was before the mixin was executed.
NOTE: If the code block between {{if}} and {{ifEnd}} is executed, at the end of the code block, the data pointer must be unchanged (i.e return it to where it was before).
Params
data pointer after execution: shifted to the right by 2 (requires an extra data cell for state)
Example
{{3}}{{if:==:3}}+<<++>>{{ifEnd}}
DATA TAPE:
0x05 00 01 • (DATA PTR AT 0)
Example with condition not met
{{3}}{{if:==:4}}+<<++>>{{ifEnd}}
DATA TAPE:
0x03 00 00 • (DATA PTR AT 0)
Example with eq (2 dynamic values)
{{5}}>{{4}}}{{if:==}}+<<++>>{{ifEnd}}
DATA TAPE:
0x05 04 00 • (DATA PTR AT 1)
{{ifEnd}}
closes the code block that is executed if the conditions are met.
data pointer after execution: unchanged (data pointer back to where it was before if)
The loop library provides conditional based loop logic.
{{repeat:num}}
repeats the code block between {{repeat}} and {{repeatEnd}} num times. If no parameter provided, loops the value in current data cell times.
{{repeat}}
reserves a data cell to track stateful logic; the data pointer is shifted two times from where it was before the mixin was executed.
NOTE: At the end of the code block, the data pointer must be unchanged (i.e return it to where it was before).
Params
data pointer after execution: shifted to the right by 2 (requires an extra data cell for state)
Example
{{repeat:4}}++{{repeatEnd}}
DATA TAPE:
0x00 00 08 • (DATA PTR AT 0)
Example with no params
{{4}}{{repeat:4}}++{{repeatEnd}}
DATA TAPE:
0x04 00 08 • (DATA PTR AT 0)
{{repeatEnd}}
closes the repeat logic that is executed.
data pointer after execution: unchanged (data pointer back to where it was before repeat)
{{while:conditionalMixin:...params}}
repeats the code between {{while}} and {{whileEnd}} if {{conditionalMixin}}
is met.
{{while}}
reserves 5 data cells to track stateful logic; the data pointer is is shifted six times from where it was before the mixin was executed.
NOTE: At the end of the code block, the data pointer must be unchanged (i.e return it to where it was before).
Params
data pointer after execution: shifted to the right by 6 (requires 5 data cells for state)
Example
{{while:lessThan:4}}+++{{jump:-6}}+{{jump:6}}{{whileEnd}}
DATA TAPE:
0x04 00 00 00 00 00 0c 00 • (DATA PTR AT 0)
{{whileEnd}}
closes the logic that is executed in while loop.
data pointer after execution: unchanged (data pointer back to where it was before while)
{{for:constant:conditionalMixin:...params}}
instantiates a "looped value" and repeats the code between {{for}} and {{forEnd}} if {{conditionalMixin}}
is met.
{{for}}
reserves 5 data cells to track stateful logic; the data pointer is is shifted six times from where it was before the mixin was executed.
{{forEnd}}
takes a parameter that changes the looped value.
NOTE: At the end of the code block, the data pointer must be unchanged (i.e return it to where it was before).
Params
data pointer after execution: shifted to the right by 6 (requires 5 data cells for state)
Example
{{for:1:lessThan:4}}+++{{forEnd:1}}
DATA TAPE:
0x00 00 00 00 00 00 00 09 • (DATA PTR AT 0)
Example with no constant
{{1}}{{for::lessThan:4}}+++{{forEnd:1}}
DATA TAPE:
0x01 00 00 00 00 00 00 09 • (DATA PTR AT 0)
{{forEnd:delta}}
closes the for logic and changes looped value after each iteration.
Params
data pointer after execution: unchanged (data pointer back to where it was before for)
The storage library provides a basic register + storage programming model.
The first 32 are used as registers; data cells that are used for computation with the expectation that any data stored in registers can be overwritten in later computation. Data cells after 32 "registers" are only accessible via read or write mixins; designed for storing the results of computation.
{{jumpToStorageSlots}}
jumps the current data pointer to the start of the storage data cells.
data pointer after execution: data cell index 33
Example
{{jumpToStorageSlots}},
DATA TAPE:
0x00 • (DATA PTR AT 32)
{{store:writeFromIndex:slotIndex}}
stores the value at writeFromIndex into data slotIndex.
Params
data pointer after execution: writeFromIndex
Example
{{3}}{{store:0:0}}
DATA TAPE:
0x03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 • (DATA PTR AT 0)
{{read:readIntoIndex:slotIndex}}
reads the value at data slotIndex into readIntoIndex.
Params
data pointer after execution: readIntoIndex
Example
{{3}}{{store:0:0}}{{read:2:0}}
DATA TAPE:
0x03 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 • (DATA PTR AT 2)
{{logStorage:fromSlotIndex:toSlotIndex}}
outputs the stored values fromSlotIndex - toSlotIndex.
Params
data pointer after execution: readIntoIndex
Ready to join the ABF Corps?
JOIN NOWREAD DOCS