#lang scheme/base

;; Forth macro language syntax.

(provide
 (all-defined-out))
(require
 "../scat-tx.ss"
 (for-template
  "../scat.ss"
  "macro-prim.ss"
  scheme/base))

;; 'lit' and 'word' are defined in macro.ss

;; Macros are SCAT word structures wrapped in a parameter.

(define (macro-immediate im e) #`((lit #,im) #,e))
(define (macro-function fn e)  #`(#,fn #,e))

;; Instead of mapping identifiers to prefixed ones on the first pass,
;; insert a reference to the 'word' macro defined in macro.ss which
;; will do it on second pass. This gives a simpler dictionary
;; representation.

;; rpn-tx.ss knows how to deal with this: it forces expansion to
;; determine if it maps to a macro identifier.

;; FIXME: somehow this doesn't really work out very well.. i switched
;; it back.
(define (macro-map-identifier id)
  ;; #`(word #,id))mac
  (ns-prefixed #'(macro) id))

;; Namespace for instantiated code.
(define (macro-map-target-identifier id)
  (ns-prefixed #'(target) id))

(define (with-macro-syntax thunk)
  (parameterize
      ((rpn-immediate              macro-immediate)
       (rpn-function               macro-function)
       (rpn-lambda                 scat-lambda)
       (rpn-map-identifier         macro-map-identifier)
       (rpn-map-target-identifier  macro-map-target-identifier)
       (rpn-context                with-macro-syntax))
    (thunk)))
