From 90f618cbe7ac7740accf501a75be6972bd95be1a Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Sat, 28 Feb 2015 11:09:54 -0600 Subject: All: rename stepA_interop to stepA_mal Also, add missed postscript interop tests. --- clojure/Makefile | 2 +- clojure/src/stepA_interop.clj | 181 ---------------------------------------- clojure/src/stepA_mal.clj | 181 ++++++++++++++++++++++++++++++++++++++++ clojure/tests/stepA_interop.mal | 17 ---- clojure/tests/stepA_mal.mal | 17 ++++ 5 files changed, 199 insertions(+), 199 deletions(-) delete mode 100644 clojure/src/stepA_interop.clj create mode 100644 clojure/src/stepA_mal.clj delete mode 100644 clojure/tests/stepA_interop.mal create mode 100644 clojure/tests/stepA_mal.mal (limited to 'clojure') diff --git a/clojure/Makefile b/clojure/Makefile index 6d227a2..ec55ac1 100644 --- a/clojure/Makefile +++ b/clojure/Makefile @@ -1,5 +1,5 @@ SOURCES_BASE = src/readline.clj src/reader.clj src/printer.clj -SOURCES_LISP = src/env.clj src/core.clj src/stepA_interop.clj +SOURCES_LISP = src/env.clj src/core.clj src/stepA_mal.clj SOURCES = $(SOURCES_BASE) $(SOURCES_LISP) all: diff --git a/clojure/src/stepA_interop.clj b/clojure/src/stepA_interop.clj deleted file mode 100644 index 6ed9964..0000000 --- a/clojure/src/stepA_interop.clj +++ /dev/null @@ -1,181 +0,0 @@ -(ns stepA-interop - (:refer-clojure :exclude [macroexpand]) - (:require [clojure.repl] - [readline] - [reader] - [printer] - [env] - [core])) - -;; read -(defn READ [& [strng]] - (let [line (if strng strng (read-line))] - (reader/read-string strng))) - -;; eval -(declare EVAL) -(defn is-pair [x] - (and (sequential? x) (> (count x) 0))) - -(defn quasiquote [ast] - (cond - (not (is-pair ast)) - (list 'quote ast) - - (= 'unquote (first ast)) - (second ast) - - (and (is-pair (first ast)) (= 'splice-unquote (ffirst ast))) - (list 'concat (-> ast first second) (quasiquote (rest ast))) - - :else - (list 'cons (quasiquote (first ast)) (quasiquote (rest ast))))) - -(defn is-macro-call [ast env] - (and (seq? ast) - (symbol? (first ast)) - (env/env-find env (first ast)) - (:ismacro (meta (env/env-get env (first ast)))))) - -(defn macroexpand [ast env] - (loop [ast ast] - (if (is-macro-call ast env) - (let [mac (env/env-get env (first ast))] - (recur (apply mac (rest ast)))) - ast))) - -(defn eval-ast [ast env] - (cond - (symbol? ast) (env/env-get env ast) - - (seq? ast) (doall (map #(EVAL % env) ast)) - - (vector? ast) (vec (doall (map #(EVAL % env) ast))) - - (map? ast) (apply hash-map (doall (map #(EVAL % env) - (mapcat identity ast)))) - - :else ast)) - -(defn EVAL [ast env] - (loop [ast ast - env env] - ;;(prn "EVAL" ast (keys @env)) (flush) - (if (not (seq? ast)) - (eval-ast ast env) - - ;; apply list - (let [ast (macroexpand ast env)] - (if (not (seq? ast)) - ast - - (let [[a0 a1 a2 a3] ast] - (condp = a0 - 'def! - (env/env-set env a1 (EVAL a2 env)) - - 'let* - (let [let-env (env/env env)] - (doseq [[b e] (partition 2 a1)] - (env/env-set let-env b (EVAL e let-env))) - (recur a2 let-env)) - - 'quote - a1 - - 'quasiquote - (recur (quasiquote a1) env) - - 'defmacro! - (let [func (with-meta (EVAL a2 env) - {:ismacro true})] - (env/env-set env a1 func)) - - 'macroexpand - (macroexpand a1 env) - - 'clj* - (eval (reader/read-string a1)) - - 'try* - (if (= 'catch* (nth a2 0)) - (try - (EVAL a1 env) - (catch clojure.lang.ExceptionInfo ei - (EVAL (nth a2 2) (env/env env - [(nth a2 1)] - [(:data (ex-data ei))]))) - (catch Throwable t - (EVAL (nth a2 2) (env/env env - [(nth a2 1)] - [(.getMessage t)])))) - (EVAL a1 env)) - - 'do - (do (eval-ast (->> ast (drop-last) (drop 1)) env) - (recur (last ast) env)) - - 'if - (let [cond (EVAL a1 env)] - (if (or (= cond nil) (= cond false)) - (if (> (count ast) 2) - (recur a3 env) - nil) - (recur a2 env))) - - 'fn* - (with-meta - (fn [& args] - (EVAL a2 (env/env env a1 args))) - {:expression a2 - :environment env - :parameters a1}) - - ;; apply - (let [el (eval-ast ast env) - f (first el) - args (rest el) - {:keys [expression environment parameters]} (meta f)] - (if expression - (recur expression (env/env environment parameters args)) - (apply f args)))))))))) - -;; print -(defn PRINT [exp] (pr-str exp)) - -;; repl -(def repl-env (env/env)) -(defn rep - [strng] - (PRINT (EVAL (READ strng) repl-env))) - -;; core.clj: defined using Clojure -(doseq [[k v] core/core_ns] (env/env-set repl-env k v)) -(env/env-set repl-env 'eval (fn [ast] (EVAL ast repl-env))) -(env/env-set repl-env '*ARGV* ()) - -;; core.mal: defined using the language itself -(rep "(def! *host-language* \"clojure\")") -(rep "(def! not (fn* [a] (if a false true)))") -(rep "(def! load-file (fn* [f] (eval (read-string (str \"(do \" (slurp f) \")\")))))") -(rep "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))") -(rep "(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))") - -;; repl loop -(defn repl-loop [] - (let [line (readline/readline "user> ")] - (when line - (when-not (re-seq #"^\s*$|^\s*;.*$" line) ; blank/comment - (try - (println (rep line)) - (catch Throwable e - (clojure.repl/pst e)))) - (recur)))) - -(defn -main [& args] - (env/env-set repl-env '*ARGV* (rest args)) - (if args - (rep (str "(load-file \"" (first args) "\")")) - (do - (rep "(println (str \"Mal [\" *host-language* \"]\"))") - (repl-loop)))) diff --git a/clojure/src/stepA_mal.clj b/clojure/src/stepA_mal.clj new file mode 100644 index 0000000..6ed9964 --- /dev/null +++ b/clojure/src/stepA_mal.clj @@ -0,0 +1,181 @@ +(ns stepA-interop + (:refer-clojure :exclude [macroexpand]) + (:require [clojure.repl] + [readline] + [reader] + [printer] + [env] + [core])) + +;; read +(defn READ [& [strng]] + (let [line (if strng strng (read-line))] + (reader/read-string strng))) + +;; eval +(declare EVAL) +(defn is-pair [x] + (and (sequential? x) (> (count x) 0))) + +(defn quasiquote [ast] + (cond + (not (is-pair ast)) + (list 'quote ast) + + (= 'unquote (first ast)) + (second ast) + + (and (is-pair (first ast)) (= 'splice-unquote (ffirst ast))) + (list 'concat (-> ast first second) (quasiquote (rest ast))) + + :else + (list 'cons (quasiquote (first ast)) (quasiquote (rest ast))))) + +(defn is-macro-call [ast env] + (and (seq? ast) + (symbol? (first ast)) + (env/env-find env (first ast)) + (:ismacro (meta (env/env-get env (first ast)))))) + +(defn macroexpand [ast env] + (loop [ast ast] + (if (is-macro-call ast env) + (let [mac (env/env-get env (first ast))] + (recur (apply mac (rest ast)))) + ast))) + +(defn eval-ast [ast env] + (cond + (symbol? ast) (env/env-get env ast) + + (seq? ast) (doall (map #(EVAL % env) ast)) + + (vector? ast) (vec (doall (map #(EVAL % env) ast))) + + (map? ast) (apply hash-map (doall (map #(EVAL % env) + (mapcat identity ast)))) + + :else ast)) + +(defn EVAL [ast env] + (loop [ast ast + env env] + ;;(prn "EVAL" ast (keys @env)) (flush) + (if (not (seq? ast)) + (eval-ast ast env) + + ;; apply list + (let [ast (macroexpand ast env)] + (if (not (seq? ast)) + ast + + (let [[a0 a1 a2 a3] ast] + (condp = a0 + 'def! + (env/env-set env a1 (EVAL a2 env)) + + 'let* + (let [let-env (env/env env)] + (doseq [[b e] (partition 2 a1)] + (env/env-set let-env b (EVAL e let-env))) + (recur a2 let-env)) + + 'quote + a1 + + 'quasiquote + (recur (quasiquote a1) env) + + 'defmacro! + (let [func (with-meta (EVAL a2 env) + {:ismacro true})] + (env/env-set env a1 func)) + + 'macroexpand + (macroexpand a1 env) + + 'clj* + (eval (reader/read-string a1)) + + 'try* + (if (= 'catch* (nth a2 0)) + (try + (EVAL a1 env) + (catch clojure.lang.ExceptionInfo ei + (EVAL (nth a2 2) (env/env env + [(nth a2 1)] + [(:data (ex-data ei))]))) + (catch Throwable t + (EVAL (nth a2 2) (env/env env + [(nth a2 1)] + [(.getMessage t)])))) + (EVAL a1 env)) + + 'do + (do (eval-ast (->> ast (drop-last) (drop 1)) env) + (recur (last ast) env)) + + 'if + (let [cond (EVAL a1 env)] + (if (or (= cond nil) (= cond false)) + (if (> (count ast) 2) + (recur a3 env) + nil) + (recur a2 env))) + + 'fn* + (with-meta + (fn [& args] + (EVAL a2 (env/env env a1 args))) + {:expression a2 + :environment env + :parameters a1}) + + ;; apply + (let [el (eval-ast ast env) + f (first el) + args (rest el) + {:keys [expression environment parameters]} (meta f)] + (if expression + (recur expression (env/env environment parameters args)) + (apply f args)))))))))) + +;; print +(defn PRINT [exp] (pr-str exp)) + +;; repl +(def repl-env (env/env)) +(defn rep + [strng] + (PRINT (EVAL (READ strng) repl-env))) + +;; core.clj: defined using Clojure +(doseq [[k v] core/core_ns] (env/env-set repl-env k v)) +(env/env-set repl-env 'eval (fn [ast] (EVAL ast repl-env))) +(env/env-set repl-env '*ARGV* ()) + +;; core.mal: defined using the language itself +(rep "(def! *host-language* \"clojure\")") +(rep "(def! not (fn* [a] (if a false true)))") +(rep "(def! load-file (fn* [f] (eval (read-string (str \"(do \" (slurp f) \")\")))))") +(rep "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))") +(rep "(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))") + +;; repl loop +(defn repl-loop [] + (let [line (readline/readline "user> ")] + (when line + (when-not (re-seq #"^\s*$|^\s*;.*$" line) ; blank/comment + (try + (println (rep line)) + (catch Throwable e + (clojure.repl/pst e)))) + (recur)))) + +(defn -main [& args] + (env/env-set repl-env '*ARGV* (rest args)) + (if args + (rep (str "(load-file \"" (first args) "\")")) + (do + (rep "(println (str \"Mal [\" *host-language* \"]\"))") + (repl-loop)))) diff --git a/clojure/tests/stepA_interop.mal b/clojure/tests/stepA_interop.mal deleted file mode 100644 index b323222..0000000 --- a/clojure/tests/stepA_interop.mal +++ /dev/null @@ -1,17 +0,0 @@ -;; Testing basic clojure interop - -(clj* "7") -;=>7 - -(clj* "\"abc\"") -;=>"abc" - -(clj* "{\"abc\" 123}") -;=>{"abc" 123} - -(clj* "(prn \"foo\")") -; "foo" -;=>nil - -(clj* "(for [x [1 2 3]] (+ 1 x))") -;=>(2 3 4) diff --git a/clojure/tests/stepA_mal.mal b/clojure/tests/stepA_mal.mal new file mode 100644 index 0000000..b323222 --- /dev/null +++ b/clojure/tests/stepA_mal.mal @@ -0,0 +1,17 @@ +;; Testing basic clojure interop + +(clj* "7") +;=>7 + +(clj* "\"abc\"") +;=>"abc" + +(clj* "{\"abc\" 123}") +;=>{"abc" 123} + +(clj* "(prn \"foo\")") +; "foo" +;=>nil + +(clj* "(for [x [1 2 3]] (+ 1 x))") +;=>(2 3 4) -- cgit v1.2.3