Advertisement
Guest User

Untitled

a guest
May 18th, 2019
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 4.72 KB | None | 0 0
  1. #lang racket
  2.  
  3. (define globals (make-hash))
  4.  
  5. (define-struct amb-function [argument body env])
  6.  
  7. (define (extend-environment name value env)
  8.   (cons (cons name value) env))
  9.  
  10. (define (lookup-variable name env)
  11.   (cond
  12.     [(assq name env) => cdr]
  13.     [(hash-ref globals name)]))
  14.  
  15. (define (amb-function* arguments body env)
  16.   (when (null? arguments)
  17.     (error "amb-function requires at least one argument"))
  18.   (if (null? (cdr arguments))
  19.       (amb-function (car arguments) body env)
  20.       (amb-function (car arguments)
  21.                     (amb-function* (cdr arguments) body env)
  22.                     env)))
  23.  
  24. (define (stream-mappend function stream)
  25.   (stream-fold stream-append empty-stream
  26.                (stream-map function stream)))
  27.  
  28. (define (amb-apply1 function argument)
  29.   (stream-mappend
  30.    (lambda (x)
  31.      (cond
  32.        [(amb-function? x)
  33.         (evaluate (amb-function-body x)
  34.                   (extend-environment (amb-function-argument x)
  35.                                       (stream argument)
  36.                                       (amb-function-env x)))]
  37.        [(procedure? x)
  38.         (stream (x argument))]
  39.        [else (error "not a function" x)]))
  40.    function))
  41.  
  42. (define (amb-apply function arguments)
  43.   (if (null? arguments)
  44.       function
  45.       (let ([app1 (stream-mappend (lambda (x)
  46.                                     (amb-apply1 function x))
  47.                                   (car arguments))])
  48.         (amb-apply app1 (cdr arguments)))))
  49.  
  50. (define (amb values env)
  51.   (if (null? values)
  52.       empty-stream
  53.       (stream-append (evaluate (car values) env)
  54.                      (amb (cdr values) env))))
  55.  
  56. (define (evaluate value env)
  57.   (match value
  58.     [`(lambda ,arguments ,body)
  59.      (evaluate
  60.       (let loop ([arguments arguments])
  61.         (cond
  62.          [(null? arguments)
  63.           (error "lambda takes at least one argument")]
  64.          [(null? (cdr arguments))
  65.           `(lambda1 ,(car arguments) ,body)]
  66.          [else
  67.           `(lambda1 ,(car arguments)
  68.                     ,(loop (cdr arguments)))]))
  69.       env)]
  70.     [`(lambda1 ,argument ,body)
  71.      (stream (amb-function argument body env))]
  72.     [`(let ,binds ,body)
  73.      (let ([new-value `((lambda ,(map first binds) ,body) . ,(map second binds))])
  74.        (evaluate new-value env))]
  75.     [`(begin . ,exprs)
  76.      (for/last ([expr exprs])
  77.        (evaluate expr env))]
  78.     [`(quote ,value) (stream value)]
  79.     [`(amb . ,values)
  80.      (amb values env)]
  81.     [`(define (,name . ,args) ,body)
  82.      (evaluate
  83.       `(define ,name (lambda ,args ,body))
  84.       env)]
  85.     [`(define ,name ,value)
  86.      (hash-set! globals name
  87.                 (evaluate value env))
  88.      (stream name)]
  89.     [`(if ,test ,then ,else)
  90.      ;; Try to avoid repeating evaluation.
  91.      (let ([then (delay (evaluate then env))]
  92.            [else (delay (evaluate else env))])
  93.        (stream-mappend (lambda (x)
  94.                          (if x
  95.                              (force then)
  96.                              (force else)))
  97.                        (evaluate test env)))]
  98.     [`(,function . ,args)
  99.      (let ([function (evaluate function env)]
  100.            [args (map (lambda (x) (evaluate x env)) args)])
  101.        (amb-apply function args))]
  102.     [_
  103.      (if (symbol? value)
  104.          (lookup-variable value env)
  105.          (stream value))]))
  106.  
  107. (define (curry2 proc)
  108.   (lambda (x)
  109.     (lambda (y)
  110.       (proc x y))))
  111.  
  112. (define default-environment
  113.   `((cons . ,(stream (curry2 cons)))
  114.     (car  . ,(stream car))
  115.     (cdr  . ,(stream cdr))
  116.     (add1 . ,(stream add1))
  117.     (print . ,(stream print))
  118.     (>    . ,(stream (curry2 >)))
  119.     (=    . ,(stream (curry2 =)))
  120.     (*    . ,(stream (curry2 *)))
  121.     (+    . ,(stream (curry2 +)))
  122.     (~    . ,(stream -))
  123.     (-    . ,(stream (curry2 -)))
  124.     (+-   . ,(stream (amb-function 'x
  125.                                    '(amb x (~ x))
  126.                                    '())))
  127.     (not  . ,(stream not))
  128.     (range . ,(stream (amb-function 'low
  129.                                     '(lambda (high) (if (> low high)
  130.                                                         (amb)
  131.                                                         (amb low
  132.                                                              (range (add1 low)
  133.                                                                     high))))
  134.                                     '())))))
  135. (for ([pair default-environment])
  136.   (match pair
  137.    [(cons name value)
  138.     (hash-set! globals name value)]))
  139.  
  140. (define (repl (environment '()))
  141.   (let loop ()
  142.     (let ([input (read)])
  143.       (with-handlers ([exn:fail? (lambda (e) (displayln e))])
  144.         (time
  145.          (for ([value (evaluate input environment)])
  146.            (pretty-print value)))))
  147.     (loop)))
  148.  
  149. (repl)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement