Skip to content

Expressions

Expressions calculate values inside String and Number inputs. They read declared variables and fields; they do not replace the visual editor’s methods, conditions, or loops.

A String can mix normal text with any number of expressions:

Score: ${private.score}, doubled: ${private.score * 2}
Hello, ${private.playerName}!

If score is 7, the first String becomes Score: 7, doubled: 14. The result of each expression is converted to text, while surrounding spaces and punctuation remain as entered. Null prints as null. Number display removes unnecessary trailing decimal zeros.

Enter this text into a String item’s dialog or an inline String argument. Compile the draft after changing the argument.

A Number input must consist of one complete expression, optionally surrounded by whitespace:

${private.score * 2}
${(private.base + environment.bonus) / 2}
${save.bestScore ?? 0}

The result must be a non-null Number. Score: ${private.score} is valid as a String but invalid as a Number. Bare arithmetic such as 2 + 3 is not Number-expression syntax; enter ${2 + 3}.

Create typed Variable declarations first. For example, declare Private Number score, assign it 7, then use ${private.score * 2}. Writing a name in an expression does not declare or assign it.

Form Meaning
score Current routine’s Private score
private.score Explicit Private binding
public.round Shared Public binding
save.bestScore Persistent Save binding
environment.bonus Live read-only setting
private.stats.points Field points on the custom object in stats

Field access follows class visibility and type rules. An unassigned field still needs initialization or a fallback. Expressions cannot bypass Private/Protected restrictions.

Identifiers begin with a letter, _, or $, followed by letters, digits, _, or $. Unicode letters/numbers are supported by the identifier check. Dots separate scopes and fields. Names containing spaces remain usable through Variable items; rename an expression-facing binding if necessary. Preserve capitalization consistently.

Priority, highest first Operators Behavior
Grouping ( ... ) Evaluate the grouped expression
Power/unary ^, unary +, unary - Powers associate right; unary signs enclose a power expression
Multiplication *, /, % Multiply, divide, remainder
Addition +, - Add/subtract; String concatenation for +
Fallback ?? Lazy null/unassigned fallback; associates right

${2 ^ 3} is 8. Use ^ for exponentiation; ** is no longer accepted.

${2 + 3 * 4} is 14; ${(2 + 3) * 4} is 20; ${2 ^ 3 ^ 2} is 512. ${-2 ^ 2} is -4; use ${(-2) ^ 2} for 4. Parentheses make mixed signs/powers easier to read.

Division by zero and non-finite results report errors rather than producing Infinity or NaN. Remainder is not a guarantee of a nonnegative mathematical modulo for negative inputs.

Quoted Strings may use single or double quotes inside an expression:

${'Round ' + public.round}
${"Score: " + (private.score + 1)}

If either operand of + is a String, it joins text. Otherwise arithmetic requires Numbers. '5' + 2 produces text 52, not Number 7. String escape sequences include \n, \t, and \r; a backslash can escape a quote. Number constants support decimal/scientific notation. true, false, and null are constants, but they do not make a valid non-null Number result by themselves.

${save.bestScore ?? 0}
${private.nickname ?? 'Guest'}

?? evaluates its fallback only when the primary is null or unassigned. It does not change the primary binding. An undeclared name remains a declaration/type error; declare it first. Division errors, invalid field access, and other failures are not hidden by fallback.

Both branches must have compatible types. Coalescing a nullable Number with 0 can supply a non-null Number. Coalescing it with a String is not a way to silently change its declared type.

Escape the opening marker in a String:

Write \${private.score} to show the syntax.

The displayed text contains ${private.score} instead of evaluating it. Escaping the only marker in a Number does not produce a Number expression.

Expressions support the operators above, names, fields, constants, and grouping. They do not support method calls, Java/JavaScript APIs, arbitrary script execution, collection indexing syntax, comparisons such as >, or Boolean operators such as &&. Use visual If blocks and the operation reference for those tasks.

Current bounds include 32,768 input characters, 32,768 output characters, 64 parser nesting levels, 1,024 expression nodes, and an 8,192-step evaluation allowance. Particular input dialogs can impose smaller limits (the common text form is capped at 8,192 characters). Plot execution budgets also apply. Resource-limit failures cannot be treated as ordinary catchable expression errors.

Symptom Check
Undeclared expression variable Create the typed binding; check scope and spelling
Variable/field is unassigned Assign it first or use a compatible fallback
Number expression must produce a non-null Number Remove surrounding text, fix types, coalesce nullable values
Unclosed expression Close } and any quoted String
Unexpected syntax Remove unsupported calls/operators; check parentheses
Old value still appears Compile the draft; check the active build and scope

See the compact syntax reference, fields, and environment settings.