#lang scheme/base

;; Forth style parsing words are implemented as binary functions bound
;; as syntax. See rpn-tx.ss : (next <code> <expr>) for more information.

(provide
 (all-defined-out))

(require
 "../scat.ss"
 "../forth.ss"
 "../coma.ss"
 "../control.ss"
 "../comp.ss"
 "../tools.ss"

 (for-syntax
  scheme/base
  "../scat-tx.ss"
  "../forth-tx.ss"
  ))

;; Definitions + forth / macro mode switch syntax.

(tx->syntax-ns (macro)
               (:       :-tx)
               (:macro  :macro-tx)
               (create  create-tx)
               (forth   forth-tx)
               (macro   macro-tx)
               (\|      locals-tx)
               (require require-tx)
               (provide provide-tx)
               (|[|     open-paren-tx)
               (|]|     close-paren-tx)
               (|{|     open-sexp-tx)
               (load    load-tx)
               (path    path-tx)
               )


;; Subtitution macros.

;; Because Forth is non-concatenative (for anything that changes the
;; semantics of names), and the macro system is purely concatenative /
;; compositional, the need arises for a mechanism to metaprogram
;; non-concatenative code.

;; In standard Forth this is implemented by a reflective operation:
;; code implementing macros has access to the current input. This
;; doesn't work in Purrr, which employs a more declarative style with
;; 'unrolled' reflection in the form of substitution macros.

(substitutions
  (macro)

  ((|`| name)       ('name))
  ((|'| name)       (',(ns (macro) name)))
  ((variable name)  (create name 1 allot))
  ((2variable name) (create name 2 allot))
  ((declare name)   (:macro name 'name undefined |;|))
  ((parameter name) (:macro name ,(make-constant 'name) |;|))
  ((|#lang| _)      ())                     
  ((string name)    (',(symbol->string 'name)))

  ;; Trouble with the word 'f->' being defined later...
  ;; ((fstring name)   (f-> string name |string,|))

  )

