Explicit mutation
Persistent state changes are visible in source instead of being hidden inside arbitrary assignment expressions.
Patch programming language · 0.2 beta.36+
Patch is a change-oriented programming language where persistent mutation is expressed through explicit semantic change operations. The compiler derives operation- and magnitude-aware Change Contracts from the same source-level substrate.
create number score = 0 change score: add 1 show score
Persistent state changes are visible in source instead of being hidden inside arbitrary assignment expressions.
Recipes expose which paths they may change, in which direction, and where provable, by what bounded amount.
Patch currently targets its interpreter, direct WebAssembly, portable C99, standalone web apps and explicit native desktop application paths.
Patch explores whether mutation can be made easier to inspect, constrain, replay and validate by treating change itself as a first-class semantic object. The project combines a small language, Change IR, source-backed GUI design, capability-style constraints and reproducible assurance tooling.
Beta.32 introduced invocation-frame-aware direct-Wasm correspondence for the supported finite-call-tree subset. Current beta.36 Studio, resource and native GUI work expands product behavior without widening that formal claim. Patch does not claim a fully verified compiler.
Patch values are numbers, text, booleans, lists and Things. A Thing is a finite record of named fields. The field names __proto__, prototype and constructor are rejected. Runtime Thing storage is prototype-free, and paths such as player.score only follow own fields.
create thing player: name = "Sam" score = 0 change player: add 10 to score show player.name
Thing equality is structural: two Things compare equal when they have the same own field names and values, independent of declaration order. JSON serialization is not the equality oracle. Direct Wasm and portable C99 stay on the numeric Console subset and fail closed on Things. Thing records are product runtime, not part of the beta.32 Lean runtime-correspondence claim.
A Slider declares its numeric range directly in Patch source. Its changed event receives a finite numeric value. Moving the toolkit control does not itself mutate persistent Patch state.
create number volume = 50
window "Mixer":
slider 0..100 as volume step 5
when volume changed:
change volume:
set = value
step defaults to 1; signed and decimal ranges are supported. A same-name persistent binding must be number state. Patch Studio, Standalone Window Web and the current Windows, macOS and Linux Ready/offline paths preserve native Slider support through Native GUI IR 1.9 / payload v19 / runtime v1.10 using Win32 TRACKBAR, AppKit NSSlider and GTK GtkScale.
The Native GUI IR 1.3, payload v13 and runtime v1.4 Slider line remains a versioned compatibility boundary. Native GUI IR 1.2 / payload v12 / runtime v1.3 remains the frozen compatibility TreeView line and intentionally stays Slider fail-closed. Payload v17/runtime v1.8 remains an explicit Offline Compiler compatibility path. Versioned contracts are not redefined in place.
A ListBox bound to create text remains single-select and its changed handler receives text. A ListBox bound to create list is multi-select in Patch Studio App Preview and Standalone Window Web, direct Win32/AppKit/GTK AOT and current token-free Ready/offline desktop builds. Its handler receives a transient list of selected strings.
create list fruits = ["Banana", "Mango"]
window "Fruit Picker":
listbox "Apple", "Banana", "Cherry", "Mango" as fruits
when fruits changed:
change fruits:
set = value
The toolkit selection itself is not persistent Patch state. Persistence occurs only because the handler executes an explicit semantic change. Native GUI IR 1.1 introduced the list-state ABI; the current Native GUI IR 1.9 / payload v19 / runtime v1.10 line preserves it together with later Menu, TreeView, Slider, Chrome, Shape, PaintBox, Button/ImageList and application-icon extensions.
Table structure and rows live in Patch source. Selecting a row is transient UI interaction and value is the selected row as a list of display strings. Persistence still requires explicit change.
window "People" as main size 520, 320:
table "Name", "Role" as people at 24, 64 size 440, 180:
row "Ada", "Engineer"
row "Grace", "Scientist"
when people changed:
show value
Table originated in Native GUI IR 0.8 / sealed payload v9 / runtime v1.0. The current Native GUI IR 1.9 / payload v19 / runtime v1.10 contract preserves that representation while composing later list, Menu, TreeView, Slider, Chrome, Shape, PaintBox, Button/ImageList and application-icon extensions.
A TreeView declares its hierarchy directly in Patch source. Selection exposes the selected root-to-node display path as a transient text-list event value. Nodes may also carry source-backed image ImageList.item, quoted hint text and a bounded presentation-only state tone: muted, info, success, warning or danger.
create list selected = []
window "Files" as main size 560, 380:
tree as files at 24, 56 size 300, 240:
node "src"
node "compiler.js"
node "parser.js"
when files changed:
change selected:
set = value
Selecting compiler.js yields ["src", "compiler.js"] as transient value. Renderer or native-toolkit selection alone does not mutate persistent state. Native GUI IR 1.2 introduced TreeView; the current IR 1.9 / payload v19 / runtime v1.10 line preserves that hierarchy while composing later Slider, Chrome, Shape, PaintBox, Button/ImageList and application-icon support.
Picture, Shape and PaintBox declarations are ordinary Patch source. ImageList is a nonvisual source-backed collection of project-resource references. Current Ready support remains explicit: Picture has bounded native PNG/JPEG support under native-picture-formats/1.0; Shape and PaintBox have native Ready support; PaintBox includes bounded PNG/JPEG draw image; Buttons may bind image list.item on Web and native Windows/macOS/Linux; Forms may declare icon under window-icon/1.0 for Studio/Web and native application/Form icon packaging.
Current native line: Native GUI IR 1.8 / payload v18 / runtime v1.9 introduced Button/ImageList consumers on Win32, AppKit and GTK. Native GUI IR 1.9 / payload v19 / runtime v1.10 preserves that layer and adds application/Form Window icons plus deterministic Windows PE, macOS app-bundle and Linux desktop icon packaging. Release/digest/source-binding and dual-runtime Offline Compiler promotion evidence is complete, so IR 1.9/v19/runtime v1.10 is the public Ready/offline contract.
window "Counter" as counter size 520, 360 icon "patch-resource:app.icon":
picture as logo from "patch-resource:app.logo" fit cover description "Product logo"
shape ellipse as badge
paintbox as canvas
imagelist as icons size 16, 16:
image open from "patch-resource:icons.open"
button "Open" as open_button image icons.open
PaintBox paint handlers are pure drawing handlers and cannot commit persistent change. Native PaintBox expressions deliberately use bounded literals, count inside repeat and simple number/text/boolean state names; unsupported state references fail closed. ImageList exposes no event in Stage 1. Native Picture keeps default contain/centered/opaque rendering and fail-closes other fit/center/opacity values.
Use Patch Studio for the visual workflow, or download the offline compiler when you want to run, compile and link supported Patch applications directly from your own machine.