;; Forth interpreter loop — interpret mode only (Phase 1).
;; Reads whitespace-delimited words, looks them up, executes.
;; Numbers (parsed via BASE) push onto the data stack.
;; Unknown words raise "?".

(define
  forth-execute-word
  (fn (state word) (let ((body (get word "body"))) (body state))))

(define
  forth-interpret-token
  (fn
    (state tok)
    (let
      ((w (forth-lookup state tok)))
      (if
        (not (nil? w))
        (forth-execute-word state w)
        (let
          ((n (forth-parse-number tok (get state "base"))))
          (if
            (not (nil? n))
            (forth-push state n)
            (forth-error state (str tok " ?"))))))))

(define
  forth-interpret
  (fn
    (state src)
    (for-each
      (fn (tok) (forth-interpret-token state tok))
      (forth-tokens src))
    state))

;; Convenience: build a fresh state with primitives loaded.
(define
  forth-boot
  (fn () (let ((s (forth-make-state))) (forth-install-primitives! s) s)))

;; Run source on a fresh state and return (state, output, stack-top-to-bottom).
(define
  forth-run
  (fn
    (src)
    (let
      ((s (forth-boot)))
      (forth-interpret s src)
      (list s (get s "output") (reverse (get s "dstack"))))))
