Add page-render-plan to deps.sx: given page source + env + IO names,
computes a dict mapping each needed component to "server" or "client",
with server/client lists and IO dep collection. 5 new spec tests.
Integration:
- PageDef.render_plan field caches the plan at registration
- compute_page_render_plans() called from auto_mount_pages()
- Client page registry includes :render-plan per page
- Affinity demo page shows per-page render plans
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add :affinity :client/:server/:auto annotations to defcomp, with
render-target function combining affinity + IO analysis. Includes
spec (eval.sx, deps.sx), tests, Python evaluator, and demo page.
Fix critical bug: Python SX parser _ESCAPE_MAP was missing \r and \0,
causing bootstrapped JS parser to treat 'r' as whitespace — breaking
all client-side SX parsing. Also add \0 to JS string emitter and
fix serializer round-tripping for \r and \0.
Reserved word escaping: bootstrappers now auto-append _ to identifiers
colliding with JS/Python reserved words (e.g. default → default_,
final → final_), so the spec never needs to avoid host language keywords.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
test.sx now defines deftest/defsuite as macros. Any host that provides
5 platform functions (try-call, report-pass, report-fail, push-suite,
pop-suite) can evaluate the file directly — no bootstrap compilation
step needed for JS.
- Added defmacro for deftest (wraps body in thunk, catches via try-call)
- Added defmacro for defsuite (push/pop suite context stack)
- Created run.js: sx-browser.js evaluates test.sx directly (81/81 pass)
- Created run.py: Python evaluator evaluates test.sx directly (81/81 pass)
- Deleted bootstrap_test_js.py and generated test_sx_spec.js
- Updated testing docs page to reflect self-executing architecture
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>