I've found two bugs in the transpiled code. Here's my analysis:
Issue 1: Screen output never flushes (primary visible bug)
The screen output goroutine at /tmp/life.go:469-481 uses a bufio.NewWriter with the default 4096-byte buffer. Output only flushes when:
- Byte 255 is received (a special flush marker) — never sent by life.occ
- The buffer fills up to 4096 bytes
In edit mode, each cursor movement writes only ~8-24 bytes to the screen channel. This never reaches 4096 bytes, so nothing appears on the terminal. The editor is actually processing keys correctly — the cursor coordinates are updating — but the output is stuck in the buffer.
The reason "Idle" is visible: when idle, the busy-wait loop (see issue 2) calls display_activity thousands of times per second, quickly filling the 4096-byte buffer and triggering a flush.
Fix: Auto-flush the buffer when the channel is drained. After w.WriteByte(b), add:
if len(screen) == 0 {
w.Flush()
}
This flushes after each burst of output while still batching rapid sequential writes.
Issue 2: PRI ALT SKIP guard causes busy-wait (CPU spin)
The controller's PRI ALT at life.occ:395-412:
PRI ALT
(activity <> editing) & keyboard ? char -- guard 1
...
(activity <> idle) & SKIP -- guard 2
...
Translates to a Go select with default (/tmp/life.go:331-351). The problem: Go's default fires unconditionally when no channel is ready, ignoring the SKIP guard's boolean condition (activity <> idle).
When activity = idle: the SKIP guard should be disabled and the ALT should block on the keyboard channel. Instead, the default branch fires, checks activity != idle → false, does nothing, and loops — spinning the CPU at 100%.
This is a codegen bug: when the only non-channel alternative is a guarded SKIP, the default case should be conditional on the boolean guard.
Want me to fix these? Issue 1 is a simple preamble change. Issue 2 is a more involved ALT codegen change.