Skip to content

Instantly share code, notes, and snippets.

@fredyr
Last active December 22, 2015 19:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fredyr/6521407 to your computer and use it in GitHub Desktop.
Save fredyr/6521407 to your computer and use it in GitHub Desktop.
Very basic scheme interpreter based on PAIP (http://norvig.com/paip.html)
(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