Compare commits
9 Commits
cfe5371354
...
loops/hs
| Author | SHA1 | Date | |
|---|---|---|---|
| 6169c99036 | |||
| 8915eeaf5e | |||
| de493e41d8 | |||
| e4e784dba6 | |||
| e9ea1bf160 | |||
| ce39a35c6b | |||
| a20c9c4625 | |||
| c2dcc94ce2 | |||
| 6327c05ca6 |
@@ -2042,8 +2042,8 @@ PLATFORM_DOM_JS = """
|
|||||||
// If lambda takes 0 params, call without event arg (convenience for on-click handlers)
|
// If lambda takes 0 params, call without event arg (convenience for on-click handlers)
|
||||||
var wrapped = isLambda(handler)
|
var wrapped = isLambda(handler)
|
||||||
? (lambdaParams(handler).length === 0
|
? (lambdaParams(handler).length === 0
|
||||||
? function(e) { try { var r = cekCall(handler, NIL); if (globalThis._driveAsync) globalThis._driveAsync(r); } catch(err) { console.error("[sx-ref] domListen handler error:", name, err); } }
|
? function(e) { try { cekCall(handler, NIL); } catch(err) { console.error("[sx-ref] domListen handler error:", name, err); } }
|
||||||
: function(e) { try { var r = cekCall(handler, [e]); if (globalThis._driveAsync) globalThis._driveAsync(r); } catch(err) { console.error("[sx-ref] domListen handler error:", name, err); } })
|
: function(e) { try { cekCall(handler, [e]); } catch(err) { console.error("[sx-ref] domListen handler error:", name, err); } })
|
||||||
: handler;
|
: handler;
|
||||||
if (name === "click") logInfo("domListen: click on <" + (el.tagName||"?").toLowerCase() + "> text=" + (el.textContent||"").substring(0,20) + " isLambda=" + isLambda(handler));
|
if (name === "click") logInfo("domListen: click on <" + (el.tagName||"?").toLowerCase() + "> text=" + (el.textContent||"").substring(0,20) + " isLambda=" + isLambda(handler));
|
||||||
var passiveEvents = { touchstart: 1, touchmove: 1, wheel: 1, scroll: 1 };
|
var passiveEvents = { touchstart: 1, touchmove: 1, wheel: 1, scroll: 1 };
|
||||||
|
|||||||
@@ -1892,34 +1892,8 @@ let handle_sx_harness_eval args =
|
|||||||
let file = args |> member "file" |> to_string_option in
|
let file = args |> member "file" |> to_string_option in
|
||||||
let setup_str = args |> member "setup" |> to_string_option in
|
let setup_str = args |> member "setup" |> to_string_option in
|
||||||
let files_json = try args |> member "files" with _ -> `Null in
|
let files_json = try args |> member "files" with _ -> `Null in
|
||||||
let host_stubs = match args |> member "host_stubs" with `Bool b -> b | _ -> false in
|
|
||||||
let e = !env in
|
let e = !env in
|
||||||
let warnings = ref [] in
|
let warnings = ref [] in
|
||||||
(* Inject stub host primitives so files using host-get/host-new/etc. can load *)
|
|
||||||
if host_stubs then begin
|
|
||||||
let stubs = {|
|
|
||||||
(define host-global (fn (&rest _) nil))
|
|
||||||
(define host-get (fn (&rest _) nil))
|
|
||||||
(define host-set! (fn (obj k v) v))
|
|
||||||
(define host-call (fn (&rest _) nil))
|
|
||||||
(define host-new (fn (&rest _) (dict)))
|
|
||||||
(define host-callback (fn (f) f))
|
|
||||||
(define host-typeof (fn (&rest _) "string"))
|
|
||||||
(define hs-ref-eq (fn (a b) (identical? a b)))
|
|
||||||
(define host-call-fn (fn (&rest _) nil))
|
|
||||||
(define host-iter? (fn (&rest _) false))
|
|
||||||
(define host-to-list (fn (&rest _) (list)))
|
|
||||||
(define host-await (fn (&rest _) nil))
|
|
||||||
(define host-new-function (fn (&rest _) nil))
|
|
||||||
(define load-library! (fn (&rest _) false))
|
|
||||||
|} in
|
|
||||||
let stub_exprs = Sx_parser.parse_all stubs in
|
|
||||||
List.iter (fun expr ->
|
|
||||||
try ignore (Sx_ref.eval_expr expr (Env e))
|
|
||||||
with exn ->
|
|
||||||
warnings := Printf.sprintf "Stub warning: %s" (Printexc.to_string exn) :: !warnings
|
|
||||||
) stub_exprs
|
|
||||||
end;
|
|
||||||
(* Collect all files to load *)
|
(* Collect all files to load *)
|
||||||
let all_files = match files_json with
|
let all_files = match files_json with
|
||||||
| `List items ->
|
| `List items ->
|
||||||
@@ -3044,8 +3018,7 @@ let tool_definitions = `List [
|
|||||||
("mock", `Assoc [("type", `String "string"); ("description", `String "Optional mock platform overrides as SX dict, e.g. {:fetch (fn (url) {:status 200})}")]);
|
("mock", `Assoc [("type", `String "string"); ("description", `String "Optional mock platform overrides as SX dict, e.g. {:fetch (fn (url) {:status 200})}")]);
|
||||||
("file", `Assoc [("type", `String "string"); ("description", `String "Optional .sx file to load for definitions")]);
|
("file", `Assoc [("type", `String "string"); ("description", `String "Optional .sx file to load for definitions")]);
|
||||||
("files", `Assoc [("type", `String "array"); ("items", `Assoc [("type", `String "string")]); ("description", `String "Multiple .sx files to load in order")]);
|
("files", `Assoc [("type", `String "array"); ("items", `Assoc [("type", `String "string")]); ("description", `String "Multiple .sx files to load in order")]);
|
||||||
("setup", `Assoc [("type", `String "string"); ("description", `String "SX setup expression to run before main evaluation")]);
|
("setup", `Assoc [("type", `String "string"); ("description", `String "SX setup expression to run before main evaluation")])]
|
||||||
("host_stubs", `Assoc [("type", `String "boolean"); ("description", `String "If true, inject nil-returning stubs for host-get/host-set!/host-call/host-new/etc. so files that use host primitives can load in the harness")])]
|
|
||||||
["expr"];
|
["expr"];
|
||||||
tool "sx_nav" "Manage sx-docs navigation and articles. Modes: list (all nav items with status), check (validate consistency), add (create article + nav entry), delete (remove nav entry + page fn), move (move entry between sections, rewriting hrefs)."
|
tool "sx_nav" "Manage sx-docs navigation and articles. Modes: list (all nav items with status), check (validate consistency), add (create article + nav entry), delete (remove nav entry + page fn), move (move entry between sections, rewriting hrefs)."
|
||||||
[("mode", `Assoc [("type", `String "string"); ("description", `String "Mode: list, check, add, delete, or move")]);
|
[("mode", `Assoc [("type", `String "string"); ("description", `String "Mode: list, check, add, delete, or move")]);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
(let
|
(let
|
||||||
((th (first target)))
|
((th (first target)))
|
||||||
(cond
|
(cond
|
||||||
((or (= th dot-sym) (= th (make-symbol "poss")))
|
((= th dot-sym)
|
||||||
(let
|
(let
|
||||||
((base-ast (nth target 1)) (prop (nth target 2)))
|
((base-ast (nth target 1)) (prop (nth target 2)))
|
||||||
(cond
|
(cond
|
||||||
@@ -67,62 +67,17 @@
|
|||||||
value))
|
value))
|
||||||
(list (quote hs-query-all) (nth inner 1)))))
|
(list (quote hs-query-all) (nth inner 1)))))
|
||||||
(true
|
(true
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list
|
|
||||||
(quote __hs-obj)
|
|
||||||
(if
|
|
||||||
(or
|
|
||||||
(symbol? base-ast)
|
|
||||||
(and
|
|
||||||
(list? base-ast)
|
|
||||||
(= (str (first base-ast)) "ref")))
|
|
||||||
(let
|
|
||||||
((sel (if (symbol? base-ast) (str base-ast) (nth base-ast 1))))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list
|
|
||||||
(quote host-set!)
|
|
||||||
(list (quote host-global) "window")
|
|
||||||
"_hs_last_query_sel"
|
|
||||||
sel)
|
|
||||||
(hs-to-sx base-ast)))
|
|
||||||
(hs-to-sx base-ast))))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-obj))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list
|
|
||||||
(quote not)
|
|
||||||
(list (quote nil?) (quote __hs-obj)))
|
|
||||||
(list
|
(list
|
||||||
(quote dom-set-prop)
|
(quote dom-set-prop)
|
||||||
(quote __hs-obj)
|
(hs-to-sx base-ast)
|
||||||
prop
|
prop
|
||||||
value))))))))
|
value)))))
|
||||||
((= th (quote attr))
|
((= th (quote attr))
|
||||||
(let
|
|
||||||
((base-ast (nth target 2)))
|
|
||||||
(if
|
|
||||||
(and (list? base-ast) (= (str (first base-ast)) "ref"))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list
|
|
||||||
(quote set!)
|
|
||||||
(quote _hs-last-query-sel)
|
|
||||||
(nth base-ast 1))
|
|
||||||
(list
|
(list
|
||||||
(quote hs-set-attr!)
|
(quote hs-set-attr!)
|
||||||
(hs-to-sx base-ast)
|
(hs-to-sx (nth target 2))
|
||||||
(nth target 1)
|
(nth target 1)
|
||||||
value))
|
value))
|
||||||
(list
|
|
||||||
(quote hs-set-attr!)
|
|
||||||
(hs-to-sx base-ast)
|
|
||||||
(nth target 1)
|
|
||||||
value))))
|
|
||||||
((= th (quote style))
|
((= th (quote style))
|
||||||
(list
|
(list
|
||||||
(quote dom-set-style)
|
(quote dom-set-style)
|
||||||
@@ -190,16 +145,7 @@
|
|||||||
(hs-to-sx obj-ast)
|
(hs-to-sx obj-ast)
|
||||||
(nth prop-ast 1)
|
(nth prop-ast 1)
|
||||||
value)
|
value)
|
||||||
(if
|
(list (quote set!) (hs-to-sx target) value))))))
|
||||||
(and
|
|
||||||
(list? prop-ast)
|
|
||||||
(= (first prop-ast) (quote style)))
|
|
||||||
(list
|
|
||||||
(quote dom-set-style)
|
|
||||||
(hs-to-sx obj-ast)
|
|
||||||
(nth prop-ast 1)
|
|
||||||
value)
|
|
||||||
(list (quote set!) (hs-to-sx target) value)))))))
|
|
||||||
(true (list (quote set!) (hs-to-sx target) value)))))))
|
(true (list (quote set!) (hs-to-sx target) value)))))))
|
||||||
(define
|
(define
|
||||||
emit-on
|
emit-on
|
||||||
@@ -235,9 +181,9 @@
|
|||||||
(let
|
(let
|
||||||
((raw-compiled (hs-to-sx stripped-body)))
|
((raw-compiled (hs-to-sx stripped-body)))
|
||||||
(let
|
(let
|
||||||
((compiled-body (let ((base (if (> (len event-refs) 0) (let ((bindings (map (fn (r) (let ((name (nth r 1))) (list (make-symbol name) (list (quote let) (list (list (quote _det) (list (quote host-get) (quote event) "detail"))) (list (quote if) (list (quote and) (quote _det) (list (quote not) (list (quote nil?) (list (quote host-get) (quote _det) name)))) (list (quote host-get) (quote _det) name) (list (quote host-get) (quote event) name)))))) event-refs))) (list (quote let) bindings raw-compiled)) raw-compiled))) (if elsewhere? (list (quote when) (list (quote not) (list (quote host-call) (quote me) "contains" (list (quote host-get) (quote event) "target"))) base) base))))
|
((compiled-body (let ((base (if (> (len event-refs) 0) (let ((bindings (map (fn (r) (let ((name (nth r 1))) (list (make-symbol name) (list (quote host-get) (list (quote host-get) (quote event) "detail") name)))) event-refs))) (list (quote let) bindings raw-compiled)) raw-compiled))) (if elsewhere? (list (quote when) (list (quote not) (list (quote host-call) (quote me) "contains" (list (quote host-get) (quote event) "target"))) base) base))))
|
||||||
(let
|
(let
|
||||||
((wrapped-body (if catch-info (let ((var (make-symbol (nth catch-info 0))) (catch-body (hs-to-sx (nth catch-info 1)))) (if finally-info (list (quote let) (list (list (quote __hs-exc) nil) (list (quote __hs-reraise) false)) (list (quote do) (list (quote guard) (list var (list true (list (quote let) (list (list var (list (quote host-hs-normalize-exc) var))) (list (quote guard) (list (quote __inner-exc) (list true (list (quote do) (list (quote set!) (quote __hs-exc) (quote __inner-exc)) (list (quote set!) (quote __hs-reraise) true)))) catch-body)))) compiled-body) (hs-to-sx finally-info) (list (quote when) (quote __hs-reraise) (list (quote raise) (quote __hs-exc))))) (list (quote let) (list (list (quote __hs-exc) nil) (list (quote __hs-reraise) false)) (list (quote do) (list (quote guard) (list var (list true (list (quote let) (list (list var (list (quote host-hs-normalize-exc) var))) (list (quote guard) (list (quote __inner-exc) (list true (list (quote do) (list (quote set!) (quote __hs-exc) (quote __inner-exc)) (list (quote set!) (quote __hs-reraise) true)))) catch-body)))) compiled-body) (list (quote when) (quote __hs-reraise) (list (quote raise) (quote __hs-exc))))))) (if finally-info (list (quote do) compiled-body (hs-to-sx finally-info)) compiled-body))))
|
((wrapped-body (if catch-info (let ((var (make-symbol (nth catch-info 0))) (catch-body (hs-to-sx (nth catch-info 1)))) (if finally-info (list (quote do) (list (quote guard) (list var (list true catch-body)) compiled-body) (hs-to-sx finally-info)) (list (quote guard) (list var (list true catch-body)) compiled-body))) (if finally-info (list (quote do) compiled-body (hs-to-sx finally-info)) compiled-body))))
|
||||||
(let
|
(let
|
||||||
((handler (let ((uses-the-result? (fn (expr) (cond ((= expr (quote the-result)) true) ((list? expr) (some (fn (x) (uses-the-result? x)) expr)) (true false))))) (let ((base-handler (list (quote fn) (list (quote event)) (if (uses-the-result? wrapped-body) (list (quote let) (list (list (quote the-result) nil)) wrapped-body) wrapped-body)))) (if count-filter-info (let ((mn (get count-filter-info "min")) (mx (get count-filter-info "max"))) (list (quote let) (list (list (quote __hs-count) 0)) (list (quote fn) (list (quote event)) (list (quote begin) (list (quote set!) (quote __hs-count) (list (quote +) (quote __hs-count) 1)) (list (quote when) (if (= mx -1) (list (quote >=) (quote __hs-count) mn) (list (quote and) (list (quote >=) (quote __hs-count) mn) (list (quote <=) (quote __hs-count) mx))) (nth base-handler 2)))))) base-handler)))))
|
((handler (let ((uses-the-result? (fn (expr) (cond ((= expr (quote the-result)) true) ((list? expr) (some (fn (x) (uses-the-result? x)) expr)) (true false))))) (let ((base-handler (list (quote fn) (list (quote event)) (if (uses-the-result? wrapped-body) (list (quote let) (list (list (quote the-result) nil)) wrapped-body) wrapped-body)))) (if count-filter-info (let ((mn (get count-filter-info "min")) (mx (get count-filter-info "max"))) (list (quote let) (list (list (quote __hs-count) 0)) (list (quote fn) (list (quote event)) (list (quote begin) (list (quote set!) (quote __hs-count) (list (quote +) (quote __hs-count) 1)) (list (quote when) (if (= mx -1) (list (quote >=) (quote __hs-count) mn) (list (quote and) (list (quote >=) (quote __hs-count) mn) (list (quote <=) (quote __hs-count) mx))) (nth base-handler 2)))))) base-handler)))))
|
||||||
(let
|
(let
|
||||||
@@ -410,13 +356,13 @@
|
|||||||
(cond
|
(cond
|
||||||
((and (= (len ast) 4) (list? (nth ast 2)) (= (first (nth ast 2)) (quote dict)))
|
((and (= (len ast) 4) (list? (nth ast 2)) (= (first (nth ast 2)) (quote dict)))
|
||||||
(list
|
(list
|
||||||
(quote hs-dispatch!)
|
(quote dom-dispatch)
|
||||||
(hs-to-sx (nth ast 3))
|
(hs-to-sx (nth ast 3))
|
||||||
name
|
name
|
||||||
(hs-to-sx (nth ast 2))))
|
(hs-to-sx (nth ast 2))))
|
||||||
((= (len ast) 3)
|
((= (len ast) 3)
|
||||||
(list
|
(list
|
||||||
(quote hs-dispatch!)
|
(quote dom-dispatch)
|
||||||
(hs-to-sx (nth ast 2))
|
(hs-to-sx (nth ast 2))
|
||||||
name
|
name
|
||||||
(list (quote dict) "sender" (quote me))))
|
(list (quote dict) "sender" (quote me))))
|
||||||
@@ -466,20 +412,12 @@
|
|||||||
(quote hs-repeat-times)
|
(quote hs-repeat-times)
|
||||||
(hs-to-sx mode)
|
(hs-to-sx mode)
|
||||||
(list (quote fn) (list) body)))))))
|
(list (quote fn) (list) body)))))))
|
||||||
(define
|
|
||||||
hs-reserved-var?
|
|
||||||
(fn (name) (or (= name "meta") (= name "event") (= name "result"))))
|
|
||||||
(define
|
(define
|
||||||
emit-for
|
emit-for
|
||||||
(fn
|
(fn
|
||||||
(ast)
|
(ast)
|
||||||
(let
|
(let
|
||||||
((var-name (nth ast 1))
|
((var-name (nth ast 1))
|
||||||
(safe-param
|
|
||||||
(if
|
|
||||||
(hs-reserved-var? var-name)
|
|
||||||
(str "_hs_lv_" var-name)
|
|
||||||
var-name))
|
|
||||||
(raw-coll-ast (nth ast 2))
|
(raw-coll-ast (nth ast 2))
|
||||||
(where-cond
|
(where-cond
|
||||||
(if
|
(if
|
||||||
@@ -514,12 +452,12 @@
|
|||||||
(quote map-indexed)
|
(quote map-indexed)
|
||||||
(list
|
(list
|
||||||
(quote fn)
|
(quote fn)
|
||||||
(list (make-symbol (nth ast 5)) (make-symbol safe-param))
|
(list (make-symbol (nth ast 5)) (make-symbol var-name))
|
||||||
body)
|
body)
|
||||||
collection)
|
collection)
|
||||||
(list
|
(list
|
||||||
(quote hs-for-each)
|
(quote hs-for-each)
|
||||||
(list (quote fn) (list (make-symbol safe-param)) body)
|
(list (quote fn) (list (make-symbol var-name)) body)
|
||||||
collection)))))
|
collection)))))
|
||||||
(define
|
(define
|
||||||
emit-wait-for
|
emit-wait-for
|
||||||
@@ -628,18 +566,9 @@
|
|||||||
(quote do)
|
(quote do)
|
||||||
(list (quote dom-set-attr) el attr-name (quote __hs-new))
|
(list (quote dom-set-attr) el attr-name (quote __hs-new))
|
||||||
(list (quote set!) (quote it) (quote __hs-new))))))
|
(list (quote set!) (quote it) (quote __hs-new))))))
|
||||||
((and (list? expr) (or (= (first expr) dot-sym) (= (first expr) (make-symbol "poss"))))
|
((and (list? expr) (= (first expr) dot-sym))
|
||||||
(let
|
(let
|
||||||
((obj (hs-to-sx (nth expr 1))) (prop (nth expr 2)))
|
((obj (hs-to-sx (nth expr 1))) (prop (nth expr 2)))
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-obj) obj))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-obj))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list (quote not) (list (quote nil?) (quote __hs-obj)))
|
|
||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list
|
(list
|
||||||
@@ -649,16 +578,12 @@
|
|||||||
(quote +)
|
(quote +)
|
||||||
(list
|
(list
|
||||||
(quote hs-to-number)
|
(quote hs-to-number)
|
||||||
(list (quote host-get) (quote __hs-obj) prop))
|
(list (quote host-get) obj prop))
|
||||||
amount)))
|
amount)))
|
||||||
(list
|
(list
|
||||||
(quote do)
|
(quote do)
|
||||||
(list
|
(list (quote host-set!) obj prop (quote __hs-new))
|
||||||
(quote host-set!)
|
(list (quote set!) (quote it) (quote __hs-new))))))
|
||||||
(quote __hs-obj)
|
|
||||||
prop
|
|
||||||
(quote __hs-new))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-new)))))))))
|
|
||||||
((and (list? expr) (= (first expr) (quote style)))
|
((and (list? expr) (= (first expr) (quote style)))
|
||||||
(let
|
(let
|
||||||
((el (if tgt-override (hs-to-sx tgt-override) (quote me)))
|
((el (if tgt-override (hs-to-sx tgt-override) (quote me)))
|
||||||
@@ -757,18 +682,9 @@
|
|||||||
(quote do)
|
(quote do)
|
||||||
(list (quote dom-set-attr) el attr-name (quote __hs-new))
|
(list (quote dom-set-attr) el attr-name (quote __hs-new))
|
||||||
(list (quote set!) (quote it) (quote __hs-new))))))
|
(list (quote set!) (quote it) (quote __hs-new))))))
|
||||||
((and (list? expr) (or (= (first expr) dot-sym) (= (first expr) (make-symbol "poss"))))
|
((and (list? expr) (= (first expr) dot-sym))
|
||||||
(let
|
(let
|
||||||
((obj (hs-to-sx (nth expr 1))) (prop (nth expr 2)))
|
((obj (hs-to-sx (nth expr 1))) (prop (nth expr 2)))
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-obj) obj))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-obj))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list (quote not) (list (quote nil?) (quote __hs-obj)))
|
|
||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list
|
(list
|
||||||
@@ -778,16 +694,12 @@
|
|||||||
(quote -)
|
(quote -)
|
||||||
(list
|
(list
|
||||||
(quote hs-to-number)
|
(quote hs-to-number)
|
||||||
(list (quote host-get) (quote __hs-obj) prop))
|
(list (quote host-get) obj prop))
|
||||||
amount)))
|
amount)))
|
||||||
(list
|
(list
|
||||||
(quote do)
|
(quote do)
|
||||||
(list
|
(list (quote host-set!) obj prop (quote __hs-new))
|
||||||
(quote host-set!)
|
(list (quote set!) (quote it) (quote __hs-new))))))
|
||||||
(quote __hs-obj)
|
|
||||||
prop
|
|
||||||
(quote __hs-new))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-new)))))))))
|
|
||||||
((and (list? expr) (= (first expr) (quote style)))
|
((and (list? expr) (= (first expr) (quote style)))
|
||||||
(let
|
(let
|
||||||
((el (if tgt-override (hs-to-sx tgt-override) (quote me)))
|
((el (if tgt-override (hs-to-sx tgt-override) (quote me)))
|
||||||
@@ -873,21 +785,35 @@
|
|||||||
(make-symbol name)
|
(make-symbol name)
|
||||||
(list
|
(list
|
||||||
(quote fn)
|
(quote fn)
|
||||||
(cons
|
(cons (quote me) (map make-symbol params))
|
||||||
(quote me)
|
(cons (quote do) (map hs-to-sx body)))))))
|
||||||
(map
|
(define
|
||||||
(fn
|
emit-socket
|
||||||
(p)
|
|
||||||
(if (list? p) (make-symbol (nth p 1)) (make-symbol p)))
|
|
||||||
params))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list (list (quote beingTold) (quote me)))
|
|
||||||
(cons (quote do) (map hs-to-sx body))))))))
|
|
||||||
(fn
|
(fn
|
||||||
(ast)
|
(ast)
|
||||||
(let
|
(let
|
||||||
((ast (if (and (dict? ast) (get ast :hs-ast)) (get ast :children) ast)))
|
((name-path (nth ast 1))
|
||||||
|
(url (nth ast 2))
|
||||||
|
(timeout-ms (nth ast 3))
|
||||||
|
(on-msg (nth ast 4)))
|
||||||
|
(let
|
||||||
|
((handler
|
||||||
|
(if
|
||||||
|
(nil? on-msg)
|
||||||
|
nil
|
||||||
|
(let
|
||||||
|
((body (hs-to-sx (nth on-msg 2))))
|
||||||
|
(list (quote fn) (list (quote event)) body))))
|
||||||
|
(json?-val (if (nil? on-msg) false (nth on-msg 1))))
|
||||||
|
(list
|
||||||
|
(quote hs-socket-register!)
|
||||||
|
(cons (quote list) name-path)
|
||||||
|
url
|
||||||
|
(if (nil? timeout-ms) nil (hs-to-sx timeout-ms))
|
||||||
|
handler
|
||||||
|
json?-val)))))
|
||||||
|
(fn
|
||||||
|
(ast)
|
||||||
(cond
|
(cond
|
||||||
((nil? ast) nil)
|
((nil? ast) nil)
|
||||||
((number? ast) ast)
|
((number? ast) ast)
|
||||||
@@ -992,10 +918,7 @@
|
|||||||
(let
|
(let
|
||||||
((ch (nth raw i)))
|
((ch (nth raw i)))
|
||||||
(if
|
(if
|
||||||
(and
|
(and (= ch "\\") (< (+ i 1) n) (= (nth raw (+ i 1)) "$"))
|
||||||
(= ch "\\")
|
|
||||||
(< (+ i 1) n)
|
|
||||||
(= (nth raw (+ i 1)) "$"))
|
|
||||||
(do
|
(do
|
||||||
(set! buf (str buf "$"))
|
(set! buf (str buf "$"))
|
||||||
(set! i (+ i 2))
|
(set! i (+ i 2))
|
||||||
@@ -1017,8 +940,7 @@
|
|||||||
(append
|
(append
|
||||||
parts
|
parts
|
||||||
(list
|
(list
|
||||||
(hs-to-sx
|
(hs-to-sx (hs-compile expr-src)))))
|
||||||
(hs-compile expr-src)))))
|
|
||||||
(set! i (+ close 1))
|
(set! i (+ close 1))
|
||||||
(tpl-collect)))))
|
(tpl-collect)))))
|
||||||
(let
|
(let
|
||||||
@@ -1034,8 +956,7 @@
|
|||||||
(append
|
(append
|
||||||
parts
|
parts
|
||||||
(list
|
(list
|
||||||
(hs-to-sx
|
(hs-to-sx (hs-compile ident)))))
|
||||||
(hs-compile ident)))))
|
|
||||||
(set! i end)
|
(set! i end)
|
||||||
(tpl-collect))))))
|
(tpl-collect))))))
|
||||||
(do
|
(do
|
||||||
@@ -1113,21 +1034,13 @@
|
|||||||
(hs-to-sx (nth ast 1))
|
(hs-to-sx (nth ast 1))
|
||||||
(nth ast 2)))
|
(nth ast 2)))
|
||||||
((= head (quote coll-where))
|
((= head (quote coll-where))
|
||||||
(let
|
|
||||||
((raw-coll (hs-to-sx (nth ast 1))))
|
|
||||||
(list
|
(list
|
||||||
(quote filter)
|
(quote filter)
|
||||||
(list
|
(list
|
||||||
(quote fn)
|
(quote fn)
|
||||||
(list (quote it))
|
(list (quote it))
|
||||||
(hs-to-sx (nth ast 2)))
|
(hs-to-sx (nth ast 2)))
|
||||||
(if
|
(hs-to-sx (nth ast 1))))
|
||||||
(symbol? raw-coll)
|
|
||||||
(list
|
|
||||||
(quote cek-try)
|
|
||||||
(list (quote fn) (list) raw-coll)
|
|
||||||
(list (quote fn) (list (quote _e)) nil))
|
|
||||||
raw-coll))))
|
|
||||||
((= head (quote coll-sorted))
|
((= head (quote coll-sorted))
|
||||||
(list
|
(list
|
||||||
(quote hs-sorted-by)
|
(quote hs-sorted-by)
|
||||||
@@ -1169,29 +1082,13 @@
|
|||||||
(if
|
(if
|
||||||
(and
|
(and
|
||||||
(list? dot-node)
|
(list? dot-node)
|
||||||
(or
|
(= (first dot-node) (make-symbol ".")))
|
||||||
(= (str (first dot-node)) ".")
|
|
||||||
(= (str (first dot-node)) "poss")))
|
|
||||||
(let
|
(let
|
||||||
((receiver-ast (nth dot-node 1))
|
((obj (hs-to-sx (nth dot-node 1)))
|
||||||
(method (nth dot-node 2))
|
(method (nth dot-node 2)))
|
||||||
(sel
|
|
||||||
(hs-receiver-selector (nth dot-node 1) "poss")))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list (quote __hs-recv) (hs-to-sx receiver-ast)))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list
|
|
||||||
(quote host-set!)
|
|
||||||
(list (quote host-global) "window")
|
|
||||||
"_hs_last_query_sel"
|
|
||||||
sel)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-recv))
|
|
||||||
(cons
|
(cons
|
||||||
(quote hs-method-call)
|
(quote hs-method-call)
|
||||||
(cons (quote __hs-recv) (cons method args))))))
|
(cons obj (cons method args))))
|
||||||
(if
|
(if
|
||||||
(and
|
(and
|
||||||
(list? dot-node)
|
(list? dot-node)
|
||||||
@@ -1209,9 +1106,11 @@
|
|||||||
(let
|
(let
|
||||||
((params (map make-symbol (nth ast 1)))
|
((params (map make-symbol (nth ast 1)))
|
||||||
(body (hs-to-sx (nth ast 2))))
|
(body (hs-to-sx (nth ast 2))))
|
||||||
(list (quote fn) params body)))
|
(if
|
||||||
|
(= (len params) 0)
|
||||||
|
body
|
||||||
|
(list (quote fn) params body))))
|
||||||
((= head (quote me)) (quote me))
|
((= head (quote me)) (quote me))
|
||||||
((= head (quote beingTold)) (quote beingTold))
|
|
||||||
((= head (quote it)) (quote it))
|
((= head (quote it)) (quote it))
|
||||||
((= head (quote event)) (quote event))
|
((= head (quote event)) (quote event))
|
||||||
((= head dot-sym)
|
((= head dot-sym)
|
||||||
@@ -1222,16 +1121,11 @@
|
|||||||
((= prop "first") (list (quote hs-first) target))
|
((= prop "first") (list (quote hs-first) target))
|
||||||
((= prop "last") (list (quote hs-last) target))
|
((= prop "last") (list (quote hs-last) target))
|
||||||
(true (list (quote host-get) target prop)))))
|
(true (list (quote host-get) target prop)))))
|
||||||
((= head (make-symbol "poss"))
|
|
||||||
(let
|
|
||||||
((target (hs-to-sx (nth ast 1))) (prop (nth ast 2)))
|
|
||||||
(list (quote host-get) target prop)))
|
|
||||||
((= head (quote ref))
|
((= head (quote ref))
|
||||||
(cond
|
(if
|
||||||
((= (nth ast 1) "selection")
|
(= (nth ast 1) "selection")
|
||||||
(list (quote hs-get-selection)))
|
(list (quote hs-get-selection))
|
||||||
((= (nth ast 1) "element") (make-symbol "me"))
|
(make-symbol (nth ast 1))))
|
||||||
(else (make-symbol (nth ast 1)))))
|
|
||||||
((= head (quote query))
|
((= head (quote query))
|
||||||
(list (quote hs-query-first) (nth ast 1)))
|
(list (quote hs-query-first) (nth ast 1)))
|
||||||
((= head (quote query-scoped))
|
((= head (quote query-scoped))
|
||||||
@@ -1267,8 +1161,6 @@
|
|||||||
(list (quote not) (hs-to-sx (nth ast 1))))
|
(list (quote not) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote no))
|
((= head (quote no))
|
||||||
(list (quote hs-falsy?) (hs-to-sx (nth ast 1))))
|
(list (quote hs-falsy?) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote hs-falsy?))
|
|
||||||
(list (quote hs-falsy?) (hs-to-sx (nth ast 1))))
|
|
||||||
((= head (quote and))
|
((= head (quote and))
|
||||||
(list
|
(list
|
||||||
(quote and)
|
(quote and)
|
||||||
@@ -1284,11 +1176,6 @@
|
|||||||
(quote =)
|
(quote =)
|
||||||
(hs-to-sx (nth ast 1))
|
(hs-to-sx (nth ast 1))
|
||||||
(hs-to-sx (nth ast 2))))
|
(hs-to-sx (nth ast 2))))
|
||||||
((= head (quote hs-id=))
|
|
||||||
(list
|
|
||||||
(quote hs-id=)
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(hs-to-sx (nth ast 2))))
|
|
||||||
((= head (quote +))
|
((= head (quote +))
|
||||||
(list
|
(list
|
||||||
(quote hs-add)
|
(quote hs-add)
|
||||||
@@ -1328,10 +1215,7 @@
|
|||||||
((left (nth ast 1)) (right (nth ast 2)))
|
((left (nth ast 1)) (right (nth ast 2)))
|
||||||
(if
|
(if
|
||||||
(and (list? right) (= (first right) (quote query)))
|
(and (list? right) (= (first right) (quote query)))
|
||||||
(list
|
(list (quote hs-matches?) (hs-to-sx left) (nth right 1))
|
||||||
(quote hs-matches?)
|
|
||||||
(hs-to-sx left)
|
|
||||||
(nth right 1))
|
|
||||||
(list
|
(list
|
||||||
(quote hs-matches?)
|
(quote hs-matches?)
|
||||||
(hs-to-sx left)
|
(hs-to-sx left)
|
||||||
@@ -1382,10 +1266,7 @@
|
|||||||
(hs-to-sx (nth ast 1))
|
(hs-to-sx (nth ast 1))
|
||||||
(hs-to-sx (nth ast 2))))
|
(hs-to-sx (nth ast 2))))
|
||||||
((= head (quote as))
|
((= head (quote as))
|
||||||
(list
|
(list (quote hs-coerce) (hs-to-sx (nth ast 1)) (nth ast 2)))
|
||||||
(quote hs-coerce)
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(nth ast 2)))
|
|
||||||
((= head (quote in?))
|
((= head (quote in?))
|
||||||
(list
|
(list
|
||||||
(quote hs-in?)
|
(quote hs-in?)
|
||||||
@@ -1462,28 +1343,20 @@
|
|||||||
((= head (quote last))
|
((= head (quote last))
|
||||||
(if
|
(if
|
||||||
(> (len ast) 2)
|
(> (len ast) 2)
|
||||||
(list
|
(list (quote hs-last) (hs-to-sx (nth ast 2)) (nth ast 1))
|
||||||
(quote hs-last)
|
|
||||||
(hs-to-sx (nth ast 2))
|
|
||||||
(nth ast 1))
|
|
||||||
(list (quote hs-query-last) (nth ast 1))))
|
(list (quote hs-query-last) (nth ast 1))))
|
||||||
((= head (quote add-class))
|
((= head (quote add-class))
|
||||||
(let
|
(let
|
||||||
((raw-tgt (nth ast 2)))
|
((raw-tgt (nth ast 2)))
|
||||||
(if
|
(if
|
||||||
(and
|
(and (list? raw-tgt) (= (first raw-tgt) (quote query)))
|
||||||
(list? raw-tgt)
|
|
||||||
(= (first raw-tgt) (quote query)))
|
|
||||||
(list
|
(list
|
||||||
(quote for-each)
|
(quote for-each)
|
||||||
(list
|
(list
|
||||||
(quote fn)
|
(quote fn)
|
||||||
(list (quote _el))
|
(list (quote _el))
|
||||||
(list
|
(list (quote dom-add-class) (quote _el) (nth ast 1)))
|
||||||
(quote dom-add-class)
|
(list (quote hs-query-all) (nth raw-tgt 1)))
|
||||||
(quote _el)
|
|
||||||
(nth ast 1)))
|
|
||||||
(list (quote hs-query-all-checked) (nth raw-tgt 1)))
|
|
||||||
(list
|
(list
|
||||||
(quote dom-add-class)
|
(quote dom-add-class)
|
||||||
(hs-to-sx raw-tgt)
|
(hs-to-sx raw-tgt)
|
||||||
@@ -1497,27 +1370,13 @@
|
|||||||
((= head (quote set-styles))
|
((= head (quote set-styles))
|
||||||
(let
|
(let
|
||||||
((pairs (nth ast 1)) (tgt (hs-to-sx (nth ast 2))))
|
((pairs (nth ast 1)) (tgt (hs-to-sx (nth ast 2))))
|
||||||
(list
|
(cons
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-tgt) tgt))
|
|
||||||
(list
|
|
||||||
(quote do)
|
(quote do)
|
||||||
(list (quote hs-null-raise!) (quote __hs-tgt))
|
|
||||||
(cons
|
|
||||||
(quote when)
|
|
||||||
(cons
|
|
||||||
(list
|
|
||||||
(quote not)
|
|
||||||
(list (quote nil?) (quote __hs-tgt)))
|
|
||||||
(map
|
(map
|
||||||
(fn
|
(fn
|
||||||
(p)
|
(p)
|
||||||
(list
|
(list (quote dom-set-style) tgt (first p) (nth p 1)))
|
||||||
(quote dom-set-style)
|
pairs))))
|
||||||
(quote __hs-tgt)
|
|
||||||
(first p)
|
|
||||||
(nth p 1)))
|
|
||||||
pairs)))))))
|
|
||||||
((= head (quote multi-add-class))
|
((= head (quote multi-add-class))
|
||||||
(let
|
(let
|
||||||
((target (hs-to-sx (nth ast 1)))
|
((target (hs-to-sx (nth ast 1)))
|
||||||
@@ -1552,10 +1411,7 @@
|
|||||||
(quote set!)
|
(quote set!)
|
||||||
(quote the-result)
|
(quote the-result)
|
||||||
(quote __hs-matched))
|
(quote __hs-matched))
|
||||||
(list
|
(list (quote set!) (quote it) (quote __hs-matched))
|
||||||
(quote set!)
|
|
||||||
(quote it)
|
|
||||||
(quote __hs-matched))
|
|
||||||
(list
|
(list
|
||||||
(quote for-each)
|
(quote for-each)
|
||||||
(list
|
(list
|
||||||
@@ -1590,10 +1446,7 @@
|
|||||||
(quote set!)
|
(quote set!)
|
||||||
(quote the-result)
|
(quote the-result)
|
||||||
(quote __hs-matched))
|
(quote __hs-matched))
|
||||||
(list
|
(list (quote set!) (quote it) (quote __hs-matched))
|
||||||
(quote set!)
|
|
||||||
(quote it)
|
|
||||||
(quote __hs-matched))
|
|
||||||
(list
|
(list
|
||||||
(quote for-each)
|
(quote for-each)
|
||||||
(list
|
(list
|
||||||
@@ -1613,17 +1466,13 @@
|
|||||||
(cons
|
(cons
|
||||||
(quote do)
|
(quote do)
|
||||||
(map
|
(map
|
||||||
(fn
|
(fn (cls) (list (quote dom-remove-class) target cls))
|
||||||
(cls)
|
|
||||||
(list (quote dom-remove-class) target cls))
|
|
||||||
classes))))
|
classes))))
|
||||||
((= head (quote remove-class))
|
((= head (quote remove-class))
|
||||||
(let
|
(let
|
||||||
((raw-tgt (nth ast 2)))
|
((raw-tgt (nth ast 2)))
|
||||||
(if
|
(if
|
||||||
(and
|
(and (list? raw-tgt) (= (first raw-tgt) (quote query)))
|
||||||
(list? raw-tgt)
|
|
||||||
(= (first raw-tgt) (quote query)))
|
|
||||||
(list
|
(list
|
||||||
(quote for-each)
|
(quote for-each)
|
||||||
(list
|
(list
|
||||||
@@ -1633,45 +1482,18 @@
|
|||||||
(quote dom-remove-class)
|
(quote dom-remove-class)
|
||||||
(quote _el)
|
(quote _el)
|
||||||
(nth ast 1)))
|
(nth ast 1)))
|
||||||
(list (quote hs-query-all-checked) (nth raw-tgt 1)))
|
(list (quote hs-query-all) (nth raw-tgt 1)))
|
||||||
(list
|
(list
|
||||||
(quote dom-remove-class)
|
(quote dom-remove-class)
|
||||||
(if (nil? raw-tgt) (quote me) (hs-to-sx raw-tgt))
|
(if (nil? raw-tgt) (quote me) (hs-to-sx raw-tgt))
|
||||||
(nth ast 1)))))
|
(nth ast 1)))))
|
||||||
((= head (quote remove-class-when))
|
|
||||||
(let
|
|
||||||
((cls (nth ast 1))
|
|
||||||
(raw-tgt (nth ast 2))
|
|
||||||
(when-cond (nth ast 3)))
|
|
||||||
(let
|
|
||||||
((tgt-expr (cond ((and (list? raw-tgt) (= (first raw-tgt) (quote query))) (list (quote hs-query-all) (nth raw-tgt 1))) (true (hs-to-sx raw-tgt)))))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list
|
|
||||||
(quote __hs-matched)
|
|
||||||
(list
|
|
||||||
(quote filter)
|
|
||||||
(list
|
|
||||||
(quote fn)
|
|
||||||
(list (quote it))
|
|
||||||
(hs-to-sx when-cond))
|
|
||||||
tgt-expr)))
|
|
||||||
(list
|
|
||||||
(quote for-each)
|
|
||||||
(list
|
|
||||||
(quote fn)
|
|
||||||
(list (quote it))
|
|
||||||
(list (quote dom-remove-class) (quote it) cls))
|
|
||||||
(quote __hs-matched))))))
|
|
||||||
((= head (quote remove-element))
|
((= head (quote remove-element))
|
||||||
(let
|
(let
|
||||||
((tgt (nth ast 1)))
|
((tgt (nth ast 1)))
|
||||||
(cond
|
(cond
|
||||||
((and (list? tgt) (= (first tgt) (quote array-index)))
|
((and (list? tgt) (= (first tgt) (quote array-index)))
|
||||||
(let
|
(let
|
||||||
((coll (nth tgt 1))
|
((coll (nth tgt 1)) (idx (hs-to-sx (nth tgt 2))))
|
||||||
(idx (hs-to-sx (nth tgt 2))))
|
|
||||||
(emit-set
|
(emit-set
|
||||||
coll
|
coll
|
||||||
(list (quote hs-splice-at!) (hs-to-sx coll) idx))))
|
(list (quote hs-splice-at!) (hs-to-sx coll) idx))))
|
||||||
@@ -1680,10 +1502,7 @@
|
|||||||
((obj (nth tgt 1)) (prop (nth tgt 2)))
|
((obj (nth tgt 1)) (prop (nth tgt 2)))
|
||||||
(emit-set
|
(emit-set
|
||||||
obj
|
obj
|
||||||
(list
|
(list (quote hs-dict-without) (hs-to-sx obj) prop))))
|
||||||
(quote hs-dict-without)
|
|
||||||
(hs-to-sx obj)
|
|
||||||
prop))))
|
|
||||||
((and (list? tgt) (= (first tgt) (quote of)))
|
((and (list? tgt) (= (first tgt) (quote of)))
|
||||||
(let
|
(let
|
||||||
((prop-ast (nth tgt 1)) (obj-ast (nth tgt 2)))
|
((prop-ast (nth tgt 1)) (obj-ast (nth tgt 2)))
|
||||||
@@ -1695,21 +1514,7 @@
|
|||||||
(quote hs-dict-without)
|
(quote hs-dict-without)
|
||||||
(hs-to-sx obj-ast)
|
(hs-to-sx obj-ast)
|
||||||
prop)))))
|
prop)))))
|
||||||
(true
|
(true (list (quote dom-remove) (hs-to-sx tgt))))))
|
||||||
(let
|
|
||||||
((tgt (hs-to-sx tgt)))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-tgt) tgt))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-tgt))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list
|
|
||||||
(quote not)
|
|
||||||
(list (quote nil?) (quote __hs-tgt)))
|
|
||||||
(list (quote dom-remove) (quote __hs-tgt))))))))))
|
|
||||||
((= head (quote add-value))
|
((= head (quote add-value))
|
||||||
(let
|
(let
|
||||||
((val (hs-to-sx (nth ast 1))) (tgt (nth ast 2)))
|
((val (hs-to-sx (nth ast 1))) (tgt (nth ast 2)))
|
||||||
@@ -1738,14 +1543,6 @@
|
|||||||
(emit-set
|
(emit-set
|
||||||
tgt
|
tgt
|
||||||
(list (quote hs-empty-like) (hs-to-sx tgt))))
|
(list (quote hs-empty-like) (hs-to-sx tgt))))
|
||||||
((and (list? tgt) (= (first tgt) (quote query)))
|
|
||||||
(list
|
|
||||||
(quote for-each)
|
|
||||||
(list
|
|
||||||
(quote fn)
|
|
||||||
(list (quote _el))
|
|
||||||
(list (quote hs-empty-target!) (quote _el)))
|
|
||||||
(list (quote hs-query-all) (nth tgt 1))))
|
|
||||||
(true (list (quote hs-empty-target!) (hs-to-sx tgt))))))
|
(true (list (quote hs-empty-target!) (hs-to-sx tgt))))))
|
||||||
((= head (quote open-element))
|
((= head (quote open-element))
|
||||||
(list (quote hs-open!) (hs-to-sx (nth ast 1))))
|
(list (quote hs-open!) (hs-to-sx (nth ast 1))))
|
||||||
@@ -1769,21 +1566,7 @@
|
|||||||
((= head (quote remove-attr))
|
((= head (quote remove-attr))
|
||||||
(let
|
(let
|
||||||
((tgt (if (nil? (nth ast 2)) (quote me) (hs-to-sx (nth ast 2)))))
|
((tgt (if (nil? (nth ast 2)) (quote me) (hs-to-sx (nth ast 2)))))
|
||||||
(list
|
(list (quote dom-remove-attr) tgt (nth ast 1))))
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-tgt) tgt))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-tgt))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list
|
|
||||||
(quote not)
|
|
||||||
(list (quote nil?) (quote __hs-tgt)))
|
|
||||||
(list
|
|
||||||
(quote dom-remove-attr)
|
|
||||||
(quote __hs-tgt)
|
|
||||||
(nth ast 1)))))))
|
|
||||||
((= head (quote remove-css))
|
((= head (quote remove-css))
|
||||||
(let
|
(let
|
||||||
((tgt (if (nil? (nth ast 2)) (quote me) (hs-to-sx (nth ast 2))))
|
((tgt (if (nil? (nth ast 2)) (quote me) (hs-to-sx (nth ast 2))))
|
||||||
@@ -1829,12 +1612,6 @@
|
|||||||
(if source (hs-to-sx source) (quote me))
|
(if source (hs-to-sx source) (quote me))
|
||||||
event-name)
|
event-name)
|
||||||
(list (quote hs-toggle-class!) tgt cls))))
|
(list (quote hs-toggle-class!) tgt cls))))
|
||||||
((= head (quote toggle-var-cycle))
|
|
||||||
(list
|
|
||||||
(quote hs-toggle-var-cycle!)
|
|
||||||
(list (quote host-global) "window")
|
|
||||||
(nth ast 1)
|
|
||||||
(cons (quote list) (map hs-to-sx (nth ast 2)))))
|
|
||||||
((= head (quote set-on))
|
((= head (quote set-on))
|
||||||
(list
|
(list
|
||||||
(quote hs-set-on!)
|
(quote hs-set-on!)
|
||||||
@@ -1913,18 +1690,6 @@
|
|||||||
(hs-to-sx (nth ast 4))))
|
(hs-to-sx (nth ast 4))))
|
||||||
((= head (quote set!))
|
((= head (quote set!))
|
||||||
(emit-set (nth ast 1) (hs-to-sx (nth ast 2))))
|
(emit-set (nth ast 1) (hs-to-sx (nth ast 2))))
|
||||||
((= head (quote set-el!))
|
|
||||||
(list
|
|
||||||
(quote hs-set-element!)
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(hs-to-sx (nth ast 2))))
|
|
||||||
((= head (quote view-transition!))
|
|
||||||
(let
|
|
||||||
((body (nth ast 2)))
|
|
||||||
(list
|
|
||||||
(quote hs-view-transition!)
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(if (nil? body) (quote nil) (hs-to-sx body)))))
|
|
||||||
((= head (quote put!))
|
((= head (quote put!))
|
||||||
(let
|
(let
|
||||||
((val (hs-to-sx (nth ast 1)))
|
((val (hs-to-sx (nth ast 1)))
|
||||||
@@ -1934,13 +1699,8 @@
|
|||||||
((and (or (= pos "end") (= pos "start")) (list? raw-tgt) (or (= (first raw-tgt) (quote local)) (= (first raw-tgt) (quote ref))))
|
((and (or (= pos "end") (= pos "start")) (list? raw-tgt) (or (= (first raw-tgt) (quote local)) (= (first raw-tgt) (quote ref))))
|
||||||
(emit-set
|
(emit-set
|
||||||
raw-tgt
|
raw-tgt
|
||||||
(list
|
(list (quote hs-put-at!) val pos (hs-to-sx raw-tgt))))
|
||||||
(quote hs-put-at!)
|
(true (list (quote hs-put!) val pos (hs-to-sx raw-tgt))))))
|
||||||
val
|
|
||||||
pos
|
|
||||||
(hs-to-sx raw-tgt))))
|
|
||||||
(true
|
|
||||||
(list (quote hs-put!) val pos (hs-to-sx raw-tgt))))))
|
|
||||||
((= head (quote if))
|
((= head (quote if))
|
||||||
(if
|
(if
|
||||||
(> (len ast) 3)
|
(> (len ast) 3)
|
||||||
@@ -1968,7 +1728,6 @@
|
|||||||
(list? c)
|
(list? c)
|
||||||
(or
|
(or
|
||||||
(= (first c) (quote hs-fetch))
|
(= (first c) (quote hs-fetch))
|
||||||
(= (first c) (quote hs-fetch-no-throw))
|
|
||||||
(= (first c) (quote hs-wait))
|
(= (first c) (quote hs-wait))
|
||||||
(= (first c) (quote hs-wait-for))
|
(= (first c) (quote hs-wait-for))
|
||||||
(= (first c) (quote hs-wait-for-or))
|
(= (first c) (quote hs-wait-for-or))
|
||||||
@@ -1982,9 +1741,7 @@
|
|||||||
(if
|
(if
|
||||||
(and
|
(and
|
||||||
(list? cmd)
|
(list? cmd)
|
||||||
(or
|
(= (first cmd) (quote hs-fetch)))
|
||||||
(= (first cmd) (quote hs-fetch))
|
|
||||||
(= (first cmd) (quote hs-fetch-no-throw))))
|
|
||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list (list (quote it) cmd))
|
(list (list (quote it) cmd))
|
||||||
@@ -2017,11 +1774,7 @@
|
|||||||
((= head (quote wait)) (list (quote hs-wait) (nth ast 1)))
|
((= head (quote wait)) (list (quote hs-wait) (nth ast 1)))
|
||||||
((= head (quote wait-for)) (emit-wait-for ast))
|
((= head (quote wait-for)) (emit-wait-for ast))
|
||||||
((= head (quote log))
|
((= head (quote log))
|
||||||
(cons
|
(list (quote console-log) (hs-to-sx (nth ast 1))))
|
||||||
(quote do)
|
|
||||||
(map
|
|
||||||
(fn (arg) (list (quote console-log) (hs-to-sx arg)))
|
|
||||||
(rest ast))))
|
|
||||||
((= head (quote send)) (emit-send ast))
|
((= head (quote send)) (emit-send ast))
|
||||||
((= head (quote trigger))
|
((= head (quote trigger))
|
||||||
(let
|
(let
|
||||||
@@ -2034,7 +1787,7 @@
|
|||||||
(tgt (if (= (len ast) 4) (nth ast 3) (nth ast 2)))
|
(tgt (if (= (len ast) 4) (nth ast 3) (nth ast 2)))
|
||||||
(detail (if (= (len ast) 4) (nth ast 2) nil)))
|
(detail (if (= (len ast) 4) (nth ast 2) nil)))
|
||||||
(list
|
(list
|
||||||
(quote hs-dispatch!)
|
(quote dom-dispatch)
|
||||||
(hs-to-sx tgt)
|
(hs-to-sx tgt)
|
||||||
name
|
name
|
||||||
(if has-detail (hs-to-sx detail) nil))))
|
(if has-detail (hs-to-sx detail) nil))))
|
||||||
@@ -2110,13 +1863,7 @@
|
|||||||
(list (quote fn) (list) (hs-to-sx (nth ast 1)))
|
(list (quote fn) (list) (hs-to-sx (nth ast 1)))
|
||||||
(list (quote fn) (list) (hs-to-sx (nth ast 2)))))
|
(list (quote fn) (list) (hs-to-sx (nth ast 2)))))
|
||||||
((= head (quote fetch))
|
((= head (quote fetch))
|
||||||
(list
|
(list (quote hs-fetch) (hs-to-sx (nth ast 1)) (nth ast 2) (nth ast 3) (quote me)))
|
||||||
(if
|
|
||||||
(nth ast 3)
|
|
||||||
(quote hs-fetch-no-throw)
|
|
||||||
(quote hs-fetch))
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(nth ast 2)))
|
|
||||||
((= head (quote fetch-gql))
|
((= head (quote fetch-gql))
|
||||||
(list
|
(list
|
||||||
(quote hs-fetch-gql)
|
(quote hs-fetch-gql)
|
||||||
@@ -2131,61 +1878,26 @@
|
|||||||
(make-symbol raw-fn)
|
(make-symbol raw-fn)
|
||||||
(hs-to-sx raw-fn)))
|
(hs-to-sx raw-fn)))
|
||||||
(args (map hs-to-sx (rest (rest ast)))))
|
(args (map hs-to-sx (rest (rest ast)))))
|
||||||
(cond
|
(if
|
||||||
((and (list? raw-fn) (= (first raw-fn) (quote ref)))
|
(and (list? raw-fn) (= (first raw-fn) (quote ref)))
|
||||||
(emit-set
|
|
||||||
(quote the-result)
|
|
||||||
(list
|
(list
|
||||||
(quote hs-win-call)
|
(quote hs-win-call)
|
||||||
(nth raw-fn 1)
|
(nth raw-fn 1)
|
||||||
(cons (quote list) args))))
|
(cons (quote list) args))
|
||||||
((and (list? raw-fn) (= (str (first raw-fn)) "."))
|
(cons fn-expr args))))
|
||||||
(let
|
|
||||||
((receiver-ast (nth raw-fn 1))
|
|
||||||
(prop-name (nth raw-fn 2))
|
|
||||||
(sel (hs-receiver-selector (nth raw-fn 1) "dot")))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list
|
|
||||||
(quote __hs-recv)
|
|
||||||
(hs-to-sx receiver-ast)))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list
|
|
||||||
(quote set!)
|
|
||||||
(quote _hs-last-query-sel)
|
|
||||||
sel)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-recv))
|
|
||||||
(emit-set
|
|
||||||
(quote the-result)
|
|
||||||
(cons
|
|
||||||
(list
|
|
||||||
(quote host-get)
|
|
||||||
(quote __hs-recv)
|
|
||||||
prop-name)
|
|
||||||
args))))))
|
|
||||||
(true
|
|
||||||
(emit-set (quote the-result) (cons fn-expr args))))))
|
|
||||||
((= head (quote return))
|
((= head (quote return))
|
||||||
(let
|
(let
|
||||||
((val (nth ast 1)))
|
((val (nth ast 1)))
|
||||||
(if
|
(if
|
||||||
(nil? val)
|
(nil? val)
|
||||||
(list
|
(list (quote raise) (list (quote list) "hs-return" nil))
|
||||||
(quote raise)
|
|
||||||
(list (quote list) "hs-return" nil))
|
|
||||||
(list
|
(list
|
||||||
(quote raise)
|
(quote raise)
|
||||||
(list (quote list) "hs-return" (hs-to-sx val))))))
|
(list (quote list) "hs-return" (hs-to-sx val))))))
|
||||||
((= head (quote throw))
|
((= head (quote throw))
|
||||||
(list (quote raise) (hs-to-sx (nth ast 1))))
|
(list (quote raise) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote settle))
|
((= head (quote settle))
|
||||||
(let
|
(list (quote hs-settle) (quote me)))
|
||||||
((raw-tgt (if (> (len ast) 1) (nth ast 1) nil)))
|
|
||||||
(list
|
|
||||||
(quote hs-settle)
|
|
||||||
(if (nil? raw-tgt) (quote me) (hs-to-sx raw-tgt)))))
|
|
||||||
((= head (quote go))
|
((= head (quote go))
|
||||||
(list (quote hs-navigate!) (hs-to-sx (nth ast 1))))
|
(list (quote hs-navigate!) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote ask))
|
((= head (quote ask))
|
||||||
@@ -2196,10 +1908,7 @@
|
|||||||
(list (list (quote __hs-a) val))
|
(list (list (quote __hs-a) val))
|
||||||
(list
|
(list
|
||||||
(quote begin)
|
(quote begin)
|
||||||
(list
|
(list (quote set!) (quote the-result) (quote __hs-a))
|
||||||
(quote set!)
|
|
||||||
(quote the-result)
|
|
||||||
(quote __hs-a))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-a))
|
(list (quote set!) (quote it) (quote __hs-a))
|
||||||
(quote __hs-a)))))
|
(quote __hs-a)))))
|
||||||
((= head (quote answer))
|
((= head (quote answer))
|
||||||
@@ -2210,10 +1919,7 @@
|
|||||||
(list (list (quote __hs-a) val))
|
(list (list (quote __hs-a) val))
|
||||||
(list
|
(list
|
||||||
(quote begin)
|
(quote begin)
|
||||||
(list
|
(list (quote set!) (quote the-result) (quote __hs-a))
|
||||||
(quote set!)
|
|
||||||
(quote the-result)
|
|
||||||
(quote __hs-a))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-a))
|
(list (quote set!) (quote it) (quote __hs-a))
|
||||||
(quote __hs-a)))))
|
(quote __hs-a)))))
|
||||||
((= head (quote answer-alert))
|
((= head (quote answer-alert))
|
||||||
@@ -2224,10 +1930,7 @@
|
|||||||
(list (list (quote __hs-a) val))
|
(list (list (quote __hs-a) val))
|
||||||
(list
|
(list
|
||||||
(quote begin)
|
(quote begin)
|
||||||
(list
|
(list (quote set!) (quote the-result) (quote __hs-a))
|
||||||
(quote set!)
|
|
||||||
(quote the-result)
|
|
||||||
(quote __hs-a))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-a))
|
(list (quote set!) (quote it) (quote __hs-a))
|
||||||
(quote __hs-a)))))
|
(quote __hs-a)))))
|
||||||
((= head (quote __get-cmd))
|
((= head (quote __get-cmd))
|
||||||
@@ -2238,10 +1941,7 @@
|
|||||||
(list (list (quote __hs-g) val))
|
(list (list (quote __hs-g) val))
|
||||||
(list
|
(list
|
||||||
(quote begin)
|
(quote begin)
|
||||||
(list
|
(list (quote set!) (quote the-result) (quote __hs-g))
|
||||||
(quote set!)
|
|
||||||
(quote the-result)
|
|
||||||
(quote __hs-g))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-g))
|
(list (quote set!) (quote it) (quote __hs-g))
|
||||||
(quote __hs-g)))))
|
(quote __hs-g)))))
|
||||||
((= head (quote append!))
|
((= head (quote append!))
|
||||||
@@ -2264,7 +1964,7 @@
|
|||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list
|
(list
|
||||||
(list (quote beingTold) tgt)
|
(list (quote me) tgt)
|
||||||
(list (quote you) tgt)
|
(list (quote you) tgt)
|
||||||
(list (quote yourself) tgt))
|
(list (quote yourself) tgt))
|
||||||
(hs-to-sx (nth ast 2)))))
|
(hs-to-sx (nth ast 2)))))
|
||||||
@@ -2315,22 +2015,7 @@
|
|||||||
(true (list (quote hs-take!) target kind name scope))))))
|
(true (list (quote hs-take!) target kind name scope))))))
|
||||||
((= head (quote make)) (emit-make ast))
|
((= head (quote make)) (emit-make ast))
|
||||||
((= head (quote install))
|
((= head (quote install))
|
||||||
(let
|
(cons (quote hs-install) (map hs-to-sx (rest ast))))
|
||||||
((bname (nth ast 1)))
|
|
||||||
(cons
|
|
||||||
(make-symbol bname)
|
|
||||||
(cons
|
|
||||||
(quote me)
|
|
||||||
(map
|
|
||||||
(fn
|
|
||||||
(arg)
|
|
||||||
(if
|
|
||||||
(and
|
|
||||||
(list? arg)
|
|
||||||
(= (first arg) (quote type-assert)))
|
|
||||||
(+ (nth arg 2) 0)
|
|
||||||
(hs-to-sx arg)))
|
|
||||||
(rest (rest ast)))))))
|
|
||||||
((= head (quote measure))
|
((= head (quote measure))
|
||||||
(list (quote hs-measure) (hs-to-sx (nth ast 1))))
|
(list (quote hs-measure) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote increment!))
|
((= head (quote increment!))
|
||||||
@@ -2355,50 +2040,18 @@
|
|||||||
((= head (quote exit)) nil)
|
((= head (quote exit)) nil)
|
||||||
((= head (quote live-no-op)) nil)
|
((= head (quote live-no-op)) nil)
|
||||||
((= head (quote when-feat-no-op)) nil)
|
((= head (quote when-feat-no-op)) nil)
|
||||||
((= head (quote bind-feat)) nil)
|
|
||||||
((= head (quote socket))
|
|
||||||
(let
|
|
||||||
((name-path (nth ast 1))
|
|
||||||
(url (nth ast 2))
|
|
||||||
(timeout (nth ast 3))
|
|
||||||
(on-message (nth ast 4)))
|
|
||||||
(let
|
|
||||||
((handler-sx (if (and (list? on-message) (= (first on-message) (quote on-message))) (list (quote fn) (list (quote event)) (hs-to-sx (nth on-message 2))) nil)))
|
|
||||||
(let
|
|
||||||
((json? (if (and (list? on-message) (= (first on-message) (quote on-message))) (nth on-message 1) false)))
|
|
||||||
(list
|
|
||||||
(quote hs-socket-register!)
|
|
||||||
(cons
|
|
||||||
(quote list)
|
|
||||||
(map (fn (seg) seg) name-path))
|
|
||||||
(hs-to-sx url)
|
|
||||||
(hs-to-sx timeout)
|
|
||||||
handler-sx
|
|
||||||
json?)))))
|
|
||||||
((= head (quote on)) (emit-on ast))
|
((= head (quote on)) (emit-on ast))
|
||||||
((= head (quote when-changes))
|
((= head (quote when-changes))
|
||||||
(let
|
(let
|
||||||
((expr (nth ast 1)) (body (nth ast 2)))
|
((expr (nth ast 1)) (body (nth ast 2)))
|
||||||
(cond
|
(if
|
||||||
((and (list? expr) (= (first expr) (quote dom-ref)))
|
(and (list? expr) (= (first expr) (quote dom-ref)))
|
||||||
(list
|
(list
|
||||||
(quote hs-dom-watch!)
|
(quote hs-dom-watch!)
|
||||||
(hs-to-sx (nth expr 2))
|
(hs-to-sx (nth expr 2))
|
||||||
(nth expr 1)
|
(nth expr 1)
|
||||||
(list
|
(list (quote fn) (list (quote it)) (hs-to-sx body)))
|
||||||
(quote fn)
|
nil)))
|
||||||
(list (quote it))
|
|
||||||
(hs-to-sx body))))
|
|
||||||
((and (list? expr) (= (first expr) (quote local)))
|
|
||||||
(list
|
|
||||||
(quote hs-scoped-watch!)
|
|
||||||
(quote me)
|
|
||||||
(nth expr 1)
|
|
||||||
(list
|
|
||||||
(quote fn)
|
|
||||||
(list (quote it))
|
|
||||||
(hs-to-sx body))))
|
|
||||||
(true nil))))
|
|
||||||
((= head (quote init))
|
((= head (quote init))
|
||||||
(list
|
(list
|
||||||
(quote hs-init)
|
(quote hs-init)
|
||||||
@@ -2453,6 +2106,7 @@
|
|||||||
(quote _hs-def-val))
|
(quote _hs-def-val))
|
||||||
(quote _hs-def-val))))))
|
(quote _hs-def-val))))))
|
||||||
((= head (quote behavior)) (emit-behavior ast))
|
((= head (quote behavior)) (emit-behavior ast))
|
||||||
|
((= head (quote socket)) (emit-socket ast))
|
||||||
((= head (quote sx-eval))
|
((= head (quote sx-eval))
|
||||||
(let
|
(let
|
||||||
((src (nth ast 1)))
|
((src (nth ast 1)))
|
||||||
@@ -2579,47 +2233,13 @@
|
|||||||
(list
|
(list
|
||||||
(quote hs-is)
|
(quote hs-is)
|
||||||
(hs-to-sx (nth ast 1))
|
(hs-to-sx (nth ast 1))
|
||||||
(list
|
(list (quote fn) (list) (hs-to-sx (nth (nth ast 2) 2)))
|
||||||
(quote fn)
|
|
||||||
(list)
|
|
||||||
(hs-to-sx (nth (nth ast 2) 2)))
|
|
||||||
(nth ast 3)))
|
(nth ast 3)))
|
||||||
((= head (quote halt!))
|
((= head (quote halt!))
|
||||||
(list (quote hs-halt!) (quote event) (nth ast 1)))
|
(list (quote hs-halt!) (quote event) (nth ast 1)))
|
||||||
((= head (quote focus!))
|
((= head (quote focus!))
|
||||||
(list (quote dom-focus) (hs-to-sx (nth ast 1))))
|
(list (quote dom-focus) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote js-block))
|
(true ast))))))))
|
||||||
(let
|
|
||||||
((params (nth ast 1)) (js-src (nth ast 2)))
|
|
||||||
(let
|
|
||||||
((bound-syms (map (fn (p) (make-symbol p)) params)))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list
|
|
||||||
(quote __hs-js)
|
|
||||||
(list
|
|
||||||
(quote hs-js-exec)
|
|
||||||
(cons (quote list) params)
|
|
||||||
js-src
|
|
||||||
(cons (quote list) bound-syms))))
|
|
||||||
(list
|
|
||||||
(quote begin)
|
|
||||||
(list (quote set!) (quote it) (quote __hs-js))
|
|
||||||
(quote __hs-js))))))
|
|
||||||
(true ast)))))))))
|
|
||||||
|
|
||||||
;; ── Convenience: source → SX ─────────────────────────────────
|
;; ── Convenience: source → SX ─────────────────────────────────
|
||||||
(define
|
|
||||||
hs-receiver-selector
|
|
||||||
(fn
|
|
||||||
(ast notation)
|
|
||||||
(cond
|
|
||||||
((and (list? ast) (= (str (first ast)) "ref")) (nth ast 1))
|
|
||||||
((and (list? ast) (= (str (first ast)) "."))
|
|
||||||
(str (hs-receiver-selector (nth ast 1) notation) "." (nth ast 2)))
|
|
||||||
((and (list? ast) (= (str (first ast)) "poss"))
|
|
||||||
(str (hs-receiver-selector (nth ast 1) "poss") "'s " (nth ast 2)))
|
|
||||||
(true "?"))))
|
|
||||||
|
|
||||||
(define hs-to-sx-from-source (fn (src) (hs-to-sx (hs-compile src))))
|
(define hs-to-sx-from-source (fn (src) (hs-to-sx (hs-compile src))))
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
(define
|
(define
|
||||||
reserved
|
reserved
|
||||||
(list
|
(list
|
||||||
(quote beingTold)
|
|
||||||
(quote me)
|
(quote me)
|
||||||
(quote it)
|
(quote it)
|
||||||
(quote event)
|
(quote event)
|
||||||
@@ -66,87 +65,33 @@
|
|||||||
(list (quote me))
|
(list (quote me))
|
||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list
|
(list (list (quote it) nil) (list (quote event) nil))
|
||||||
(list (quote beingTold) (quote me))
|
|
||||||
(list (quote it) nil)
|
|
||||||
(list (quote event) nil))
|
|
||||||
guarded))))))))))
|
guarded))))))))))
|
||||||
|
|
||||||
;; ── Activate a single element ───────────────────────────────────
|
;; ── Activate a single element ───────────────────────────────────
|
||||||
;; Reads the _="..." attribute, compiles, and executes with me=element.
|
;; Reads the _="..." attribute, compiles, and executes with me=element.
|
||||||
;; Marks the element to avoid double-activation.
|
;; Marks the element to avoid double-activation.
|
||||||
|
|
||||||
(define
|
|
||||||
hs-register-scripts!
|
|
||||||
(fn
|
|
||||||
()
|
|
||||||
(for-each
|
|
||||||
(fn
|
|
||||||
(script)
|
|
||||||
(when
|
|
||||||
(not (dom-get-data script "hs-script-loaded"))
|
|
||||||
(let
|
|
||||||
((src (host-get script "innerHTML")))
|
|
||||||
(when
|
|
||||||
(and src (not (= src "")))
|
|
||||||
(guard
|
|
||||||
(_e (true nil))
|
|
||||||
(eval-expr-cek (hs-to-sx-from-source src)))
|
|
||||||
(dom-set-data script "hs-script-loaded" true)))))
|
|
||||||
(hs-query-all "script[type=text/hyperscript]"))))
|
|
||||||
|
|
||||||
;; ── Boot: scan entire document ──────────────────────────────────
|
|
||||||
;; Called once at page load. Finds all elements with _ attribute,
|
|
||||||
;; compiles their hyperscript, and activates them.
|
|
||||||
|
|
||||||
(define
|
|
||||||
hs-scripting-disabled?
|
|
||||||
(fn
|
|
||||||
(el)
|
|
||||||
(if
|
|
||||||
(= el nil)
|
|
||||||
false
|
|
||||||
(if
|
|
||||||
(dom-get-attr el "disable-scripting")
|
|
||||||
true
|
|
||||||
(hs-scripting-disabled? (dom-parent el))))))
|
|
||||||
|
|
||||||
;; ── Boot subtree: for dynamic content ───────────────────────────
|
|
||||||
;; Called after HTMX swaps or dynamic DOM insertion.
|
|
||||||
;; Only activates elements within the given root.
|
|
||||||
|
|
||||||
(define
|
(define
|
||||||
hs-activate!
|
hs-activate!
|
||||||
(fn
|
(fn
|
||||||
(el)
|
(el)
|
||||||
(do
|
|
||||||
(hs-register-scripts!)
|
|
||||||
(let
|
(let
|
||||||
((src (dom-get-attr el "_")) (prev (dom-get-data el "hs-script")))
|
((src (dom-get-attr el "_")) (prev (dom-get-data el "hs-script")))
|
||||||
(when
|
(when
|
||||||
(and src (not (= src prev)) (not (hs-scripting-disabled? el)))
|
(and src (not (= src prev)))
|
||||||
(when
|
(when
|
||||||
(dom-dispatch el "hyperscript:before:init" nil)
|
(dom-dispatch el "hyperscript:before:init" nil)
|
||||||
(hs-log-event! "hyperscript:init")
|
(hs-log-event! "hyperscript:init")
|
||||||
(dom-set-data el "hs-script" src)
|
(dom-set-data el "hs-script" src)
|
||||||
(dom-set-data el "hs-active" true)
|
(dom-set-data el "hs-active" true)
|
||||||
(dom-set-attr el "data-hyperscript-powered" "true")
|
(dom-set-attr el "data-hyperscript-powered" "true")
|
||||||
(guard
|
(let ((handler (hs-handler src))) (handler el))
|
||||||
(_e (true nil))
|
(dom-dispatch el "hyperscript:after:init" nil))))))
|
||||||
(let
|
|
||||||
((handler (hs-handler src)))
|
;; ── Boot: scan entire document ──────────────────────────────────
|
||||||
(let
|
;; Called once at page load. Finds all elements with _ attribute,
|
||||||
((el-type (dom-get-attr el "type"))
|
;; compiles their hyperscript, and activates them.
|
||||||
(comp-name (dom-get-attr el "component")))
|
|
||||||
(let
|
|
||||||
((safe-handler (fn (e) (host-call-fn handler (list e)))))
|
|
||||||
(if
|
|
||||||
(= el-type "text/hyperscript-template")
|
|
||||||
(for-each
|
|
||||||
safe-handler
|
|
||||||
(hs-query-all (or comp-name "")))
|
|
||||||
(safe-handler el))))))
|
|
||||||
(dom-dispatch el "hyperscript:after:init" nil)))))))
|
|
||||||
|
|
||||||
(define
|
(define
|
||||||
hs-deactivate!
|
hs-deactivate!
|
||||||
@@ -159,6 +104,10 @@
|
|||||||
(dom-set-data el "hs-active" false)
|
(dom-set-data el "hs-active" false)
|
||||||
(dom-set-data el "hs-script" nil))))
|
(dom-set-data el "hs-script" nil))))
|
||||||
|
|
||||||
|
;; ── Boot subtree: for dynamic content ───────────────────────────
|
||||||
|
;; Called after HTMX swaps or dynamic DOM insertion.
|
||||||
|
;; Only activates elements within the given root.
|
||||||
|
|
||||||
(define
|
(define
|
||||||
hs-boot!
|
hs-boot!
|
||||||
(fn
|
(fn
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -131,7 +131,6 @@
|
|||||||
"append"
|
"append"
|
||||||
"settle"
|
"settle"
|
||||||
"transition"
|
"transition"
|
||||||
"view"
|
|
||||||
"over"
|
"over"
|
||||||
"closest"
|
"closest"
|
||||||
"next"
|
"next"
|
||||||
@@ -209,8 +208,7 @@
|
|||||||
"using"
|
"using"
|
||||||
"giving"
|
"giving"
|
||||||
"ask"
|
"ask"
|
||||||
"answer"
|
"answer"))
|
||||||
"bind"))
|
|
||||||
|
|
||||||
(define hs-keyword? (fn (word) (some (fn (k) (= k word)) hs-keywords)))
|
(define hs-keyword? (fn (word) (some (fn (k) (= k word)) hs-keywords)))
|
||||||
|
|
||||||
@@ -336,17 +334,11 @@
|
|||||||
(= ch "r")
|
(= ch "r")
|
||||||
(do (append! chars "\r") (hs-advance! 1))
|
(do (append! chars "\r") (hs-advance! 1))
|
||||||
(= ch "b")
|
(= ch "b")
|
||||||
(do
|
(do (append! chars (char-from-code 8)) (hs-advance! 1))
|
||||||
(append! chars (char-from-code 8))
|
|
||||||
(hs-advance! 1))
|
|
||||||
(= ch "f")
|
(= ch "f")
|
||||||
(do
|
(do (append! chars (char-from-code 12)) (hs-advance! 1))
|
||||||
(append! chars (char-from-code 12))
|
|
||||||
(hs-advance! 1))
|
|
||||||
(= ch "v")
|
(= ch "v")
|
||||||
(do
|
(do (append! chars (char-from-code 11)) (hs-advance! 1))
|
||||||
(append! chars (char-from-code 11))
|
|
||||||
(hs-advance! 1))
|
|
||||||
(= ch "\\")
|
(= ch "\\")
|
||||||
(do (append! chars "\\") (hs-advance! 1))
|
(do (append! chars "\\") (hs-advance! 1))
|
||||||
(= ch quote-char)
|
(= ch quote-char)
|
||||||
@@ -362,15 +354,11 @@
|
|||||||
(let
|
(let
|
||||||
((d1 (hs-hex-val (hs-cur)))
|
((d1 (hs-hex-val (hs-cur)))
|
||||||
(d2 (hs-hex-val (hs-peek 1))))
|
(d2 (hs-hex-val (hs-peek 1))))
|
||||||
(append!
|
(append! chars (char-from-code (+ (* d1 16) d2)))
|
||||||
chars
|
|
||||||
(char-from-code (+ (* d1 16) d2)))
|
|
||||||
(hs-advance! 2))
|
(hs-advance! 2))
|
||||||
(error "Invalid hexadecimal escape: \\x")))
|
(error "Invalid hexadecimal escape: \\x")))
|
||||||
:else (do
|
:else
|
||||||
(append! chars "\\")
|
(do (append! chars "\\") (append! chars ch) (hs-advance! 1)))))
|
||||||
(append! chars ch)
|
|
||||||
(hs-advance! 1)))))
|
|
||||||
(loop))
|
(loop))
|
||||||
(= (hs-cur) quote-char)
|
(= (hs-cur) quote-char)
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
@@ -457,68 +445,27 @@
|
|||||||
read-class-name
|
read-class-name
|
||||||
(fn
|
(fn
|
||||||
(start)
|
(start)
|
||||||
(define
|
(when
|
||||||
build-name
|
(and
|
||||||
(fn
|
(< pos src-len)
|
||||||
(acc depth)
|
(or
|
||||||
(cond
|
(hs-ident-char? (hs-cur))
|
||||||
((and (< pos src-len) (= (hs-cur) "\\") (< (+ pos 1) src-len))
|
(= (hs-cur) ":")
|
||||||
(do
|
(= (hs-cur) "[")
|
||||||
|
(= (hs-cur) "]")))
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(let
|
(read-class-name start))
|
||||||
((c (hs-cur)))
|
(slice src start pos)))
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name (str acc c) depth))))
|
|
||||||
((and (< pos src-len) (= (hs-cur) "["))
|
|
||||||
(do
|
|
||||||
(let
|
|
||||||
((c (hs-cur)))
|
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name (str acc c) (+ depth 1)))))
|
|
||||||
((and (< pos src-len) (= (hs-cur) "]"))
|
|
||||||
(do
|
|
||||||
(let
|
|
||||||
((c (hs-cur)))
|
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name
|
|
||||||
(str acc c)
|
|
||||||
(if (> depth 0) (- depth 1) 0)))))
|
|
||||||
((and (< pos src-len) (> depth 0) (or (= (hs-cur) "(") (= (hs-cur) ")")))
|
|
||||||
(do
|
|
||||||
(let
|
|
||||||
((c (hs-cur)))
|
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name (str acc c) depth))))
|
|
||||||
((and (< pos src-len) (or (hs-ident-char? (hs-cur)) (= (hs-cur) ":") (= (hs-cur) "&")))
|
|
||||||
(do
|
|
||||||
(let
|
|
||||||
((c (hs-cur)))
|
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name (str acc c) depth))))
|
|
||||||
(true acc))))
|
|
||||||
(build-name "" 0)))
|
|
||||||
(define
|
(define
|
||||||
hs-emit!
|
hs-emit!
|
||||||
(fn
|
(fn
|
||||||
(type value start)
|
(type value start)
|
||||||
(let
|
(append! tokens (hs-make-token type value start))))
|
||||||
((tok (hs-make-token type value start))
|
|
||||||
(end-pos
|
|
||||||
(max pos (+ start (if (nil? value) 0 (len (str value)))))))
|
|
||||||
(do
|
|
||||||
(dict-set! tok "end" end-pos)
|
|
||||||
(dict-set! tok "line" (len (split (slice src 0 start) "\n")))
|
|
||||||
(append! tokens tok)))))
|
|
||||||
(define
|
(define
|
||||||
scan!
|
scan!
|
||||||
(fn
|
(fn
|
||||||
()
|
()
|
||||||
(let
|
|
||||||
((ws-start pos))
|
|
||||||
(skip-ws!)
|
(skip-ws!)
|
||||||
(when
|
|
||||||
(and (> (len tokens) 0) (> pos ws-start))
|
|
||||||
(hs-emit! "whitespace" (slice src ws-start pos) ws-start)))
|
|
||||||
(when
|
(when
|
||||||
(< pos src-len)
|
(< pos src-len)
|
||||||
(let
|
(let
|
||||||
@@ -526,7 +473,11 @@
|
|||||||
(cond
|
(cond
|
||||||
(and (= ch "-") (< (+ pos 1) src-len) (= (hs-peek 1) "-"))
|
(and (= ch "-") (< (+ pos 1) src-len) (= (hs-peek 1) "-"))
|
||||||
(do (hs-advance! 2) (skip-comment!) (scan!))
|
(do (hs-advance! 2) (skip-comment!) (scan!))
|
||||||
(and (= ch "/") (< (+ pos 1) src-len) (= (hs-peek 1) "/"))
|
(and
|
||||||
|
(= ch "/")
|
||||||
|
(< (+ pos 1) src-len)
|
||||||
|
(= (hs-peek 1) "/")
|
||||||
|
(not (and (> pos 0) (= (hs-peek -1) ":"))))
|
||||||
(do (hs-advance! 2) (skip-comment!) (scan!))
|
(do (hs-advance! 2) (skip-comment!) (scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "<")
|
(= ch "<")
|
||||||
@@ -538,26 +489,10 @@
|
|||||||
(= (hs-peek 1) "#")
|
(= (hs-peek 1) "#")
|
||||||
(= (hs-peek 1) "[")
|
(= (hs-peek 1) "[")
|
||||||
(= (hs-peek 1) "*")
|
(= (hs-peek 1) "*")
|
||||||
(= (hs-peek 1) ":")
|
(= (hs-peek 1) ":")))
|
||||||
(= (hs-peek 1) "$")))
|
|
||||||
(do (hs-emit! "selector" (read-selector) start) (scan!))
|
(do (hs-emit! "selector" (read-selector) start) (scan!))
|
||||||
(and (= ch ".") (< (+ pos 1) src-len) (= (hs-peek 1) "."))
|
(and (= ch ".") (< (+ pos 1) src-len) (= (hs-peek 1) "."))
|
||||||
(do (hs-emit! "op" ".." start) (hs-advance! 2) (scan!))
|
(do (hs-emit! "op" ".." start) (hs-advance! 2) (scan!))
|
||||||
(and
|
|
||||||
(= ch ".")
|
|
||||||
(< (+ pos 1) src-len)
|
|
||||||
(or
|
|
||||||
(hs-letter? (hs-peek 1))
|
|
||||||
(= (hs-peek 1) "-")
|
|
||||||
(= (hs-peek 1) "_"))
|
|
||||||
(> (len tokens) 0)
|
|
||||||
(let
|
|
||||||
((lt (dict-get (nth tokens (- (len tokens) 1)) :type)))
|
|
||||||
(or
|
|
||||||
(= lt "paren-close")
|
|
||||||
(= lt "brace-close")
|
|
||||||
(= lt "bracket-close"))))
|
|
||||||
(do (hs-emit! "dot" "." start) (hs-advance! 1) (scan!))
|
|
||||||
(and
|
(and
|
||||||
(= ch ".")
|
(= ch ".")
|
||||||
(< (+ pos 1) src-len)
|
(< (+ pos 1) src-len)
|
||||||
@@ -569,18 +504,6 @@
|
|||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "class" (read-class-name pos) start)
|
(hs-emit! "class" (read-class-name pos) start)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
|
||||||
(= ch "#")
|
|
||||||
(< (+ pos 1) src-len)
|
|
||||||
(hs-ident-start? (hs-peek 1))
|
|
||||||
(> (len tokens) 0)
|
|
||||||
(let
|
|
||||||
((lt (dict-get (nth tokens (- (len tokens) 1)) :type)))
|
|
||||||
(or
|
|
||||||
(= lt "paren-close")
|
|
||||||
(= lt "brace-close")
|
|
||||||
(= lt "bracket-close"))))
|
|
||||||
(do (hs-emit! "op" "#" start) (hs-advance! 1) (scan!))
|
|
||||||
(and
|
(and
|
||||||
(= ch "#")
|
(= ch "#")
|
||||||
(< (+ pos 1) src-len)
|
(< (+ pos 1) src-len)
|
||||||
@@ -650,7 +573,21 @@
|
|||||||
(let
|
(let
|
||||||
((word (read-ident start)))
|
((word (read-ident start)))
|
||||||
(let
|
(let
|
||||||
((full-word (if (and (< pos src-len) (= (hs-cur) "'") (< (+ pos 1) src-len) (hs-letter? (hs-peek 1)) (not (and (= (hs-peek 1) "s") (or (>= (+ pos 2) src-len) (not (hs-ident-char? (hs-peek 2))))))) (do (hs-advance! 1) (str word "'" (read-ident pos))) word)))
|
((full-word
|
||||||
|
(if
|
||||||
|
(and
|
||||||
|
(< pos src-len)
|
||||||
|
(= (hs-cur) "'")
|
||||||
|
(< (+ pos 1) src-len)
|
||||||
|
(hs-letter? (hs-peek 1))
|
||||||
|
(not
|
||||||
|
(and
|
||||||
|
(= (hs-peek 1) "s")
|
||||||
|
(or
|
||||||
|
(>= (+ pos 2) src-len)
|
||||||
|
(not (hs-ident-char? (hs-peek 2)))))))
|
||||||
|
(do (hs-advance! 1) (str word "'" (read-ident pos)))
|
||||||
|
word)))
|
||||||
(hs-emit!
|
(hs-emit!
|
||||||
(if (hs-keyword? full-word) "keyword" "ident")
|
(if (hs-keyword? full-word) "keyword" "ident")
|
||||||
full-word
|
full-word
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ Live tally for `plans/hs-conformance-to-100.md`. Update after every cluster comm
|
|||||||
|
|
||||||
```
|
```
|
||||||
Baseline: 1213/1496 (81.1%)
|
Baseline: 1213/1496 (81.1%)
|
||||||
Merged: 1405/1496 (93.9%) delta +192
|
Merged: 1312/1496 (87.7%) delta +99
|
||||||
Worktree: all landed
|
Worktree: all landed
|
||||||
Target: 1496/1496 (100.0%)
|
Target: 1496/1496 (100.0%)
|
||||||
Remaining: ~87 tests
|
Remaining: ~192 tests (clusters 17/29(partial)/31 blocked; 33/34 partial)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cluster ledger
|
## Cluster ledger
|
||||||
@@ -30,7 +30,7 @@ Remaining: ~87 tests
|
|||||||
| 12 | `show` multi-element + display retention | done | +2 | 98c957b3 |
|
| 12 | `show` multi-element + display retention | done | +2 | 98c957b3 |
|
||||||
| 13 | `toggle` multi-class + timed + until-event | partial | +2 | bd821c04 |
|
| 13 | `toggle` multi-class + timed + until-event | partial | +2 | bd821c04 |
|
||||||
| 14 | `unless` modifier | done | +1 | c4da0698 |
|
| 14 | `unless` modifier | done | +1 | c4da0698 |
|
||||||
| 15 | `transition` query-ref + multi-prop + initial | partial | +3 | 3d352055 |
|
| 15 | `transition` query-ref + multi-prop + initial | partial | +2 | 3d352055 |
|
||||||
| 16 | `send can reference sender` | done | +1 | ed8d71c9 |
|
| 16 | `send can reference sender` | done | +1 | ed8d71c9 |
|
||||||
| 17 | `tell` semantics | blocked | — | — |
|
| 17 | `tell` semantics | blocked | — | — |
|
||||||
| 18 | `throw` respond async/sync | done | +2 | dda3becb |
|
| 18 | `throw` respond async/sync | done | +2 | dda3becb |
|
||||||
@@ -61,7 +61,7 @@ Remaining: ~87 tests
|
|||||||
|
|
||||||
| # | Cluster | Status | Δ |
|
| # | Cluster | Status | Δ |
|
||||||
|---|---------|--------|---|
|
|---|---------|--------|---|
|
||||||
| 31 | runtime null-safety error reporting | done | +13 |
|
| 31 | runtime null-safety error reporting | blocked | — |
|
||||||
| 32 | MutationObserver mock + `on mutation` | done | +7 |
|
| 32 | MutationObserver mock + `on mutation` | done | +7 |
|
||||||
| 33 | cookie API | partial | +4 |
|
| 33 | cookie API | partial | +4 |
|
||||||
| 34 | event modifier DSL | partial | +7 |
|
| 34 | event modifier DSL | partial | +7 |
|
||||||
@@ -72,10 +72,10 @@ Remaining: ~87 tests
|
|||||||
|
|
||||||
| # | Cluster | Status | Design doc |
|
| # | Cluster | Status | Design doc |
|
||||||
|---|---------|--------|------------|
|
|---|---------|--------|------------|
|
||||||
| 36 | WebSocket + `socket` + RPC proxy | done | +16 | 623529d3 |
|
| 36 | WebSocket + `socket` + RPC proxy | design-done | `plans/designs/e36-websocket.md` |
|
||||||
| 37 | Tokenizer-as-API | done | +17 | 54b54f4e |
|
| 37 | Tokenizer-as-API | design-done | `plans/designs/e37-tokenizer-api.md` |
|
||||||
| 38 | SourceInfo API | done | +2 | 48eaeb04 |
|
| 38 | SourceInfo API | design-done | `plans/designs/e38-sourceinfo.md` |
|
||||||
| 39 | WebWorker plugin | done | +1 | 8e8c2a73 |
|
| 39 | WebWorker plugin | design-done | `plans/designs/e39-webworker.md` |
|
||||||
| 40 | Fetch non-2xx / before-fetch / real response | done | +7 | d7244d1d |
|
| 40 | Fetch non-2xx / before-fetch / real response | done | +7 | d7244d1d |
|
||||||
|
|
||||||
### Bucket F — generator translation gaps
|
### Bucket F — generator translation gaps
|
||||||
@@ -88,8 +88,6 @@ Defer until A–D drain. Estimated ~25 recoverable tests.
|
|||||||
| F2 | empty multi-element (query→for-each) | done | +1 | 875e9ba3 |
|
| F2 | empty multi-element (query→for-each) | done | +1 | 875e9ba3 |
|
||||||
| F3 | hs-make-object _order + assert= for dicts | done | +1 | daea2808 |
|
| F3 | hs-make-object _order + assert= for dicts | done | +1 | daea2808 |
|
||||||
| F4 | array literal arg to JS fn (sxToJs + reduce→SX) | done | +1 | da2e6b1b |
|
| F4 | array literal arg to JS fn (sxToJs + reduce→SX) | done | +1 | da2e6b1b |
|
||||||
| F5 | `bind` feature parser stub | done | +32 | 846650da |
|
|
||||||
| F6 | `asyncError` rejected promise catch | done | +1 | — |
|
|
||||||
|
|
||||||
## Buckets roll-up
|
## Buckets roll-up
|
||||||
|
|
||||||
@@ -99,7 +97,7 @@ Defer until A–D drain. Estimated ~25 recoverable tests.
|
|||||||
| B | 7 | 0 | 0 | 0 | 0 | — | 7 |
|
| B | 7 | 0 | 0 | 0 | 0 | — | 7 |
|
||||||
| C | 4 | 1 | 0 | 0 | 0 | — | 5 |
|
| C | 4 | 1 | 0 | 0 | 0 | — | 5 |
|
||||||
| D | 2 | 2 | 0 | 0 | 1 | — | 5 |
|
| D | 2 | 2 | 0 | 0 | 1 | — | 5 |
|
||||||
| E | 5 | 0 | 0 | 0 | 0 | 0 | 5 |
|
| E | 1 | 0 | 0 | 0 | 0 | 4 | 5 |
|
||||||
| F | — | — | — | ~10 | — | — | ~10 |
|
| F | — | — | — | ~10 | — | — | ~10 |
|
||||||
|
|
||||||
## Maintenance
|
## Maintenance
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ Orchestrator cherry-picks worktree commits onto `architecture` one at a time; re
|
|||||||
|
|
||||||
All five have design docs on their own worktree branches pending review + merge. After merge, status flips to `design-ready` and they become eligible for the loop.
|
All five have design docs on their own worktree branches pending review + merge. After merge, status flips to `design-ready` and they become eligible for the loop.
|
||||||
|
|
||||||
36. **[design-done, pending review — `plans/designs/e36-websocket.md` on `worktree-agent-a9daf73703f520257`] WebSocket + `socket`** — 16 tests. Upstream shape is `socket NAME URL [with timeout N] [on message [as JSON] …] end` with an **implicit `.rpc` Proxy** (ES6 Proxy lives in JS, not SX), not `with proxy { send, receive }` as this row previously claimed. Design doc has 8-commit checklist, +12–16 delta estimate. Ship only with intentional design review.
|
36. **[DONE +16 — branch `hs-e36-websocket`] WebSocket + `socket`** — 16/16 tests passing. `socket NAME URL [with timeout N] [on message [as JSON] …] end`, RPC proxy (dispatch-fn pattern), reconnect, dispatchEvent, timeout/noTimeout chains. All 16 upstream tests green.
|
||||||
|
|
||||||
37. **[done +17]** Tokenizer-as-API — `hs-tokens-of` / `hs-stream-token` / `hs-token-type` / `hs-token-value` / `hs-token-op?`; type-map + normalize; `read-number` dot-stop fix; `\$` template escape in compiler + runtime; generator pattern in `generate-sx-tests.py`. 17/17.
|
37. **[done +17]** Tokenizer-as-API — `hs-tokens-of` / `hs-stream-token` / `hs-token-type` / `hs-token-value` / `hs-token-op?`; type-map + normalize; `read-number` dot-stop fix; `\$` template escape in compiler + runtime; generator pattern in `generate-sx-tests.py`. 17/17.
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
(let
|
(let
|
||||||
((th (first target)))
|
((th (first target)))
|
||||||
(cond
|
(cond
|
||||||
((or (= th dot-sym) (= th (make-symbol "poss")))
|
((= th dot-sym)
|
||||||
(let
|
(let
|
||||||
((base-ast (nth target 1)) (prop (nth target 2)))
|
((base-ast (nth target 1)) (prop (nth target 2)))
|
||||||
(cond
|
(cond
|
||||||
@@ -67,62 +67,17 @@
|
|||||||
value))
|
value))
|
||||||
(list (quote hs-query-all) (nth inner 1)))))
|
(list (quote hs-query-all) (nth inner 1)))))
|
||||||
(true
|
(true
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list
|
|
||||||
(quote __hs-obj)
|
|
||||||
(if
|
|
||||||
(or
|
|
||||||
(symbol? base-ast)
|
|
||||||
(and
|
|
||||||
(list? base-ast)
|
|
||||||
(= (str (first base-ast)) "ref")))
|
|
||||||
(let
|
|
||||||
((sel (if (symbol? base-ast) (str base-ast) (nth base-ast 1))))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list
|
|
||||||
(quote host-set!)
|
|
||||||
(list (quote host-global) "window")
|
|
||||||
"_hs_last_query_sel"
|
|
||||||
sel)
|
|
||||||
(hs-to-sx base-ast)))
|
|
||||||
(hs-to-sx base-ast))))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-obj))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list
|
|
||||||
(quote not)
|
|
||||||
(list (quote nil?) (quote __hs-obj)))
|
|
||||||
(list
|
(list
|
||||||
(quote dom-set-prop)
|
(quote dom-set-prop)
|
||||||
(quote __hs-obj)
|
(hs-to-sx base-ast)
|
||||||
prop
|
prop
|
||||||
value))))))))
|
value)))))
|
||||||
((= th (quote attr))
|
((= th (quote attr))
|
||||||
(let
|
|
||||||
((base-ast (nth target 2)))
|
|
||||||
(if
|
|
||||||
(and (list? base-ast) (= (str (first base-ast)) "ref"))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list
|
|
||||||
(quote set!)
|
|
||||||
(quote _hs-last-query-sel)
|
|
||||||
(nth base-ast 1))
|
|
||||||
(list
|
(list
|
||||||
(quote hs-set-attr!)
|
(quote hs-set-attr!)
|
||||||
(hs-to-sx base-ast)
|
(hs-to-sx (nth target 2))
|
||||||
(nth target 1)
|
(nth target 1)
|
||||||
value))
|
value))
|
||||||
(list
|
|
||||||
(quote hs-set-attr!)
|
|
||||||
(hs-to-sx base-ast)
|
|
||||||
(nth target 1)
|
|
||||||
value))))
|
|
||||||
((= th (quote style))
|
((= th (quote style))
|
||||||
(list
|
(list
|
||||||
(quote dom-set-style)
|
(quote dom-set-style)
|
||||||
@@ -190,16 +145,7 @@
|
|||||||
(hs-to-sx obj-ast)
|
(hs-to-sx obj-ast)
|
||||||
(nth prop-ast 1)
|
(nth prop-ast 1)
|
||||||
value)
|
value)
|
||||||
(if
|
(list (quote set!) (hs-to-sx target) value))))))
|
||||||
(and
|
|
||||||
(list? prop-ast)
|
|
||||||
(= (first prop-ast) (quote style)))
|
|
||||||
(list
|
|
||||||
(quote dom-set-style)
|
|
||||||
(hs-to-sx obj-ast)
|
|
||||||
(nth prop-ast 1)
|
|
||||||
value)
|
|
||||||
(list (quote set!) (hs-to-sx target) value)))))))
|
|
||||||
(true (list (quote set!) (hs-to-sx target) value)))))))
|
(true (list (quote set!) (hs-to-sx target) value)))))))
|
||||||
(define
|
(define
|
||||||
emit-on
|
emit-on
|
||||||
@@ -235,9 +181,9 @@
|
|||||||
(let
|
(let
|
||||||
((raw-compiled (hs-to-sx stripped-body)))
|
((raw-compiled (hs-to-sx stripped-body)))
|
||||||
(let
|
(let
|
||||||
((compiled-body (let ((base (if (> (len event-refs) 0) (let ((bindings (map (fn (r) (let ((name (nth r 1))) (list (make-symbol name) (list (quote let) (list (list (quote _det) (list (quote host-get) (quote event) "detail"))) (list (quote if) (list (quote and) (quote _det) (list (quote not) (list (quote nil?) (list (quote host-get) (quote _det) name)))) (list (quote host-get) (quote _det) name) (list (quote host-get) (quote event) name)))))) event-refs))) (list (quote let) bindings raw-compiled)) raw-compiled))) (if elsewhere? (list (quote when) (list (quote not) (list (quote host-call) (quote me) "contains" (list (quote host-get) (quote event) "target"))) base) base))))
|
((compiled-body (let ((base (if (> (len event-refs) 0) (let ((bindings (map (fn (r) (let ((name (nth r 1))) (list (make-symbol name) (list (quote host-get) (list (quote host-get) (quote event) "detail") name)))) event-refs))) (list (quote let) bindings raw-compiled)) raw-compiled))) (if elsewhere? (list (quote when) (list (quote not) (list (quote host-call) (quote me) "contains" (list (quote host-get) (quote event) "target"))) base) base))))
|
||||||
(let
|
(let
|
||||||
((wrapped-body (if catch-info (let ((var (make-symbol (nth catch-info 0))) (catch-body (hs-to-sx (nth catch-info 1)))) (if finally-info (list (quote let) (list (list (quote __hs-exc) nil) (list (quote __hs-reraise) false)) (list (quote do) (list (quote guard) (list var (list true (list (quote let) (list (list var (list (quote host-hs-normalize-exc) var))) (list (quote guard) (list (quote __inner-exc) (list true (list (quote do) (list (quote set!) (quote __hs-exc) (quote __inner-exc)) (list (quote set!) (quote __hs-reraise) true)))) catch-body)))) compiled-body) (hs-to-sx finally-info) (list (quote when) (quote __hs-reraise) (list (quote raise) (quote __hs-exc))))) (list (quote let) (list (list (quote __hs-exc) nil) (list (quote __hs-reraise) false)) (list (quote guard) (list var (list true (list (quote let) (list (list var (list (quote host-hs-normalize-exc) var))) (list (quote guard) (list (quote __inner-exc) (list true (list (quote do) (list (quote set!) (quote __hs-exc) (quote __inner-exc)) (list (quote set!) (quote __hs-reraise) true)))) catch-body)))) compiled-body) (list (quote when) (quote __hs-reraise) (list (quote raise) (quote __hs-exc)))))) (if finally-info (list (quote do) compiled-body (hs-to-sx finally-info)) compiled-body))))
|
((wrapped-body (if catch-info (let ((var (make-symbol (nth catch-info 0))) (catch-body (hs-to-sx (nth catch-info 1)))) (if finally-info (list (quote do) (list (quote guard) (list var (list true catch-body)) compiled-body) (hs-to-sx finally-info)) (list (quote guard) (list var (list true catch-body)) compiled-body))) (if finally-info (list (quote do) compiled-body (hs-to-sx finally-info)) compiled-body))))
|
||||||
(let
|
(let
|
||||||
((handler (let ((uses-the-result? (fn (expr) (cond ((= expr (quote the-result)) true) ((list? expr) (some (fn (x) (uses-the-result? x)) expr)) (true false))))) (let ((base-handler (list (quote fn) (list (quote event)) (if (uses-the-result? wrapped-body) (list (quote let) (list (list (quote the-result) nil)) wrapped-body) wrapped-body)))) (if count-filter-info (let ((mn (get count-filter-info "min")) (mx (get count-filter-info "max"))) (list (quote let) (list (list (quote __hs-count) 0)) (list (quote fn) (list (quote event)) (list (quote begin) (list (quote set!) (quote __hs-count) (list (quote +) (quote __hs-count) 1)) (list (quote when) (if (= mx -1) (list (quote >=) (quote __hs-count) mn) (list (quote and) (list (quote >=) (quote __hs-count) mn) (list (quote <=) (quote __hs-count) mx))) (nth base-handler 2)))))) base-handler)))))
|
((handler (let ((uses-the-result? (fn (expr) (cond ((= expr (quote the-result)) true) ((list? expr) (some (fn (x) (uses-the-result? x)) expr)) (true false))))) (let ((base-handler (list (quote fn) (list (quote event)) (if (uses-the-result? wrapped-body) (list (quote let) (list (list (quote the-result) nil)) wrapped-body) wrapped-body)))) (if count-filter-info (let ((mn (get count-filter-info "min")) (mx (get count-filter-info "max"))) (list (quote let) (list (list (quote __hs-count) 0)) (list (quote fn) (list (quote event)) (list (quote begin) (list (quote set!) (quote __hs-count) (list (quote +) (quote __hs-count) 1)) (list (quote when) (if (= mx -1) (list (quote >=) (quote __hs-count) mn) (list (quote and) (list (quote >=) (quote __hs-count) mn) (list (quote <=) (quote __hs-count) mx))) (nth base-handler 2)))))) base-handler)))))
|
||||||
(let
|
(let
|
||||||
@@ -410,13 +356,13 @@
|
|||||||
(cond
|
(cond
|
||||||
((and (= (len ast) 4) (list? (nth ast 2)) (= (first (nth ast 2)) (quote dict)))
|
((and (= (len ast) 4) (list? (nth ast 2)) (= (first (nth ast 2)) (quote dict)))
|
||||||
(list
|
(list
|
||||||
(quote hs-dispatch!)
|
(quote dom-dispatch)
|
||||||
(hs-to-sx (nth ast 3))
|
(hs-to-sx (nth ast 3))
|
||||||
name
|
name
|
||||||
(hs-to-sx (nth ast 2))))
|
(hs-to-sx (nth ast 2))))
|
||||||
((= (len ast) 3)
|
((= (len ast) 3)
|
||||||
(list
|
(list
|
||||||
(quote hs-dispatch!)
|
(quote dom-dispatch)
|
||||||
(hs-to-sx (nth ast 2))
|
(hs-to-sx (nth ast 2))
|
||||||
name
|
name
|
||||||
(list (quote dict) "sender" (quote me))))
|
(list (quote dict) "sender" (quote me))))
|
||||||
@@ -466,20 +412,12 @@
|
|||||||
(quote hs-repeat-times)
|
(quote hs-repeat-times)
|
||||||
(hs-to-sx mode)
|
(hs-to-sx mode)
|
||||||
(list (quote fn) (list) body)))))))
|
(list (quote fn) (list) body)))))))
|
||||||
(define
|
|
||||||
hs-reserved-var?
|
|
||||||
(fn (name) (or (= name "meta") (= name "event") (= name "result"))))
|
|
||||||
(define
|
(define
|
||||||
emit-for
|
emit-for
|
||||||
(fn
|
(fn
|
||||||
(ast)
|
(ast)
|
||||||
(let
|
(let
|
||||||
((var-name (nth ast 1))
|
((var-name (nth ast 1))
|
||||||
(safe-param
|
|
||||||
(if
|
|
||||||
(hs-reserved-var? var-name)
|
|
||||||
(str "_hs_lv_" var-name)
|
|
||||||
var-name))
|
|
||||||
(raw-coll-ast (nth ast 2))
|
(raw-coll-ast (nth ast 2))
|
||||||
(where-cond
|
(where-cond
|
||||||
(if
|
(if
|
||||||
@@ -514,12 +452,12 @@
|
|||||||
(quote map-indexed)
|
(quote map-indexed)
|
||||||
(list
|
(list
|
||||||
(quote fn)
|
(quote fn)
|
||||||
(list (make-symbol (nth ast 5)) (make-symbol safe-param))
|
(list (make-symbol (nth ast 5)) (make-symbol var-name))
|
||||||
body)
|
body)
|
||||||
collection)
|
collection)
|
||||||
(list
|
(list
|
||||||
(quote hs-for-each)
|
(quote hs-for-each)
|
||||||
(list (quote fn) (list (make-symbol safe-param)) body)
|
(list (quote fn) (list (make-symbol var-name)) body)
|
||||||
collection)))))
|
collection)))))
|
||||||
(define
|
(define
|
||||||
emit-wait-for
|
emit-wait-for
|
||||||
@@ -628,18 +566,9 @@
|
|||||||
(quote do)
|
(quote do)
|
||||||
(list (quote dom-set-attr) el attr-name (quote __hs-new))
|
(list (quote dom-set-attr) el attr-name (quote __hs-new))
|
||||||
(list (quote set!) (quote it) (quote __hs-new))))))
|
(list (quote set!) (quote it) (quote __hs-new))))))
|
||||||
((and (list? expr) (or (= (first expr) dot-sym) (= (first expr) (make-symbol "poss"))))
|
((and (list? expr) (= (first expr) dot-sym))
|
||||||
(let
|
(let
|
||||||
((obj (hs-to-sx (nth expr 1))) (prop (nth expr 2)))
|
((obj (hs-to-sx (nth expr 1))) (prop (nth expr 2)))
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-obj) obj))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-obj))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list (quote not) (list (quote nil?) (quote __hs-obj)))
|
|
||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list
|
(list
|
||||||
@@ -649,16 +578,12 @@
|
|||||||
(quote +)
|
(quote +)
|
||||||
(list
|
(list
|
||||||
(quote hs-to-number)
|
(quote hs-to-number)
|
||||||
(list (quote host-get) (quote __hs-obj) prop))
|
(list (quote host-get) obj prop))
|
||||||
amount)))
|
amount)))
|
||||||
(list
|
(list
|
||||||
(quote do)
|
(quote do)
|
||||||
(list
|
(list (quote host-set!) obj prop (quote __hs-new))
|
||||||
(quote host-set!)
|
(list (quote set!) (quote it) (quote __hs-new))))))
|
||||||
(quote __hs-obj)
|
|
||||||
prop
|
|
||||||
(quote __hs-new))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-new)))))))))
|
|
||||||
((and (list? expr) (= (first expr) (quote style)))
|
((and (list? expr) (= (first expr) (quote style)))
|
||||||
(let
|
(let
|
||||||
((el (if tgt-override (hs-to-sx tgt-override) (quote me)))
|
((el (if tgt-override (hs-to-sx tgt-override) (quote me)))
|
||||||
@@ -757,18 +682,9 @@
|
|||||||
(quote do)
|
(quote do)
|
||||||
(list (quote dom-set-attr) el attr-name (quote __hs-new))
|
(list (quote dom-set-attr) el attr-name (quote __hs-new))
|
||||||
(list (quote set!) (quote it) (quote __hs-new))))))
|
(list (quote set!) (quote it) (quote __hs-new))))))
|
||||||
((and (list? expr) (or (= (first expr) dot-sym) (= (first expr) (make-symbol "poss"))))
|
((and (list? expr) (= (first expr) dot-sym))
|
||||||
(let
|
(let
|
||||||
((obj (hs-to-sx (nth expr 1))) (prop (nth expr 2)))
|
((obj (hs-to-sx (nth expr 1))) (prop (nth expr 2)))
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-obj) obj))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-obj))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list (quote not) (list (quote nil?) (quote __hs-obj)))
|
|
||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list
|
(list
|
||||||
@@ -778,16 +694,12 @@
|
|||||||
(quote -)
|
(quote -)
|
||||||
(list
|
(list
|
||||||
(quote hs-to-number)
|
(quote hs-to-number)
|
||||||
(list (quote host-get) (quote __hs-obj) prop))
|
(list (quote host-get) obj prop))
|
||||||
amount)))
|
amount)))
|
||||||
(list
|
(list
|
||||||
(quote do)
|
(quote do)
|
||||||
(list
|
(list (quote host-set!) obj prop (quote __hs-new))
|
||||||
(quote host-set!)
|
(list (quote set!) (quote it) (quote __hs-new))))))
|
||||||
(quote __hs-obj)
|
|
||||||
prop
|
|
||||||
(quote __hs-new))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-new)))))))))
|
|
||||||
((and (list? expr) (= (first expr) (quote style)))
|
((and (list? expr) (= (first expr) (quote style)))
|
||||||
(let
|
(let
|
||||||
((el (if tgt-override (hs-to-sx tgt-override) (quote me)))
|
((el (if tgt-override (hs-to-sx tgt-override) (quote me)))
|
||||||
@@ -873,21 +785,35 @@
|
|||||||
(make-symbol name)
|
(make-symbol name)
|
||||||
(list
|
(list
|
||||||
(quote fn)
|
(quote fn)
|
||||||
(cons
|
(cons (quote me) (map make-symbol params))
|
||||||
(quote me)
|
(cons (quote do) (map hs-to-sx body)))))))
|
||||||
(map
|
(define
|
||||||
(fn
|
emit-socket
|
||||||
(p)
|
|
||||||
(if (list? p) (make-symbol (nth p 1)) (make-symbol p)))
|
|
||||||
params))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list (list (quote beingTold) (quote me)))
|
|
||||||
(cons (quote do) (map hs-to-sx body))))))))
|
|
||||||
(fn
|
(fn
|
||||||
(ast)
|
(ast)
|
||||||
(let
|
(let
|
||||||
((ast (if (and (dict? ast) (get ast :hs-ast)) (get ast :children) ast)))
|
((name-path (nth ast 1))
|
||||||
|
(url (nth ast 2))
|
||||||
|
(timeout-ms (nth ast 3))
|
||||||
|
(on-msg (nth ast 4)))
|
||||||
|
(let
|
||||||
|
((handler
|
||||||
|
(if
|
||||||
|
(nil? on-msg)
|
||||||
|
nil
|
||||||
|
(let
|
||||||
|
((body (hs-to-sx (nth on-msg 2))))
|
||||||
|
(list (quote fn) (list (quote event)) body))))
|
||||||
|
(json?-val (if (nil? on-msg) false (nth on-msg 1))))
|
||||||
|
(list
|
||||||
|
(quote hs-socket-register!)
|
||||||
|
(cons (quote list) name-path)
|
||||||
|
url
|
||||||
|
(if (nil? timeout-ms) nil (hs-to-sx timeout-ms))
|
||||||
|
handler
|
||||||
|
json?-val)))))
|
||||||
|
(fn
|
||||||
|
(ast)
|
||||||
(cond
|
(cond
|
||||||
((nil? ast) nil)
|
((nil? ast) nil)
|
||||||
((number? ast) ast)
|
((number? ast) ast)
|
||||||
@@ -992,10 +918,7 @@
|
|||||||
(let
|
(let
|
||||||
((ch (nth raw i)))
|
((ch (nth raw i)))
|
||||||
(if
|
(if
|
||||||
(and
|
(and (= ch "\\") (< (+ i 1) n) (= (nth raw (+ i 1)) "$"))
|
||||||
(= ch "\\")
|
|
||||||
(< (+ i 1) n)
|
|
||||||
(= (nth raw (+ i 1)) "$"))
|
|
||||||
(do
|
(do
|
||||||
(set! buf (str buf "$"))
|
(set! buf (str buf "$"))
|
||||||
(set! i (+ i 2))
|
(set! i (+ i 2))
|
||||||
@@ -1017,8 +940,7 @@
|
|||||||
(append
|
(append
|
||||||
parts
|
parts
|
||||||
(list
|
(list
|
||||||
(hs-to-sx
|
(hs-to-sx (hs-compile expr-src)))))
|
||||||
(hs-compile expr-src)))))
|
|
||||||
(set! i (+ close 1))
|
(set! i (+ close 1))
|
||||||
(tpl-collect)))))
|
(tpl-collect)))))
|
||||||
(let
|
(let
|
||||||
@@ -1034,8 +956,7 @@
|
|||||||
(append
|
(append
|
||||||
parts
|
parts
|
||||||
(list
|
(list
|
||||||
(hs-to-sx
|
(hs-to-sx (hs-compile ident)))))
|
||||||
(hs-compile ident)))))
|
|
||||||
(set! i end)
|
(set! i end)
|
||||||
(tpl-collect))))))
|
(tpl-collect))))))
|
||||||
(do
|
(do
|
||||||
@@ -1113,21 +1034,13 @@
|
|||||||
(hs-to-sx (nth ast 1))
|
(hs-to-sx (nth ast 1))
|
||||||
(nth ast 2)))
|
(nth ast 2)))
|
||||||
((= head (quote coll-where))
|
((= head (quote coll-where))
|
||||||
(let
|
|
||||||
((raw-coll (hs-to-sx (nth ast 1))))
|
|
||||||
(list
|
(list
|
||||||
(quote filter)
|
(quote filter)
|
||||||
(list
|
(list
|
||||||
(quote fn)
|
(quote fn)
|
||||||
(list (quote it))
|
(list (quote it))
|
||||||
(hs-to-sx (nth ast 2)))
|
(hs-to-sx (nth ast 2)))
|
||||||
(if
|
(hs-to-sx (nth ast 1))))
|
||||||
(symbol? raw-coll)
|
|
||||||
(list
|
|
||||||
(quote cek-try)
|
|
||||||
(list (quote fn) (list) raw-coll)
|
|
||||||
(list (quote fn) (list (quote _e)) nil))
|
|
||||||
raw-coll))))
|
|
||||||
((= head (quote coll-sorted))
|
((= head (quote coll-sorted))
|
||||||
(list
|
(list
|
||||||
(quote hs-sorted-by)
|
(quote hs-sorted-by)
|
||||||
@@ -1169,29 +1082,13 @@
|
|||||||
(if
|
(if
|
||||||
(and
|
(and
|
||||||
(list? dot-node)
|
(list? dot-node)
|
||||||
(or
|
(= (first dot-node) (make-symbol ".")))
|
||||||
(= (str (first dot-node)) ".")
|
|
||||||
(= (str (first dot-node)) "poss")))
|
|
||||||
(let
|
(let
|
||||||
((receiver-ast (nth dot-node 1))
|
((obj (hs-to-sx (nth dot-node 1)))
|
||||||
(method (nth dot-node 2))
|
(method (nth dot-node 2)))
|
||||||
(sel
|
|
||||||
(hs-receiver-selector (nth dot-node 1) "poss")))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list (quote __hs-recv) (hs-to-sx receiver-ast)))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list
|
|
||||||
(quote host-set!)
|
|
||||||
(list (quote host-global) "window")
|
|
||||||
"_hs_last_query_sel"
|
|
||||||
sel)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-recv))
|
|
||||||
(cons
|
(cons
|
||||||
(quote hs-method-call)
|
(quote hs-method-call)
|
||||||
(cons (quote __hs-recv) (cons method args))))))
|
(cons obj (cons method args))))
|
||||||
(if
|
(if
|
||||||
(and
|
(and
|
||||||
(list? dot-node)
|
(list? dot-node)
|
||||||
@@ -1209,9 +1106,11 @@
|
|||||||
(let
|
(let
|
||||||
((params (map make-symbol (nth ast 1)))
|
((params (map make-symbol (nth ast 1)))
|
||||||
(body (hs-to-sx (nth ast 2))))
|
(body (hs-to-sx (nth ast 2))))
|
||||||
(list (quote fn) params body)))
|
(if
|
||||||
|
(= (len params) 0)
|
||||||
|
body
|
||||||
|
(list (quote fn) params body))))
|
||||||
((= head (quote me)) (quote me))
|
((= head (quote me)) (quote me))
|
||||||
((= head (quote beingTold)) (quote beingTold))
|
|
||||||
((= head (quote it)) (quote it))
|
((= head (quote it)) (quote it))
|
||||||
((= head (quote event)) (quote event))
|
((= head (quote event)) (quote event))
|
||||||
((= head dot-sym)
|
((= head dot-sym)
|
||||||
@@ -1222,16 +1121,11 @@
|
|||||||
((= prop "first") (list (quote hs-first) target))
|
((= prop "first") (list (quote hs-first) target))
|
||||||
((= prop "last") (list (quote hs-last) target))
|
((= prop "last") (list (quote hs-last) target))
|
||||||
(true (list (quote host-get) target prop)))))
|
(true (list (quote host-get) target prop)))))
|
||||||
((= head (make-symbol "poss"))
|
|
||||||
(let
|
|
||||||
((target (hs-to-sx (nth ast 1))) (prop (nth ast 2)))
|
|
||||||
(list (quote host-get) target prop)))
|
|
||||||
((= head (quote ref))
|
((= head (quote ref))
|
||||||
(cond
|
(if
|
||||||
((= (nth ast 1) "selection")
|
(= (nth ast 1) "selection")
|
||||||
(list (quote hs-get-selection)))
|
(list (quote hs-get-selection))
|
||||||
((= (nth ast 1) "element") (make-symbol "me"))
|
(make-symbol (nth ast 1))))
|
||||||
(else (make-symbol (nth ast 1)))))
|
|
||||||
((= head (quote query))
|
((= head (quote query))
|
||||||
(list (quote hs-query-first) (nth ast 1)))
|
(list (quote hs-query-first) (nth ast 1)))
|
||||||
((= head (quote query-scoped))
|
((= head (quote query-scoped))
|
||||||
@@ -1267,8 +1161,6 @@
|
|||||||
(list (quote not) (hs-to-sx (nth ast 1))))
|
(list (quote not) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote no))
|
((= head (quote no))
|
||||||
(list (quote hs-falsy?) (hs-to-sx (nth ast 1))))
|
(list (quote hs-falsy?) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote hs-falsy?))
|
|
||||||
(list (quote hs-falsy?) (hs-to-sx (nth ast 1))))
|
|
||||||
((= head (quote and))
|
((= head (quote and))
|
||||||
(list
|
(list
|
||||||
(quote and)
|
(quote and)
|
||||||
@@ -1284,11 +1176,6 @@
|
|||||||
(quote =)
|
(quote =)
|
||||||
(hs-to-sx (nth ast 1))
|
(hs-to-sx (nth ast 1))
|
||||||
(hs-to-sx (nth ast 2))))
|
(hs-to-sx (nth ast 2))))
|
||||||
((= head (quote hs-id=))
|
|
||||||
(list
|
|
||||||
(quote hs-id=)
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(hs-to-sx (nth ast 2))))
|
|
||||||
((= head (quote +))
|
((= head (quote +))
|
||||||
(list
|
(list
|
||||||
(quote hs-add)
|
(quote hs-add)
|
||||||
@@ -1328,10 +1215,7 @@
|
|||||||
((left (nth ast 1)) (right (nth ast 2)))
|
((left (nth ast 1)) (right (nth ast 2)))
|
||||||
(if
|
(if
|
||||||
(and (list? right) (= (first right) (quote query)))
|
(and (list? right) (= (first right) (quote query)))
|
||||||
(list
|
(list (quote hs-matches?) (hs-to-sx left) (nth right 1))
|
||||||
(quote hs-matches?)
|
|
||||||
(hs-to-sx left)
|
|
||||||
(nth right 1))
|
|
||||||
(list
|
(list
|
||||||
(quote hs-matches?)
|
(quote hs-matches?)
|
||||||
(hs-to-sx left)
|
(hs-to-sx left)
|
||||||
@@ -1382,10 +1266,7 @@
|
|||||||
(hs-to-sx (nth ast 1))
|
(hs-to-sx (nth ast 1))
|
||||||
(hs-to-sx (nth ast 2))))
|
(hs-to-sx (nth ast 2))))
|
||||||
((= head (quote as))
|
((= head (quote as))
|
||||||
(list
|
(list (quote hs-coerce) (hs-to-sx (nth ast 1)) (nth ast 2)))
|
||||||
(quote hs-coerce)
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(nth ast 2)))
|
|
||||||
((= head (quote in?))
|
((= head (quote in?))
|
||||||
(list
|
(list
|
||||||
(quote hs-in?)
|
(quote hs-in?)
|
||||||
@@ -1462,28 +1343,20 @@
|
|||||||
((= head (quote last))
|
((= head (quote last))
|
||||||
(if
|
(if
|
||||||
(> (len ast) 2)
|
(> (len ast) 2)
|
||||||
(list
|
(list (quote hs-last) (hs-to-sx (nth ast 2)) (nth ast 1))
|
||||||
(quote hs-last)
|
|
||||||
(hs-to-sx (nth ast 2))
|
|
||||||
(nth ast 1))
|
|
||||||
(list (quote hs-query-last) (nth ast 1))))
|
(list (quote hs-query-last) (nth ast 1))))
|
||||||
((= head (quote add-class))
|
((= head (quote add-class))
|
||||||
(let
|
(let
|
||||||
((raw-tgt (nth ast 2)))
|
((raw-tgt (nth ast 2)))
|
||||||
(if
|
(if
|
||||||
(and
|
(and (list? raw-tgt) (= (first raw-tgt) (quote query)))
|
||||||
(list? raw-tgt)
|
|
||||||
(= (first raw-tgt) (quote query)))
|
|
||||||
(list
|
(list
|
||||||
(quote for-each)
|
(quote for-each)
|
||||||
(list
|
(list
|
||||||
(quote fn)
|
(quote fn)
|
||||||
(list (quote _el))
|
(list (quote _el))
|
||||||
(list
|
(list (quote dom-add-class) (quote _el) (nth ast 1)))
|
||||||
(quote dom-add-class)
|
(list (quote hs-query-all) (nth raw-tgt 1)))
|
||||||
(quote _el)
|
|
||||||
(nth ast 1)))
|
|
||||||
(list (quote hs-query-all-checked) (nth raw-tgt 1)))
|
|
||||||
(list
|
(list
|
||||||
(quote dom-add-class)
|
(quote dom-add-class)
|
||||||
(hs-to-sx raw-tgt)
|
(hs-to-sx raw-tgt)
|
||||||
@@ -1497,27 +1370,13 @@
|
|||||||
((= head (quote set-styles))
|
((= head (quote set-styles))
|
||||||
(let
|
(let
|
||||||
((pairs (nth ast 1)) (tgt (hs-to-sx (nth ast 2))))
|
((pairs (nth ast 1)) (tgt (hs-to-sx (nth ast 2))))
|
||||||
(list
|
(cons
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-tgt) tgt))
|
|
||||||
(list
|
|
||||||
(quote do)
|
(quote do)
|
||||||
(list (quote hs-null-raise!) (quote __hs-tgt))
|
|
||||||
(cons
|
|
||||||
(quote when)
|
|
||||||
(cons
|
|
||||||
(list
|
|
||||||
(quote not)
|
|
||||||
(list (quote nil?) (quote __hs-tgt)))
|
|
||||||
(map
|
(map
|
||||||
(fn
|
(fn
|
||||||
(p)
|
(p)
|
||||||
(list
|
(list (quote dom-set-style) tgt (first p) (nth p 1)))
|
||||||
(quote dom-set-style)
|
pairs))))
|
||||||
(quote __hs-tgt)
|
|
||||||
(first p)
|
|
||||||
(nth p 1)))
|
|
||||||
pairs)))))))
|
|
||||||
((= head (quote multi-add-class))
|
((= head (quote multi-add-class))
|
||||||
(let
|
(let
|
||||||
((target (hs-to-sx (nth ast 1)))
|
((target (hs-to-sx (nth ast 1)))
|
||||||
@@ -1552,10 +1411,7 @@
|
|||||||
(quote set!)
|
(quote set!)
|
||||||
(quote the-result)
|
(quote the-result)
|
||||||
(quote __hs-matched))
|
(quote __hs-matched))
|
||||||
(list
|
(list (quote set!) (quote it) (quote __hs-matched))
|
||||||
(quote set!)
|
|
||||||
(quote it)
|
|
||||||
(quote __hs-matched))
|
|
||||||
(list
|
(list
|
||||||
(quote for-each)
|
(quote for-each)
|
||||||
(list
|
(list
|
||||||
@@ -1590,10 +1446,7 @@
|
|||||||
(quote set!)
|
(quote set!)
|
||||||
(quote the-result)
|
(quote the-result)
|
||||||
(quote __hs-matched))
|
(quote __hs-matched))
|
||||||
(list
|
(list (quote set!) (quote it) (quote __hs-matched))
|
||||||
(quote set!)
|
|
||||||
(quote it)
|
|
||||||
(quote __hs-matched))
|
|
||||||
(list
|
(list
|
||||||
(quote for-each)
|
(quote for-each)
|
||||||
(list
|
(list
|
||||||
@@ -1613,17 +1466,13 @@
|
|||||||
(cons
|
(cons
|
||||||
(quote do)
|
(quote do)
|
||||||
(map
|
(map
|
||||||
(fn
|
(fn (cls) (list (quote dom-remove-class) target cls))
|
||||||
(cls)
|
|
||||||
(list (quote dom-remove-class) target cls))
|
|
||||||
classes))))
|
classes))))
|
||||||
((= head (quote remove-class))
|
((= head (quote remove-class))
|
||||||
(let
|
(let
|
||||||
((raw-tgt (nth ast 2)))
|
((raw-tgt (nth ast 2)))
|
||||||
(if
|
(if
|
||||||
(and
|
(and (list? raw-tgt) (= (first raw-tgt) (quote query)))
|
||||||
(list? raw-tgt)
|
|
||||||
(= (first raw-tgt) (quote query)))
|
|
||||||
(list
|
(list
|
||||||
(quote for-each)
|
(quote for-each)
|
||||||
(list
|
(list
|
||||||
@@ -1633,45 +1482,18 @@
|
|||||||
(quote dom-remove-class)
|
(quote dom-remove-class)
|
||||||
(quote _el)
|
(quote _el)
|
||||||
(nth ast 1)))
|
(nth ast 1)))
|
||||||
(list (quote hs-query-all-checked) (nth raw-tgt 1)))
|
(list (quote hs-query-all) (nth raw-tgt 1)))
|
||||||
(list
|
(list
|
||||||
(quote dom-remove-class)
|
(quote dom-remove-class)
|
||||||
(if (nil? raw-tgt) (quote me) (hs-to-sx raw-tgt))
|
(if (nil? raw-tgt) (quote me) (hs-to-sx raw-tgt))
|
||||||
(nth ast 1)))))
|
(nth ast 1)))))
|
||||||
((= head (quote remove-class-when))
|
|
||||||
(let
|
|
||||||
((cls (nth ast 1))
|
|
||||||
(raw-tgt (nth ast 2))
|
|
||||||
(when-cond (nth ast 3)))
|
|
||||||
(let
|
|
||||||
((tgt-expr (cond ((and (list? raw-tgt) (= (first raw-tgt) (quote query))) (list (quote hs-query-all) (nth raw-tgt 1))) (true (hs-to-sx raw-tgt)))))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list
|
|
||||||
(quote __hs-matched)
|
|
||||||
(list
|
|
||||||
(quote filter)
|
|
||||||
(list
|
|
||||||
(quote fn)
|
|
||||||
(list (quote it))
|
|
||||||
(hs-to-sx when-cond))
|
|
||||||
tgt-expr)))
|
|
||||||
(list
|
|
||||||
(quote for-each)
|
|
||||||
(list
|
|
||||||
(quote fn)
|
|
||||||
(list (quote it))
|
|
||||||
(list (quote dom-remove-class) (quote it) cls))
|
|
||||||
(quote __hs-matched))))))
|
|
||||||
((= head (quote remove-element))
|
((= head (quote remove-element))
|
||||||
(let
|
(let
|
||||||
((tgt (nth ast 1)))
|
((tgt (nth ast 1)))
|
||||||
(cond
|
(cond
|
||||||
((and (list? tgt) (= (first tgt) (quote array-index)))
|
((and (list? tgt) (= (first tgt) (quote array-index)))
|
||||||
(let
|
(let
|
||||||
((coll (nth tgt 1))
|
((coll (nth tgt 1)) (idx (hs-to-sx (nth tgt 2))))
|
||||||
(idx (hs-to-sx (nth tgt 2))))
|
|
||||||
(emit-set
|
(emit-set
|
||||||
coll
|
coll
|
||||||
(list (quote hs-splice-at!) (hs-to-sx coll) idx))))
|
(list (quote hs-splice-at!) (hs-to-sx coll) idx))))
|
||||||
@@ -1680,10 +1502,7 @@
|
|||||||
((obj (nth tgt 1)) (prop (nth tgt 2)))
|
((obj (nth tgt 1)) (prop (nth tgt 2)))
|
||||||
(emit-set
|
(emit-set
|
||||||
obj
|
obj
|
||||||
(list
|
(list (quote hs-dict-without) (hs-to-sx obj) prop))))
|
||||||
(quote hs-dict-without)
|
|
||||||
(hs-to-sx obj)
|
|
||||||
prop))))
|
|
||||||
((and (list? tgt) (= (first tgt) (quote of)))
|
((and (list? tgt) (= (first tgt) (quote of)))
|
||||||
(let
|
(let
|
||||||
((prop-ast (nth tgt 1)) (obj-ast (nth tgt 2)))
|
((prop-ast (nth tgt 1)) (obj-ast (nth tgt 2)))
|
||||||
@@ -1695,21 +1514,7 @@
|
|||||||
(quote hs-dict-without)
|
(quote hs-dict-without)
|
||||||
(hs-to-sx obj-ast)
|
(hs-to-sx obj-ast)
|
||||||
prop)))))
|
prop)))))
|
||||||
(true
|
(true (list (quote dom-remove) (hs-to-sx tgt))))))
|
||||||
(let
|
|
||||||
((tgt (hs-to-sx tgt)))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-tgt) tgt))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-tgt))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list
|
|
||||||
(quote not)
|
|
||||||
(list (quote nil?) (quote __hs-tgt)))
|
|
||||||
(list (quote dom-remove) (quote __hs-tgt))))))))))
|
|
||||||
((= head (quote add-value))
|
((= head (quote add-value))
|
||||||
(let
|
(let
|
||||||
((val (hs-to-sx (nth ast 1))) (tgt (nth ast 2)))
|
((val (hs-to-sx (nth ast 1))) (tgt (nth ast 2)))
|
||||||
@@ -1738,14 +1543,6 @@
|
|||||||
(emit-set
|
(emit-set
|
||||||
tgt
|
tgt
|
||||||
(list (quote hs-empty-like) (hs-to-sx tgt))))
|
(list (quote hs-empty-like) (hs-to-sx tgt))))
|
||||||
((and (list? tgt) (= (first tgt) (quote query)))
|
|
||||||
(list
|
|
||||||
(quote for-each)
|
|
||||||
(list
|
|
||||||
(quote fn)
|
|
||||||
(list (quote _el))
|
|
||||||
(list (quote hs-empty-target!) (quote _el)))
|
|
||||||
(list (quote hs-query-all) (nth tgt 1))))
|
|
||||||
(true (list (quote hs-empty-target!) (hs-to-sx tgt))))))
|
(true (list (quote hs-empty-target!) (hs-to-sx tgt))))))
|
||||||
((= head (quote open-element))
|
((= head (quote open-element))
|
||||||
(list (quote hs-open!) (hs-to-sx (nth ast 1))))
|
(list (quote hs-open!) (hs-to-sx (nth ast 1))))
|
||||||
@@ -1769,21 +1566,7 @@
|
|||||||
((= head (quote remove-attr))
|
((= head (quote remove-attr))
|
||||||
(let
|
(let
|
||||||
((tgt (if (nil? (nth ast 2)) (quote me) (hs-to-sx (nth ast 2)))))
|
((tgt (if (nil? (nth ast 2)) (quote me) (hs-to-sx (nth ast 2)))))
|
||||||
(list
|
(list (quote dom-remove-attr) tgt (nth ast 1))))
|
||||||
(quote let)
|
|
||||||
(list (list (quote __hs-tgt) tgt))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-tgt))
|
|
||||||
(list
|
|
||||||
(quote when)
|
|
||||||
(list
|
|
||||||
(quote not)
|
|
||||||
(list (quote nil?) (quote __hs-tgt)))
|
|
||||||
(list
|
|
||||||
(quote dom-remove-attr)
|
|
||||||
(quote __hs-tgt)
|
|
||||||
(nth ast 1)))))))
|
|
||||||
((= head (quote remove-css))
|
((= head (quote remove-css))
|
||||||
(let
|
(let
|
||||||
((tgt (if (nil? (nth ast 2)) (quote me) (hs-to-sx (nth ast 2))))
|
((tgt (if (nil? (nth ast 2)) (quote me) (hs-to-sx (nth ast 2))))
|
||||||
@@ -1829,12 +1612,6 @@
|
|||||||
(if source (hs-to-sx source) (quote me))
|
(if source (hs-to-sx source) (quote me))
|
||||||
event-name)
|
event-name)
|
||||||
(list (quote hs-toggle-class!) tgt cls))))
|
(list (quote hs-toggle-class!) tgt cls))))
|
||||||
((= head (quote toggle-var-cycle))
|
|
||||||
(list
|
|
||||||
(quote hs-toggle-var-cycle!)
|
|
||||||
(list (quote host-global) "window")
|
|
||||||
(nth ast 1)
|
|
||||||
(cons (quote list) (map hs-to-sx (nth ast 2)))))
|
|
||||||
((= head (quote set-on))
|
((= head (quote set-on))
|
||||||
(list
|
(list
|
||||||
(quote hs-set-on!)
|
(quote hs-set-on!)
|
||||||
@@ -1913,18 +1690,6 @@
|
|||||||
(hs-to-sx (nth ast 4))))
|
(hs-to-sx (nth ast 4))))
|
||||||
((= head (quote set!))
|
((= head (quote set!))
|
||||||
(emit-set (nth ast 1) (hs-to-sx (nth ast 2))))
|
(emit-set (nth ast 1) (hs-to-sx (nth ast 2))))
|
||||||
((= head (quote set-el!))
|
|
||||||
(list
|
|
||||||
(quote hs-set-element!)
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(hs-to-sx (nth ast 2))))
|
|
||||||
((= head (quote view-transition!))
|
|
||||||
(let
|
|
||||||
((body (nth ast 2)))
|
|
||||||
(list
|
|
||||||
(quote hs-view-transition!)
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(if (nil? body) (quote nil) (hs-to-sx body)))))
|
|
||||||
((= head (quote put!))
|
((= head (quote put!))
|
||||||
(let
|
(let
|
||||||
((val (hs-to-sx (nth ast 1)))
|
((val (hs-to-sx (nth ast 1)))
|
||||||
@@ -1934,13 +1699,8 @@
|
|||||||
((and (or (= pos "end") (= pos "start")) (list? raw-tgt) (or (= (first raw-tgt) (quote local)) (= (first raw-tgt) (quote ref))))
|
((and (or (= pos "end") (= pos "start")) (list? raw-tgt) (or (= (first raw-tgt) (quote local)) (= (first raw-tgt) (quote ref))))
|
||||||
(emit-set
|
(emit-set
|
||||||
raw-tgt
|
raw-tgt
|
||||||
(list
|
(list (quote hs-put-at!) val pos (hs-to-sx raw-tgt))))
|
||||||
(quote hs-put-at!)
|
(true (list (quote hs-put!) val pos (hs-to-sx raw-tgt))))))
|
||||||
val
|
|
||||||
pos
|
|
||||||
(hs-to-sx raw-tgt))))
|
|
||||||
(true
|
|
||||||
(list (quote hs-put!) val pos (hs-to-sx raw-tgt))))))
|
|
||||||
((= head (quote if))
|
((= head (quote if))
|
||||||
(if
|
(if
|
||||||
(> (len ast) 3)
|
(> (len ast) 3)
|
||||||
@@ -1968,7 +1728,6 @@
|
|||||||
(list? c)
|
(list? c)
|
||||||
(or
|
(or
|
||||||
(= (first c) (quote hs-fetch))
|
(= (first c) (quote hs-fetch))
|
||||||
(= (first c) (quote hs-fetch-no-throw))
|
|
||||||
(= (first c) (quote hs-wait))
|
(= (first c) (quote hs-wait))
|
||||||
(= (first c) (quote hs-wait-for))
|
(= (first c) (quote hs-wait-for))
|
||||||
(= (first c) (quote hs-wait-for-or))
|
(= (first c) (quote hs-wait-for-or))
|
||||||
@@ -1982,9 +1741,7 @@
|
|||||||
(if
|
(if
|
||||||
(and
|
(and
|
||||||
(list? cmd)
|
(list? cmd)
|
||||||
(or
|
(= (first cmd) (quote hs-fetch)))
|
||||||
(= (first cmd) (quote hs-fetch))
|
|
||||||
(= (first cmd) (quote hs-fetch-no-throw))))
|
|
||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list (list (quote it) cmd))
|
(list (list (quote it) cmd))
|
||||||
@@ -2030,7 +1787,7 @@
|
|||||||
(tgt (if (= (len ast) 4) (nth ast 3) (nth ast 2)))
|
(tgt (if (= (len ast) 4) (nth ast 3) (nth ast 2)))
|
||||||
(detail (if (= (len ast) 4) (nth ast 2) nil)))
|
(detail (if (= (len ast) 4) (nth ast 2) nil)))
|
||||||
(list
|
(list
|
||||||
(quote hs-dispatch!)
|
(quote dom-dispatch)
|
||||||
(hs-to-sx tgt)
|
(hs-to-sx tgt)
|
||||||
name
|
name
|
||||||
(if has-detail (hs-to-sx detail) nil))))
|
(if has-detail (hs-to-sx detail) nil))))
|
||||||
@@ -2106,13 +1863,7 @@
|
|||||||
(list (quote fn) (list) (hs-to-sx (nth ast 1)))
|
(list (quote fn) (list) (hs-to-sx (nth ast 1)))
|
||||||
(list (quote fn) (list) (hs-to-sx (nth ast 2)))))
|
(list (quote fn) (list) (hs-to-sx (nth ast 2)))))
|
||||||
((= head (quote fetch))
|
((= head (quote fetch))
|
||||||
(list
|
(list (quote hs-fetch) (hs-to-sx (nth ast 1)) (nth ast 2) (nth ast 3) (quote me)))
|
||||||
(if
|
|
||||||
(nth ast 3)
|
|
||||||
(quote hs-fetch-no-throw)
|
|
||||||
(quote hs-fetch))
|
|
||||||
(hs-to-sx (nth ast 1))
|
|
||||||
(nth ast 2)))
|
|
||||||
((= head (quote fetch-gql))
|
((= head (quote fetch-gql))
|
||||||
(list
|
(list
|
||||||
(quote hs-fetch-gql)
|
(quote hs-fetch-gql)
|
||||||
@@ -2127,61 +1878,26 @@
|
|||||||
(make-symbol raw-fn)
|
(make-symbol raw-fn)
|
||||||
(hs-to-sx raw-fn)))
|
(hs-to-sx raw-fn)))
|
||||||
(args (map hs-to-sx (rest (rest ast)))))
|
(args (map hs-to-sx (rest (rest ast)))))
|
||||||
(cond
|
(if
|
||||||
((and (list? raw-fn) (= (first raw-fn) (quote ref)))
|
(and (list? raw-fn) (= (first raw-fn) (quote ref)))
|
||||||
(emit-set
|
|
||||||
(quote the-result)
|
|
||||||
(list
|
(list
|
||||||
(quote hs-win-call)
|
(quote hs-win-call)
|
||||||
(nth raw-fn 1)
|
(nth raw-fn 1)
|
||||||
(cons (quote list) args))))
|
(cons (quote list) args))
|
||||||
((and (list? raw-fn) (= (str (first raw-fn)) "."))
|
(cons fn-expr args))))
|
||||||
(let
|
|
||||||
((receiver-ast (nth raw-fn 1))
|
|
||||||
(prop-name (nth raw-fn 2))
|
|
||||||
(sel (hs-receiver-selector (nth raw-fn 1) "dot")))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list
|
|
||||||
(quote __hs-recv)
|
|
||||||
(hs-to-sx receiver-ast)))
|
|
||||||
(list
|
|
||||||
(quote do)
|
|
||||||
(list
|
|
||||||
(quote set!)
|
|
||||||
(quote _hs-last-query-sel)
|
|
||||||
sel)
|
|
||||||
(list (quote hs-null-raise!) (quote __hs-recv))
|
|
||||||
(emit-set
|
|
||||||
(quote the-result)
|
|
||||||
(cons
|
|
||||||
(list
|
|
||||||
(quote host-get)
|
|
||||||
(quote __hs-recv)
|
|
||||||
prop-name)
|
|
||||||
args))))))
|
|
||||||
(true
|
|
||||||
(emit-set (quote the-result) (cons fn-expr args))))))
|
|
||||||
((= head (quote return))
|
((= head (quote return))
|
||||||
(let
|
(let
|
||||||
((val (nth ast 1)))
|
((val (nth ast 1)))
|
||||||
(if
|
(if
|
||||||
(nil? val)
|
(nil? val)
|
||||||
(list
|
(list (quote raise) (list (quote list) "hs-return" nil))
|
||||||
(quote raise)
|
|
||||||
(list (quote list) "hs-return" nil))
|
|
||||||
(list
|
(list
|
||||||
(quote raise)
|
(quote raise)
|
||||||
(list (quote list) "hs-return" (hs-to-sx val))))))
|
(list (quote list) "hs-return" (hs-to-sx val))))))
|
||||||
((= head (quote throw))
|
((= head (quote throw))
|
||||||
(list (quote raise) (hs-to-sx (nth ast 1))))
|
(list (quote raise) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote settle))
|
((= head (quote settle))
|
||||||
(let
|
(list (quote hs-settle) (quote me)))
|
||||||
((raw-tgt (if (> (len ast) 1) (nth ast 1) nil)))
|
|
||||||
(list
|
|
||||||
(quote hs-settle)
|
|
||||||
(if (nil? raw-tgt) (quote me) (hs-to-sx raw-tgt)))))
|
|
||||||
((= head (quote go))
|
((= head (quote go))
|
||||||
(list (quote hs-navigate!) (hs-to-sx (nth ast 1))))
|
(list (quote hs-navigate!) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote ask))
|
((= head (quote ask))
|
||||||
@@ -2192,10 +1908,7 @@
|
|||||||
(list (list (quote __hs-a) val))
|
(list (list (quote __hs-a) val))
|
||||||
(list
|
(list
|
||||||
(quote begin)
|
(quote begin)
|
||||||
(list
|
(list (quote set!) (quote the-result) (quote __hs-a))
|
||||||
(quote set!)
|
|
||||||
(quote the-result)
|
|
||||||
(quote __hs-a))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-a))
|
(list (quote set!) (quote it) (quote __hs-a))
|
||||||
(quote __hs-a)))))
|
(quote __hs-a)))))
|
||||||
((= head (quote answer))
|
((= head (quote answer))
|
||||||
@@ -2206,10 +1919,7 @@
|
|||||||
(list (list (quote __hs-a) val))
|
(list (list (quote __hs-a) val))
|
||||||
(list
|
(list
|
||||||
(quote begin)
|
(quote begin)
|
||||||
(list
|
(list (quote set!) (quote the-result) (quote __hs-a))
|
||||||
(quote set!)
|
|
||||||
(quote the-result)
|
|
||||||
(quote __hs-a))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-a))
|
(list (quote set!) (quote it) (quote __hs-a))
|
||||||
(quote __hs-a)))))
|
(quote __hs-a)))))
|
||||||
((= head (quote answer-alert))
|
((= head (quote answer-alert))
|
||||||
@@ -2220,10 +1930,7 @@
|
|||||||
(list (list (quote __hs-a) val))
|
(list (list (quote __hs-a) val))
|
||||||
(list
|
(list
|
||||||
(quote begin)
|
(quote begin)
|
||||||
(list
|
(list (quote set!) (quote the-result) (quote __hs-a))
|
||||||
(quote set!)
|
|
||||||
(quote the-result)
|
|
||||||
(quote __hs-a))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-a))
|
(list (quote set!) (quote it) (quote __hs-a))
|
||||||
(quote __hs-a)))))
|
(quote __hs-a)))))
|
||||||
((= head (quote __get-cmd))
|
((= head (quote __get-cmd))
|
||||||
@@ -2234,10 +1941,7 @@
|
|||||||
(list (list (quote __hs-g) val))
|
(list (list (quote __hs-g) val))
|
||||||
(list
|
(list
|
||||||
(quote begin)
|
(quote begin)
|
||||||
(list
|
(list (quote set!) (quote the-result) (quote __hs-g))
|
||||||
(quote set!)
|
|
||||||
(quote the-result)
|
|
||||||
(quote __hs-g))
|
|
||||||
(list (quote set!) (quote it) (quote __hs-g))
|
(list (quote set!) (quote it) (quote __hs-g))
|
||||||
(quote __hs-g)))))
|
(quote __hs-g)))))
|
||||||
((= head (quote append!))
|
((= head (quote append!))
|
||||||
@@ -2260,7 +1964,7 @@
|
|||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list
|
(list
|
||||||
(list (quote beingTold) tgt)
|
(list (quote me) tgt)
|
||||||
(list (quote you) tgt)
|
(list (quote you) tgt)
|
||||||
(list (quote yourself) tgt))
|
(list (quote yourself) tgt))
|
||||||
(hs-to-sx (nth ast 2)))))
|
(hs-to-sx (nth ast 2)))))
|
||||||
@@ -2311,22 +2015,7 @@
|
|||||||
(true (list (quote hs-take!) target kind name scope))))))
|
(true (list (quote hs-take!) target kind name scope))))))
|
||||||
((= head (quote make)) (emit-make ast))
|
((= head (quote make)) (emit-make ast))
|
||||||
((= head (quote install))
|
((= head (quote install))
|
||||||
(let
|
(cons (quote hs-install) (map hs-to-sx (rest ast))))
|
||||||
((bname (nth ast 1)))
|
|
||||||
(cons
|
|
||||||
(make-symbol bname)
|
|
||||||
(cons
|
|
||||||
(quote me)
|
|
||||||
(map
|
|
||||||
(fn
|
|
||||||
(arg)
|
|
||||||
(if
|
|
||||||
(and
|
|
||||||
(list? arg)
|
|
||||||
(= (first arg) (quote type-assert)))
|
|
||||||
(+ (nth arg 2) 0)
|
|
||||||
(hs-to-sx arg)))
|
|
||||||
(rest (rest ast)))))))
|
|
||||||
((= head (quote measure))
|
((= head (quote measure))
|
||||||
(list (quote hs-measure) (hs-to-sx (nth ast 1))))
|
(list (quote hs-measure) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote increment!))
|
((= head (quote increment!))
|
||||||
@@ -2351,31 +2040,18 @@
|
|||||||
((= head (quote exit)) nil)
|
((= head (quote exit)) nil)
|
||||||
((= head (quote live-no-op)) nil)
|
((= head (quote live-no-op)) nil)
|
||||||
((= head (quote when-feat-no-op)) nil)
|
((= head (quote when-feat-no-op)) nil)
|
||||||
((= head (quote bind-feat)) nil)
|
|
||||||
((= head (quote on)) (emit-on ast))
|
((= head (quote on)) (emit-on ast))
|
||||||
((= head (quote when-changes))
|
((= head (quote when-changes))
|
||||||
(let
|
(let
|
||||||
((expr (nth ast 1)) (body (nth ast 2)))
|
((expr (nth ast 1)) (body (nth ast 2)))
|
||||||
(cond
|
(if
|
||||||
((and (list? expr) (= (first expr) (quote dom-ref)))
|
(and (list? expr) (= (first expr) (quote dom-ref)))
|
||||||
(list
|
(list
|
||||||
(quote hs-dom-watch!)
|
(quote hs-dom-watch!)
|
||||||
(hs-to-sx (nth expr 2))
|
(hs-to-sx (nth expr 2))
|
||||||
(nth expr 1)
|
(nth expr 1)
|
||||||
(list
|
(list (quote fn) (list (quote it)) (hs-to-sx body)))
|
||||||
(quote fn)
|
nil)))
|
||||||
(list (quote it))
|
|
||||||
(hs-to-sx body))))
|
|
||||||
((and (list? expr) (= (first expr) (quote local)))
|
|
||||||
(list
|
|
||||||
(quote hs-scoped-watch!)
|
|
||||||
(quote me)
|
|
||||||
(nth expr 1)
|
|
||||||
(list
|
|
||||||
(quote fn)
|
|
||||||
(list (quote it))
|
|
||||||
(hs-to-sx body))))
|
|
||||||
(true nil))))
|
|
||||||
((= head (quote init))
|
((= head (quote init))
|
||||||
(list
|
(list
|
||||||
(quote hs-init)
|
(quote hs-init)
|
||||||
@@ -2430,6 +2106,7 @@
|
|||||||
(quote _hs-def-val))
|
(quote _hs-def-val))
|
||||||
(quote _hs-def-val))))))
|
(quote _hs-def-val))))))
|
||||||
((= head (quote behavior)) (emit-behavior ast))
|
((= head (quote behavior)) (emit-behavior ast))
|
||||||
|
((= head (quote socket)) (emit-socket ast))
|
||||||
((= head (quote sx-eval))
|
((= head (quote sx-eval))
|
||||||
(let
|
(let
|
||||||
((src (nth ast 1)))
|
((src (nth ast 1)))
|
||||||
@@ -2556,47 +2233,13 @@
|
|||||||
(list
|
(list
|
||||||
(quote hs-is)
|
(quote hs-is)
|
||||||
(hs-to-sx (nth ast 1))
|
(hs-to-sx (nth ast 1))
|
||||||
(list
|
(list (quote fn) (list) (hs-to-sx (nth (nth ast 2) 2)))
|
||||||
(quote fn)
|
|
||||||
(list)
|
|
||||||
(hs-to-sx (nth (nth ast 2) 2)))
|
|
||||||
(nth ast 3)))
|
(nth ast 3)))
|
||||||
((= head (quote halt!))
|
((= head (quote halt!))
|
||||||
(list (quote hs-halt!) (quote event) (nth ast 1)))
|
(list (quote hs-halt!) (quote event) (nth ast 1)))
|
||||||
((= head (quote focus!))
|
((= head (quote focus!))
|
||||||
(list (quote dom-focus) (hs-to-sx (nth ast 1))))
|
(list (quote dom-focus) (hs-to-sx (nth ast 1))))
|
||||||
((= head (quote js-block))
|
(true ast))))))))
|
||||||
(let
|
|
||||||
((params (nth ast 1)) (js-src (nth ast 2)))
|
|
||||||
(let
|
|
||||||
((bound-syms (map (fn (p) (make-symbol p)) params)))
|
|
||||||
(list
|
|
||||||
(quote let)
|
|
||||||
(list
|
|
||||||
(list
|
|
||||||
(quote __hs-js)
|
|
||||||
(list
|
|
||||||
(quote hs-js-exec)
|
|
||||||
(cons (quote list) params)
|
|
||||||
js-src
|
|
||||||
(cons (quote list) bound-syms))))
|
|
||||||
(list
|
|
||||||
(quote begin)
|
|
||||||
(list (quote set!) (quote it) (quote __hs-js))
|
|
||||||
(quote __hs-js))))))
|
|
||||||
(true ast)))))))))
|
|
||||||
|
|
||||||
;; ── Convenience: source → SX ─────────────────────────────────
|
;; ── Convenience: source → SX ─────────────────────────────────
|
||||||
(define
|
|
||||||
hs-receiver-selector
|
|
||||||
(fn
|
|
||||||
(ast notation)
|
|
||||||
(cond
|
|
||||||
((and (list? ast) (= (str (first ast)) "ref")) (nth ast 1))
|
|
||||||
((and (list? ast) (= (str (first ast)) "."))
|
|
||||||
(str (hs-receiver-selector (nth ast 1) notation) "." (nth ast 2)))
|
|
||||||
((and (list? ast) (= (str (first ast)) "poss"))
|
|
||||||
(str (hs-receiver-selector (nth ast 1) "poss") "'s " (nth ast 2)))
|
|
||||||
(true "?"))))
|
|
||||||
|
|
||||||
(define hs-to-sx-from-source (fn (src) (hs-to-sx (hs-compile src))))
|
(define hs-to-sx-from-source (fn (src) (hs-to-sx (hs-compile src))))
|
||||||
File diff suppressed because one or more lines are too long
@@ -19,7 +19,6 @@
|
|||||||
(define
|
(define
|
||||||
reserved
|
reserved
|
||||||
(list
|
(list
|
||||||
(quote beingTold)
|
|
||||||
(quote me)
|
(quote me)
|
||||||
(quote it)
|
(quote it)
|
||||||
(quote event)
|
(quote event)
|
||||||
@@ -66,45 +65,17 @@
|
|||||||
(list (quote me))
|
(list (quote me))
|
||||||
(list
|
(list
|
||||||
(quote let)
|
(quote let)
|
||||||
(list
|
(list (list (quote it) nil) (list (quote event) nil))
|
||||||
(list (quote beingTold) (quote me))
|
|
||||||
(list (quote it) nil)
|
|
||||||
(list (quote event) nil))
|
|
||||||
guarded))))))))))
|
guarded))))))))))
|
||||||
|
|
||||||
;; ── Activate a single element ───────────────────────────────────
|
;; ── Activate a single element ───────────────────────────────────
|
||||||
;; Reads the _="..." attribute, compiles, and executes with me=element.
|
;; Reads the _="..." attribute, compiles, and executes with me=element.
|
||||||
;; Marks the element to avoid double-activation.
|
;; Marks the element to avoid double-activation.
|
||||||
|
|
||||||
(define
|
|
||||||
hs-register-scripts!
|
|
||||||
(fn
|
|
||||||
()
|
|
||||||
(for-each
|
|
||||||
(fn
|
|
||||||
(script)
|
|
||||||
(when
|
|
||||||
(not (dom-get-data script "hs-script-loaded"))
|
|
||||||
(let
|
|
||||||
((src (host-get script "innerHTML")))
|
|
||||||
(when
|
|
||||||
(and src (not (= src "")))
|
|
||||||
(guard
|
|
||||||
(_e (true nil))
|
|
||||||
(eval-expr-cek (hs-to-sx-from-source src)))
|
|
||||||
(dom-set-data script "hs-script-loaded" true)))))
|
|
||||||
(hs-query-all "script[type=text/hyperscript]"))))
|
|
||||||
|
|
||||||
;; ── Boot: scan entire document ──────────────────────────────────
|
|
||||||
;; Called once at page load. Finds all elements with _ attribute,
|
|
||||||
;; compiles their hyperscript, and activates them.
|
|
||||||
|
|
||||||
(define
|
(define
|
||||||
hs-activate!
|
hs-activate!
|
||||||
(fn
|
(fn
|
||||||
(el)
|
(el)
|
||||||
(do
|
|
||||||
(hs-register-scripts!)
|
|
||||||
(let
|
(let
|
||||||
((src (dom-get-attr el "_")) (prev (dom-get-data el "hs-script")))
|
((src (dom-get-attr el "_")) (prev (dom-get-data el "hs-script")))
|
||||||
(when
|
(when
|
||||||
@@ -115,26 +86,12 @@
|
|||||||
(dom-set-data el "hs-script" src)
|
(dom-set-data el "hs-script" src)
|
||||||
(dom-set-data el "hs-active" true)
|
(dom-set-data el "hs-active" true)
|
||||||
(dom-set-attr el "data-hyperscript-powered" "true")
|
(dom-set-attr el "data-hyperscript-powered" "true")
|
||||||
(guard
|
(let ((handler (hs-handler src))) (handler el))
|
||||||
(_e (true nil))
|
(dom-dispatch el "hyperscript:after:init" nil))))))
|
||||||
(let
|
|
||||||
((handler (hs-handler src)))
|
|
||||||
(let
|
|
||||||
((el-type (dom-get-attr el "type"))
|
|
||||||
(comp-name (dom-get-attr el "component")))
|
|
||||||
(let
|
|
||||||
((safe-handler (fn (e) (host-call-fn handler (list e)))))
|
|
||||||
(if
|
|
||||||
(= el-type "text/hyperscript-template")
|
|
||||||
(for-each
|
|
||||||
safe-handler
|
|
||||||
(hs-query-all (or comp-name "")))
|
|
||||||
(safe-handler el))))))
|
|
||||||
(dom-dispatch el "hyperscript:after:init" nil)))))))
|
|
||||||
|
|
||||||
;; ── Boot subtree: for dynamic content ───────────────────────────
|
;; ── Boot: scan entire document ──────────────────────────────────
|
||||||
;; Called after HTMX swaps or dynamic DOM insertion.
|
;; Called once at page load. Finds all elements with _ attribute,
|
||||||
;; Only activates elements within the given root.
|
;; compiles their hyperscript, and activates them.
|
||||||
|
|
||||||
(define
|
(define
|
||||||
hs-deactivate!
|
hs-deactivate!
|
||||||
@@ -147,6 +104,10 @@
|
|||||||
(dom-set-data el "hs-active" false)
|
(dom-set-data el "hs-active" false)
|
||||||
(dom-set-data el "hs-script" nil))))
|
(dom-set-data el "hs-script" nil))))
|
||||||
|
|
||||||
|
;; ── Boot subtree: for dynamic content ───────────────────────────
|
||||||
|
;; Called after HTMX swaps or dynamic DOM insertion.
|
||||||
|
;; Only activates elements within the given root.
|
||||||
|
|
||||||
(define
|
(define
|
||||||
hs-boot!
|
hs-boot!
|
||||||
(fn
|
(fn
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -131,7 +131,6 @@
|
|||||||
"append"
|
"append"
|
||||||
"settle"
|
"settle"
|
||||||
"transition"
|
"transition"
|
||||||
"view"
|
|
||||||
"over"
|
"over"
|
||||||
"closest"
|
"closest"
|
||||||
"next"
|
"next"
|
||||||
@@ -209,8 +208,7 @@
|
|||||||
"using"
|
"using"
|
||||||
"giving"
|
"giving"
|
||||||
"ask"
|
"ask"
|
||||||
"answer"
|
"answer"))
|
||||||
"bind"))
|
|
||||||
|
|
||||||
(define hs-keyword? (fn (word) (some (fn (k) (= k word)) hs-keywords)))
|
(define hs-keyword? (fn (word) (some (fn (k) (= k word)) hs-keywords)))
|
||||||
|
|
||||||
@@ -336,17 +334,11 @@
|
|||||||
(= ch "r")
|
(= ch "r")
|
||||||
(do (append! chars "\r") (hs-advance! 1))
|
(do (append! chars "\r") (hs-advance! 1))
|
||||||
(= ch "b")
|
(= ch "b")
|
||||||
(do
|
(do (append! chars (char-from-code 8)) (hs-advance! 1))
|
||||||
(append! chars (char-from-code 8))
|
|
||||||
(hs-advance! 1))
|
|
||||||
(= ch "f")
|
(= ch "f")
|
||||||
(do
|
(do (append! chars (char-from-code 12)) (hs-advance! 1))
|
||||||
(append! chars (char-from-code 12))
|
|
||||||
(hs-advance! 1))
|
|
||||||
(= ch "v")
|
(= ch "v")
|
||||||
(do
|
(do (append! chars (char-from-code 11)) (hs-advance! 1))
|
||||||
(append! chars (char-from-code 11))
|
|
||||||
(hs-advance! 1))
|
|
||||||
(= ch "\\")
|
(= ch "\\")
|
||||||
(do (append! chars "\\") (hs-advance! 1))
|
(do (append! chars "\\") (hs-advance! 1))
|
||||||
(= ch quote-char)
|
(= ch quote-char)
|
||||||
@@ -362,15 +354,11 @@
|
|||||||
(let
|
(let
|
||||||
((d1 (hs-hex-val (hs-cur)))
|
((d1 (hs-hex-val (hs-cur)))
|
||||||
(d2 (hs-hex-val (hs-peek 1))))
|
(d2 (hs-hex-val (hs-peek 1))))
|
||||||
(append!
|
(append! chars (char-from-code (+ (* d1 16) d2)))
|
||||||
chars
|
|
||||||
(char-from-code (+ (* d1 16) d2)))
|
|
||||||
(hs-advance! 2))
|
(hs-advance! 2))
|
||||||
(error "Invalid hexadecimal escape: \\x")))
|
(error "Invalid hexadecimal escape: \\x")))
|
||||||
:else (do
|
:else
|
||||||
(append! chars "\\")
|
(do (append! chars "\\") (append! chars ch) (hs-advance! 1)))))
|
||||||
(append! chars ch)
|
|
||||||
(hs-advance! 1)))))
|
|
||||||
(loop))
|
(loop))
|
||||||
(= (hs-cur) quote-char)
|
(= (hs-cur) quote-char)
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
@@ -457,68 +445,27 @@
|
|||||||
read-class-name
|
read-class-name
|
||||||
(fn
|
(fn
|
||||||
(start)
|
(start)
|
||||||
(define
|
(when
|
||||||
build-name
|
(and
|
||||||
(fn
|
(< pos src-len)
|
||||||
(acc depth)
|
(or
|
||||||
(cond
|
(hs-ident-char? (hs-cur))
|
||||||
((and (< pos src-len) (= (hs-cur) "\\") (< (+ pos 1) src-len))
|
(= (hs-cur) ":")
|
||||||
(do
|
(= (hs-cur) "[")
|
||||||
|
(= (hs-cur) "]")))
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(let
|
(read-class-name start))
|
||||||
((c (hs-cur)))
|
(slice src start pos)))
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name (str acc c) depth))))
|
|
||||||
((and (< pos src-len) (= (hs-cur) "["))
|
|
||||||
(do
|
|
||||||
(let
|
|
||||||
((c (hs-cur)))
|
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name (str acc c) (+ depth 1)))))
|
|
||||||
((and (< pos src-len) (= (hs-cur) "]"))
|
|
||||||
(do
|
|
||||||
(let
|
|
||||||
((c (hs-cur)))
|
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name
|
|
||||||
(str acc c)
|
|
||||||
(if (> depth 0) (- depth 1) 0)))))
|
|
||||||
((and (< pos src-len) (> depth 0) (or (= (hs-cur) "(") (= (hs-cur) ")")))
|
|
||||||
(do
|
|
||||||
(let
|
|
||||||
((c (hs-cur)))
|
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name (str acc c) depth))))
|
|
||||||
((and (< pos src-len) (or (hs-ident-char? (hs-cur)) (= (hs-cur) ":") (= (hs-cur) "&")))
|
|
||||||
(do
|
|
||||||
(let
|
|
||||||
((c (hs-cur)))
|
|
||||||
(hs-advance! 1)
|
|
||||||
(build-name (str acc c) depth))))
|
|
||||||
(true acc))))
|
|
||||||
(build-name "" 0)))
|
|
||||||
(define
|
(define
|
||||||
hs-emit!
|
hs-emit!
|
||||||
(fn
|
(fn
|
||||||
(type value start)
|
(type value start)
|
||||||
(let
|
(append! tokens (hs-make-token type value start))))
|
||||||
((tok (hs-make-token type value start))
|
|
||||||
(end-pos
|
|
||||||
(max pos (+ start (if (nil? value) 0 (len (str value)))))))
|
|
||||||
(do
|
|
||||||
(dict-set! tok "end" end-pos)
|
|
||||||
(dict-set! tok "line" (len (split (slice src 0 start) "\n")))
|
|
||||||
(append! tokens tok)))))
|
|
||||||
(define
|
(define
|
||||||
scan!
|
scan!
|
||||||
(fn
|
(fn
|
||||||
()
|
()
|
||||||
(let
|
|
||||||
((ws-start pos))
|
|
||||||
(skip-ws!)
|
(skip-ws!)
|
||||||
(when
|
|
||||||
(and (> (len tokens) 0) (> pos ws-start))
|
|
||||||
(hs-emit! "whitespace" (slice src ws-start pos) ws-start)))
|
|
||||||
(when
|
(when
|
||||||
(< pos src-len)
|
(< pos src-len)
|
||||||
(let
|
(let
|
||||||
@@ -526,7 +473,11 @@
|
|||||||
(cond
|
(cond
|
||||||
(and (= ch "-") (< (+ pos 1) src-len) (= (hs-peek 1) "-"))
|
(and (= ch "-") (< (+ pos 1) src-len) (= (hs-peek 1) "-"))
|
||||||
(do (hs-advance! 2) (skip-comment!) (scan!))
|
(do (hs-advance! 2) (skip-comment!) (scan!))
|
||||||
(and (= ch "/") (< (+ pos 1) src-len) (= (hs-peek 1) "/"))
|
(and
|
||||||
|
(= ch "/")
|
||||||
|
(< (+ pos 1) src-len)
|
||||||
|
(= (hs-peek 1) "/")
|
||||||
|
(not (and (> pos 0) (= (hs-peek -1) ":"))))
|
||||||
(do (hs-advance! 2) (skip-comment!) (scan!))
|
(do (hs-advance! 2) (skip-comment!) (scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "<")
|
(= ch "<")
|
||||||
@@ -542,21 +493,6 @@
|
|||||||
(do (hs-emit! "selector" (read-selector) start) (scan!))
|
(do (hs-emit! "selector" (read-selector) start) (scan!))
|
||||||
(and (= ch ".") (< (+ pos 1) src-len) (= (hs-peek 1) "."))
|
(and (= ch ".") (< (+ pos 1) src-len) (= (hs-peek 1) "."))
|
||||||
(do (hs-emit! "op" ".." start) (hs-advance! 2) (scan!))
|
(do (hs-emit! "op" ".." start) (hs-advance! 2) (scan!))
|
||||||
(and
|
|
||||||
(= ch ".")
|
|
||||||
(< (+ pos 1) src-len)
|
|
||||||
(or
|
|
||||||
(hs-letter? (hs-peek 1))
|
|
||||||
(= (hs-peek 1) "-")
|
|
||||||
(= (hs-peek 1) "_"))
|
|
||||||
(> (len tokens) 0)
|
|
||||||
(let
|
|
||||||
((lt (dict-get (nth tokens (- (len tokens) 1)) :type)))
|
|
||||||
(or
|
|
||||||
(= lt "paren-close")
|
|
||||||
(= lt "brace-close")
|
|
||||||
(= lt "bracket-close"))))
|
|
||||||
(do (hs-emit! "dot" "." start) (hs-advance! 1) (scan!))
|
|
||||||
(and
|
(and
|
||||||
(= ch ".")
|
(= ch ".")
|
||||||
(< (+ pos 1) src-len)
|
(< (+ pos 1) src-len)
|
||||||
@@ -568,18 +504,6 @@
|
|||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "class" (read-class-name pos) start)
|
(hs-emit! "class" (read-class-name pos) start)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
|
||||||
(= ch "#")
|
|
||||||
(< (+ pos 1) src-len)
|
|
||||||
(hs-ident-start? (hs-peek 1))
|
|
||||||
(> (len tokens) 0)
|
|
||||||
(let
|
|
||||||
((lt (dict-get (nth tokens (- (len tokens) 1)) :type)))
|
|
||||||
(or
|
|
||||||
(= lt "paren-close")
|
|
||||||
(= lt "brace-close")
|
|
||||||
(= lt "bracket-close"))))
|
|
||||||
(do (hs-emit! "op" "#" start) (hs-advance! 1) (scan!))
|
|
||||||
(and
|
(and
|
||||||
(= ch "#")
|
(= ch "#")
|
||||||
(< (+ pos 1) src-len)
|
(< (+ pos 1) src-len)
|
||||||
@@ -649,7 +573,21 @@
|
|||||||
(let
|
(let
|
||||||
((word (read-ident start)))
|
((word (read-ident start)))
|
||||||
(let
|
(let
|
||||||
((full-word (if (and (< pos src-len) (= (hs-cur) "'") (< (+ pos 1) src-len) (hs-letter? (hs-peek 1)) (not (and (= (hs-peek 1) "s") (or (>= (+ pos 2) src-len) (not (hs-ident-char? (hs-peek 2))))))) (do (hs-advance! 1) (str word "'" (read-ident pos))) word)))
|
((full-word
|
||||||
|
(if
|
||||||
|
(and
|
||||||
|
(< pos src-len)
|
||||||
|
(= (hs-cur) "'")
|
||||||
|
(< (+ pos 1) src-len)
|
||||||
|
(hs-letter? (hs-peek 1))
|
||||||
|
(not
|
||||||
|
(and
|
||||||
|
(= (hs-peek 1) "s")
|
||||||
|
(or
|
||||||
|
(>= (+ pos 2) src-len)
|
||||||
|
(not (hs-ident-char? (hs-peek 2)))))))
|
||||||
|
(do (hs-advance! 1) (str word "'" (read-ident pos)))
|
||||||
|
word)))
|
||||||
(hs-emit!
|
(hs-emit!
|
||||||
(if (hs-keyword? full-word) "keyword" "ident")
|
(if (hs-keyword? full-word) "keyword" "ident")
|
||||||
full-word
|
full-word
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -46045,7 +46045,7 @@ d2=133,bi=102,bh="Re__Hash_set",cA="Stdlib__Type",cB=114,fF="Stdlib__Buffer",dX=
|
|||||||
}
|
}
|
||||||
return trampoline(eval_expr(Sx_types[75].call(null, mac), local));
|
return trampoline(eval_expr(Sx_types[75].call(null, mac), local));
|
||||||
}
|
}
|
||||||
var step_limit = [0, 0], step_count = [0, 0], _wc_check = 0;
|
var step_limit = [0, 0], step_count = [0, 0];
|
||||||
function cek_step_loop(state$0){
|
function cek_step_loop(state$0){
|
||||||
var state = state$0;
|
var state = state$0;
|
||||||
for(;;){
|
for(;;){
|
||||||
@@ -46055,11 +46055,6 @@ d2=133,bi=102,bh="Re__Hash_set",cA="Stdlib__Type",cB=114,fF="Stdlib__Buffer",dX=
|
|||||||
throw caml_maybe_attach_backtrace
|
throw caml_maybe_attach_backtrace
|
||||||
([0, Sx_types[9], "TIMEOUT: step limit exceeded"], 1);
|
([0, Sx_types[9], "TIMEOUT: step limit exceeded"], 1);
|
||||||
}
|
}
|
||||||
if(++_wc_check >= 10000){ _wc_check = 0;
|
|
||||||
if(globalThis.__hs_deadline && Date.now() > globalThis.__hs_deadline)
|
|
||||||
throw caml_maybe_attach_backtrace
|
|
||||||
([0, Sx_types[9], "TIMEOUT: wall clock exceeded"], 1);
|
|
||||||
}
|
|
||||||
var
|
var
|
||||||
or = cek_terminal_p(state),
|
or = cek_terminal_p(state),
|
||||||
or$0 = Sx_types[56].call(null, or) ? or : cek_suspended_p(state);
|
or$0 = Sx_types[56].call(null, or) ? or : cek_suspended_p(state);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,263 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
/**
|
|
||||||
* Evaluate SX (or inspect HS compiler/parser output) in the full WASM kernel.
|
|
||||||
*
|
|
||||||
* Environment variables (preferred — avoids shell escaping):
|
|
||||||
* HS_EVAL_EXPR SX expression to evaluate (required unless --expr arg given)
|
|
||||||
* HS_EVAL_SETUP SX setup expression run before main eval
|
|
||||||
* HS_EVAL_FILES Comma-separated list of .sx files to load first
|
|
||||||
* HS_EVAL_MODE 'eval' (default) | 'compile' | 'parse'
|
|
||||||
* compile: wraps expr as hs-compile arg, returns SX AST string
|
|
||||||
* parse: wraps expr as hs-parse arg, returns parse tree string
|
|
||||||
*
|
|
||||||
* CLI fallback: first positional arg used as expression if HS_EVAL_EXPR not set.
|
|
||||||
*
|
|
||||||
* Output: JSON to stdout { ok: true, result: "..." }
|
|
||||||
* or { ok: false, error: "..." }
|
|
||||||
* Progress / load errors go to stderr.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const PROJECT = path.resolve(__dirname, '..');
|
|
||||||
const WASM_DIR = path.join(PROJECT, 'shared/static/wasm');
|
|
||||||
const SX_DIR = path.join(WASM_DIR, 'sx');
|
|
||||||
|
|
||||||
// ── Load WASM kernel ────────────────────────────────────────────
|
|
||||||
eval(fs.readFileSync(path.join(WASM_DIR, 'sx_browser.bc.js'), 'utf8'));
|
|
||||||
const K = globalThis.SxKernel;
|
|
||||||
|
|
||||||
// ── Minimal DOM mock ────────────────────────────────────────────
|
|
||||||
class CL {
|
|
||||||
constructor() { this._s = new Set(); }
|
|
||||||
add(c) { if (c) this._s.add(c); }
|
|
||||||
remove(c) { this._s.delete(c); }
|
|
||||||
contains(c) { return this._s.has(c); }
|
|
||||||
toggle(c) { this._s.has(c) ? this.remove(c) : this.add(c); return this._s.has(c); }
|
|
||||||
_sync(v) { this._s = new Set((v||'').split(' ').filter(Boolean)); }
|
|
||||||
}
|
|
||||||
class El {
|
|
||||||
constructor(t) {
|
|
||||||
this.tagName = t.toUpperCase(); this.nodeName = this.tagName; this.nodeType = 1;
|
|
||||||
this.id = ''; this.className = ''; this.textContent = ''; this.innerHTML = '';
|
|
||||||
this.value = ''; this.checked = false; this.disabled = false; this.type = '';
|
|
||||||
this.style = { setProperty(p,v){this[p]=v;}, getPropertyValue(p){return this[p]||'';} };
|
|
||||||
this.attributes = {}; this.children = []; this.childNodes = [];
|
|
||||||
this.childNodes.item = i => this.childNodes[i] || null;
|
|
||||||
this.parentNode = null; this.parentElement = null; this._listeners = {};
|
|
||||||
this.classList = new CL();
|
|
||||||
this.dataset = {};
|
|
||||||
this.open = false; this.multiple = false; this.selected = false;
|
|
||||||
}
|
|
||||||
setAttribute(n,v) {
|
|
||||||
this.attributes[n] = String(v);
|
|
||||||
if (n==='id') this.id = v;
|
|
||||||
if (n==='class') { this.className = v; this.classList._sync(v); }
|
|
||||||
if (n==='value') this.value = v;
|
|
||||||
}
|
|
||||||
getAttribute(n) { return this.attributes[n] !== undefined ? this.attributes[n] : null; }
|
|
||||||
removeAttribute(n){ delete this.attributes[n]; }
|
|
||||||
hasAttribute(n) { return n in this.attributes; }
|
|
||||||
appendChild(c) { if(c){ c.parentNode=this; c.parentElement=this; this.children.push(c); this.childNodes.push(c); } return c; }
|
|
||||||
removeChild(c) { this.children=this.children.filter(x=>x!==c); this.childNodes=this.childNodes.filter(x=>x!==c); if(c){c.parentNode=null;c.parentElement=null;} return c; }
|
|
||||||
remove() { if(this.parentNode) this.parentNode.removeChild(this); }
|
|
||||||
prepend(c) { if(c){ c.parentNode=this; this.children.unshift(c); this.childNodes.unshift(c); } }
|
|
||||||
insertBefore(c,r) { if(!r) return this.appendChild(c); const i=this.childNodes.indexOf(r); if(i<0) return this.appendChild(c); this.childNodes.splice(i,0,c); this.children.splice(i,0,c); c.parentNode=this; return c; }
|
|
||||||
replaceChild(n,o) { const i=this.childNodes.indexOf(o); if(i>=0){ this.childNodes[i]=n; this.children[i]=n; n.parentNode=this; o.parentNode=null; } return o; }
|
|
||||||
cloneNode(deep) { const c=new El(this.tagName); if(deep) for(const ch of this.childNodes) c.appendChild(ch.cloneNode&&ch.cloneNode(true)||{...ch}); return c; }
|
|
||||||
addEventListener(t,h) { if(!this._listeners[t]) this._listeners[t]=[]; this._listeners[t].push(h); }
|
|
||||||
removeEventListener(t,h) { if(this._listeners[t]) this._listeners[t]=this._listeners[t].filter(x=>x!==h); }
|
|
||||||
dispatchEvent(ev) { (this._listeners[ev&&ev.type]||[]).forEach(h=>{ try{h(ev);}catch(e){} }); return true; }
|
|
||||||
querySelector(sel) {
|
|
||||||
if (!sel) return null;
|
|
||||||
if (sel.startsWith('#')) { const id=sel.slice(1); if(this.id===id) return this; for(const c of this.childNodes){const r=c.querySelector&&c.querySelector(sel); if(r) return r;} return null; }
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
querySelectorAll() { return []; }
|
|
||||||
closest(sel) { return sel && this.matches(sel) ? this : (this.parentNode && this.parentNode.closest ? this.parentNode.closest(sel) : null); }
|
|
||||||
matches(sel) {
|
|
||||||
if (!sel) return false;
|
|
||||||
if (sel.startsWith('#')) return this.id === sel.slice(1);
|
|
||||||
if (sel.startsWith('.')) return this.classList.contains(sel.slice(1));
|
|
||||||
return this.tagName.toLowerCase() === sel.toLowerCase();
|
|
||||||
}
|
|
||||||
focus() {}
|
|
||||||
blur() {}
|
|
||||||
click() { this.dispatchEvent(new Ev('click',{bubbles:true})); }
|
|
||||||
getBoundingClientRect() { return {width:0,height:0,top:0,left:0,right:0,bottom:0}; }
|
|
||||||
}
|
|
||||||
class Ev {
|
|
||||||
constructor(t,o) { this.type=t; const opts=o||{}; this.bubbles=opts.bubbles!==false; this.detail=opts.detail||null; this.target=null; this.currentTarget=null; }
|
|
||||||
preventDefault() {}
|
|
||||||
stopPropagation() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
const _body = new El('body');
|
|
||||||
const _head = new El('head');
|
|
||||||
const _docListeners = {};
|
|
||||||
const _domRegistry = new Map(); // id -> El
|
|
||||||
|
|
||||||
function _findById(id) {
|
|
||||||
function find(el) {
|
|
||||||
if (!(el instanceof El)) return null;
|
|
||||||
if (el.id === id) return el;
|
|
||||||
for (const c of (el.childNodes||[])) { const r = find(c); if (r) return r; }
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return find(_body);
|
|
||||||
}
|
|
||||||
|
|
||||||
globalThis.document = {
|
|
||||||
body: _body, head: _head, title: '',
|
|
||||||
createElement: t => new El(t),
|
|
||||||
createElementNS: (ns,t) => new El(t),
|
|
||||||
createTextNode: s => ({ nodeType:3, textContent:String(s||''), nodeName:'#text', parentNode:null }),
|
|
||||||
createDocumentFragment: () => { const f=new El('fragment'); f.nodeType=11; return f; },
|
|
||||||
createComment: s => ({ nodeType:8, textContent:s, nodeName:'#comment' }),
|
|
||||||
getElementById: id => _findById(id),
|
|
||||||
querySelector: sel => sel && sel.startsWith('#') ? _findById(sel.slice(1)) : null,
|
|
||||||
querySelectorAll: () => [],
|
|
||||||
addEventListener: (t,h) => { if(!_docListeners[t]) _docListeners[t]=[]; _docListeners[t].push(h); },
|
|
||||||
removeEventListener: (t,h) => { if(_docListeners[t]) _docListeners[t]=_docListeners[t].filter(x=>x!==h); },
|
|
||||||
dispatchEvent: ev => { (_docListeners[ev&&ev.type]||[]).forEach(h=>{ try{h(ev);}catch(e){} }); },
|
|
||||||
activeElement: null,
|
|
||||||
};
|
|
||||||
globalThis.CustomEvent = Ev;
|
|
||||||
globalThis.Event = Ev;
|
|
||||||
globalThis.window = globalThis;
|
|
||||||
try { globalThis.navigator = { userAgent: 'node' }; } catch(e) { Object.defineProperty(globalThis, 'navigator', { value: { userAgent: 'node' }, writable: true, configurable: true }); }
|
|
||||||
globalThis.location = { href:'http://localhost/', pathname:'/', search:'', hash:'' };
|
|
||||||
globalThis.history = { pushState(){}, replaceState(){} };
|
|
||||||
globalThis.getSelection = () => ({ toString: () => '' });
|
|
||||||
globalThis.console = { log:()=>{}, error:()=>{}, warn:()=>{}, info:()=>{}, debug:()=>{} };
|
|
||||||
globalThis.ResizeObserver = class { observe(){} unobserve(){} disconnect(){} };
|
|
||||||
globalThis.IntersectionObserver = class { constructor(cb){} observe(){} unobserve(){} disconnect(){} takeRecords(){return[];} };
|
|
||||||
|
|
||||||
// ── FFI registrations ───────────────────────────────────────────
|
|
||||||
K.registerNative('hs-ref-eq', a => a[0]===a[1]);
|
|
||||||
K.registerNative('host-global', a => { const n=a[0]; return (n in globalThis)?globalThis[n]:null; });
|
|
||||||
K.registerNative('host-get', a => {
|
|
||||||
if (a[0]==null) return null;
|
|
||||||
if (a[0] && a[0]._type==='list' && (a[1]==='length'||a[1]==='size')) return a[0].items.length;
|
|
||||||
if (a[0] instanceof El && a[1]==='innerText') return String(a[0].textContent||'');
|
|
||||||
const v = a[0][a[1]]; return v===undefined ? null : v;
|
|
||||||
});
|
|
||||||
K.registerNative('host-set!', a => { if(a[0]!=null){ a[0][a[1]]=a[2]; if(a[0] instanceof El && a[1]==='id' && a[2]) a[0].id=a[2]; } return a[2]; });
|
|
||||||
K.registerNative('host-call', a => {
|
|
||||||
const [o,m,...r]=a;
|
|
||||||
if(o==null){ const f=globalThis[m]; return typeof f==='function'?f.apply(null,r):null; }
|
|
||||||
if(o && typeof o[m]==='function'){ try{ const v=o[m].apply(o,r); return v===undefined?null:v; }catch(e){ return null; } }
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
K.registerNative('host-call-fn', a => {
|
|
||||||
const [fn,argList]=a;
|
|
||||||
if(!fn) return null;
|
|
||||||
const args=(argList&&argList._type==='list'&&argList.items)?Array.from(argList.items):(Array.isArray(argList)?argList:[]);
|
|
||||||
if(fn&&fn.__sx_handle!==undefined) return K.callFn(fn,args);
|
|
||||||
try{ return fn.apply(null,args); }catch(e){ return null; }
|
|
||||||
});
|
|
||||||
K.registerNative('host-new', a => { const C=typeof a[0]==='string'?globalThis[a[0]]:a[0]; return typeof C==='function'?new C(...a.slice(1)):null; });
|
|
||||||
K.registerNative('host-callback',a => {
|
|
||||||
const fn=a[0];
|
|
||||||
if(fn&&fn.__sx_handle!==undefined) return function(){ const r=K.callFn(fn,Array.from(arguments)); if(globalThis._driveAsync) globalThis._driveAsync(r); return r; };
|
|
||||||
return typeof fn==='function'?fn:function(){};
|
|
||||||
});
|
|
||||||
K.registerNative('host-typeof', a => { const o=a[0]; if(o==null) return 'nil'; if(o instanceof El) return 'element'; if(o instanceof Ev) return 'event'; return typeof o; });
|
|
||||||
K.registerNative('host-iter?', ([obj]) => obj!=null && typeof obj[Symbol.iterator]==='function');
|
|
||||||
K.registerNative('host-to-list', ([obj]) => { try{ return [...obj]; }catch(e){ return []; } });
|
|
||||||
K.registerNative('host-await', () => {});
|
|
||||||
K.registerNative('host-new-function', a => { const p=(a[0]&&a[0]._type==='list')?Array.from(a[0].items):[]; try{ return new Function(...p,a[1]); }catch(e){ return null; } });
|
|
||||||
K.registerNative('host-promise-state', a => { const p=a[0]; if(!p||typeof p.then!=='function') return null; const s=globalThis._promiseStates&&globalThis._promiseStates.get(p); return s?{ok:s.ok,value:s.value}:null; });
|
|
||||||
K.registerNative('load-library!', () => false);
|
|
||||||
|
|
||||||
// Async IO driver
|
|
||||||
let _evalDeadline = 0;
|
|
||||||
globalThis._driveAsync = function driveAsync(r, depth) {
|
|
||||||
depth = depth||0;
|
|
||||||
if (_evalDeadline && Date.now() > _evalDeadline) throw new Error('TIMEOUT: wall clock exceeded');
|
|
||||||
if (!r || !r.suspended || depth > 200) return;
|
|
||||||
const req = r.request;
|
|
||||||
const items = req && (req.items || req);
|
|
||||||
const op = items && items[0];
|
|
||||||
const opName = typeof op==='string' ? op : (op&&op.name)||String(op);
|
|
||||||
function doResume(v) { try{ const x=r.resume(v); driveAsync(x,depth+1); }catch(e){} }
|
|
||||||
if (opName==='io-sleep'||opName==='wait') doResume(null);
|
|
||||||
else if (opName==='io-wait-event') {
|
|
||||||
const target=items&&items[1];
|
|
||||||
const evName=typeof items[2]==='string'?items[2]:'';
|
|
||||||
const timeout=items&&items.length>3?items[3]:undefined;
|
|
||||||
if (typeof timeout==='number') { doResume(null); }
|
|
||||||
else if (target && target instanceof El && evName) {
|
|
||||||
const handler=function(ev){ target.removeEventListener(evName,handler); doResume(ev); };
|
|
||||||
target.addEventListener(evName,handler);
|
|
||||||
} else { doResume(null); }
|
|
||||||
}
|
|
||||||
else if (opName==='io-transition') doResume(null);
|
|
||||||
else doResume(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
// ── SX aliases ──────────────────────────────────────────────────
|
|
||||||
K.eval('(define SX_VERSION "hs-eval-1.0")');
|
|
||||||
K.eval('(define SX_ENGINE "ocaml-vm-sandbox")');
|
|
||||||
K.eval('(define parse sx-parse)');
|
|
||||||
K.eval('(define serialize sx-serialize)');
|
|
||||||
|
|
||||||
// ── Load HS modules ─────────────────────────────────────────────
|
|
||||||
const WEB = ['render','core-signals','signals','deps','router','page-helpers','freeze','dom','browser',
|
|
||||||
'adapter-html','adapter-sx','adapter-dom','boot-helpers','hypersx','engine','orchestration','boot'];
|
|
||||||
const HS = ['hs-tokenizer','hs-parser','hs-compiler','hs-runtime','hs-integration'];
|
|
||||||
K.beginModuleLoad();
|
|
||||||
for (const mod of [...WEB, ...HS]) {
|
|
||||||
const sp = path.join(SX_DIR, mod+'.sx');
|
|
||||||
const lp = path.join(PROJECT, 'lib/hyperscript', mod.replace(/^hs-/,'')+'.sx');
|
|
||||||
let s;
|
|
||||||
try {
|
|
||||||
const lpExists = mod.startsWith('hs-') && fs.existsSync(lp);
|
|
||||||
s = lpExists ? fs.readFileSync(lp,'utf8')
|
|
||||||
: fs.existsSync(sp) ? fs.readFileSync(sp,'utf8')
|
|
||||||
: fs.readFileSync(lp,'utf8');
|
|
||||||
} catch(e) { continue; }
|
|
||||||
try { K.load(s); } catch(e) { process.stderr.write(`LOAD ERROR: ${mod}: ${e.message}\n`); }
|
|
||||||
}
|
|
||||||
K.endModuleLoad();
|
|
||||||
|
|
||||||
// ── Extra files ─────────────────────────────────────────────────
|
|
||||||
const extraFiles = (process.env.HS_EVAL_FILES || '').split(',').filter(Boolean);
|
|
||||||
for (const f of extraFiles) {
|
|
||||||
try { K.load(fs.readFileSync(f.trim(),'utf8')); }
|
|
||||||
catch(e) { process.stderr.write(`FILE ERROR: ${f}: ${e.message}\n`); }
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Setup expression ────────────────────────────────────────────
|
|
||||||
const setup = process.env.HS_EVAL_SETUP || '';
|
|
||||||
if (setup) {
|
|
||||||
try { K.eval(setup); }
|
|
||||||
catch(e) {
|
|
||||||
process.stdout.write(JSON.stringify({ok:false,error:`Setup error: ${e.message||String(e)}`})+'\n');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Main evaluation ─────────────────────────────────────────────
|
|
||||||
const mode = process.env.HS_EVAL_MODE || 'eval';
|
|
||||||
const rawExpr = process.env.HS_EVAL_EXPR || process.argv[2] || '';
|
|
||||||
if (!rawExpr) {
|
|
||||||
process.stdout.write(JSON.stringify({ok:false,error:'No expression provided. Set HS_EVAL_EXPR or pass as first argument.'})+'\n');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const expr = mode==='compile' ? `(str (hs-compile ${JSON.stringify(rawExpr)}))`
|
|
||||||
: mode==='parse' ? `(str (hs-parse ${JSON.stringify(rawExpr)}))`
|
|
||||||
: rawExpr;
|
|
||||||
|
|
||||||
_evalDeadline = Date.now() + parseInt(process.env.HS_EVAL_TIMEOUT_MS||'30000');
|
|
||||||
try {
|
|
||||||
const result = K.eval(expr);
|
|
||||||
let resultStr;
|
|
||||||
try { resultStr = JSON.stringify(result); } catch(e) { resultStr = String(result); }
|
|
||||||
process.stdout.write(JSON.stringify({ok:true,result:resultStr})+'\n');
|
|
||||||
} catch(e) {
|
|
||||||
process.stdout.write(JSON.stringify({ok:false,error:e.message||String(e)})+'\n');
|
|
||||||
}
|
|
||||||
@@ -14,6 +14,32 @@ const SX_DIR = path.join(WASM_DIR, 'sx');
|
|||||||
eval(fs.readFileSync(path.join(WASM_DIR, 'sx_browser.bc.js'), 'utf8'));
|
eval(fs.readFileSync(path.join(WASM_DIR, 'sx_browser.bc.js'), 'utf8'));
|
||||||
const K = globalThis.SxKernel;
|
const K = globalThis.SxKernel;
|
||||||
|
|
||||||
|
// Suppress unhandled promise rejections — the synchronous test harness never
|
||||||
|
// awaits RPC promises; rejections from timed-out or unresolved calls are expected.
|
||||||
|
process.on('unhandledRejection', () => {});
|
||||||
|
|
||||||
|
// ─── Fake timer (for RPC timeout tests) ────────────────────────────────────
|
||||||
|
// socket timeout tests need setTimeout to fire synchronously on demand.
|
||||||
|
// Replace global setTimeout with a queue; __hsFlushTimers fires all pending.
|
||||||
|
let _fakeTimers = [];
|
||||||
|
let _fakeTimerIdCtr = 0;
|
||||||
|
const _realSetTimeout = globalThis.setTimeout;
|
||||||
|
globalThis.setTimeout = function(cb, _delay) {
|
||||||
|
const id = ++_fakeTimerIdCtr;
|
||||||
|
_fakeTimers.push({ id, cb });
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
globalThis.clearTimeout = function(id) {
|
||||||
|
const idx = _fakeTimers.findIndex(t => t.id === id);
|
||||||
|
if (idx >= 0) _fakeTimers.splice(idx, 1);
|
||||||
|
};
|
||||||
|
// __hsFlushTimers — drain all pending timers synchronously.
|
||||||
|
// Exposed as a plain object so host-call o "call" works.
|
||||||
|
globalThis.__hsFlushTimers = { call: function() {
|
||||||
|
const batch = _fakeTimers.splice(0);
|
||||||
|
for (const { cb } of batch) { try { cb(); } catch (_) {} }
|
||||||
|
}};
|
||||||
|
|
||||||
// Step limit API — exposed from OCaml kernel
|
// Step limit API — exposed from OCaml kernel
|
||||||
const STEP_LIMIT = parseInt(process.env.HS_STEP_LIMIT || '200000');
|
const STEP_LIMIT = parseInt(process.env.HS_STEP_LIMIT || '200000');
|
||||||
|
|
||||||
@@ -81,7 +107,7 @@ class El {
|
|||||||
hasAttribute(n) { return n in this.attributes; }
|
hasAttribute(n) { return n in this.attributes; }
|
||||||
addEventListener(e,f) { if(!this._listeners[e])this._listeners[e]=[]; this._listeners[e].push(f); }
|
addEventListener(e,f) { if(!this._listeners[e])this._listeners[e]=[]; this._listeners[e].push(f); }
|
||||||
removeEventListener(e,f) { if(this._listeners[e])this._listeners[e]=this._listeners[e].filter(x=>x!==f); }
|
removeEventListener(e,f) { if(this._listeners[e])this._listeners[e]=this._listeners[e].filter(x=>x!==f); }
|
||||||
dispatchEvent(ev) { ev.target=ev.target||this; ev.currentTarget=this; const fns=[...(this._listeners[ev.type]||[])]; for(const f of fns){if(ev._si)break;try{f.call(this,ev);}catch(e){}} if(ev.bubbles&&!ev._sp){if(this.parentElement){this.parentElement.dispatchEvent(ev);}else if(globalThis._windowListeners){globalThis.dispatchEvent(ev);}} return !ev.defaultPrevented; }
|
dispatchEvent(ev) { ev.target=ev.target||this; ev.currentTarget=this; const fns=[...(this._listeners[ev.type]||[])]; for(const f of fns){if(ev._si)break;try{f.call(this,ev);}catch(e){}} if(ev.bubbles&&!ev._sp&&this.parentElement){this.parentElement.dispatchEvent(ev);} return !ev.defaultPrevented; }
|
||||||
appendChild(c) { if(c.parentElement)c.parentElement.removeChild(c); c.parentElement=this; c.parentNode=this; this.children.push(c); this.childNodes.push(c); if(this.tagName==='SELECT'&&c.tagName==='OPTION'){this.options.push(c);if(c.selected&&this.selectedIndex<0)this.selectedIndex=this.options.length-1;} this._syncText(); return c; }
|
appendChild(c) { if(c.parentElement)c.parentElement.removeChild(c); c.parentElement=this; c.parentNode=this; this.children.push(c); this.childNodes.push(c); if(this.tagName==='SELECT'&&c.tagName==='OPTION'){this.options.push(c);if(c.selected&&this.selectedIndex<0)this.selectedIndex=this.options.length-1;} this._syncText(); return c; }
|
||||||
removeChild(c) { this.children=this.children.filter(x=>x!==c); this.childNodes=this.childNodes.filter(x=>x!==c); c.parentElement=null; c.parentNode=null; this._syncText(); return c; }
|
removeChild(c) { this.children=this.children.filter(x=>x!==c); this.childNodes=this.childNodes.filter(x=>x!==c); c.parentElement=null; c.parentNode=null; this._syncText(); return c; }
|
||||||
insertBefore(n,r) { if(n.parentElement)n.parentElement.removeChild(n); const i=this.children.indexOf(r); if(i>=0){this.children.splice(i,0,n);this.childNodes.splice(i,0,n);}else{this.children.push(n);this.childNodes.push(n);} n.parentElement=this;n.parentNode=this; this._syncText(); return n; }
|
insertBefore(n,r) { if(n.parentElement)n.parentElement.removeChild(n); const i=this.children.indexOf(r); if(i>=0){this.children.splice(i,0,n);this.childNodes.splice(i,0,n);}else{this.children.push(n);this.childNodes.push(n);} n.parentElement=this;n.parentNode=this; this._syncText(); return n; }
|
||||||
@@ -239,9 +265,9 @@ function parseHTMLFragments(html) {
|
|||||||
// this keeps behaviour lenient without running past the next tag.
|
// this keeps behaviour lenient without running past the next tag.
|
||||||
}
|
}
|
||||||
const el = new El(tag);
|
const el = new El(tag);
|
||||||
const attrRe = /([\w-]+)(?:=(?:"([^"]*)"|'([^']*)'|([^\s>"'\/>][^\s>]*)))?/g; let am;
|
const attrRe = /([\w-]+)(?:="([^"]*)")?/g; let am;
|
||||||
while ((am = attrRe.exec(attrs))) {
|
while ((am = attrRe.exec(attrs))) {
|
||||||
const nm = am[1]; const val = am[2] !== undefined ? am[2] : am[3] !== undefined ? am[3] : am[4];
|
const nm = am[1]; const val = am[2];
|
||||||
if (val !== undefined) el.setAttribute(nm, val);
|
if (val !== undefined) el.setAttribute(nm, val);
|
||||||
else el.setAttribute(nm, '');
|
else el.setAttribute(nm, '');
|
||||||
}
|
}
|
||||||
@@ -297,15 +323,6 @@ function mt(e,s) {
|
|||||||
const m = base.match(/^\[([^\]=]+)(?:="([^"]*)")?\]$/);
|
const m = base.match(/^\[([^\]=]+)(?:="([^"]*)")?\]$/);
|
||||||
if(m) return m[2] !== undefined ? e.getAttribute(m[1]) === m[2] : e.hasAttribute(m[1]);
|
if(m) return m[2] !== undefined ? e.getAttribute(m[1]) === m[2] : e.hasAttribute(m[1]);
|
||||||
}
|
}
|
||||||
// Compound tag[attr=val] e.g. input[type=checkbox] or input[type="checkbox"]
|
|
||||||
if(base.includes('[')) {
|
|
||||||
const cm = base.match(/^([\w-]+)(\[.+\])$/);
|
|
||||||
if(cm) {
|
|
||||||
if(e.tagName.toLowerCase() !== cm[1]) return false;
|
|
||||||
const attrParts = cm[2].match(/^\[([^\]=]+)(?:=["']?([^"'\]]+)["']?)?\]$/);
|
|
||||||
if(attrParts) return attrParts[2] !== undefined ? e.getAttribute(attrParts[1]) === attrParts[2] : e.hasAttribute(attrParts[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(base.includes('.')) { const [tag, cls] = base.split('.'); return e.tagName.toLowerCase() === tag && e.classList.contains(cls); }
|
if(base.includes('.')) { const [tag, cls] = base.split('.'); return e.tagName.toLowerCase() === tag && e.classList.contains(cls); }
|
||||||
if(base.includes('#')) { const [tag, id] = base.split('#'); return e.tagName.toLowerCase() === tag && e.id === id; }
|
if(base.includes('#')) { const [tag, id] = base.split('#'); return e.tagName.toLowerCase() === tag && e.id === id; }
|
||||||
return e.tagName.toLowerCase() === base.toLowerCase();
|
return e.tagName.toLowerCase() === base.toLowerCase();
|
||||||
@@ -336,11 +353,6 @@ const document = {
|
|||||||
createEvent(t){return new Ev(t);}, addEventListener(){}, removeEventListener(){},
|
createEvent(t){return new Ev(t);}, addEventListener(){}, removeEventListener(){},
|
||||||
};
|
};
|
||||||
globalThis.document=document; globalThis.window=globalThis; globalThis.HTMLElement=El; globalThis.Element=El;
|
globalThis.document=document; globalThis.window=globalThis; globalThis.HTMLElement=El; globalThis.Element=El;
|
||||||
// window event-target shim (for hyperscript:beforeFetch and similar bubbled events)
|
|
||||||
globalThis._windowListeners={};
|
|
||||||
globalThis.addEventListener=function(e,f){if(!globalThis._windowListeners[e])globalThis._windowListeners[e]=[];globalThis._windowListeners[e].push(f);};
|
|
||||||
globalThis.removeEventListener=function(e,f){if(globalThis._windowListeners[e])globalThis._windowListeners[e]=globalThis._windowListeners[e].filter(x=>x!==f);};
|
|
||||||
globalThis.dispatchEvent=function(ev){const fns=[...(globalThis._windowListeners[ev.type]||[])];for(const f of fns){if(ev&&ev._si)break;try{f.call(globalThis,ev);}catch(e){}}return ev?!ev.defaultPrevented:true;};
|
|
||||||
// cluster-33: cookie store + document.cookie + cookies Proxy.
|
// cluster-33: cookie store + document.cookie + cookies Proxy.
|
||||||
globalThis.__hsCookieStore = new Map();
|
globalThis.__hsCookieStore = new Map();
|
||||||
Object.defineProperty(document, 'cookie', {
|
Object.defineProperty(document, 'cookie', {
|
||||||
@@ -360,8 +372,7 @@ globalThis.cookies = new Proxy({}, {
|
|||||||
get(_, k){
|
get(_, k){
|
||||||
if(k==='length') return globalThis.__hsCookieStore.size;
|
if(k==='length') return globalThis.__hsCookieStore.size;
|
||||||
if(k==='clear') return (name)=>globalThis.__hsCookieStore.delete(String(name));
|
if(k==='clear') return (name)=>globalThis.__hsCookieStore.delete(String(name));
|
||||||
if(k===Symbol.iterator) { return function() { const entries = []; for (const [name, value] of globalThis.__hsCookieStore) entries.push({_type:'dict', name, value}); return entries[Symbol.iterator](); }; }
|
if(typeof k==='symbol' || k==='_type' || k==='_order') return undefined;
|
||||||
if(typeof k==='symbol' || k==='_order') return undefined;
|
|
||||||
return globalThis.__hsCookieStore.has(k) ? globalThis.__hsCookieStore.get(k) : null;
|
return globalThis.__hsCookieStore.has(k) ? globalThis.__hsCookieStore.get(k) : null;
|
||||||
},
|
},
|
||||||
set(_, k, v){ globalThis.__hsCookieStore.set(String(k), String(v)); return true; },
|
set(_, k, v){ globalThis.__hsCookieStore.set(String(k), String(v)); return true; },
|
||||||
@@ -371,11 +382,6 @@ globalThis.cookies = new Proxy({}, {
|
|||||||
if(globalThis.__hsCookieStore.has(k)) return {value: globalThis.__hsCookieStore.get(k), enumerable: true, configurable: true};
|
if(globalThis.__hsCookieStore.has(k)) return {value: globalThis.__hsCookieStore.get(k), enumerable: true, configurable: true};
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
[Symbol.iterator]() {
|
|
||||||
const entries = [];
|
|
||||||
for (const [name, value] of globalThis.__hsCookieStore) entries.push({_type:'dict', name, value});
|
|
||||||
return entries[Symbol.iterator]();
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
// cluster-28: test-name-keyed confirm/prompt/alert mocks. The upstream
|
// cluster-28: test-name-keyed confirm/prompt/alert mocks. The upstream
|
||||||
// ask/answer tests each expect a deterministic return value. Keyed on
|
// ask/answer tests each expect a deterministic return value. Keyed on
|
||||||
@@ -396,13 +402,6 @@ globalThis.prompt = function(_msg){
|
|||||||
globalThis.Event=Ev; globalThis.CustomEvent=Ev; globalThis.NodeList=Array; globalThis.HTMLCollection=Array;
|
globalThis.Event=Ev; globalThis.CustomEvent=Ev; globalThis.NodeList=Array; globalThis.HTMLCollection=Array;
|
||||||
globalThis.getComputedStyle=(e)=>e?e.style:{}; globalThis.requestAnimationFrame=(f)=>{f();return 0;};
|
globalThis.getComputedStyle=(e)=>e?e.style:{}; globalThis.requestAnimationFrame=(f)=>{f();return 0;};
|
||||||
globalThis.cancelAnimationFrame=()=>{};
|
globalThis.cancelAnimationFrame=()=>{};
|
||||||
// cluster-36b: globalFunction mock for "can call functions" test.
|
|
||||||
// The test calls globalFunction("foo") via hyperscript and checks window.calledWith.
|
|
||||||
globalThis.globalFunction = function(x) { globalThis.calledWith = x; };
|
|
||||||
// asyncCheck: async-when test needs a truthy-returning global (simulates async guard).
|
|
||||||
globalThis.asyncCheck = function() { return true; };
|
|
||||||
// cluster-asyncError: function that returns a rejected promise.
|
|
||||||
globalThis.failAsync = function() { return Promise.reject(new Error("boom")); };
|
|
||||||
// HsMutationObserver — cluster-32 mutation mock. Maintains a global
|
// HsMutationObserver — cluster-32 mutation mock. Maintains a global
|
||||||
// registry; setAttribute/appendChild/removeChild/_setInnerHTML hooks below
|
// registry; setAttribute/appendChild/removeChild/_setInnerHTML hooks below
|
||||||
// fire matching observers synchronously. A re-entry guard
|
// fire matching observers synchronously. A re-entry guard
|
||||||
@@ -555,94 +554,85 @@ class HsIntersectionObserver {
|
|||||||
}
|
}
|
||||||
globalThis.IntersectionObserver = HsIntersectionObserver;
|
globalThis.IntersectionObserver = HsIntersectionObserver;
|
||||||
globalThis.IntersectionObserverEntry = class {};
|
globalThis.IntersectionObserverEntry = class {};
|
||||||
// WebSocket mock for socket feature tests (E36)
|
|
||||||
globalThis.WebSocket = function HsWebSocket(url) {
|
|
||||||
const sock = {
|
|
||||||
url, readyState: 1, onmessage: null, onclose: null, onerror: null, onopen: null,
|
|
||||||
_listeners: {}, _sent: [],
|
|
||||||
send(msg) { sock._sent.push(msg); },
|
|
||||||
addEventListener(t, h) { (sock._listeners[t] = sock._listeners[t] || []).push(h); },
|
|
||||||
removeEventListener(t, h) { if (sock._listeners[t]) sock._listeners[t] = sock._listeners[t].filter(x => x !== h); },
|
|
||||||
close() { sock.readyState = 3; (sock._listeners['close'] || []).forEach(h => h({})); if (sock.onclose) sock.onclose({}); }
|
|
||||||
};
|
|
||||||
globalThis.__hs_ws_created = globalThis.__hs_ws_created || [];
|
|
||||||
globalThis.__hs_ws_created.push(sock);
|
|
||||||
return sock;
|
|
||||||
};
|
|
||||||
globalThis.WebSocket.CONNECTING = 0; globalThis.WebSocket.OPEN = 1; globalThis.WebSocket.CLOSING = 2; globalThis.WebSocket.CLOSED = 3;
|
|
||||||
var _iidCounter = 0;
|
|
||||||
function _hsRpcCall(wrapper, fnName, args, timeout) {
|
|
||||||
if (wrapper._closed) {
|
|
||||||
const ws2 = new (wrapper._WS || globalThis.WebSocket)(wrapper._url);
|
|
||||||
wrapper._ws = ws2; wrapper._closed = false;
|
|
||||||
if (wrapper._onmessage_handler) ws2.onmessage = wrapper._onmessage_handler;
|
|
||||||
ws2.addEventListener('close', () => { wrapper._closed = true; });
|
|
||||||
}
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const iid = String(++_iidCounter);
|
|
||||||
const ws = wrapper._ws;
|
|
||||||
if (!wrapper._pending) wrapper._pending = {};
|
|
||||||
wrapper._pending[iid] = { resolve, reject };
|
|
||||||
if (ws && ws.send) ws.send(JSON.stringify({ iid, function: fnName, args }));
|
|
||||||
if (timeout !== Infinity && timeout != null) {
|
|
||||||
setTimeout(() => {
|
|
||||||
if (wrapper._pending && wrapper._pending[iid]) {
|
|
||||||
delete wrapper._pending[iid];
|
|
||||||
reject('Timed out');
|
|
||||||
}
|
|
||||||
}, timeout);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function _hsMakeRpcProxy(wrapper, overrides) {
|
|
||||||
overrides = overrides || {};
|
|
||||||
// The OCaml WASM kernel cannot store values created inside a JS Proxy's get trap —
|
|
||||||
// they arrive as nil. Use a dispatch-object pattern instead: host-get detects
|
|
||||||
// _hsRpcDispatch and calls it directly, bypassing Proxy trap issues.
|
|
||||||
const rpc = function() {};
|
|
||||||
rpc._hsRpcDispatch = function(name) {
|
|
||||||
name = String(name);
|
|
||||||
if (['then', 'catch', 'length', 'toJSON'].includes(name)) return null;
|
|
||||||
if (name === 'noTimeout') return _hsMakeRpcProxy(wrapper, Object.assign({}, overrides, { timeout: Infinity }));
|
|
||||||
if (name === 'timeout') return function(n) { return _hsMakeRpcProxy(wrapper, Object.assign({}, overrides, { timeout: n })); };
|
|
||||||
const t = overrides.timeout !== undefined ? overrides.timeout : (wrapper._timeout != null ? wrapper._timeout : 0);
|
|
||||||
return function() { return _hsRpcCall(wrapper, name, Array.from(arguments), t); };
|
|
||||||
};
|
|
||||||
return rpc;
|
|
||||||
}
|
|
||||||
globalThis._hs_make_rpc_proxy = _hsMakeRpcProxy;
|
|
||||||
function _hsSetupSocket(wrapper) {
|
|
||||||
wrapper.dispatchEvent = function(evt) {
|
|
||||||
if (wrapper._closed) {
|
|
||||||
const ws2 = new (wrapper._WS || globalThis.WebSocket)(wrapper._url);
|
|
||||||
wrapper._ws = ws2; wrapper._closed = false;
|
|
||||||
if (wrapper._onmessage_handler) ws2.onmessage = wrapper._onmessage_handler;
|
|
||||||
ws2.addEventListener('close', () => { wrapper._closed = true; });
|
|
||||||
}
|
|
||||||
const ws = wrapper._ws;
|
|
||||||
if (!ws) return;
|
|
||||||
const payload = { type: evt.type };
|
|
||||||
const detail = evt.detail || {};
|
|
||||||
for (const k of Object.keys(detail)) {
|
|
||||||
if (k !== 'sender' && k !== '_namedArgList_' && k !== '_type') payload[k] = detail[k];
|
|
||||||
}
|
|
||||||
ws.send(JSON.stringify(payload));
|
|
||||||
};
|
|
||||||
wrapper.rpc = _hsMakeRpcProxy(wrapper, {});
|
|
||||||
return wrapper;
|
|
||||||
}
|
|
||||||
globalThis._hsSetupSocket = _hsSetupSocket;
|
|
||||||
globalThis.navigator={userAgent:'node'}; globalThis.location={href:'http://localhost/',pathname:'/',search:'',hash:'',protocol:'http:',host:'localhost',hostname:'localhost',port:''};
|
globalThis.navigator={userAgent:'node'}; globalThis.location={href:'http://localhost/',pathname:'/',search:'',hash:'',protocol:'http:',host:'localhost',hostname:'localhost',port:''};
|
||||||
globalThis.history={pushState(){},replaceState(){},back(){},forward(){}};
|
globalThis.history={pushState(){},replaceState(){},back(){},forward(){}};
|
||||||
globalThis.getSelection=()=>({toString:()=>(globalThis.__test_selection||'')});
|
globalThis.getSelection=()=>({toString:()=>(globalThis.__test_selection||'')});
|
||||||
|
// HsWebSocket — cluster-36 WebSocket mock. Records every constructed socket
|
||||||
|
// in globalThis.__hs_ws_created so tests can assert on URLs and sent frames.
|
||||||
|
// Tests may override globalThis.WebSocket before activating hyperscript.
|
||||||
|
// __hs_ws_created is a plain object with numeric keys (NOT a JS array).
|
||||||
|
// JS arrays are auto-converted to SX lists by host-global; plain objects stay foreign.
|
||||||
|
// host-get foreign 0 → foreign[0] → mock sock ✓
|
||||||
|
globalThis.__hs_ws_created = {_len: 0};
|
||||||
|
globalThis.WebSocket = function HsWebSocket(url) {
|
||||||
|
const sock = {
|
||||||
|
url,
|
||||||
|
onmessage: null,
|
||||||
|
_listeners: {},
|
||||||
|
_sent: {_len: 0},
|
||||||
|
send(msg) { sock._sent[sock._sent._len]=msg; sock._sent._len++; },
|
||||||
|
addEventListener(t, h) { (sock._listeners[t] = sock._listeners[t] || []).push(h); },
|
||||||
|
removeEventListener(t, h) { const a = sock._listeners[t]; if (a) { const i = a.indexOf(h); if (i >= 0) a.splice(i, 1); } },
|
||||||
|
close() { (sock._listeners['close'] || []).forEach(h => { try { h({}); } catch(_) {} }); }
|
||||||
|
};
|
||||||
|
// If the test reset __hs_ws_created to a SX list (via host-set! ... (list)), reinitialise.
|
||||||
|
if (typeof globalThis.__hs_ws_created?._len !== 'number') globalThis.__hs_ws_created = {_len: 0};
|
||||||
|
const idx = globalThis.__hs_ws_created._len;
|
||||||
|
globalThis.__hs_ws_created[idx] = sock;
|
||||||
|
globalThis.__hs_ws_created._len++;
|
||||||
|
return sock;
|
||||||
|
};
|
||||||
|
// _hs_make_rpc_proxy — cluster-36 RPC proxy factory. Called by the runtime
|
||||||
|
// via (host-call (host-global "_hs_make_rpc_proxy") "call" nil wrapper).
|
||||||
|
// wrapper is the SX dict: {raw, url, timeout, pending, ...}
|
||||||
|
// Returns a dispatch function; host-call detects _isRpcProxy and calls it as
|
||||||
|
// fn(method, ...args) rather than fn.method().
|
||||||
|
function _hsRpcCall(wrapper, fnName, args, timeoutMs) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Lazy reconnect: if the underlying socket closed, open a fresh one
|
||||||
|
// closedFlag is set to "1" (string) by the SX close listener.
|
||||||
|
if (wrapper.closedFlag) {
|
||||||
|
const oldOnmessage = wrapper.raw && wrapper.raw.onmessage;
|
||||||
|
const newWs = new globalThis.WebSocket(wrapper.url);
|
||||||
|
newWs.onmessage = oldOnmessage;
|
||||||
|
wrapper.raw = newWs;
|
||||||
|
wrapper.closedFlag = null;
|
||||||
|
}
|
||||||
|
const iid = String(Math.random()).slice(2) + String(Date.now());
|
||||||
|
if (!wrapper.pending) wrapper.pending = {};
|
||||||
|
wrapper.pending[iid] = { resolve, reject };
|
||||||
|
const raw = wrapper.raw;
|
||||||
|
const msg = JSON.stringify({ iid, function: fnName, args });
|
||||||
|
raw.send(msg);
|
||||||
|
const ms = timeoutMs === undefined ? (typeof wrapper.timeout === 'number' ? wrapper.timeout : 0) : timeoutMs;
|
||||||
|
if (ms !== Infinity && typeof ms === 'number') {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (wrapper.pending && wrapper.pending[iid]) {
|
||||||
|
delete wrapper.pending[iid];
|
||||||
|
reject('Timed out');
|
||||||
|
}
|
||||||
|
}, ms);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function _hs_make_rpc_proxy(wrapper, overrides) {
|
||||||
|
overrides = overrides || {};
|
||||||
|
const fn = function _rpcDispatch(method, ...args) {
|
||||||
|
if (['then', 'catch', 'length', 'toJSON'].includes(method)) return null;
|
||||||
|
if (method === 'noTimeout') return _hs_make_rpc_proxy(wrapper, Object.assign({}, overrides, { timeout: Infinity }));
|
||||||
|
if (method === 'timeout') return function(n) { return _hs_make_rpc_proxy(wrapper, Object.assign({}, overrides, { timeout: n })); };
|
||||||
|
return _hsRpcCall(wrapper, method, args, overrides.timeout);
|
||||||
|
};
|
||||||
|
fn._isRpcProxy = true;
|
||||||
|
return fn;
|
||||||
|
}
|
||||||
|
// host-call passes args as (this_placeholder, ...rest); strip the nil first-arg.
|
||||||
|
globalThis._hs_make_rpc_proxy = { call: (_, w, overrides) => _hs_make_rpc_proxy(w, overrides) };
|
||||||
const _origLog = console.log;
|
const _origLog = console.log;
|
||||||
globalThis.console = { log: () => {}, error: () => {}, warn: () => {}, info: () => {}, debug: () => {} }; // suppress ALL console noise
|
globalThis.console = { log: () => {}, error: () => {}, warn: () => {}, info: () => {}, debug: () => {} }; // suppress ALL console noise
|
||||||
const _log = _origLog; // keep reference for our own output
|
const _log = _origLog; // keep reference for our own output
|
||||||
|
|
||||||
// ─── FFI ────────────────────────────────────────────────────────
|
// ─── FFI ────────────────────────────────────────────────────────
|
||||||
// JS-level reference equality for host objects (works around OCaml boxing).
|
|
||||||
// The SX `=` primitive doesn't do JS === for host objects in the WASM kernel.
|
|
||||||
K.registerNative('hs-ref-eq',a=>a[0]===a[1]);
|
|
||||||
K.registerNative('host-global',a=>{const n=a[0];return(n in globalThis)?globalThis[n]:null;});
|
K.registerNative('host-global',a=>{const n=a[0];return(n in globalThis)?globalThis[n]:null;});
|
||||||
K.registerNative('host-get',a=>{
|
K.registerNative('host-get',a=>{
|
||||||
if(a[0]==null)return null;
|
if(a[0]==null)return null;
|
||||||
@@ -650,87 +640,24 @@ K.registerNative('host-get',a=>{
|
|||||||
// through JS property access. Hand-roll common collection queries so
|
// through JS property access. Hand-roll common collection queries so
|
||||||
// compiled HS `x.length` / `x.size` works on scoped lists.
|
// compiled HS `x.length` / `x.size` works on scoped lists.
|
||||||
if(a[0] && a[0]._type==='list' && (a[1]==='length' || a[1]==='size')) return a[0].items.length;
|
if(a[0] && a[0]._type==='list' && (a[1]==='length' || a[1]==='size')) return a[0].items.length;
|
||||||
if(a[0] && a[0]._type==='list' && typeof a[1]==='number') return a[0].items[a[1]]!==undefined?a[0].items[a[1]]:null;
|
|
||||||
if(a[0] && a[0]._type==='dict' && a[1]==='size') return Object.keys(a[0]).filter(k=>k!=='_type').length;
|
if(a[0] && a[0]._type==='dict' && a[1]==='size') return Object.keys(a[0]).filter(k=>k!=='_type').length;
|
||||||
// innerText is DOM-level alias for textContent (close enough for mock purposes)
|
// innerText is DOM-level alias for textContent (close enough for mock purposes)
|
||||||
if(a[0] instanceof El && a[1]==='innerText') return String(a[0].textContent||'');
|
if(a[0] instanceof El && a[1]==='innerText') return String(a[0].textContent||'');
|
||||||
// RPC dispatch object: _hsRpcDispatch bypasses Proxy-in-WASM-kernel nil issue
|
|
||||||
if(a[0] && typeof a[0]._hsRpcDispatch==='function'){const rv=a[0]._hsRpcDispatch(String(a[1]));return rv===undefined?null:rv;}
|
|
||||||
let v=a[0][a[1]];
|
let v=a[0][a[1]];
|
||||||
if(v===undefined)return null;
|
if(v===undefined)return null;
|
||||||
// Only coerce DOM property strings for actual DOM elements — plain JS objects
|
if((a[1]==='innerHTML'||a[1]==='textContent'||a[1]==='value'||a[1]==='className')&&typeof v!=='string')v=String(v!=null?v:'');
|
||||||
// (e.g. promise-state dicts with a "value" key) must not be stringified.
|
|
||||||
if(a[0] instanceof El&&(a[1]==='innerHTML'||a[1]==='textContent'||a[1]==='value'||a[1]==='className')&&typeof v!=='string')v=String(v!=null?v:'');
|
|
||||||
return v;
|
return v;
|
||||||
});
|
});
|
||||||
K.registerNative('host-set!',a=>{if(a[0]!=null){const v=a[2]; if(a[1]==='innerHTML'&&a[0] instanceof El){const s=v===null?'null':v===undefined?'':String(v);a[0]._setInnerHTML(s);a[0][a[1]]=a[0].innerHTML;} else if(a[1]==='textContent'&&a[0] instanceof El){const s=v===null?'null':v===undefined?'':String(v);a[0].textContent=s;a[0].innerHTML=s;for(const c of a[0].children){c.parentElement=null;c.parentNode=null;}a[0].children=[];a[0].childNodes=[];} else{a[0][a[1]]=v;}} return a[2];});
|
K.registerNative('host-set!',a=>{if(a[0]!=null){const v=a[2]; if(a[1]==='innerHTML'&&a[0] instanceof El){const s=v===null?'null':v===undefined?'':String(v);a[0]._setInnerHTML(s);a[0][a[1]]=a[0].innerHTML;} else if(a[1]==='textContent'&&a[0] instanceof El){const s=v===null?'null':v===undefined?'':String(v);a[0].textContent=s;a[0].innerHTML=s;for(const c of a[0].children){c.parentElement=null;c.parentNode=null;}a[0].children=[];a[0].childNodes=[];} else{a[0][a[1]]=v;}} return a[2];});
|
||||||
K.registerNative('host-call',a=>{if(_testDeadline&&Date.now()>_testDeadline)throw new Error('TIMEOUT: wall clock exceeded');const[o,m,...r]=a;if(o==null){const f=globalThis[m];return typeof f==='function'?f.apply(null,r):null;}if(o&&typeof o[m]==='function'){try{const v=o[m].apply(o,r);return v===undefined?null:v;}catch(e){return null;}}return null;});
|
K.registerNative('host-call',a=>{if(_testDeadline&&Date.now()>_testDeadline)throw new Error('TIMEOUT: wall clock exceeded');const[o,m,...r]=a;if(o==null){const f=globalThis[m];return typeof f==='function'?f.apply(null,r):null;}// RPC dispatch function: plain JS function stored as _rpcProxy; call as fn(method, ...args)
|
||||||
K.registerNative('host-call-fn',a=>{const[fn,argList]=a;if(typeof fn!=='function'&&!(fn&&fn.__sx_handle!==undefined))return null;const callArgs=(argList&&argList._type==='list'&&argList.items)?Array.from(argList.items):(Array.isArray(argList)?argList:[]);if(fn&&fn.__sx_handle!==undefined){try{return K.callFn(fn,callArgs);}catch(e){const msg=e&&e.message||'';if(String(msg).includes('TIMEOUT'))throw e;return null;}}function sxToJs(v){if(v&&v._type==='list'&&v.items)return Array.from(v.items).map(sxToJs);return v;}try{const v=fn.apply(null,callArgs.map(sxToJs));return v===undefined?null:v;}catch(e){return null;}});
|
// because host-call normally does o[method]() which would return undefined on a function obj.
|
||||||
|
if(o&&o._isRpcProxy){try{const v=o(m,...r);return v===undefined?null:v;}catch(e){return null;}}if(o&&o.__sx_handle!==undefined){try{const v=K.callFn(o,[m,...r]);if(globalThis._driveAsync)globalThis._driveAsync(v);return v===undefined?null:v;}catch(e){return null;}}if(o&&typeof o[m]==='function'){try{const v=o[m].apply(o,r);return v===undefined?null:v;}catch(e){return null;}}return null;});
|
||||||
|
K.registerNative('host-call-fn',a=>{const[fn,argList]=a;if(typeof fn!=='function'&&!(fn&&fn.__sx_handle!==undefined))return null;const callArgs=(argList&&argList._type==='list'&&argList.items)?Array.from(argList.items):(Array.isArray(argList)?argList:[]);if(fn&&fn.__sx_handle!==undefined)return K.callFn(fn,callArgs);try{const v=fn.apply(null,callArgs);return v===undefined?null:v;}catch(e){return null;}});
|
||||||
K.registerNative('host-new',a=>{const C=typeof a[0]==='string'?globalThis[a[0]]:a[0];return typeof C==='function'?new C(...a.slice(1)):null;});
|
K.registerNative('host-new',a=>{const C=typeof a[0]==='string'?globalThis[a[0]]:a[0];return typeof C==='function'?new C(...a.slice(1)):null;});
|
||||||
K.registerNative('host-callback',a=>{const fn=a[0];if(typeof fn==='function'&&fn.__sx_handle===undefined)return fn;if(fn&&fn.__sx_handle!==undefined)return function(){const r=K.callFn(fn,Array.from(arguments));if(globalThis._driveAsync)globalThis._driveAsync(r);return r;};return function(){};});
|
K.registerNative('host-callback',a=>{const fn=a[0];if(typeof fn==='function'&&fn.__sx_handle===undefined)return fn;if(fn&&fn.__sx_handle!==undefined){const _fn=fn;return function(){try{const r=K.callFn(_fn,Array.from(arguments));if(globalThis._driveAsync)globalThis._driveAsync(r);return r;}catch(e){}};} return function(){};});
|
||||||
K.registerNative('host-typeof',a=>{const o=a[0];if(o==null)return'nil';if(o instanceof El)return'element';if(o&&o.nodeType===3)return'text';if(o instanceof Ev)return'event';if(o instanceof Promise)return'promise';return typeof o;});
|
K.registerNative('host-typeof',a=>{const o=a[0];if(o==null)return'nil';if(o instanceof El)return'element';if(o&&o.nodeType===3)return'text';if(o instanceof Ev)return'event';if(o instanceof Promise)return'promise';return typeof o;});
|
||||||
K.registerNative('host-iter?',([obj])=>obj!=null&&typeof obj[Symbol.iterator]==='function');
|
|
||||||
K.registerNative('host-to-list',([obj])=>{try{return[...obj];}catch(e){return[];}});
|
|
||||||
K.registerNative('host-await',a=>{});
|
K.registerNative('host-await',a=>{});
|
||||||
K.registerNative('load-library!',()=>false);
|
K.registerNative('load-library!',()=>false);
|
||||||
K.registerNative('hs-is-set?',a=>a[0] instanceof Set);
|
|
||||||
K.registerNative('hs-is-map?',a=>a[0] instanceof Map);
|
|
||||||
// Upstream test fixtures: synchronous stubs matching OCaml run_tests.ml registrations
|
|
||||||
globalThis.promiseAString = () => 'foo';
|
|
||||||
globalThis.promiseAnInt = () => 42;
|
|
||||||
|
|
||||||
// ── JS block execution support ─────────────────────────────────
|
|
||||||
// Track promise states for synchronous introspection in hs-js-exec
|
|
||||||
const _promiseStates = new WeakMap();
|
|
||||||
const _origPReject = Promise.reject.bind(Promise);
|
|
||||||
const _origPResolve = Promise.resolve.bind(Promise);
|
|
||||||
Promise.reject = function(v) {
|
|
||||||
const p = _origPReject(v);
|
|
||||||
_promiseStates.set(p, {ok: false, value: v});
|
|
||||||
p.catch(() => {}); // suppress unhandled rejection warning
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
Promise.resolve = function(v) {
|
|
||||||
if (v && typeof v === 'object' && typeof v.then === 'function') return _origPResolve(v);
|
|
||||||
const p = _origPResolve(v);
|
|
||||||
_promiseStates.set(p, {ok: true, value: v});
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
K.registerNative('host-new-function', a => {
|
|
||||||
const paramList = a[0];
|
|
||||||
const src = a[1];
|
|
||||||
const params = paramList && paramList._type === 'list' && paramList.items
|
|
||||||
? Array.from(paramList.items)
|
|
||||||
: Array.isArray(paramList) ? paramList : [];
|
|
||||||
try { return new Function(...params, src); } catch(e) { return null; }
|
|
||||||
});
|
|
||||||
|
|
||||||
K.registerNative('host-promise-state', a => {
|
|
||||||
const p = a[0];
|
|
||||||
if (!p || typeof p.then !== 'function') return null;
|
|
||||||
const s = _promiseStates.get(p);
|
|
||||||
if (!s) return null;
|
|
||||||
// Wrap Error objects as plain dicts — the WASM bridge serializes arbitrary
|
|
||||||
// JS objects to strings, so we extract message before crossing the boundary.
|
|
||||||
const val = s.value instanceof Error
|
|
||||||
? {message: s.value.message}
|
|
||||||
: (s.value != null ? s.value : null);
|
|
||||||
return {ok: s.ok, value: val};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Normalize exception in catch blocks: if this is the async-error sentinel string,
|
|
||||||
// retrieve the original error object from the side-channel global instead.
|
|
||||||
K.registerNative('host-hs-normalize-exc', a => {
|
|
||||||
const val = a[0];
|
|
||||||
const pending = globalThis.__hs_async_error;
|
|
||||||
if (pending !== undefined && pending !== null && val === '__hs_async_error__') {
|
|
||||||
globalThis.__hs_async_error = null;
|
|
||||||
return pending;
|
|
||||||
}
|
|
||||||
globalThis.__hs_async_error = null;
|
|
||||||
return val;
|
|
||||||
});
|
|
||||||
|
|
||||||
let _testDeadline = 0;
|
let _testDeadline = 0;
|
||||||
// Mock fetch routes
|
// Mock fetch routes
|
||||||
@@ -741,41 +668,23 @@ const _fetchRoutes = {
|
|||||||
'/number': { status: 200, body: '1.2' },
|
'/number': { status: 200, body: '1.2' },
|
||||||
'/users/Joe': { status: 200, body: 'Joe', json: '{"name":"Joe"}' },
|
'/users/Joe': { status: 200, body: 'Joe', json: '{"name":"Joe"}' },
|
||||||
};
|
};
|
||||||
// Per-test fetch overrides keyed by test name; takes priority over _fetchRoutes.
|
|
||||||
const _fetchScripts = {
|
|
||||||
"as response does not throw on 404":
|
|
||||||
{ "/test": { status: 404, body: "not found" } },
|
|
||||||
"do not throw passes through 404 response":
|
|
||||||
{ "/test": { status: 404, body: "the body" } },
|
|
||||||
"don't throw passes through 404 response":
|
|
||||||
{ "/test": { status: 404, body: "the body" } },
|
|
||||||
"throws on non-2xx response by default":
|
|
||||||
{ "/test": { status: 404, body: "not found" } },
|
|
||||||
"Response can be converted to JSON via as JSON":
|
|
||||||
{ "/test": { status: 200, body: '{"name":"Joe"}', json: '{"name":"Joe"}',
|
|
||||||
contentType: "application/json" } },
|
|
||||||
"can catch an error that occurs when using fetch":
|
|
||||||
{ "/test": { networkError: true } },
|
|
||||||
"triggers an event just before fetching":
|
|
||||||
{ "/test": { status: 200, body: "yay", contentType: "text/html" } },
|
|
||||||
"can do a simple fetch w/ a custom conversion":
|
|
||||||
{ "/test": { status: 200, body: "1.2" } },
|
|
||||||
};
|
|
||||||
function _mockFetch(url) {
|
function _mockFetch(url) {
|
||||||
const scriptRoutes = _fetchScripts[globalThis.__currentHsTestName];
|
const route = _fetchRoutes[url] || _fetchRoutes['/test'];
|
||||||
const route = (scriptRoutes && scriptRoutes[url]) || _fetchRoutes[url] || _fetchRoutes['/test'];
|
return { ok: route.status < 400, status: route.status || 200, url: url || '/test',
|
||||||
return { ok: (route.status||200) < 400, status: route.status || 200, url: url || '/test',
|
|
||||||
_body: route.body || '', _json: route.json || route.body || '', _html: route.html || route.body || '' };
|
_body: route.body || '', _json: route.json || route.body || '', _html: route.html || route.body || '' };
|
||||||
}
|
}
|
||||||
globalThis._driveAsync=function driveAsync(r,d){d=d||0;if(_testDeadline && Date.now()>_testDeadline)throw new Error('TIMEOUT: wall clock exceeded');if(globalThis._hs_null_error)return;if(d>500||!r||!r.suspended)return;const req=r.request;const items=req&&(req.items||req);const op=items&&items[0];const opName=typeof op==='string'?op:(op&&op.name)||String(op);
|
globalThis._driveAsync=function driveAsync(r,d){d=d||0;if(d>500||!r||!r.suspended)return;if(_testDeadline && Date.now()>_testDeadline)throw new Error('TIMEOUT: wall clock exceeded');const req=r.request;const items=req&&(req.items||req);const op=items&&items[0];const opName=typeof op==='string'?op:(op&&op.name)||String(op);
|
||||||
function doResume(v){try{const x=r.resume(v);driveAsync(x,d+1);}catch(e){const msg=e&&(e.message||(Array.isArray(e)&&typeof e[2]==='string'&&e[2])||'');if(String(msg).includes('TIMEOUT'))throw e;}}
|
function doResume(v){try{const x=r.resume(v);driveAsync(x,d+1);}catch(e){}}
|
||||||
if(opName==='io-sleep'||opName==='wait')doResume(null);
|
if(opName==='io-sleep'||opName==='wait')doResume(null);
|
||||||
else if(opName==='io-fetch'){
|
else if(opName==='io-fetch'){
|
||||||
const url=typeof items[1]==='string'?items[1]:'/test';
|
const url=typeof items[1]==='string'?items[1]:'/test';
|
||||||
const scriptRoutes=_fetchScripts[globalThis.__currentHsTestName];
|
const fmt=typeof items[2]==='string'?items[2]:'text';
|
||||||
const route=(scriptRoutes&&scriptRoutes[url])||_fetchRoutes[url]||_fetchRoutes['/test'];
|
const route=_fetchRoutes[url]||_fetchRoutes['/test'];
|
||||||
if(route&&route.networkError){doResume({_type:'dict','_network-error':true,message:'aborted'});}
|
if(fmt==='json'){try{doResume(JSON.parse(route.json||route.body||'{}'));}catch(e){doResume(null);}}
|
||||||
else{const st=route.status||200;doResume({_type:'dict',ok:st<400,status:st,url,_body:route.body||'',_json:route.json||route.body||'',_html:route.html||route.body||'',_number:route.number||route.body||''});}
|
else if(fmt==='html'){const frag=new El('fragment');frag.nodeType=11;frag.innerHTML=route.html||route.body||'';frag.textContent=frag.innerHTML.replace(/<[^>]*>/g,'');doResume(frag);}
|
||||||
|
else if(fmt==='response')doResume({ok:(route.status||200)<400,status:route.status||200,url});
|
||||||
|
else if(fmt.toLowerCase()==='number')doResume(parseFloat(route.number||route.body||'0'));
|
||||||
|
else doResume(route.body||'');
|
||||||
}
|
}
|
||||||
else if(opName==='io-parse-text'){const resp=items&&items[1];doResume(resp&&resp._body?resp._body:typeof resp==='string'?resp:'');}
|
else if(opName==='io-parse-text'){const resp=items&&items[1];doResume(resp&&resp._body?resp._body:typeof resp==='string'?resp:'');}
|
||||||
else if(opName==='io-parse-json'){const resp=items&&items[1];try{doResume(JSON.parse(typeof resp==='string'?resp:resp&&resp._json?resp._json:'{}'));}catch(e){doResume(null);}}
|
else if(opName==='io-parse-json'){const resp=items&&items[1];try{doResume(JSON.parse(typeof resp==='string'?resp:resp&&resp._json?resp._json:'{}'));}catch(e){doResume(null);}}
|
||||||
@@ -810,8 +719,7 @@ const t_mod = Date.now();
|
|||||||
const WEB=['render','core-signals','signals','deps','router','page-helpers','freeze','dom','browser','adapter-html','adapter-sx','adapter-dom','boot-helpers','hypersx','engine','orchestration','boot'];
|
const WEB=['render','core-signals','signals','deps','router','page-helpers','freeze','dom','browser','adapter-html','adapter-sx','adapter-dom','boot-helpers','hypersx','engine','orchestration','boot'];
|
||||||
const HS=['hs-tokenizer','hs-parser','hs-compiler','hs-runtime','hs-integration'];
|
const HS=['hs-tokenizer','hs-parser','hs-compiler','hs-runtime','hs-integration'];
|
||||||
K.beginModuleLoad();
|
K.beginModuleLoad();
|
||||||
// hs-* modules: prefer lib/hyperscript/ (source of truth for conformance work) over WASM sx dir
|
for(const mod of[...WEB,...HS]){const sp=path.join(SX_DIR,mod+'.sx');const lp=path.join(PROJECT,'lib/hyperscript',mod.replace(/^hs-/,'')+'.sx');let s;try{s=fs.existsSync(sp)?fs.readFileSync(sp,'utf8'):fs.readFileSync(lp,'utf8');}catch(e){continue;}try{K.load(s);}catch(e){process.stderr.write(`LOAD ERROR: ${mod}: ${e.message}\n`);}}
|
||||||
for(const mod of[...WEB,...HS]){const sp=path.join(SX_DIR,mod+'.sx');const lp=path.join(PROJECT,'lib/hyperscript',mod.replace(/^hs-/,'')+'.sx');let s;try{const lpExists=mod.startsWith('hs-')&&fs.existsSync(lp);s=lpExists?fs.readFileSync(lp,'utf8'):(fs.existsSync(sp)?fs.readFileSync(sp,'utf8'):fs.readFileSync(lp,'utf8'));}catch(e){continue;}try{K.load(s);}catch(e){process.stderr.write(`LOAD ERROR: ${mod}: ${e.message}\n`);}}
|
|
||||||
K.endModuleLoad();
|
K.endModuleLoad();
|
||||||
process.stderr.write(`Modules loaded in ${Date.now()-t_mod}ms\n`);
|
process.stderr.write(`Modules loaded in ${Date.now()-t_mod}ms\n`);
|
||||||
|
|
||||||
@@ -846,26 +754,6 @@ for(const f of['spec/harness.sx','spec/tests/test-framework.sx','spec/tests/test
|
|||||||
}
|
}
|
||||||
process.stderr.write(`Tests loaded in ${Date.now()-t_tests}ms\n`);
|
process.stderr.write(`Tests loaded in ${Date.now()-t_tests}ms\n`);
|
||||||
|
|
||||||
// Redefine try-call to actually catch errors for assert-throws.
|
|
||||||
// During loading it was the registration version (stores thunks, returns {:ok true}).
|
|
||||||
// Now that tests are registered, redefine it to run the thunk and catch any exception.
|
|
||||||
K.eval('(define try-call _run-test-thunk)');
|
|
||||||
|
|
||||||
// Override eval-hs-error for runtimeErrors tests: hs-null-raise!/hs-empty-raise!/hs-win-call
|
|
||||||
// each wrap their (raise msg) in a self-contained guard so the raise is swallowed before
|
|
||||||
// it can escape through the empty JIT kont and trigger the slow host_error path (~34s).
|
|
||||||
// The null error message is stored in window._hs_null_error (side channel) before the raise,
|
|
||||||
// so we can recover it here even when eval-hs returns normally.
|
|
||||||
K.eval(`(define eval-hs-error
|
|
||||||
(fn (src)
|
|
||||||
(host-set! (host-global "window") "_hs_null_error" nil)
|
|
||||||
(let ((result
|
|
||||||
(guard (_e (true (if (string? _e) _e (str _e))))
|
|
||||||
(eval-hs src)
|
|
||||||
nil)))
|
|
||||||
(or (host-get (host-global "window") "_hs_null_error") result))))`);
|
|
||||||
K.eval('(define x nil)(define y nil)(define z nil)');
|
|
||||||
|
|
||||||
const testCount = K.eval('(len _test-registry)');
|
const testCount = K.eval('(len _test-registry)');
|
||||||
// Pre-read names
|
// Pre-read names
|
||||||
const names = [];
|
const names = [];
|
||||||
@@ -889,98 +777,30 @@ for(let i=startTest;i<Math.min(endTest,testCount);i++){
|
|||||||
|
|
||||||
// Reset body
|
// Reset body
|
||||||
_body.children=[];_body.childNodes=[];_body.innerHTML='';_body.textContent='';
|
_body.children=[];_body.childNodes=[];_body.innerHTML='';_body.textContent='';
|
||||||
globalThis._hs_null_error=null;
|
|
||||||
globalThis.__test_selection='';
|
globalThis.__test_selection='';
|
||||||
globalThis.__hsCookieStore.clear();
|
globalThis.__hsCookieStore.clear();
|
||||||
globalThis.__hsMutationRegistry.length = 0;
|
globalThis.__hsMutationRegistry.length = 0;
|
||||||
globalThis.__hsMutationActive = false;
|
globalThis.__hsMutationActive = false;
|
||||||
globalThis._windowListeners={};
|
|
||||||
globalThis.__currentHsTestName = name;
|
globalThis.__currentHsTestName = name;
|
||||||
|
_fakeTimers = []; // reset timer queue between tests
|
||||||
|
|
||||||
// Hypertrace tests use async wait loops that legitimately exceed the step limit.
|
// Enable step limit for timeout protection
|
||||||
// Disable CEK step counting for these — wall-clock deadline still applies.
|
setStepLimit(STEP_LIMIT);
|
||||||
// Tests that require async event dispatch not supported in the sync test runner.
|
_testDeadline = Date.now() + 10000; // 10 second wall-clock timeout per test
|
||||||
// These tests hang indefinitely because io-wait-event suspends the OCaml kernel
|
|
||||||
// waiting for an event that is never fired from outside the K.eval call chain.
|
|
||||||
const _SKIP_TESTS = new Set([
|
|
||||||
"until event keyword works",
|
|
||||||
// Generator gap: spec is missing click dispatches; asserts textContent="1" with no events fired.
|
|
||||||
"throttled at <time> drops events within the window",
|
|
||||||
]);
|
|
||||||
if (_SKIP_TESTS.has(name)) continue;
|
|
||||||
|
|
||||||
const _NO_STEP_LIMIT = new Set([
|
|
||||||
"async hypertrace is reasonable",
|
|
||||||
"hypertrace from javascript is reasonable",
|
|
||||||
"hypertrace is reasonable",
|
|
||||||
"repeat forever works",
|
|
||||||
"repeat forever works w/o keyword",
|
|
||||||
"receives named events",
|
|
||||||
"passes the sieve test",
|
|
||||||
]);
|
|
||||||
// Suites where JIT cascade legitimately exceeds the per-test step limit.
|
|
||||||
const _NO_STEP_LIMIT_SUITES = new Set([
|
|
||||||
"hs-upstream-core/runtimeErrors",
|
|
||||||
"hs-upstream-core/sourceInfo",
|
|
||||||
"hs-upstream-expressions/collectionExpressions",
|
|
||||||
"hs-upstream-expressions/typecheck",
|
|
||||||
"hs-upstream-socket",
|
|
||||||
]);
|
|
||||||
// Enable step limit for timeout protection — reset counter first so accumulation
|
|
||||||
// across tests doesn't cause signed-32-bit wraparound (~2B extra steps before limit fires).
|
|
||||||
// Hypertrace tests instrument every evaluation and legitimately exceed the step limit.
|
|
||||||
resetStepCount();
|
|
||||||
setStepLimit((_NO_STEP_LIMIT.has(name) || _NO_STEP_LIMIT_SUITES.has(suite)) ? 0 : STEP_LIMIT);
|
|
||||||
const _SLOW_DEADLINE = {
|
|
||||||
"async hypertrace is reasonable": 8000,
|
|
||||||
"hypertrace from javascript is reasonable": 8000,
|
|
||||||
"hypertrace is reasonable": 8000,
|
|
||||||
"passes the sieve test": 180000,
|
|
||||||
"behavior scoping is isolated from other behaviors": 60000,
|
|
||||||
"behavior scoping is isolated from the core element scope": 60000,
|
|
||||||
// repeat suite: two JIT preheat calls each take 7-12s cold
|
|
||||||
"can nest loops": 60000,
|
|
||||||
"only executes the init expression once": 60000,
|
|
||||||
"repeat forever works": 60000,
|
|
||||||
"repeat forever works w/o keyword": 60000,
|
|
||||||
"until keyword works": 60000,
|
|
||||||
"while keyword works": 60000,
|
|
||||||
};
|
|
||||||
const _SLOW_DEADLINE_SUITES = {
|
|
||||||
"hs-upstream-core/runtimeErrors": 30000,
|
|
||||||
"hs-upstream-expressions/collectionExpressions": 60000,
|
|
||||||
"hs-upstream-expressions/typecheck": 30000,
|
|
||||||
"hs-upstream-behavior": 20000,
|
|
||||||
// eventsource: JIT saturation after multiple compilations in suite sequence
|
|
||||||
"hs-upstream-ext/eventsource": 30000,
|
|
||||||
// socket: first call to hs-socket-register! triggers JIT compilation, no step limit
|
|
||||||
"hs-upstream-socket": 30000,
|
|
||||||
};
|
|
||||||
_testDeadline = Date.now() + (_SLOW_DEADLINE[name] || _SLOW_DEADLINE_SUITES[suite] || 10000);
|
|
||||||
globalThis.__hs_deadline = _testDeadline; // expose to WASM cek_step_loop
|
|
||||||
if(process.env.HS_VERBOSE)process.stderr.write(`T${i} `);
|
if(process.env.HS_VERBOSE)process.stderr.write(`T${i} `);
|
||||||
|
|
||||||
let ok=false,err=null;
|
let ok=false,err=null;
|
||||||
try{
|
try{
|
||||||
// Use SX-level guard to catch errors, avoiding __sxR side-channel issues
|
// Use SX-level guard to catch errors, avoiding __sxR side-channel issues
|
||||||
// Returns a dict with :ok and :error keys.
|
// Returns a dict with :ok and :error keys
|
||||||
// Note: api_eval returns "Error: <msg>" string (not throw) for SX exceptions,
|
const _dbgR=K.eval(`(define _test-result (_run-test-thunk (get (nth _test-registry ${i}) "thunk")))`);
|
||||||
// so K.eval may return an error string rather than throwing. Check for this.
|
if(suite==='hs-upstream-socket'&&i<=1310)process.stderr.write(`[D] i=${i} r=${JSON.stringify(_dbgR)?.slice(0,160)}\n`);
|
||||||
const defineR = K.eval(`(define _test-result (_run-test-thunk (get (nth _test-registry ${i}) "thunk")))`);
|
|
||||||
// Clear deadline immediately: once the test thunk finishes (or times out and
|
|
||||||
// the guard catches it), further K.eval calls for result inspection must not
|
|
||||||
// keep re-firing the deadline check on every 10k steps.
|
|
||||||
globalThis.__hs_deadline = 0;
|
|
||||||
if(typeof defineR==='string' && defineR.startsWith('Error: ')){
|
|
||||||
err=defineR.slice(7,157); // strip "Error: " prefix
|
|
||||||
} else {
|
|
||||||
const isOk=K.eval('(get _test-result "ok")');
|
const isOk=K.eval('(get _test-result "ok")');
|
||||||
if(isOk===true){ok=true;}
|
if(isOk===true){ok=true;}
|
||||||
else{
|
else{
|
||||||
const errMsg=K.eval('(get _test-result "error")');
|
const errMsg=K.eval('(get _test-result "error")');
|
||||||
err=errMsg?String(errMsg).slice(0,150):'unknown error';
|
err=errMsg?String(errMsg).slice(0,150):'unknown error';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}catch(e){err=(e.message||'').slice(0,150);}
|
}catch(e){err=(e.message||'').slice(0,150);}
|
||||||
setStepLimit(0); // disable step limit between tests
|
setStepLimit(0); // disable step limit between tests
|
||||||
|
|
||||||
@@ -997,7 +817,7 @@ for(let i=startTest;i<Math.min(endTest,testCount);i++){
|
|||||||
else if(err&&err.includes('Unhandled'))t='unhandled';
|
else if(err&&err.includes('Unhandled'))t='unhandled';
|
||||||
errTypes[t]=(errTypes[t]||0)+1;
|
errTypes[t]=(errTypes[t]||0)+1;
|
||||||
}
|
}
|
||||||
_testDeadline = 0; globalThis.__hs_deadline = 0;
|
_testDeadline = 0;
|
||||||
if((i+1)%100===0)process.stdout.write(` ${i+1}/${testCount} (${passed} pass, ${failed} fail)\n`);
|
if((i+1)%100===0)process.stdout.write(` ${i+1}/${testCount} (${passed} pass, ${failed} fail)\n`);
|
||||||
if(elapsed > 5000)process.stdout.write(` SLOW: test ${i} took ${elapsed}ms [${suite}] ${name}\n`);
|
if(elapsed > 5000)process.stdout.write(` SLOW: test ${i} took ${elapsed}ms [${suite}] ${name}\n`);
|
||||||
if(!ok && err && err.includes('TIMEOUT'))process.stdout.write(` TIMEOUT: test ${i} [${suite}] ${name}\n`);
|
if(!ok && err && err.includes('TIMEOUT'))process.stdout.write(` TIMEOUT: test ${i} [${suite}] ${name}\n`);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,6 @@ import time
|
|||||||
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
RUNNER_PATH = os.path.join(PROJECT_DIR, "tests/hs-run-filtered.js")
|
RUNNER_PATH = os.path.join(PROJECT_DIR, "tests/hs-run-filtered.js")
|
||||||
GEN_PATH = os.path.join(PROJECT_DIR, "tests/playwright/generate-sx-tests.py")
|
GEN_PATH = os.path.join(PROJECT_DIR, "tests/playwright/generate-sx-tests.py")
|
||||||
EVAL_PATH = os.path.join(PROJECT_DIR, "tests/hs-kernel-eval.js")
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -219,135 +218,6 @@ def hs_test_status(args):
|
|||||||
return text_result("\n".join(info))
|
return text_result("\n".join(info))
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Shared helper: run hs-kernel-eval.js
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def _kernel_eval(mode, expr, setup=None, files=None, timeout_secs=60):
|
|
||||||
"""Run hs-kernel-eval.js and return a text_result."""
|
|
||||||
if not os.path.isfile(EVAL_PATH):
|
|
||||||
return error_result(f"Eval script not found at {EVAL_PATH}")
|
|
||||||
env = os.environ.copy()
|
|
||||||
env["HS_EVAL_MODE"] = mode
|
|
||||||
env["HS_EVAL_EXPR"] = expr
|
|
||||||
env["HS_EVAL_TIMEOUT_MS"] = str(max(5000, int(timeout_secs) * 1000))
|
|
||||||
if setup:
|
|
||||||
env["HS_EVAL_SETUP"] = setup
|
|
||||||
if files:
|
|
||||||
env["HS_EVAL_FILES"] = ",".join(files)
|
|
||||||
timeout = max(10, min(int(timeout_secs), 300))
|
|
||||||
try:
|
|
||||||
r = subprocess.run(
|
|
||||||
["node", EVAL_PATH],
|
|
||||||
cwd=PROJECT_DIR, env=env,
|
|
||||||
capture_output=True, text=True, timeout=timeout,
|
|
||||||
)
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
return error_result(f"Kernel eval timed out after {timeout}s")
|
|
||||||
stderr = (r.stderr or "").strip()
|
|
||||||
stdout = (r.stdout or "").strip()
|
|
||||||
# Parse JSON result from stdout
|
|
||||||
try:
|
|
||||||
import json
|
|
||||||
data = json.loads(stdout)
|
|
||||||
if data.get("ok"):
|
|
||||||
result = data.get("result", "nil")
|
|
||||||
# Unescape JSON-stringified result
|
|
||||||
try:
|
|
||||||
result = json.loads(result)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
out = f"Result: {result}"
|
|
||||||
else:
|
|
||||||
out = f"Error: {data.get('error', 'unknown error')}"
|
|
||||||
except Exception:
|
|
||||||
out = stdout or "(no output)"
|
|
||||||
if stderr:
|
|
||||||
# Filter noisy load-progress lines, keep errors
|
|
||||||
err_lines = [l for l in stderr.splitlines()
|
|
||||||
if not l.startswith("Loading") and not l.startswith("Modules") and "ms" not in l]
|
|
||||||
if err_lines:
|
|
||||||
out += "\n\nstderr:\n" + "\n".join(err_lines)
|
|
||||||
return text_result(out)
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Tool: sx_kernel_eval
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def sx_kernel_eval(args):
|
|
||||||
"""Evaluate a SX expression in the full WASM kernel with HS modules loaded.
|
|
||||||
|
|
||||||
The kernel includes mock DOM, so HS runtime functions (hs-repeat-forever,
|
|
||||||
hs-compile, dom-dispatch, etc.) are available. Use this when sx_harness_eval
|
|
||||||
fails due to missing host primitives (host-new, host-get, etc.).
|
|
||||||
|
|
||||||
Args:
|
|
||||||
expr: SX expression to evaluate (required).
|
|
||||||
setup: SX setup expression run before main eval (optional).
|
|
||||||
files: List of .sx files to load before eval (optional).
|
|
||||||
timeout_secs: Wall-clock cap in seconds (default 60, max 300).
|
|
||||||
"""
|
|
||||||
expr = args.get("expr", "").strip()
|
|
||||||
if not expr:
|
|
||||||
return error_result("'expr' is required")
|
|
||||||
return _kernel_eval(
|
|
||||||
mode="eval",
|
|
||||||
expr=expr,
|
|
||||||
setup=args.get("setup"),
|
|
||||||
files=args.get("files"),
|
|
||||||
timeout_secs=int(args.get("timeout_secs", 60)),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Tool: hs_compile_inspect
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def hs_compile_inspect(args):
|
|
||||||
"""Compile an HS source string and return the generated SX AST.
|
|
||||||
|
|
||||||
Runs hs-compile on the source and returns its string representation.
|
|
||||||
Useful for debugging what AST the HS compiler produces for a given snippet.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
hs_source: HS source code to compile (required).
|
|
||||||
timeout_secs: Wall-clock cap in seconds (default 30).
|
|
||||||
"""
|
|
||||||
src = args.get("hs_source", "").strip()
|
|
||||||
if not src:
|
|
||||||
return error_result("'hs_source' is required")
|
|
||||||
return _kernel_eval(
|
|
||||||
mode="compile",
|
|
||||||
expr=src,
|
|
||||||
timeout_secs=int(args.get("timeout_secs", 30)),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
# Tool: hs_parse_inspect
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def hs_parse_inspect(args):
|
|
||||||
"""Parse an HS source string and return the raw parser AST (before compilation).
|
|
||||||
|
|
||||||
Runs hs-parse on the source and returns its string representation.
|
|
||||||
Useful for debugging tokenizer/parser output before the compiler sees it.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
hs_source: HS source code to parse (required).
|
|
||||||
timeout_secs: Wall-clock cap in seconds (default 30).
|
|
||||||
"""
|
|
||||||
src = args.get("hs_source", "").strip()
|
|
||||||
if not src:
|
|
||||||
return error_result("'hs_source' is required")
|
|
||||||
return _kernel_eval(
|
|
||||||
mode="parse",
|
|
||||||
expr=src,
|
|
||||||
timeout_secs=int(args.get("timeout_secs", 30)),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# JSON-RPC dispatch
|
# JSON-RPC dispatch
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -395,40 +265,6 @@ TOOLS = [
|
|||||||
{},
|
{},
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
tool(
|
|
||||||
"sx_kernel_eval",
|
|
||||||
"Evaluate a SX expression in the full WASM kernel with HS modules and mock DOM loaded. "
|
|
||||||
"Use when sx_harness_eval fails due to missing host primitives (host-new, host-get, etc.). "
|
|
||||||
"Has access to hs-compile, hs-parse, hs-repeat-forever, dom-dispatch, etc.",
|
|
||||||
{
|
|
||||||
"expr": {"type": "string", "description": "SX expression to evaluate"},
|
|
||||||
"setup": {"type": "string", "description": "SX setup expression run before eval (optional)"},
|
|
||||||
"files": {"type": "array", "items": {"type": "string"},
|
|
||||||
"description": "Extra .sx files to load before eval (optional)"},
|
|
||||||
"timeout_secs": {"type": "integer", "description": "Wall-clock cap in seconds (default 60, max 300)"},
|
|
||||||
},
|
|
||||||
["expr"],
|
|
||||||
),
|
|
||||||
tool(
|
|
||||||
"hs_compile_inspect",
|
|
||||||
"Compile an HS source snippet and return the generated SX AST string. "
|
|
||||||
"Runs hs-compile and returns (str result). Use to debug what AST the compiler produces.",
|
|
||||||
{
|
|
||||||
"hs_source": {"type": "string", "description": "HS source code to compile"},
|
|
||||||
"timeout_secs": {"type": "integer", "description": "Wall-clock cap in seconds (default 30)"},
|
|
||||||
},
|
|
||||||
["hs_source"],
|
|
||||||
),
|
|
||||||
tool(
|
|
||||||
"hs_parse_inspect",
|
|
||||||
"Parse an HS source snippet and return the raw parser AST (before compilation). "
|
|
||||||
"Runs hs-parse and returns (str result). Use to debug tokenizer/parser output.",
|
|
||||||
{
|
|
||||||
"hs_source": {"type": "string", "description": "HS source code to parse"},
|
|
||||||
"timeout_secs": {"type": "integer", "description": "Wall-clock cap in seconds (default 30)"},
|
|
||||||
},
|
|
||||||
["hs_source"],
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -442,12 +278,6 @@ def handle_tool(name, args):
|
|||||||
return hs_test_regen(args)
|
return hs_test_regen(args)
|
||||||
case "hs_test_status":
|
case "hs_test_status":
|
||||||
return hs_test_status(args)
|
return hs_test_status(args)
|
||||||
case "sx_kernel_eval":
|
|
||||||
return sx_kernel_eval(args)
|
|
||||||
case "hs_compile_inspect":
|
|
||||||
return hs_compile_inspect(args)
|
|
||||||
case "hs_parse_inspect":
|
|
||||||
return hs_parse_inspect(args)
|
|
||||||
case _:
|
case _:
|
||||||
return error_result(f"Unknown tool: {name}")
|
return error_result(f"Unknown tool: {name}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user