> For the complete documentation index, see [llms.txt](https://guide.cronuszen.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guide.cronuszen.com/gpcscripting/gpc-script-guide/reference/language-and-operators.md).

# Language and operators

This page covers the public source grammar and operators for Zen Studio Live. It complements the function, constant, and diagnostic appendices.

### Script sections and declarations

<table data-search="false"><thead><tr><th>Form</th><th>Syntax</th><th>Purpose</th><th>Runtime behavior</th></tr></thead><tbody><tr><td>Definition</td><td><code>define NAME = constant_expression;</code></td><td>Named compile-time integer</td><td>Replaced during compilation</td></tr><tr><td>Enumeration</td><td><code>enum { A, B, C };</code></td><td>Sequence of named compile-time integers</td><td>Replaced during compilation</td></tr><tr><td>Raw data</td><td><code>data(value, ...);</code></td><td>Immutable packed bytes</td><td>Read through data readers</td></tr><tr><td>Const array</td><td><code>const uint8 NAME[] = { ... };</code></td><td>Immutable typed data</td><td>Read by index/address</td></tr><tr><td>Const string</td><td><code>const string NAME = "text";</code></td><td>Immutable string data</td><td>Passed by const-data address</td></tr><tr><td>Const image</td><td><code>const image NAME = { ... };</code></td><td>Packed monochrome image</td><td>Passed by const-data address</td></tr><tr><td>Const ADT</td><td><code>const ps5adt NAME = { 11 bytes };</code></td><td>PS5 adaptive-trigger record</td><td>Passed by const-data address</td></tr><tr><td>Remap</td><td><code>remap INPUT -> OUTPUT;</code></td><td>Static report remap</td><td>Applied after <code>main</code></td></tr><tr><td>Unmap</td><td><code>unmap OUTPUT;</code></td><td>Remove output forwarding</td><td>Applied after <code>main</code></td></tr><tr><td>Variable</td><td><code>int name;</code></td><td>Mutable signed 32-bit state</td><td>Global, starts at zero</td></tr><tr><td>Runtime array</td><td><code>int name[SIZE];</code></td><td>Mutable slot array</td><td>Global, all elements start at zero</td></tr><tr><td>Init</td><td><code>init { ... }</code></td><td>One-time setup</td><td>All declared <code>init</code> sections are merged and run once before <code>main</code></td></tr><tr><td>Main</td><td><code>main { ... }</code></td><td>Real-time report logic</td><td>All declared <code>main</code> sections are merged and run continuously top-to-bottom</td></tr><tr><td>User function</td><td><code>function name(args) { ... }</code></td><td>Reusable logic with integer return</td><td>Runs when called</td></tr><tr><td>Combo</td><td><code>combo name { ... }</code></td><td>Scheduled instruction sequence</td><td>Controlled with the documented <code>combo_*</code>, <code>wait</code>, and <code>call</code> forms</td></tr><tr><td>Fast combo</td><td><code>fcombo name { ... }</code></td><td>Zen combo variant</td><td>Uses the same documented control surface</td></tr></tbody></table>

At least one `main` section is required. Zen Studio Live accepts multiple `init` and `main` sections and merges each set into its combined phase. All runtime variable declarations are top-level. Only function parameters are local.

***

### Const element types

<table data-search="false"><thead><tr><th>Type</th><th align="right">Bytes</th><th>Range/structure</th><th>Multi-dimensional</th></tr></thead><tbody><tr><td><code>int8</code></td><td align="right">1</td><td><code>-128..127</code></td><td>Yes</td></tr><tr><td><code>uint8</code></td><td align="right">1</td><td><code>0..255</code></td><td>Yes</td></tr><tr><td><code>int16</code></td><td align="right">2</td><td><code>-32768..32767</code></td><td>Yes</td></tr><tr><td><code>uint16</code></td><td align="right">2</td><td><code>0..65535</code></td><td>Yes</td></tr><tr><td><code>int32</code></td><td align="right">4</td><td>signed 32-bit</td><td>Yes</td></tr><tr><td><code>string</code></td><td align="right">variable</td><td>bytes plus string metadata/termination</td><td>String arrays only</td></tr><tr><td><code>image</code></td><td align="right">variable</td><td>width, height, packed pixels</td><td>Arrays of image records</td></tr><tr><td><code>ps5adt</code></td><td align="right">11</td><td>exactly 11 unsigned bytes</td><td>Arrays of ADT records</td></tr></tbody></table>

`int32` is a const-data type, not a different runtime declaration type. Runtime `int` is already 32-bit in Live.

***

### Literals

| Kind                      | Example              | Notes                                                           |
| ------------------------- | -------------------- | --------------------------------------------------------------- |
| Decimal integer           | `123`, `-75`         | Signed integer expression                                       |
| Hexadecimal               | `0xFF`, `0x12345678` | Useful for masks/data                                           |
| Binary                    | `0b1010`             | Useful for flags                                                |
| Decimal/fractional source | `2.5`                | Rounded by compiler with warning; avoid in production           |
| String                    | `"MENU"`             | Valid in const string declarations, not a general runtime value |
| Escape                    | `"A\nB"`, `"\x41"`   | Must be a recognized, complete escape                           |

GPC has no runtime floating-point type. Runtime division truncates.

***

### Primary compile-time forms

#### `sizeof`

```gpc
sizeof(NAME)
```

Returns compiler-known size for a supported variable/array/element operand. It does not accept every bare type keyword or arbitrary expression.

Supported fixed-width type keywords can also be queried directly: `sizeof(int8)` and `sizeof(uint8)` return `1`, `sizeof(int16)` and `sizeof(uint16)` return `2`, and `sizeof(int32)` returns `4`. Unsupported or target-inapplicable keywords produce a compiler error.

#### `addr`

```gpc
addr(CONST_ITEM)
```

Returns the const-data address required by APIs that consume string, image, or `ps5adt` records. The operand must resolve to valid const data.

***

### Flow keywords

<table data-search="false"><thead><tr><th>Keyword</th><th>Form</th><th>Effect</th></tr></thead><tbody><tr><td><code>if</code></td><td><code>if(condition) { ... }</code></td><td>Run when condition is nonzero</td></tr><tr><td><code>else if</code></td><td><code>else if(condition) { ... }</code></td><td>Alternate conditional branch</td></tr><tr><td><code>else</code></td><td><code>else { ... }</code></td><td>Fallback branch</td></tr><tr><td><code>switch</code></td><td><code>switch(value) { ... }</code></td><td>Select matching case</td></tr><tr><td><code>case</code></td><td><code>case CONSTANT: { ... }</code></td><td>Compile-time constant branch</td></tr><tr><td><code>default</code></td><td><code>default: { ... }</code></td><td>No-case fallback</td></tr><tr><td><code>while</code></td><td><code>while(condition) { ... }</code></td><td>Pre-tested loop</td></tr><tr><td><code>do</code>, <code>while</code></td><td><code>do { ... } while(condition);</code></td><td>Post-tested loop; runs once minimum</td></tr><tr><td><code>for</code></td><td><code>for(init; test; step) { ... }</code></td><td>Counted/general loop</td></tr><tr><td><code>break</code></td><td><code>break;</code></td><td>Exit nearest loop or switch</td></tr><tr><td><code>continue</code></td><td><code>continue;</code></td><td>Start next iteration of nearest loop</td></tr><tr><td><code>return</code></td><td><code>return expression;</code></td><td>Exit user function with value</td></tr></tbody></table>

Switch case bodies require braces. `case` values must be unique compile-time integers.

***

### Complete operator set

#### Conditional

| Operator                               | Meaning                             | Example                       |
| -------------------------------------- | ----------------------------------- | ----------------------------- |
| `condition ? true_value : false_value` | Select one of two expression values | `output = enabled ? 100 : 0;` |

Evaluation proceeds in two steps:

1. GPC evaluates `condition`.
2. If it is nonzero, GPC evaluates and returns `true_value`. Otherwise, GPC evaluates and returns `false_value`.

Only the selected expression is evaluated. The unselected branch does not run, so its function calls, assignments, increments, divisions, and other side effects do not occur.

{% code title="conditional-operator.gpc" lineNumbers="true" %}

```gpc
int numerator = 100;
int divisor;
int result;

main {
    // A zero divisor selects 0; numerator / divisor is not evaluated.
    result = divisor != 0 ? numerator / divisor : 0;
}
```

{% endcode %}

This behavior is equivalent to assigning the result in an `if`/`else`, but the operator can be used wherever an expression value is accepted. Use parentheses around nested conditional expressions and prefer the longer `if`/`else` form when either branch needs several statements.

Two diagnostics relate to this operator: [`GPC2117`](/gpcscripting/gpc-script-guide/troubleshooting/compiler-diagnostic-catalog/parser-syntax-errors-gpc2xxx.md) when the `:` is missing, and [`GPC4032`](/gpcscripting/gpc-script-guide/troubleshooting/compiler-diagnostic-catalog/semantic-errors-gpc40xx.md) when a conditional is written as a statement instead of used as a value.

#### Assignment

| Operator | Meaning                | Example       |
| -------- | ---------------------- | ------------- |
| `=`      | assign                 | `a = 5;`      |
| `+=`     | add and assign         | `a += 2;`     |
| `-=`     | subtract and assign    | `a -= 2;`     |
| `*=`     | multiply and assign    | `a *= 2;`     |
| `/=`     | divide and assign      | `a /= 2;`     |
| `%=`     | remainder and assign   | `a %= 2;`     |
| `\|=`    | bitwise OR and assign  | `a \|= MASK;` |
| `&=`     | bitwise AND and assign | `a &= MASK;`  |
| `^=`     | bitwise XOR and assign | `a ^= MASK;`  |
| `<<=`    | shift left and assign  | `a <<= 1;`    |
| `>>=`    | shift right and assign | `a >>= 1;`    |
| `&&=`    | logical AND and assign | `a &&= b;`    |
| `\|\|=`  | logical OR and assign  | `a \|\|= b;`  |
| `^^=`    | logical XOR and assign | `a ^^= b;`    |

#### Arithmetic and increment

| Operator | Meaning                     | Example result  |
| -------- | --------------------------- | --------------- |
| `+`      | addition                    | `10 + 5` → `15` |
| `-`      | subtraction/unary negate    | `10 - 5` → `5`  |
| `*`      | multiplication              | `10 * 5` → `50` |
| `/`      | truncating integer division | `10 / 3` → `3`  |
| `%`      | integer remainder           | `10 % 3` → `1`  |
| `++`     | increment                   | `a++;`          |
| `--`     | decrement                   | `a--;`          |

#### Logical

| Operator | Meaning     |
| -------- | ----------- |
| `!`      | logical NOT |
| `&&`     | logical AND |
| `\|\|`   | logical OR  |
| `^^`     | logical XOR |

#### Comparison

`==`, `!=`, `<`, `<=`, `>`, `>=`

#### Bitwise

| Operator | Meaning         |
| -------- | --------------- |
| `~`      | invert all bits |
| `&`      | bitwise AND     |
| `\|`     | bitwise OR      |
| `^`      | bitwise XOR     |
| `<<`     | left shift      |
| `>>`     | right shift     |

Shift counts must stay within `0..31` for Live integers.

***

### Operator precedence

Lowest binding strength is listed first; parentheses override the table.

<table data-search="false"><thead><tr><th align="right">Level</th><th>Operators</th><th>Associativity/category</th></tr></thead><tbody><tr><td align="right">1</td><td><code>=</code> <code>+=</code> <code>-=</code> <code>*=</code> <code>/=</code> <code>%=</code> <code>&#x26;=</code> <code>|=</code> <code>^=</code> <code>&#x3C;&#x3C;=</code> <code>>>=</code> <code>&#x26;&#x26;=</code> <code>||=</code> <code>^^=</code></td><td>assignment, right-to-left</td></tr><tr><td align="right">2</td><td><code>? :</code></td><td>conditional selection; use parentheses for nested forms</td></tr><tr><td align="right">3</td><td><code>||</code></td><td>logical OR</td></tr><tr><td align="right">4</td><td><code>^^</code></td><td>logical XOR</td></tr><tr><td align="right">5</td><td><code>&#x26;&#x26;</code></td><td>logical AND</td></tr><tr><td align="right">6</td><td><code>|</code></td><td>bitwise OR</td></tr><tr><td align="right">7</td><td><code>^</code></td><td>bitwise XOR</td></tr><tr><td align="right">8</td><td><code>&#x26;</code></td><td>bitwise AND</td></tr><tr><td align="right">9</td><td><code>==</code> <code>!=</code></td><td>equality</td></tr><tr><td align="right">10</td><td><code>></code> <code>>=</code> <code>&#x3C;</code> <code>&#x3C;=</code></td><td>relational</td></tr><tr><td align="right">11</td><td><code>&#x3C;&#x3C;</code> <code>>></code></td><td>shift</td></tr><tr><td align="right">12</td><td><code>+</code> <code>-</code></td><td>additive</td></tr><tr><td align="right">13</td><td><code>*</code> <code>/</code> <code>%</code></td><td>multiplicative</td></tr><tr><td align="right">14</td><td><code>!</code> unary <code>-</code> <code>~</code> prefix <code>++</code> prefix <code>--</code></td><td>unary, right-to-left</td></tr><tr><td align="right">15</td><td>postfix <code>++</code> postfix <code>--</code> <code>[ ]</code> <code>( )</code></td><td>postfix/call/subscript</td></tr><tr><td align="right">16</td><td>literals, identifiers, <code>sizeof()</code>, <code>addr()</code>, grouping <code>( )</code></td><td>primary</td></tr></tbody></table>

Classic trap:

```gpc
if((flags & MASK) == MASK) { }  // correct
```

`flags & MASK == MASK` evaluates equality before bitwise AND.

***

### Remap timing

```gpc
remap PS5_CROSS -> PS5_SQUARE;
unmap PS5_TRIANGLE;
```

`main` reads/writes original identifiers. Static remap/unmap finalization happens afterward. An unmapped input remains readable by the script.

***

### Function rules

{% code title="bounded-function.gpc" %}

```gpc
function bounded(value, low, high) {
    if(value < low) return low;
    if(value > high) return high;
    return value;
}
```

{% endcode %}

* Parameters are local signed integers passed by value.
* Globals remain visible.
* No block-local variable declarations exist.
* No reached `return` means an automatic return value of zero.
* Do not mix valued and bare returns.
* Recursion is accepted with a stack warning; avoid it in real-time code.
* A built-in marked as returning a required value must have that value consumed.

***

### Namespace and mutability

Variables, definitions, enum members, and const-data names share the data-symbol namespace. User-function names and combo names are resolved separately from it, and function parameters are local to their function. Language keywords and built-in names remain reserved. Only runtime variables, runtime-array elements, and supported variable parameters are writable; const data, definitions, enum members, literals, and built-in constants are not assignment targets.

### Comments

```gpc
// Line comment
/* Block comment */
```

Block comments terminate at the first `*/` and cannot nest.

***

### Public/private boundary

This edition documents the current reader-facing language surface, including combo controls, combo-only commands, bit helpers, math helpers, device functions, BVAR read/write, and OLED drawing.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://guide.cronuszen.com/gpcscripting/gpc-script-guide/reference/language-and-operators.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
