#lang racket/base (require "../syntax/syntax.rkt" "../syntax/taint.rkt" "../syntax/match.rkt" "parsed.rkt" "rebuild.rkt") (provide (struct-out expanded+parsed) (struct-out semi-parsed-define-values) (struct-out semi-parsed-begin-for-syntax) extract-syntax parsed-only syntax-only) ;; When expanding a module, we may need to compile and instantiate it, ;; too (as or for submodules), so keep both expanded and compiled ;; variants of a form together: (struct expanded+parsed (s parsed) #:authentic) ;; A `define-values` or `begin-for-syntax-form` is in limbo though ;; some passes. (struct semi-parsed-define-values (s syms ids rhs) #:authentic) (struct semi-parsed-begin-for-syntax (s body) #:authentic) (define (extract-syntax s) (if (expanded+parsed? s) (expanded+parsed-s s) s)) (define (parsed-only l) (for/list ([i (in-list l)] #:when (or (parsed? i) (expanded+parsed? i) (semi-parsed-begin-for-syntax? i))) (cond [(expanded+parsed? i) (expanded+parsed-parsed i)] [(semi-parsed-begin-for-syntax? i) (parsed-begin-for-syntax (semi-parsed-begin-for-syntax-s i) (parsed-only (semi-parsed-begin-for-syntax-body i)))] [else i]))) (define (syntax-only l) (for/list ([i (in-list l)] #:when (or (syntax? i) (expanded+parsed? i) (semi-parsed-begin-for-syntax? i))) (cond [(expanded+parsed? i) (expanded+parsed-s i)] [(semi-parsed-begin-for-syntax? i) ;; If `l` is after skipping `module*` expansion, then we may ;; still have semi-parsed `begin-for-syntax` (define s (semi-parsed-begin-for-syntax-s i)) (define nested-bodys (semi-parsed-begin-for-syntax-body i)) (define-match m s '(begin-for-syntax _ ...)) (rebuild s `(,(m 'begin-for-syntax) ,@(syntax-only nested-bodys)))] [else i])))