Skip to content

SJON Reference

PNGine source is SJON: S-expression forms validated against the WebGPU schema in schema/pngine.sjon. Each form maps to a WebGPU resource or operation.

PNGine is a host of the SJON language: SJON owns the syntax, validation, cross-reference resolution, expressions and sugar lowering, while PNGine owns the schema above, the pngine/* lowering hooks (the compiler steps that expand sugar into ordinary forms), and bytecode emission. For the language itself (reader syntax, value kinds, how a schema is written), see the SJON documentation.

Every named form also requires its :name; the column below lists what else the form cannot compile without.

Form Purpose Required
(shader-module …) Named WGSL module :code
(buffer …) GPU buffer :usage, and a size from :size, :data, :index-of or :file
(texture …) GPU texture :size, :format, :usage
(texture-view …) Explicit view over a texture :texture
(sampler …) Texture sampler -
(query-set …) Occlusion / timestamp queries :type, :count
(bind-group-layout …) Explicit bind group layout - (an (entry …) per binding is usual; an empty layout is legal WebGPU)
(pipeline-layout …) Explicit pipeline layout :bind-group-layouts
(bind-group …) Resource binding :layout
(render-pipeline …) Render pipeline :layout, (vertex …)
(compute-pipeline …) Compute pipeline :layout, (compute …)
(render-pass …) Render pass an attachment (a pass with attachments alone is a clear-only pass)
(compute-pass …) Compute pass :pipeline, one (dispatch …)
(render-bundle …) Pre-recorded draw sequence :color-formats, one (draw …)
(frame …) Frame execution :perform
(data …) Embedded data / shapes :float32, a shape sub-form, or :file
(queue …) Queue operations - (an empty queue is legal; several actions are usual)
(image-bitmap …) Decoded image → texture :data
(wasm-call …) WASM function call :file, :func, :returns
(init …) One-shot compute init (sugar) :buffer, :module, :workgroups
(pass-graph …) Shader-art (pass …) sugar one (pass …)
(define …) Compile-time constant :value
(limits …) Raised device limits (singleton) -
(canvas …) Canvas alpha mode (singleton) -
  • (data …) - Embedded float arrays, shape generators, image files, or WASM-generated bytes
  • (queue …) - Buffer writes, copies, and query resolves
  • (wasm-call …) - Call WASM module functions each frame
  • References - Bare identifier resolution and special values
  • Expressions - Compile-time arithmetic and constants

A few capabilities are deliberately absent today:

  • Multi-file documents. There is no include or import form; keep every shader, resource, pipeline, pass and frame in a single .sjon file.
  • Shader fragment composition. (shader-module …) holds one self-contained WGSL module as opaque text; there is no fragment/imports mechanism. Repeat shared helper code in each module that needs it.
  • Timeline / scene scheduling. SJON models a frame loop; drive scene changes from the JavaScript API instead.
(form-name :key value :flag true
(sub-form positional :key value)
[array of items])
; comments start with a semicolon
Type Example Description
String "WGSL code" / """multi-line""" Quoted / triple-quoted text
Number 123, 0.5 Decimal or float
Boolean true, false Boolean values
Symbol myName, triangle-list Bare identifier (enum or cross-ref)
Array [a b c] Space-separated list
Sub-form (vertex :module code :entry vs) Positional nested form
Expression (* NUM 16) Compile-time arithmetic

Resources are referenced by name. SJON’s validator resolves identifiers document-wide against the declared forms:

:pipeline mainPipeline ; resolves to a (render-pipeline …) or (compute-pipeline …)
:module shader ; resolves to a (shader-module …)
:buffer vertices ; resolves to a (buffer …)

Names live in one namespace across every form kind, so a buffer and a texture cannot share one, and the built-in spellings (canvas, context-current-texture, preferred-canvas-format, pngine-inputs) cannot be declared at all.

See References for complete resolution rules.