-
Notifications
You must be signed in to change notification settings - Fork 0
/
beta-reduce.scm
138 lines (119 loc) · 4.05 KB
/
beta-reduce.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
; Copyright (c) 2011, Peter Brottveit Bock
; Released under the BSD 3-Clause License
; See: https://raw.github.com/peterbb/compiler/master/LICENSE
(define beta-reduce
(lambda (ast)
(cond ((constant? ast) ast)
((halt-continuation? ast) ast)
((variable? ast) ast)
((if? ast) (beta-reduce-if ast))
((application? ast) (beta-reduce-app ast))
((lambda? ast) (beta-reduce-lambda ast))
((assignment/k? ast) (beta-reduce-set! ast))
((definition/k? ast) (beta-reduce-def ast))
((activation-record? ast) (beta-reduce-ar ast))
(else
(error "beta-reduce: unkown ast:" ast)))))
(define beta-reduce-if
(lambda (ast)
(let ((pred (if-predicate ast))
(con (if-consequence ast))
(alt (if-alternative ast)))
(make-if
(beta-reduce pred)
(beta-reduce con)
(beta-reduce alt)))))
(define beta-reduce-app
(lambda (ast)
(let ((op (beta-reduce (application-procedure ast)))
(args (map beta-reduce (application-arguments ast))))
(if (activation-record? op)
(apply-beta-reduce-ar op args)
(make-application op args)))))
(define apply-beta-reduce-ar
(lambda (op args)
(if (not (= 1 (length args)))
(error "apply-beta-reduce-ar: too many arguments" (length args)))
(beta-reduce (substitute (activation-record-body op)
(activation-record-variable op)
(car args)))))
(define beta-reduce-lambda
(lambda (ast)
(make-lambda
(lambda-variable* ast)
(beta-reduce (lambda-body ast))
(lambda-debug-name ast))))
(define beta-reduce-set!
(lambda (ast)
(make-assignment/k
(assignment/k-variable ast)
(beta-reduce (assignment/k-expression ast))
(beta-reduce (assignment/k-kont ast)))))
(define beta-reduce-def
(lambda (ast)
(make-definition/k
(definition/k-variable ast)
(beta-reduce (definition/k-expression ast))
(beta-reduce (definition/k-kont ast)))))
(define beta-reduce-ar
(lambda (ast)
(make-activation-record
(activation-record-variable ast)
(beta-reduce (activation-record-body ast)))))
;;; substitute[P, x, R] == P [x := R].
(define substitute
(lambda (exp var sub)
(cond ((constant? exp) exp)
((halt-continuation? exp) exp)
((variable? exp) (substitute-var exp var sub))
((if? exp) (substitute-if exp var sub))
((application? exp) (substitute-app exp var sub))
((lambda? exp) (substitute-lambda exp var sub))
((activation-record? exp) (substitute-ar exp var sub))
((assignment/k? exp) (substitute-set! exp var sub))
((definition/k? exp) (substitute-def exp var sub))
(else
(error "substitute: unknown ast:" exp)))))
(define substitute-var
(lambda (exp var sub)
(if (var=? var exp)
sub
exp)))
(define substitute-if
(lambda (exp var sub)
(make-if (substitute (if-predicate exp) var sub)
(substitute (if-consequence exp) var sub)
(substitute (if-alternative exp) var sub))))
(define substitute-app
(lambda (exp var sub)
(make-application
(substitute (application-procedure exp) var sub)
(map (lambda (e) (substitute e var sub))
(application-arguments exp)))))
(define substitute-lambda
(lambda (exp var sub)
(make-lambda
(lambda-variable* exp)
(substitute (lambda-body exp) var sub)
(lambda-debug-name exp))))
(define substitute-ar
(lambda (exp var sub)
(make-activation-record
(activation-record-variable exp)
(substitute (activation-record-body exp) var sub))))
(define substitute-set!
(lambda (exp var sub)
(if (var=? var (assignment/k-variable exp))
(error "substitute-assignment: cant substitute mutated variable" var))
(make-assignment/k
(assignment/k-variable exp)
(substitute (assignment/k-expression exp) var sub)
(substitute (assignment/k-kont exp) var sub))))
(define substitute-def
(lambda (exp var sub)
(if (var=? var (definition/k-variable exp))
(error "substitute-definition: cant substitute defined variable" var))
(make-definition/k
(definition/k-variable exp)
(substitute (definition/k-expression exp) var sub)
(substitute (definition/k-kont exp) var sub))))