diff --git a/lib/hyperscript/compiler.sx b/lib/hyperscript/compiler.sx index 95152437..4262346c 100644 --- a/lib/hyperscript/compiler.sx +++ b/lib/hyperscript/compiler.sx @@ -333,7 +333,7 @@ (hs-to-sx (nth ast 1)) (hs-to-sx (nth ast 2)))) ((= head (quote empty?)) - (list (quote empty?) (hs-to-sx (nth ast 1)))) + (list (quote hs-empty?) (hs-to-sx (nth ast 1)))) ((= head (quote exists?)) (list (quote not) @@ -356,10 +356,13 @@ (hs-to-sx (nth ast 2)) (hs-to-sx (nth ast 1)))) ((= head (quote of)) - (list - (quote get) - (hs-to-sx (nth ast 2)) - (hs-to-sx (nth ast 1)))) + (let + ((prop (hs-to-sx (nth ast 1))) + (target (hs-to-sx (nth ast 2)))) + (cond + ((= prop (quote first)) (list (quote first) target)) + ((= prop (quote last)) (list (quote last) target)) + (true (list (quote get) target prop))))) ((= head "!=") (list (quote not) diff --git a/lib/hyperscript/parser.sx b/lib/hyperscript/parser.sx index e2558f7c..f4c96bc3 100644 --- a/lib/hyperscript/parser.sx +++ b/lib/hyperscript/parser.sx @@ -187,20 +187,26 @@ ((and (= typ "keyword") (= val "some")) (do (adv!) - (let - ((var-name (tp-val))) - (do - (adv!) - (match-kw "in") - (let - ((collection (parse-expr))) - (do - (match-kw "with") - (list - (quote some) - var-name - collection - (parse-expr)))))))) + (if + (and + (= (tp-type) "ident") + (> (len tokens) (+ p 1)) + (= (get (nth tokens (+ p 1)) "value") "in")) + (let + ((var-name (tp-val))) + (do + (adv!) + (match-kw "in") + (let + ((collection (parse-expr))) + (do + (match-kw "with") + (list + (quote some) + var-name + collection + (parse-expr)))))) + (list (quote not) (list (quote no) (parse-expr)))))) ((and (= typ "keyword") (= val "every")) (do (adv!) @@ -277,7 +283,7 @@ (do (adv!) (let - ((strict (if (string-ends-with? type-name "!") (string-slice type-name 0 (- (len type-name) 1)) nil))) + ((strict (if (= (nth type-name (- (len type-name) 1)) "!") (string-slice type-name 0 (- (len type-name) 1)) nil))) (if strict (list @@ -327,7 +333,7 @@ (do (adv!) (let - ((strict (if (string-ends-with? type-name "!") (string-slice type-name 0 (- (len type-name) 1)) nil))) + ((strict (if (= (nth type-name (- (len type-name) 1)) "!") (string-slice type-name 0 (- (len type-name) 1)) nil))) (if strict (list (quote type-check!) left strict) diff --git a/lib/hyperscript/runtime.sx b/lib/hyperscript/runtime.sx index 62153fec..8b71b93e 100644 --- a/lib/hyperscript/runtime.sx +++ b/lib/hyperscript/runtime.sx @@ -295,7 +295,15 @@ (define hs-falsy? - (fn (v) (or (nil? v) (= v false) (and (string? v) (= v ""))))) + (fn + (v) + (cond + ((nil? v) true) + ((= v false) true) + ((and (string? v) (= v "")) true) + ((and (list? v) (= (len v) 0)) true) + ((= v 0) true) + (true false)))) (define hs-matches? @@ -313,4 +321,15 @@ (cond ((list? collection) (some (fn (x) (= x item)) collection)) ((string? collection) (string-contains? collection item)) + (true false)))) + +(define + hs-empty? + (fn + (v) + (cond + ((nil? v) true) + ((string? v) (= (len v) 0)) + ((list? v) (= (len v) 0)) + ((dict? v) (= (len (keys v)) 0)) (true false)))) \ No newline at end of file diff --git a/lib/hyperscript/tokenizer.sx b/lib/hyperscript/tokenizer.sx index 30bcb6c6..44fe6fce 100644 --- a/lib/hyperscript/tokenizer.sx +++ b/lib/hyperscript/tokenizer.sx @@ -152,7 +152,8 @@ "includes" "contain" "undefined" - "exist")) + "exist" + "match")) (define hs-keyword? (fn (word) (some (fn (k) (= k word)) hs-keywords))) diff --git a/spec/tests/test-hyperscript-conformance.sx b/spec/tests/test-hyperscript-conformance.sx index acfa8ea0..967977e1 100644 --- a/spec/tests/test-hyperscript-conformance.sx +++ b/spec/tests/test-hyperscript-conformance.sx @@ -22,7 +22,8 @@ (list (quote hs-type-check!) hs-type-check!) (list (quote hs-matches?) hs-matches?) (list (quote hs-coerce) hs-coerce) - (list (quote hs-contains?) hs-contains?))) + (list (quote hs-contains?) hs-contains?) + (list (quote hs-empty?) hs-empty?))) (overrides (list))) (do (when @@ -51,17 +52,19 @@ (list (quote let) defaults (list (quote let) overrides sx))))))))) ;; ── run-hs-fixture: evaluate one test case ──────────────────────────── -(define - run-hs-fixture - (fn - (f) - (let - ((src (get f "src")) - (expected (get f "expected")) - (ctx (if (or (get f "locals") (get f "me")) {:me (get f "me") :locals (get f "locals")} nil))) +(begin + (define _hs-error-sentinel "_HS_EVAL_ERROR_") + (define + run-hs-fixture + (fn + (f) (let - ((result (if ctx (eval-hs src ctx) (eval-hs src)))) - (assert= result expected src))))) + ((src (get f "src")) + (expected (get f "expected")) + (ctx (if (or (get f "locals") (get f "me")) {:me (get f "me") :locals (get f "locals")} nil))) + (let + ((result (if ctx (eval-hs src ctx) (eval-hs src)))) + (assert= result expected src)))))) ;; ── arrayIndex (1 fixtures) ────────────────────────────── (defsuite