HS behavioral tests: 478→509/831 (57%→61%), parser/compiler/runtime fixes
Parser: am-a/am-not-a type checks, transition element/selector targeting, take @attr=value with replacement, toggle my/the possessive, <selector/> syntax in parse-atom, the-of for style/attr/class/selector, when-clause filtering for add, starts/ends-with ignoring case. Compiler: take attr passthrough, toggle-style nil→me default, scoped querySelectorAll for add/remove/toggle-class, has-class? entry, matches? extracts selector from (query sel), add-class-when with for-each filter, starts/ends-with-ic entries, hs-add replaces + for polymorphic add. Runtime: hs-take! proper attr values, hs-type-check Element/Node via host-typeof, hs-toggle-style! opacity 0↔1, hs-coerce +8 coercions (Keys/Values/Entries/Reversed/Unique/Flat/JSON/Object), hs-query-all bypasses broken dom-query-all (WASM auto-converts arrays), hs-matches? handles DOM el.matches(selector), hs-add list+string+number polymorphic, hs-starts/ends-with-ic for case-insensitive comparison. DOM mock: mkStyle() with setProperty/getPropertyValue, fndAll.item(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -513,12 +513,26 @@
|
||||
(do
|
||||
(adv!)
|
||||
(match-kw "with")
|
||||
(list (quote starts-with?) left (parse-expr))))
|
||||
(let
|
||||
((rhs (parse-atom)))
|
||||
(if
|
||||
(match-kw "ignoring")
|
||||
(do
|
||||
(match-kw "case")
|
||||
(list (quote starts-with-ic?) left rhs))
|
||||
(list (quote starts-with?) left rhs)))))
|
||||
((and (or (= typ "keyword") (= typ "ident")) (= val "ends"))
|
||||
(do
|
||||
(adv!)
|
||||
(match-kw "with")
|
||||
(list (quote ends-with?) left (parse-expr))))
|
||||
(let
|
||||
((rhs (parse-atom)))
|
||||
(if
|
||||
(match-kw "ignoring")
|
||||
(do
|
||||
(match-kw "case")
|
||||
(list (quote ends-with-ic?) left rhs))
|
||||
(list (quote ends-with?) left rhs)))))
|
||||
((and (= typ "keyword") (= val "matches"))
|
||||
(do
|
||||
(adv!)
|
||||
@@ -607,11 +621,17 @@
|
||||
(quote not)
|
||||
(list (quote contains?) left (parse-expr))))
|
||||
((match-kw "start")
|
||||
(do (match-kw "with")
|
||||
(list (quote not) (list (quote starts-with?) left (parse-expr)))))
|
||||
(do
|
||||
(match-kw "with")
|
||||
(list
|
||||
(quote not)
|
||||
(list (quote starts-with?) left (parse-expr)))))
|
||||
((match-kw "end")
|
||||
(do (match-kw "with")
|
||||
(list (quote not) (list (quote ends-with?) left (parse-expr)))))
|
||||
(do
|
||||
(match-kw "with")
|
||||
(list
|
||||
(quote not)
|
||||
(list (quote ends-with?) left (parse-expr)))))
|
||||
(true left))))
|
||||
((and (= typ "keyword") (= val "equals"))
|
||||
(do (adv!) (list (quote =) left (parse-expr))))
|
||||
@@ -693,12 +713,20 @@
|
||||
nil
|
||||
(do
|
||||
(when
|
||||
(and (number? left) (= (tp-type) "ident")
|
||||
(not (or (= (tp-val) "starts") (= (tp-val) "ends")
|
||||
(= (tp-val) "contains") (= (tp-val) "matches")
|
||||
(= (tp-val) "is") (= (tp-val) "does")
|
||||
(= (tp-val) "in") (= (tp-val) "precedes")
|
||||
(= (tp-val) "follows"))))
|
||||
(and
|
||||
(number? left)
|
||||
(= (tp-type) "ident")
|
||||
(not
|
||||
(or
|
||||
(= (tp-val) "starts")
|
||||
(= (tp-val) "ends")
|
||||
(= (tp-val) "contains")
|
||||
(= (tp-val) "matches")
|
||||
(= (tp-val) "is")
|
||||
(= (tp-val) "does")
|
||||
(= (tp-val) "in")
|
||||
(= (tp-val) "precedes")
|
||||
(= (tp-val) "follows"))))
|
||||
(let
|
||||
((unit (tp-val)))
|
||||
(do
|
||||
@@ -757,12 +785,25 @@
|
||||
(collect-classes!)
|
||||
(let
|
||||
((tgt (parse-tgt-kw "to" (list (quote me)))))
|
||||
(if
|
||||
(empty? extra-classes)
|
||||
(list (quote add-class) cls tgt)
|
||||
(cons
|
||||
(quote multi-add-class)
|
||||
(cons tgt (cons cls extra-classes))))))
|
||||
(let
|
||||
((when-clause (if (match-kw "when") (parse-expr) nil)))
|
||||
(if
|
||||
(empty? extra-classes)
|
||||
(if
|
||||
when-clause
|
||||
(list (quote add-class-when) cls tgt when-clause)
|
||||
(list (quote add-class) cls tgt))
|
||||
(if
|
||||
when-clause
|
||||
(list
|
||||
(quote multi-add-class-when)
|
||||
tgt
|
||||
when-clause
|
||||
cls
|
||||
extra-classes)
|
||||
(cons
|
||||
(quote multi-add-class)
|
||||
(cons tgt (cons cls extra-classes))))))))
|
||||
nil)))
|
||||
(define
|
||||
parse-remove-cmd
|
||||
@@ -893,6 +934,70 @@
|
||||
(let
|
||||
((tgt (parse-tgt-kw "on" (list (quote me)))))
|
||||
(list (quote toggle-attr) attr-name tgt)))))
|
||||
((and (= (tp-type) "keyword") (= (tp-val) "my"))
|
||||
(do
|
||||
(adv!)
|
||||
(cond
|
||||
((= (tp-type) "style")
|
||||
(let
|
||||
((prop (get (adv!) "value")))
|
||||
(if
|
||||
(match-kw "between")
|
||||
(let
|
||||
((val1 (parse-expr)))
|
||||
(expect-kw! "and")
|
||||
(let
|
||||
((val2 (parse-expr)))
|
||||
(let
|
||||
((tgt (if (match-kw "on") (parse-expr) nil)))
|
||||
(list
|
||||
(quote toggle-style-between)
|
||||
prop
|
||||
val1
|
||||
val2
|
||||
tgt))))
|
||||
(let
|
||||
((tgt (if (match-kw "on") (parse-expr) nil)))
|
||||
(list (quote toggle-style) prop tgt)))))
|
||||
((= (tp-type) "attr")
|
||||
(let
|
||||
((attr-name (get (adv!) "value")))
|
||||
(let
|
||||
((tgt (if (match-kw "on") (parse-expr) nil)))
|
||||
(list (quote toggle-attr) attr-name tgt))))
|
||||
(true nil))))
|
||||
((and (= (tp-type) "keyword") (= (tp-val) "the"))
|
||||
(do
|
||||
(adv!)
|
||||
(let
|
||||
((expr (parse-the-expr)))
|
||||
(cond
|
||||
((and (list? expr) (= (first expr) (quote style)))
|
||||
(let
|
||||
((prop (nth expr 1)) (tgt (nth expr 2)))
|
||||
(if
|
||||
(match-kw "between")
|
||||
(let
|
||||
((val1 (parse-expr)))
|
||||
(expect-kw! "and")
|
||||
(let
|
||||
((val2 (parse-expr)))
|
||||
(list
|
||||
(quote toggle-style-between)
|
||||
prop
|
||||
val1
|
||||
val2
|
||||
tgt)))
|
||||
(list (quote toggle-style) prop tgt))))
|
||||
((and (list? expr) (= (first expr) (quote attr)))
|
||||
(let
|
||||
((attr-name (nth expr 1)) (tgt (nth expr 2)))
|
||||
(list (quote toggle-attr) attr-name tgt)))
|
||||
((and (list? expr) (= (first expr) (quote has-class?)))
|
||||
(let
|
||||
((tgt (nth expr 1)) (cls (nth expr 2)))
|
||||
(list (quote toggle-class) cls tgt)))
|
||||
(true nil)))))
|
||||
(true nil))))
|
||||
(define
|
||||
parse-set-cmd
|
||||
@@ -1080,21 +1185,26 @@
|
||||
(fn
|
||||
()
|
||||
(let
|
||||
((prop (cond ((= (tp-type) "style") (get (adv!) "value")) ((= (tp-val) "my") (do (adv!) (if (= (tp-type) "style") (get (adv!) "value") (get (adv!) "value")))) (true (get (adv!) "value")))))
|
||||
((tgt (cond ((and (= (tp-type) "ident") (= (tp-val) "element")) (do (adv!) (parse-atom))) ((= (tp-type) "id") (parse-atom)) ((= (tp-type) "class") (parse-atom)) ((= (tp-type) "selector") (parse-atom)) (true nil))))
|
||||
(let
|
||||
((from-val (if (match-kw "from") (parse-expr) nil)))
|
||||
(expect-kw! "to")
|
||||
((prop (cond ((= (tp-type) "style") (get (adv!) "value")) ((= (tp-val) "my") (do (adv!) (if (= (tp-type) "style") (get (adv!) "value") (get (adv!) "value")))) (true (get (adv!) "value")))))
|
||||
(let
|
||||
((value (parse-expr)))
|
||||
((from-val (if (match-kw "from") (parse-expr) nil)))
|
||||
(expect-kw! "to")
|
||||
(let
|
||||
((dur (if (match-kw "over") (parse-expr) nil)))
|
||||
(if
|
||||
from-val
|
||||
(list (quote transition-from) prop from-val value dur)
|
||||
((value (parse-expr)))
|
||||
(let
|
||||
((dur (if (match-kw "over") (parse-expr) nil)))
|
||||
(if
|
||||
dur
|
||||
(list (quote transition) prop value dur nil)
|
||||
(list (quote transition) prop value nil)))))))))
|
||||
from-val
|
||||
(list
|
||||
(quote transition-from)
|
||||
prop
|
||||
from-val
|
||||
value
|
||||
dur
|
||||
tgt)
|
||||
(list (quote transition) prop value dur tgt)))))))))
|
||||
(define
|
||||
parse-repeat-cmd
|
||||
(fn
|
||||
@@ -1223,22 +1333,53 @@
|
||||
()
|
||||
(let
|
||||
((typ (tp-type)) (val (tp-val)))
|
||||
(if
|
||||
(or (= typ "ident") (= typ "keyword"))
|
||||
(do
|
||||
(adv!)
|
||||
(if
|
||||
(match-kw "of")
|
||||
(list (make-symbol ".") (parse-expr) val)
|
||||
(cond
|
||||
((= val "result") (list (quote it)))
|
||||
((= val "first") (parse-pos-kw (quote first)))
|
||||
((= val "last") (parse-pos-kw (quote last)))
|
||||
((= val "closest") (parse-trav (quote closest)))
|
||||
((= val "next") (parse-trav (quote next)))
|
||||
((= val "previous") (parse-trav (quote previous)))
|
||||
(true (list (quote ref) val)))))
|
||||
(parse-atom)))))
|
||||
(cond
|
||||
((= typ "style")
|
||||
(do
|
||||
(adv!)
|
||||
(if
|
||||
(match-kw "of")
|
||||
(list (quote style) val (parse-expr))
|
||||
(list (quote style) val (list (quote me))))))
|
||||
((= typ "attr")
|
||||
(do
|
||||
(adv!)
|
||||
(if
|
||||
(match-kw "of")
|
||||
(list (quote attr) val (parse-expr))
|
||||
(list (quote attr) val (list (quote me))))))
|
||||
((= typ "class")
|
||||
(do
|
||||
(adv!)
|
||||
(if
|
||||
(match-kw "of")
|
||||
(list (quote has-class?) (parse-expr) val)
|
||||
(list (quote has-class?) (list (quote me)) val))))
|
||||
((= typ "selector")
|
||||
(do
|
||||
(adv!)
|
||||
(if
|
||||
(match-kw "in")
|
||||
(list
|
||||
(quote in?)
|
||||
(list (quote query) val)
|
||||
(parse-expr))
|
||||
(list (quote query) val))))
|
||||
((or (= typ "ident") (= typ "keyword"))
|
||||
(do
|
||||
(adv!)
|
||||
(if
|
||||
(match-kw "of")
|
||||
(list (make-symbol ".") (parse-expr) val)
|
||||
(cond
|
||||
((= val "result") (list (quote it)))
|
||||
((= val "first") (parse-pos-kw (quote first)))
|
||||
((= val "last") (parse-pos-kw (quote last)))
|
||||
((= val "closest") (parse-trav (quote closest)))
|
||||
((= val "next") (parse-trav (quote next)))
|
||||
((= val "previous") (parse-trav (quote previous)))
|
||||
(true (list (quote ref) val))))))
|
||||
(true (parse-atom))))))
|
||||
(define
|
||||
parse-array-lit
|
||||
(fn
|
||||
|
||||
Reference in New Issue
Block a user