live/rpn-target.ss
#lang scheme/base

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

(provide (all-defined-out))


;; 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.

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

;; IDENTIFIERS refer to one of
;;
;;   - prefix parsing macros that escape the default semantics (see
;;   commands.ss)
;;
;;   - names of on-target binary code.  such will be executed.
;;
;;   - names of composite macros.  such will be expanded and attempted
;;   to be interpreted as code/data.
;;
;;   - scat functions (or automatically lifted scheme functions).


;; Classical Forth doesn't interpret macros at the console, 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.

;; If identifiers do not have bound syntax, interpretation is delayed
;; until runtime.  The target: language always runs interactively with
;; an associated toplevel namespace for maximum debugging flexibility.


;; FIXME: this prefers code over data, instead of the first one found.
;; Might need to do it differently?

(define (target-interpret sym)
  (define defined? (make-ns-defined? sym))
  (cond
   ((target-find-code sym) => (lambda (x) (live: ',x texec/b)))
   ((target-find-data sym) => (lambda (x) (live: ',x >t)))
   ((defined? '(macro))    => (lambda (x) (live: ',x tsim)))
   (else (live-interpret sym))))
   
(define-syntax-rule (target id)
  (target-interpret 'id))

;; Abstracted out: used in other target-like language parsers.
(define-syntax-rule (target-parse (ns push) code ...)
  (make-word
   (rpn-parse (rpn:-compile
               ns
               scat-apply
               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 ...)
  (target-parse ((target)
                 target-push)
                code ...))
             
(define-syntax-rule (target> code ...)
  (void ((target: code ...) (state:stack))))

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