You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
typesetting/quad2/pipeline.rkt

80 lines
3.0 KiB
Racket

#lang debug racket/base
(require racket/match
racket/string
(for-syntax racket/base)
"param.rkt"
"quad.rkt")
(provide (all-defined-out))
(define (list-of proc)
(λ (x)
(and (list? x)
(for/and ([xi (in-list x)])
(or (proc xi)
(let ([procname (object-name proc)])
(raise-argument-error
(string->symbol (format "list-of ~a" procname))
(symbol->string procname) xi)))))))
(struct pipeline (passes)
#:guard (λ (procs name)
(unless ((list-of procedure?) procs)
(raise-argument-error 'bad-input-to-compiler-constructor "list of procedures" procs))
procs)
#:property prop:procedure
(λ args
(match-define (list* pipeline pass-arg _) args)
(let ([show-timing? (current-show-timing?)])
(for/fold ([pass-arg pass-arg])
([pass (in-list (pipeline-passes pipeline))])
(define thunk (λ () (pass pass-arg)))
(if show-timing?
(time (displayln pass) (thunk))
(thunk))))))
(define (make-pipeline . passes)
(pipeline passes))
(define (compiler-append c passes)
(make-pipeline (append (pipeline-passes c) passes)))
(define-syntax (define-pass stx)
(syntax-case stx ()
[(_ (PASS-NAME ARG OTHER-ARG ...)
#:pre PRECOND-PROC
#:post POSTCOND-PROC
EXPRS ...)
#`(define PASS-NAME
(make-pipeline
(procedure-rename
#,(syntax/loc stx
(λ (ARG)
(define ((make-failure-handler failure-msg) exn)
(raise (make-exn:fail:contract
(string-replace (exn-message exn) "contract violation" (string-append "contract violation in " failure-msg)) (exn-continuation-marks exn))))
(when (current-use-preconditions?)
(define failure-msg (format "~a pass (as precondition)" 'PASS-NAME))
(with-handlers ([exn:fail:contract? (make-failure-handler failure-msg)])
(unless (PRECOND-PROC ARG)
(raise-argument-error 'PASS-NAME (format "~a" 'PRECOND-PROC) ARG))))
;; a pass can be functional or mutational.
;; if it returns void, assume mutational
;; and return the input item.
(define res (match (let () EXPRS ...)
[(? void?) ARG]
[val val]))
(begin0
res
(when (current-use-postconditions?)
(define failure-msg (format "~a pass (as postcondition)" 'PASS-NAME))
(with-handlers ([exn:fail:contract? (make-failure-handler failure-msg)])
(unless (POSTCOND-PROC res)
(raise-argument-error 'PASS-NAME (format "~a" 'POSTCOND-PROC) ARG)))))))
'PASS-NAME)))]))
(define-pass (print-pass qs)
#:pre values
#:post values
(for-each println qs))