aboutsummaryrefslogtreecommitdiff
path: root/lc.rkt
blob: cea86c84d345c10dd6dd0d91d576dd92c4795b0a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#lang racket ; note: do NOT use racket/base
(require "lib.rkt")

;; The Untyped Lambda Calculus

; note: default arguments MUST all be at the end
(define (interpret expr [ctx '()])
  (match expr
    [`(λ ,id ,body)
      `(λ ,id ,(interpret body ctx))]
    [`((λ ,id ,body) ,arg)
      (interpret body (dict-set ctx id arg))]
    [`(,id ,arg) #:when (dict-has-key? ctx id)
      (interpret `(,(interpret (dict-ref ctx id) ctx) ,arg))]
    [`(,body ,arg)
      (let ([reduced (interpret body ctx)])
        (if (equal? body reduced)
          `(,reduced ,(interpret arg ctx))
          (interpret `(,reduced ,arg) ctx)))]
    [id #:when (dict-has-key? ctx id)
      (interpret (dict-ref ctx id) ctx)]
    [val #:when (symbol? val) val]
    [_ (err (format "unknown expression ~a" expr))]))

(require rackunit)
(check-equal? (interpret '(λ x x)) '(λ x x))
(check-equal? (interpret '((λ a a) (x y))) '(x y))
(check-equal? (interpret '((λ a (x y)) (λ z z))) '(x y))
(check-equal? (interpret '((λ a (a y)) x)) '(x y))