#lang scheme/base

(require
 "../target.ss"
 "../scat.ss"
 "../ns.ss"
 "../rpn.ss"
 "../macro.ss"
 "tethered.ss"
 "commands.ss"
 "../forth/forth-lex.ss"
 (for-syntax
  "../ns-tx.ss"
  scheme/base))

(provide target:
         target
         forth-command)

;; The target: language is used for interaction with a live machine.
;; It provides a simulation of a Forth console.  The target: form
;; produces a scat function.  The body forms have the following
;; semantics:

;; LITERALS are moved to the target parameter stack.
(define-syntax-rule (target-push  im p sub)
  (let ((p ((scat: 'im >t) p))) sub))

;; IDENTIFIERS refer to one of:
;;   - names of on-target binary code.  such will be executed.
;;   - names of composite macros.  such will be expanded and possibly interpreted as code/data (*)
;;   - prefix parsing macros that escape this default semantics (see
;;     commands.ss)

;; (*) Classical Forth doesn't do this, but since Coma Forth is based
;; heavily on macros, interaction would be quite painful without first
;; instantiating some macros as binary code on the target.  Note that
;; this is basicly a hack, and not all macros can be instantiated.

(define-syntax (target stx)
  (syntax-case stx ()
    ((_ id) (and (identifier? #'id)
                 (not (identifier-binding
                       (ns-prefixed #'(target) #'id))))
     #`(scat: ',(macro id) tsim))
    ((_ form)
     #`(scat: ',(ns (target) form) texec/w))))


(define-syntax-rule (target: code ...)
  (rpn-parse (rpn:-compile
              (target)
              scat-apply
              target-push
              scat-push    ;; Program quotations are not used in target language,
              scat:        ;; so they escape to scat.
              (rpn-lambda)
              ) code ...))
             
(define-syntax-rule (target> code ...)
  (void ((target: code ...) (state:stack))))

(define-syntax-rule (forth-command str)
  (forth-lex-string/cps target> str))
