#lang scheme/base
(provide (all-defined-out))
(require "../rpn.ss"
"../tools.ss"
"../ns.ss"
"../macro.ss"
"../forth/forth-lex.ss"
scheme/stxparam
scheme/splicing
scheme/pretty
(for-syntax scheme/base
scheme/pretty
"../tools.ss"
"../forth/forth-tx.ss"
"../rpn.ss"))
(define-for-syntax (mcf-not-defined stx)
(raise-syntax-error #f "undefined syntax parameter" stx))
(define-syntax-rule (mcf-params: p ...)
(begin (define-syntax-parameter p mcf-not-defined) ...))
(mcf-params: mcf mcf-push mcf: word variable immediate)
(define-syntax-rule (mcf-parse begin-dict code ...)
(rpn-parse (begin-dict
(mcf)
scat-apply
mcf-push
mcf-push
mcf:
(word #f) ) code ...))
(ns (mcf)
(define-syntax \:
(make-rpn-forth-definition-transformer
(lambda (name)
#`(word #,name)))))
(ns (mcf)
(define-syntax variable
(make-rpn-forth-definition-transformer
(lambda (name)
#`(variable #,name)))))
(ns (mcf)
(define-syntax immediate
(make-rpn-transformer
(lambda (w d k)
(define (->immediate lst)
(cons #'immediate (cdr lst)))
(k (w-cdr w)
(d-on-last d ->immediate))))))
(prefix-parsers
(mcf)
((| ((postpone word) ('word |compile,|)))
(define-syntax-rule (quote-dict entry ...)
(quote (entry ...)))
(define-syntax-rule (begin-dict _ entry ...) (begin entry ...))
(define-syntax-rule (define-word name . code)
(ns (postponed) (define name (rpn-lambda . code))))
(define-for-syntax slv syntax-local-value)
(define-syntax-rule (target-begin code ...)
(splicing-syntax-parameterize
((mcf (slv #'macro))
(mcf-push (slv #'macro-push))
(word (slv #'define-word))
(immediate (slv #'define-word))
(variable (slv #'define-word)))
(mcf-parse begin-dict code ...)))
(define-syntax-rule (lifted-begin code ...)
(splicing-syntax-parameterize
((mcf (slv #'scat))
(mcf-push (slv #'scat-push))
(word (slv #'lift-word))
(immediate (slv #'lift-immediate))
(variable (slv #'lift-variable)))
(mcf-parse begin-dict-pruned code ...)))
(define-syntax-rule (forth-begin code ...)
(begin
(target-begin code ...)
(lifted-begin code ...)))
(define-syntax-rule (lift target-ns name . code)
(ns target-ns (define name (rpn-lambda . code))))
(define-syntax-rule (lift-immediate . def) (lift (macro) . def))
(define-syntax-rule (lift-word . def) (lift (scat) . def))
(define-syntax-rule (lift-variable name)
(ns (scat) (define name #f)))
(define-syntax (begin-dict-pruned stx)
(define entries (cddr (syntax->list stx)))
(define-hashes imms dict deps dropped)
(define (code->deps stx)
(filter
id
(for/list ((c (syntax->list stx)))
(syntax-case c (mcf)
((_ (mcf id)) (syntax->datum #'id))
(_ #f)))))
(define (parse!)
(for ((e entries))
(syntax-case e ()
((semantics name . code)
(when (eq? 'immediate (datum #'semantics))
(id-reg! imms #'name))
(id-reg! dict #'name (code->deps #'code))))))
(define (mark!)
(for ((d (dependencies
(lambda (id) (id-find dict id))
(ids imms))))
(id-reg! deps d)))
(define (necessary!? stx)
(syntax-case stx (immediate)
((immediate . _) #t)
((_ name . _)
(if* (id-find deps #'name) it
(false (id-reg! dropped #'name))))))
(define (sweep!)
(let ((filtered-entries
(filter necessary!? entries)))
(printf "used: ~a\n" (ids deps))
(printf "dropped: ~a\n" (ids dropped))
#`(begin #,@filtered-entries)))
(parse!)
(mark!)
(sweep!))
(define-syntax-rule (boot file)
(forth-lex-file/cps forth-begin file))