#lang scheme/base
(provide
forth-begin-tx
forth-begin-tx-debug)
(require
(for-template
scheme/base
"../scat.ss"
"../comp.ss")
scheme/pretty
"../tools.ss"
(lib "pretty.ss")
"../scat-tx.ss"
"../macro-tx.ss"
"../forth-tx.ss"
scheme/base)
(define forth-begin-tx-debug (make-parameter #f))
(define (forth-begin-tx stx init-forms register-code)
(define (toplevel-syntax expr)
(datum->syntax stx expr))
(define (record->form register! record)
(syntax-case record ()
((name lang loc rep)
(syntax-case #'lang (macro scheme)
(scheme
(toplevel-syntax #'rep))
(macro
(syntax-case #'name ()
(#f #`(void)) (_ #`(redefine!-ns
(macro) name
(wrap-macro/mexit 'name loc rep)))))
(_
(let ((wrap-macro
(syntax-case #'lang (variable forth)
(variable #'wrap-macro/postponed-variable)
(forth #'wrap-macro/postponed-word))))
(syntax-case (generate-temporaries
'(label wrapper postponed)) ()
((label wrapper postponed)
(register! #'postponed) (syntax-case #'name ()
(#f #`(define postponed rep))
(_ #`(begin
(define-values
(label
wrapper
postponed)
(#,wrap-macro 'name loc rep))
#,(redefine!-tx (rpn-map-identifier)
#'(define name wrapper))
#,(let ((target-id ((rpn-map-target-identifier) #'name)))
#`(define #,target-id label))
)))))))))))
(define (code->toplevel-form code)
(define words '())
#`(begin
#,@(map
(lambda (record)
(record->form
(lambda (x) (push! words x))
record))
(forth->records code))
(#,register-code
(target-compile (list #,@words)))))
(syntax-case stx ()
((_ . code)
(let ((form
#`(begin
#,@(toplevel-syntax init-forms)
#,(code->toplevel-form #'code))))
(when (forth-begin-tx-debug)
(pretty-print (syntax->datum form)))
form))))