summaryrefslogtreecommitdiff
path: root/lambda-calcul/clojure/src/lccl/lc/evaluator.clj
blob: 70e972e39c29105dbafe31e1946fd0b17aac83d6 (plain)
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
(ns lccl.lc.evaluator
  (:import [lccl.lc.ast Var Abs App])
  (:require [lccl.lc.ast :refer [->Abs ->App]]))

(declare substitute)

(defmulti evaluate (fn [term] [(type term)]))
(defmethod evaluate [Var] ([term] term))
(defmethod evaluate [Abs] ([term] term))
(defmethod evaluate [App]
  ([term]
   (let [left (-> term :left)]
     (condp = (type left)
       Abs (substitute (:body left) (:arg left) (:right term))
       term))))

(defmulti substitute (fn [body arg val] [(type body)]))
(defmethod substitute [Var]
  ([body arg val]
   (if (= (:name body) arg) val body)))
(defmethod substitute [Abs]
  ([body arg val]
   (if (= (:arg body) arg)
     body
     (->Abs (:arg body) (substitute (:body body) arg val)))))
(defmethod substitute [App]
  ([body arg val]
   (->App (substitute (:left body) arg val) (substitute (:right body) arg val))))