Compare commits
8 Commits
912649c426
...
b41d9d143b
| Author | SHA1 | Date | |
|---|---|---|---|
| b41d9d143b | |||
| d663c91f4b | |||
| e989ff3865 | |||
| 8e2a633b7f | |||
| cc2a296306 | |||
| 9c8da50003 | |||
| 573f9fa4b3 | |||
| 20a643806b |
@@ -789,6 +789,7 @@
|
|||||||
(cons (quote do) (map hs-to-sx body)))))))
|
(cons (quote do) (map hs-to-sx body)))))))
|
||||||
(fn
|
(fn
|
||||||
(ast)
|
(ast)
|
||||||
|
(let ((ast (if (and (dict? ast) (get ast :hs-ast)) (get ast :children) ast)))
|
||||||
(cond
|
(cond
|
||||||
((nil? ast) nil)
|
((nil? ast) nil)
|
||||||
((number? ast) ast)
|
((number? ast) ast)
|
||||||
@@ -2207,7 +2208,7 @@
|
|||||||
(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))))
|
||||||
(true ast))))))))
|
(true ast)))))))))
|
||||||
|
|
||||||
;; ── Convenience: source → SX ─────────────────────────────────
|
;; ── Convenience: source → SX ─────────────────────────────────
|
||||||
(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))))
|
||||||
@@ -21,6 +21,15 @@
|
|||||||
adv!
|
adv!
|
||||||
(fn () (let ((t (nth tokens p))) (set! p (+ p 1)) t)))
|
(fn () (let ((t (nth tokens p))) (set! p (+ p 1)) t)))
|
||||||
(define at-end? (fn () (or (>= p tok-len) (= (tp-type) "eof"))))
|
(define at-end? (fn () (or (>= p tok-len) (= (tp-type) "eof"))))
|
||||||
|
(define cur-start (fn () (if (< p tok-len) (get (tp) "pos") 0)))
|
||||||
|
(define cur-line (fn () (if (< p tok-len) (get (tp) "line") 1)))
|
||||||
|
(define prev-end (fn () (if (> p 0) (get (nth tokens (- p 1)) "end") 0)))
|
||||||
|
(define hs-ast-wrap
|
||||||
|
(fn (raw kind start end-pos line fields)
|
||||||
|
(if hs-span-mode
|
||||||
|
{:hs-ast true :kind kind :start start :end end-pos :line line
|
||||||
|
:src src :children raw :fields fields}
|
||||||
|
raw)))
|
||||||
(define
|
(define
|
||||||
match-kw
|
match-kw
|
||||||
(fn
|
(fn
|
||||||
@@ -69,19 +78,28 @@
|
|||||||
parse-prop-chain
|
parse-prop-chain
|
||||||
(fn
|
(fn
|
||||||
(base)
|
(base)
|
||||||
|
(let
|
||||||
|
((base-start (if (and (dict? base) (get base :hs-ast)) (get base :start) (cur-start)))
|
||||||
|
(base-line (if (and (dict? base) (get base :hs-ast)) (get base :line) (cur-line))))
|
||||||
(if
|
(if
|
||||||
(and (= (tp-type) "class") (not (at-end?)))
|
(and (= (tp-type) "class") (not (at-end?)))
|
||||||
(let
|
(let
|
||||||
((prop (tp-val)))
|
((prop (tp-val)))
|
||||||
(do
|
(do
|
||||||
(adv!)
|
(adv!)
|
||||||
(parse-prop-chain (list (make-symbol ".") base prop))))
|
(parse-prop-chain
|
||||||
|
(hs-ast-wrap
|
||||||
|
(list (make-symbol ".") base prop)
|
||||||
|
"member" base-start (prev-end) base-line {:root base}))))
|
||||||
(if
|
(if
|
||||||
(= (tp-type) "paren-open")
|
(= (tp-type) "paren-open")
|
||||||
(let
|
(let
|
||||||
((args (parse-call-args)))
|
((args (parse-call-args)))
|
||||||
(parse-prop-chain (list (quote method-call) base args)))
|
(parse-prop-chain
|
||||||
base))))
|
(hs-ast-wrap
|
||||||
|
(list (quote method-call) base args)
|
||||||
|
"call" base-start (prev-end) base-line {:root base})))
|
||||||
|
base)))))
|
||||||
(define
|
(define
|
||||||
parse-trav
|
parse-trav
|
||||||
(fn
|
(fn
|
||||||
@@ -124,8 +142,12 @@
|
|||||||
(let
|
(let
|
||||||
((typ (tp-type)) (val (tp-val)))
|
((typ (tp-type)) (val (tp-val)))
|
||||||
(cond
|
(cond
|
||||||
((= typ "number") (do (adv!) (parse-dur val)))
|
((= typ "number")
|
||||||
((= typ "string") (do (adv!) val))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (parse-dur val) "number" s (prev-end) l {}))))
|
||||||
|
((= typ "string")
|
||||||
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap val "string" s (prev-end) l {}))))
|
||||||
((= typ "template") (do (adv!) (list (quote template) val)))
|
((= typ "template") (do (adv!) (list (quote template) val)))
|
||||||
((and (= typ "keyword") (= val "true")) (do (adv!) true))
|
((and (= typ "keyword") (= val "true")) (do (adv!) true))
|
||||||
((and (= typ "keyword") (= val "false")) (do (adv!) false))
|
((and (= typ "keyword") (= val "false")) (do (adv!) false))
|
||||||
@@ -190,10 +212,13 @@
|
|||||||
((and (= typ "keyword") (= val "last"))
|
((and (= typ "keyword") (= val "last"))
|
||||||
(do (adv!) (parse-pos-kw (quote last))))
|
(do (adv!) (parse-pos-kw (quote last))))
|
||||||
((= typ "id")
|
((= typ "id")
|
||||||
(do (adv!) (list (quote query) (str "#" val))))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (list (quote query) (str "#" val)) "selector" s (prev-end) l {}))))
|
||||||
((= typ "selector")
|
((= typ "selector")
|
||||||
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
(do
|
(do
|
||||||
(adv!)
|
(adv!)
|
||||||
|
(hs-ast-wrap
|
||||||
(if
|
(if
|
||||||
(and (= (tp-type) "keyword") (= (tp-val) "in"))
|
(and (= (tp-type) "keyword") (= (tp-val) "in"))
|
||||||
(do
|
(do
|
||||||
@@ -202,7 +227,8 @@
|
|||||||
(quote query-scoped)
|
(quote query-scoped)
|
||||||
val
|
val
|
||||||
(parse-cmp (parse-arith (parse-poss (parse-atom))))))
|
(parse-cmp (parse-arith (parse-poss (parse-atom))))))
|
||||||
(list (quote query) val))))
|
(list (quote query) val))
|
||||||
|
"selector" s (prev-end) l {}))))
|
||||||
((= typ "attr")
|
((= typ "attr")
|
||||||
(do (adv!) (list (quote attr) val (list (quote me)))))
|
(do (adv!) (list (quote attr) val (list (quote me)))))
|
||||||
((= typ "style")
|
((= typ "style")
|
||||||
@@ -219,8 +245,11 @@
|
|||||||
(adv!)
|
(adv!)
|
||||||
(list (quote dom-ref) name (list (quote me)))))))
|
(list (quote dom-ref) name (list (quote me)))))))
|
||||||
((= typ "class")
|
((= typ "class")
|
||||||
(do (adv!) (list (quote query) (str "." val))))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
((= typ "ident") (do (adv!) (list (quote ref) val)))
|
(do (adv!) (hs-ast-wrap (list (quote query) (str "." val)) "selector" s (prev-end) l {}))))
|
||||||
|
((= typ "ident")
|
||||||
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (list (quote ref) val) "ref" s (prev-end) l {}))))
|
||||||
((= typ "paren-open")
|
((= typ "paren-open")
|
||||||
(do
|
(do
|
||||||
(adv!)
|
(adv!)
|
||||||
@@ -2021,7 +2050,11 @@
|
|||||||
((op (cond ((= val "+") (quote +)) ((= val "-") (quote -)) ((= val "*") (quote *)) ((= val "/") (quote /)) ((or (= val "%") (= val "mod")) (make-symbol "%")))))
|
((op (cond ((= val "+") (quote +)) ((= val "-") (quote -)) ((= val "*") (quote *)) ((= val "/") (quote /)) ((or (= val "%") (= val "mod")) (make-symbol "%")))))
|
||||||
(let
|
(let
|
||||||
((right (let ((a (parse-atom))) (if (nil? a) a (parse-poss a)))))
|
((right (let ((a (parse-atom))) (if (nil? a) a (parse-poss a)))))
|
||||||
(parse-arith (list op left right)))))
|
(let
|
||||||
|
((lhs-start (if (and (dict? left) (get left :hs-ast)) (get left :start) 0))
|
||||||
|
(lhs-line (if (and (dict? left) (get left :hs-ast)) (get left :line) 1)))
|
||||||
|
(parse-arith
|
||||||
|
(hs-ast-wrap (list op left right) "arith" lhs-start (prev-end) lhs-line {:lhs left :rhs right}))))))
|
||||||
left))))
|
left))))
|
||||||
(define
|
(define
|
||||||
parse-the-expr
|
parse-the-expr
|
||||||
@@ -2421,7 +2454,15 @@
|
|||||||
((and (= typ "keyword") (= val "put"))
|
((and (= typ "keyword") (= val "put"))
|
||||||
(do (adv!) (parse-put-cmd)))
|
(do (adv!) (parse-put-cmd)))
|
||||||
((and (= typ "keyword") (= val "if"))
|
((and (= typ "keyword") (= val "if"))
|
||||||
(do (adv!) (parse-if-cmd)))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do
|
||||||
|
(adv!)
|
||||||
|
(let ((r (parse-if-cmd)))
|
||||||
|
(let ((tb (if (and (list? r) (> (len r) 2)) (nth r 2) nil)))
|
||||||
|
(hs-ast-wrap r "if" s (prev-end) l
|
||||||
|
(if tb
|
||||||
|
{:true-branch (if (and (list? tb) (= (first tb) (quote do))) (nth tb 1) tb)}
|
||||||
|
{})))))))
|
||||||
((and (= typ "keyword") (= val "wait"))
|
((and (= typ "keyword") (= val "wait"))
|
||||||
(do (adv!) (parse-wait-cmd)))
|
(do (adv!) (parse-wait-cmd)))
|
||||||
((and (= typ "keyword") (= val "send"))
|
((and (= typ "keyword") (= val "send"))
|
||||||
@@ -2429,7 +2470,8 @@
|
|||||||
((and (= typ "keyword") (= val "trigger"))
|
((and (= typ "keyword") (= val "trigger"))
|
||||||
(do (adv!) (parse-trigger-cmd)))
|
(do (adv!) (parse-trigger-cmd)))
|
||||||
((and (= typ "keyword") (= val "log"))
|
((and (= typ "keyword") (= val "log"))
|
||||||
(do (adv!) (parse-log-cmd)))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (parse-log-cmd) "cmd" s (prev-end) l {}))))
|
||||||
((and (= typ "keyword") (= val "increment"))
|
((and (= typ "keyword") (= val "increment"))
|
||||||
(do (adv!) (parse-inc-cmd)))
|
(do (adv!) (parse-inc-cmd)))
|
||||||
((and (= typ "keyword") (= val "decrement"))
|
((and (= typ "keyword") (= val "decrement"))
|
||||||
@@ -2469,7 +2511,8 @@
|
|||||||
((and (= typ "keyword") (= val "tell"))
|
((and (= typ "keyword") (= val "tell"))
|
||||||
(do (adv!) (parse-tell-cmd)))
|
(do (adv!) (parse-tell-cmd)))
|
||||||
((and (= typ "keyword") (= val "for"))
|
((and (= typ "keyword") (= val "for"))
|
||||||
(do (adv!) (parse-for-cmd)))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (parse-for-cmd) "cmd" s (prev-end) l {}))))
|
||||||
((and (= typ "keyword") (= val "make"))
|
((and (= typ "keyword") (= val "make"))
|
||||||
(do (adv!) (parse-make-cmd)))
|
(do (adv!) (parse-make-cmd)))
|
||||||
((and (= typ "keyword") (= val "install"))
|
((and (= typ "keyword") (= val "install"))
|
||||||
@@ -2591,13 +2634,31 @@
|
|||||||
(true acc2)))))))
|
(true acc2)))))))
|
||||||
(let
|
(let
|
||||||
((cmds (cl-collect (list))))
|
((cmds (cl-collect (list))))
|
||||||
|
(define
|
||||||
|
link-next-cmds
|
||||||
|
(fn
|
||||||
|
(cmds-list)
|
||||||
|
(define
|
||||||
|
loop
|
||||||
|
(fn
|
||||||
|
(i)
|
||||||
|
(when (< i (- (len cmds-list) 1))
|
||||||
|
(let
|
||||||
|
((cur-node (nth cmds-list i)) (nxt-node (nth cmds-list (+ i 1))))
|
||||||
|
(when (and (dict? cur-node) (get cur-node :hs-ast))
|
||||||
|
(dict-set! (get cur-node :fields) "next" nxt-node)))
|
||||||
|
(loop (+ i 1)))))
|
||||||
|
(loop 0)
|
||||||
|
cmds-list))
|
||||||
|
(let
|
||||||
|
((linked (if hs-span-mode (link-next-cmds cmds) cmds)))
|
||||||
(cond
|
(cond
|
||||||
((= (len cmds) 0) nil)
|
((= (len linked) 0) nil)
|
||||||
((= (len cmds) 1) (first cmds))
|
((= (len linked) 1) (first linked))
|
||||||
(true
|
(true
|
||||||
(cons
|
(cons
|
||||||
(quote do)
|
(quote do)
|
||||||
(filter (fn (c) (not (= c (quote __then__)))) cmds)))))))
|
(filter (fn (c) (not (= c (quote __then__)))) linked))))))))
|
||||||
(define
|
(define
|
||||||
parse-on-feat
|
parse-on-feat
|
||||||
(fn
|
(fn
|
||||||
@@ -2749,6 +2810,7 @@
|
|||||||
((= val "behavior") (do (adv!) (parse-behavior-feat)))
|
((= val "behavior") (do (adv!) (parse-behavior-feat)))
|
||||||
((= val "live") (do (adv!) (parse-live-feat)))
|
((= val "live") (do (adv!) (parse-live-feat)))
|
||||||
((= val "when") (do (adv!) (parse-when-feat)))
|
((= val "when") (do (adv!) (parse-when-feat)))
|
||||||
|
((= val "worker") (error "worker plugin is not installed — see https://hyperscript.org/features/worker"))
|
||||||
(true (parse-cmd-list))))))
|
(true (parse-cmd-list))))))
|
||||||
(define
|
(define
|
||||||
coll-feats
|
coll-feats
|
||||||
@@ -2767,4 +2829,12 @@
|
|||||||
(first features)
|
(first features)
|
||||||
(cons (quote do) features))))))
|
(cons (quote do) features))))))
|
||||||
|
|
||||||
|
(define hs-span-mode false)
|
||||||
|
|
||||||
(define hs-compile (fn (src) (hs-parse (hs-tokenize src) src)))
|
(define hs-compile (fn (src) (hs-parse (hs-tokenize src) src)))
|
||||||
|
|
||||||
|
(define hs-parse-ast
|
||||||
|
(fn (src)
|
||||||
|
(set! hs-span-mode true)
|
||||||
|
(let ((result (hs-parse (hs-tokenize src) src)))
|
||||||
|
(do (set! hs-span-mode false) result))))
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
(fn
|
(fn
|
||||||
(target event-name handler)
|
(target event-name handler)
|
||||||
(let
|
(let
|
||||||
((wrapped (fn (event) (guard (e ((and (not (= event-name "exception")) (not (= event-name "error"))) (dom-dispatch target "exception" {:error e})) (true (raise e))) (handler event)))))
|
((wrapped (fn (event) (guard (e ((and (not (= event-name "exception")) (not (= event-name "error"))) (dom-dispatch target "exception" {:error e})) (true (raise e))) (do (handler event) (when event (host-call event "stopPropagation")))))))
|
||||||
(let
|
(let
|
||||||
((unlisten (dom-listen target event-name wrapped))
|
((unlisten (dom-listen target event-name wrapped))
|
||||||
(prev (or (dom-get-data target "hs-unlisteners") (list))))
|
(prev (or (dom-get-data target "hs-unlisteners") (list))))
|
||||||
@@ -2525,3 +2525,57 @@
|
|||||||
(fn
|
(fn
|
||||||
(fn-name args)
|
(fn-name args)
|
||||||
(let ((fn (host-global fn-name))) (if fn (host-call-fn fn args) nil))))
|
(let ((fn (host-global fn-name))) (if fn (host-call-fn fn args) nil))))
|
||||||
|
|
||||||
|
;; ── SourceInfo API ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-source-for
|
||||||
|
(fn
|
||||||
|
(node)
|
||||||
|
(substring (get node :src) (get node :start) (get node :end))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-line-for
|
||||||
|
(fn
|
||||||
|
(node)
|
||||||
|
(let
|
||||||
|
((lines (split (get node :src) "\n"))
|
||||||
|
(line-idx (- (get node :line) 1)))
|
||||||
|
(if (< line-idx (len lines)) (nth lines line-idx) ""))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-node-get
|
||||||
|
(fn
|
||||||
|
(node key)
|
||||||
|
(get (get node :fields) key)))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-src
|
||||||
|
(fn (src-str)
|
||||||
|
(hs-source-for (hs-parse-ast src-str))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-src-at
|
||||||
|
(fn
|
||||||
|
(src-str path)
|
||||||
|
(define
|
||||||
|
walk
|
||||||
|
(fn
|
||||||
|
(node keys)
|
||||||
|
(if (or (nil? keys) (= (len keys) 0))
|
||||||
|
node
|
||||||
|
(walk (hs-node-get node (first keys)) (rest keys)))))
|
||||||
|
(hs-source-for (walk (hs-parse-ast src-str) path))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-line-at
|
||||||
|
(fn
|
||||||
|
(src-str path)
|
||||||
|
(define
|
||||||
|
walk
|
||||||
|
(fn
|
||||||
|
(node keys)
|
||||||
|
(if (or (nil? keys) (= (len keys) 0))
|
||||||
|
node
|
||||||
|
(walk (hs-node-get node (first keys)) (rest keys)))))
|
||||||
|
(hs-line-for (walk (hs-parse-ast src-str) path))))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
;; _hyperscript tokenizer — produces token stream from hyperscript source
|
;; _hyperscript tokenizer — produces token stream from hyperscript source
|
||||||
;;
|
;;
|
||||||
;; Tokens: {:type T :value V :pos P}
|
;; Tokens: {:type T :value V :pos P :end E :line L}
|
||||||
;; Types: "keyword" "ident" "number" "string" "class" "id" "attr" "style"
|
;; Types: "keyword" "ident" "number" "string" "class" "id" "attr" "style"
|
||||||
;; "selector" "op" "dot" "paren-open" "paren-close" "bracket-open"
|
;; "selector" "op" "dot" "paren-open" "paren-close" "bracket-open"
|
||||||
;; "bracket-close" "brace-open" "brace-close" "comma" "colon"
|
;; "bracket-close" "brace-open" "brace-close" "comma" "colon"
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
;; ── Token constructor ─────────────────────────────────────────────
|
;; ── Token constructor ─────────────────────────────────────────────
|
||||||
|
|
||||||
(define hs-make-token (fn (type value pos) {:pos pos :value value :type type}))
|
(define hs-make-token (fn (type value pos end line) {:pos pos :end end :line line :value value :type type}))
|
||||||
|
|
||||||
;; ── Character predicates ──────────────────────────────────────────
|
;; ── Character predicates ──────────────────────────────────────────
|
||||||
|
|
||||||
@@ -198,14 +198,22 @@
|
|||||||
(fn
|
(fn
|
||||||
(src)
|
(src)
|
||||||
(let
|
(let
|
||||||
((tokens (list)) (pos 0) (src-len (len src)))
|
((tokens (list)) (pos 0) (src-len (len src)) (current-line 1))
|
||||||
(define
|
(define
|
||||||
hs-peek
|
hs-peek
|
||||||
(fn
|
(fn
|
||||||
(offset)
|
(offset)
|
||||||
(if (< (+ pos offset) src-len) (nth src (+ pos offset)) nil)))
|
(if (< (+ pos offset) src-len) (nth src (+ pos offset)) nil)))
|
||||||
(define hs-cur (fn () (hs-peek 0)))
|
(define hs-cur (fn () (hs-peek 0)))
|
||||||
(define hs-advance! (fn (n) (set! pos (+ pos n))))
|
(define
|
||||||
|
hs-advance!
|
||||||
|
(fn
|
||||||
|
(n)
|
||||||
|
(when
|
||||||
|
(> n 0)
|
||||||
|
(when (= (hs-cur) "\n") (set! current-line (+ current-line 1)))
|
||||||
|
(set! pos (+ pos 1))
|
||||||
|
(hs-advance! (- n 1)))))
|
||||||
(define
|
(define
|
||||||
skip-ws!
|
skip-ws!
|
||||||
(fn
|
(fn
|
||||||
@@ -427,8 +435,8 @@
|
|||||||
(define
|
(define
|
||||||
hs-emit!
|
hs-emit!
|
||||||
(fn
|
(fn
|
||||||
(type value start)
|
(type value start start-line)
|
||||||
(append! tokens (hs-make-token type value start))))
|
(append! tokens (hs-make-token type value start pos start-line))))
|
||||||
(define
|
(define
|
||||||
scan!
|
scan!
|
||||||
(fn
|
(fn
|
||||||
@@ -437,7 +445,7 @@
|
|||||||
(when
|
(when
|
||||||
(< pos src-len)
|
(< pos src-len)
|
||||||
(let
|
(let
|
||||||
((ch (hs-cur)) (start pos))
|
((ch (hs-cur)) (start pos) (start-line current-line))
|
||||||
(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!))
|
||||||
@@ -454,9 +462,9 @@
|
|||||||
(= (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 start-line) (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-advance! 2) (hs-emit! "op" ".." start start-line) (scan!))
|
||||||
(and
|
(and
|
||||||
(= ch ".")
|
(= ch ".")
|
||||||
(< (+ pos 1) src-len)
|
(< (+ pos 1) src-len)
|
||||||
@@ -466,7 +474,7 @@
|
|||||||
(= (hs-peek 1) "_")))
|
(= (hs-peek 1) "_")))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "class" (read-class-name pos) start)
|
(hs-emit! "class" (read-class-name pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "#")
|
(= ch "#")
|
||||||
@@ -474,7 +482,7 @@
|
|||||||
(hs-ident-start? (hs-peek 1)))
|
(hs-ident-start? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "id" (read-ident pos) start)
|
(hs-emit! "id" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "@")
|
(= ch "@")
|
||||||
@@ -482,7 +490,7 @@
|
|||||||
(hs-ident-char? (hs-peek 1)))
|
(hs-ident-char? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "attr" (read-ident pos) start)
|
(hs-emit! "attr" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "^")
|
(= ch "^")
|
||||||
@@ -490,7 +498,7 @@
|
|||||||
(hs-ident-char? (hs-peek 1)))
|
(hs-ident-char? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "hat" (read-ident pos) start)
|
(hs-emit! "hat" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "~")
|
(= ch "~")
|
||||||
@@ -498,7 +506,7 @@
|
|||||||
(hs-letter? (hs-peek 1)))
|
(hs-letter? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "component" (str "~" (read-ident pos)) start)
|
(hs-emit! "component" (str "~" (read-ident pos)) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "*")
|
(= ch "*")
|
||||||
@@ -506,7 +514,7 @@
|
|||||||
(hs-letter? (hs-peek 1)))
|
(hs-letter? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "style" (read-ident pos) start)
|
(hs-emit! "style" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch ":")
|
(= ch ":")
|
||||||
@@ -514,7 +522,7 @@
|
|||||||
(hs-ident-start? (hs-peek 1)))
|
(hs-ident-start? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "local" (read-ident pos) start)
|
(hs-emit! "local" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(or
|
(or
|
||||||
(= ch "\"")
|
(= ch "\"")
|
||||||
@@ -527,11 +535,11 @@
|
|||||||
(or
|
(or
|
||||||
(>= (+ pos 2) src-len)
|
(>= (+ pos 2) src-len)
|
||||||
(not (hs-ident-char? (hs-peek 2))))))))
|
(not (hs-ident-char? (hs-peek 2))))))))
|
||||||
(do (hs-emit! "string" (read-string ch) start) (scan!))
|
(do (hs-emit! "string" (read-string ch) start start-line) (scan!))
|
||||||
(= ch "`")
|
(= ch "`")
|
||||||
(do (hs-emit! "template" (read-template) start) (scan!))
|
(do (hs-emit! "template" (read-template) start start-line) (scan!))
|
||||||
(hs-digit? ch)
|
(hs-digit? ch)
|
||||||
(do (hs-emit! "number" (read-number start) start) (scan!))
|
(do (hs-emit! "number" (read-number start) start start-line) (scan!))
|
||||||
(hs-ident-start? ch)
|
(hs-ident-start? ch)
|
||||||
(do
|
(do
|
||||||
(let
|
(let
|
||||||
@@ -539,7 +547,8 @@
|
|||||||
(hs-emit!
|
(hs-emit!
|
||||||
(if (hs-keyword? word) "keyword" "ident")
|
(if (hs-keyword? word) "keyword" "ident")
|
||||||
word
|
word
|
||||||
start))
|
start
|
||||||
|
start-line))
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(or (= ch "=") (= ch "!") (= ch "<") (= ch ">"))
|
(or (= ch "=") (= ch "!") (= ch "<") (= ch ">"))
|
||||||
@@ -551,8 +560,8 @@
|
|||||||
(or (= ch "=") (= ch "!"))
|
(or (= ch "=") (= ch "!"))
|
||||||
(< (+ pos 2) src-len)
|
(< (+ pos 2) src-len)
|
||||||
(= (hs-peek 2) "="))
|
(= (hs-peek 2) "="))
|
||||||
(do (hs-emit! "op" (str ch "==") start) (hs-advance! 3))
|
(do (hs-advance! 3) (hs-emit! "op" (str ch "==") start start-line))
|
||||||
(do (hs-emit! "op" (str ch "=") start) (hs-advance! 2)))
|
(do (hs-advance! 2) (hs-emit! "op" (str ch "=") start start-line)))
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "'")
|
(= ch "'")
|
||||||
@@ -561,66 +570,66 @@
|
|||||||
(or
|
(or
|
||||||
(>= (+ pos 2) src-len)
|
(>= (+ pos 2) src-len)
|
||||||
(not (hs-ident-char? (hs-peek 2)))))
|
(not (hs-ident-char? (hs-peek 2)))))
|
||||||
(do (hs-emit! "op" "'s" start) (hs-advance! 2) (scan!))
|
(do (hs-advance! 2) (hs-emit! "op" "'s" start start-line) (scan!))
|
||||||
(= ch "(")
|
(= ch "(")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "paren-open" "(" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "paren-open" "(" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch ")")
|
(= ch ")")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "paren-close" ")" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "paren-close" ")" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch "[")
|
(= ch "[")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "bracket-open" "[" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "bracket-open" "[" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch "]")
|
(= ch "]")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "bracket-close" "]" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "bracket-close" "]" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch "{")
|
(= ch "{")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "brace-open" "{" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "brace-open" "{" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch "}")
|
(= ch "}")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "brace-close" "}" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "brace-close" "}" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch ",")
|
(= ch ",")
|
||||||
(do (hs-emit! "comma" "," start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "comma" "," start start-line) (scan!))
|
||||||
(= ch "+")
|
(= ch "+")
|
||||||
(do (hs-emit! "op" "+" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "+" start start-line) (scan!))
|
||||||
(= ch "-")
|
(= ch "-")
|
||||||
(do (hs-emit! "op" "-" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "-" start start-line) (scan!))
|
||||||
(= ch "/")
|
(= ch "/")
|
||||||
(do (hs-emit! "op" "/" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "/" start start-line) (scan!))
|
||||||
(= ch "=")
|
(= ch "=")
|
||||||
(do (hs-emit! "op" "=" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "=" start start-line) (scan!))
|
||||||
(= ch "<")
|
(= ch "<")
|
||||||
(do (hs-emit! "op" "<" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "<" start start-line) (scan!))
|
||||||
(= ch ">")
|
(= ch ">")
|
||||||
(do (hs-emit! "op" ">" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" ">" start start-line) (scan!))
|
||||||
(= ch "!")
|
(= ch "!")
|
||||||
(do (hs-emit! "op" "!" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "!" start start-line) (scan!))
|
||||||
(= ch "*")
|
(= ch "*")
|
||||||
(do (hs-emit! "op" "*" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "*" start start-line) (scan!))
|
||||||
(= ch "%")
|
(= ch "%")
|
||||||
(do (hs-emit! "op" "%" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "%" start start-line) (scan!))
|
||||||
(= ch ".")
|
(= ch ".")
|
||||||
(do (hs-emit! "dot" "." start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "dot" "." start start-line) (scan!))
|
||||||
(= ch "\\")
|
(= ch "\\")
|
||||||
(do (hs-emit! "op" "\\" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "\\" start start-line) (scan!))
|
||||||
(= ch ":")
|
(= ch ":")
|
||||||
(do (hs-emit! "colon" ":" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "colon" ":" start start-line) (scan!))
|
||||||
(= ch "|")
|
(= ch "|")
|
||||||
(do (hs-emit! "op" "|" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "|" start start-line) (scan!))
|
||||||
:else (do (hs-advance! 1) (scan!)))))))
|
:else (do (hs-advance! 1) (scan!)))))))
|
||||||
(scan!)
|
(scan!)
|
||||||
(hs-emit! "eof" nil pos)
|
(hs-emit! "eof" nil pos current-line)
|
||||||
tokens)))
|
tokens)))
|
||||||
@@ -4,7 +4,7 @@ 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: 1303/1496 (87.1%) delta +90
|
Merged: 1306/1496 (87.3%) delta +93
|
||||||
Worktree: all landed
|
Worktree: all landed
|
||||||
Target: 1496/1496 (100.0%)
|
Target: 1496/1496 (100.0%)
|
||||||
Remaining: ~194 tests (clusters 17/29(partial)/31 blocked; 33/34 partial)
|
Remaining: ~194 tests (clusters 17/29(partial)/31 blocked; 33/34 partial)
|
||||||
@@ -22,7 +22,7 @@ Remaining: ~194 tests (clusters 17/29(partial)/31 blocked; 33/34 partial)
|
|||||||
| 4 | `not` precedence over `or` | done | +3 | 4fe0b649 |
|
| 4 | `not` precedence over `or` | done | +3 | 4fe0b649 |
|
||||||
| 5 | `some` selector for nonempty match | done | +1 | e7b86264 |
|
| 5 | `some` selector for nonempty match | done | +1 | e7b86264 |
|
||||||
| 6 | string template `${x}` | done | +2 | 108e25d4 |
|
| 6 | string template `${x}` | done | +2 | 108e25d4 |
|
||||||
| 7 | `put` hyperscript reprocessing | partial | +1 | f21eb008 |
|
| 7 | `put` hyperscript reprocessing | partial | +4 | d663c91f |
|
||||||
| 8 | `select` returns selected text | done | +1 | d862efe8 |
|
| 8 | `select` returns selected text | done | +1 | d862efe8 |
|
||||||
| 9 | `wait on event` basics | done | +4 | f79f96c1 |
|
| 9 | `wait on event` basics | done | +4 | f79f96c1 |
|
||||||
| 10 | `swap` variable ↔ property | done | +1 | 30f33341 |
|
| 10 | `swap` variable ↔ property | done | +1 | 30f33341 |
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ Orchestrator cherry-picks worktree commits onto `architecture` one at a time; re
|
|||||||
|
|
||||||
6. **[done (+2)] string template `${x}`** — `expressions/strings / string templates work w/ props` + `w/ braces` (2 tests). Template interpolation isn't substituting property accesses. Check `hs-template` runtime. Expected: +2.
|
6. **[done (+2)] string template `${x}`** — `expressions/strings / string templates work w/ props` + `w/ braces` (2 tests). Template interpolation isn't substituting property accesses. Check `hs-template` runtime. Expected: +2.
|
||||||
|
|
||||||
7. **[done (+1) — partial, 3 tests remain: inserted-button handler doesn't fire for afterbegin/innerHTML paths; might need targeted trace of hs-boot-subtree! or _setInnerHTML timing] `put` hyperscript reprocessing** — `put / properly processes hyperscript at end/start/content/symbol` (4 tests, all `Expected 42, got 40`). After a put operation, newly inserted HS scripts aren't being activated. Fix: `hs-put-at!` should `hs-boot-subtree!` on the target after DOM insertion. Expected: +4.
|
7. **[done (+4) — partial, 1 test remains: "waits on promises" (async/Promise resolution)] `put` hyperscript reprocessing** — `put / properly processes hyperscript at end/start/content/symbol` (4 tests, all `Expected 42, got 40`). After a put operation, newly inserted HS scripts aren't being activated. Fix: `hs-put-at!` should `hs-boot-subtree!` on the target after DOM insertion. Expected: +4.
|
||||||
|
|
||||||
8. **[done (+1)] `select returns selected text`** (1 test, `hs-upstream-select`). Runtime `hs-get-selection` helper reads `window.__test_selection` stash (or falls back to real `window.getSelection().toString()`). Compiler rewrites `(ref "selection")` to `(hs-get-selection)`. Generator detects the `createRange` / `setStart` / `setEnd` / `addRange` block and emits a single `(host-set! ... __test_selection ...)` op with the resolved text slice of the target element. Expected: +1.
|
8. **[done (+1)] `select returns selected text`** (1 test, `hs-upstream-select`). Runtime `hs-get-selection` helper reads `window.__test_selection` stash (or falls back to real `window.getSelection().toString()`). Compiler rewrites `(ref "selection")` to `(hs-get-selection)`. Generator detects the `createRange` / `setStart` / `setEnd` / `addRange` block and emits a single `(host-set! ... __test_selection ...)` op with the resolved text slice of the target element. Expected: +1.
|
||||||
|
|
||||||
@@ -175,6 +175,9 @@ Many tests are `SKIP (untranslated)` because `tests/playwright/generate-sx-tests
|
|||||||
|
|
||||||
## Progress log
|
## Progress log
|
||||||
|
|
||||||
|
### 2026-04-26 — cluster 7 put hyperscript reprocessing (partial +3 more)
|
||||||
|
- **d663c91f** — `hs: stop event propagation after each hs-on handler fires (+3 tests)`. Root cause: click events bubble from b1 (inside d1) to d1, causing d1's `on click put ...` handler to re-fire and replace the just-modified b1 with fresh content (text=40). Fix: `hs-on`'s wrapped handler now calls `event.stopPropagation()` after each handler runs, preventing the bubbled click from reaching ancestor HS listeners. Tests 1147/1149/1150 now pass. Suite hs-upstream-put: 34/38 → 37/38. Smoke 0-195: 173/195 unchanged. One test remains: "waits on promises" (async/Promise issue).
|
||||||
|
|
||||||
(Reverse chronological — newest at top.)
|
(Reverse chronological — newest at top.)
|
||||||
|
|
||||||
### 2026-04-25 — Bucket F: in-expression filter semantics (+1)
|
### 2026-04-25 — Bucket F: in-expression filter semantics (+1)
|
||||||
|
|||||||
@@ -789,6 +789,7 @@
|
|||||||
(cons (quote do) (map hs-to-sx body)))))))
|
(cons (quote do) (map hs-to-sx body)))))))
|
||||||
(fn
|
(fn
|
||||||
(ast)
|
(ast)
|
||||||
|
(let ((ast (if (and (dict? ast) (get ast :hs-ast)) (get ast :children) ast)))
|
||||||
(cond
|
(cond
|
||||||
((nil? ast) nil)
|
((nil? ast) nil)
|
||||||
((number? ast) ast)
|
((number? ast) ast)
|
||||||
@@ -2207,7 +2208,7 @@
|
|||||||
(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))))
|
||||||
(true ast))))))))
|
(true ast)))))))))
|
||||||
|
|
||||||
;; ── Convenience: source → SX ─────────────────────────────────
|
;; ── Convenience: source → SX ─────────────────────────────────
|
||||||
(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))))
|
||||||
@@ -21,6 +21,15 @@
|
|||||||
adv!
|
adv!
|
||||||
(fn () (let ((t (nth tokens p))) (set! p (+ p 1)) t)))
|
(fn () (let ((t (nth tokens p))) (set! p (+ p 1)) t)))
|
||||||
(define at-end? (fn () (or (>= p tok-len) (= (tp-type) "eof"))))
|
(define at-end? (fn () (or (>= p tok-len) (= (tp-type) "eof"))))
|
||||||
|
(define cur-start (fn () (if (< p tok-len) (get (tp) "pos") 0)))
|
||||||
|
(define cur-line (fn () (if (< p tok-len) (get (tp) "line") 1)))
|
||||||
|
(define prev-end (fn () (if (> p 0) (get (nth tokens (- p 1)) "end") 0)))
|
||||||
|
(define hs-ast-wrap
|
||||||
|
(fn (raw kind start end-pos line fields)
|
||||||
|
(if hs-span-mode
|
||||||
|
{:hs-ast true :kind kind :start start :end end-pos :line line
|
||||||
|
:src src :children raw :fields fields}
|
||||||
|
raw)))
|
||||||
(define
|
(define
|
||||||
match-kw
|
match-kw
|
||||||
(fn
|
(fn
|
||||||
@@ -69,19 +78,28 @@
|
|||||||
parse-prop-chain
|
parse-prop-chain
|
||||||
(fn
|
(fn
|
||||||
(base)
|
(base)
|
||||||
|
(let
|
||||||
|
((base-start (if (and (dict? base) (get base :hs-ast)) (get base :start) (cur-start)))
|
||||||
|
(base-line (if (and (dict? base) (get base :hs-ast)) (get base :line) (cur-line))))
|
||||||
(if
|
(if
|
||||||
(and (= (tp-type) "class") (not (at-end?)))
|
(and (= (tp-type) "class") (not (at-end?)))
|
||||||
(let
|
(let
|
||||||
((prop (tp-val)))
|
((prop (tp-val)))
|
||||||
(do
|
(do
|
||||||
(adv!)
|
(adv!)
|
||||||
(parse-prop-chain (list (make-symbol ".") base prop))))
|
(parse-prop-chain
|
||||||
|
(hs-ast-wrap
|
||||||
|
(list (make-symbol ".") base prop)
|
||||||
|
"member" base-start (prev-end) base-line {:root base}))))
|
||||||
(if
|
(if
|
||||||
(= (tp-type) "paren-open")
|
(= (tp-type) "paren-open")
|
||||||
(let
|
(let
|
||||||
((args (parse-call-args)))
|
((args (parse-call-args)))
|
||||||
(parse-prop-chain (list (quote method-call) base args)))
|
(parse-prop-chain
|
||||||
base))))
|
(hs-ast-wrap
|
||||||
|
(list (quote method-call) base args)
|
||||||
|
"call" base-start (prev-end) base-line {:root base})))
|
||||||
|
base)))))
|
||||||
(define
|
(define
|
||||||
parse-trav
|
parse-trav
|
||||||
(fn
|
(fn
|
||||||
@@ -124,8 +142,12 @@
|
|||||||
(let
|
(let
|
||||||
((typ (tp-type)) (val (tp-val)))
|
((typ (tp-type)) (val (tp-val)))
|
||||||
(cond
|
(cond
|
||||||
((= typ "number") (do (adv!) (parse-dur val)))
|
((= typ "number")
|
||||||
((= typ "string") (do (adv!) val))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (parse-dur val) "number" s (prev-end) l {}))))
|
||||||
|
((= typ "string")
|
||||||
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap val "string" s (prev-end) l {}))))
|
||||||
((= typ "template") (do (adv!) (list (quote template) val)))
|
((= typ "template") (do (adv!) (list (quote template) val)))
|
||||||
((and (= typ "keyword") (= val "true")) (do (adv!) true))
|
((and (= typ "keyword") (= val "true")) (do (adv!) true))
|
||||||
((and (= typ "keyword") (= val "false")) (do (adv!) false))
|
((and (= typ "keyword") (= val "false")) (do (adv!) false))
|
||||||
@@ -190,10 +212,13 @@
|
|||||||
((and (= typ "keyword") (= val "last"))
|
((and (= typ "keyword") (= val "last"))
|
||||||
(do (adv!) (parse-pos-kw (quote last))))
|
(do (adv!) (parse-pos-kw (quote last))))
|
||||||
((= typ "id")
|
((= typ "id")
|
||||||
(do (adv!) (list (quote query) (str "#" val))))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (list (quote query) (str "#" val)) "selector" s (prev-end) l {}))))
|
||||||
((= typ "selector")
|
((= typ "selector")
|
||||||
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
(do
|
(do
|
||||||
(adv!)
|
(adv!)
|
||||||
|
(hs-ast-wrap
|
||||||
(if
|
(if
|
||||||
(and (= (tp-type) "keyword") (= (tp-val) "in"))
|
(and (= (tp-type) "keyword") (= (tp-val) "in"))
|
||||||
(do
|
(do
|
||||||
@@ -202,7 +227,8 @@
|
|||||||
(quote query-scoped)
|
(quote query-scoped)
|
||||||
val
|
val
|
||||||
(parse-cmp (parse-arith (parse-poss (parse-atom))))))
|
(parse-cmp (parse-arith (parse-poss (parse-atom))))))
|
||||||
(list (quote query) val))))
|
(list (quote query) val))
|
||||||
|
"selector" s (prev-end) l {}))))
|
||||||
((= typ "attr")
|
((= typ "attr")
|
||||||
(do (adv!) (list (quote attr) val (list (quote me)))))
|
(do (adv!) (list (quote attr) val (list (quote me)))))
|
||||||
((= typ "style")
|
((= typ "style")
|
||||||
@@ -219,8 +245,11 @@
|
|||||||
(adv!)
|
(adv!)
|
||||||
(list (quote dom-ref) name (list (quote me)))))))
|
(list (quote dom-ref) name (list (quote me)))))))
|
||||||
((= typ "class")
|
((= typ "class")
|
||||||
(do (adv!) (list (quote query) (str "." val))))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
((= typ "ident") (do (adv!) (list (quote ref) val)))
|
(do (adv!) (hs-ast-wrap (list (quote query) (str "." val)) "selector" s (prev-end) l {}))))
|
||||||
|
((= typ "ident")
|
||||||
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (list (quote ref) val) "ref" s (prev-end) l {}))))
|
||||||
((= typ "paren-open")
|
((= typ "paren-open")
|
||||||
(do
|
(do
|
||||||
(adv!)
|
(adv!)
|
||||||
@@ -2021,7 +2050,11 @@
|
|||||||
((op (cond ((= val "+") (quote +)) ((= val "-") (quote -)) ((= val "*") (quote *)) ((= val "/") (quote /)) ((or (= val "%") (= val "mod")) (make-symbol "%")))))
|
((op (cond ((= val "+") (quote +)) ((= val "-") (quote -)) ((= val "*") (quote *)) ((= val "/") (quote /)) ((or (= val "%") (= val "mod")) (make-symbol "%")))))
|
||||||
(let
|
(let
|
||||||
((right (let ((a (parse-atom))) (if (nil? a) a (parse-poss a)))))
|
((right (let ((a (parse-atom))) (if (nil? a) a (parse-poss a)))))
|
||||||
(parse-arith (list op left right)))))
|
(let
|
||||||
|
((lhs-start (if (and (dict? left) (get left :hs-ast)) (get left :start) 0))
|
||||||
|
(lhs-line (if (and (dict? left) (get left :hs-ast)) (get left :line) 1)))
|
||||||
|
(parse-arith
|
||||||
|
(hs-ast-wrap (list op left right) "arith" lhs-start (prev-end) lhs-line {:lhs left :rhs right}))))))
|
||||||
left))))
|
left))))
|
||||||
(define
|
(define
|
||||||
parse-the-expr
|
parse-the-expr
|
||||||
@@ -2421,7 +2454,15 @@
|
|||||||
((and (= typ "keyword") (= val "put"))
|
((and (= typ "keyword") (= val "put"))
|
||||||
(do (adv!) (parse-put-cmd)))
|
(do (adv!) (parse-put-cmd)))
|
||||||
((and (= typ "keyword") (= val "if"))
|
((and (= typ "keyword") (= val "if"))
|
||||||
(do (adv!) (parse-if-cmd)))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do
|
||||||
|
(adv!)
|
||||||
|
(let ((r (parse-if-cmd)))
|
||||||
|
(let ((tb (if (and (list? r) (> (len r) 2)) (nth r 2) nil)))
|
||||||
|
(hs-ast-wrap r "if" s (prev-end) l
|
||||||
|
(if tb
|
||||||
|
{:true-branch (if (and (list? tb) (= (first tb) (quote do))) (nth tb 1) tb)}
|
||||||
|
{})))))))
|
||||||
((and (= typ "keyword") (= val "wait"))
|
((and (= typ "keyword") (= val "wait"))
|
||||||
(do (adv!) (parse-wait-cmd)))
|
(do (adv!) (parse-wait-cmd)))
|
||||||
((and (= typ "keyword") (= val "send"))
|
((and (= typ "keyword") (= val "send"))
|
||||||
@@ -2429,7 +2470,8 @@
|
|||||||
((and (= typ "keyword") (= val "trigger"))
|
((and (= typ "keyword") (= val "trigger"))
|
||||||
(do (adv!) (parse-trigger-cmd)))
|
(do (adv!) (parse-trigger-cmd)))
|
||||||
((and (= typ "keyword") (= val "log"))
|
((and (= typ "keyword") (= val "log"))
|
||||||
(do (adv!) (parse-log-cmd)))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (parse-log-cmd) "cmd" s (prev-end) l {}))))
|
||||||
((and (= typ "keyword") (= val "increment"))
|
((and (= typ "keyword") (= val "increment"))
|
||||||
(do (adv!) (parse-inc-cmd)))
|
(do (adv!) (parse-inc-cmd)))
|
||||||
((and (= typ "keyword") (= val "decrement"))
|
((and (= typ "keyword") (= val "decrement"))
|
||||||
@@ -2469,7 +2511,8 @@
|
|||||||
((and (= typ "keyword") (= val "tell"))
|
((and (= typ "keyword") (= val "tell"))
|
||||||
(do (adv!) (parse-tell-cmd)))
|
(do (adv!) (parse-tell-cmd)))
|
||||||
((and (= typ "keyword") (= val "for"))
|
((and (= typ "keyword") (= val "for"))
|
||||||
(do (adv!) (parse-for-cmd)))
|
(let ((s (cur-start)) (l (cur-line)))
|
||||||
|
(do (adv!) (hs-ast-wrap (parse-for-cmd) "cmd" s (prev-end) l {}))))
|
||||||
((and (= typ "keyword") (= val "make"))
|
((and (= typ "keyword") (= val "make"))
|
||||||
(do (adv!) (parse-make-cmd)))
|
(do (adv!) (parse-make-cmd)))
|
||||||
((and (= typ "keyword") (= val "install"))
|
((and (= typ "keyword") (= val "install"))
|
||||||
@@ -2591,13 +2634,31 @@
|
|||||||
(true acc2)))))))
|
(true acc2)))))))
|
||||||
(let
|
(let
|
||||||
((cmds (cl-collect (list))))
|
((cmds (cl-collect (list))))
|
||||||
|
(define
|
||||||
|
link-next-cmds
|
||||||
|
(fn
|
||||||
|
(cmds-list)
|
||||||
|
(define
|
||||||
|
loop
|
||||||
|
(fn
|
||||||
|
(i)
|
||||||
|
(when (< i (- (len cmds-list) 1))
|
||||||
|
(let
|
||||||
|
((cur-node (nth cmds-list i)) (nxt-node (nth cmds-list (+ i 1))))
|
||||||
|
(when (and (dict? cur-node) (get cur-node :hs-ast))
|
||||||
|
(dict-set! (get cur-node :fields) "next" nxt-node)))
|
||||||
|
(loop (+ i 1)))))
|
||||||
|
(loop 0)
|
||||||
|
cmds-list))
|
||||||
|
(let
|
||||||
|
((linked (if hs-span-mode (link-next-cmds cmds) cmds)))
|
||||||
(cond
|
(cond
|
||||||
((= (len cmds) 0) nil)
|
((= (len linked) 0) nil)
|
||||||
((= (len cmds) 1) (first cmds))
|
((= (len linked) 1) (first linked))
|
||||||
(true
|
(true
|
||||||
(cons
|
(cons
|
||||||
(quote do)
|
(quote do)
|
||||||
(filter (fn (c) (not (= c (quote __then__)))) cmds)))))))
|
(filter (fn (c) (not (= c (quote __then__)))) linked))))))))
|
||||||
(define
|
(define
|
||||||
parse-on-feat
|
parse-on-feat
|
||||||
(fn
|
(fn
|
||||||
@@ -2749,6 +2810,7 @@
|
|||||||
((= val "behavior") (do (adv!) (parse-behavior-feat)))
|
((= val "behavior") (do (adv!) (parse-behavior-feat)))
|
||||||
((= val "live") (do (adv!) (parse-live-feat)))
|
((= val "live") (do (adv!) (parse-live-feat)))
|
||||||
((= val "when") (do (adv!) (parse-when-feat)))
|
((= val "when") (do (adv!) (parse-when-feat)))
|
||||||
|
((= val "worker") (error "worker plugin is not installed — see https://hyperscript.org/features/worker"))
|
||||||
(true (parse-cmd-list))))))
|
(true (parse-cmd-list))))))
|
||||||
(define
|
(define
|
||||||
coll-feats
|
coll-feats
|
||||||
@@ -2767,4 +2829,12 @@
|
|||||||
(first features)
|
(first features)
|
||||||
(cons (quote do) features))))))
|
(cons (quote do) features))))))
|
||||||
|
|
||||||
|
(define hs-span-mode false)
|
||||||
|
|
||||||
(define hs-compile (fn (src) (hs-parse (hs-tokenize src) src)))
|
(define hs-compile (fn (src) (hs-parse (hs-tokenize src) src)))
|
||||||
|
|
||||||
|
(define hs-parse-ast
|
||||||
|
(fn (src)
|
||||||
|
(set! hs-span-mode true)
|
||||||
|
(let ((result (hs-parse (hs-tokenize src) src)))
|
||||||
|
(do (set! hs-span-mode false) result))))
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
(fn
|
(fn
|
||||||
(target event-name handler)
|
(target event-name handler)
|
||||||
(let
|
(let
|
||||||
((wrapped (fn (event) (guard (e ((and (not (= event-name "exception")) (not (= event-name "error"))) (dom-dispatch target "exception" {:error e})) (true (raise e))) (handler event)))))
|
((wrapped (fn (event) (guard (e ((and (not (= event-name "exception")) (not (= event-name "error"))) (dom-dispatch target "exception" {:error e})) (true (raise e))) (do (handler event) (when event (host-call event "stopPropagation")))))))
|
||||||
(let
|
(let
|
||||||
((unlisten (dom-listen target event-name wrapped))
|
((unlisten (dom-listen target event-name wrapped))
|
||||||
(prev (or (dom-get-data target "hs-unlisteners") (list))))
|
(prev (or (dom-get-data target "hs-unlisteners") (list))))
|
||||||
@@ -2525,3 +2525,57 @@
|
|||||||
(fn
|
(fn
|
||||||
(fn-name args)
|
(fn-name args)
|
||||||
(let ((fn (host-global fn-name))) (if fn (host-call-fn fn args) nil))))
|
(let ((fn (host-global fn-name))) (if fn (host-call-fn fn args) nil))))
|
||||||
|
|
||||||
|
;; ── SourceInfo API ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-source-for
|
||||||
|
(fn
|
||||||
|
(node)
|
||||||
|
(substring (get node :src) (get node :start) (get node :end))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-line-for
|
||||||
|
(fn
|
||||||
|
(node)
|
||||||
|
(let
|
||||||
|
((lines (split (get node :src) "\n"))
|
||||||
|
(line-idx (- (get node :line) 1)))
|
||||||
|
(if (< line-idx (len lines)) (nth lines line-idx) ""))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-node-get
|
||||||
|
(fn
|
||||||
|
(node key)
|
||||||
|
(get (get node :fields) key)))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-src
|
||||||
|
(fn (src-str)
|
||||||
|
(hs-source-for (hs-parse-ast src-str))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-src-at
|
||||||
|
(fn
|
||||||
|
(src-str path)
|
||||||
|
(define
|
||||||
|
walk
|
||||||
|
(fn
|
||||||
|
(node keys)
|
||||||
|
(if (or (nil? keys) (= (len keys) 0))
|
||||||
|
node
|
||||||
|
(walk (hs-node-get node (first keys)) (rest keys)))))
|
||||||
|
(hs-source-for (walk (hs-parse-ast src-str) path))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-line-at
|
||||||
|
(fn
|
||||||
|
(src-str path)
|
||||||
|
(define
|
||||||
|
walk
|
||||||
|
(fn
|
||||||
|
(node keys)
|
||||||
|
(if (or (nil? keys) (= (len keys) 0))
|
||||||
|
node
|
||||||
|
(walk (hs-node-get node (first keys)) (rest keys)))))
|
||||||
|
(hs-line-for (walk (hs-parse-ast src-str) path))))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
;; _hyperscript tokenizer — produces token stream from hyperscript source
|
;; _hyperscript tokenizer — produces token stream from hyperscript source
|
||||||
;;
|
;;
|
||||||
;; Tokens: {:type T :value V :pos P}
|
;; Tokens: {:type T :value V :pos P :end E :line L}
|
||||||
;; Types: "keyword" "ident" "number" "string" "class" "id" "attr" "style"
|
;; Types: "keyword" "ident" "number" "string" "class" "id" "attr" "style"
|
||||||
;; "selector" "op" "dot" "paren-open" "paren-close" "bracket-open"
|
;; "selector" "op" "dot" "paren-open" "paren-close" "bracket-open"
|
||||||
;; "bracket-close" "brace-open" "brace-close" "comma" "colon"
|
;; "bracket-close" "brace-open" "brace-close" "comma" "colon"
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
;; ── Token constructor ─────────────────────────────────────────────
|
;; ── Token constructor ─────────────────────────────────────────────
|
||||||
|
|
||||||
(define hs-make-token (fn (type value pos) {:pos pos :value value :type type}))
|
(define hs-make-token (fn (type value pos end line) {:pos pos :end end :line line :value value :type type}))
|
||||||
|
|
||||||
;; ── Character predicates ──────────────────────────────────────────
|
;; ── Character predicates ──────────────────────────────────────────
|
||||||
|
|
||||||
@@ -198,14 +198,22 @@
|
|||||||
(fn
|
(fn
|
||||||
(src)
|
(src)
|
||||||
(let
|
(let
|
||||||
((tokens (list)) (pos 0) (src-len (len src)))
|
((tokens (list)) (pos 0) (src-len (len src)) (current-line 1))
|
||||||
(define
|
(define
|
||||||
hs-peek
|
hs-peek
|
||||||
(fn
|
(fn
|
||||||
(offset)
|
(offset)
|
||||||
(if (< (+ pos offset) src-len) (nth src (+ pos offset)) nil)))
|
(if (< (+ pos offset) src-len) (nth src (+ pos offset)) nil)))
|
||||||
(define hs-cur (fn () (hs-peek 0)))
|
(define hs-cur (fn () (hs-peek 0)))
|
||||||
(define hs-advance! (fn (n) (set! pos (+ pos n))))
|
(define
|
||||||
|
hs-advance!
|
||||||
|
(fn
|
||||||
|
(n)
|
||||||
|
(when
|
||||||
|
(> n 0)
|
||||||
|
(when (= (hs-cur) "\n") (set! current-line (+ current-line 1)))
|
||||||
|
(set! pos (+ pos 1))
|
||||||
|
(hs-advance! (- n 1)))))
|
||||||
(define
|
(define
|
||||||
skip-ws!
|
skip-ws!
|
||||||
(fn
|
(fn
|
||||||
@@ -427,8 +435,8 @@
|
|||||||
(define
|
(define
|
||||||
hs-emit!
|
hs-emit!
|
||||||
(fn
|
(fn
|
||||||
(type value start)
|
(type value start start-line)
|
||||||
(append! tokens (hs-make-token type value start))))
|
(append! tokens (hs-make-token type value start pos start-line))))
|
||||||
(define
|
(define
|
||||||
scan!
|
scan!
|
||||||
(fn
|
(fn
|
||||||
@@ -437,7 +445,7 @@
|
|||||||
(when
|
(when
|
||||||
(< pos src-len)
|
(< pos src-len)
|
||||||
(let
|
(let
|
||||||
((ch (hs-cur)) (start pos))
|
((ch (hs-cur)) (start pos) (start-line current-line))
|
||||||
(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!))
|
||||||
@@ -454,9 +462,9 @@
|
|||||||
(= (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 start-line) (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-advance! 2) (hs-emit! "op" ".." start start-line) (scan!))
|
||||||
(and
|
(and
|
||||||
(= ch ".")
|
(= ch ".")
|
||||||
(< (+ pos 1) src-len)
|
(< (+ pos 1) src-len)
|
||||||
@@ -466,7 +474,7 @@
|
|||||||
(= (hs-peek 1) "_")))
|
(= (hs-peek 1) "_")))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "class" (read-class-name pos) start)
|
(hs-emit! "class" (read-class-name pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "#")
|
(= ch "#")
|
||||||
@@ -474,7 +482,7 @@
|
|||||||
(hs-ident-start? (hs-peek 1)))
|
(hs-ident-start? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "id" (read-ident pos) start)
|
(hs-emit! "id" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "@")
|
(= ch "@")
|
||||||
@@ -482,7 +490,7 @@
|
|||||||
(hs-ident-char? (hs-peek 1)))
|
(hs-ident-char? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "attr" (read-ident pos) start)
|
(hs-emit! "attr" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "^")
|
(= ch "^")
|
||||||
@@ -490,7 +498,7 @@
|
|||||||
(hs-ident-char? (hs-peek 1)))
|
(hs-ident-char? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "hat" (read-ident pos) start)
|
(hs-emit! "hat" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "~")
|
(= ch "~")
|
||||||
@@ -498,7 +506,7 @@
|
|||||||
(hs-letter? (hs-peek 1)))
|
(hs-letter? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "component" (str "~" (read-ident pos)) start)
|
(hs-emit! "component" (str "~" (read-ident pos)) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "*")
|
(= ch "*")
|
||||||
@@ -506,7 +514,7 @@
|
|||||||
(hs-letter? (hs-peek 1)))
|
(hs-letter? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "style" (read-ident pos) start)
|
(hs-emit! "style" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch ":")
|
(= ch ":")
|
||||||
@@ -514,7 +522,7 @@
|
|||||||
(hs-ident-start? (hs-peek 1)))
|
(hs-ident-start? (hs-peek 1)))
|
||||||
(do
|
(do
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
(hs-emit! "local" (read-ident pos) start)
|
(hs-emit! "local" (read-ident pos) start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(or
|
(or
|
||||||
(= ch "\"")
|
(= ch "\"")
|
||||||
@@ -527,11 +535,11 @@
|
|||||||
(or
|
(or
|
||||||
(>= (+ pos 2) src-len)
|
(>= (+ pos 2) src-len)
|
||||||
(not (hs-ident-char? (hs-peek 2))))))))
|
(not (hs-ident-char? (hs-peek 2))))))))
|
||||||
(do (hs-emit! "string" (read-string ch) start) (scan!))
|
(do (hs-emit! "string" (read-string ch) start start-line) (scan!))
|
||||||
(= ch "`")
|
(= ch "`")
|
||||||
(do (hs-emit! "template" (read-template) start) (scan!))
|
(do (hs-emit! "template" (read-template) start start-line) (scan!))
|
||||||
(hs-digit? ch)
|
(hs-digit? ch)
|
||||||
(do (hs-emit! "number" (read-number start) start) (scan!))
|
(do (hs-emit! "number" (read-number start) start start-line) (scan!))
|
||||||
(hs-ident-start? ch)
|
(hs-ident-start? ch)
|
||||||
(do
|
(do
|
||||||
(let
|
(let
|
||||||
@@ -539,7 +547,8 @@
|
|||||||
(hs-emit!
|
(hs-emit!
|
||||||
(if (hs-keyword? word) "keyword" "ident")
|
(if (hs-keyword? word) "keyword" "ident")
|
||||||
word
|
word
|
||||||
start))
|
start
|
||||||
|
start-line))
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(or (= ch "=") (= ch "!") (= ch "<") (= ch ">"))
|
(or (= ch "=") (= ch "!") (= ch "<") (= ch ">"))
|
||||||
@@ -551,8 +560,8 @@
|
|||||||
(or (= ch "=") (= ch "!"))
|
(or (= ch "=") (= ch "!"))
|
||||||
(< (+ pos 2) src-len)
|
(< (+ pos 2) src-len)
|
||||||
(= (hs-peek 2) "="))
|
(= (hs-peek 2) "="))
|
||||||
(do (hs-emit! "op" (str ch "==") start) (hs-advance! 3))
|
(do (hs-advance! 3) (hs-emit! "op" (str ch "==") start start-line))
|
||||||
(do (hs-emit! "op" (str ch "=") start) (hs-advance! 2)))
|
(do (hs-advance! 2) (hs-emit! "op" (str ch "=") start start-line)))
|
||||||
(scan!))
|
(scan!))
|
||||||
(and
|
(and
|
||||||
(= ch "'")
|
(= ch "'")
|
||||||
@@ -561,66 +570,66 @@
|
|||||||
(or
|
(or
|
||||||
(>= (+ pos 2) src-len)
|
(>= (+ pos 2) src-len)
|
||||||
(not (hs-ident-char? (hs-peek 2)))))
|
(not (hs-ident-char? (hs-peek 2)))))
|
||||||
(do (hs-emit! "op" "'s" start) (hs-advance! 2) (scan!))
|
(do (hs-advance! 2) (hs-emit! "op" "'s" start start-line) (scan!))
|
||||||
(= ch "(")
|
(= ch "(")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "paren-open" "(" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "paren-open" "(" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch ")")
|
(= ch ")")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "paren-close" ")" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "paren-close" ")" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch "[")
|
(= ch "[")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "bracket-open" "[" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "bracket-open" "[" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch "]")
|
(= ch "]")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "bracket-close" "]" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "bracket-close" "]" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch "{")
|
(= ch "{")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "brace-open" "{" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "brace-open" "{" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch "}")
|
(= ch "}")
|
||||||
(do
|
(do
|
||||||
(hs-emit! "brace-close" "}" start)
|
|
||||||
(hs-advance! 1)
|
(hs-advance! 1)
|
||||||
|
(hs-emit! "brace-close" "}" start start-line)
|
||||||
(scan!))
|
(scan!))
|
||||||
(= ch ",")
|
(= ch ",")
|
||||||
(do (hs-emit! "comma" "," start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "comma" "," start start-line) (scan!))
|
||||||
(= ch "+")
|
(= ch "+")
|
||||||
(do (hs-emit! "op" "+" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "+" start start-line) (scan!))
|
||||||
(= ch "-")
|
(= ch "-")
|
||||||
(do (hs-emit! "op" "-" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "-" start start-line) (scan!))
|
||||||
(= ch "/")
|
(= ch "/")
|
||||||
(do (hs-emit! "op" "/" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "/" start start-line) (scan!))
|
||||||
(= ch "=")
|
(= ch "=")
|
||||||
(do (hs-emit! "op" "=" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "=" start start-line) (scan!))
|
||||||
(= ch "<")
|
(= ch "<")
|
||||||
(do (hs-emit! "op" "<" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "<" start start-line) (scan!))
|
||||||
(= ch ">")
|
(= ch ">")
|
||||||
(do (hs-emit! "op" ">" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" ">" start start-line) (scan!))
|
||||||
(= ch "!")
|
(= ch "!")
|
||||||
(do (hs-emit! "op" "!" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "!" start start-line) (scan!))
|
||||||
(= ch "*")
|
(= ch "*")
|
||||||
(do (hs-emit! "op" "*" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "*" start start-line) (scan!))
|
||||||
(= ch "%")
|
(= ch "%")
|
||||||
(do (hs-emit! "op" "%" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "%" start start-line) (scan!))
|
||||||
(= ch ".")
|
(= ch ".")
|
||||||
(do (hs-emit! "dot" "." start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "dot" "." start start-line) (scan!))
|
||||||
(= ch "\\")
|
(= ch "\\")
|
||||||
(do (hs-emit! "op" "\\" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "\\" start start-line) (scan!))
|
||||||
(= ch ":")
|
(= ch ":")
|
||||||
(do (hs-emit! "colon" ":" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "colon" ":" start start-line) (scan!))
|
||||||
(= ch "|")
|
(= ch "|")
|
||||||
(do (hs-emit! "op" "|" start) (hs-advance! 1) (scan!))
|
(do (hs-advance! 1) (hs-emit! "op" "|" start start-line) (scan!))
|
||||||
:else (do (hs-advance! 1) (scan!)))))))
|
:else (do (hs-advance! 1) (scan!)))))))
|
||||||
(scan!)
|
(scan!)
|
||||||
(hs-emit! "eof" nil pos)
|
(hs-emit! "eof" nil pos current-line)
|
||||||
tokens)))
|
tokens)))
|
||||||
@@ -2467,13 +2467,28 @@
|
|||||||
;; ── core/sourceInfo (4 tests) ──
|
;; ── core/sourceInfo (4 tests) ──
|
||||||
(defsuite "hs-upstream-core/sourceInfo"
|
(defsuite "hs-upstream-core/sourceInfo"
|
||||||
(deftest "debug"
|
(deftest "debug"
|
||||||
(error "SKIP (untranslated): debug"))
|
(assert= (hs-src "<button.foo/>") "<button.foo/>"))
|
||||||
(deftest "get line works for statements"
|
(deftest "get line works for statements"
|
||||||
(error "SKIP (untranslated): get line works for statements"))
|
(assert= (hs-line-at "if true\n log 'it was true'\n log 'it was true'" (list)) "if true")
|
||||||
|
(assert= (hs-line-at "if true\n log 'it was true'\n log 'it was true'" (list :true-branch)) " log 'it was true'")
|
||||||
|
(assert= (hs-line-at "if true\n log 'it was true'\n log 'it was true'" (list :true-branch :next)) " log 'it was true'"))
|
||||||
(deftest "get source works for expressions"
|
(deftest "get source works for expressions"
|
||||||
(error "SKIP (untranslated): get source works for expressions"))
|
(assert= (hs-src "1") "1")
|
||||||
|
(assert= (hs-src "a.b") "a.b")
|
||||||
|
(assert= (hs-src-at "a.b" (list :root)) "a")
|
||||||
|
(assert= (hs-src "a.b()") "a.b()")
|
||||||
|
(assert= (hs-src-at "a.b()" (list :root)) "a.b")
|
||||||
|
(assert= (hs-src-at "a.b()" (list :root :root)) "a")
|
||||||
|
(assert= (hs-src "<button.foo/>") "<button.foo/>")
|
||||||
|
(assert= (hs-src "x + y") "x + y")
|
||||||
|
(assert= (hs-src-at "x + y" (list :lhs)) "x")
|
||||||
|
(assert= (hs-src-at "x + y" (list :rhs)) "y")
|
||||||
|
(assert= (hs-src "'foo'") "'foo'")
|
||||||
|
(assert= (hs-src ".foo") ".foo")
|
||||||
|
(assert= (hs-src "#bar") "#bar"))
|
||||||
(deftest "get source works for statements"
|
(deftest "get source works for statements"
|
||||||
(error "SKIP (untranslated): get source works for statements"))
|
(assert= (hs-src "if true log 'it was true'") "if true log 'it was true'")
|
||||||
|
(assert= (hs-src "for x in [1, 2, 3] log x then log x end") "for x in [1, 2, 3] log x then log x end"))
|
||||||
)
|
)
|
||||||
|
|
||||||
;; ── core/tokenizer (17 tests) ──
|
;; ── core/tokenizer (17 tests) ──
|
||||||
@@ -13595,5 +13610,9 @@ end")
|
|||||||
;; ── worker (1 tests) ──
|
;; ── worker (1 tests) ──
|
||||||
(defsuite "hs-upstream-worker"
|
(defsuite "hs-upstream-worker"
|
||||||
(deftest "raises a helpful error when the worker plugin is not installed"
|
(deftest "raises a helpful error when the worker plugin is not installed"
|
||||||
(error "SKIP (untranslated): raises a helpful error when the worker plugin is not installed"))
|
(let ((result (guard (e (true (if (string? e) e (str e))))
|
||||||
|
(hs-compile "worker MyWorker def noop() end end")
|
||||||
|
"")))
|
||||||
|
(assert (contains? result "worker plugin"))
|
||||||
|
(assert (contains? result "hyperscript.org/features/worker"))))
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2015,6 +2015,47 @@ def generate_eval_only_test(test, idx):
|
|||||||
f' )'
|
f' )'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Special case: cluster-38 sourceInfo tests.
|
||||||
|
if test['name'] == 'debug':
|
||||||
|
return (
|
||||||
|
f' (deftest "{safe_name}"\n'
|
||||||
|
f' (assert= (hs-src "<button.foo/>") "<button.foo/>"))'
|
||||||
|
)
|
||||||
|
|
||||||
|
if test['name'] == 'get source works for expressions':
|
||||||
|
return (
|
||||||
|
f' (deftest "{safe_name}"\n'
|
||||||
|
f' (assert= (hs-src "1") "1")\n'
|
||||||
|
f' (assert= (hs-src "a.b") "a.b")\n'
|
||||||
|
f' (assert= (hs-src-at "a.b" (list :root)) "a")\n'
|
||||||
|
f' (assert= (hs-src "a.b()") "a.b()")\n'
|
||||||
|
f' (assert= (hs-src-at "a.b()" (list :root)) "a.b")\n'
|
||||||
|
f' (assert= (hs-src-at "a.b()" (list :root :root)) "a")\n'
|
||||||
|
f' (assert= (hs-src "<button.foo/>") "<button.foo/>")\n'
|
||||||
|
f' (assert= (hs-src "x + y") "x + y")\n'
|
||||||
|
f' (assert= (hs-src-at "x + y" (list :lhs)) "x")\n'
|
||||||
|
f' (assert= (hs-src-at "x + y" (list :rhs)) "y")\n'
|
||||||
|
f" (assert= (hs-src \"'foo'\") \"'foo'\")\n"
|
||||||
|
f' (assert= (hs-src ".foo") ".foo")\n'
|
||||||
|
f' (assert= (hs-src "#bar") "#bar"))'
|
||||||
|
)
|
||||||
|
|
||||||
|
if test['name'] == 'get source works for statements':
|
||||||
|
return (
|
||||||
|
f' (deftest "{safe_name}"\n'
|
||||||
|
f" (assert= (hs-src \"if true log 'it was true'\") \"if true log 'it was true'\")\n"
|
||||||
|
f' (assert= (hs-src "for x in [1, 2, 3] log x then log x end") "for x in [1, 2, 3] log x then log x end"))'
|
||||||
|
)
|
||||||
|
|
||||||
|
if test['name'] == 'get line works for statements':
|
||||||
|
src = "if true\\n log 'it was true'\\n log 'it was true'"
|
||||||
|
return (
|
||||||
|
f' (deftest "{safe_name}"\n'
|
||||||
|
f' (assert= (hs-line-at "{src}" (list)) "if true")\n'
|
||||||
|
f" (assert= (hs-line-at \"{src}\" (list :true-branch)) \" log 'it was true'\")\n"
|
||||||
|
f" (assert= (hs-line-at \"{src}\" (list :true-branch :next)) \" log 'it was true'\"))"
|
||||||
|
)
|
||||||
|
|
||||||
lines.append(f' (deftest "{safe_name}"')
|
lines.append(f' (deftest "{safe_name}"')
|
||||||
|
|
||||||
assertions = []
|
assertions = []
|
||||||
|
|||||||
Reference in New Issue
Block a user