???
???
7.5.0.16

Okay, here’s a tiny example compiler, showing how to break a compiler into multiple files.

Here’s "stage 1":

#lang racket
 
(require rackunit)
 
(provide shrink)
 
;; this is stage 1 of the compiler:
 
;; simple shrink
(define (shrink input)
  (match input
    [(? number?) input]
    [(list '+ exp1 exp2)
     (list '+ (shrink exp1) (shrink exp2))]
    [(list '- exp1 exp2)
     (list '+ (shrink exp1) (list 'neg (shrink exp2)))]
    [(list 'read) input]))
 
(check-equal? (shrink '(+ (- (read) 8) (- (- 2 2) 3)))
              '(+ (+ (read) (neg 8)) (+ (+ 2 (neg 2)) (neg 3))))
 

Here’s "stage 2":

#lang racket
 
(require rackunit)
 
(provide opt)
 
;; this is stage 2 of the compiler
 
(define (opt sexp)
  (match sexp
    [(list '+ exp1 exp2)
     (define opt1 (opt exp1))
     (define opt2 (opt exp2))
     (match (list opt1 opt2)
       [(list (? number? n1) (? number? n2))
        (+ n1 n2)]
       [other (list '+ opt1 opt2)])]
    [(list 'neg exp1)
     (define opt1 (opt exp1))
     (match opt1
       [(? number? n) (- n)]
       [other (list 'neg opt1)])]
    [other other]))
 
 
(check-equal? (opt '(+ (+ (+ 3 (neg (+ 4 4))) (read))
                       (+ 18 (neg 9))))
              '(+ (+ -5 (read))
                  9))
 

And finally, a top level that calls both of them:

#lang racket
 
(require "stage1.rkt"
         "stage2.rkt"
         rackunit)
 
(define (compile input)
  (opt (shrink input)))
 
 
 
(check-equal? (compile '(+ (- (read) 8) (- (- 2 2) 3)))
              '(+ (+ (read) -8) -3))