#lang scheme/base
(require "../rpn.ss"
"../macro.ss"
"../tools.ss"
(for-syntax scheme/base
"../forth/lexer-tx.ss"
"../rpn.ss"
"../forth/forth-tx.ss"))
(provide (all-defined-out))
(define-syntax macro-word
(syntax-rules ()
((_ _ _ #f _ . code) (word-trap-anon . code)) ((_ register! wrap name compile code ...)
(ns (macro)
(define name
(wrap 'name #f (compile code ...)))))))
(define-syntax-rule (word-trap-anon) (begin))
(define-syntax define/false
(syntax-rules ()
((_ _ #f _) (begin)) ((_ (n ...) name value) (ns (n ...) (define name value)))))
(define-syntax forth-word
(syntax-rules ()
((_ register! wrap name compile code ...)
(begin
(define-values
(label wrapper inline)
(wrap 'name #f (compile code ...)))
(define/false (target) name label)
(define/false (macro) name wrapper)
(define/false (inline) name inline)
(register! inline)))))
(define-syntax-rule (forth-begin/init init code ...)
(rpn-parse (begin
(macro)
scat-apply
macro-push
macro-push
macro:
init)
code ...))
(define-syntax-rule (provide-words w ...)
(provide
(ns-out (target) w) ...
(ns-out (macro) w) ...
(ns-out (inline) w) ...))
(begin-for-syntax
(define (with-mode def-word register! wrap)
(make-rpn-forth-definition-transformer
(lambda (name)
#`(#,def-word #,register! #,wrap #,name rpn-lambda))))
(define (last-mode register! forthword wrapword macroword wrapmacro)
(make-rpn-same-definition-transformer
(lambda (d) (let ((entry (d-last d)))
(rpn-make-header->compile
(lambda (name)
(syntax-case entry (macro-word)
((macro-word . _) #`(#,macroword #,register! #,wrapmacro #,name rpn-lambda))
(else #`(#,forthword #,register! #,wrapword #,name rpn-lambda)))))))))
(define (stx->path it)
(let* ((it (syntax->datum it))
(it (if (symbol? it) (symbol->string it) it)))
(string->path it)))
)
(define-syntax-rule (define-forth
(forth-begin forth macro : :macro :forth :variable)
(reg wrap-macro wrap-word wrap-variable))
(begin
(ns (macro) (define-syntax :macro (with-mode #'macro-word #'reg #'wrap-macro)))
(ns (macro) (define-syntax :forth (with-mode #'forth-word #'reg #'wrap-word)))
(ns (macro) (define-syntax :variable (with-mode #'forth-word #'reg #'wrap-variable)))
(ns (macro) (define-syntax : (last-mode #'reg
#'forth-word #'wrap-word
#'macro-word #'wrap-macro)))
(prefix-parsers
(macro)
((forth) (:forth #f)) ((macro) (:macro #f)))
(define-syntax-rule (forth-begin . code)
(forth-begin-empty
(forth-word reg wrap-word #f rpn-lambda) . code))))
(ns (macro) (define-syntax load (make-rpn-include-transformer
file->forth-syntax
stx->path
forth-path
(lambda (filename) (printf " include ~s\n" (path->string filename))))))
(ns (macro) (define-syntax expand (make-rpn-expand-transformer #'forth-begin)))
(ns (macro) (define-syntax |{| rpn-curly-brace-transformer))
(ns (macro) (define-syntax |#lang|
(rpn-syntax-rules (planet)
((_ planet spec) ())
((_ spec) ()))))
(require scheme/match)
(require "../comp/state.ss")
(define (macro-pop state n)
(let-values (((state+ popped) (state-pop state n (ns (op ? qw)))))
(apply values (cons state+ popped))))
(define-syntax-rule (macro-locals . a)
(rpn-let-locals ((macro) macro: macro-pop) . a))
(ns (macro) (define-syntax \| (make-rpn-locals-transformer #'macro-locals)))
(ns (macro) (define-syntax path (make-rpn-path-transformer stx->path)))
(define-syntax (require-sym stx)
(syntax-case stx ()
((_ sym)
#`(require #,(path->string (stx->path #'sym))))))
(ns (macro) (define-syntax provide-all
(make-rpn-transformer
(lambda (w d k)
(k (w-cdr w)
(rpn-compile-toplevel
(datum->syntax (w-car w) '(provide (all-defined-out)))
d))))))
(prefix-parsers
(macro)
((require m) (|{| require-sym m |}| expand)) ((planet m) (|{| require (planet m) |}| expand))
((provide w) (|{| provide-words w |}|))
((variable n) (:variable n 1 allot))
)