mason

All Mason programs must use the msl (Mason Standard Library) package.

The examples can be run on the site, but you may want to install mason too.

syntax

Character sequences are valid names if they have no special characters (() [ {} # % ^ & _ | \ : ; ' " , .] or whitespace), do not start with a digit or ~, and are not keywords.

Blocks of code are written as indented blocks of text. Tabs by default, but there is a compiler option for spaces.

Spaces within a line are significant too, so don't go adding spaces anywhere the examples don't. a. b, a.b, and a .b all mean different things!

You don't need semicolons, commas, or curly braces, and parentheses are rare.

Mason generally uses prefix syntax as in + 1 2 instead of infix 1 + 2 in JavaScript. The few infix operators such as a = 1 are statements — meaning they only occur once per line, and can't appear as subexpressions — so operator precedence is not necessary.

|| is an ignored line comment. For other comments, see doc.

block

In addition to normal blocks, blocks of code can also build objects, arrays, and maps.

object

Objects are written as indented blocks of key. value pairs.

x. 1
y. 2

Object keys are local variables, so you can use them as if you had used =.

If an object key is a local variable from elsewhere, just write foo..

one. 1
uno. one
ein = uno
ein.

array

Arrays are also written in indented blocks.

Each line beginning with ., followed by a space, writes a new entry to it.

... adds many elements.

. 1
. 2
... [3 4]

map

Maps follow the same pattern.

Each line with a -> writes an entry to the map.

1 -> 2
3 -> 4

building

Why are these called builders?

It's because they build their result incrementally, making them more advanced than just literals.

. 1
if false
	. 2
if true
	. 3

short forms

You can also do it all on one line.

obj = {a. 1 b. 2}
arr = [1 2]
|| When a value is just accessing the variable with the key name, you don't have to type it.
. {foo. 1 arr.}
|| When all values are just local accesses, you don't need `.`.
. {obj arr}

value blocks

If a block appears in a value position, either it is a builder it returns its last line.

Mason doesn't have a return keyword.
two = 2
two

Yes, you can use a block anywhere a value is expected!

a.
	|| `x` is scoped to this block.
	x = 1
	x
b.
	. 1
	.
		|| `. ` expects a value, which can of course be a block!
		. 2
		. 3

literals

Constants and numbers work as in JavaScript.

. true
. false
. null
. undefined
. 0
. -1.1
. 0b10
. 0o10
. 0x10

strings

Text surrounded in " makes a string.

Interpolate values with #(). For a local name use #foo without parentheses.

\ escapes special characters as in JavaScript.

Multi-line strings go in indented text.

Note that the string's indentation is whatever you add past the block's indentation, so in the example only #equation is indented.

For short strings, use ' followed by an identifier. This is useful for the names of events, CSS classes, methods, etc.

wise-man = 'Confucius
equation = "1 + 1 = #(+ 1 1)"
"
	#wise-man say:
		#equation
	but I don't know if I believe it...

regexps

RegExps look just like strings but use ` instead of ".

You can include any of the flags g i m y after the closing `.

Flags must appear in alphabetical order. If the y flag isn't available on your system, you won't be able to compile it yet.

When interpolated values are RegExps, their .source is interpolated, so regexps can compose. But flags on interpolated regexps are ignored.

Otherwise, interpolated values are converted to strings, and are not escaped, meaning they are treated as regexp code.
hex-digit = `[0-9a-f]`
hex-number = `0x#(hex-digit)+`i
. hex-number
|| We used the `i` flag, so capital letters are OK.
. hex-number.test "0xDEADBEEF"

operators

Operators are written in prefix notation.

They can take any number of arguments. Unlike function calls, they don't require parentheses.

The operators are:

** is equivalent to Math.pow.

==? tests identity while =? is overridable via binary=?.

|| Operators ending in `?` test their arguments in pairs.
|| This is equivalent to `and <? 1 2 <? 2 3`.
. <? 1 2 3

|| Other operators run left to right.
|| This is equivalent to `- (- 3 2) 1`.
. - 3 2 1

|| Operators don't require parentheses.
|| This is equivalent to `=? 9 (* 3 (+ 2 1))`.
. =? 9 * 3 + 2 1

Since operators take any number of arguments, you will still occasionally need parentheses to distinguish these:

|| + 1 (* 2 3 (- 4 5))
. + 1 * 2 3 - 4 5

|| + 1 (* 2 3) (- 4 5)
. + 1 (* 2 3) - 4 5

There are also two unary operators, neg and not.

These take only one argument no matter what, so neg a b is parsed as neg (a b).

. neg 1
. not true
|| Equivalent to `neg (identity 1)`
. neg identity 1

Mason does not implement these javascript operators:

<< >> >>> & ^ | ~ ++ -- in

or the unary + operator.

If you need these, they are available as functions such as js<<.

functions

Functions are written with \ followed by arguments.

The body of a function is a block meaning it can be a builder.

Calling a function doesn't usually require parentheses, except for arguments that are theirselves function calls.

id = \a
	a
two-of = \a
	. a
	. a

. id 1
. two-of 1
|| Parentheses are only needed when a subexpression is itself a function call.
. id (id 1)

If you want to put a block inside parentheses, just don't include the closing parenthesis.

two-of = \a
	. a
	. a

two-of (two-of
	. 1
	. 2
	|| No closing parenthesis!

For functions with no return value, use !\.

If you don't need to do anything in a block, use pass.

A function with no arguments is called like fun().

do-nothing! = !\
	pass
do-nothing!()

this-functions

Normal functions compile to JavaScript's arrow functions.

For function() { }, which has a freshly bound this variable, use .\ and .!\.

In inner functions, it's safe to use this.

You usually won't need these, because Mason has class syntax.

f = .\
	|| In here `this` has a different value than outside.
	\
		|| In here `this` has the same value as in `f`.
		this
(f.call 3)()

new

Calling a constructor looks like a function call with new in front.

new is parsed like an operator, as are all other expression keywords. So foo new Bar is foo (new Bar).
new Array 4

modules

Mason is planned to compile to JavaScript native modules.

A module is written as an object block.

The default export is an entry with the same name as the file name.

|| my-module.ms

|| default export
my-module. 1

|| named export
a. 2

If your module does not have any named exports, it is treated as a block and its value is assigned to the default export.

To export nothing, just end the file with pass.

So, the code for a module whose default export is zero is:

0

Module imports go at the top of a script and use a special syntax.

import
	|| Uses the globally available module `fs`.
	fs

	|| File "brother.ms" (or ".js") in the same directory.
	.brother

	|| ./brother-dir/nephew.ms
	.brother-dir.nephew

	|| ../aunt.ms
	..aunt

	|| ../../aunt/cousin.ms
	...aunt.cousin

	|| Creates a local `a` equal to the module's default export.
	a

	|| Imports named exports `b` and `c` as locals.
	a b c

	|| Both combined. The default export is still called `a`, not `_`.
	a _ b c

Mason doesn't normally allow global variables (except for builtin globals), but you can declare them using the fake global module.

import
	global alert

alert 'hi

Some values from msl such as identity are builtins — you don't have to explitly import them. The necessary imports will be added for you.

The list of builtins is currently only available here.

Putting these together, global variables such as Object are really builtins from the global module. Common JS globals (not including web-specific ones) are builtins.

If you need it, the global variable 'global' an object containing all globals is shimmed to work on either client or server.