GP-Crystal Block Catalog
Status: normative. The standard library block palette — the union of the MicroBlocks and GP base sets, carried into GPCR. Every entry is either Crystal-native syntax (rendered through node-kind renderings; it is the language and needs no definition) or a block defined in GPCR (@[GPCR::Block] def whose body uses only renderable elements; the compiler enforces that, and inlines the block away). The places Crystal-native code actually enters are all on the GP-Crystal Primitive Catalog page.
Conventions: kebab-case spoken names; hats are on-X-do-Y (when is a Crystal keyword, never used); 0-based indexing with "first"/"last" as spoken sugar for 0/−1; the unit a hat starts is a graph — a @[GPCR::Graph] def in its own fiber.
Events
The DSL defines exactly one hat form, on-event; events are provided by the runtime, not the language.
| Block | MicroBlocks | GP | Definition |
|---|---|---|---|
| on start | when started | when flag clicked | hat over receive-event |
| on message m | when I receive | when I receive | hat over receive-event |
| broadcast m | broadcast | broadcast | over send-event; fire-and-forget — synchronous sequencing is a direct def call, and a multi-receiver join, if ever needed, is a block over WaitGroup |
| every n seconds | — | — | wait inside a hat loop |
| on-condition expr | when <cond> | — | polled; future |
Control
| Block | Form |
|---|---|
| forever / repeat n | primitives — the per-iteration scheduler yield (MicroBlocks doctrine: a tight loop never starves other graphs) needs a carrier def |
| repeat-until / if / if-else / for-each | Crystal-native (until, if/else, .each) |
| wait secs | block over the sleep primitive; decimals native (0.5) |
| wait-until expr | block: until + sleep tick |
| stop-graph | Crystal-native (return) |
| stop-all | primitive (runtime halt) |
Operators and expressions
Typing is compile-time throughout: literals decide kind (whole → Int32, decimal → Float64), mixed arithmetic promotes natively, / is Float64 (// is whole division). Cross-kind reassignment of a variable is caught by the post-apply semantic gate and surfaced as a spoken-grade hint with explicit convert blocks. No silent casts, no runtime tags.
| Block | Form |
|---|---|
| + − × ÷ mod, comparisons, and/or/not, whole-divide, bit ops, indexing | Crystal-native operators |
| abs / min / max | blocks over Crystal-native operators |
| random a to b | primitive |
Variables
Declaration is itself a block; the name is spelled (or picked) once at declaration. Spoken references use the declaration block's {index,gen} address — or the name, since the declared-name set feeds the speech recognizer's biasing vocabulary and recognition stays inside a closed set. Default scope is graph-local; shared at declaration generates a compile-time-typed property on GPCR::Shared (Crystal has no globals — top-level locals are file-local and invisible inside defs).
| Block | Form |
|---|---|
| declare [shared] variable name [initial val] | Crystal-native assignment + registry entry |
| set / change-by / value-of | Crystal-native |
Lists and strings
Faces over single Crystal-native expressions (indexing, +, .size, <<, .includes?, .split).
| Block | Form |
|---|---|
| list of / add / delete item / item of / length / contains | blocks |
| join / letter of / split | blocks |
Input and output
| Block | Form |
|---|---|
| say x | block: newline + write-stream |
| set-user-led / read-button / pins | primitives (hardware shims) |
| timer / reset-timer | blocks: monotonic clock + shared variable |
Functions
| Block | Form |
|---|---|
| define name (params) / return | Crystal-native — def is the block-definer; a defined block is a callable, inlinable graph |
require is not a block: it is a Crystal statement with its own prose rendering (require path). A program needs exactly one — require "gpcr/main" brings in the palette, the runtime, and the standard entry point.
Out of scope here
UI elements route through the Pikchr UI Subset. Tables are sequenced after the base palette (an implementation is parked on session branch 876c7f9a). Fibers stay implicit under graphs — no cloning or explicit thread blocks.
Implementation sequencing
First the machinery that makes blocks exist: the annotations, the reflection macros, the primitive floor, def rendering. Then this palette, written in GPCR — the direct measure of the self-hosting goal. Then the remaining blocks (every, wait-until, on-condition, timer) and the semantic type gate. Then tables revive from the parked branch.