Java style FOR loop in a clojure interpeter ?
- by Kevin
I have a basic interpreter in clojure. Now i need to implement
for (initialisation; finish-test; loop-update) {
statements
}
inside my interpreter. I will attach my interpreter code I got so far. Any help is appreciated.
Interpreter
(declare interpret make-env) ;;
(def do-trace false) ;;
;; simple utilities
(def third ; return third item in a list
(fn [a-list]
(second (rest a-list))))
(def fourth ; return fourth item in a list
(fn [a-list]
(third (rest a-list))))
(def run ; make it easy to test the interpreter
(fn [e]
(println "Processing: " e)
(println "=> " (interpret e (make-env)))))
;; for the environment
(def make-env
(fn []
'()))
(def add-var
(fn [env var val]
(cons (list var val) env)))
(def lookup-var
(fn [env var]
(cond (empty? env) 'error
(= (first (first env)) var) (second (first env))
:else (lookup-var (rest env) var))))
;; -- define numbers
(def is-number?
(fn [expn]
(number? expn)))
(def interpret-number
(fn [expn env]
expn))
;; -- define symbols
(def is-symbol?
(fn [expn]
(symbol? expn)))
(def interpret-symbol
(fn [expn env]
(lookup-var env expn)))
;; -- define boolean
(def is-boolean?
(fn [expn]
(or
(= expn 'true)
(= expn 'false))))
(def interpret-boolean
(fn [expn env]
expn))
;; -- define functions
(def is-function?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= 'lambda (first expn)))))
(def interpret-function
(fn [expn env]
expn))
;; -- define addition
(def is-plus?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '+ (first expn)))))
(def interpret-plus
(fn [expn env]
(+
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define subtraction
(def is-minus?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '- (first expn)))))
(def interpret-minus
(fn [expn env]
(-
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define multiplication
(def is-times?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '* (first expn)))))
(def interpret-times
(fn [expn env]
(*
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define division
(def is-divides?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '/ (first expn)))))
(def interpret-divides
(fn [expn env]
(/
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define equals test
(def is-equals?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '= (first expn)))))
(def interpret-equals
(fn [expn env]
(=
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define greater-than test
(def is-greater-than?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= '> (first expn)))))
(def interpret-greater-than
(fn [expn env]
(>
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define not
(def is-not?
(fn [expn]
(and
(list? expn)
(= 2 (count expn))
(= 'not (first expn)))))
(def interpret-not
(fn [expn env]
(not
(interpret (second expn) env))))
;; -- define or
(def is-or?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= 'or (first expn)))))
(def interpret-or
(fn [expn env]
(or
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define and
(def is-and?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= 'and (first expn)))))
(def interpret-and
(fn [expn env]
(and
(interpret (second expn) env)
(interpret (third expn) env))))
;; -- define with
(def is-with?
(fn [expn]
(and
(list? expn)
(= 3 (count expn))
(= 'with (first expn)))))
(def interpret-with
(fn [expn env]
(interpret (third expn)
(add-var env
(first (second expn))
(interpret (second (second expn)) env)))))
;; -- define if
(def is-if?
(fn [expn]
(and
(list? expn)
(= 4 (count expn))
(= 'if (first expn)))))
(def interpret-if
(fn [expn env]
(cond (interpret (second expn) env) (interpret (third expn) env)
:else (interpret (fourth expn) env))))
;; -- define function-application
(def is-function-application?
(fn [expn env]
(and
(list? expn)
(= 2 (count expn))
(is-function? (interpret (first expn) env)))))
(def interpret-function-application
(fn [expn env]
(let [function (interpret (first expn) env)]
(interpret (third function)
(add-var env
(first (second function))
(interpret (second expn) env))))))
;; the interpreter itself
(def interpret
(fn [expn env]
(cond do-trace (println "Interpret is processing: " expn))
(cond
; basic values
(is-number? expn) (interpret-number expn env)
(is-symbol? expn) (interpret-symbol expn env)
(is-boolean? expn) (interpret-boolean expn env)
(is-function? expn) (interpret-function expn env)
; built-in functions
(is-plus? expn) (interpret-plus expn env)
(is-minus? expn) (interpret-minus expn env)
(is-times? expn) (interpret-times expn env)
(is-divides? expn) (interpret-divides expn env)
(is-equals? expn) (interpret-equals expn env)
(is-greater-than? expn) (interpret-greater-than expn env)
(is-not? expn) (interpret-not expn env)
(is-or? expn) (interpret-or expn env)
(is-and? expn) (interpret-and expn env)
; special syntax
(is-with? expn) (interpret-with expn env)
(is-if? expn) (interpret-if expn env)
; functions
(is-function-application? expn env) (interpret-function-application expn env)
:else 'error)))