GP-Crystal Primitive Catalog
Status: normative. A primitive is a place where Crystal-native code enters GPCR: a def or macro whose body cannot be expressed in renderable elements. Its face — shape, label, category, declared by @[GPCR::Primitive] — renders fully graphically at every call site; its body renders as a Markdown code fence, because it contains AST elements with no graphical rendering. This page is the complete inventory. Growing it is a design event, not an implementation detail. Everything the palette offers beyond this page is a block defined in GPCR — see the GP-Crystal Block Catalog.
Runtime primitives (defs)
| Primitive | Body bottoms out on | Serves |
|---|---|---|
sleep |
event-loop timer | the wait block, timed yields |
forever / repeat n |
scheduler (Fiber.yield at the bottom of every iteration) |
the MicroBlocks loop-scheduling doctrine; the yield needs a carrier def, so these are primitives, not bare Crystal loops |
argument n |
ARGV |
CLI input; the standard entry point's mode selection |
receive-event name |
Channel receive | all hats (on start, on message) |
send-event name |
Channel send | broadcast |
write-stream |
IO write to the gpcr output stream | say; STDOUT by default, redirectable to UI elements, which may tee to the dev-shell |
| monotonic clock read | Time.monotonic |
timer blocks |
random a to b |
rand |
its own face |
| hardware shims | board I/O per node profile (LED, buttons, pins) | set-user-led, read-button, pin blocks |
| file open/read/write | File |
file blocks and the mediated require block — no arbitrary require inside a script |
parse-source |
Crystal::Parser |
source text → node data; the editor path for rendering and editing any file |
stop-all |
runtime halt | its own face (the one runtime primitive outside the def model) |
Compile-time primitives (macros)
Macros are primitives too: their bodies are macro-land code, which is never renderable, but what they produce feeds everything above the line.
| Primitive | What it does |
|---|---|
| block-face reflection | walks defs and their @[GPCR::Primitive]/@[GPCR::Block] annotations, derives each block face (shape, label slots checked against parameters, inputs) — GPCR.blocks_of today |
| body reification | walks a def body's AST and emits it as node-data literals (kind, label parts, children, source text), so a compiled gpcr program carries its own reified tree and can render itself without the compiler library |
| graph registry + standard entry point | reflects the @[GPCR::Graph] defs, self-embeds the program source via their filenames, and generates the standard main (run/render/faces) — GPCR.standard_main, brought in by require "gpcr/main" |
| block contract check | verifies a @[GPCR::Block] body uses only renderable elements — calls to blocks/primitives and Crystal-native forms with node-kind renderings; violation is a compile error |
The node data model these produce is shared with parse-source: two producers, one representation, and the whole rendering pipeline above it — layout, shape drawing, Pikchr emission — is defined blocks operating on that data.
Shape drawings
The four shape drawings (hat, command, reporter, boolean — README, Block shapes) sit below the line today. The aim is to migrate them to blocks that emit Pikchr through write-stream, at which point they leave this page.
Conventions the primitives fix
The event bus provides only start and message events; button-press arrives as a message generator, and new events never grow the language. Time is seconds with native decimals. The output stream is newline-terminated messages. Hardware availability comes from the node profile (the per-machine capability description: LED, display, stdout, pins).