Fix Pretext island: library functions inside define-library begin block

Root cause: sx_insert_near placed break-lines-greedy, pretext-position-line,
pretext-layout-lines OUTSIDE the define-library begin block. The bytecode
compiler only compiles forms inside begin as STORE_GLOBAL — forms outside
are invisible to the browser VM.

Fix: moved all function definitions inside (begin ...) of (define-library).
Bytecode now includes all 17 functions (11K compiled, was 9K).

Browser load-sxbc: simplified VmSuspended handling — just catch and
continue, since STORE_GLOBAL ops already ran before the import OP_PERFORM.
sync_vm_to_env copies them to global_env.

Island now calls break-lines and pretext-layout-lines from bytecode-compiled
library — runs on VM, not CEK interpreter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-12 17:53:50 +00:00
parent 45209caf73
commit 7ec42386fb
14 changed files with 275 additions and 316 deletions

View File

@@ -13,21 +13,6 @@
;; Knuth-Plass optimal line breaking (DP over break candidates).
;; Liang's hyphenation (trie over character patterns).
(define
pretext-position-line
(fn
(words widths gap-w)
(let
loop
((i 0) (x 0) (acc (list)))
(if
(>= i (len words))
acc
(loop
(+ i 1)
(+ x (nth widths i) gap-w)
(append acc (list {:width (nth widths i) :x x :word (nth words i)})))))))
(define-library
(sx text-layout)
(export
@@ -149,6 +134,32 @@
(let
((ends (append (rest starts) (list n))))
(map-indexed (fn (i s) (list s (nth ends i))) starts)))))))
(define
break-lines-greedy
(fn
(widths space-width max-width)
(let
((n (len widths)))
(if
(= n 0)
(list)
(let
((lines (list)) (start 0) (used 0))
(for-each
(fn
(i)
(let
((w (nth widths i))
(needed (if (= i start) w (+ used space-width w))))
(if
(and (> needed max-width) (not (= i start)))
(do
(set! lines (append lines (list (list start i))))
(set! start i)
(set! used w))
(set! used needed))))
(range n))
(append lines (list (list start n))))))))
(define
position-line
(fn
@@ -181,6 +192,45 @@
(line-widths (slice widths start end)))
(position-line line-words line-widths space-width x0 y))))
line-ranges)))
(define
pretext-position-line
(fn
(words widths gap-w)
(let
loop
((i 0) (x 0) (acc (list)))
(if
(>= i (len words))
acc
(loop
(+ i 1)
(+ x (nth widths i) gap-w)
(append acc (list {:width (nth widths i) :x x :word (nth words i)})))))))
(define
pretext-layout-lines
(fn
(words widths ranges space-width max-width line-height)
(let
((n-lines (len ranges)))
(map
(fn
(line-idx)
(let
((range (nth ranges line-idx))
(y (* line-idx line-height)))
(let
((start (first range)) (end (nth range 1)))
(let
((lw (slice words start end))
(lwid (slice widths start end)))
(let
((total-w (reduce + 0 lwid))
(n-gaps (max 1 (- (len lw) 1)))
(is-last (= line-idx (- n-lines 1))))
(let
((gap (if is-last space-width (/ (- max-width total-w) n-gaps))))
{:y y :words (pretext-position-line lw lwid gap)}))))))
(range n-lines)))))
(define
make-hyphenation-trie
(fn
@@ -327,31 +377,4 @@
(lh (or line-height 1.4)))
(layout-paragraph words f s w lh))))))
(define
break-lines-greedy
(fn
(widths space-width max-width)
(let
((n (len widths)))
(if
(= n 0)
(list)
(let
((lines (list)) (start 0) (used 0))
(for-each
(fn
(i)
(let
((w (nth widths i))
(needed (if (= i start) w (+ used space-width w))))
(if
(and (> needed max-width) (not (= i start)))
(do
(set! lines (append lines (list (list start i))))
(set! start i)
(set! used w))
(set! used needed))))
(range n))
(append lines (list (list start n))))))))
(import (sx text-layout))