diff options
Diffstat (limited to 'clojure/src/lccl/lc/evaluator.clj')
| -rw-r--r-- | clojure/src/lccl/lc/evaluator.clj | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/clojure/src/lccl/lc/evaluator.clj b/clojure/src/lccl/lc/evaluator.clj new file mode 100644 index 0000000..70e972e --- /dev/null +++ b/clojure/src/lccl/lc/evaluator.clj @@ -0,0 +1,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)))) |
