-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcps.scm
76 lines (65 loc) · 2.48 KB
/
cps.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
(load "utilities.scm")
(define not-cps-proc-list '())
(define (cps-trans-if args cont)
(let ((test (car args))
(then (cadr args))
(alt (if (null? (cddr args)) 'undefined (caddr args)))
(v (gensym)))
(cps-trans
test
(list 'lambda (list v)
(list 'if v (cps-trans then cont)
(cps-trans alt (copy-tree cont)))))))
(define (cps-trans-begin args cont)
(if (null? args)
(list cont 'undefined)
(cps-trans (car args)
(if (null? (cdr args))
cont
(let ((ig (gensym)))
(list 'lambda (list ig)
(cps-trans-begin (cdr args) cont)))))))
(define (cps-trans-lambda args cont)
(let ((c (gensym)))
(list cont
(list 'lambda (cons c (car args))
(cps-trans-begin (cdr args) c)))))
(define (cps-trans-set! args cont)
(if (pair? (cadr args))
(let ((v (gensym)))
(cps-trans (cadr args)
(list 'lambda (list v)
(list cont (list 'set! (car args) v)))))
(list cont (list* 'set! args))))
(define (cps-trans-evlis rargs rparam acc)
(if (null? rargs)
acc
(cps-trans-evlis
(cdr rargs) (cdr rparam)
(if (pair? (car rargs))
(cps-trans (car rargs) (list 'lambda (list (car rparam)) acc))
acc))))
(define (cps-trans-not-cps-proc fn args cont)
(let* ((param (map (lambda (arg) (if (pair? arg) (gensym) arg)) args))
(call (list cont (cons fn param))))
(cps-trans-evlis (reverse args) (reverse param) call)))
(define (cps-trans-proc fn args cont)
(let* ((param (map (lambda (arg) (if (pair? arg) (gensym) arg))
(cons fn args)))
(call (list* (car param) cont (cdr param))))
(cps-trans-evlis (reverse (cons fn args)) (reverse param) call)))
(define (cps-trans-pair op args cont)
(cond ((eq? op 'quote) (list cont (cons op args)))
((eq? op 'if) (cps-trans-if args cont))
((eq? op 'begin) (cps-trans-begin args cont))
((eq? op 'lambda) (cps-trans-lambda args cont))
((eq? op 'set!) (cps-trans-set! args cont))
((member op not-cps-proc-list) (cps-trans-not-cps-proc op args cont))
(else (cps-trans-proc op args cont))))
(define (cps-trans exp cont)
(if (pair? exp)
(cps-trans-pair (car exp) (cdr exp) cont)
(list cont exp)))
(define (cps exp)
(let ((cont (gensym)))
(cps-trans exp (list 'lambda (list cont) cont))))