#lang racket (require racket/match) (require racket/fixnum) (define assert (lambda (msg b) (if (not b) (begin (display "ERROR: ") (display msg) (newline)) (void)))) (define ast1.4 `(- 8)) (define ast1.1 `(+ 50 ,ast1.4)) (match ast1.1 [`(,op ,child1 ,child2) (print op) (newline) (print child1) (newline) (print child2)]) (define (arith-kind arith) (match arith [(? fixnum?) `int] [`(- ,c1) `neg] [`(+ ,c1 ,c2) `add])) (arith-kind `50) (arith-kind `(- 8)) (arith-kind `(+ 50 (- 8))) (define (arith? sexp) (match sexp [(? fixnum?) #t] [`(+ ,e1 ,e2) (and (arith? e1) (arith? e2))] [`(- ,e) (arith? e)] [else #f])) (arith? `(+ 50 (- 8))) (arith? `(- 50 (+ 8))) (define (interp-R0 e) (match e [(? fixnum?) e] [`(read) (let ([r (read)]) (cond [(fixnum? r) r] [else (error 'interp-R0 "input was not an integer" r)]))] [`(- ,(app interp-R0 v)) (fx- 0 v)] [`(+ ,(app interp-R0 v1) ,(app interp-R0 v2)) (fx+ v1 v2)] )) (interp-R0 ast1.1) ;(interp-R0 `(+ (read) (- 8))) (define (pe-neg r) (match r [(? fixnum?) (fx- 0 r)] [else `(- ,r)] )) (define (pe-add r1 r2) (match (list r1 r2) [`(,n1 ,n2) #:when (and (fixnum? n1) (fixnum? n2)) (fx+ r1 r2)] [else `(+ ,r1 ,r2)] )) (define (pe-arith e) (match e [(? fixnum?) e] [`(read) `(read)] [`(- ,e1) (pe-neg (pe-arith e1))] [`(+ ,e1 ,e2) (pe-add (pe-arith e1) (pe-arith e2))] )) ;; e ::= (read) | (- (read)) | (+ e e) ;; r ::= n | (+ n e) | e (define (pe-neg2 r) (match r [(? fixnum?) (fx- 0 r)] [`(+ ,n ,e2) #:when (fixnum? n) `(+ ,(fx- 0 n) ,(pe-neg2 e2))] [`(read) `(- (read))] [`(- ,e2) e2] [`(+ ,e1 ,e2) `(+ ,(pe-neg2 e1) ,(pe-neg2 e2))] )) (define (pe-add2 r1 r2) (match r1 [(? fixnum?) (match r2 [(? fixnum?) (fx+ r1 r2)] [`(+ ,n2 ,e2) #:when (fixnum? n2) `(+ ,(fx+ r1 n2) ,e2)] [else `(+ ,r1 ,r2)])] [`(+ ,n1 ,e1) (match r2 [(? fixnum?) `(+ (fx+ n1 r2) ,e1)] [`(+ ,n2 ,e2) #:when (fixnum? n2) `(+ ,(fx+ n1 n2) (+ ,e1 ,e2))] [else `(+ ,r1 ,r2)])] [else (match r2 [(? fixnum?) `(+ ,r2 ,r1)] [else `(+ ,r1 ,r2)])] )) (define (pe-arith2 e) (match e [(? fixnum?) e] [`(read) `(read)] [`(- ,e1) (pe-neg2 (pe-arith2 e1))] [`(+ ,e1 ,e2) (pe-add2 (pe-arith2 e1) (pe-arith2 e2))] )) (define (test-pe pe p) (assert "testing pe-arith" (equal? (interp-R0 p) (interp-R0 (pe p))))) (if #f (begin (test-pe pe-arith `(+ (read) (- (+ 5 3)))) (test-pe pe-arith `(+ 1 (+ (read) 1))) (test-pe pe-arith `(- (+ (read) (- 5)))) (test-pe pe-arith2 `(+ (read) (- (+ 5 3)))) (test-pe pe-arith2 `(+ 1 (+ (read) 1))) (test-pe pe-arith2 `(- (+ (read) (- 5)))) ) (void))