diff --git a/src/compiler/pass.rkt b/src/compiler/pass.rkt index a23d776..986a28d 100644 --- a/src/compiler/pass.rkt +++ b/src/compiler/pass.rkt @@ -11,22 +11,26 @@ (provide (struct-out pass) run-pass sequence debug schema non-empty-string? non-empty-list? non-empty-hash? a-symbol? a-number? a-string? - a-pair? a-list? list-of? a-set? a-function? ast-subset? + a-pair? a-list? list-of? a-set? a-function? ast-subset? not-nil? schema-validation-error?) -(struct pass (schema transform) #:transparent) +(struct pass (input-schema transform output-schema) #:transparent) (define (run-pass pass env) - (unless (env-contains? env 'no-validation) - ((pass-schema pass) env)) - ((pass-transform pass) env)) + (if (env-contains? env 'no-validation) + ((pass-transform pass) env) + (let* ((pre ((pass-input-schema pass) env)) + (result ((pass-transform pass) env)) + (post ((pass-output-schema pass) result))) + result))) (define (sequence . passes) (pass (schema "sequence") (lambda (env) (foldl run-pass env - passes)))) + passes)) + (schema "sequence output"))) (define (schema hint . properties) (lambda (env) @@ -49,7 +53,12 @@ (pass (schema "debug") (lambda (env) (pretty-print (ast->plain (env-get env 'ast))) - env))) + env) + (schema "debug output"))) + +(define (not-nil? val) + (when (equal? val '()) + (schema-validation-error "Not a non-nil value" val))) (define (non-empty-string? val) (unless (and (string? val) diff --git a/src/compiler/passes/alpha-conversion.rkt b/src/compiler/passes/alpha-conversion.rkt index d2ed696..5f58fe0 100644 --- a/src/compiler/passes/alpha-conversion.rkt +++ b/src/compiler/passes/alpha-conversion.rkt @@ -20,7 +20,9 @@ (pass (schema "alpha-convert" 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))) (lambda (env) - (env-update env 'ast (partial alpha-rename (make-subs '())))))) + (env-update env 'ast (partial alpha-rename (make-subs '())))) + (schema "alpha-convert output" + 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))))) (define (alpha-rename subs expr) (define (loop subs expr) diff --git a/src/compiler/passes/bindings.rkt b/src/compiler/passes/bindings.rkt index 45f47e3..2e5e629 100644 --- a/src/compiler/passes/bindings.rkt +++ b/src/compiler/passes/bindings.rkt @@ -19,7 +19,11 @@ if do let letrec binding lambda app primop-app def ))) (lambda (env) - (env-update env 'ast (partial analyze-bindings #f))))) + (env-update env 'ast (partial analyze-bindings #f))) + (schema "annotate-bindings output" + 'ast (ast-subset? '(const symbol + if do let letrec binding lambda app + primop-app def ))))) (define (analyze-bindings within-letrec? expr) (match-ast expr diff --git a/src/compiler/passes/builtins.rkt b/src/compiler/passes/builtins.rkt index 23a0392..74cd5c4 100644 --- a/src/compiler/passes/builtins.rkt +++ b/src/compiler/passes/builtins.rkt @@ -19,7 +19,9 @@ 'intrinsics a-list? 'ast (ast-subset? '(const symbol if do let letrec binding lambda app primop-app))) (lambda (env) - (env-update env 'ast (partial inline-app-ops (env-get env 'intrinsics)))))) + (env-update env 'ast (partial inline-app-ops (env-get env 'intrinsics)))) + (schema "inline-builtins output" + 'ast (ast-subset? '(const symbol if do let letrec binding lambda app primop-app))))) (define (inline-app-ops builtins expr) (substitute (lambda (subs expr kont) diff --git a/src/compiler/passes/closures.rkt b/src/compiler/passes/closures.rkt index 72b3d16..bc56ecf 100644 --- a/src/compiler/passes/closures.rkt +++ b/src/compiler/passes/closures.rkt @@ -19,10 +19,11 @@ (define closure-convert (pass (schema "closure-convert" 'globals a-set? - 'ast (ast-subset? '(const symbol - if do let fix binding lambda app primop-app))) + 'ast (ast-subset? '(const symbol if do let fix binding lambda app primop-app))) (lambda (env) - (env-update env 'ast (flip convert-closures (env-get env 'globals)))))) + (env-update env 'ast (flip convert-closures (env-get env 'globals)))) + (schema "closure-convert output" + 'ast (ast-subset? '(const symbol if do let fix binding lambda app primop-app))))) (define (convert-closures expr globals) (match-ast expr diff --git a/src/compiler/passes/const-folding.rkt b/src/compiler/passes/const-folding.rkt index d8a84bd..dab8485 100644 --- a/src/compiler/passes/const-folding.rkt +++ b/src/compiler/passes/const-folding.rkt @@ -16,7 +16,9 @@ (pass (schema "fold-constants" 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))) (lambda (env) - (env-update env 'ast constant-folding)))) + (env-update env 'ast constant-folding)) + (schema "fold-constants output" + 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))))) (define (constant-folding expr) (map-ast (lambda (expr) diff --git a/src/compiler/passes/const-propagation.rkt b/src/compiler/passes/const-propagation.rkt index 08fd8aa..f0ab086 100644 --- a/src/compiler/passes/const-propagation.rkt +++ b/src/compiler/passes/const-propagation.rkt @@ -18,7 +18,9 @@ (pass (schema "propagate-constants" 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))) (lambda (env) - (env-update env 'ast (partial constant-propagation (make-subs '())))))) + (env-update env 'ast (partial constant-propagation (make-subs '())))) + (schema "propagate-constants output" + 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))))) (define (constant-propagation subs expr) (propagate const-binding? diff --git a/src/compiler/passes/const.rkt b/src/compiler/passes/const.rkt index 28feafc..602b7ae 100644 --- a/src/compiler/passes/const.rkt +++ b/src/compiler/passes/const.rkt @@ -19,7 +19,11 @@ if do let letrec binding lambda app primop-app def ))) (lambda (env) - (env-update env 'ast wrap-constants)))) + (env-update env 'ast wrap-constants)) + (schema "annotate-constants output" + 'ast (ast-subset? '(const number symbol string list + if do let letrec binding lambda app + primop-app def ))))) (define (wrap-constants expr) (case (ast-node-type expr) diff --git a/src/compiler/passes/copy-propagation.rkt b/src/compiler/passes/copy-propagation.rkt index b2d39c9..bc8f70a 100644 --- a/src/compiler/passes/copy-propagation.rkt +++ b/src/compiler/passes/copy-propagation.rkt @@ -18,7 +18,9 @@ (pass (schema "propagate-copies" 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))) (lambda (env) - (env-update env 'ast (partial copy-propagation (make-subs '())))))) + (env-update env 'ast (partial copy-propagation (make-subs '())))) + (schema "propagate-copies output" + 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))))) (define (copy-propagation subs expr) (propagate symbol-binding? diff --git a/src/compiler/passes/cpc.rkt b/src/compiler/passes/cpc.rkt index 5c7eeca..acf9a4b 100644 --- a/src/compiler/passes/cpc.rkt +++ b/src/compiler/passes/cpc.rkt @@ -22,7 +22,9 @@ 'ast (ast-subset? '(const symbol if do let fix binding lambda app primop-app))) (lambda (env) (env-update env 'ast (lambda (expr) - (cpc expr #f (make-identity-continuation))))))) + (cpc expr #f (make-identity-continuation))))) + (schema "continuation-passing-convert output" + 'ast (ast-subset? '(const symbol if do let fix binding lambda app primop-app))))) (define (make-identity-continuation) id) diff --git a/src/compiler/passes/cse.rkt b/src/compiler/passes/cse.rkt index 106ca43..96e5381 100644 --- a/src/compiler/passes/cse.rkt +++ b/src/compiler/passes/cse.rkt @@ -19,7 +19,9 @@ 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))) (lambda (env) (env-update env 'ast (lambda (expr) - (cse (subexpr-extractor (env-get env 'intrinsics)) '() expr)))))) + (cse (subexpr-extractor (env-get env 'intrinsics)) '() expr)))) + (schema "eliminate-common-subexpressions output" + 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))))) (define (cse extract-subexprs subexprs expr) (let loop ((subexprs subexprs) diff --git a/src/compiler/passes/dce.rkt b/src/compiler/passes/dce.rkt index 9efe6ca..7698e41 100644 --- a/src/compiler/passes/dce.rkt +++ b/src/compiler/passes/dce.rkt @@ -19,7 +19,9 @@ (pass (schema "eliminate-dead-code" 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))) (lambda (env) - (env-update env 'ast (partial dce (set)))))) + (env-update env 'ast (partial dce (set)))) + (schema "eliminate-dead-code output" + 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))))) (define (dce eta-disallow expr) (match-ast expr diff --git a/src/compiler/passes/errors.rkt b/src/compiler/passes/errors.rkt index bd70db8..9fdc3e6 100644 --- a/src/compiler/passes/errors.rkt +++ b/src/compiler/passes/errors.rkt @@ -22,7 +22,8 @@ (source-order errors)) (raise-compilation-error (location 0 0) (format "Compilation aborted due to ~s errors." (length errors)))) - env)))) + env)) + (schema "report-errors output"))) (define (report-error env error) (let* ((location (compilation-error-location error)) diff --git a/src/compiler/passes/freevars.rkt b/src/compiler/passes/freevars.rkt index b0f3d15..696c0c3 100644 --- a/src/compiler/passes/freevars.rkt +++ b/src/compiler/passes/freevars.rkt @@ -18,7 +18,11 @@ if do let letrec fix binding lambda app ;; NOTE fix, since this pass is used multiple times. primop-app def ))) (lambda (env) - (env-update env 'ast compute-free-vars)))) + (env-update env 'ast compute-free-vars)) + (schema "annotate-free-vars output" + 'ast (ast-subset? '(const symbol + if do let letrec fix binding lambda app + primop-app def ))))) (define (compute-free-vars expr) (map-ast (lambda (expr) diff --git a/src/compiler/passes/generator.rkt b/src/compiler/passes/generator.rkt index f2e2dc1..5497988 100644 --- a/src/compiler/passes/generator.rkt +++ b/src/compiler/passes/generator.rkt @@ -19,4 +19,6 @@ (generate-js env)) (else (generate-scheme env))))) - (env-set env 'generated gen))))) + (env-set env 'generated gen))) + (schema "generate-target-code output" + 'generated not-nil?))) diff --git a/src/compiler/passes/globalization.rkt b/src/compiler/passes/globalization.rkt index a8a11b9..b0cda60 100644 --- a/src/compiler/passes/globalization.rkt +++ b/src/compiler/passes/globalization.rkt @@ -22,7 +22,11 @@ (-> env (env-remove 'ast) (env-set 'data (car result) - 'init (cadr result))))))) + 'init (cadr result))))) + (schema "globalize output" + 'data (list-of? (a-pair? a-symbol? + (ast-subset? '(const symbol if do let binding lambda primop-app)))) + 'init (ast-subset? '(const symbol if do let binding primop-app))))) (define (hoist-values expr) (let* ((hoisted '()) diff --git a/src/compiler/passes/instrument.rkt b/src/compiler/passes/instrument.rkt index c053458..a228f9e 100644 --- a/src/compiler/passes/instrument.rkt +++ b/src/compiler/passes/instrument.rkt @@ -11,4 +11,5 @@ (pass (schema "instrument" 'instrument a-function?) (lambda (env) - (env-update env 'ast (env-get env 'instrument))))) + (env-update env 'ast (env-get env 'instrument))) + (schema "instrument output"))) diff --git a/src/compiler/passes/lambdas.rkt b/src/compiler/passes/lambdas.rkt index ff84de4..bd7fe94 100644 --- a/src/compiler/passes/lambdas.rkt +++ b/src/compiler/passes/lambdas.rkt @@ -21,7 +21,9 @@ (pass (schema "inline-lambdas" 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))) (lambda (env) - (env-update env 'ast (partial lambda-inlining '()))))) + (env-update env 'ast (partial lambda-inlining '()))) + (schema "inline-lambdas output" + 'ast (ast-subset? '(const symbol if do let letrec fix binding lambda app primop-app))))) (define (lambda-inlining lambdas expr) (let ((loop (partial traverse-ast lambda-inlining lambdas))) diff --git a/src/compiler/passes/letrec-bindings.rkt b/src/compiler/passes/letrec-bindings.rkt index d937be0..eab16cd 100644 --- a/src/compiler/passes/letrec-bindings.rkt +++ b/src/compiler/passes/letrec-bindings.rkt @@ -56,10 +56,11 @@ (define reorder-letrec-bindings (pass (schema "reorder-letrec-bindings" - 'ast (ast-subset? '(const symbol - if do let letrec binding lambda app primop-app))) + 'ast (ast-subset? '(const symbol if do let letrec binding lambda app primop-app))) (lambda (env) - (env-update env 'ast reorder-letrec)))) + (env-update env 'ast reorder-letrec)) + (schema "reorder-letrec-bindings output" + 'ast (ast-subset? '(const symbol if do let letrec binding lambda app primop-app))))) (define (reorder-letrec expr) (map-ast (lambda (expr) diff --git a/src/compiler/passes/letrec-fix.rkt b/src/compiler/passes/letrec-fix.rkt index 31aa904..fb45351 100644 --- a/src/compiler/passes/letrec-fix.rkt +++ b/src/compiler/passes/letrec-fix.rkt @@ -18,10 +18,11 @@ (define fix-letrec (pass (schema "fix-letrec" - 'ast (ast-subset? '(const symbol - if do let letrec binding lambda app primop-app))) + 'ast (ast-subset? '(const symbol if do let letrec binding lambda app primop-app))) (lambda (env) - (env-update env 'ast fixing-letrec)))) + (env-update env 'ast fixing-letrec)) + (schema "fix-letrec output" + 'ast (ast-subset? '(const symbol if do let fix binding lambda app primop-app))))) (define (fixing-letrec expr) (map-ast (lambda (expr) diff --git a/src/compiler/passes/macro-expander.rkt b/src/compiler/passes/macro-expander.rkt index fb01317..e055f03 100644 --- a/src/compiler/passes/macro-expander.rkt +++ b/src/compiler/passes/macro-expander.rkt @@ -26,4 +26,10 @@ (env-get env 'ast)))))) (env-set env 'ast (car result) - 'errors (cadr result)))))) + 'errors (cadr result)))) + (schema "macro-expand output" + 'errors a-list? + 'ast (ast-subset? '(quote quasiquote unquote unquote-splicing + number symbol string list + if do let letrec binding lambda app + primop-app def ))))) diff --git a/src/compiler/passes/metadata.rkt b/src/compiler/passes/metadata.rkt index f46e6cb..da7edbc 100644 --- a/src/compiler/passes/metadata.rkt +++ b/src/compiler/passes/metadata.rkt @@ -12,9 +12,7 @@ (define extract-metadata (pass (schema "extract-metadata" - 'ast (ast-subset? '(const symbol - if do let letrec binding lambda app - primop-app def )) + 'ast (ast-subset? '(const symbol if do let letrec binding lambda app primop-app def )) 'intrinsics a-list?) (lambda (env) (let* ((ast (env-get env 'ast)) @@ -24,7 +22,10 @@ (updated (cdr result))) (env-set env 'ast updated - 'intrinsics primitives))))) + 'intrinsics primitives))) + (schema "extract-metadata output" + 'ast (ast-subset? '(const symbol if do let letrec binding lambda app primop-app def )) + 'intrinsics a-list?))) (define (extract-intrinsics-metadata ast) (define (replace-with-nil expr) diff --git a/src/compiler/passes/optimize.rkt b/src/compiler/passes/optimize.rkt index becd93d..625df36 100644 --- a/src/compiler/passes/optimize.rkt +++ b/src/compiler/passes/optimize.rkt @@ -22,7 +22,8 @@ ((naive) optimize-naive) ((super) optimize-super))) passes - env))))) + env))) + (schema "optimize output"))) (define +optimization-loops+ 23) diff --git a/src/compiler/passes/parser.rkt b/src/compiler/passes/parser.rkt index f441dcd..92b49b4 100644 --- a/src/compiler/passes/parser.rkt +++ b/src/compiler/passes/parser.rkt @@ -297,7 +297,12 @@ "Expected a Spartan module, found something else:"))))))) (env-set env 'ast (car result) - 'errors (cadr result)))))) + 'errors (cadr result)))) + (schema "parse output" + 'ast (ast-subset? '(quote quasiquote unquote unquote-splicing + number symbol string list + primop-app body )) + 'errors a-list?))) (define no-inline ;; NOTE Prevents inlining of this rule making it hit the cache more often and perform better. diff --git a/src/compiler/passes/qq.rkt b/src/compiler/passes/qq.rkt index 7e2d0a2..36b1ddf 100644 --- a/src/compiler/passes/qq.rkt +++ b/src/compiler/passes/qq.rkt @@ -26,7 +26,13 @@ (expand-quasiquote (env-get env 'ast)))))) (env-set env 'ast (car result) - 'errors (cadr result)))))) + 'errors (cadr result)))) + (schema "quasiquote-expand output" + 'errors a-list? + 'ast (ast-subset? '(quote quasiquote unquote unquote-splicing ;; NOTE Quasiquote et al can appear with (quote ,@value) + number symbol string list + if do let letrec binding lambda app + primop-app def ))))) (define (expand-quasiquote expr) (case (ast-node-type expr) diff --git a/src/compiler/passes/rename.rkt b/src/compiler/passes/rename.rkt index 366066d..439c4d0 100644 --- a/src/compiler/passes/rename.rkt +++ b/src/compiler/passes/rename.rkt @@ -24,7 +24,11 @@ (map (lambda (v) (cons (symbol->safe (car v)) (mangle-names (cdr v)))) - values)))))) + values)))) + (schema "symbol-rename output" + 'data (list-of? (a-pair? a-symbol? + (ast-subset? '(const symbol if do let binding lambda primop-app)))) + 'init (ast-subset? '(const symbol if do let binding primop-app))))) (define (mangle-names expr) (match-ast expr diff --git a/src/compiler/passes/validate.rkt b/src/compiler/passes/validate.rkt index 6a62e94..a1a5d30 100644 --- a/src/compiler/passes/validate.rkt +++ b/src/compiler/passes/validate.rkt @@ -21,21 +21,26 @@ 'errors a-list? 'globals a-set? 'ast (ast-subset? '(const symbol - if do let letrec binding lambda app - primop-app def ))) - (lambda (env) - (let ((result (collect-errors (env-get env 'errors) - (lambda () - (let ((expr (env-get env 'ast)) - (globals (env-get env 'globals))) - (validate-ast globals - (get-undefined-vars expr globals) - (set) - (set) - expr)))))) - (env-set env - 'ast (car result) - 'errors (cadr result)))))) + if do let letrec binding lambda app + primop-app def ))) + (lambda (env) + (let ((result (collect-errors (env-get env 'errors) + (lambda () + (let ((expr (env-get env 'ast)) + (globals (env-get env 'globals))) + (validate-ast globals + (get-undefined-vars expr globals) + (set) + (set) + expr)))))) + (env-set env + 'ast (car result) + 'errors (cadr result)))) + (schema "validate output" + 'errors a-list? + 'ast (ast-subset? '(const symbol + if do let letrec binding lambda app + primop-app def ))))) (define (get-undefined-vars expr globals) (set-difference (ast-node-free-vars expr) globals))