js-on-sx: postfix + prefix ++/--
Parser: jp-parse-postfix emits (js-postfix op target) on trailing ++/--; jp-parse-primary emits (js-prefix op target) before the unary -/+/!/~ branch. Transpile: js-transpile-prefix → (set! name (+ (js-to-number name) ±1)) for idents, (js-set-prop obj key ...) for members/indices. js-transpile-postfix caches old value in a let binding, updates, returns the saved value. 340/342 unit (+11), 148/148 slice unchanged.
This commit is contained in:
@@ -333,6 +333,10 @@
|
||||
(do (jp-advance! st) (jp-parse-new-expr st)))
|
||||
((and (= (get t :type) "keyword") (= (get t :value) "this"))
|
||||
(do (jp-advance! st) (list (quote js-ident) "this")))
|
||||
((and (= (get t :type) "op") (or (= (get t :value) "++") (= (get t :value) "--")))
|
||||
(do
|
||||
(jp-advance! st)
|
||||
(list (quote js-prefix) (get t :value) (jp-parse-unary st))))
|
||||
((and (= (get t :type) "op") (or (= (get t :value) "-") (= (get t :value) "+") (= (get t :value) "!") (= (get t :value) "~")))
|
||||
(do
|
||||
(jp-advance! st)
|
||||
@@ -582,6 +586,11 @@
|
||||
(jp-call-args-loop st args)
|
||||
(jp-expect! st "punct" ")")
|
||||
(jp-parse-postfix st (list (quote js-call) left args)))))
|
||||
((or (jp-at? st "op" "++") (jp-at? st "op" "--"))
|
||||
(let
|
||||
((op (get (jp-peek st) :value)))
|
||||
(jp-advance! st)
|
||||
(list (quote js-postfix) op left)))
|
||||
(else left))))
|
||||
|
||||
(define
|
||||
|
||||
@@ -875,6 +875,30 @@ cat > "$TMPFILE" << 'EPOCHS'
|
||||
(epoch 1208)
|
||||
(eval "(js-eval \"isFinite(1/0)\")")
|
||||
|
||||
;; ── Phase 11.incdec: ++ / -- ─────────────────────────────────────
|
||||
(epoch 1300)
|
||||
(eval "(js-eval \"var x = 5; x++; x\")")
|
||||
(epoch 1301)
|
||||
(eval "(js-eval \"var x = 5; var y = x++; y\")")
|
||||
(epoch 1302)
|
||||
(eval "(js-eval \"var x = 5; ++x\")")
|
||||
(epoch 1303)
|
||||
(eval "(js-eval \"var x = 5; var y = ++x; y\")")
|
||||
(epoch 1304)
|
||||
(eval "(js-eval \"var x = 5; x--; x\")")
|
||||
(epoch 1305)
|
||||
(eval "(js-eval \"var x = 5; --x\")")
|
||||
(epoch 1306)
|
||||
(eval "(js-eval \"var o = {n: 10}; o.n++; o.n\")")
|
||||
(epoch 1307)
|
||||
(eval "(js-eval \"var o = {n: 10}; ++o.n\")")
|
||||
(epoch 1308)
|
||||
(eval "(js-eval \"var a = [1,2,3]; a[1]++; a[1]\")")
|
||||
(epoch 1309)
|
||||
(eval "(js-eval \"var x = 5; for (var i = 0; i < 3; i++) x++; x\")")
|
||||
(epoch 1310)
|
||||
(eval "(js-eval \"var sum = 0; for (var i = 1; i <= 5; i++) sum = sum + i; sum\")")
|
||||
|
||||
EPOCHS
|
||||
|
||||
OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
|
||||
@@ -1340,6 +1364,19 @@ check 1206 "Number.EPSILON > 0" 'true'
|
||||
check 1207 "isFinite(1)" 'true'
|
||||
check 1208 "isFinite(Inf)" 'false'
|
||||
|
||||
# ── Phase 11.incdec: ++ / -- ────────────────────────────────────
|
||||
check 1300 "x++ bumps x" '6'
|
||||
check 1301 "x++ returns old" '5'
|
||||
check 1302 "++x bumps and returns" '6'
|
||||
check 1303 "++x captured new" '6'
|
||||
check 1304 "x-- decrements" '4'
|
||||
check 1305 "--x decrements, returns new" '4'
|
||||
check 1306 "obj.n++" '11'
|
||||
check 1307 "++obj.n" '11'
|
||||
check 1308 "a[1]++" '3'
|
||||
check 1309 "for-loop x++" '8'
|
||||
check 1310 "for-loop accumulator" '15'
|
||||
|
||||
TOTAL=$((PASS + FAIL))
|
||||
if [ $FAIL -eq 0 ]; then
|
||||
echo "✓ $PASS/$TOTAL JS-on-SX tests passed"
|
||||
|
||||
@@ -101,6 +101,10 @@
|
||||
(js-transpile-funcexpr (nth ast 1) (nth ast 2) (nth ast 3)))
|
||||
((js-tag? ast "js-assign")
|
||||
(js-transpile-assign (nth ast 1) (nth ast 2) (nth ast 3)))
|
||||
((js-tag? ast "js-postfix")
|
||||
(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-new")
|
||||
(js-transpile-new (nth ast 1) (nth ast 2)))
|
||||
((js-tag? ast "js-class")
|
||||
@@ -440,6 +444,120 @@
|
||||
((= op "=") rhs-expr)
|
||||
(else (js-compound-update op lhs-expr rhs-expr)))))
|
||||
|
||||
(define
|
||||
js-transpile-prefix
|
||||
(fn
|
||||
(op target)
|
||||
(let
|
||||
((delta (if (= op "++") 1 -1)))
|
||||
(cond
|
||||
((js-tag? target "js-ident")
|
||||
(let
|
||||
((name (nth target 1)))
|
||||
(let
|
||||
((sxname (js-sym name)))
|
||||
(list
|
||||
(js-sym "set!")
|
||||
sxname
|
||||
(list
|
||||
(js-sym "+")
|
||||
(list (js-sym "js-to-number") sxname)
|
||||
delta)))))
|
||||
((js-tag? target "js-member")
|
||||
(let
|
||||
((obj-sx (js-transpile (nth target 1))) (key (nth target 2)))
|
||||
(list
|
||||
(js-sym "js-set-prop")
|
||||
obj-sx
|
||||
key
|
||||
(list
|
||||
(js-sym "+")
|
||||
(list
|
||||
(js-sym "js-to-number")
|
||||
(list (js-sym "js-get-prop") obj-sx key))
|
||||
delta))))
|
||||
((js-tag? target "js-index")
|
||||
(let
|
||||
((obj-sx (js-transpile (nth target 1)))
|
||||
(key-sx (js-transpile (nth target 2))))
|
||||
(list
|
||||
(js-sym "js-set-prop")
|
||||
obj-sx
|
||||
key-sx
|
||||
(list
|
||||
(js-sym "+")
|
||||
(list
|
||||
(js-sym "js-to-number")
|
||||
(list (js-sym "js-get-prop") obj-sx key-sx))
|
||||
delta))))
|
||||
(else (error "js-transpile-prefix: unsupported target"))))))
|
||||
|
||||
(define
|
||||
js-transpile-postfix
|
||||
(fn
|
||||
(op target)
|
||||
(let
|
||||
((delta (if (= op "++") 1 -1)))
|
||||
(cond
|
||||
((js-tag? target "js-ident")
|
||||
(let
|
||||
((name (nth target 1)))
|
||||
(let
|
||||
((sxname (js-sym name)))
|
||||
(list
|
||||
(js-sym "let")
|
||||
(list
|
||||
(list
|
||||
(js-sym "__js_old__")
|
||||
(list (js-sym "js-to-number") sxname)))
|
||||
(list
|
||||
(js-sym "set!")
|
||||
sxname
|
||||
(list (js-sym "+") (js-sym "__js_old__") delta))
|
||||
(js-sym "__js_old__")))))
|
||||
((js-tag? target "js-member")
|
||||
(let
|
||||
((obj-sx (js-transpile (nth target 1))) (key (nth target 2)))
|
||||
(list
|
||||
(js-sym "let")
|
||||
(list
|
||||
(list (js-sym "__js_obj__") obj-sx)
|
||||
(list
|
||||
(js-sym "__js_old__")
|
||||
(list
|
||||
(js-sym "js-to-number")
|
||||
(list (js-sym "js-get-prop") (js-sym "__js_obj__") key))))
|
||||
(list
|
||||
(js-sym "js-set-prop")
|
||||
(js-sym "__js_obj__")
|
||||
key
|
||||
(list (js-sym "+") (js-sym "__js_old__") delta))
|
||||
(js-sym "__js_old__"))))
|
||||
((js-tag? target "js-index")
|
||||
(let
|
||||
((obj-sx (js-transpile (nth target 1)))
|
||||
(key-sx (js-transpile (nth target 2))))
|
||||
(list
|
||||
(js-sym "let")
|
||||
(list
|
||||
(list (js-sym "__js_obj__") obj-sx)
|
||||
(list (js-sym "__js_key__") key-sx)
|
||||
(list
|
||||
(js-sym "__js_old__")
|
||||
(list
|
||||
(js-sym "js-to-number")
|
||||
(list
|
||||
(js-sym "js-get-prop")
|
||||
(js-sym "__js_obj__")
|
||||
(js-sym "__js_key__")))))
|
||||
(list
|
||||
(js-sym "js-set-prop")
|
||||
(js-sym "__js_obj__")
|
||||
(js-sym "__js_key__")
|
||||
(list (js-sym "+") (js-sym "__js_old__") delta))
|
||||
(js-sym "__js_old__"))))
|
||||
(else (error "js-transpile-postfix: unsupported target"))))))
|
||||
|
||||
(define
|
||||
js-param-sym
|
||||
(fn
|
||||
|
||||
Reference in New Issue
Block a user