Advertisement
timothy235

sicp-4-2-2-optionally-lazy-repl-program

Mar 19th, 2017
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 21.96 KB | None | 0 0
  1. #lang racket
  2. (require racket/mpair)
  3. (provide (all-defined-out))
  4.  
  5. ;; This is the repl program for exercise 4.31 from section 4.2.2.  It is the same as
  6. ;; the repl program from section 4.1.4, only modified to allow for three different
  7. ;; evaluation strategies for procedure arguments:  eager evaluation by default, lazy
  8. ;; evaluation without memoization using the lazy keyword, or lazy evaluation with
  9. ;; memoization using the lazy-memo keyword.  There are tests at the end of the file.
  10.  
  11. ;; PROGRAM SECTIONS
  12.  
  13. ;; 1. my-eval and my-apply
  14. ;; 2. eval procedures
  15. ;; 3. self-evaluating expressions, variables, and quotations
  16. ;; 4. definition and assignment
  17. ;; 5. thunks, lambdas, procedures and applications
  18. ;; 6. sequences and begin expressions
  19. ;; 7. boolean expressions
  20. ;; 8. if and cond expressions
  21. ;; 9. let, let*, and named-let
  22. ;; 10. environment and frames
  23. ;; 11. primitive procedures and the global environment
  24. ;; 12. repl operations
  25. ;; 13. tests
  26.  
  27. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  28. ;; 1. MY-EVAL AND MY-APPLY  ;;
  29. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  30.  
  31. (define (my-eval expr env)
  32.   (cond [(self-evaluating? expr) expr]
  33.         [(variable? expr) (lookup-variable-value expr env)]
  34.         [(quoted? expr) (text-of-quotation expr)]
  35.         [(definition? expr) (eval-definition expr env)]
  36.         [(assignment? expr) (eval-assignment expr env)]
  37.         [(if? expr) (eval-if expr env)]
  38.         [(cond? expr) (my-eval (cond->if expr) env)]
  39.         [(begin? expr) (eval-sequence (begin-actions expr) env)]
  40.         [(and? expr) (eval-and expr env)]
  41.         [(or? expr) (eval-or expr env)]
  42.         [(let? expr) (my-eval (let->combination expr) env)]
  43.         [(let*? expr) (my-eval (let*->nested-lets expr) env)]
  44.         [(named-let? expr) (my-eval (named-let->sequence expr) env)]
  45.         [(lambda? expr)
  46.          (make-procedure (lambda-parameters expr)
  47.                          (lambda-body expr)
  48.                          env)]
  49.         [(application? expr)
  50.          (my-apply (actual-value (operator expr) env)
  51.                    (operands expr)
  52.                    env)]
  53.         [else (error "Unknown expression type -- MY-EVAL" expr)]))
  54.  
  55. (define (my-apply procedure arguments env)
  56.   (cond [(primitive-procedure? procedure)
  57.          (apply-primitive-procedure
  58.            procedure
  59.            (list-of-arg-values arguments env))]
  60.         [(compound-procedure? procedure)
  61.          (eval-sequence
  62.            (procedure-body procedure)
  63.            (extend-environment
  64.              (procedure-parameters procedure)
  65.              (list-of-args arguments
  66.                            (procedure-types procedure)
  67.                            env)
  68.              (procedure-environment procedure)))]
  69.         [else (error "Unknown procedure type -- APPLY" procedure)]))
  70.  
  71. ;;;;;;;;;;;;;;;;;;;;;;;;;
  72. ;; 2. EVAL PROCEDURES  ;;
  73. ;;;;;;;;;;;;;;;;;;;;;;;;;
  74.  
  75. (define (eval-definition expr env)
  76.   (define-variable! (definition-variable expr)
  77.                     (my-eval (definition-value expr) env)
  78.                     env)
  79.   'ok)
  80. (define (eval-assignment expr env)
  81.   (set-variable-value! (assignment-variable expr)
  82.                        (my-eval (assignment-value expr) env)
  83.                        env)
  84.   'ok)
  85. (define (list-of-values exprs env)
  86.   (if (no-operands? exprs)
  87.     empty
  88.     (cons (my-eval (first-operand exprs) env)
  89.           (list-of-values (rest-operands exprs) env))))
  90. (define (eval-sequence exprs env)
  91.   (cond [(last-exp? exprs) (my-eval (first-exp exprs) env)]
  92.         [else (my-eval (first-exp exprs) env)
  93.               (eval-sequence (rest-exps exprs) env)]))
  94. (define (eval-if expr env)
  95.   (if (true? (actual-value (if-predicate expr) env))
  96.     (my-eval (if-consequent expr) env)
  97.     (my-eval (if-alternative expr) env)))
  98. (define (eval-and expr env)
  99.   (define ops (and-operands expr))
  100.   (cond [(empty? ops) 'true] ; (and) should be true
  101.         [else
  102.           (define val (my-eval (first ops) env))
  103.           (define rest-ops (rest ops))
  104.           (cond [(empty? rest-ops) val] ; (and x) should be x
  105.                 [(false? val) false]
  106.                 [else
  107.                   (eval-and (make-and rest-ops) env)])]))
  108. (define (eval-or expr env)
  109.   (define ops (or-operands expr))
  110.   (cond [(empty? ops) 'false] ; (or) should be false
  111.         [else
  112.           (define val (my-eval (first ops) env))
  113.           (define rest-ops (rest ops))
  114.           (cond [(empty? rest-ops) val] ; (or x) should be x
  115.                 [(not (false? val)) val]
  116.                 [else
  117.                   (eval-or (make-or rest-ops) env)])]))
  118.  
  119. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  120. ;; 3. SELF-EVALUATING EXPRESSIONS, VARIABLES, AND QUOTATIONS  ;;
  121. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  122.  
  123. (define (tagged-list? expr tag)
  124.   (or (and (pair? expr) (eq? (first expr) tag))
  125.       (and (mpair? expr) (eq? (mcar expr) tag))))
  126. ;; Only numbers and strings are self-evaluating.
  127. (define (self-evaluating? expr)
  128.   (cond [(number? expr) true]
  129.         [(string? expr) true]
  130.         [else false]))
  131. (define (variable? expr)
  132.   (symbol? expr))
  133. ;; Quotations have the form:  (quote <text-of-quotation>)
  134. (define (quoted? expr)
  135.   (tagged-list? expr 'quote))
  136. (define (text-of-quotation expr)
  137.   (second expr))
  138.  
  139. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  140. ;; 4. DEFINITION AND ASSIGNMENT  ;;
  141. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  142.  
  143. ;; Variable definitions have the form:  (define <var> <value>)
  144.  
  145. ;; Procedure definitions have the form:
  146. ;; (define (<var> <parameter-1> ... <parameter-n>) <body>)
  147. ;; which is equivalent to:
  148. ;; (define <var> (lambda (<parameter-1> ... <parameter-n>) <body>))
  149.  
  150. (define (definition? expr)
  151.   (tagged-list? expr 'define))
  152. (define (procedure-definition? expr)
  153.   (and (definition? expr)
  154.        (pair? (second expr))))
  155. (define (definition-variable expr)
  156.   (if (procedure-definition? expr)
  157.     (first (second expr))
  158.     (second expr)))
  159. (define (definition-parameters expr)
  160.   (rest (second expr)))
  161. (define (definition-value expr)
  162.   (if (procedure-definition? expr)
  163.     (make-lambda (definition-parameters expr)
  164.                  (drop expr 2))
  165.     (third expr)))
  166.  
  167. ;; All lambda parameters are a two-element list now: the first element is the
  168. ;; parameter name, and the second element is the parameter type, either 'eager,
  169. ;; 'lazy, or 'lazy-memo.
  170. (define (make-all-typed params)
  171.   (map (lambda (p)
  172.          (if (symbol? p)
  173.            (list p 'eager)
  174.            p))
  175.        params))
  176.  
  177. ;; Assignments have the form:  (set! <var> <value>)
  178. (define (assignment? expr)
  179.   (tagged-list? expr 'set!))
  180. (define (assignment-variable expr) (second expr))
  181. (define (assignment-value expr) (third expr))
  182.  
  183. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  184. ;; 5. THUNKS, LAMBDAS, PROCEDURES AND APPLICATIONS  ;;
  185. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  186.  
  187. (define (thunk-memo? obj) (tagged-list? obj 'thunk-memo))
  188. (define (thunk-no-memo? obj) (tagged-list? obj 'thunk-no-memo))
  189. (define (thunk-exp my-thunk) (mcar (mcdr my-thunk)))
  190. (define (thunk-env my-thunk) (mcar (mcdr (mcdr my-thunk))))
  191. (define (delay-it-memo expr env)
  192.   (mlist 'thunk-memo expr env))
  193. (define (delay-it-no-memo expr env)
  194.   (mlist 'thunk-no-memo expr env))
  195. (define (evaluated-thunk? obj) (tagged-list? obj 'evaluated-thunk))
  196. (define (thunk-value evaluated-thunk) (mcar (mcdr evaluated-thunk)))
  197. (define (force-it obj) ; changed
  198.   (cond [(thunk-memo? obj)
  199.          (define result (actual-value (thunk-exp obj) (thunk-env obj)))
  200.          (set-mcar! obj 'evaluated-thunk)
  201.          (set-mcar! (mcdr obj) result)
  202.          (set-mcdr! (mcdr obj) empty)
  203.          result]
  204.         [(evaluated-thunk? obj) (thunk-value obj)]
  205.         [(thunk-no-memo? obj)
  206.          (actual-value (thunk-exp obj) (thunk-env obj))]
  207.         [else obj]))
  208.  
  209. ;; Lambda expressions have the form:
  210. ;; (lambda ((<var> <type>) ... ) <body>)
  211. (define (lambda? expr) (tagged-list? expr 'lambda))
  212. (define (lambda-parameters expr) (second expr))
  213. (define (lambda-body expr) (drop expr 2))
  214. (define (make-lambda parameters body)
  215.   (cons 'lambda (cons (make-all-typed parameters) body))) ; changed
  216.  
  217. ;; Procedures:
  218. (define (make-procedure parameters body env)
  219.   (list 'procedure parameters body env))
  220. (define (compound-procedure? p)
  221.   (tagged-list? p 'procedure))
  222. (define (procedure-parameters p) (map first (second p)))
  223. (define (procedure-types p) (map second (second p)))
  224. (define (procedure-body p) (third p))
  225. (define (procedure-environment p) (fourth p))
  226.  
  227. ;; Procedure applications have the from:
  228. ;; (<var> <parameter> ...)
  229. (define (application? expr) (pair? expr))
  230. (define (operator expr) (first expr))
  231. (define (operands expr) (rest expr))
  232. (define (no-operands? ops) (empty? ops))
  233. (define (first-operand ops) (first ops))
  234. (define (rest-operands ops) (rest ops))
  235. (define (actual-value expr env)
  236.   (force-it (my-eval expr env)))
  237. (define (list-of-arg-values exprs env)
  238.   (if (no-operands? exprs)
  239.     empty
  240.     (cons (actual-value (first-operand exprs) env)
  241.           (list-of-arg-values (rest-operands exprs)
  242.                               env))))
  243. (define (list-of-args exprs types env)
  244.   (cond [(no-operands? exprs)
  245.         empty]
  246.         [else
  247.           (define e (first-operand exprs))
  248.           (define t (first types))
  249.           (define arg (cond [(eq? t 'eager) (actual-value e env)]
  250.                             [(eq? t 'lazy) (delay-it-no-memo e env)]
  251.                             [(eq? t 'lazy-memo) (delay-it-memo e env)]
  252.                             [else (error "Unknown type -- LIST-OF-ARGS" t)]))
  253.           (cons arg (list-of-args (rest-operands exprs)
  254.                                   (rest types)
  255.                                   env))]))
  256.  
  257. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  258. ;; 6. SEQUENCES AND BEGIN EXPRESSIONS  ;;
  259. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  260.  
  261. ;; Begin has the form:  (begin <actions>)
  262. (define (begin? expr) (tagged-list? expr 'begin))
  263. (define (begin-actions expr) (rest expr))
  264. (define (last-exp? seq) (empty? (rest seq)))
  265. (define (first-exp seq) (first seq))
  266. (define (rest-exps seq) (rest seq))
  267. (define (sequence->exp seq)
  268.   (cond [(empty? seq) seq]
  269.         [(last-exp? seq) (first-exp seq)]
  270.         [else (make-begin seq)]))
  271. ;; begin constructor used by cond->if
  272. (define (make-begin seq) (cons 'begin seq))
  273.  
  274. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  275. ;; 7. BOOLEAN EXPRESSIONS  ;;
  276. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  277.  
  278. (define (true? x) (not (false? x)))
  279. (define (and? expr) (tagged-list? expr 'and))
  280. (define (and-operands expr) (rest expr))
  281. (define (make-and sequence) (cons 'and sequence))
  282. (define (or? expr) (tagged-list? expr 'or))
  283. (define (or-operands expr) (rest expr))
  284. (define (make-or sequence) (cons 'or sequence))
  285.  
  286. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  287. ;; 8. IF AND COND EXPRESSIONS  ;;
  288. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  289.  
  290. ;; Conditionals have the form:  (if <predicate> <consequent> <alternative>)
  291. ;; If no alternative, use false.
  292. (define (if? expr) (tagged-list? expr 'if))
  293. (define (if-predicate expr) (second expr))
  294. (define (if-consequent expr) (third expr))
  295. (define (if-alternative expr)
  296.   (if (not (empty? (drop expr 3)))
  297.     (fourth expr)
  298.     'false))
  299. (define (make-if predicate consequent alternative)
  300.   (list 'if predicate consequent alternative))
  301.  
  302. ;; Cond has the form:
  303. ;; (cond ((<predicate> <actions>)
  304.        ;; (else <actions>))) ; if no else, assume (else false) clause
  305. (define (cond? expr) (tagged-list? expr 'cond))
  306. (define (cond-clauses expr) (rest expr))
  307. ;; regular cond clause
  308. (define (cond-predicate clause) (first clause))
  309. (define (cond-actions clause) (rest clause))
  310. ;; alternate test clause
  311. (define (cond-alternate-clause? clause)
  312.   (eq? (second clause) '=>))
  313. (define (cond-test clause) (first clause))
  314. (define (cond-recipient clause) (third clause))
  315. ;; else clause
  316. (define (cond-else-clause? clause)
  317.   (eq? (cond-predicate clause) 'else))
  318. ;; derive cond from if
  319. (define (cond->if expr)
  320.   (expand-clauses (cond-clauses expr)))
  321. (define (expand-clauses clauses)
  322.   (cond [(empty? clauses) 'false] ; no else clause
  323.         [else
  324.           (define first-clause (first clauses))
  325.           (define rest-clauses (rest clauses))
  326.           (cond [(cond-else-clause? first-clause)
  327.                  (if (empty? rest-clauses)
  328.                    (sequence->exp (cond-actions first-clause))
  329.                    (error "ELSE clause isn't last -- COND->IF" clauses))]
  330.                 [(cond-alternate-clause? first-clause)
  331.                  (define test (cond-test first-clause)) ; gets evaluated twice
  332.                  (make-if test
  333.                           (list (cond-recipient first-clause)
  334.                                 test)
  335.                           (expand-clauses rest-clauses))]
  336.                 [else
  337.                   (make-if (cond-predicate first-clause)
  338.                            (sequence->exp (cond-actions first-clause))
  339.                            (expand-clauses rest-clauses))])]))
  340.  
  341. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  342. ;; 9. LET, LET*, AND NAMED-LET  ;;
  343. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  344.  
  345. ;; Let has the form:  (let (<bindings>) <body>)
  346. (define (let? expr)
  347.   (and (tagged-list? expr 'let)
  348.        (list? (second expr))))
  349. (define (let-bindings expr) (second expr))
  350. (define (let-parameters expr) (map first (let-bindings expr)))
  351. (define (let-expressions expr) (map second (let-bindings expr)))
  352. (define (let-body expr) (drop expr 2))
  353. (define (let->combination expr)
  354.   (cond [(empty? (let-bindings expr)) ; do not unnecessarily lambda wrap
  355.          (sequence->exp (let-body expr))]
  356.         [else
  357.           (cons (make-lambda (let-parameters expr)
  358.                              (let-body expr))
  359.                 (let-expressions expr))]))
  360. (define (make-let bindings body)
  361.   (cons 'let (cons bindings body)))
  362.  
  363. ;; Let* has the same form as let, but bindings are sequential.
  364. (define (let*? expr) (tagged-list? expr 'let*))
  365. (define (let*-bindings expr) (second expr))
  366. (define (let*-body expr) (drop expr 2))
  367. (define (make-let* bindings body)
  368.   (cons 'let* (cons bindings body)))
  369. (define (let*->nested-lets expr)
  370.   (define bindings (let*-bindings expr))
  371.   (cond [(empty? bindings)
  372.          (sequence->exp (let-body expr))]
  373.         [else
  374.           (list 'let
  375.                 (list (first bindings))
  376.                 (let*->nested-lets
  377.                   (make-let* (rest bindings)
  378.                              (let-body expr))))]))
  379.  
  380. ;; Named-let has the form:  (let <name> (<bindings>) <body>)
  381. (define (named-let? expr)
  382.   (and (tagged-list? expr 'let)
  383.        (not (list? (second expr)))))
  384. (define (named-let-name expr) (second expr))
  385. (define (named-let-bindings expr) (third expr))
  386. (define (named-let-parameters expr) (map first (named-let-bindings expr)))
  387. (define (named-let-expressions expr) (map second (named-let-bindings expr)))
  388. (define (named-let-body expr) (drop expr 3))
  389. (define (named-let->sequence expr)
  390.   (define bindings (named-let-bindings expr))
  391.   (cond [(empty? bindings)
  392.          (sequence->exp (named-let-body expr))]
  393.         [else
  394.           (list 'begin
  395.                 (cons 'define ; first define the named function
  396.                       (cons (cons (named-let-name expr)
  397.                                   (named-let-parameters expr))
  398.                             (named-let-body expr)))
  399.                 (cons (named-let-name expr) ; then apply it to the expressions
  400.                       (named-let-expressions expr)))]))
  401.  
  402. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  403. ;; 10. ENVIRONMENT AND FRAMES  ;;
  404. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  405.  
  406. ;; An environment is a mutable list of frames.  The enclosing environment is the mcdr
  407. ;; of the list.  A frame is a mutable list of bindings with a 'frame header.  A
  408. ;; binding is a var-val pair ie (mcons var val).
  409.  
  410. ;; Environments support four procedures:
  411.     ;; lookup-variable-value
  412.     ;; extend-environment
  413.     ;; define-variable
  414.     ;; set-variable-value
  415.  
  416. ;; Two helper functions support the environment procedures:
  417.     ;; find-binding-in-frame
  418.     ;; find-binding-in-environment
  419.  
  420. (define (enclosing-environment env) (mcdr env))
  421. (define (first-frame env) (mcar env))
  422. (define the-empty-environment empty)
  423. (define the-empty-frame (mlist 'frame))
  424. (define (empty-frame? frame)
  425.   (empty? (frame-bindings frame)))
  426. (define (make-frame vars vals)
  427.   (mcons 'frame
  428.          (mmap mcons
  429.                (list->mlist vars)
  430.                (list->mlist vals))))
  431. (define (frame-bindings frame) (mcdr frame))
  432. (define (frame-variables frame) (mmap mcar (frame-bindings frame)))
  433. (define (frame-values frame) (mmap mcdr (frame-bindings frame)))
  434.  
  435. (define (binding-variable binding) (mcar binding))
  436. (define (binding-value binding) (mcdr binding))
  437. (define (set-value! binding val) (set-mcdr! binding val))
  438. (define (add-binding-to-frame! var val frame)
  439.   (mappend! frame (mlist (mcons var val))))
  440. (define (find-binding-in-frame var frame)
  441.   ; Return the var-val pair if present else false.
  442.   (define (loop bindings)
  443.     (cond [(empty? bindings) false]
  444.           [else
  445.             (define b (mcar bindings))
  446.             (if (eq? var (binding-variable b))
  447.               b
  448.               (loop (mcdr bindings)))]))
  449.   (loop (frame-bindings frame)))
  450. (define (find-binding-in-env var env)
  451.   ; Return the closest binding for var if present else false.
  452.   (cond [(eq? env the-empty-environment) false]
  453.         [else
  454.           (define b (find-binding-in-frame var (first-frame env)))
  455.           (or b (find-binding-in-env var (enclosing-environment env)))]))
  456.  
  457. (define (lookup-variable-value var env)
  458.   (define b (find-binding-in-env var env))
  459.   (if b
  460.     (binding-value b)
  461.     (error "Unbound variable" var)))
  462. (define (extend-environment vars vals base-env)
  463.   (cond [(= (length vars) (length vals))
  464.          (mcons (make-frame vars vals) base-env)]
  465.         [else
  466.           (if (< (length vars) (length vals))
  467.             (error "Too many arguments supplied" vars vals)
  468.             (error "Too few arguments supplied" vars vals))]))
  469. (define (define-variable! var val env)
  470.   (define frame (first-frame env))
  471.   (define b (find-binding-in-frame var frame))
  472.   (if b
  473.     (set-value! b val)
  474.     (add-binding-to-frame! var val frame)))
  475. (define (set-variable-value! var val env)
  476.   (define b (find-binding-in-env var env))
  477.   (if b
  478.     (set-value! b val)
  479.     (error "Unbound variable -- SET!" var)))
  480.  
  481. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  482. ;; 11. PRIMITIVE PROCEDURES AND THE GLOBAL ENVIRONMENT  ;;
  483. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  484.  
  485. (define primitive-procedures
  486.   (list
  487.     (list 'cons cons)
  488.     (list 'car car)
  489.     (list 'cdr cdr)
  490.     (list '+ +)
  491.     (list '* *)
  492.     (list '- -)
  493.     (list '< <)
  494.     (list '> >)
  495.     (list '<= <=)
  496.     (list '>= >=)
  497.     (list '= =)
  498.     (list 'not not)
  499.     (list 'false? false?)
  500.     (list 'true? (lambda (x) (not (false? x))))
  501.     (list 'empty? empty?)
  502.     (list 'displayln displayln)
  503.     (list 'list list)
  504.     ))
  505. (define (primitive-procedure? proc)
  506.   (tagged-list? proc 'primitive))
  507. (define (primitive-implementation proc)
  508.   (second proc))
  509. (define (primitive-procedure-names)
  510.   (map first primitive-procedures))
  511. (define (primitive-procedure-objects)
  512.   (map (lambda (proc) (list 'primitive (second proc)))
  513.        primitive-procedures))
  514. (define apply-in-underlying-scheme apply)
  515. ;; The metacircular evaluator's apply is my-apply.
  516. (define (apply-primitive-procedure proc args)
  517.   (apply-in-underlying-scheme
  518.     (primitive-implementation proc) args))
  519.  
  520. (define (setup-environment)
  521.   (define initial-env
  522.     (extend-environment (primitive-procedure-names)
  523.                         (primitive-procedure-objects)
  524.                         the-empty-environment))
  525.   (define-variable! 'true true initial-env)
  526.   (define-variable! 'false false initial-env)
  527.   initial-env)
  528. (define the-global-environment (setup-environment))
  529.  
  530. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  531. ;; 12. REPL OPERATIONS  ;;
  532. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  533.  
  534. (define input-prompt ";;; M-Eval input:")
  535. (define output-prompt ";;; M-Eval value:")
  536. (define (driver-loop)
  537.   (prompt-for-input input-prompt)
  538.   (let* ([input (read)]
  539.          [output (actual-value input the-global-environment)])
  540.     (announce-output output-prompt)
  541.     (user-print output))
  542.   (driver-loop))
  543. (define prompt-for-input displayln)
  544. (define announce-output displayln)
  545. (define (user-print object)
  546.   (if (compound-procedure? object)
  547.     (displayln (list 'compound-procedure
  548.                    (procedure-parameters object)
  549.                    (procedure-body object)
  550.                    '<procedure-env>))
  551.     (displayln object)))
  552.  
  553. ;;;;;;;;;;;;;;;
  554. ;; 13. TESTS ;;
  555. ;;;;;;;;;;;;;;;
  556.  
  557. ;; (my-eval '(define (try a (b lazy)) (if (= a 0) 1 b)) the-global-environment)
  558. ;; ;; 'ok
  559. ;; (my-eval '(try 0 (/ 1 0)) the-global-environment)
  560. ;; ;; 1
  561.  
  562. ;; ;; the book example with count and (id (id 10)) with lazy-memo:
  563.  
  564. ;; (my-eval '(define count 0) the-global-environment)
  565. ;; ;; 'ok
  566. ;; (my-eval '(define (id (x lazy-memo)) (set! count (+ count 1)) x)
  567.             ;; the-global-environment)
  568. ;; ;; 'ok
  569. ;; (my-eval 'count the-global-environment) ; should be 0
  570. ;; ;; 0
  571. ;; (my-eval '(define w (id (id 10))) the-global-environment)
  572. ;; ;; 'ok
  573. ;; (my-eval 'count the-global-environment) ; should be 1
  574. ;; ;; 1
  575. ;; (actual-value 'w the-global-environment) ; should be 10
  576. ;; ;; 10
  577. ;; (my-eval 'count the-global-environment) ; should be 2
  578. ;; ;; 2
  579. ;; (actual-value 'w the-global-environment)
  580. ;; ;; 10
  581. ;; (my-eval 'count the-global-environment) ; should still be 2
  582. ;; ;; 2
  583.  
  584. ;; ;; the book example with count and (id (id 10)) with lazy, no memo:
  585.  
  586. ;; (my-eval '(define count2 0) the-global-environment)
  587. ;; ;; 'ok
  588. ;; (my-eval '(define (id2 (x lazy)) (set! count2 (+ count2 1)) x) ; no memo
  589.             ;; the-global-environment)
  590. ;; ;; 'ok
  591. ;; (my-eval 'count2 the-global-environment) ; should be 0
  592. ;; ;; 0
  593. ;; (my-eval '(define w (id2 (id2 10))) the-global-environment)
  594. ;; ;; 'ok
  595. ;; (my-eval 'count2 the-global-environment) ; should be 1
  596. ;; ;; 1
  597. ;; (actual-value 'w the-global-environment) ; should be 10
  598. ;; ;; 10
  599. ;; (my-eval 'count2 the-global-environment) ; should be 2
  600. ;; ;; 2
  601. ;; (actual-value 'w the-global-environment)
  602. ;; ;; 10
  603. ;; (my-eval 'count2 the-global-environment) ; should be 3
  604. ;; ;; 3
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement