#lang scheme/base
(require "../rpn.ss"
"../macro.ss"
"../tools.ss"
(for-syntax scheme/base
"../tools/stx.ss"
"../forth/lexer-tx.ss"
"../rpn.ss"
"../forth/forth-tx.ss"))
(provide (all-defined-out))
(define-syntax macro-word
(syntax-rules ()
((_ _ _ #f . _) (begin)) ((_ 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 forth-dictionary-log (make-parameter #f))
(define-syntax (forth-compile-dictionary stx)
(define (cleanup it)
(cond
((syntax? it) (cleanup (syntax-e it)))
((pair? it) (cons (cleanup (car it))
(cleanup (cdr it))))
((or
(null? it)
(string? it)
(number? it)
(symbol? it)) it)
(else
(format "~a" it)))) (syntax-case stx ()
((_ form ...)
#`(begin
(forth-dictionary-log '#,(cleanup #'(form ...)))
form ...))))
(define-syntax-rule (forth-begin/init init code ...)
(rpn-parse (forth-compile-dictionary
(macro)
scat-apply
macro-push
macro-push
macro:
init)
code ...))
(define-syntax-rule (provide-words w ...)
(provide
(ns-out (macro) w) ...
))
(prefix-parsers
(macro)
((|'| name) (',(macro name)))
((|`| name) ('name))
((provide w) (|{| provide-words 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)))
(cond
((symbol? it) (string->path (symbol->string it)))
((string? it) (string->path it))
((path? it) it)
(else
(raise-syntax-error #f "can't convert to path" it)))))
)
(define-syntax (define-forth-parser stx)
(syntax-case stx ()
((_ forth-begin (reg wrap-macro wrap-word wrap-variable))
(syntax-introduce-identifiers
stx
( forth macro : :macro :forth :variable variable 2variable
expand require require-file planet staapl
allot)
#`(begin
(define-syntax-rule (forth-begin . code)
(forth-begin/init (forth-word reg wrap-word #f rpn-lambda) . code)) (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)))
(ns (macro) (define-syntax expand
(make-rpn-expand-transformer
(lambda ()
#`(forth-begin #,(forth-path-dump))))))
(prefix-parsers
(macro)
((forth) (:forth #f))
((macro) (:macro #f))
((variable n) (:variable n 1 allot)) ((2variable n) (:variable n 2 allot))
((require id) (|{| require-id spec id |}| expand))
((staapl id) (|{| require-id staapl id |}| expand))
((planet id) (|{| require-id planet id |}| expand))
((require-file id) (|{| require-id file id |}| expand))
))))))
(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))))))
(ns (macro) (define-syntax load (make-rpn-include-transformer
file->forth-syntax
stx->path
(lambda (filename) (printf " include ~s\n" (path->string filename))))))
(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)))
(ns (macro) (define-syntax \[ (make-rpn-quotation-transformer
(lambda (expr) #`(macro-push (macro: #,@expr))))))
(define-syntax (require-id stx)
(define req
(syntax-case stx ()
((_ _ id)
(lambda (sexpr)
(datum->syntax #'id `(require ,sexpr))))))
(syntax-case stx (spec file planet staapl)
((_ file id) (req `(file ,(path->string (stx->path #'id)))))
((_ planet id) (req `(planet ,#'id)))
((_ staapl id) (req `(planet ,(string->symbol
(format "zwizwa/staapl/~a"
(syntax->datum #'id))))))))