Last active
December 22, 2015 19:39
-
-
Save fredyr/6521407 to your computer and use it in GitHub Desktop.
Very basic scheme interpreter based on PAIP (http://norvig.com/paip.html)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns interp.core) | |
(defn get-var [var env] (@env var)) | |
(defn set-var! [var val env] | |
(swap! env conj {var val})) | |
(def global-env (atom {})) | |
(defn ext-env [vars vals env] | |
(->> (zipmap vars vals) | |
(conj @env) | |
(atom))) | |
(defn atom? [x] (not (coll? x))) | |
(defn length=1 [lst] (= (count lst) 1)) | |
(defn maybe-add [op exps] | |
(cond | |
(length=1 exps) (first exps) | |
:else (cons op exps))) | |
(defn interp [x env] | |
(cond | |
(symbol? x) (get-var x env) | |
(atom? x) x | |
:else (case (first x) | |
quote (second x) | |
begin (last (map #(interp % env) (next x))) | |
set! (set-var! (second x) (interp (nth x 2) env) env) | |
if (if (interp (second x) env) | |
(interp (nth x 2) env) | |
(interp (nth x 3) env)) | |
lambda (let [parms (second x) | |
code (maybe-add 'begin (nnext x))] | |
(fn [& args] (interp code (ext-env parms args env)))) | |
(apply (interp (first x) env) | |
(map #(interp % env) (next x)))))) | |
;; Usage | |
(set-var! '+ + global-env) | |
(set-var! '- - global-env) | |
(set-var! '* * global-env) | |
(set-var! '= = global-env) | |
(interp | |
'(begin | |
(set! fac | |
(lambda (n) | |
(if (= n 0) | |
1 | |
(* n (fac (- n 1)))))) | |
(fac 20)) global-env) | |
;; Let construct using lambdas | |
(interp | |
'((lambda (x) | |
((lambda (y) | |
(+ x y)) 2)) 1) | |
global-env) | |
;; => 3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment