#lang scheme/base
(require "../rpn.ss"
"../tools/io.ss"
"../tools/stx.ss"
)
(provide (all-defined-out))
(define-struct forth-path (here search) #:mutable)
(define current-forth-path (make-parameter (make-forth-path "." '())))
(define (forth-path-add! p)
(let ((fp (current-forth-path)))
(set-forth-path-search! fp (cons p (forth-path-search fp)))))
(define (forth-here! p)
(set-forth-path-here! (current-forth-path) p))
(define (forth-here)
(forth-path-here (current-forth-path)))
(define (forth-search)
(forth-path-search (current-forth-path)))
(define (forth-path-dump)
(let ((fp (current-forth-path)))
(rpn-begin! (current-forth-path fp))))
(define (make-rpn-path-transformer stx->path)
(make-rpn-transformer
(lambda (w d k)
(forth-path-add! (stx->path (w-cadr w)))
(k (w-cddr w) d))))
(define-syntax-rule (rpn-begin! . body)
(make-rpn-transformer
(lambda (w d k)
(begin . body)
(k (w-cdr w) d))))
(define (make-rpn-locals-transformer locals)
(make-rpn-transformer
(lambda (w d k)
(let next ((w (w-cdr w))
(l '()))
(let ((f (w-car w)))
(if (eq? '\| (syntax->datum f))
(k (w-cdr w)
(d-compile #`(#,locals #,(reverse l)) d))
(next (w-cdr w)
(cons f l))))))))
(define (make-rpn-definition-transformer compile)
(make-rpn-same-definition-transformer (lambda (d) compile)))
(define (make-rpn-same-definition-transformer get-compile)
(rpn-dict-rule d (name)
(let ((compile (get-compile d))) (let* ((d (d-start d))
(d (compile #'name d))) d))))
(define (rpn-compile-toplevel stx d)
(d-insert (syntax->list/recertify stx) d))
(define (make-rpn-sexp-transformer open close compile-sexp)
(make-rpn-transformer
(lambda (w-in d k)
(define (collect w-start)
(let next ((w w-start)
(l '()))
(when (w-null? w)
(raise-syntax-error
#f (format "expected '~a', sexp starts" close)
(car w-in)))
(let ((w-sym (syntax->datum (w-car w)))
(w+ (w-cdr w)))
(cond
((eq? open w-sym)
(let-values (((w-next lst) (collect w+)))
(next w-next
(cons lst l))))
((eq? close w-sym)
(values w+
(datum->syntax #f (reverse l)))) (else
(next w+
(cons (w-car w) l)))))))
(let-values (((w-next s) (collect (w-cdr w-in))))
(k w-next (compile-sexp s d))))))
(define (make-rpn-parameterize-transformer param init-state compile-state)
(lambda (w d k)
(let-values
(((d+ k)
(parameterize ((param init-state))
(printf "nesting: ~a\n" param)
(rpn-parse-nested (w-cdr w) d k))))
(k '() (compile-state (param) d+)))))
(define (make-rpn-include-transformer file->syntax
filename-syntax->string
[logger void])
(make-rpn-transformer
(lambda (w d k)
(let ((here (forth-here))) (let ((filename-stx (w-cadr w))
(w-rest (w-cddr w)))
(let* ([filename
(filename-syntax->string filename-stx)]
[search-path
(cons here (forth-search))]
[resolved-filename
(resolve-path-list filename search-path)]
[dir
(filename->path resolved-filename)])
(logger resolved-filename)
(forth-here! dir)
(k (w-append
(file->syntax resolved-filename filename-stx)
(list (rpn-begin! (forth-here! here)))
w-rest)
d)))))))
(define (make-rpn-expand-transformer begin-stx-thunk)
(make-rpn-transformer
(lambda (w d k)
(let* ((header (begin-stx-thunk)) (footer (w-cdr w))
(form #`(#,@header #,@footer))
(form/r (syntax-recertify form header (current-code-inspector) #f)))
(k '() (rpn-compile-toplevel form/r d))))))
(define (rpn-make-header->compile make-header)
(lambda (n d)
(foldl d-compile d (syntax->list/recertify (make-header n)))))
(define (make-rpn-forth-definition-transformer make-header)
(make-rpn-definition-transformer
(rpn-make-header->compile make-header)))
(define rpn-curly-brace-transformer
(make-rpn-sexp-transformer
(string->symbol "{")
(string->symbol "}")
rpn-compile-toplevel))
(define (make-rpn-quotation-transformer compile)
(let ((open (string->symbol "["))
(close (string->symbol "]")))
(make-rpn-sexp-transformer
open close
(lambda (expr dict)
(d-compile (compile expr) dict)))))
(define rpn-slurp
(make-rpn-transformer
(lambda (w d k)
(let ((parser (w-cadr w))
(rest (w-cddr w)))
(k (list parser rest) d)))))