Skip to content

Language reference

This part of the documentation describes the MaSH language itself: what a script looks like, what values it can hold, how expressions and statements behave, and what happens when something goes wrong. It does not describe the objects a script can call, such as mash.files or mash.http. Those are in the library reference.

If you are new to MaSH, read the tutorial first. This reference is for looking things up.

Each page states a rule, then shows an example. An example is a mash block followed by the exact output it prints:

printline "Hello from MaSH"
Hello from MaSH

Every example in this reference is run automatically, so the output you see is what a script prints. An example marked as not run needs something outside the language, such as a live share or a mail server.

MaSH has a “natural” syntax and a “standard” syntax. They are not two languages. They run the same way, and you can mix them in one script, and in one statement.

The natural syntax reads like instructions. A body ends with end, a statement call has no brackets (printline total), and set x to 5 and increment x by 2 are available for assignment. The standard syntax uses symbols and braces, like most programming languages. The same script, in both:

set total to 0
each 1...3 as n
increment total by n
end
printline total
6

The documentation shows both forms wherever they differ. Pick a tab on any page and the choice applies to every page, and is remembered for your next visit. An example whose two forms would read the same has no tabs.

The two forms can be mixed. This script closes the first loop with end, uses braces for the second, and calls printline both with and without brackets:

total = 0
each 1...3 as n
total += n
end
each (1...3) as n {
total += n
}
printline(total)
printline total
12
12

The main differences are:

NaturalStandard
set x to 5x = 5
if x is less than 5 … endif x < 5 { ... }
x is not 5x != 5
a and b, a or ba && b, a || b
a otherwise ba ?? b
1 thru 5, 1 through 51...5
increment x by 2x += 2
raise "text"throw "text"
printline "hi"printline("hi")
block add a b … endblock add(a, b) { ... }
each items as item … endeach (items) as item { ... }

Both forms are always accepted. A brace body does not need an end, and brackets round a condition are optional. In this reference, “natural” examples use the word forms for control flow and calls. The operators ==, < and && work in natural code too, and most examples use them because they are shorter.

A script is a list of statements, run from the top. Blocks (the language’s functions) can be defined anywhere in the script and used before their definition. See Blocks and calls.

A script can finish in three ways:

  • It reaches the last statement.
  • It runs exit or return at the top level. The run counts as a success.
  • It runs fail, or something goes wrong that the script cannot recover from. The run counts as an error.

Most errors in MaSH are not in the third group. A failing statement records the error and the script carries on. This is the single most important rule in the language, and the Errors page covers it in full.

  1. Lexical structure: comments, names, keywords, literals, line endings.
  2. Values and types: null, booleans, numbers, strings, arrays, dictionaries, ranges, objects.
  3. Variables and scope: assignment, here, globals and locals.
  4. Expressions and operators: the operator table, precedence, natural-language comparisons.
  5. Statements: if, each, while, until, ensure, break, next, exit.
  6. Blocks and calls: defining and calling blocks, calls without brackets, callbacks, yield.
  7. Errors: recorded errors, error blocks, fail, stoponerror.
  8. Objects and member access: dots, indexes, method calls, what scripts cannot reach.
  9. Limits: time, memory, and what differs between Foldr Cloud and an appliance.