# Syntax, settings and scope

[Start here](https://pegmatite.dev/guide/start.md). Fetch this topic for exact rules on names, numbers, strings and statements, persistent settings and `unset`, how far a setting reaches, and colors.

## Values and names

- Numbers are integers or decimals with an optional `-`: `10`, `0.5`, `-2.5`. `.5`, `1.`, `+1` and `1e3` are not numbers. `2pi` is an error; write `(2 * pi)`.
- A numeric argument also takes a variable, a parenthesized [expression](https://pegmatite.dev/guide/expressions.md), a function call or a measure: `$size`, `($size / 2)`, `sqrt($area)`, `base.width`. A `-` against any of them negates it: `-$size`, `-($a + 1)`, `-base.width`.
- Percentages, in alignments and `cut`, are a literal number followed directly by `%`: `25%`. A variable or expression cannot take `%`.
- Strings are in double quotes and may span lines. Escapes: `\n` line break, `\"` double quote, `\\` backslash, `\u{…}` a hex code point such as `\u{B0}` for `°`. Any other escape is an error, so a literal backslash is `\\`. Strings serve `text`, `path` (with its own limits, see [shapes](https://pegmatite.dev/guide/shapes.md)), `font` and `set`.
- Names are case-sensitive, start with a letter and continue with letters, digits or underscores; letters may be Unicode. Variables carry `$`, macros `%`, labels end in `:`, so no word is reserved: `cube: cube 10` labels a cube `cube`. Only `root`, which every context already has, and `pi` cannot be labels.
- A word against `(` is a function call, but command and statement words never are: `repeat(` is no call.
- Block comments do not nest: the first `*/` closes the comment.

## Statements

A script is a sequence of statements, with [macro definitions](https://pegmatite.dev/guide/macros.md) and [parts](https://pegmatite.dev/guide/booleans.md) among them.

| Statement           | Example                   | Meaning                                      |
| ------------------- | ------------------------- | -------------------------------------------- |
| Qualified solid     | `color red @left cube 10` | one solid with everything qualifying it      |
| Persistent setter   | `!color red`              | a setting for every following solid          |
| List                | `[ … ]`                   | each item built from the same reference      |
| Reference           | `on #front`, `on base`    | what the next solid is built against         |
| Pattern             | `repeat 4 cube 10`        | the body built several times                 |
| Conditional         | `if $ears == 1 %ears`     | the body built only when the test holds      |
| Variable assignment | `set $size 10`            | binds a value                                |
| Sketch              | `circle 10`               | a 2D outline drawn without building material |

**Syntax:** **`set`** _variable_ _value_

A qualified solid is one-shot setters with an optional label among them, an optional boolean sign, the solid and its `|` pipeline. Line breaks do not split it.

A one-shot setter belongs to the solid or pattern after it, and may stand before the `on` leading into it: `color red on #front cube 10` is `on #front color red cube 10`. A setter standing alone, or separated from its solid by another statement, applies to nothing and warns:

```pegm
/* Expected warning: the color setter has no solid. */
color red
set $size 10   /* warning: "color red" applies to no solid */
cube $size
```

Before `repeat`, one-shot setters go to the first solid it builds. Before the other [patterns](https://pegmatite.dev/guide/patterns.md), placement setters position the whole pattern and appearance setters reach its first solid.

## Setters

**Syntax:** **`x`** [_align_] [_offset_]

**Syntax:** **`y`** [_align_] [_offset_]

**Syntax:** **`z`** [_align_] [_offset_]

**Syntax:** **`color`** _color_

**Syntax:** **`font-size`** _size_

**Syntax:** **`font`** _family_ [_weight_]

Anchors with their gap are setters too. Alignments are in [placement](https://pegmatite.dev/guide/placement.md), fonts in [text](https://pegmatite.dev/guide/text.md).

### Persistent settings

`!` attached to a setter, `!color red`, `!x 10`, `!@right 10`, applies it to every following solid until changed or its scope ends; `! color red` is an error. A persistent setter is a statement of its own, so it goes before any one-shot setter of the next solid. A one-shot setter overrides it for one solid:

```pegm
!color red
cube 10
color blue
cube 10   /* red, blue, red */
cube 10
```

The three axes are separate setters, so one overrides only its own axis. Naming an axis with `0` cancels its persistent offset for one solid and keeps its alignment:

```pegm
!@right
!y 10
block 10 10 10
y 0
block 10 10 20   /* centered on y again */
block 10 10 30   /* 10 back of center once more */
```

### Unset

`unset` clears a setting. `!y unset` clears the persistent one for all following solids; `y unset` clears it for the next solid only, after which it resumes. `y 0` changes only the offset; `y unset` clears alignment and offset, so the anchor or the default applies. On an anchor, `unset` clears the gap and keeps the direction: `!@right unset` closes up a row spaced by `!@right 10`. `color unset` restores the default color for one solid, `!color unset` clears the persistent color.

```pegm
!@right
!y 10
cube 10
y unset
cube 10   /* centered; the others 10 back */
cube 10
```

## Colors

`color` takes an HTML named color or a hex `#rrggbb`:

```pegm
color blue
cube 10
color #ff0000
cube 20
color unset
cube 5
```

3MF and STEP carry colors only when the model uses one. Then it exports as one object per color, the default included, for a slicer to give each its own filament. [Parts](https://pegmatite.dev/guide/booleans.md) are split by color within each part. A compound keeps the colors of the solids it fuses; where two overlap, the earlier solid keeps the shared volume. In STEP each body has one color, so a compound of several shows the color most of it is drawn in.

## Scope

Settings come in two families:

- **Appearance**, `color`, `font-size`, `font`: reach this context, the lists opened in it, and compound and macro bodies.
- **Placement**, `x`, `y`, `z`, `@anchor`: reach this context and its lists. They position a finished body, not the solids inside it.

A change inside a list or body stays there. Both towers are red, 4 apart; the gap does not separate a cylinder from its base:

```pegm
def %tower $height {
  block 10 10 3
  cylinder 5 $height
}

!color red
!@right 4
%tower 14
%tower 14
```

A body wanting a row of its own sets the pitch inside, `{ !@right 15 sphere 30 cube 20 }`.

What each construct scopes:

- **List `[ … ]`**: each item branches from the saved reference, `]` restores it. Settings are inherited, changes stay inside. Outer labels are visible, new ones stay inside. Variables and booleans are the surrounding context's.
- **Compound `{ … }`**: own origin, placed as one volume. Appearance settings enter, placement settings do not; changes stay inside. Labels are isolated for `on`, but measures read outer ones; `root` is the compound's origin. Variables are inherited, assignments stay inside. Booleans affect only the body.
- **Macro body**: as a compound, except labels are isolated for measures too, and variables are those set above the definition, with their values there, under the parameters. See [macros](https://pegmatite.dev/guide/macros.md).
- **Pattern body**: `repeat` continues the sequence, the others start each iteration at its own point; the pattern leaves one combined slot. A single statement adds no scope and its assignments persist; a braced body is a compound. The index variable is restored afterwards. Booleans affect the surrounding context.
- **Conditional**: stands for the branch it picks; with none picked, what follows is placed as if it were not written. A single statement adds no scope and the picked branch's assignments persist; a braced branch is a compound.
- **`on`**: selects a volume or face and opens no scope. Axis settings stay in force in the selected frame; a persistent anchor skips the first solid against the face and resumes after it. An initial face sets the build plane, `on root #face` inside a compound.
- **`part`**: starts a new boolean context and nothing else; settings, labels, variables and placement carry on as if it were not written.

**Syntax:** **`on`** _reference_

**Syntax:** **`part`** _name_

A list changes placement, not which geometry a cut reaches; isolate a cut with braces, a macro, or a part.
