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:
@@ -491,17 +491,37 @@
|
||||
|
||||
(define sf-defcomp
|
||||
(fn (args env)
|
||||
;; (defcomp ~name (params) [:affinity :client|:server] body)
|
||||
;; Body is always the last element. Optional keyword annotations
|
||||
;; may appear between the params list and the body.
|
||||
(let ((name-sym (first args))
|
||||
(params-raw (nth args 1))
|
||||
(body (nth args 2))
|
||||
(body (last args))
|
||||
(comp-name (strip-prefix (symbol-name name-sym) "~"))
|
||||
(parsed (parse-comp-params params-raw))
|
||||
(params (first parsed))
|
||||
(has-children (nth parsed 1)))
|
||||
(let ((comp (make-component comp-name params has-children body env)))
|
||||
(has-children (nth parsed 1))
|
||||
(affinity (defcomp-kwarg args "affinity" "auto")))
|
||||
(let ((comp (make-component comp-name params has-children body env affinity)))
|
||||
(env-set! env (symbol-name name-sym) comp)
|
||||
comp))))
|
||||
|
||||
(define defcomp-kwarg
|
||||
(fn (args key default)
|
||||
;; Search for :key value between params (index 2) and body (last).
|
||||
(let ((end (- (len args) 1))
|
||||
(result default))
|
||||
(for-each
|
||||
(fn (i)
|
||||
(when (and (= (type-of (nth args i)) "keyword")
|
||||
(= (keyword-name (nth args i)) key)
|
||||
(< (+ i 1) end))
|
||||
(let ((val (nth args (+ i 1))))
|
||||
(set! result (if (= (type-of val) "keyword")
|
||||
(keyword-name val) val)))))
|
||||
(range 2 end 1))
|
||||
result)))
|
||||
|
||||
(define parse-comp-params
|
||||
(fn (params-expr)
|
||||
;; Parse (&key param1 param2 &children) → (params has-children)
|
||||
@@ -879,7 +899,7 @@
|
||||
;;
|
||||
;; Constructors:
|
||||
;; (make-lambda params body env) → Lambda
|
||||
;; (make-component name params has-children body env) → Component
|
||||
;; (make-component name params has-children body env affinity) → Component
|
||||
;; (make-macro params rest-param body env name) → Macro
|
||||
;; (make-thunk expr env) → Thunk
|
||||
;;
|
||||
@@ -893,6 +913,7 @@
|
||||
;; (component-body c) → expr
|
||||
;; (component-closure c) → env
|
||||
;; (component-has-children? c) → boolean
|
||||
;; (component-affinity c) → "auto" | "client" | "server"
|
||||
;; (macro-params m) → list of strings
|
||||
;; (macro-rest-param m) → string or nil
|
||||
;; (macro-body m) → expr
|
||||
|
||||
Reference in New Issue
Block a user