Advertisement
timothy235

sicp-4-3-3-exercises-amb-repl-program

Mar 25th, 2017
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 27.57 KB | None | 0 0
  1. #lang racket
  2. (require racket/mpair
  3.          math/number-theory) ; for prime?
  4. (provide (all-defined-out))
  5.  
  6. ;; This is the exercise 4.54 amb repl program.  It is the same as the 4.3.3 amb repl
  7. ;; program, except that we have implemented permanent-set! from exercise 4.51,
  8. ;; if-fail from exercise 4.52, and my-require is now a syntactic form and not a
  9. ;; defined function.
  10.  
  11. ;; PROGRAM SECTIONS:
  12.  
  13. ;; 1. my-eval and analyze
  14. ;; 2. amb and my-require
  15. ;; 3. self-evaluating expressions, variables, and quotations
  16. ;; 4. definition and assignment
  17. ;; 5. lambdas, procedures and applications
  18. ;; 6. sequences and begin expressions
  19. ;; 7. boolean expressions
  20. ;; 8. if and cond expressions
  21. ;; 9. let, let*, named-let, and letrec
  22. ;; 10. environment and frames
  23. ;; 11. primitive procedures and the global environment
  24. ;; 12. repl operations
  25. ;; 13. helper functions
  26.  
  27. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  28. ;; 1. MY-EVAL AND ANALYZE  ;;
  29. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  30.  
  31. (define (ambeval expr env succeed fail)
  32.   ((analyze expr) env succeed fail))
  33.  
  34. (define (analyze expr)
  35.   (cond [(self-evaluating? expr)
  36.          (analyze-self-evaluating expr)]
  37.         [(amb? expr) (analyze-amb expr)]
  38.         [(my-require? expr) (analyze-my-require expr)]
  39.         [(quoted? expr) (analyze-quoted expr)]
  40.         [(variable? expr) (analyze-variable expr)]
  41.         [(assignment? expr) (analyze-assignment expr)]
  42.         [(permanent-assignment? expr) (analyze-permanent-assignment expr)]
  43.         [(definition? expr) (analyze-definition expr)]
  44.         [(if? expr) (analyze-if expr)]
  45.         [(if-fail? expr) (analyze-if-fail expr)]
  46.         [(lambda? expr) (analyze-lambda expr)]
  47.         [(begin? expr) (analyze-sequence (begin-actions expr))]
  48.         [(cond? expr) (analyze (cond->if expr))]
  49.         [(and? expr) (analyze (and->if expr))]
  50.         [(or? expr) (analyze (or->if expr))]
  51.         [(let? expr) (analyze (let->combination expr))]
  52.         [(let*? expr) (analyze (let*->nested-lets expr))]
  53.         [(named-let? expr) (analyze (named-let->sequence expr))]
  54.         [(letrec? expr) (analyze (letrec->simultaneous-lets expr))]
  55.         [(application? expr) (analyze-application expr)]
  56.         [else (error "Unknown expression type -- ANALYZE" expr)]))
  57.  
  58. ;;;;;;;;;;;;;;;;;;;;;;;;;;;
  59. ;; 2. AMB AND MY-REQUIRE ;;
  60. ;;;;;;;;;;;;;;;;;;;;;;;;;;;
  61.  
  62. (define (amb? expr) (tagged-list? expr 'amb))
  63. (define (amb-choices expr) (rest expr))
  64.  
  65. ;; succeed and fail are continuations.  A success continuation is a function of two
  66. ;; arguments, the value just obtained and a fail continuation used to backtrack.  A
  67. ;; fail continuation is a function of no arguments.
  68.  
  69. ;; analyze will return an execution procedure which will look like:
  70. ;; (lambda (env succeed fail)
  71.   ;; ;; succeed is (lambda (value fail) ...)
  72.   ;; ;; fail is (lambda () ...)
  73.   ;; ...)
  74. (define (analyze-amb expr)
  75.   (define cprocs (map analyze (amb-choices expr)))
  76.   (lambda (env succeed fail)
  77.     (define (try-next choices)
  78.       (if (empty? choices)
  79.         (fail)
  80.         ((first choices) env
  81.                          succeed
  82.                          (lambda ()
  83.                            (try-next (rest choices))))))
  84.     (try-next cprocs)))
  85.  
  86. ;; my-require
  87. (define (my-require? expr) (tagged-list? expr 'my-require))
  88. (define (my-require-predicate expr) (second expr))
  89. (define (analyze-my-require expr)
  90.   (define pproc (analyze (my-require-predicate expr)))
  91.   (lambda (env succeed fail)
  92.     (pproc env
  93.            (lambda (pred-value fail2)
  94.              (if (not pred-value)
  95.                (fail2)
  96.                (succeed 'ok fail2)))
  97.            fail)))
  98.  
  99. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  100. ;; 3. SELF-EVALUATING EXPRESSIONS, VARIABLES, AND QUOTATIONS  ;;
  101. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  102.  
  103. (define (tagged-list? expr tag)
  104.   (if (pair? expr)
  105.     (eq? (first expr) tag)
  106.     false))
  107. (define *reserved-symbols*
  108.   (list
  109.     '*unassigned*
  110.     ))
  111.  
  112. ;; Only numbers, strings, and reserved symbols are self-evaluating.
  113. (define (self-evaluating? expr)
  114.   (or (number? expr)
  115.       (string? expr)
  116.       (member expr *reserved-symbols*)))
  117. (define (analyze-self-evaluating expr)
  118.   (lambda (env succeed fail)
  119.     (succeed expr fail)))
  120. (define (variable? expr)
  121.   (and (symbol? expr)
  122.        (not (member expr *reserved-symbols*))))
  123. (define (analyze-variable expr)
  124.   (lambda (env succeed fail)
  125.     (succeed (lookup-variable-value expr env)
  126.              fail)))
  127.  
  128. ;; Quotations have the form:  (quote <text-of-quotation>)
  129. (define (quoted? expr)
  130.   (tagged-list? expr 'quote))
  131. (define (text-of-quotation expr)
  132.   (second expr))
  133. (define (analyze-quoted expr)
  134.   (define qval (text-of-quotation expr))
  135.   (lambda (env succeed fail)
  136.     (succeed qval fail)))
  137.  
  138. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  139. ;; 4. DEFINITION AND ASSIGNMENT  ;;
  140. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  141.  
  142. ;; Variable definitions have the form:  (define <var> <value>)
  143.  
  144. ;; Procedure definitions have the form:
  145. ;; (define (<var> <parameter-1> ... <parameter-n>) <body>)
  146. ;; which is equivalent to:
  147. ;; (define <var> (lambda (<parameter-1> ... <parameter-n>) <body>))
  148. (define (definition? expr) (tagged-list? expr 'define))
  149. (define (definition-variable expr)
  150.   (if (symbol? (second expr))
  151.     (second expr)
  152.     (first (second expr))))
  153. (define (definition-value expr)
  154.   (if (symbol? (second expr))
  155.     (third expr)
  156.     (make-lambda (rest (second expr)) ; formal parameters
  157.                  (drop expr 2))))
  158. (define (analyze-definition expr)
  159.   (define var (definition-variable expr))
  160.   (define vproc (analyze (definition-value expr)))
  161.   (lambda (env succeed fail)
  162.     (vproc env
  163.            (lambda (val fail2)
  164.              (define-variable! var val env)
  165.              (succeed 'ok fail2))
  166.            fail)))
  167.  
  168. ;; Assignments have the form:  (set! <var> <value>)
  169. (define (assignment? expr)
  170.   (tagged-list? expr 'set!))
  171. (define (assignment-variable expr) (second expr))
  172. (define (assignment-value expr) (third expr))
  173. ; must remember old value to restore if branch later fails
  174. (define (analyze-assignment expr)
  175.   (define var (assignment-variable expr))
  176.   (define vproc (analyze (assignment-value expr)))
  177.   (lambda (env succeed fail)
  178.     (vproc env
  179.            (lambda (val fail2)      ; *1*
  180.              (define old-value (lookup-variable-value var env))
  181.              (set-variable-value! var val env)
  182.              (succeed 'ok
  183.                       (lambda ()    ; *2*
  184.                         (set-variable-value! var old-value env)
  185.                         (fail2))))
  186.            fail)))
  187.  
  188. ;; Permanent assignments have the form:  (permanent-set! <var> <value>)
  189. (define (permanent-assignment? expr)
  190.   (tagged-list? expr 'permanent-set!))
  191. (define (permanent-assignment-variable expr) (second expr))
  192. (define (permanent-assignment-value expr) (third expr))
  193. ; do not restore old value if branch later fails
  194. (define (analyze-permanent-assignment expr)
  195.   (define var (permanent-assignment-variable expr))
  196.   (define vproc (analyze (permanent-assignment-value expr)))
  197.   (lambda (env succeed fail)
  198.     (vproc env
  199.            (lambda (val fail2)
  200.              (set-variable-value! var val env)
  201.              (succeed 'ok
  202.                       (lambda ()
  203.                         (fail2))))
  204.            fail)))
  205.  
  206. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  207. ;; 5. LAMBDAS, PROCEDURES AND APPLICATIONS  ;;
  208. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  209.  
  210. ;; Lambda expressions have the form:
  211. ;; (lambda (<parameters>) <body>)
  212. (define (lambda? expr) (tagged-list? expr 'lambda))
  213. (define (lambda-parameters expr) (second expr))
  214. (define (lambda-body expr)
  215.   (drop expr 2))
  216. (define (make-lambda parameters body)
  217.   (cons 'lambda (cons parameters body)))
  218. (define (scan-out-defines body)
  219.   (define defines (filter definition? body))
  220.   (cond [(empty? defines) body]
  221.         [else
  222.           (define rest-of-body (filter-not definition? body))
  223.           (define vars (map definition-variable defines))
  224.           (define vals (map definition-value defines))
  225.           (define bindings
  226.             (for/list ([v vars])
  227.                       (list v '*unassigned*)))
  228.           (define assigns
  229.             (for/list ([v vars]
  230.                        [e vals])
  231.                       (list 'set! v e)))
  232.           ; a body is a list of expressions
  233.           (list
  234.             (make-let
  235.               bindings
  236.               (append assigns rest-of-body)))]))
  237. (define (analyze-lambda expr) ; changed
  238.   (define vars (lambda-parameters expr))
  239.   (define bproc (analyze-sequence (scan-out-defines (lambda-body expr))))
  240.   (lambda (env succeed fail)
  241.     (succeed (make-procedure vars bproc env)
  242.              fail)))
  243.  
  244. ;; Procedures:
  245. (define (compound-procedure? p)
  246.   (tagged-list? p 'procedure))
  247. (define (make-procedure parameters body env)
  248.   (list 'procedure parameters body env))
  249. (define (procedure-parameters p) (second p))
  250. (define (procedure-body p) (third p))
  251. (define (procedure-environment p) (fourth p))
  252.  
  253. ;; Procedure applications have the from:
  254. ;; (<var> <parameter> ...)
  255. (define (application? expr) (pair? expr))
  256. (define (operator expr) (first expr))
  257. (define (operands expr) (rest expr))
  258. (define (no-operands? ops) (empty? ops))
  259. (define (first-operand ops) (first ops))
  260. (define (rest-operands ops) (rest ops))
  261. (define (analyze-application expr)
  262.   (define fproc (analyze (operator expr)))
  263.   (define aprocs (map analyze (operands expr)))
  264.   (lambda (env succeed fail)
  265.     (fproc env
  266.            (lambda (proc fail2)
  267.              (get-args aprocs
  268.                        env
  269.                        (lambda (args fail3)
  270.                          (execute-application
  271.                            proc args succeed fail3))
  272.                        fail2))
  273.            fail)))
  274.  
  275. ;; "In get-args, notice how cdring down the list of aproc execution procedures and
  276. ;; consing up the resulting list of args is accomplished by calling each aproc in the
  277. ;; list with a success continuation that recursively calls get-args. Each of these
  278. ;; recursive calls to get-args has a success continuation whose value is the cons of
  279. ;; the newly obtained argument onto the list of accumulated arguments:"
  280.  
  281. (define (get-args aprocs env succeed fail)
  282.   (if (empty? aprocs)
  283.     (succeed empty fail)
  284.     ((first aprocs) env
  285.                     ; success continuation for this aproc
  286.                     (lambda (arg fail2)
  287.                       (get-args (rest aprocs)
  288.                                 env
  289.                                 ; success continuation for recursive call to
  290.                                 ; get-args
  291.                                 (lambda (args fail3)
  292.                                   (succeed (cons arg args)
  293.                                            fail3))
  294.                                 fail2))
  295.                     fail)))
  296. (define (execute-application proc args succeed fail)
  297.   (cond [(primitive-procedure? proc)
  298.          (succeed (apply-primitive-procedure proc args)
  299.                   fail)]
  300.         [(compound-procedure? proc)
  301.          ((procedure-body proc)
  302.           (extend-environment (procedure-parameters proc)
  303.                               args
  304.                               (procedure-environment proc))
  305.           succeed
  306.           fail)]
  307.         [else
  308.           (error "Unknown procedure type -- EXECUTE-APPLICATION" proc)]))
  309.  
  310. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  311. ;; 6. SEQUENCES AND BEGIN EXPRESSIONS  ;;
  312. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  313.  
  314. ;; Begin has the form:  (begin <actions>)
  315. (define (begin? expr) (tagged-list? expr 'begin))
  316. (define (begin-actions expr) (rest expr))
  317. (define (last-exp? seq) (empty? (rest seq)))
  318. (define (first-exp seq) (first seq))
  319. (define (rest-exps seq) (rest seq))
  320. (define (sequence->exp seq)
  321.   (cond [(empty? seq) seq]
  322.         [(last-exp? seq) (first-exp seq)]
  323.         [else (make-begin seq)]))
  324. (define (make-begin seq) (cons 'begin seq))
  325. (define (analyze-sequence exprs)
  326.   (define (sequentially a b)
  327.     (lambda (env succeed fail)
  328.       (a env
  329.          ; success continuation for calling a
  330.          (lambda (a-value fail2)
  331.            (b env succeed fail2))
  332.          ; failure continuation for calling a
  333.          fail)))
  334.   (define (loop first-proc rest-procs)
  335.     (if (empty? rest-procs)
  336.       first-proc
  337.       (loop (sequentially first-proc (first rest-procs))
  338.             (rest rest-procs))))
  339.   (define procs (map analyze exprs))
  340.   (if (empty? procs) (error "Empty sequence -- ANALYZE")
  341.     (loop (first procs) (rest procs))))
  342.  
  343. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  344. ;; 7. BOOLEAN EXPRESSIONS  ;;
  345. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  346.  
  347. (define (true? x) (not (false? x)))
  348. (define (and? expr) (tagged-list? expr 'and))
  349. (define (and-operands expr) (rest expr))
  350. (define (make-and sequence) (cons 'and sequence))
  351. (define (and->if expr)
  352.   (expand-and-operands (and-operands expr)))
  353. (define (expand-and-operands ops)
  354.   (cond [(empty? ops) 'true]
  355.         [else
  356.           (define first-op (first ops))
  357.           (define rest-ops (rest ops))
  358.           (cond [(empty? rest-ops) first-op]
  359.                 [else
  360.                   (make-if first-op
  361.                            (and->if (make-and rest-ops))
  362.                            'false)])]))
  363. (define (or? expr) (tagged-list? expr 'or))
  364. (define (or-operands expr) (rest expr))
  365. (define (make-or sequence) (cons 'or sequence))
  366. (define (or->if expr)
  367.   (expand-or-operands (or-operands expr)))
  368. (define (expand-or-operands ops)
  369.   (cond [(empty? ops) 'false] ; (or) should return false
  370.         [else
  371.           (define first-op (first ops))
  372.           (define rest-ops (rest ops))
  373.           (cond [(empty? rest-ops) first-op] ; (or x) should return x
  374.                 [else
  375.                   (make-if first-op
  376.                            first-op ; inefficient second evaluation
  377.                            (or->if (make-or rest-ops)))])]))
  378.  
  379. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  380. ;; 8. IF AND COND EXPRESSIONS  ;;
  381. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  382.  
  383. ;; Conditionals have the form:  (if <predicate> <consequent> <alternative>)
  384. ;; If no alternative, use false.
  385. (define (if? expr) (tagged-list? expr 'if))
  386. (define (if-predicate expr) (second expr))
  387. (define (if-consequent expr) (third expr))
  388. (define (if-alternative expr)
  389.   (if (not (empty? (drop expr 3)))
  390.     (fourth expr)
  391.     'false))
  392. (define (make-if predicate consequent alternative)
  393.   (list 'if predicate consequent alternative))
  394. (define (analyze-if expr)
  395.   (define pproc (analyze (if-predicate expr)))
  396.   (define cproc (analyze (if-consequent expr)))
  397.   (define aproc (analyze (if-alternative expr)))
  398.   (lambda (env succeed fail)
  399.     (pproc env
  400.            ; success continuation for evaluating the predicate
  401.            ; to obtain pred-value
  402.            (lambda (pred-value fail2)
  403.              (if pred-value ; (true? pred-value)
  404.                (cproc env succeed fail2)
  405.                (aproc env succeed fail2)))
  406.            ; failure continuation for evaluating the predicate
  407.            fail)))
  408.  
  409. ;; if-fail has the form:  (if-fail <success-clause> <failure-clause>)
  410. (define (if-fail? expr) (tagged-list? expr 'if-fail))
  411. (define (if-fail-success-clause expr) (second expr))
  412. (define (if-fail-failure-clause expr) (third expr))
  413. (define (analyze-if-fail expr)
  414.   (define sproc (analyze (if-fail-success-clause expr)))
  415.   (define fproc (analyze (if-fail-failure-clause expr)))
  416.   (lambda (env succeed fail)
  417.     (sproc env
  418.            (lambda (val fail2)
  419.              (succeed val fail2))
  420.            (lambda () (fproc env succeed fail)))))
  421.  
  422. ;; Cond has the form:
  423. ;; (cond ((<predicate> <actions>)
  424.        ;; (else <actions>))) ; if no else, assume (else false) clause
  425. (define (cond? expr) (tagged-list? expr 'cond))
  426. (define (cond-clauses expr) (rest expr))
  427. ;; regular cond clause
  428. (define (cond-predicate clause) (first clause))
  429. (define (cond-actions clause) (rest clause))
  430. ;; alternate test clause
  431. (define (cond-alternate-clause? clause)
  432.   (eq? (second clause) '=>))
  433. (define (cond-test clause) (first clause))
  434. (define (cond-recipient clause) (third clause))
  435. ;; else clause
  436. (define (cond-else-clause? clause)
  437.   (eq? (cond-predicate clause) 'else))
  438. ;; derive cond from if
  439. (define (cond->if expr)
  440.   (expand-clauses (cond-clauses expr)))
  441. (define (expand-clauses clauses)
  442.   (cond [(empty? clauses) 'false] ; no else clause
  443.         [else
  444.           (define first-clause (first clauses))
  445.           (define rest-clauses (rest clauses))
  446.           (cond [(cond-else-clause? first-clause)
  447.                  (if (empty? rest-clauses)
  448.                    (sequence->exp (cond-actions first-clause))
  449.                    (error "ELSE clause is not last -- COND->IF" clauses))]
  450.                 [(cond-alternate-clause? first-clause)
  451.                  (define test (cond-test first-clause)) ; gets evaluated twice
  452.                  (make-if test
  453.                           (list (cond-recipient first-clause)
  454.                                 test)
  455.                           (expand-clauses rest-clauses))]
  456.                 [else
  457.                   (make-if (cond-predicate first-clause)
  458.                            (sequence->exp (cond-actions first-clause))
  459.                            (expand-clauses rest-clauses))])]))
  460.  
  461. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  462. ;; 9. LET, LET*, NAMED-LET, AND LETREC  ;;
  463. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  464.  
  465. ;; Let has the form:  (let (<bindings>) <body>)
  466. (define (let? expr)
  467.   (and (tagged-list? expr 'let)
  468.        (list? (second expr))))
  469. (define (let-bindings expr) (second expr))
  470. (define (let-parameters expr) (map first (let-bindings expr)))
  471. (define (let-expressions expr) (map second (let-bindings expr)))
  472. (define (let-body expr) (drop expr 2))
  473. (define (let->combination expr)
  474.   (cond [(empty? (let-bindings expr)) ; do not unnecessarily lambda wrap
  475.          (sequence->exp (let-body expr))]
  476.         [else
  477.           (cons (make-lambda (let-parameters expr)
  478.                              (let-body expr))
  479.                 (let-expressions expr))]))
  480. (define (make-let bindings body)
  481.   (cons 'let (cons bindings body)))
  482.  
  483. ;; Let* has the same form as let, but bindings are sequential.
  484. (define (let*? expr) (tagged-list? expr 'let*))
  485. (define (let*-bindings expr) (second expr))
  486. (define (let*-body expr) (drop expr 2))
  487. (define (make-let* bindings body)
  488.   (cons 'let* (cons bindings body)))
  489. (define (let*->nested-lets expr)
  490.   (define bindings (let*-bindings expr))
  491.   (cond [(empty? bindings)
  492.          (sequence->exp (let-body expr))]
  493.         [else
  494.           (list 'let
  495.                 (list (first bindings))
  496.                 (let*->nested-lets
  497.                   (make-let* (rest bindings)
  498.                              (let-body expr))))]))
  499.  
  500. ;; Named-let has the form:  (let <name> (<bindings>) <body>)
  501. (define (named-let? expr)
  502.   (and (tagged-list? expr 'let)
  503.        (not (list? (second expr)))))
  504. (define (named-let-name expr) (second expr))
  505. (define (named-let-bindings expr) (third expr))
  506. (define (named-let-parameters expr) (map first (named-let-bindings expr)))
  507. (define (named-let-expressions expr) (map second (named-let-bindings expr)))
  508. (define (named-let-body expr) (drop expr 3))
  509. (define (named-let->sequence expr)
  510.   (define bindings (named-let-bindings expr))
  511.   (cond [(empty? bindings)
  512.          (sequence->exp (named-let-body expr))]
  513.         [else
  514.           (list 'begin
  515.                 (cons 'define ; first define the named function
  516.                       (cons (cons (named-let-name expr)
  517.                                   (named-let-parameters expr))
  518.                             (named-let-body expr)))
  519.                 (cons (named-let-name expr) ; then apply it to the expressions
  520.                       (named-let-expressions expr)))]))
  521.  
  522. ;; Letrec has the same form as let, but letrec parameters are first bound to
  523. ;; '*unassigned* and then set! to their values to mimic simultaneous definitions.
  524. (define (letrec? expr) (tagged-list? expr 'letrec))
  525. (define (letrec-bindings expr) (second expr))
  526. (define (letrec-body expr) (drop expr 2))
  527. (define (letrec->simultaneous-lets expr)
  528.   (define bindings (letrec-bindings expr))
  529.   (cond [(empty? bindings)
  530.          (letrec-body expr)]
  531.         [else
  532.           (define vars (map first bindings))
  533.           (define vals (map second bindings))
  534.           (define new-bindings
  535.             (for/list ([v vars])
  536.                       (list v '*unassigned*)))
  537.           (define assigns
  538.             (for/list ([v vars]
  539.                        [e vals])
  540.                       (list 'set! v e)))
  541.           (make-let
  542.             new-bindings
  543.             (append assigns (letrec-body expr)))]))
  544.  
  545. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  546. ;; 10. ENVIRONMENT AND FRAMES  ;;
  547. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  548.  
  549. ;; An environment is a mutable list of frames.  The enclosing environment is the mcdr
  550. ;; of the list.  A frame is a mutable list of bindings with a 'frame header.  A
  551. ;; binding is a var-val pair ie (mcons var val).
  552.  
  553. ;; Environments support four procedures:
  554.     ;; lookup-variable-value
  555.     ;; extend-environment
  556.     ;; define-variable
  557.     ;; set-variable-value
  558.  
  559. ;; Two helper functions support the environment procedures:
  560.     ;; find-binding-in-frame
  561.     ;; find-binding-in-environment
  562.  
  563. (define (enclosing-environment env) (mcdr env))
  564. (define (first-frame env) (mcar env))
  565. (define the-empty-environment empty)
  566. (define the-empty-frame (mlist 'frame))
  567. (define (empty-frame? frame)
  568.   (empty? (frame-bindings frame)))
  569. (define (make-frame vars vals)
  570.   (mcons 'frame
  571.          (mmap mcons
  572.                (list->mlist vars)
  573.                (list->mlist vals))))
  574. (define (frame-bindings frame) (mcdr frame))
  575. (define (frame-variables frame) (mmap mcar (frame-bindings frame)))
  576. (define (frame-values frame) (mmap mcdr (frame-bindings frame)))
  577.  
  578. (define (binding-variable binding) (mcar binding))
  579. (define (binding-value binding) (mcdr binding))
  580. (define (set-value! binding val) (set-mcdr! binding val))
  581. (define (add-binding-to-frame! var val frame)
  582.   (mappend! frame (mlist (mcons var val))))
  583. (define (find-binding-in-frame var frame)
  584.   ; Return the var-val pair if present else false.
  585.   (define (loop bindings)
  586.     (cond [(empty? bindings) false]
  587.           [else
  588.             (define b (mcar bindings))
  589.             (if (eq? var (binding-variable b))
  590.               b
  591.               (loop (mcdr bindings)))]))
  592.   (loop (frame-bindings frame)))
  593. (define (find-binding-in-env var env)
  594.   ; Return the closest binding for var if present else false.
  595.   (cond [(eq? env the-empty-environment) false]
  596.         [else
  597.           (define b (find-binding-in-frame var (first-frame env)))
  598.           (or b (find-binding-in-env var (enclosing-environment env)))]))
  599.  
  600. ;; (define (lookup-variable-value var env)
  601.   ;; (define b (find-binding-in-env var env))
  602.   ;; (cond [(not b) (error "Unbound variable" var)]
  603.         ;; [else
  604.           ;; (define val (binding-value b))
  605.           ;; (if (eq? val '*unassigned*)
  606.             ;; (error "Unassigned variable" var)
  607.             ;; val)]))
  608. (define (lookup-variable-value var env)
  609.   (define b (find-binding-in-env var env))
  610.   (if (false? b)
  611.     (error "Unbound variable" var)
  612.     (binding-value b)))
  613. (define (extend-environment vars vals base-env)
  614.   (cond [(= (length vars) (length vals))
  615.          (mcons (make-frame vars vals) base-env)]
  616.         [else
  617.           (if (< (length vars) (length vals))
  618.             (error "Too many arguments supplied" vars vals)
  619.             (error "Too few arguments supplied" vars vals))]))
  620. (define (define-variable! var val env)
  621.   (define frame (first-frame env))
  622.   (define b (find-binding-in-frame var frame))
  623.   (if b
  624.     (set-value! b val)
  625.     (add-binding-to-frame! var val frame)))
  626. (define (set-variable-value! var val env)
  627.   (define b (find-binding-in-env var env))
  628.   (if b
  629.     (set-value! b val)
  630.     (error "Unbound variable -- SET!" var)))
  631.  
  632. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  633. ;; 11. PRIMITIVE PROCEDURES AND THE GLOBAL ENVIRONMENT  ;;
  634. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  635.  
  636. (define primitive-procedures
  637.   (list
  638.     ; booleans
  639.     (list 'not not)
  640.     (list 'false? false?)
  641.     (list 'true? (lambda (x) (not (false? x))))
  642.     ; symbols
  643.     (list 'eq? eq?)
  644.     ; lists
  645.     (list 'cons cons)
  646.     (list 'car car)
  647.     (list 'cdr cdr)
  648.     (list 'list list)
  649.     (list 'member member)
  650.     (list 'empty? empty?)
  651.     (list 'first first)
  652.     (list 'rest rest)
  653.     (list 'second second)
  654.     ; numbers
  655.     (list 'even? even?)
  656.     (list 'odd? odd?)
  657.     (list '+ +)
  658.     (list '* *)
  659.     (list '- -)
  660.     (list '< <)
  661.     (list '> >)
  662.     (list '<= <=)
  663.     (list '>= >=)
  664.     (list '= =)
  665.     (list 'abs abs)
  666.     (list 'prime? prime?)
  667.     ))
  668. (define (primitive-procedure? proc)
  669.   (tagged-list? proc 'primitive))
  670. (define (primitive-implementation proc)
  671.   (second proc))
  672. (define (primitive-procedure-names)
  673.   (map first primitive-procedures))
  674. (define (primitive-procedure-objects)
  675.   (map (lambda (proc) (list 'primitive (second proc)))
  676.        primitive-procedures))
  677. (define apply-in-underlying-scheme apply)
  678. ;; The metacircular evaluator's apply is my-apply.
  679. (define (apply-primitive-procedure proc args)
  680.   (apply-in-underlying-scheme
  681.     (primitive-implementation proc) args))
  682.  
  683. (define (setup-environment)
  684.   (define initial-env
  685.     (extend-environment (primitive-procedure-names)
  686.                         (primitive-procedure-objects)
  687.                         the-empty-environment))
  688.   (define-variable! 'true true initial-env)
  689.   (define-variable! 'false false initial-env)
  690.   initial-env)
  691. (define the-global-environment (setup-environment))
  692.  
  693. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  694. ;; 12. REPL OPERATIONS  ;;
  695. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  696.  
  697. (define input-prompt ";;; Amb-Eval input:")
  698. (define output-prompt ";;; Amb-Eval value:")
  699. (define (driver-loop)
  700.   (define (internal-loop try-again)
  701.     (prompt-for-input input-prompt)
  702.     (define input (read))
  703.     (cond [(eq? input 'try-again) (try-again)]
  704.           [else
  705.             (displayln ";;; Starting a new problem ")
  706.             (ambeval input
  707.                      the-global-environment
  708.                      ; ambeval success
  709.                      (lambda (val next-alternative)
  710.                        (announce-output output-prompt)
  711.                        (user-print val)
  712.                        (internal-loop next-alternative))
  713.                      ; ambeval failure
  714.                      (lambda ()
  715.                        (announce-output
  716.                          ";;; There are no more values of")
  717.                        (user-print input)
  718.                        (driver-loop)))]))
  719.   (internal-loop
  720.     (lambda ()
  721.       (displayln ";;; There is no current problem")
  722.       (driver-loop))))
  723. (define prompt-for-input displayln)
  724. (define announce-output displayln)
  725. (define (user-print object)
  726.   (if (compound-procedure? object)
  727.     (displayln (list 'compound-procedure
  728.                    (procedure-parameters object)
  729.                    (procedure-body object)
  730.                    '<procedure-env>))
  731.     (displayln object)))
  732.  
  733. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  734. ;; 13. INSTALL SOME HELPER FUNCTIONS ;;
  735. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  736.  
  737. (define helpers
  738.   (list
  739.     '(define (distinct? items)
  740.        (cond [(empty? items) true]
  741.              [(empty? (cdr items)) true]
  742.              [(member (car items) (cdr items)) false]
  743.              [else (distinct? (cdr items))]))
  744.     '(define (an-element-of items)
  745.        (my-require (not (empty? items)))
  746.        (amb (car items) (an-element-of (cdr items))))
  747.     '(define (an-integer-starting-from n)
  748.        (amb n (an-integer-starting-from (+ n 1))))
  749.     ))
  750. (define (install-helpers)
  751.   (define (install expr)
  752.     (ambeval expr
  753.              the-global-environment
  754.              (lambda (value fail) value)
  755.              (lambda () 'failed)))
  756.   (for ([e helpers])
  757.     (install e))
  758.   'helper-functions-installed)
  759. (install-helpers)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement