applyeval.scm 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. (define apply-in-underlying-scheme apply)
  2. (define (eval exp env)
  3. (cond ((self-evaluating? exp) exp)
  4. ((variable? exp) (lookup-variable-value exp env))
  5. ((quoted? exp) (text-of-quotation exp))
  6. ((assignment? exp) (eval-assignment exp env))
  7. ((if? exp) (eval-if exp env))
  8. ((lambda? exp)
  9. (make-procedure (lambda-parameters exp)
  10. (lambda-body exp)
  11. env))
  12. ((begin? exp)
  13. (eval-sequence (begin-actions exp) env))
  14. ((cond? exp) (eval (cond->if exp) env))
  15. ((application? exp)
  16. (apply (eval (operator exp) env)
  17. (list-of-values (operands exp) env)))
  18. (else
  19. (error "Unknown expression type -- EVAL" exp))))
  20. (define (apply procedure arguments)
  21. (cond ((primitive-procedure? procedure)
  22. (apply-primitive-procedure procedure arguments))
  23. ((compound-procedure? procedure)
  24. (eval-sequence
  25. (procedure-body procedure)
  26. (extend-environment
  27. (procedure-parameters procedure)
  28. arguments
  29. (procedure-environment procedure))))
  30. (else
  31. (error
  32. "Unknown procedure type -- APPLY" procedure))))
  33. (define (list-of-values exps env)
  34. (if (no-operands? exps)
  35. '()
  36. (cons (eval (first-operand exps) env)
  37. (list-of-values (rest-operands exps) env))))
  38. (define (eval-if exp env)
  39. (if (true? (eval (if-predicate exp) env))
  40. (eval (if-consequent exp) env)
  41. (eval (if-alternative exp) env)))
  42. (define (eval-sequence exps env)
  43. (cond ((last-exp? exps) (eval (first-exp exps) env))
  44. (else (eval (first-exp exps) env)
  45. (eval-sequence (rest-exps exps) env))))
  46. (define (eval-assignment exp env)
  47. (set-variable-value! (assignment-variable exp)
  48. (eval (assignment-value exp) env)
  49. env)
  50. 'ok)
  51. (define (eval-definition exp env)
  52. (define-variable! (definition-variable exp)
  53. (eval (definition-value exp) env)
  54. env)
  55. 'ok)
  56. (define (self-evaluating? exp)
  57. (cond ((number? exp) true)
  58. ((string? exp) true)
  59. (else false)))
  60. (define (variable? exp)
  61. (symbol? exp))
  62. (define (quoted? exp)
  63. (tagged-list? exp 'quote))
  64. (define (text-of-quotation exp)
  65. (cadr exp))
  66. (define (tagged-list? exp tag)
  67. (if (pair? exp)
  68. (eq? (car exp) tag)
  69. false))
  70. (define (assignment? exp)
  71. (tagged-list? exp 'set!))
  72. (define (assignment-variable exp) (cadr exp))
  73. (define (assignment-value exp) (caddr exp))
  74. (define (definition? exp)
  75. (tagged-list? exp 'define))
  76. (define (definition-variable exp)
  77. (if (symbol? (cadr exp))
  78. (cadr exp)
  79. (caadr exp)))
  80. (define (definition-value exp)
  81. (if (symbol? (cadr exp))
  82. (cadr exp)
  83. (make-lambda (cdadr exp) ;; formal params
  84. (cddr exp)))) ;; body
  85. (define (lambda? exp)
  86. (tagged-list? exp 'lambda))
  87. (define (lambda-paramaters exp)
  88. (cadr exp))
  89. (define (lambda-body exp)
  90. (cddr exp))
  91. (define (make-lambda parameters body)
  92. (cons 'lambda (cons parameters body)))
  93. (define (if? exp) (tagged-list? exp 'if))
  94. (define (if-predicate exp) (cadr exp))
  95. (define (if-consequent exp) (caddr exp))
  96. (define (if-alternative exp)
  97. (if (not (null? (cdddr exp)))
  98. (cadddr exp)
  99. 'false))
  100. (define (make-if predicate consequent alternative)
  101. (list 'if predicate consequent alternative))
  102. (define (begin? exp) (tagged-list? exp 'begin))
  103. (define (begin-actions exp) (cdr exp))
  104. (define (last-exp? seq) (null? (cdr seq)))
  105. (define (first-exp seq) (car seq))
  106. (define (rest-exps seq) (cdr seq))
  107. (define (sequence->exp seq)
  108. (cond ((null? seq) seq)
  109. ((last-exp? seq) (first-exp seq))
  110. (else (make-begin seq))))
  111. (define (make-begin seq) (cons 'begin seq))
  112. (define (application? exp) (pair? exp))
  113. (define (operator exp) (car exp))
  114. (define (operands exp) (cdr exp))
  115. (define (no-operands? ops) (null? ops))
  116. (define (first-operand ops) (car ops))
  117. (define (rest-operands ops) (cdr ops))
  118. (define (cond? exp) (tagged-list? exp 'cond))
  119. (define (cond-clauses exp) (cdr exp))
  120. (define (cond-else-clause? clause)
  121. (eq? (cond-predicate clause) 'else))
  122. (define (cond-predicate clause) (car clause))
  123. (define (cond-actions clause) (cdr clause))
  124. (define (cond->if exp)
  125. (expand-clauses (cond-clauses exp)))
  126. (define (expand-clauses clauses)
  127. (if (null? clauses)
  128. 'false ; no else clause
  129. (let ((first (car clauses))
  130. (rest (cdr clauses)))
  131. (if (cond-else-clause? first)
  132. (if (null? rest)
  133. (sequence->exp (cond-actions first))
  134. (error "ELSE clause isn't last -- COND->IF"
  135. clauses))
  136. (make-if (cond-predicate first)
  137. (sequence-exp (cond-actions first))
  138. (expand-clauses rest))))))
  139. (define (true? x) (not (eq? x false)))
  140. (define (false? x) (eq? x false))
  141. (define (make-procedure parameters body env)
  142. (list 'procedure parameters body env))
  143. (define (compound-procedure? p)
  144. (tagged-list? p 'procedure))
  145. (define (procedure-parameters p) (cadr p))
  146. (define (procedure-body p) (caddr p))
  147. (define (procedure-environment p) (cadddr p))
  148. (define (enclosing-environment env) (cdr env))
  149. (define (first-frame env) (car env))
  150. (define the-empty-environment '())
  151. (define (make-frame variables values)
  152. (cons variables values))
  153. (define (frame-variables frame) (car frame))
  154. (define (frame-values frame) (cdr frame))
  155. (define (add-binding-to-frame! var val frame)
  156. (set-car! frame (cons var (car frame)))
  157. (set-cdr! frame (cons val (cdr frame))))
  158. (define (extend-environment vars vals base-env)
  159. (if (= (length vars) (length vals))
  160. (cons (make-frame vars vals) base-env)
  161. (if (< (length vars) (length vals))
  162. (error "Too many args supplied" vars vals)
  163. (error "Too few args supplied" vars vals))))
  164. (define (lookup-variable-value var env)
  165. (define (env-loop env)
  166. (define (scan vars vals)
  167. (cond ((null? vars)
  168. (env-loop (enclosing-environment env)))
  169. ((eq? var (car vars))
  170. (car vals))
  171. (else (scan (cdr vars) (cdr vals)))))
  172. (if (eq? env the-empty-environment)
  173. (error "Unbound var" var)
  174. (let ((frame (first-frame env)))
  175. (scan (frame-variables frame)
  176. (frame-values frame)))))
  177. (env-loop env))
  178. (define (set-variable-value! var val env)
  179. (define (env-loop env)
  180. (define (scan vars vals)
  181. (cond ((null? vars)
  182. (env-loop (enclosing-environment env)))
  183. ((eq? var (car vars))
  184. (set-car! vals val))
  185. (else (scan (cdr vars) (cdr vals)))))
  186. (if (eq? env the-empty-environment)
  187. (error "Unbound var -- SET!" var)
  188. (let ((frame (first-frame env)))
  189. (scan (frame-variables frame)
  190. (frame-values frame)))))
  191. (env-loop env))
  192. (define (define-variable! var val env)
  193. (let ((frame (first-frame env)))
  194. (define (scan vars vals)
  195. (cond ((null? vars)
  196. (add-binding-to-frame! var val frame))
  197. ((eq? var (car vars))
  198. (set-car! vals val))
  199. (else (scan (cdr vars) (cdr vals)))))
  200. (scan (frame-variables frame)
  201. (frame-values frame))))
  202. (define (setup-environment)
  203. (let ((initial-env
  204. (extend-environment (primitive-procedure-names)
  205. (primitive-procedure-objects)
  206. the-empty-environment)))
  207. (define-variable! 'true true initial-env)
  208. (define-variable! 'false false initial-env)
  209. initial-env))
  210. (define (primitive-procedure? proc)
  211. (tagged-list? proc 'primitive))
  212. (define (primitive-implementation proc) (cadr proc))
  213. (define primitive-procedures
  214. (list (list 'car car)
  215. (list 'cdr cdr)
  216. (list 'cons cons)
  217. (list 'null? null?)
  218. ))
  219. (define (primitive-procedure-names)
  220. (map car
  221. primitive-procedures))
  222. (define (primitive-procedure-objects)
  223. (map (lambda (proc) (list 'primitive (cadr proc)))
  224. primitive-procedures))
  225. (define (apply-primitive-procedure proc args)
  226. (apply-in-underlying-scheme
  227. (primitive-implementation proc) args))
  228. (define input-prompt ";;; M-Eval input: ")
  229. (define output-prompt ";;; M-Eval value: ")
  230. (define (driver-loop)
  231. (prompt-for-input input-prompt)
  232. (let ((input (read)))
  233. (let ((output (eval input the-global-environment)))
  234. (announce-output output-prompt)
  235. (user-print output)))
  236. (driver-loop))
  237. (define (prompt-for-input string)
  238. (newline) (newline) (display string) (newline))
  239. (define (announce-output string)
  240. (newline) (display string) (newline))
  241. (define (user-print object)
  242. (if (compound-procedure? object)
  243. (display (list 'compound-procedure
  244. (procedure-parameters object)
  245. (procedure-body object)
  246. '<procedure-env>))
  247. (display object)))
  248. ;; run these after loading this file:
  249. ;(define the-global-environment (setup-environment))
  250. ;(driver-loop)