js-on-sx: switch/case/default/break
Parser: jp-parse-switch-stmt + jp-parse-switch-cases + jp-parse-switch-body.
AST: (js-switch discr (("case" val body) ("default" nil body) ...)).
Transpile: wraps body in (call/cc (fn (__break__) ...)). Each case
clause becomes (when (or __matched__ (js-strict-eq discr val))
(set! __matched__ true) body). Fall-through works naturally via
__matched__. Default appended as (when (not __matched__) body).
363/365 unit (+6), 148/148 slice unchanged.
This commit is contained in:
@@ -105,6 +105,8 @@
|
||||
(js-transpile-postfix (nth ast 1) (nth ast 2)))
|
||||
((js-tag? ast "js-prefix")
|
||||
(js-transpile-prefix (nth ast 1) (nth ast 2)))
|
||||
((js-tag? ast "js-switch")
|
||||
(js-transpile-switch (nth ast 1) (nth ast 2)))
|
||||
((js-tag? ast "js-new")
|
||||
(js-transpile-new (nth ast 1) (nth ast 2)))
|
||||
((js-tag? ast "js-class")
|
||||
@@ -558,6 +560,89 @@
|
||||
(js-sym "__js_old__"))))
|
||||
(else (error "js-transpile-postfix: unsupported target"))))))
|
||||
|
||||
(define
|
||||
js-transpile-switch
|
||||
(fn
|
||||
(discr cases)
|
||||
(let
|
||||
((discr-sym (js-sym "__discr__"))
|
||||
(matched-sym (js-sym "__matched__"))
|
||||
(break-sym (js-sym "__break__")))
|
||||
(list
|
||||
(js-sym "call/cc")
|
||||
(list
|
||||
(js-sym "fn")
|
||||
(list break-sym)
|
||||
(list
|
||||
(js-sym "let")
|
||||
(list
|
||||
(list discr-sym (js-transpile discr))
|
||||
(list matched-sym false))
|
||||
(js-transpile-switch-clauses cases discr-sym matched-sym)))))))
|
||||
|
||||
(define
|
||||
js-transpile-switch-clauses
|
||||
(fn
|
||||
(cases discr-sym matched-sym)
|
||||
(let
|
||||
((forms (list)))
|
||||
(for-each
|
||||
(fn
|
||||
(c)
|
||||
(let
|
||||
((kind (nth c 0)))
|
||||
(cond
|
||||
((= kind "case")
|
||||
(let
|
||||
((val (nth c 1)) (body (nth c 2)))
|
||||
(append!
|
||||
forms
|
||||
(list
|
||||
(js-sym "when")
|
||||
(list
|
||||
(js-sym "or")
|
||||
matched-sym
|
||||
(list
|
||||
(js-sym "js-strict-eq")
|
||||
discr-sym
|
||||
(js-transpile val)))
|
||||
(js-transpile-switch-body-block matched-sym body)))))
|
||||
((= kind "default")
|
||||
(let
|
||||
((body (nth c 2)))
|
||||
(append!
|
||||
forms
|
||||
(list
|
||||
(js-sym "when")
|
||||
matched-sym
|
||||
(js-transpile-switch-body-block matched-sym body))))))))
|
||||
cases)
|
||||
(let
|
||||
((def-body nil))
|
||||
(for-each
|
||||
(fn
|
||||
(c)
|
||||
(when (= (nth c 0) "default") (set! def-body (nth c 2))))
|
||||
cases)
|
||||
(when
|
||||
(not (= def-body nil))
|
||||
(append!
|
||||
forms
|
||||
(list
|
||||
(js-sym "when")
|
||||
(list (js-sym "not") matched-sym)
|
||||
(js-transpile-switch-body-block matched-sym def-body)))))
|
||||
(cons (js-sym "begin") forms))))
|
||||
|
||||
(define
|
||||
js-transpile-switch-body-block
|
||||
(fn
|
||||
(matched-sym body)
|
||||
(let
|
||||
((forms (list (list (js-sym "set!") matched-sym true))))
|
||||
(for-each (fn (stmt) (append! forms (js-transpile stmt))) body)
|
||||
(cons (js-sym "begin") forms))))
|
||||
|
||||
(define
|
||||
js-param-sym
|
||||
(fn
|
||||
|
||||
Reference in New Issue
Block a user