Minim

From Esolang
Jump to navigation Jump to search
Minim
Paradigm(s) Imperative
Designed by Christian Alexander
Appeared in 2017
Memory system Pointer-based
Computational class Bounded-Storage Machine
Major implementations Kotlin Interpreter
File extension(s) .min

About

Minim is a minimal, low-level, interpreted programming language designed by KakkoiiChris (formerly TheNewComposer). It was inspired by the minimal nature of other esolangs, with a memory access syntax inspired by python's index and slice notation, while retaining many of the standard operators that languages like C have, in order to be somewhat useful. While there is a bit of syntactical sugar here and there to make writing programs more developer friendly, the goal was always to have just barely enough language features so that it was still a reasonable challenge to do so.

History

Minim was originally developed for the final project of a high level college Java Programming class. The syntax used by the current stable implementation is the 5th version.

V1

Early grammars called for a Count Operator 'C', which returned the length of an array, and a Reverse Operator 'R', which reversed an array. Both were used in the original Hello World program, which was one of 3 example programs submitted with the project to prove it's functionality.

1 [0] = C"Hello, World!\n".
2 [1 : [0]] = R"Hello, World!\n".
3 @ [0]--
4     <- $[[0]].
5 !@.

The count and reverse operators were implemented to help with finding the bounds of strings in memory. The reverse operator was used solely because it was more efficient to count back to 0 with index 0, than to allot another index to count up to the length of the string.

It should be noted, despite having gotos, labels, and the ternary operator implemented at the time, which would have been enough to simulate loops, that V1 still implemented a while loop syntax. These loops were the only statement to ever be compound (note the lack of an end-of-statement token on line 3), as no if-statement syntax was ever thought up or implemented.

V2

In Minim V2, which was developed after the class ended, the loop statement and its syntax were dropped in favor gotos and labels. Strings were now null-terminated, meaning that a 0 was guaranteed to be at the very end of any and all strings inserted into memory. This 0 could now be used to determine where the end of a string was, removing the need for the count and reverse operators, which were dropped in this version as well.

V3

Minim V3 simply altered the start of statement syntax for all of the statements except for the expression statement, and added a handful of new operators.

V4

V4 was the first version that was written in Kotlin. The ease of use of Kotlin compared to Java spurred the implementation of a feature originally planned for V1. In previous versions, all numbers were stored as 32-bit integers. In V4, all numbers were switched to bytes. Any number bigger than a byte would be converted to arrays of sequential bytes, and numerical operators would be updated to handle operations between a byte and an array, and between two arrays. The B, S, I, and L literals were added so the programmer could signal which array accessors were acting as bigger numbers:

[0 @ B] ; byte,  1 byte
[0 @ S] ; short, 2 bytes
[0 @ I] ; int,   4 bytes
[0 @ L] ; long,  8 bytes

It was discovered, through extensive testing, that this higher data type functionality would quickly bog down and overcomplicate programs, and that strings using any character set above ASCII Extended would require a new extended string syntax, or multidimensional arrays to store them. The next version dropped bytes in favor of 32-bit numerical types, and the number-array and array-array arithmetic functionality was scrapped.

V5

Minim V5 is the current language being developed. It changed the start of statement syntax again, and added further control statements, system call statements, and memory statements. In this version, all values can now be either 32-bit floats or 32-bit integers. Lastly, a library of system functions was added, along with the System Argument and System Call statements. V5 is intended to be the final verson of the language's syntax, and any and all further updates will only add further system library functions and bug fixes.

Command Line Tool

The Minim Command Line Tool can be used to run Minim programs from your system's terminal.

Flags

The following flags can be used to change the behavior of the interpreter:

Arguments (-a)

The Arguments flag is used to pass program arguments to the interpreter, which can be queried using the dynamic array literal A.

C:\Users\chris> minim -a <args>_

Debug (-d)

The debug flag activates debug mode.

C:\Users\chris> minim -d_

When debug mode is activated, a memory table is printed after the runtime has finished running.

C:\Users\chris> minim -d -f hello.min

Hello, World!
Index |    0 |    1 |     2 |     3 |     4 |     5 |    6 |    7 |    8 |     9 |    10 |...
Value | 15.0 | 72.0 | 101.0 | 108.0 | 108.0 | 111.0 | 44.0 | 32.0 | 87.0 | 111.0 | 114.0 |...
 Char | \x0f |    H |     e |     l |     l |     o |    , |      |    W |     o |     r |...

C:\Users\chris> _

Also, when an error occurs, the full error message and traceback from the implementing language will be shown.

Debug Off:

Lexer Error @ REPL.min (1, 2) :: Character 'q' is invalid!

Debug On:

minim.util.MinimError: Lexer Error @ REPL.min (1, 2) :: Character 'q' is invalid!
    at minim.util.MinimErrorKt.lexerError(MinimError.kt:12)
    at minim.util.MinimErrorKt.invalidCharError(MinimError.kt:15)
    at minim.lexer.Lexer.word(Lexer.kt:188)
    at minim.lexer.Lexer.lex(Lexer.kt:52)
    at minim.util.Source.compile(Source.kt:25)
    at minim.MainKt.repl(Main.kt:108)
    at minim.MainKt.main(Main.kt:60)

File (-f)

The file flag specifies the file to be executed. If no file is specified, the interpreter enters REPL mode.

C:\Users\chris> minim -f <path>_

Size (-s)

The size flag specifies size of each scope pushed into memory.

C:\Users\chris> minim -s <size>_

A couple suffixes can be used for shorthand memory sizes:

Memory Size Suffixes
Suffix Size
K k 1,000
M m 1,000,000
B b 1,000,000,000

Examples:

1.2K (1,200)
5.28m (5,280,000)

Modes

There are two interpreter modes:

REPL

If no file is specified, the tool enters REPL (Read-Eval-Print Loop) mode. In this mode, single expressions can be specially evaluated, as well as any sequence of statements. The value of any evaluated expression is stored in index 0.

C:\Users\chris> minim
##.      .##'    .##
####.  .##'    .##'
## '####'    .##'
##         .##'    .
##       .##'    .##
##     .##'    .####
     .##'    .##' ##
   .##'    .##'   ##
 .##'    .##'     ##
##'    .##'       ##
--------------------
 Minim  Programming
  Language V 5.1.5

$> 3 + 5

$< 8.0, '\b' (0.0059329 s)

$> 3 | 8

$< 11.0, '\v' (3.02E-5 s)

$> !5

$< 0.0, '\0' (3.664E-4 s)

$> 94r

Lexer Error @ REPL.min (1, 3) :: Character 'r' is invalid!

$> 0 ? 1 : 5

$< 5.0, '\x05' (3.41E-5 s)

$> $< 42.
*
$< 5.0, '\x05' (3.41E-5 s)

$> _

File

If a file name is provided, it is executed normally, with all language features available.

C:\Users\chris> minim -f C:\Users\chris\Documents\hello.min

Hello, World!
Done: 15.0 (0.004 s)

C:\Users\chris> _

The intepreter returns the value of memory index 0 when it is done running any program. This is why there is a 15.0 in the done message, which in the case of the standard Hello World program, happens to be the index after the last character read from memory, including the null terminator.

Syntax & Semantics

Minim is an imperative, procedural programming language which, true to it's name, is minimalist in terms of functionality.

Comments

Comments are marked by a semicolon, and can appear at any point on a line:

; This is a comment!

Comments end at a newline, but can be continued to the next line with a backslash:

; This is also \
  a comment!

There are no block comments.

Values

In Minim, all terminal values are 32-bit floating-point numbers by default, but can be converted into 32-bit integers and back using the Integer Cast and Float Cast operators.

Numbers

Number Literals
Name Example
Binary 0b11001010
Decimal 202
Hexadecimal 0xCA
Float 3.1415
Engineer Notation 1E9, 6.5E-7, 2.78e+4
Infinity I
NaN N
Pi P
Euler's Constant E

There are also a few dynamic number literals that will return a different value based on the state of the program.

Dynamic Literals
Name Literal Description
Counter C A reference to the current value of the program counter
Random R A random number between 0.0 and 1.0
Size S The current memory size

Booleans

Logical operations treat 0 as false, and all other non-zero numbers as true.

Boolean Literals
Literal Value
T 1
F 0

Characters

Character literals are surrounded by single-quotes, and are converted to a single numeric literal by the lexer.

'A', 'a', '\n'

Escaped characters are marked by a backslash.

Escape Characters
Escape Description
\\ Backslash
\' Single Quote
\" Double Quote
\0 Null Terminator
\a Beep
\b Backspace
\f Form Feed
\n Line Feed (Newline)
\r Carriage Return
\t Horizontal Tab
\u---- Hexadecimal 4-Digit Unicode
\v Vertical Tab
\x-- Hexadecimal 2-Digit ASCII

Arrays

An array is a fixed-size ordered collection of values. An array literal is a list of expressions, separated by commas, and surrounded by curly braces.

{ 0, 1, 3, 7, 15, 31, 63, 127, 255 }

Arrays cannot be indexed, and cannot contain other arrays.

The only array dynamic literal available is the Args literal, which contains the program arguments passed to the command line tool.

Array Literals
Name Example
Args A

Strings

String literals are a series of characters and escape characters surrounded by double quotes.

"Hello"

They are converted to a null-terminated array of unicode values by the lexer.

"Hello" -> { 72, 101, 108, 108, 111, 0 }

Memory

Minim has no named variables. Instead, program memory is stored as a globally accessible array; a one-dimensional, zero-indexed tape of numbers. Memory has a size of 65536 (0x10000) by default.

Single Access

To access one number at a time, an expression is placed inside of square brackets:

[<expr>]

A number can be used as an index.

[42] ; Access memory at index 42

Negative indices act like they do in Python: -i evaluates to size - i.

[-42] ; Access memory at index 65494

Memory accessors can be nested:

[[69]] ; Access the memory at the index stored at index 69

Fixed Range Access

To access multiple numbers, up to 3 expressions, separated by colons, are placed inside of square brackets:

[<expr> : <expr> : <expr>]

The first expression (start) is the first index. The second expression (end) is the last index, exclusive. The third expression (step) is the distance between indices accessed.

These ranges behave exactly like Python's slice notation.

[0 : 5 : 1] ; Access every index from 0 until 5 (0, 1, 2, 3, 4)
[0 : 5 : 2] ; Access the first of every two indices from 0 until 5 (0, 2, 4)
[2 : 5 : 2] ; Access the first of every two indices from 2 until 5 (2, 4)

The step expression defaults to 1, so it can be empty:

[0 : 5 :] ; Access every index from 0 until 5 (0, 1, 2, 3, 4)

The last colon can also be left out:

[0 : 5] ; Access every index from 0 until 5 (0, 1, 2, 3, 4)

The end expression defaults to the last memory index (65535 by default), so it can be empty:

[0 :: 1] ; Access every index from 0 until the end (0, 1, 2, 3, 4, 5, 6, 7, ...)
[0 ::]   ; Access every index from 0 until the end (0, 1, 2, 3, 4, 5, 6, 7, ...)
[0 :]    ; Access every index from 0 until the end (0, 1, 2, 3, 4, 5, 6, 7, ...)
[0 :: 2] ; Access the first of every two indices from 0 until the end (0, 2, 4, 6, 8, 10, 12, ...)

The first colon cannot be left out in this case.

The start expression defaults to 0, so it can be empty:

[: 5 : 1] ; Access every index from 0 until 5 (0, 1, 2, 3, 4)
[: 5 :]   ; Access every index from 0 until 5 (0, 1, 2, 3, 4)
[: 5]     ; Access every index from 0 until 5 (0, 1, 2, 3, 4)
[: 5 : 2] ; Access the first of every two indices from 0 until 5 (0, 2, 4)

All three can be left blank, in which case the entire memory space will be accessed:

[::] ; Access Everything
[:]  ; Access Everything

In this case, the first colon can also be left out:

[] ; Access Everything

Relative Range Access

Relative range access is denoted when the first colon is replaced by the '@' symbol:

[<expr> @ <expr> : <expr>]

The first expression (start) is the first index.

The second expression (count) is the amount of indices to access.

The third expression (step) is the distance between indices accessed.

For relative ranges, the only value that has no default is the count expression. All other syntax ommissions from the fixed range access apply:

[0 @ 5 : 1] ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[0 @ 5 : 2] ; Access 5 indices, two apart, starting from 0 (0, 2, 4, 6, 8)
[2 @ 5 : 1] ; Access 5 indices starting from 2 (2, 3, 4, 5, 6)
[0 @ 5 :]   ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[0 @ 5]     ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[2 @ 5]     ; Access 5 indices starting from 2 (2, 3, 4, 5, 6)
[@ 5 : 1]   ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[@ 5 :]     ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[@ 5]       ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[@ 5 : 2]   ; Access 5 indices, two apart, starting from 0 (0, 2, 4, 6, 8)

Operators

Most all standard operators are available, though some operate differently, due to the simplified type system. Evaluation order is from left to right.

Operator Precedence
Level Operator Description Associativity
14 -
!
?
~
++
--
unary minus
logical not
logical narrowing
bitwise not
pre-increment
pre-decrement
right to left
13 ++
--
f
i
s
post-increment
post-decrement
float cast
integer cast
string cast
left to right
12 * / % multiplicative left to right
11 + - additive left to right
10 << >> >>> shift left to right
09 < <= > >= relational not associative
08 == <> equality left to right
07 & bitwise and left to right
06 ^ bitwise xor left to right
05 | bitwise or left to right
04 && logical and left to right
03 || logical or left to right
02 ?: ternary right to left
01 = assignment left to right

All bitwise operators round their float operands down to the nearest integer before evaluating.

Most operators operate in the way that they do in most programming languages. Those that do not, or are unique to Minim, are explained below.


Unary Operators

Logical Not (!x)

Evaluates to 0 if x ≠ 0, or 1 if x = 0.

!T  -> 0
!F  -> 1
!5  -> 0
!0  -> 1
!!5 -> 1


Logical Narrowing (?x)

Evaluates to 0 if x = 0, or 1 if x ≠ 0.

?T  -> 1
?F  -> 0
?5  -> 1
?0  -> 0
??5 -> 1


Float Cast (xf)

Casts x to a float.

1f   -> 1.0
1.0f -> 1.0

If placed at the end of and array or ranged accessor, all of the contents of the resulting array are cast to floats.


Integer Cast (xi)

Casts x to an integer.

1i   -> 1
1.0i -> 1

If placed at the end of and array or ranged accessor, all of the contents of the resulting array are cast to integers.


String Cast (xs)

Converts a number to it's string representation.

1s   -> "1"
1.0s -> "1.0"

If placed at the end of and array or ranged accessor, a formatted display version of the array is returned as a single string.


Binary Operators

Mod (x % y)

The mod operator evaluates as expected for numeric operands. However, in a similar fashion to Python, it can be used to format one array with any other numbers. Any instances of '%' (37) in the left hand array will be sequentially replaced with the contents of a right hand array.

One instance of '%' can be replaced with a single expression on the right hand side.

Less (x < y)

Evaluates to 1 if x < y, or 0 otherwise.

5 < 2 -> 0
5 < 5 -> 0
5 < 8 -> 1


Less or Equal (x <= y)

Evaluates to 1 if x ≤ y, or 0 otherwise.

5 <= 2 -> 0
5 <= 5 -> 1
5 <= 8 -> 1


Greater (x > y)

Evaluates to 1 if x > y, or 0 otherwise.

5 > 2 -> 1
5 > 5 -> 0
5 > 8 -> 0


Greater or Equal (x >= y)

Evaluates to 1 if x ≥ y, or 0 otherwise.

5 >= 2 -> 1
5 >= 5 -> 1
5 >= 8 -> 0


Equal (x == y)

Evaluates to 1 if x = y, or 0 otherwise.

5 == 2 -> 0
5 == 5 -> 1
5 == 8 -> 0


Not Equal (x <> y)

Evaluates to 1 if x ≠ y, or 0 otherwise.

5 <> 2 -> 1
5 <> 5 -> 0
5 <> 8 -> 1


Logical And (x && y)

0 && 0 -> 0
0 && 1 -> 0
1 && 0 -> 0
1 && 1 -> 1


Logical Or (x || y)

Evaluates to 1 if x or y is nonzero, or 0 otherwise.

0 || 0 -> 0
0 || 1 -> 1
1 || 0 -> 1
1 || 1 -> 1


Assign (x = y)

Assigns the value or values on the right to the memory location or locations on the left.

If the left is a single access, and the right is a single value, the value is assigned.

[3] = 7 ; 0, 0, 0, 7, 0...

If the left is a ranged access, and the right is a single value, the value is assigned to all indices in the range.

[3 : 5] = 7.     ; 0, 0, 0, 7, 7, 7, 0...
[3 @ 5] = 7.     ; 0, 0, 0, 7, 7, 7, 7, 7, 0...
[3 : 5 : 2] = 7. ; 0, 0, 0, 7, 0, 7, 0...
[3 @ 5 : 2] = 7. ; 0, 0, 0, 7, 0, 7, 0, 7, 0, 7, 0, 7, 0...

If the left is a single access, and the right is an array, then the first value of the array is assigned.

[3] = {1, 2, 3}. ; 0, 0, 0, 1, 0
[3] = "Hello".   ; 0, 0, 0, 72, 0

Lastly, if the left is a ranged access, and the right is an array, then the array values assigned are truncated to fit the size of the accessor.

[3 : 5] = {1, 2, 3, 4, 5}.     ; 0, 0, 0, 1, 2, 3, 0...
[3 @ 5] = {1, 2, 3, 4, 5}.     ; 0, 0, 0, 1, 2, 3, 4, 5, 0...
[3 : 5 : 2] = {1, 2, 3, 4, 5}. ; 0, 0, 0, 1, 0, 2, 0...
[3 @ 5 : 2] = {1, 2, 3, 4, 5}. ; 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0...


Ternary Operator (x ? y : z)

Evaluates to y if x is nonzero, or z otherwise.

1 ? 42 : 69 -> 42
0 ? 42 : 69 -> 69


Statements

All statements are terminated by a period:

<statement>.

Expression

Contains a single expression, excluding top-level assignments, to be evaluated.

Assignment (=)

If an assignment expression appears at the top level of an expression statement, it is converted into an assignment statement. The memory accessor being assigned to in this statement will not access the entire memory space stated, and will just access what is necessary to achieve the assignment.

Numeric Input (#>)

Used to write a value as a number to the console.

#> [0]. ; Typed 5, got 5.0

To read the number as an integer, the 'i' operator is used as a flag to change the result.

#>i [0]. ; Typed 5, got 5

The 'f' operator flag works too, but works the same as the default.

#>f [0]. ; Typed 5, got 5.0

Numeric Output (#<)

Used to read a value as a number from input into memory.

#< [0]. ; 5.0

To write the number as an integer, the 'i' operator is used as a flag to change the result.

#<i [0]. ; 5

The 'f' operator flag works too, but works the same as the default.

#<f [0]. ; 5.0

Text Input ($>)

Used to read a value as a Unicode character from input into memory:

$> [0].

Text Output ($<)

Used to write a value as a Unicode character to the console:

$< [0].

Text Flush ($!)

Clears the text input queue.

Label (_>)

Defines a goto label:

_> 0.
_> 'A'. ; Same as _> 65.

Goto (_<)

Redirects program execution to the label given by the expression. If the label does not exist, no jump will occur.

_< 0.
_< 'A'. ; Same as _< 65.

Jump (_^)

Skips the next statement if the condition is met:

The first example prints "B":

_^ 1.
    $< 'A'.
$< 'B'.

The second example prints "AB":

_^ 0.
    $< 'A'.
$< 'B'.

Gosub (_+)

Like Goto, this statement will move the program pointer to the given label. However, the last program counter position will be pushed to the call stack. If the given label does not exist, no jump will occur.

_+ 123.
...
_> 123.
...

Return (_-)

If the call stack is not empty, it will pop the top position, and set the program counter back to that position.

...
_-.

System Arg (\<)

Adds a value to the system input queue. This first value added will be the memory index where the name of the system function to call. Any subsequent values added will be used as arguments to the function.\

[] = "sin".
\< 0.
\< P / 4.
...

System Call (\>)

Invokes a system function if the system input queue is not empty, the results of which are sent to the system output queue. Then, if the system output queue is not empty, it will yield one of its values each time this statement is reached, until the system output queue is empty again.

...
\> [0]. ; 0.70710678118

System Flush (\!)

Clears the system input and system output queues.

Memory Push (M+)

Pushes a clean memory space on to the memory stack.

[0] = 5.
M+.
#< [0]. ; 0
...

Memory Pop (M-)

Pops a memory space from the memory stack.

...
M-.
#< [0]. ; 5

Memory Out (M<)

Sends a value to the memory queue. This is used to preserve values between memory scopes.

#> [0].
M< [0].
M+.
...

Memory In (M>)

Takes a value from the memory queue and puts it into the given memory location.

...
M> [0].
#< [0].

Memory Flush (M!)

Clears the memory queue.

System Functions

A collection of system functions are available for performing more complicated functions. The standard library includes functions for timing, mathematics, and text manipulation.

General Functions

Name Arity Params Result
time 0 N/A Current unix time in seconds
wait 1 s Program execution waits for s seconds

Math Functions

Name Arity Params Result
abs 1 n Absolute value of n
acos 1 n Arc cosine of n
acosh 1 n Hyperbolic arccosine of n
asin 1 n Arcsine of n
asinh 1 n Hyperbolic arcsine of n
atan 1 n Arctangent of n
atan2 2 y, x Arctangent of x + iy
atanh 1 n Hyperbolic arctangent of n
cbrt 1 n Cube root of n
ceil 1 n Ceiling of n
cos 1 n Cosine of n
cosh 1 n Hyperbolic cosine of n
deg 1 n n radians to degrees
exp 1 n e to the power of n
expm1 1 n e to the power of n - 1
floor 1 n Floor of n
hypot 2 x, y Hypotenuse of x and y
ln 1 n Natural log of n
ln1p 1 n Natural log of (n + 1)
log 2 n, b Log base b of n
log10 1 n Log base 10 of n
log2 1 n Log base 2 of n
map 5 n, fromMin, fromMax, toMin, toMax Map n as a value between fromMin and fromMax to a value between toMin and toMax
max 2 a, b Maximum value between a and b
min 2 a, b Minimum value between a and b
nextdown 1 n Next number down from n
nextto 2 a, b Next number towards a from b
nextup 1 n Next number up from n
pow 2 b, e b to the power of e
rad 1 n n degrees to radians
round 1 n n rounded
sign 1 n Signum of n
sin 1 n Sine of n
sinh 1 n Hyperbolic sine of n
tan 1 n Tangent of n
tanh 1 n Hyperbolic tangent of n
truncate 1 n n truncated
ulp 1 n Unit of least precision of n

Text Functions

Name Arity Params Result
isalpha 1 c 1 if c is alphabetic, or 0 otherwise
isalnum 1 c 1 if c is alphanumeric, or 0 otherwise
isdigit 1 c 1 if c is numeric, or 0 otherwise
isspace 1 c 1 if c is whitespace, or 0 otherwise
islower 1 c 1 if c is lowercase, or 0 otherwise
isupper 1 c 1 if c is uppercase, or 0 otherwise
tolower 1 c The uppercase version of c
toupper 1 c The lowercase version of c

Design Patterns

A collection of constructs that mimic common control structures and processes from other languages.

Exit

...
_< 'E'.
...
_> 'E'. ; End of File

If Statement

_< 'I' + (<condition>) * 32.
_> 'i'.
    ...
_> 'I'.

Infinite Loop

_> '@'.
    ...
_< '@'.

While Loop

_> 'W'.
    _^ !<condition>.
        _< 'w'.
    ...
    _< 'W'.
_> 'w'.

Do While Loop

_> 'W'.
    ...
    _< 'W' + (<condition>) * 32.
_> 'w'.

For Loop

_> 'F'.
    ...
    <counter>++.
    _< 'F' + (<counter-condition>) * 32.
_> 'f'.

String Input

[<n>] = <n> + 1.
_> 1.
    $> [[<n>]].
    _< ?[[<n>]++].
_> 0.

String Output

[<n>] = <n> + 1.
[<n> + 1 :] = "Hello, World!\n".
_> 1.
    $< [[<n>]++].
    _< ?[[<n>]].
_> 0.

Example Programs

Hello, world!

01 ; Hello World         \
02   Christian Alexander \
03   06/22/2021
04
05 [0] = 1.
06 [1 :] = "Hello, World!\n".
07
08 _> 1.
09     $< [[0]++].
10     _< ?[[0]].
11 _> 0.

Truth-machine

01 ; truth-machine       \
02   Christian Alexander \
03   06/23/2021
04
05 #> [0].
06
07 _> 1.
08     #< [0].
09     _< ?[0].
10 _> 0.
11
12 $< '\n'.

Cat program

01 ; Cat \
02   Christian Alexander \
03   07/12/2021
04
05 _> 2.
06     $> [0].
07     _< ?[0].
08
09 _> 1.
10     $< [0].
11     _< 2.
12
13 _> 0.
14     $< '\n'.
15     _< 2.

FizzBuzz

01 ; FizzBuzz            \
02   Christian Alexander \
03   07/23/2021
04
05 [0] = 1.
06
07 _> 1.
08     _^ !([0] % 3 && [0] % 5).
09         _< '#'.
10
11     _^ !([0] % 3).
12         _< 'F'.
13
14     [2 :] = "Fizz".
15     _+ 'P'.
16
17     _> 'F'.
18
19     _^ !([0] % 5).
20         _< 'B'.
21
22     [2 :] = "Buzz".
23     _+ 'P'.
24
25     _> 'B'.
26
27     _< ' '.
28
29     _> '#'.
30
31     #< [0].
32
33     _> ' '.
34
35     $< ' '.
36
37     _< ?([0]++ - 100).
38 _> 0.
39
40 _< '.'.
41     _> 'P'.
42         [1] = 2.
43         _> 3.
44             $< [[1]++].
45             _< ?[[1]] + 2.
46         _> 2.
47     _- 0.
48 _> '.'.

Fibonacci

01 ; Fibbonacci Numbers  \
02   Christian Alexander \
03   07/27/2021
04
05 [0] = 1.
06 [1 :] = "Nth fibonacci number? ".
07 _> 1.
08     $< [[0]++].
09     _< ?[[0]].
10 _> 0.
11
12 #> [0].
13
14 $< '\n'.
15
16 _< ([0]<3)+2.
17 _> 3.
18     [3] = 1.
19     _< 4.
20 _> 2.
21
22 [0] = [0] - 2.
23 [1] = 1.
24 [2] = 1.
25
26 _> 5.
27     [3] = [1] + [2].
28     [1] = [2].
29     [2] = [3].
30
31     _< ?--[0] + 4.
32 _> 4.
33
34 #< [3].
35
36 $< '\n'.

99 bottles of beer

01 ; 99 Bottles          \
02   Christian Alexander \
03   07/12/2021
04
05 [0] = 99.
06
07 _> '['.
08     #< [0].
09
10     [1] = 2.
11     [2 :] = ([0] - 1) ? " bottles of beer on the wall,\n" : " bottle of beer on the wall,\n".
12
13     _> 'A'.
14         $< [[1]++].
15         _< [[1]] ? 'A' : 'a'.
16     _> 'a'.
17
18     #< [0].
19
20     [1] = 2.
21     [2 :] = ([0] - 1) ? " bottles of beer.\n" : " bottle of beer.\n".
22
23     _> 'B'.
24         $< [[1]++].
25         _< [[1]] ? 'B' : 'b'.
26     _> 'b'.
27
28     _< [0] ? '+' : ']'.
29     _> '+'.
30
31     [1] = 2.
32     [2 :] = "Take one down, pass it around,\n".
33
34     _> 'C'.
35         $< [[1]++].
36         _< [[1]] ? 'C' : 'c'.
37     _> 'c'.
38
39     [0]++.
40
41     #< [0].
42
43     [1] = 2.
44     [2 :] = ([0] - 1) ? " bottles of beer on the wall,\n\n" : " bottle of beer on the wall,\n\n".
45
46     _> 'D'.
47         $< [[1]++].
48         _< [[1]] ? 'D' : 'd'.
49     _> 'd'.
50
51     _< '['.
52 _> ']'.
53
54 [1] = 2.
55 [2 :] = "Go to the store, buy some more,\n99 bottles of beer on the wall.\n".
56
57 _> 'E'.
58     $< [[1]++].
59     _< [[1]] ? 'E' : 'e'.
60 _> 'e'.

Gosubs can be used to pare down the string output boilerplate:

02 ; 99 Bottles w/ Gosub and Return \
01   Christian Alexander            \
03   07/12/2021
04
05 [0] = 99.
06
07 _> '['.
08     #< [0].
09     [2 :] = ([0] - 1) ? " bottles of beer on the wall,\n" : " bottle of beer on the wall,\n".
10     _+ 'P'.
11
12     #< [0].
13     [2 :] = ([0] - 1) ? " bottles of beer.\n" : " bottle of beer.\n".
14     _+ 'P'.
15
16     _< [0] ? '+' : ']'.
17     _> '+'.
18
19     [2 :] = "Take one down, pass it around,\n".
20     _+ 'P'.
21
22     [0]--.
23
24     #< [0].
25     [2 :] = ([0] - 1) ? " bottles of beer on the wall,\n\n" : " bottle of beer on the wall,\n\n".
26     _+ 'P'.
27
28     _< '['.
29 _> ']'.
30
31 [2 :] = "Go to the store, buy some more,\n99 bottles of beer on the wall.\n".
32 _+ 'P'.
33
34 _< '.'.
35     _> 'P'.
36         [1] = 2.
37
38         _> 1.
39             $< [[1]++].
40             _< ?[[1]].
41         _> 0.
42     _-.
43 _> '.'.

Wait

This program waits for three seconds, and then terminates.

01 ; Wait                \
02   Christian Alexander \
03   07/12/2021
04
05 [0 :] = "wait".
06
07 \< 0.
08 \< 3.
09
10 \> [0].

brainfuck

NOTE This implementation does not have negative cells, and the cells wrap around from 255 back to 0 and viceversa.

001 ; Brainfuck Interpreter \
002   Christian Alexander   \
003   07/18/2021
004
005 ; Memory Space Guide            \
006   0: End of BF source           \
007   1: Instruction pointer        \
008   2: Cell pointer               \
009   3: Loop level                 \
010   4 -> [0]: BF Source           \
011   [0] -> [0] + 30000: BF Memory
012
013 ; NOTE: There are no negative cells in this implementation.
014
015 ; BF source is passed as a command line argument.
016
017 ; Hello World\
018   ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
019
020 ; Truth-machine\
021   >>>,.[[->+<<+>]>-]<<<[<<]>[.]
022
023 ; Queue command line args system call
024 [1 :] = "args".
025 \< 1.
026
027 ; Source starts at index 4
028 [0] = 4.
029
030 ; Insert args into memory
031 _> 1.
032     \> [[0]].
033
034     _< ?[[0]++].
035 _> 0.
036
037 ; Set indices 1-3 to 0
038 [1 @ 3] = 0.
039
040 ; Begin loop
041 _> '('.
042     ; Goto that ignores all non-command characters
043     _< [[1] + 4] == '+' || [[1] + 4] == '-' || [[1] + 4] == '<' || [[1] + 4] == '>' || [[1] + 4] == '[' || [[1] + 4] == ']' || [[1] + 4] == '.' || [[1] + 4] == ',' ? [[1] + 4] : ' '.
044
045     ; + Command
046     _> '+'.
047         [[2] + [0]]++.
048
049         _^ [[2] + [0]] < 256.
050             [[2] + [0]] = 0.
051     _< ' '.
052
053     ; - Command
054     _> '-'.
055         [[2] + [0]]--.
056
057         _^ [[2] + [0]] > -1.
058             [[2] + [0]] = 255.
059     _< ' '.
060
061     ; < Command
062     _> '<'.
063         [2]--.
064
065         _^ [2] > -1.
066             [2] = 29999.
067     _< ' '.
068
069     ; > Command
070     _> '>'.
071         [2]++.
072
073         _^ [2] < 30000.
074             [2] = 0.
075     _< ' '.
076
077     ; [ Command
078     _> '['.
079         [3] = 0.
080         [3]++.
081
082         _< [[2] + [0]] == 0 ? 'A' : 'a'.
083
084         _> 'A'.
085             [1]++.
086
087             _^ [[1] + 4] <> '['.
088                 [3]++.
089
090             _^ [[1] + 4] <> ']'.
091                 [3]--.
092
093             _^ [1] < [0] - 1.
094                 [1] = [0] - 1.
095
096             _< [[1] + 4] == ']' && ![3] ? 'a' : 'A'.
097         _> 'a'.
098     _< ' '.
099
100     ; ] Command
101     _> ']'.
102         [3] = 0.
103         [3]--.
104
105         _< [[2] + [0]] <> 0 ? 'B' : 'b'.
106
107         _> 'B'.
108             [1]--.
109
110             _^ [[1] + 4] <> '['.
111                 [3]++.
112
113             _^ [[1] + 4] <> ']'.
114                 [3]--.
115
116             _^ [1] > -1.
117                 [1] = 0.
118
119             _< [[1] + 4] == '[' && ![3] ? 'b' : 'B'.
120         _> 'b'.
121     _< ' '.
122
123     ; . Command
124     _> '.'.
125         $< [[2] + [0]].
126     _< ' '.
127
128     ; , Command
129     _> ','.
130         $> [[2] + [0]].
131     _< ' '.
132
133     _> ' '.
134
135     [1]++.
136
137     _< ?[[1] + 4] ? '(' : ')'.
138 _> ')'.

Links