101 lines
3.6 KiB
Racket
101 lines
3.6 KiB
Racket
#lang racket
|
|
|
|
(require "uniquify.rkt")
|
|
|
|
(provide remove-complex-opera*)
|
|
|
|
; remove complex sub-expression
|
|
; the resulting code is either
|
|
; - a number literal
|
|
; - a symbol
|
|
; the three above are called in the following "simple terms"
|
|
; - (read)
|
|
; - (- x) where x is a simple term
|
|
; - (+ x y) where x and y are simple terms
|
|
; - (let ([var y]) z) where y and z are expressions
|
|
(define (remove-complex-opera* p)
|
|
(let ([uniq-res (uniquify p)])
|
|
(match (cadr uniq-res)
|
|
[`(program ,data ,exp)
|
|
(begin
|
|
(define initial-tmpcount (hash-ref (car uniq-res) `tmp 0))
|
|
(define-values (new-exp bla) (rco-exp exp initial-tmpcount))
|
|
`(program ,data ,new-exp))])))
|
|
|
|
(define (let-binding var val exp)
|
|
`(let ([,var ,val]) ,exp))
|
|
|
|
(define (wrap-associations assoc-list exp)
|
|
(if (empty? assoc-list)
|
|
exp
|
|
(let ([binding (car assoc-list)])
|
|
(let-binding (car binding) (cadr binding)
|
|
(wrap-associations (cdr assoc-list) exp)))))
|
|
|
|
(define (rco-exp exp tmpcount)
|
|
(match exp
|
|
[(? fixnum?) (values exp tmpcount)]
|
|
[(? symbol?) (values exp tmpcount)]
|
|
[`(read) (values exp tmpcount)]
|
|
[`(- ,e)
|
|
(begin
|
|
(define-values (new-exp assoc-list new-tmpcount) (rco-arg e tmpcount))
|
|
(values (wrap-associations assoc-list `(- ,new-exp)) new-tmpcount))]
|
|
[`(+ ,e1 ,e2)
|
|
(begin
|
|
(define-values (new-exp1 assoc-list1 new-tmpcount1) (rco-arg e1 tmpcount))
|
|
(define-values (new-exp2 assoc-list2 new-tmpcount) (rco-arg e2 new-tmpcount1))
|
|
(values (wrap-associations (append assoc-list1 assoc-list2)
|
|
`(+ ,new-exp1 ,new-exp2)) new-tmpcount))]
|
|
[`(let ([,var ,e]) ,body)
|
|
(begin
|
|
(define-values (exp-tmp exp-tmpcount) (rco-exp e tmpcount))
|
|
(define-values (new-body new-tmpcount) (rco-exp body exp-tmpcount))
|
|
(values `(let ([,var ,exp-tmp]) ,new-body)
|
|
exp-tmpcount))]))
|
|
|
|
(define (get-unique-symbol tmpcount)
|
|
(string->symbol (format "tmp.~a" tmpcount)))
|
|
|
|
(define (rco-arg exp tmpcount)
|
|
(match exp
|
|
[(? fixnum?) (values exp '() tmpcount)]
|
|
[(? symbol?) (values exp '() tmpcount)]
|
|
[`(read)
|
|
(begin
|
|
(define new-tmpcount (+ tmpcount 1))
|
|
(define tmpname (get-unique-symbol new-tmpcount))
|
|
(values tmpname
|
|
(list `(,tmpname (read)))
|
|
new-tmpcount))]
|
|
[`(- ,e)
|
|
(begin
|
|
(define-values (new-exp assoc-list exp-tmpcount) (rco-arg e tmpcount))
|
|
(define new-tmpcount (+ exp-tmpcount 1))
|
|
(define tmpname (get-unique-symbol new-tmpcount))
|
|
(set! assoc-list (append assoc-list (list `(,tmpname (- ,new-exp)))))
|
|
(values tmpname
|
|
assoc-list
|
|
new-tmpcount))]
|
|
[`(,op ,e1 ,e2)
|
|
#:when (or (eq? op `+) (eq? op `-))
|
|
(begin
|
|
(define-values (new-exp1 assoc-1 exp1-tmpcount) (rco-arg e1 tmpcount))
|
|
(define-values (new-exp2 assoc-2 exp2-tmpcount) (rco-arg e2 exp1-tmpcount))
|
|
(define assoc-list (append assoc-1 assoc-2))
|
|
(define new-tmpcount (+ exp2-tmpcount 1))
|
|
(define tmpname (get-unique-symbol new-tmpcount))
|
|
(set! assoc-list (append assoc-list (list `(,tmpname (,op ,new-exp1 ,new-exp2)))))
|
|
(values tmpname
|
|
assoc-list
|
|
new-tmpcount))]
|
|
; this must return a simple term
|
|
; i.e.: either a symbol, a read or a number literal
|
|
[`(let ([,var ,rexp]) ,body)
|
|
(begin
|
|
(define-values (new-exp exp-tmpcount) (rco-exp rexp tmpcount))
|
|
(define-values (new-body assoc-list new-tmpcount) (rco-arg body exp-tmpcount))
|
|
(values new-body
|
|
(cons `(,var ,new-exp) assoc-list)
|
|
new-tmpcount))]))
|