HS: implicit variable declaration, console mock, increment/decrement fix

Integration:
- hs-collect-vars: scan compiled SX for set! targets, collect symbols
- hs-handler: pre-declare collected variables in closure let-bindings
  so increment/decrement work on first use (variable persists across
  event handler calls via closure scope)

Compiler:
- Fix emit-inc/emit-dec: use expr (variable) not tgt-override (element)
- Simplify to plain (set! x (+ x amount)) since vars are pre-declared

Mock DOM:
- Add mock console object to host-global
- Add console handler (no-op) to host-call dispatch
- Override console-log/debug/error as no-op primitives to avoid
  str hitting circular refs in mock DOM elements

Fixes 4 log timeouts, 2+ increment/decrement failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-18 22:07:38 +00:00
parent dcbeb5cec5
commit d0b3b86823
2 changed files with 42 additions and 22 deletions

View File

@@ -364,10 +364,7 @@
(true (true
(let (let
((t (hs-to-sx expr))) ((t (hs-to-sx expr)))
(list (list (quote set!) t (list (quote +) t amount)))))))
(quote set!)
t
(list (quote +) (list (quote or) t 0) amount)))))))
(define (define
emit-dec emit-dec
(fn (fn
@@ -416,10 +413,7 @@
(true (true
(let (let
((t (hs-to-sx expr))) ((t (hs-to-sx expr)))
(list (list (quote set!) t (list (quote -) t amount)))))))
(quote set!)
t
(list (quote -) (list (quote or) t 0) amount)))))))
(define (define
emit-behavior emit-behavior
(fn (fn

View File

@@ -10,20 +10,46 @@
;; Returns a function (fn (me) ...) that can be called with a DOM element. ;; Returns a function (fn (me) ...) that can be called with a DOM element.
;; Uses eval-expr-cek to turn the SX data structure into a live closure. ;; Uses eval-expr-cek to turn the SX data structure into a live closure.
(define (begin
(define
hs-collect-vars
(fn
(sx)
(define vars (list))
(define
walk
(fn
(node)
(when
(list? node)
(when
(and
(> (len node) 1)
(= (first node) (quote set!))
(symbol? (nth node 1)))
(let
((name (nth node 1)))
(when
(not (some (fn (v) (= v name)) vars))
(set! vars (cons name vars)))))
(for-each walk node))))
(walk sx)
vars))
(define
hs-handler hs-handler
(fn (fn
(src) (src)
(let (let
((sx (hs-to-sx-from-source src))) ((sx (hs-to-sx-from-source src)))
(let
((extra-vars (hs-collect-vars sx)))
(let
((bindings (append (list (list (quote it) nil) (list (quote event) nil)) (map (fn (v) (list v nil)) extra-vars))))
(eval-expr-cek (eval-expr-cek
(list (list
(quote fn) (quote fn)
(list (quote me)) (list (quote me))
(list (list (quote let) bindings sx)))))))))
(quote let)
(list (list (quote it) nil) (list (quote event) nil))
sx))))))
;; ── Activate a single element ─────────────────────────────────── ;; ── Activate a single element ───────────────────────────────────
;; Reads the _="..." attribute, compiles, and executes with me=element. ;; Reads the _="..." attribute, compiles, and executes with me=element.