;;;---------------------------------------------------------------------------- ;;; PS2.SCM ;;; ;;; Handy procedures for 6.821 Problem Set 2, Fall '98. ;;;---------------------------------------------------------------------------- ;;;---------------------------------------------------------------------------- ;;; General simplifier (define (make-language-simplifier node-handler node=?) (lambda (rules) (lambda (node) (define (simplify node) (fixed-point simplify-one-pass node)) (define (simplify-one-pass node) (node-handler (apply-all node) (lambda (subnodes make-node) (apply make-node (map simplify-one-pass subnodes))))) (define (apply-all node) (fixed-point (apply-rules rules) node)) (define (fixed-point next arg) (let loop ((prev arg) (current (next arg))) (if (node=? prev current) current (loop current (next current))))) (simplify node) ))) ;;;---------------------------------------------------------------------------- ;;; General rule manipulation (define (apply-rules rules) (lambda (node) (rules node))) (define (compose-rules . procs) (rec-reduce o identity procs)) (define (identity x) x) (define (o f g) (lambda (x) (f (g x)))) (define (rec-reduce op id lst) (let recur ((lst lst)) (if (null? lst) id (op (car lst) (recur (cdr lst)))))) ;;;---------------------------------------------------------------------------- ;;; Sample program (define sample-program '((swap exec swap exec) (1 sub) swap (2 mul) swap 3 swap exec)) ;;;--------------------------------------------------------------------------- ;;; PostFix Syntactic Datatypes (define-datatype program ($prog (listof command))) (define-datatype command ($int int) ($seq (listof command)) ($pop) ($swap) ($dup) ($sel) ($exec) ($arithop (-> (int int) int)) ($relop (-> (int int) bool)) ) ;;;---------------------------------------------------------------------------- ;;; Parsing (define (pf-program sexp) (match sexp ((list->sexp lst) ($prog (pf-sequence lst))) (_ (error "Ill-formed program")))) (define (pf-sequence lst) (map pf-command lst)) (define (pf-command sexp) (match sexp ( (int->sexp n) ($int n) ) ( (list->sexp lst) ($seq (pf-sequence lst)) ) ( 'pop ($pop) ) ( 'swap ($swap) ) ( 'exec ($exec) ) ( 'sel ($sel) ) ( 'dup ($dup) ) ;; Below, arithop and relop operations are functions, not symbols! ( 'add ($arithop +) ) ( 'sub ($arithop -) ) ( 'mul ($arithop *) ) ( 'div ($arithop quotient) ) ; integer division ( 'lt ($relop <) ) ( 'eq ($relop =) ) ( 'gt ($relop >) ) ( _ (error "Unrecognized command" sexp) ) )) ;;;---------------------------------------------------------------------------- ;;; Unparsing (define (pf-unprogram pgm) (match pgm (($prog cmds) (pf-uncommands cmds)))) (define (pf-uncommands cmds) (map pf-uncommand cmds)) (define (pf-uncommand cmd) (match cmd (($int i) i) (($seq cmds) (pf-uncommands cmds)) (($pop) 'pop) (($swap) 'swap) (($dup) 'dup) (($sel) 'sel) (($exec) 'exec) (($arithop op) (cond ((eq? op +) 'add) ((eq? op -) 'sub) ((eq? op *) 'mul) ((eq? op quotient) 'div))) (($relop op) (cond ((eq? op <) 'lt) ((eq? op =) 'eq) ((eq? op >) 'gtl))) ))