Patterns
=========

The package `lang:bs:macro` contains a feature called *patterns*. Patterns are a convenient way to
create syntax trees in Basic Storm without manually instantiating classes for each node in the
tree. A pattern saves the parse tree generated by the parser and uses that (by calling `transform`)
to generate the desired syntax tree automatically. For example, we can generate a syntax tree that
represents creating an array as follows:

```
Expr x = pattern(block) {
	Array<Int> array;
	array.push(1);
	array.push(2);
};
print(x.toS());
```

The parameter `block` (expected to be a subclass of `lang.bs.Block`) to the `pattern` syntax
dictates in which context identifiers inside the pattern shall be resolved. When creating syntax
trees for custom syntaxes, the parent rule will provide an appropriate block to use for context.

Patterns also allow inserting expressions generated by the surrounding code using the syntax `$name`
or `${expression}`. The first syntax only allows a single identifier, while the second syntax allow
arbitrary Basic Storm expressions to be evaluated and inserted at that location in the syntax
tree. They can be used as follows:

```
Expr e = Constant(SrcPos(), 20);
Expr f = pattern(block) {
	10 * $e + ${Constant(SrcPos(), 10)};
};
print(f.toS());
```

Which produces the expression:

```
{
	10 * 20 + 10;
}
```

It is also possible to insert a variable number of expressions into a parameter list, an array
initializer or a block using `@name` or `@expression`. In this case, the expression or identifier
should evaluate to an array of `Expr` objects, which are inserted in sequence at the specified
location. For example:

```
Expr[] e = Expr:[Constant(SrcPos(), 1), Constant(SrcPos(), 2)];
Expr f = pattern(block) {
	foo(@e, 8);
};
print(f.toS());
```

Which produces the expression:

```
{
	foo(1, 2, 8);
}
```

It is not necessary to create a block. It is also possible to create a pattern containing a single
statement:

```
Expr e = Constant(SrcPos(), 20);
Expr f = pattern(block) 10 + $e;
```

As previously mentioned, patterns are useful when implementing syntax extensions. For example, we
could implement a syntax for absolute values as follows:

BNF-file:
```
SAtom => absExpr(block, expr) : "|", SExpr(block) expr, "|";
```

BS-file:
```
use lang:bs;
use lang:bs:macro;

Expr absExpr(Block block, Expr expr) {
	pattern(block) {
		Int tmp = $expr;
		if (tmp < 0) {
			0 - tmp;
		} else {
			tmp;
		}
	}
}
```

From this example, we can also see that the patterns are *hygienic*, which means that if evaluating
the expression `|tmp|` works as expected, even if `tmp` is used as a variable name inside the
pattern.
