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))