Phase 7a: affinity annotations + fix parser escape sequences

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>
This commit is contained in:
2026-03-07 23:53:33 +00:00
parent 81d8e55fb0
commit a70ff2b153
19 changed files with 540 additions and 224 deletions

View File

@@ -223,3 +223,43 @@
(deftest "leaf component is pure"
(assert-true (component-pure? "~dep-leaf" (test-env) (list "fetch-data")))))
;; --------------------------------------------------------------------------
;; 6. render-target — boundary decision with affinity
;; --------------------------------------------------------------------------
;; Components with explicit affinity annotations
(defcomp ~dep-force-client (&key x)
:affinity :client
(div (fetch-data "/api") x))
(defcomp ~dep-force-server (&key x)
:affinity :server
(div x))
(defcomp ~dep-auto-pure (&key x)
(div x))
(defcomp ~dep-auto-io (&key x)
(div (fetch-data "/api")))
(defsuite "render-target"
(deftest "pure auto component targets client"
(assert-equal "client" (render-target "~dep-auto-pure" (test-env) (list "fetch-data"))))
(deftest "IO auto component targets server"
(assert-equal "server" (render-target "~dep-auto-io" (test-env) (list "fetch-data"))))
(deftest "affinity client overrides IO to client"
(assert-equal "client" (render-target "~dep-force-client" (test-env) (list "fetch-data"))))
(deftest "affinity server overrides pure to server"
(assert-equal "server" (render-target "~dep-force-server" (test-env) (list "fetch-data"))))
(deftest "leaf component targets client"
(assert-equal "client" (render-target "~dep-leaf" (test-env) (list "fetch-data"))))
(deftest "unknown name targets server"
(assert-equal "server" (render-target "~nonexistent" (test-env) (list "fetch-data")))))