Update reference SX spec to match sx.js macros branch (CSSX, dict literals, new primitives)
- eval.sx: Add defstyle, defkeyframes, defhandler special forms; add ho-for-each
- parser.sx: Add dict {...} literal parsing and quasiquote/unquote sugar
- primitives.sx: Add parse-datetime, split-ids, css, merge-styles primitives
- render.sx: Add StyleValue handling, SVG filter elements, definition forms in render, fix render-to-html to handle HTML tags directly
- bootstrap_js.py: Add StyleValue type, buildKeyframes, isEvery platform helper, new primitives (format-date, parse-datetime, split-ids, css, merge-styles), dict/quasiquote parser, expose render functions as primitives
- sx-ref.js: Regenerated — 132/132 tests passing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,11 +18,13 @@
|
||||
;; ident → [a-zA-Z_~*+\-><=/!?&] [a-zA-Z0-9_~*+\-><=/!?.:&]*
|
||||
;; comment → ';' to end of line (discarded)
|
||||
;;
|
||||
;; Quote sugar (optional — not used in current SX):
|
||||
;; '(expr) → (quote expr)
|
||||
;; Dict literal:
|
||||
;; {key val ...} → dict object (keys are keywords or expressions)
|
||||
;;
|
||||
;; Quote sugar:
|
||||
;; `(expr) → (quasiquote expr)
|
||||
;; ~(expr) → (unquote expr)
|
||||
;; ~@(expr) → (splice-unquote expr)
|
||||
;; ,(expr) → (unquote expr)
|
||||
;; ,@(expr) → (splice-unquote expr)
|
||||
;; ==========================================================================
|
||||
|
||||
|
||||
@@ -81,6 +83,37 @@
|
||||
(advance-pos!)
|
||||
(scan-next))
|
||||
|
||||
;; Open brace (dict literal)
|
||||
(= ch "{")
|
||||
(do (append! tokens (list "lbrace" "{" line col))
|
||||
(advance-pos!)
|
||||
(scan-next))
|
||||
|
||||
;; Close brace
|
||||
(= ch "}")
|
||||
(do (append! tokens (list "rbrace" "}" line col))
|
||||
(advance-pos!)
|
||||
(scan-next))
|
||||
|
||||
;; Quasiquote sugar
|
||||
(= ch "`")
|
||||
(do (advance-pos!)
|
||||
(let ((inner (scan-next-expr)))
|
||||
(append! tokens (list "quasiquote" inner line col))
|
||||
(scan-next)))
|
||||
|
||||
;; Unquote / splice-unquote
|
||||
(= ch ",")
|
||||
(do (advance-pos!)
|
||||
(if (and (< pos len-src) (= (nth source pos) "@"))
|
||||
(do (advance-pos!)
|
||||
(let ((inner (scan-next-expr)))
|
||||
(append! tokens (list "splice-unquote" inner line col))
|
||||
(scan-next)))
|
||||
(let ((inner (scan-next-expr)))
|
||||
(append! tokens (list "unquote" inner line col))
|
||||
(scan-next))))
|
||||
|
||||
;; Keyword
|
||||
(= ch ":")
|
||||
(do (append! tokens (scan-keyword)) (scan-next))
|
||||
@@ -229,6 +262,10 @@
|
||||
(do (set! pos (inc pos))
|
||||
(parse-list tokens "rbracket"))
|
||||
|
||||
"lbrace"
|
||||
(do (set! pos (inc pos))
|
||||
(parse-dict tokens))
|
||||
|
||||
"string" (do (set! pos (inc pos)) (nth tok 1))
|
||||
"number" (do (set! pos (inc pos)) (nth tok 1))
|
||||
"boolean" (do (set! pos (inc pos)) (nth tok 1))
|
||||
@@ -261,6 +298,28 @@
|
||||
items)))
|
||||
|
||||
|
||||
(define parse-dict
|
||||
(fn (tokens)
|
||||
;; Parse {key val key val ...} until "rbrace" token.
|
||||
;; Returns a dict (plain object).
|
||||
(let ((result (dict)))
|
||||
(define parse-dict-loop
|
||||
(fn ()
|
||||
(if (>= pos (len tokens))
|
||||
(error "Unterminated dict")
|
||||
(if (= (first (nth tokens pos)) "rbrace")
|
||||
(do (set! pos (inc pos)) nil) ;; done
|
||||
(let ((key-expr (parse-expr tokens))
|
||||
(key-str (if (= (type-of key-expr) "keyword")
|
||||
(keyword-name key-expr)
|
||||
(str key-expr)))
|
||||
(val-expr (parse-expr tokens)))
|
||||
(dict-set! result key-str val-expr)
|
||||
(parse-dict-loop))))))
|
||||
(parse-dict-loop)
|
||||
result)))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Serializer — AST → SX source text
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user