Minim

=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===
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.
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.
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	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.
{ </span>0, </span>1, </span>3, </span>7, </span>15, </span>31, </span>63, </span>127, </span>255 </span>}
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.
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" </span>-> </span>{ </span>72, </span>101, </span>108, </span>108, </span>111, </span>0 </span>}
==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] </span>; Access memory at index 42
Negative indices act like they do in Python: -i evaluates to size - i.
[-42] </span>; Access memory at index 65494
Memory accessors can be nested:
[[69]] </span>; 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 </span>: </span>5 </span>: </span>1] </span>; Access every index from 0 until 5 (0, 1, 2, 3, 4)
[0 </span>: </span>5 </span>: </span>2] </span>; Access the first of every two indices from 0 until 5 (0, 2, 4)
[2 </span>: </span>5 </span>: </span>2] </span>; 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 </span>: </span>5 </span>:] </span>; Access every index from 0 until 5 (0, 1, 2, 3, 4)
The last colon can also be left out:
[0 </span>: </span>5] </span>; 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 </span>:: </span>1] </span>; Access every index from 0 until the end (0, 1, 2, 3, 4, 5, 6, 7, ...)
[0 </span>::] </span>  ; Access every index from 0 until the end (0, 1, 2, 3, 4, 5, 6, 7, ...)
[0 </span>:] </span>   ; Access every index from 0 until the end (0, 1, 2, 3, 4, 5, 6, 7, ...)
[0 </span>:: </span>2] </span>; 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:
[: </span>5 </span>: </span>1] </span>; Access every index from 0 until 5 (0, 1, 2, 3, 4)
[: </span>5 </span>:] </span>  ; Access every index from 0 until 5 (0, 1, 2, 3, 4)
[: </span>5] </span>    ; Access every index from 0 until 5 (0, 1, 2, 3, 4)
[: </span>5 </span>: </span>2] </span>; 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:
[::] </span>; Access Everything
[:] </span> ; Access Everything
In this case, the first colon can also be left out:
[] </span>; 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 </span>@ </span>5 </span>: </span>1] </span>; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[0 </span>@ </span>5 </span>: </span>2] </span>; Access 5 indices, two apart, starting from 0 (0, 2, 4, 6, 8)
[2 </span>@ </span>5 </span>: </span>1] </span>; Access 5 indices starting from 2 (2, 3, 4, 5, 6)
[0 </span>@ </span>5 </span>:] </span>  ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[0 </span>@ </span>5] </span>    ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[2 </span>@ </span>5] </span>    ; Access 5 indices starting from 2 (2, 3, 4, 5, 6)
[@ </span>5 </span>: </span>1] </span>  ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[@ </span>5 </span>:] </span>    ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[@ </span>5] </span>      ; Access 5 indices starting from 0 (0, 1, 2, 3, 4)
[@ </span>5 </span>: </span>2] </span>  ; 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.
Level	Operator 	Description 	Associativity 	
14 	-!?~++-- 	unary minuslogical notlogical narrowingbitwise notpre-incrementpre-decrement	right to left 	
13 	++--fis 	post-incrementpost-decrementfloat castinteger caststring 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  </span>-> </span>0
!F  </span>-> </span>1
!5  </span>-> </span>0
!0  </span>-> </span>1
!!5 </span>-> </span>1
====Logical Narrowing (?x)====
Evaluates to 0 if x = 0, or 1 if x ≠ 0.
?T  </span>-> </span>1
?F  </span>-> </span>0
?5  </span>-> </span>1
?0  </span>-> </span>0
??5 </span>-> </span>1
====Float Cast (xf)====
Casts x to a float.
1f   -> 1.0
1.0f </span>-> </span>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 </span>-> </span>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 </span>-> </span>"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=
* Carrd Page
* GitHub Repository
* Ruslan Spivak: Let's Build a Simple Interpreter
* Crafting Interpreters
Category:Languages
Category:2017
Category:Implemented
Category:Turing complete
Category:Bounded-storage_machine
Category:Low-level
Category:Imperative paradigm