summaryrefslogtreecommitdiff
path: root/ocaml/POKES_EXPLAINED.md
diff options
context:
space:
mode:
Diffstat (limited to 'ocaml/POKES_EXPLAINED.md')
-rw-r--r--ocaml/POKES_EXPLAINED.md256
1 files changed, 256 insertions, 0 deletions
diff --git a/ocaml/POKES_EXPLAINED.md b/ocaml/POKES_EXPLAINED.md
new file mode 100644
index 0000000..f0eb571
--- /dev/null
+++ b/ocaml/POKES_EXPLAINED.md
@@ -0,0 +1,256 @@
+# What is a "Poke"? Understanding Urbit Events
+
+## The Big Picture
+
+**Poke** is Urbit's term for "send an event to Arvo (the kernel)".
+
+Think of it like this:
+- **Unix**: You write to a file descriptor or call `ioctl()`
+- **Windows**: You send a message to a window handle
+- **Urbit**: You **poke** Arvo with an **ovum** (event)
+
+## Event Structure: Ovum
+
+An `ovum` (plural: ova) is a single event. It's a simple pair:
+
+```
+ovum = [wire card]
+```
+
+Where:
+- **wire**: A path identifying WHERE this event came from/goes to
+ - Example: `/d/term/1` (Dill terminal 1)
+ - Example: `/g/http/0v1a2b3c` (Eyre HTTP request)
+ - Example: `/a/peer/~zod` (Ames network to ~zod)
+
+- **card**: The actual action/data, structured as `[tag payload]`
+ - Example: `[%belt %ret]` (keyboard Return key)
+ - Example: `[%born ~]` (HTTP server started)
+ - Example: `[%send ...]` (Network packet)
+
+## The Poke Cycle
+
+```
+┌─────────────┐
+│ Runtime │ (Vere, Neovere, Sword)
+└──────┬──────┘
+ │
+ │ 1. Poke with ovum [wire card]
+ │
+ ▼
+┌─────────────┐
+│ Arvo │ (The kernel)
+└──────┬──────┘
+ │
+ │ 2. Returns [effects new_kernel]
+ │
+ ▼
+┌─────────────┐
+│ Runtime │
+└──────┬──────┘
+ │
+ │ 3. Execute effects
+ │ (print to terminal, send network packet, etc.)
+ │
+ └─────► Real world I/O
+```
+
+## How Poke Actually Works
+
+From the Vere C code (and our OCaml port):
+
+```ocaml
+(* Get poke function from kernel *)
+let poke_arm = slot 23 kernel in
+
+(* Create gate (function) *)
+let gate = nock kernel poke_arm in
+
+(* Call gate with event *)
+let result = slam gate event in
+
+(* Result is [effects new_kernel] *)
+match result with
+| Cell (effects, new_kernel) ->
+ (* Update kernel state *)
+ kernel := new_kernel;
+ (* Execute effects *)
+ execute_effects effects
+```
+
+## Types of Events (Common Cards)
+
+### Terminal (Dill)
+```
+Wire: /d/term/1
+
+Inputs (to Arvo):
+ [%belt %ret] - Return key
+ [%belt %bac] - Backspace
+ [%belt [%txt "hello"]] - Text input
+
+Outputs (from Arvo):
+ [%blit %lin "text"] - Print line
+ [%blit %clr] - Clear screen
+ [%blit %hop 5] - Move cursor
+```
+
+### HTTP (Eyre)
+```
+Wire: /g/http/0v...
+
+Inputs:
+ [%request request-data] - HTTP request
+
+Outputs:
+ [%http-response response] - HTTP response
+```
+
+### Network (Ames)
+```
+Wire: /a/peer/~zod
+
+Inputs:
+ [%hear packet] - Received packet
+
+Outputs:
+ [%send packet] - Send packet
+```
+
+### Timer (Behn)
+```
+Wire: /b/wait/...
+
+Inputs:
+ [%wake ~] - Timer fired
+
+Outputs:
+ [%doze time] - Set next timer
+```
+
+## Boot vs Runtime
+
+### During Boot (Lifecycle)
+```ocaml
+(* Boot uses a special formula, not poke! *)
+let lifecycle = [2 [0 3] [0 2]] in
+let kernel = nock event_list lifecycle in
+(* No effects during boot - just builds kernel *)
+```
+
+Boot events are **batch processed** via the lifecycle formula.
+They build up the kernel state but don't produce effects.
+
+### After Boot (Runtime)
+```ocaml
+(* Runtime uses poke for each event *)
+let effects = poke kernel event in
+(* Effects need to be executed! *)
+```
+
+Runtime events are **individually poked** and produce effects that must be executed.
+
+## Why Two Different Mechanisms?
+
+**Lifecycle** (boot):
+- Process many events as a batch
+- Pure state building
+- No I/O needed
+- Fast initialization
+
+**Poke** (runtime):
+- Process one event at a time
+- Produces side effects
+- Needs I/O execution
+- Interactive operation
+
+## Our Implementation
+
+### State.poke (lib/state.ml:66)
+```ocaml
+let poke state event =
+ (* Get poke gate from kernel slot 23 *)
+ let formula = slot poke_formula_axis kernel in
+ let gate = nock_on kernel formula in
+
+ (* Slam gate with event *)
+ let result = slam_on gate event in
+
+ (* Extract effects and new kernel *)
+ match result with
+ | Cell (effects, new_core) ->
+ state.roc <- new_core; (* Update kernel *)
+ state.eve <- succ eve; (* Increment event number *)
+ effects (* Return effects *)
+```
+
+### What We Need To Do Next
+
+1. ✅ **Poke works** - ~11,000 pokes/second
+2. ✅ **Effects returned** - Structure is correct
+3. ⏳ **Parse effects** - Extract wire/card from effect list
+4. ⏳ **Route effects** - Send to appropriate driver (Dill, Eyre, Ames)
+5. ⏳ **Execute effects** - Actually do the I/O
+6. ⏳ **Event loop** - Continuous input → poke → effects → output
+
+## Example: Terminal Input Flow
+
+```
+1. User types "hello" and hits Enter
+
+2. Terminal driver creates belt event:
+ ovum = [/d/term/1 [%belt [%txt "hello"]]]
+ [/d/term/1 [%belt %ret]]
+
+3. Poke Arvo:
+ effects = State.poke state ovum
+
+4. Arvo processes input, maybe runs dojo command
+
+5. Arvo returns effects:
+ [
+ [/d/term/1 [%blit [%lin "result here"]]]
+ [/d/term/1 [%blit [%lin "~zod:dojo> "]]]
+ ]
+
+6. Dill driver executes effects:
+ - Print "result here" to terminal
+ - Print prompt "~zod:dojo> "
+
+7. Wait for next input
+```
+
+## Performance Notes
+
+From our benchmarks:
+- **Poke speed**: ~11,000 pokes/second (0.09ms each)
+- **Boot time**: ~1s for full solid pill
+- **Memory**: No limit (OCaml GC manages it)
+
+This is plenty fast for interactive use!
+
+## Key Insight
+
+**Poke is just a function call into the kernel.**
+
+There's no magic. It's:
+1. Load kernel from memory
+2. Call its poke function (slot 23)
+3. Get back effects + new kernel
+4. Replace old kernel with new kernel
+5. Execute the effects
+
+The genius is that the **entire OS state** is in that kernel noun, and poke is a pure function that transforms it.
+
+## References
+
+- `vere/pkg/vere/mars.c` - C implementation
+- `vere/pkg/noun/vortex.c:u3v_poke()` - Poke implementation
+- `docs/runtime/api.md` - API documentation (check `/docs/runtime/`)
+- Arvo source: `sys/arvo.hoon` in urbit/urbit repo
+
+## See Also
+
+- `BOOT_COMPARISON.md` - Why lifecycle ≠ poke
+- `EFFECTS.md` - Effects processing architecture
+- `LOOM.md` - Memory management (or lack thereof!)