Unicode escapes, variadic infix fix, spreads demos, scoped-effects + foundations plans
- Add \uXXXX unicode escape support to parser.py and parser.sx spec - Add char-from-code primitive (Python chr(), JS String.fromCharCode()) - Fix variadic infix operators in both bootstrappers (js.sx, py.sx) — (+ a b c d) was silently dropping terms, now left-folds correctly - Rebootstrap sx_ref.py and sx-browser.js with all fixes - Fix 3 pre-existing map-dict test failures in shared/sx/tests/run.py - Add live demos alongside examples in spreads essay (side-by-side layout) - Add scoped-effects plan: algebraic effects as unified foundation for spread/collect/island/lake/signal/context - Add foundations plan: CEK machine, the computational floor, three-axis model (depth/topology/linearity), Curry-Howard correspondence - Route both plans in page-functions.sx and nav-data.sx Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1259,11 +1259,21 @@
|
||||
|
||||
(define js-emit-infix
|
||||
(fn ((op :as string) (args :as list))
|
||||
(let ((js-op (js-op-symbol op)))
|
||||
(if (and (= (len args) 1) (= op "-"))
|
||||
(str "(-" (js-expr (first args)) ")")
|
||||
(str "(" (js-expr (first args))
|
||||
" " js-op " " (js-expr (nth args 1)) ")")))))
|
||||
(let ((js-op (js-op-symbol op))
|
||||
(n (len args)))
|
||||
(cond
|
||||
(and (= n 1) (= op "-"))
|
||||
(str "(-" (js-expr (first args)) ")")
|
||||
(= n 2)
|
||||
(str "(" (js-expr (first args))
|
||||
" " js-op " " (js-expr (nth args 1)) ")")
|
||||
;; Variadic: left-fold (a op b op c op d ...)
|
||||
:else
|
||||
(let ((result (js-expr (first args))))
|
||||
(for-each (fn (arg)
|
||||
(set! result (str "(" result " " js-op " " (js-expr arg) ")")))
|
||||
(rest args))
|
||||
result)))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
@@ -80,6 +80,9 @@
|
||||
|
||||
;; -- Atom readers --
|
||||
|
||||
(define hex-digit-value :effects []
|
||||
(fn (ch) (index-of "0123456789abcdef" (lower ch))))
|
||||
|
||||
(define read-string :effects []
|
||||
(fn ()
|
||||
(set! pos (inc pos)) ;; skip opening "
|
||||
@@ -95,14 +98,29 @@
|
||||
(= ch "\\")
|
||||
(do (set! pos (inc pos))
|
||||
(let ((esc (nth source pos)))
|
||||
(set! buf (str buf
|
||||
(cond
|
||||
(= esc "n") "\n"
|
||||
(= esc "t") "\t"
|
||||
(= esc "r") "\r"
|
||||
:else esc)))
|
||||
(set! pos (inc pos))
|
||||
(read-str-loop)))
|
||||
(if (= esc "u")
|
||||
;; Unicode escape: \uXXXX → char
|
||||
(do (set! pos (inc pos))
|
||||
(let ((d0 (hex-digit-value (nth source pos)))
|
||||
(_ (set! pos (inc pos)))
|
||||
(d1 (hex-digit-value (nth source pos)))
|
||||
(_ (set! pos (inc pos)))
|
||||
(d2 (hex-digit-value (nth source pos)))
|
||||
(_ (set! pos (inc pos)))
|
||||
(d3 (hex-digit-value (nth source pos)))
|
||||
(_ (set! pos (inc pos))))
|
||||
(set! buf (str buf (char-from-code
|
||||
(+ (* d0 4096) (* d1 256) (* d2 16) d3))))
|
||||
(read-str-loop)))
|
||||
;; Standard escapes: \n \t \r or literal
|
||||
(do (set! buf (str buf
|
||||
(cond
|
||||
(= esc "n") "\n"
|
||||
(= esc "t") "\t"
|
||||
(= esc "r") "\r"
|
||||
:else esc)))
|
||||
(set! pos (inc pos))
|
||||
(read-str-loop)))))
|
||||
:else
|
||||
(do (set! buf (str buf ch))
|
||||
(set! pos (inc pos))
|
||||
|
||||
@@ -983,6 +983,7 @@ PRIMITIVES_JS_MODULES: dict[str, str] = {
|
||||
PRIMITIVES["ends-with?"] = function(s, p) { var str = String(s); return str.indexOf(p, str.length - p.length) !== -1; };
|
||||
PRIMITIVES["slice"] = function(c, a, b) { if (!c || typeof c.slice !== "function") { console.error("[sx-debug] slice called on non-sliceable:", typeof c, c, "a=", a, "b=", b, new Error().stack); return []; } return b !== undefined ? c.slice(a, b) : c.slice(a); };
|
||||
PRIMITIVES["substring"] = function(s, a, b) { return String(s).substring(a, b); };
|
||||
PRIMITIVES["char-from-code"] = function(n) { return String.fromCharCode(n); };
|
||||
PRIMITIVES["string-length"] = function(s) { return String(s).length; };
|
||||
PRIMITIVES["string-contains?"] = function(s, sub) { return String(s).indexOf(String(sub)) !== -1; };
|
||||
PRIMITIVES["concat"] = function() {
|
||||
@@ -1600,6 +1601,7 @@ PLATFORM_PARSER_JS = r"""
|
||||
return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\t/g, "\\t");
|
||||
}
|
||||
function sxExprSource(e) { return typeof e === "string" ? e : String(e); }
|
||||
var charFromCode = PRIMITIVES["char-from-code"];
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -881,6 +881,7 @@ PRIMITIVES["zero?"] = lambda n: n == 0
|
||||
"core.strings": '''
|
||||
# core.strings
|
||||
PRIMITIVES["str"] = sx_str
|
||||
PRIMITIVES["char-from-code"] = lambda n: chr(_b_int(n))
|
||||
PRIMITIVES["upper"] = lambda s: str(s).upper()
|
||||
PRIMITIVES["lower"] = lambda s: str(s).lower()
|
||||
PRIMITIVES["trim"] = lambda s: str(s).strip()
|
||||
|
||||
@@ -323,6 +323,11 @@
|
||||
:returns "number"
|
||||
:doc "Length of string in characters.")
|
||||
|
||||
(define-primitive "char-from-code"
|
||||
:params ((n :as number))
|
||||
:returns "string"
|
||||
:doc "Convert Unicode code point to single-character string.")
|
||||
|
||||
(define-primitive "substring"
|
||||
:params ((s :as string) (start :as number) (end :as number))
|
||||
:returns "string"
|
||||
|
||||
@@ -830,11 +830,21 @@
|
||||
|
||||
(define py-emit-infix
|
||||
(fn ((op :as string) (args :as list) (cell-vars :as list))
|
||||
(let ((py-op (py-op-symbol op)))
|
||||
(if (and (= (len args) 1) (= op "-"))
|
||||
(str "(-" (py-expr-with-cells (first args) cell-vars) ")")
|
||||
(str "(" (py-expr-with-cells (first args) cell-vars)
|
||||
" " py-op " " (py-expr-with-cells (nth args 1) cell-vars) ")")))))
|
||||
(let ((py-op (py-op-symbol op))
|
||||
(n (len args)))
|
||||
(cond
|
||||
(and (= n 1) (= op "-"))
|
||||
(str "(-" (py-expr-with-cells (first args) cell-vars) ")")
|
||||
(= n 2)
|
||||
(str "(" (py-expr-with-cells (first args) cell-vars)
|
||||
" " py-op " " (py-expr-with-cells (nth args 1) cell-vars) ")")
|
||||
;; Variadic: left-fold (a op b op c op d ...)
|
||||
:else
|
||||
(let ((result (py-expr-with-cells (first args) cell-vars)))
|
||||
(for-each (fn (arg)
|
||||
(set! result (str "(" result " " py-op " " (py-expr-with-cells arg cell-vars) ")")))
|
||||
(rest args))
|
||||
result)))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
@@ -851,6 +851,7 @@ PRIMITIVES["zero?"] = lambda n: n == 0
|
||||
|
||||
# core.strings
|
||||
PRIMITIVES["str"] = sx_str
|
||||
PRIMITIVES["char-from-code"] = lambda n: chr(_b_int(n))
|
||||
PRIMITIVES["upper"] = lambda s: str(s).upper()
|
||||
PRIMITIVES["lower"] = lambda s: str(s).lower()
|
||||
PRIMITIVES["trim"] = lambda s: str(s).strip()
|
||||
|
||||
Reference in New Issue
Block a user