dataflow graph
Every program is a graph of values flowing into each other. The runtime knows what depends on what — so it only recomputes what changed.
Petal is a dataflow language built for live editing. Write a sketch, watch it draw to a canvas in real time, and rewrite it mid-flight — your state keeps running.
The same Petal source on the left is compiled to WASM and running on the right. It’s a real program — physics, persistent state, mouse input. Click the canvas to fling in more balls.
1// Bouncing Balls — click to add more balls.2// Demonstrates state, frame timing, mouse input, and the drawing API.3 4state balls = []5 6let sw = float(screen_width())7let sh = float(screen_height())8let delta = dt()9 10// Seed with a few balls on first frame11if len(balls) == 0 then12 for i in range(0, 12) do13 let f = float(i)14 push(balls, {15 x: 50.0 + f * 60.0,16 y: 80.0 + f * 20.0,17 vx: 80.0 + f * 15.0,18 vy: 40.0 - f * 8.0,19 r: 12.0 + f * 1.5,20 cr: 80 + (i * 23) % 175,21 cg: 120 + (i * 47) % 135,22 cb: 200 - (i * 31) % 15023 })24 end25end26 27// Add a ball on click28if mouse_pressed(1) then29 let mx = float(mouse_x())30 let my = float(mouse_y())31 push(balls, {32 x: mx, y: my,33 vx: random(-200.0, 200.0),34 vy: random(-200.0, 0.0),35 r: random(8.0, 28.0),36 cr: int(random(80.0, 255.0)),37 cg: int(random(80.0, 255.0)),38 cb: int(random(80.0, 255.0))39 })40end41 42let gravity = 600.043 44// Physics step45let new_balls = []46for b in balls do47 let nvy = b.vy + gravity * delta48 let nx = b.x + b.vx * delta49 let ny = b.y + nvy * delta50 let nvx = b.vx51 52 // Wall collisions53 let final_vx = nvx54 let final_x = nx55 if nx - b.r < 0.0 then56 final_x = b.r57 final_vx = -nvx * 0.8558 end59 if nx + b.r > sw then60 final_x = sw - b.r61 final_vx = -nvx * 0.8562 end63 64 let final_vy = nvy65 let final_y = ny66 if ny + b.r > sh then67 final_y = sh - b.r68 final_vy = -nvy * 0.8569 end70 if ny - b.r < 0.0 then71 final_y = b.r72 final_vy = -nvy * 0.8573 end74 75 push(new_balls, {76 x: final_x, y: final_y,77 vx: final_vx, vy: final_vy,78 r: b.r, cr: b.cr, cg: b.cg, cb: b.cb79 })80end81balls = new_balls82 83// === Drawing ===84clear(14, 16, 28)85 86for b in balls do87 // soft outer halo88 draw_circle(int(b.x), int(b.y), int(b.r + 3.0), b.cr / 4, b.cg / 4, b.cb / 4)89 draw_circle(int(b.x), int(b.y), int(b.r), b.cr, b.cg, b.cb)90 draw_circle(int(b.x - b.r * 0.3), int(b.y - b.r * 0.3), int(b.r * 0.35),91 min(255, b.cr + 60), min(255, b.cg + 60), min(255, b.cb + 60))92end93 94draw_text("Bouncing Balls — click to add", 16, 12, 14, 200, 200, 220)95draw_text("count: " ++ str(len(balls)), 16, 32, 12, 150, 150, 180)Every program is a graph of values flowing into each other. The runtime knows what depends on what — so it only recomputes what changed.
Mark a variable as state and it persists across frames and calls — and survives a hot reload. Your simulation keeps running while you edit it.
A step-based evaluator lets you reshape code while it runs. Change a number, rewrite a function, watch the canvas respond instantly.
Petal compiles to WebAssembly and draws straight to a canvas. The whole site runs Petal in your browser — no install required.
Generative art, a playable game, a paint tool — each is a single Petal file compiled in your browser. Open any one in the playground and start poking at it.
A 3D star projection with motion trails. Warp speed, ~30 lines.
open starfield →A little paint program — palette, brush sizes, and a procedurally drawn mandala on first run.
open paint →The playground compiles Petal to WASM as you type and runs it live. Nothing to download — just an editor, a canvas, and the edit loop.