Advertisement
Guest User

world's shittest amb

a guest
May 20th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 5.50 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.     (nil  . ,(stream '()))
  119.     (null? . ,(stream null?))
  120.     (>    . ,(stream (curry2 >)))
  121.     (=    . ,(stream (curry2 =)))
  122.     (*    . ,(stream (curry2 *)))
  123.     (+    . ,(stream (curry2 +)))
  124.     (~    . ,(stream -))
  125.     (-    . ,(stream (curry2 -)))
  126.     (+-   . ,(stream (amb-function 'x
  127.                                    '(amb x (~ x))
  128.                                    '())))
  129.     (not  . ,(stream not))
  130.     (range . ,(stream (amb-function 'low
  131.                                     '(lambda (high) (if (> low high)
  132.                                                         (amb)
  133.                                                         (amb low
  134.                                                              (range (add1 low)
  135.                                                                     high))))
  136.                                     '())))))
  137. (for ([pair default-environment])
  138.   (match pair
  139.    [(cons name value)
  140.     (hash-set! globals name value)]))
  141.  
  142. (define (repl (environment '()))
  143.   (let ([input (read)])
  144.     (with-handlers ([exn:fail? (lambda (e) (displayln e))])
  145.       (let ([st (evaluate input environment)])
  146.         (println (stream-first st))
  147.         (let print-loop ([st (stream-rest st)])
  148.           (if (stream-empty? st)
  149.               (displayln "--end--")
  150.               (let ([command (read)])
  151.                 (cond
  152.                   [(eq? command 'q)
  153.                    (displayln "--stopped--")]
  154.                   [(number? command)
  155.                    (for ([x (in-range command)]
  156.                          #:unless (stream-empty? st))
  157.                      (println (stream-first st))
  158.                      (set! st (stream-rest st)))
  159.                    (if (stream-empty? st)
  160.                        (displayln "--end--")
  161.                        (print-loop st))]
  162.                   [else
  163.                    (println (stream-first st))
  164.                    (print-loop (stream-rest st))])))))))
  165.   (repl environment))
  166.  
  167. (repl)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement