js-on-sx: for..of / for..in + more Array methods

Parser: jp-parse-for-stmt does 2-token lookahead for (var? ident
(of|in) expr), emits (js-for-of-in kind ident iter body) else
classic (js-for init cond step body).

Transpile: wraps body in (call/cc (__break__) (let items
(for-each (fn (ident) (call/cc (__continue__) body)) items))).

Runtime: js-iterable-to-list normalizes list/string/dict for of
iteration; js-string-to-list expands string to char list.

399/401 unit (+8), 148/148 slice unchanged.
This commit is contained in:
2026-04-23 21:41:52 +00:00
parent ee16e358f3
commit f113b45d48
5 changed files with 120 additions and 14 deletions

View File

@@ -866,22 +866,48 @@
jp-parse-for-stmt
(fn
(st)
(do
(jp-advance! st)
(jp-expect! st "punct" "(")
(jp-advance! st)
(jp-expect! st "punct" "(")
(let
((has-decl false) (decl-kind nil))
(cond
((jp-at? st "keyword" "var")
(begin (set! has-decl true) (set! decl-kind "var")))
((jp-at? st "keyword" "let")
(begin (set! has-decl true) (set! decl-kind "let")))
((jp-at? st "keyword" "const")
(begin (set! has-decl true) (set! decl-kind "const")))
(else nil))
(let
((init (jp-parse-for-init st)))
(let
((cond-ast (if (jp-at? st "punct" ";") nil (jp-parse-assignment st))))
(do
(jp-expect! st "punct" ";")
(let
((step (if (jp-at? st "punct" ")") nil (jp-parse-assignment st))))
(do
(jp-expect! st "punct" ")")
((ident-off (if has-decl 1 0)))
(cond
((and (= (get (jp-peek-at st ident-off) :type) "ident") (or (and (= (get (jp-peek-at st (+ ident-off 1)) :type) "keyword") (= (get (jp-peek-at st (+ ident-off 1)) :value) "of")) (and (= (get (jp-peek-at st (+ ident-off 1)) :type) "keyword") (= (get (jp-peek-at st (+ ident-off 1)) :value) "in"))))
(begin
(when has-decl (jp-advance! st))
(let
((ident (get (jp-peek st) :value)))
(jp-advance! st)
(let
((body (jp-parse-stmt st)))
(list (quote js-for) init cond-ast step body))))))))))
((iter-kind (get (jp-peek st) :value)))
(jp-advance! st)
(let
((iter (jp-parse-assignment st)))
(jp-expect! st "punct" ")")
(let
((body (jp-parse-stmt st)))
(list (quote js-for-of-in) iter-kind ident iter body)))))))
(else
(let
((init (cond (has-decl (jp-parse-var-stmt st decl-kind)) ((jp-at? st "punct" ";") (begin (jp-advance! st) nil)) (else (let ((e (jp-parse-assignment st))) (jp-expect! st "punct" ";") (list (quote js-exprstmt) e))))))
(let
((cond-ast (if (jp-at? st "punct" ";") nil (jp-parse-assignment st))))
(jp-expect! st "punct" ";")
(let
((step (if (jp-at? st "punct" ")") nil (jp-parse-assignment st))))
(jp-expect! st "punct" ")")
(let
((body (jp-parse-stmt st)))
(list (quote js-for) init cond-ast step body)))))))))))
(define
jp-parse-for-init