RosettaCodeData/Lang/Mastermind/00-LANG.txt
2024-10-16 18:07:41 -07:00

292 lines
No EOL
9.1 KiB
Text

{{stub}}{{language|Mastermind}}
Mastermind is a programming language designed specifically to create [[Brainf***]] code. The [https://mastermind.lostpixels.org Mastermind IDE] includes a [[Rust]]-based compiler, which converts (compiles) Mastermind source programs into Brainf***.
The current Mastermind compiler generates Brainf*** code assuming an infinite bi-directional tape, as well as 8-bit wrapping cells <ref name="Mastermind">https://github.com/Heathcorp/Mastermind</ref>.
== Usage ==
=== Variables & Values ===
Variables can be defined as single cells, or as contiguous sets of cells:
<syntaxhighlight lang="mastermind">// single-cell:
let var = 56;
let c = 'g';
let bool = true; // true/false equivalent to 1/0
// multi-cell:
let array[4] = [1, 2, 3, 4];
let string[5] = "hello";</syntaxhighlight>
If left uninitialised, a cell is assumed to have a value of 0.
Expressions consist of simple adds and subtractions, arrays and strings cannot be used in expressions:
<syntaxhighlight lang="mastermind">
// supported:
var += 4 + (5 - 4 + (3 - 2));
var = 'g' - 23 + true;
var = var + 5; // inefficient but supported
var += array[0] + 5;
let arr[3] = [4 + 3 - ('5' - 46), 1, 3];
// NOT supported:
var += [4, 5, 7][1] + 3;</syntaxhighlight>
Array indices must be compile-time constant integers
=== Input & Output ===
Single bytes can be output using the ''output'' operator:
<syntaxhighlight lang="mastermind">
output 'h';
output var;
output var + 6;
output array[0];
// the following are equivalent:
output '\n';
output 10;</syntaxhighlight>
Likewise for ''input'':
<syntaxhighlight lang="mastermind">
input var;
input arr[2];</syntaxhighlight>
There is also ''*'' spread syntax and support for strings and arrays for ease of use:
<syntaxhighlight lang="mastermind">
output "hello";
output ['1', '2', '3'];
output *array;
input *array;</syntaxhighlight>
=== Loops ===
The simplest is the ''while'' loop, which only supports cell references, not expressions:
<syntaxhighlight lang="mastermind">
while var {
// do stuff
// var -= 1;
// etc
}</syntaxhighlight>
==== Draining loops ====
The "drain" loop is equivalent to the common Brainf*** construction of repeating an action ''N'' times, where ''N'' is the value of a tape cell. Hence, "draining" the cell while doing the actions in the loop body.
<syntaxhighlight lang="mastermind">
drain var {
}
// shorthand for following:
while var {
// do stuff
var -= 1;
}</syntaxhighlight>
This destructively loops as many times as the value in the cell being referenced, this can be used with expressions:
<syntaxhighlight lang="mastermind">
drain 10 {}
drain var - 6 {}</syntaxhighlight>
There is also shorthand "into" syntax for adding to other cells:
<syntaxhighlight lang="mastermind">
drain var into other_var other_var_2 *spread_array etc;
// example of typical "for loop":
let i;
drain 10 into i {
output '0' + i; // inefficient for the example
}
// "0123456789"
// equivalent to the following:
let i;
let N = 10;
while N {
output '0' + i;
}</syntaxhighlight>
==== Copying loops ====
The "copy" loop is equivalent to the drain loop, except it is not destructive. This means the variable can be accessed safely from inside the loop body.
<syntaxhighlight lang="mastermind">
copy var into other_var *spread_var etc;
// examples:
copy var {
// this will output the original var value, var times
output var;
}
let rows = 3;
let columns = 6;
let total;
drain rows {
copy columns into total {
output '.';
}
}
// ......
// ......
// ......</syntaxhighlight>
=== If/Else ===
The "if" and "else" keywords operate similar to [[C]], except "else if" is not supported. The code in the "if" body will be executed if the provided expression is positive, otherwise the "else" body is executed. If the "not" keyword is used, the behavior is reversed.
Examples:
<syntaxhighlight lang="mastermind">
if 13 {
output "13";
}
if var {
output "true";
} else {
output "false";
}
// typical equivalence use-case:
if not var - 10 {
// ==
} else {
// !=
}</syntaxhighlight>
=== Functions ===
Functions work like templates/macros, as they do not perform any passing by value. All functions are in-lined at compile time. This means multiple calls to a large function will significantly increase your compiled [[Brainf***]] size.
For this reason, function arguments are given using ''<'' angled bracket ''>'' syntax, much like generic functions in other languages:
<syntaxhighlight lang="mastermind">
def quote<arg> {
output 39; // ASCII single quote
output arg;
output 39;
}
let N = 'g';
quote<N>;
N += 3;
quote<N>;
// gj</syntaxhighlight>
=== Imports ===
Imports work much like the [[C]] preprocessor:
<syntaxhighlight lang="mastermind">
#include "other_file"</syntaxhighlight>
This copies the contents of "other_file" into the current file at compile-time.
=== In-line Brainf*** features ===
In-line Brainf*** allows the programmer to define custom behavior as if writing raw [[Brainf***]], this is analogous to [[C]]'s in-line [[Assembly]].
<syntaxhighlight lang="mastermind">
// This is its most basic form:
// find the next cell that equals -1
bf {
+[->+]-
}
// This is its more advanced form:
// input a line of lowercase letters and output the uppercase version
// this is an intentionally inefficient example
bf @3 clobbers var *spread_var etc {
,----------[++++++++++>,----------]
<[<]>
[
{
let g @0;
assert g unknown;
output g + ('A' - 'a');
// embedded Mastermind!
}
>
]
// now clear and return
<[[-]<]>
}</syntaxhighlight>
It is the programmer's responsibility to clear used cells and return back to the cell in which the in-line Brainf*** context began. If the programmer does not do this, any Mastermind code after the in-line Brainf*** command will likely break.
==== Memory location specifiers ====
For hand-tuning optimizations and in-line Brainf*** that reads from Mastermind variables, you can specify the location on the Brainf*** tape:
Variables can be fixed to a specified location on the eventual Brainf*** tape. This can also be done with in-line Brainf*** code sections. This can be used to share values between Mastermind and Brainf*** contexts.
<syntaxhighlight lang="mastermind">
let var @3 = 4;
// compiled: >>>++++
bf @4 {
<><><>
}
// compiled: >>>><><><></syntaxhighlight>
==== Clobbering and Assertions ====
The Mastermind compiler will try to predict the value of cells at compile-time, so it can prevent unnecessary cell clean-ups and unreachable code (with optimizations turned on). If your in-line Brainf*** affects existing Mastermind variables, you should tell the compiler using the "clobbers" keyword, the syntax is similar to the ''drain into'' variable list:
<syntaxhighlight lang="mastermind">
bf clobbers var *spread_var other_var etc {}</syntaxhighlight>
The compiler will now assume nothing about the values of those variables afterwards.
If instead you want to tell the compiler specifically that a value has become certain, you can use ''assert'':
<syntaxhighlight lang="mastermind">
assert var equals 3;
// most common use cases:
assert var equals 0;
assert var unknown;</syntaxhighlight>
Asserting a variable as ''unknown'' is equivalent to clobbering.
==== Embedded Mastermind ====
Embedding Mastermind into your in-line [[Brainf***]] allows you to use Mastermind syntax features for programs within your Brainf***, this is useful for ''N''-length string based programs, or anything not possible in pure Mastermind:
<syntaxhighlight lang="mastermind">
let sum @0;
bf @0 {
>>
// read input (until eof) to the tape, nullifying any spaces or newlines
// (this is probably not a good practical example, ideas are appreciated)
,[
{
let c @0;
assert c unknown; // needed otherwise the compiler assumes c = 0
if not (c - '\n') {
c = 0;
}
if not (c - ' ') {
c = 0;
}
}
>,
]
}</syntaxhighlight>
Memory location specifiers are relative to the current Mastermind context. Also, top-level variables are not cleared by default in Mastermind contexts, this allows you to "leave" variables in cells for your Brainf*** to use. If you want your embedded Mastermind to clean itself up, you can simply open a scope at the top level:
<syntaxhighlight lang="mastermind">
bf {
++----++[][][<><><>] // the program doesn't matter for this example
{
// variables here will not be cleared
let g @2;
assert g unknown;
{
// variables here will be cleared
let b = 32;
}
}
{{
// self-cleaning Mastermind code here
}}
}</syntaxhighlight>
==== Advanced ====
All Mastermind features are available within the embedded Mastermind contexts, including in-line [[Brainf***]] code.
<syntaxhighlight lang="mastermind">
bf {
++++[
{
let i @0;
assert i unknown;
let j @1 = i + 1;
bf @1 {
[.+]
{
// even more layers are possible
bf {
{
output "h"
}
}
}
}
}
-]
}
</syntaxhighlight>
== References ==
{{reflist}}