From 0f0c8ea72807dfcde3101f857e703f0ddd1c838a Mon Sep 17 00:00:00 2001 From: rhysd Date: Sat, 13 Jun 2015 22:15:42 +0900 Subject: [PATCH] import mal's tests from mal repository --- spec/crisp/mal_specs/tests/inc.mal | 4 + spec/crisp/mal_specs/tests/incA.mal | 3 + spec/crisp/mal_specs/tests/incB.mal | 10 + spec/crisp/mal_specs/tests/incC.mal | 6 + spec/crisp/mal_specs/tests/perf1.mal | 11 + spec/crisp/mal_specs/tests/perf2.mal | 13 + spec/crisp/mal_specs/tests/perf3.mal | 28 ++ spec/crisp/mal_specs/tests/step0_repl.mal | 14 + .../mal_specs/tests/step1_read_print.mal | 136 ++++++ spec/crisp/mal_specs/tests/step2_eval.mal | 31 ++ spec/crisp/mal_specs/tests/step3_env.mal | 56 +++ spec/crisp/mal_specs/tests/step4_if_fn_do.mal | 388 ++++++++++++++++++ spec/crisp/mal_specs/tests/step5_tco.mal | 30 ++ spec/crisp/mal_specs/tests/step6_file.mal | 72 ++++ spec/crisp/mal_specs/tests/step7_quote.mal | 126 ++++++ spec/crisp/mal_specs/tests/step8_macros.mal | 164 ++++++++ spec/crisp/mal_specs/tests/step9_try.mal | 264 ++++++++++++ spec/crisp/mal_specs/tests/stepA_mal.mal | 225 ++++++++++ spec/crisp/mal_specs/tests/test.txt | 1 + 19 files changed, 1582 insertions(+) create mode 100644 spec/crisp/mal_specs/tests/inc.mal create mode 100644 spec/crisp/mal_specs/tests/incA.mal create mode 100644 spec/crisp/mal_specs/tests/incB.mal create mode 100644 spec/crisp/mal_specs/tests/incC.mal create mode 100644 spec/crisp/mal_specs/tests/perf1.mal create mode 100644 spec/crisp/mal_specs/tests/perf2.mal create mode 100644 spec/crisp/mal_specs/tests/perf3.mal create mode 100644 spec/crisp/mal_specs/tests/step0_repl.mal create mode 100644 spec/crisp/mal_specs/tests/step1_read_print.mal create mode 100644 spec/crisp/mal_specs/tests/step2_eval.mal create mode 100644 spec/crisp/mal_specs/tests/step3_env.mal create mode 100644 spec/crisp/mal_specs/tests/step4_if_fn_do.mal create mode 100644 spec/crisp/mal_specs/tests/step5_tco.mal create mode 100644 spec/crisp/mal_specs/tests/step6_file.mal create mode 100644 spec/crisp/mal_specs/tests/step7_quote.mal create mode 100644 spec/crisp/mal_specs/tests/step8_macros.mal create mode 100644 spec/crisp/mal_specs/tests/step9_try.mal create mode 100644 spec/crisp/mal_specs/tests/stepA_mal.mal create mode 100644 spec/crisp/mal_specs/tests/test.txt diff --git a/spec/crisp/mal_specs/tests/inc.mal b/spec/crisp/mal_specs/tests/inc.mal new file mode 100644 index 0000000..39ebc55 --- /dev/null +++ b/spec/crisp/mal_specs/tests/inc.mal @@ -0,0 +1,4 @@ +(def! inc1 (fn* (a) (+ 1 a))) +(def! inc2 (fn* (a) (+ 2 a))) +(def! inc3 (fn* (a) + (+ 3 a))) diff --git a/spec/crisp/mal_specs/tests/incA.mal b/spec/crisp/mal_specs/tests/incA.mal new file mode 100644 index 0000000..cbbea79 --- /dev/null +++ b/spec/crisp/mal_specs/tests/incA.mal @@ -0,0 +1,3 @@ +(def! inc4 (fn* (a) (+ 4 a))) + +(prn (inc4 5)) diff --git a/spec/crisp/mal_specs/tests/incB.mal b/spec/crisp/mal_specs/tests/incB.mal new file mode 100644 index 0000000..519bdf4 --- /dev/null +++ b/spec/crisp/mal_specs/tests/incB.mal @@ -0,0 +1,10 @@ +;; A comment in a file +(def! inc4 (fn* (a) (+ 4 a))) +(def! inc5 (fn* (a) ;; a comment after code + (+ 5 a))) + +(prn "incB.mal finished") +"incB.mal return string" + +;; ending comment + diff --git a/spec/crisp/mal_specs/tests/incC.mal b/spec/crisp/mal_specs/tests/incC.mal new file mode 100644 index 0000000..e6f5041 --- /dev/null +++ b/spec/crisp/mal_specs/tests/incC.mal @@ -0,0 +1,6 @@ +(def! mymap {"a" + 1}) + +(prn "incC.mal finished") +"incC.mal return string" + diff --git a/spec/crisp/mal_specs/tests/perf1.mal b/spec/crisp/mal_specs/tests/perf1.mal new file mode 100644 index 0000000..73488f8 --- /dev/null +++ b/spec/crisp/mal_specs/tests/perf1.mal @@ -0,0 +1,11 @@ +(load-file "../core.mal") +(load-file "../perf.mal") + +;;(prn "Start: basic macros performance test") + +(time (do + (or false nil false nil false nil false nil false nil 4) + (cond false 1 nil 2 false 3 nil 4 false 5 nil 6 "else" 7) + (-> (list 1 2 3 4 5 6 7 8 9) rest rest rest rest rest rest first))) + +;;(prn "Done: basic macros performance test") diff --git a/spec/crisp/mal_specs/tests/perf2.mal b/spec/crisp/mal_specs/tests/perf2.mal new file mode 100644 index 0000000..c525baf --- /dev/null +++ b/spec/crisp/mal_specs/tests/perf2.mal @@ -0,0 +1,13 @@ +(load-file "../core.mal") +(load-file "../perf.mal") + +;;(prn "Start: basic math/recursion test") + +(def! sumdown (fn* (N) (if (> N 0) (+ N (sumdown (- N 1))) 0))) +(def! fib (fn* (N) (if (= N 0) 1 (if (= N 1) 1 (+ (fib (- N 1)) (fib (- N 2))))))) + +(time (do + (sumdown 10) + (fib 12))) + +;;(prn "Done: basic math/recursion test") diff --git a/spec/crisp/mal_specs/tests/perf3.mal b/spec/crisp/mal_specs/tests/perf3.mal new file mode 100644 index 0000000..be66239 --- /dev/null +++ b/spec/crisp/mal_specs/tests/perf3.mal @@ -0,0 +1,28 @@ +(load-file "../core.mal") +(load-file "../perf.mal") + +;;(prn "Start: basic macros/atom test") + +(def! atm (atom (list 0 1 2 3 4 5 6 7 8 9))) + +(println "iters/s:" + (run-fn-for + (fn* [] + (do + (or false nil false nil false nil false nil false nil (first @atm)) + (cond false 1 nil 2 false 3 nil 4 false 5 nil 6 "else" (first @atm)) + (-> (deref atm) rest rest rest rest rest rest first) + (swap! atm (fn* [a] (concat (rest a) (list (first a))))))) + 10)) + +;;(def! sumdown (fn* (N) (if (> N 0) (+ N (sumdown (- N 1))) 0))) +;;(def! fib (fn* (N) (if (= N 0) 1 (if (= N 1) 1 (+ (fib (- N 1)) (fib (- N 2))))))) +;; +;;(println "iters/s:" +;; (run-fn-for +;; (fn* [] +;; (do +;; (sumdown 10) +;; (fib 12))) +;; 3)) +;;(prn "Done: basic macros/atom test") diff --git a/spec/crisp/mal_specs/tests/step0_repl.mal b/spec/crisp/mal_specs/tests/step0_repl.mal new file mode 100644 index 0000000..70e2b7b --- /dev/null +++ b/spec/crisp/mal_specs/tests/step0_repl.mal @@ -0,0 +1,14 @@ +hello world +;=>hello world + +abcABC123 +;=>abcABC123 + +;:() []{}"'* +;=>;:() []{}"'* + + +;;; Test long line +hello world abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 (;:() []{}"'* ;:() []{}"'* ;:() []{}"'*) +;=>hello world abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 (;:() []{}"'* ;:() []{}"'* ;:() []{}"'*) + diff --git a/spec/crisp/mal_specs/tests/step1_read_print.mal b/spec/crisp/mal_specs/tests/step1_read_print.mal new file mode 100644 index 0000000..985b5fb --- /dev/null +++ b/spec/crisp/mal_specs/tests/step1_read_print.mal @@ -0,0 +1,136 @@ +;; Testing read of nil/true/false +nil +;=>nil +true +;=>true +false +;=>false + + +;; Testing read of numbers +1 +;=>1 +7 +;=>7 + 7 +;=>7 + + +;; Testing read of symbols ++ +;=>+ +abc +;=>abc + abc +;=>abc +abc5 +;=>abc5 +abc-def +;=>abc-def + + +;; Testing read of strings +"abc" +;=>"abc" + "abc" +;=>"abc" +"abc (with parens)" +;=>"abc (with parens)" +"abc\"def" +;=>"abc\"def" +;;;"abc\ndef" +;;;;=>"abc\ndef" +"" +;=>"" + + +;; Testing read of lists +(+ 1 2) +;=>(+ 1 2) +((3 4)) +;=>((3 4)) +(+ 1 (+ 2 3)) +;=>(+ 1 (+ 2 3)) + ( + 1 (+ 2 3 ) ) +;=>(+ 1 (+ 2 3)) +(* 1 2) +;=>(* 1 2) +(** 1 2) +;=>(** 1 2) + +;; Test commas as whitespace +(1 2, 3,,,,),, +;=>(1 2 3) + +;; Testing read of quoting +'1 +;=>(quote 1) +'(1 2 3) +;=>(quote (1 2 3)) +`1 +;=>(quasiquote 1) +`(1 2 3) +;=>(quasiquote (1 2 3)) +~1 +;=>(unquote 1) +~(1 2 3) +;=>(unquote (1 2 3)) +~@(1 2 3) +;=>(splice-unquote (1 2 3)) + +;; +;; Testing reader errors +;;; TODO: fix these so they fail correctly +(1 2 +; expected ')', got EOF +[1 2 +; expected ']', got EOF +"abc +; expected '"', got EOF + +;; +;; -------- Optional Functionality -------- + +;; Testing keywords +:kw +;=>:kw +(:kw1 :kw2 :kw3) +;=>(:kw1 :kw2 :kw3) + +;; Testing read of vectors +[+ 1 2] +;=>[+ 1 2] +[[3 4]] +;=>[[3 4]] +[+ 1 [+ 2 3]] +;=>[+ 1 [+ 2 3]] + [ + 1 [+ 2 3 ] ] +;=>[+ 1 [+ 2 3]] + +;; Testing read of hash maps +{"abc" 1} +;=>{"abc" 1} +{"a" {"b" 2}} +;=>{"a" {"b" 2}} +{"a" {"b" {"c" 3}}} +;=>{"a" {"b" {"c" 3}}} +{ "a" {"b" { "cde" 3 } }} +;=>{"a" {"b" {"cde" 3}}} +{ :a {:b { :cde 3 } }} +;=>{:a {:b {:cde 3}}} + +;; Testing read of comments + ;; whole line comment (not an exception) +1 ; comment after expression +;=>1 +1; comment after expression +;=>1 + +;; Testing read of ^/metadata +^{"a" 1} [1 2 3] +;=>(with-meta [1 2 3] {"a" 1}) + + +;; Testing read of @/deref +@a +;=>(deref a) diff --git a/spec/crisp/mal_specs/tests/step2_eval.mal b/spec/crisp/mal_specs/tests/step2_eval.mal new file mode 100644 index 0000000..e975910 --- /dev/null +++ b/spec/crisp/mal_specs/tests/step2_eval.mal @@ -0,0 +1,31 @@ +;; Testing evaluation of arithmetic operations +(+ 1 2) +;=>3 + +(+ 5 (* 2 3)) +;=>11 + +(- (+ 5 (* 2 3)) 3) +;=>8 + +(/ (- (+ 5 (* 2 3)) 3) 4) +;=>2 + +(/ (- (+ 515 (* 222 311)) 302) 27) +;=>2565 + +(abc 1 2 3) +; .*\'abc\' not found.* + +;; +;; -------- Optional Functionality -------- + +;; Testing evaluation within collection literals +[1 2 (+ 1 2)] +;=>[1 2 3] + +{"a" (+ 7 8)} +;=>{"a" 15} + +{:a (+ 7 8)} +;=>{:a 15} diff --git a/spec/crisp/mal_specs/tests/step3_env.mal b/spec/crisp/mal_specs/tests/step3_env.mal new file mode 100644 index 0000000..4ca9124 --- /dev/null +++ b/spec/crisp/mal_specs/tests/step3_env.mal @@ -0,0 +1,56 @@ +;; Testing REPL_ENV +(+ 1 2) +;=>3 +(/ (- (+ 5 (* 2 3)) 3) 4) +;=>2 + + +;; Testing def! +(def! x 3) +;=>3 +x +;=>3 +(def! x 4) +;=>4 +x +;=>4 +(def! y (+ 1 7)) +;=>8 +y +;=>8 + + +;; Testing let* +(let* (z 9) z) +;=>9 +(let* (x 9) x) +;=>9 +x +;=>4 +(let* (z (+ 2 3)) (+ 1 z)) +;=>6 +(let* (p (+ 2 3) q (+ 2 p)) (+ p q)) +;=>12 + +;; Testing outer environment +(def! a 4) +;=>4 +(let* (q 9) q) +;=>9 +(let* (q 9) a) +;=>4 +(let* (z 2) (let* (q 9) a)) +;=>4 + +;; +;; -------- Optional Functionality -------- + +;; Testing let* with vector bindings +(let* [z 9] z) +;=>9 +(let* [p (+ 2 3) q (+ 2 p)] (+ p q)) +;=>12 + +;; Testing vector evaluation +(let* (a 5 b 6) [3 4 a [b 7] 8]) +;=>[3 4 5 [6 7] 8] diff --git a/spec/crisp/mal_specs/tests/step4_if_fn_do.mal b/spec/crisp/mal_specs/tests/step4_if_fn_do.mal new file mode 100644 index 0000000..34966f5 --- /dev/null +++ b/spec/crisp/mal_specs/tests/step4_if_fn_do.mal @@ -0,0 +1,388 @@ +;; ----------------------------------------------------- + + +;; Testing list functions +(list) +;=>() +(list? (list)) +;=>true +(empty? (list)) +;=>true +(empty? (list 1)) +;=>false +(list 1 2 3) +;=>(1 2 3) +(count (list 1 2 3)) +;=>3 +(count (list)) +;=>0 +(count nil) +;=>0 +(if (> (count (list 1 2 3)) 3) "yes" "no") +;=>"no" +(if (>= (count (list 1 2 3)) 3) "yes" "no") +;=>"yes" + + +;; Testing if form +(if true 7 8) +;=>7 +(if false 7 8) +;=>8 +(if true (+ 1 7) (+ 1 8)) +;=>8 +(if false (+ 1 7) (+ 1 8)) +;=>9 +(if nil 7 8) +;=>8 +(if 0 7 8) +;=>7 +(if "" 7 8) +;=>7 +(if (list) 7 8) +;=>7 +(if (list 1 2 3) 7 8) +;=>7 +(= (list) nil) +;=>false + + +;; Testing 1-way if form +(if false (+ 1 7)) +;=>nil +(if nil 8 7) +;=>7 +(if true (+ 1 7)) +;=>8 + + +;; Testing basic conditionals +(= 2 1) +;=>false +(= 1 1) +;=>true +(= 1 2) +;=>false +(= 1 (+ 1 1)) +;=>false +(= 2 (+ 1 1)) +;=>true +(= nil 1) +;=>false +(= nil nil) +;=>true + +(> 2 1) +;=>true +(> 1 1) +;=>false +(> 1 2) +;=>false + +(>= 2 1) +;=>true +(>= 1 1) +;=>true +(>= 1 2) +;=>false + +(< 2 1) +;=>false +(< 1 1) +;=>false +(< 1 2) +;=>true + +(<= 2 1) +;=>false +(<= 1 1) +;=>true +(<= 1 2) +;=>true + + +;; Testing equality +(= 1 1) +;=>true +(= 0 0) +;=>true +(= 1 0) +;=>false +(= "" "") +;=>true +(= "abc" "") +;=>false +(= "" "abc") +;=>false +(= "abc" "def") +;=>false + +(= (list) (list)) +;=>true +(= (list 1 2) (list 1 2)) +;=>true +(= (list 1) (list)) +;=>false +(= (list) (list 1)) +;=>false +(= 0 (list)) +;=>false +(= (list) 0) +;=>false +(= (list) "") +;=>false +(= "" (list)) +;=>false + + +;; Testing builtin and user defined functions +(+ 1 2) +;=>3 +( (fn* (a b) (+ b a)) 3 4) +;=>7 +( (fn* () 4) ) +;=>4 + +( (fn* (f x) (f x)) (fn* (a) (+ 1 a)) 7) +;=>8 + + +;; Testing closures +( ( (fn* (a) (fn* (b) (+ a b))) 5) 7) +;=>12 + +(def! gen-plus5 (fn* () (fn* (b) (+ 5 b)))) +(def! plus5 (gen-plus5)) +(plus5 7) +;=>12 + +(def! gen-plusX (fn* (x) (fn* (b) (+ x b)))) +(def! plus7 (gen-plusX 7)) +(plus7 8) +;=>15 + + +;; Testing variable length arguments + +( (fn* (& more) (count more)) 1 2 3) +;=>3 +( (fn* (& more) (count more)) 1) +;=>1 +( (fn* (& more) (count more)) ) +;=>0 +( (fn* (a & more) (count more)) 1 2 3) +;=>2 +( (fn* (a & more) (count more)) 1) +;=>0 + + +;; Testing language defined not function +(not false) +;=>true +(not true) +;=>false +(not "a") +;=>false +(not 0) +;=>false + + +;; Testing do form +(do (prn "prn output1")) +; "prn output1" +;=>nil +(do (prn "prn output2") 7) +; "prn output2" +;=>7 +(do (prn "prn output1") (prn "prn output2") (+ 1 2)) +; "prn output1" +; "prn output2" +;=>3 + +(do (def! a 6) 7 (+ a 8)) +;=>14 +a +;=>6 + + +;; Testing recursive sumdown function +(def! sumdown (fn* (N) (if (> N 0) (+ N (sumdown (- N 1))) 0))) +(sumdown 1) +;=>1 +(sumdown 2) +;=>3 +(sumdown 6) +;=>21 + + +;; Testing recursive fibonacci function +(def! fib (fn* (N) (if (= N 0) 1 (if (= N 1) 1 (+ (fib (- N 1)) (fib (- N 2))))))) +(fib 1) +;=>1 +(fib 2) +;=>2 +(fib 4) +;=>5 +(fib 10) +;=>89 + +;; ----------------------------------------------------- + +;; Testing string quoting + +"" +;=>"" + +"abc" +;=>"abc" + +"abc def" +;=>"abc def" + +"\"" +;=>"\"" + + +;; Testing pr-str + +(pr-str) +;=>"" + +(pr-str "") +;=>"\"\"" + +(pr-str "abc") +;=>"\"abc\"" + +(pr-str "abc def" "ghi jkl") +;=>"\"abc def\" \"ghi jkl\"" + +(pr-str "\"") +;=>"\"\\\"\"" + +(pr-str (list 1 2 "abc" "\"") "def") +;=>"(1 2 \"abc\" \"\\\"\") \"def\"" + + +;; Testing str + +(str) +;=>"" + +(str "") +;=>"" + +(str "abc") +;=>"abc" + +(str "\"") +;=>"\"" + +(str 1 "abc" 3) +;=>"1abc3" + +(str "abc def" "ghi jkl") +;=>"abc defghi jkl" + +;;; TODO: get this working properly +;;;(str (list 1 2 "abc" "\"") "def") +;;;;=>"(1 2 \"abc\" \"\\\"\")def" + + +;; Testing prn +(prn) +; +;=>nil + +(prn "") +; "" +;=>nil + +(prn "abc") +; "abc" +;=>nil + +(prn "abc def" "ghi jkl") +; "abc def" "ghi jkl" + +(prn "\"") +; "\"" +;=>nil + +(prn (list 1 2 "abc" "\"") "def") +; (1 2 "abc" "\"") "def" +;=>nil + + +;; Testing println +(println) +; +;=>nil + +(println "") +; +;=>nil + +(println "abc") +; abc +;=>nil + +(println "abc def" "ghi jkl") +; abc def ghi jkl + +(println "\"") +; " +;=>nil + +(println (list 1 2 "abc" "\"") "def") +; (1 2 abc ") def +;=>nil + +;; +;; -------- Optional Functionality -------- + +;; Testing keywords +(= :abc :abc) +;=>true +(= :abc :def) +;=>false +(= :abc ":abc") +;=>false + +;; Testing vector truthiness +(if [] 7 8) +;=>7 + +;; Testing vector functions +(count [1 2 3]) +;=>3 +(empty? [1 2 3]) +;=>false +(empty? []) +;=>true +(list? [4 5 6]) +;=>false + +;; Testing vector equality +(= [] (list)) +;=>true +(= (list 1 2) [1 2]) +;=>true +(= (list 1) []) +;=>false +(= [] [1]) +;=>false +(= 0 []) +;=>false +(= [] 0) +;=>false +(= [] "") +;=>false +(= "" []) +;=>false + +;; Testing vector parameter lists +( (fn* [] 4) ) +;=>4 +( (fn* [f x] (f x)) (fn* [a] (+ 1 a)) 7) +;=>8 diff --git a/spec/crisp/mal_specs/tests/step5_tco.mal b/spec/crisp/mal_specs/tests/step5_tco.mal new file mode 100644 index 0000000..e8e327a --- /dev/null +++ b/spec/crisp/mal_specs/tests/step5_tco.mal @@ -0,0 +1,30 @@ +;; Testing recursive tail-call function + +(def! sum2 (fn* (n acc) (if (= n 0) acc (sum2 (- n 1) (+ n acc))))) + +(sum2 10 0) +;=>55 + +(def! res2 nil) +;=>nil +(def! res2 (sum2 10000 0)) +res2 +;=>50005000 + + +;; Test recursive non-tail call function + +(def! sum-to (fn* (n) (if (= n 0) 0 (+ n (sum-to (- n 1)))))) + +(sum-to 10) +;=>55 + +;;; no try* yet, so test completion of side-effects +(def! res1 nil) +;=>nil +;;; For implementations without their own TCO this should fail and +;;; leave res1 unchanged +(def! res1 (sum-to 10000)) +res1 +;=>nil + diff --git a/spec/crisp/mal_specs/tests/step6_file.mal b/spec/crisp/mal_specs/tests/step6_file.mal new file mode 100644 index 0000000..99da170 --- /dev/null +++ b/spec/crisp/mal_specs/tests/step6_file.mal @@ -0,0 +1,72 @@ +;;; TODO: really a step5 test +;; +;; Testing that (do (do)) not broken by TCO +(do (do 1 2)) +;=>2 + +;; +;; Testing read-string, eval and slurp +(read-string "(1 2 (3 4) nil)") +;=>(1 2 (3 4) nil) + +(read-string "(+ 2 3)") +;=>(+ 2 3) + +(read-string "7 ;; comment") +;=>7 + +;;; Differing output, but make sure no fatal error +(read-string ";; comment") + + +(eval (read-string "(+ 2 3)")) +;=>5 + +;;; TODO: fix newline matching so that this works +;;;(slurp "../tests/test.txt") +;;;;=>"A line of text\n" + + +;; Testing load-file + +(load-file "../tests/inc.mal") +(inc1 7) +;=>8 +(inc2 7) +;=>9 +(inc3 9) +;=>12 + +;; +;; Testing that *ARGV* exists and is an empty list +(list? *ARGV*) +;=>true +*ARGV* +;=>() + +;; +;; -------- Optional Functionality -------- + +;; Testing comments in a file +(load-file "../tests/incB.mal") +; "incB.mal finished" +;=>"incB.mal return string" +(inc4 7) +;=>11 +(inc5 7) +;=>12 + +;; Testing map literal across multiple lines in a file +(load-file "../tests/incC.mal") +mymap +;=>{"a" 1} + +;;; TODO: really a step5 test +;; Testing that vector params not broken by TCO +(def! g (fn* [] 78)) +(g) +;=>78 +(def! g (fn* [a] (+ a 78))) +(g 3) +;=>81 + diff --git a/spec/crisp/mal_specs/tests/step7_quote.mal b/spec/crisp/mal_specs/tests/step7_quote.mal new file mode 100644 index 0000000..dae6cbd --- /dev/null +++ b/spec/crisp/mal_specs/tests/step7_quote.mal @@ -0,0 +1,126 @@ +;; Testing cons function +(cons 1 (list)) +;=>(1) +(cons 1 (list 2)) +;=>(1 2) +(cons 1 (list 2 3)) +;=>(1 2 3) +(cons (list 1) (list 2 3)) +;=>((1) 2 3) + +;; Testing concat function +(concat) +;=>() +(concat (list 1 2)) +;=>(1 2) +(concat (list 1 2) (list 3 4)) +;=>(1 2 3 4) +(concat (list 1 2) (list 3 4) (list 5 6)) +;=>(1 2 3 4 5 6) +(concat (concat)) +;=>() + + +;; Testing regular quote +(quote 7) +;=>7 +'7 +;=>7 +(quote (1 2 3)) +;=>(1 2 3) +'(1 2 3) +;=>(1 2 3) +(quote (1 2 (3 4))) +;=>(1 2 (3 4)) +'(1 2 (3 4)) +;=>(1 2 (3 4)) + + +;; Testing simple quasiquote +(quasiquote 7) +;=>7 +`7 +;=>7 +(quasiquote (1 2 3)) +;=>(1 2 3) +`(1 2 3) +;=>(1 2 3) +(quasiquote (1 2 (3 4))) +;=>(1 2 (3 4)) +`(1 2 (3 4)) +;=>(1 2 (3 4)) + + +;; Testing unquote +`~7 +;=>7 +(def! a 8) +;=>8 +`a +;=>a +`~a +;=>8 +`(1 a 3) +;=>(1 a 3) +`(1 ~a 3) +;=>(1 8 3) +(def! b '(1 "b" "d")) +;=>(1 "b" "d") +`(1 b 3) +;=>(1 b 3) +`(1 ~b 3) +;=>(1 (1 "b" "d") 3) + + +;; Testing splice-unquote +(def! c '(1 "b" "d")) +;=>(1 "b" "d") +`(1 c 3) +;=>(1 c 3) +`(1 ~@c 3) +;=>(1 1 "b" "d" 3) + + +;; Testing symbol equality +(= 'abc 'abc) +;=>true +(= 'abc 'abcd) +;=>false +(= 'abc "abc") +;=>false +(= "abc" 'abc) +;=>false + +;;;;; Test quine +;;; TODO: needs expect line length fix +;;;((fn* [q] (quasiquote ((unquote q) (quote (unquote q))))) (quote (fn* [q] (quasiquote ((unquote q) (quote (unquote q))))))) +;;;=>((fn* [q] (quasiquote ((unquote q) (quote (unquote q))))) (quote (fn* [q] (quasiquote ((unquote q) (quote (unquote q))))))) + +;; +;; -------- Optional Functionality -------- + +;; Testing cons, concat, first, rest with vectors + +(cons [1] [2 3]) +;=>([1] 2 3) +(cons 1 [2 3]) +;=>(1 2 3) +(concat [1 2] (list 3 4) [5 6]) +;=>(1 2 3 4 5 6) + +;; Testing unquote with vectors +(def! a 8) +;=>8 +`[1 a 3] +;=>(1 a 3) +;;; TODO: fix this +;;;;=>[1 a 3] + +;; Testing splice-unquote with vectors +(def! c '(1 "b" "d")) +;=>(1 "b" "d") +`[1 ~@c 3] +;=>(1 1 "b" "d" 3) +;;; TODO: fix this +;;;;=>[1 1 "b" "d" 3] + diff --git a/spec/crisp/mal_specs/tests/step8_macros.mal b/spec/crisp/mal_specs/tests/step8_macros.mal new file mode 100644 index 0000000..a345190 --- /dev/null +++ b/spec/crisp/mal_specs/tests/step8_macros.mal @@ -0,0 +1,164 @@ +;; Testing non-macro function +(not (= 1 1)) +;=>false +;;; This should fail if it is a macro +(not (= 1 2)) +;=>true + + +;; Testing trivial macros +(defmacro! one (fn* () 1)) +(one) +;=>1 +(defmacro! two (fn* () 2)) +(two) +;=>2 + +;; Testing unless macros +(defmacro! unless (fn* (pred a b) `(if ~pred ~b ~a))) +(unless false 7 8) +;=>7 +(unless true 7 8) +;=>8 +(defmacro! unless2 (fn* (pred a b) `(if (not ~pred) ~a ~b))) +(unless2 false 7 8) +;=>7 +(unless2 true 7 8) +;=>8 + +;; Testing macroexpand +(macroexpand (unless2 2 3 4)) +;=>(if (not 2) 3 4) + + +;; Testing nth, first and rest functions + +(nth '(1) 0) +;=>1 +(nth '(1 2) 1) +;=>2 +(def! x "x") +(def! x (nth '(1 2) 2)) +x +;=>"x" + +(first '()) +;=>nil +(first '(6)) +;=>6 +(first '(7 8 9)) +;=>7 + +(rest '()) +;=>() +(rest '(6)) +;=>() +(rest '(7 8 9)) +;=>(8 9) + + +;; Testing or macro +(or) +;=>nil +(or 1) +;=>1 +(or 1 2 3 4) +;=>1 +(or false 2) +;=>2 +(or false nil 3) +;=>3 +(or false nil false false nil 4) +;=>4 +(or false nil 3 false nil 4) +;=>3 +(or (or false 4)) +;=>4 + +;; Testing cond macro + +(cond) +;=>nil +(cond true 7) +;=>7 +(cond true 7 true 8) +;=>7 +(cond false 7 true 8) +;=>8 +(cond false 7 false 8 "else" 9) +;=>9 +(cond false 7 (= 2 2) 8 "else" 9) +;=>8 +(cond false 7 false 8 false 9) +;=>nil + +;; +;; Loading core.mal +(load-file "../core.mal") + +;; Testing and macro +(and) +;=>true +(and 1) +;=>1 +(and 1 2) +;=>2 +(and 1 2 3) +;=>3 +(and 1 2 3 4) +;=>4 +(and 1 2 3 4 false) +;=>false +(and 1 2 3 4 false 5) +;=>false + +;; Testing -> macro + +(-> 7) +;=>7 +(-> (list 7 8 9) first) +;=>7 +(-> (list 7 8 9) (first)) +;=>7 +(-> (list 7 8 9) first (+ 7)) +;=>14 +(-> (list 7 8 9) rest (rest) first (+ 7)) +;=>16 + +;; Testing EVAL in let* + +(let* (x (or nil "yes")) x) +;=>"yes" + +;; +;; -------- Optional Functionality -------- + +;; Testing nth, first, rest with vectors + +(nth [1] 0) +;=>1 +(nth [1 2] 1) +;=>2 +(def! x "x") +(def! x (nth [1 2] 2)) +x +;=>"x" + +(first []) +;=>nil +(first [10]) +;=>10 +(first [10 11 12]) +;=>10 +(rest []) +;=>() +(rest [10]) +;=>() +(rest [10 11 12]) +;=>(11 12) + +;; Testing EVAL in vector let* + +(let* [x (or nil "yes")] x) +;=>"yes" + diff --git a/spec/crisp/mal_specs/tests/step9_try.mal b/spec/crisp/mal_specs/tests/step9_try.mal new file mode 100644 index 0000000..3a61f85 --- /dev/null +++ b/spec/crisp/mal_specs/tests/step9_try.mal @@ -0,0 +1,264 @@ +;; +;; Testing try*/catch* + +(try* 123 (catch* e 456)) +;=>123 + +(try* (abc 1 2) (catch* exc (prn "exc is:" exc))) +; "exc is:" "'abc' not found" +;=>nil + +;;;TODO: fix so long lines don't trigger ANSI escape codes ;;;(try* +;;;(try* (throw ["data" "foo"]) (catch* exc (do (prn "exc is:" exc) 7))) ;;;; +;;;; "exc is:" ["data" "foo"] ;;;;=>7 +;;;;=>7 + +(try* (throw (list 1 2 3)) (catch* exc (do (prn "err:" exc) 7))) +; "err:" (1 2 3) +;=>7 + +(try* (throw "my exception") (catch* exc (do (prn "exc:" exc) 7))) +; "exc:" "my exception" +;=>7 + +;;; Test that throw is a function: +(try* (map throw (list 7)) (catch* exc exc)) +;=>7 + + +;; +;; Testing builtin functions + +(symbol? 'abc) +;=>true +(symbol? "abc") +;=>false + +(nil? nil) +;=>true +(nil? true) +;=>false + +(true? true) +;=>true +(true? false) +;=>false +(true? true?) +;=>false + +(false? false) +;=>true +(false? true) +;=>false + +;; Testing apply function with core functions +(apply + (list 2 3)) +;=>5 +(apply + 4 (list 5)) +;=>9 +(apply prn (list 1 2 "3" (list))) +; 1 2 "3" () +(apply prn 1 2 (list "3" (list))) +; 1 2 "3" () + +;; Testing apply function with user functions +(apply (fn* (a b) (+ a b)) (list 2 3)) +;=>5 +(apply (fn* (a b) (+ a b)) 4 (list 5)) +;=>9 + +;; Testing map function +(def! nums (list 1 2 3)) +(def! double (fn* (a) (* 2 a))) +(double 3) +;=>6 +(map double nums) +;=>(2 4 6) +(map (fn* (x) (symbol? x)) (list 1 (symbol "two") "three")) +;=>(false true false) + +;; +;; ------- Optional Functionality ---------- +;; ------- (Needed for self-hosting) ------- + +;; Testing symbol and keyword functions +(symbol? :abc) +;=>false +(symbol? 'abc) +;=>true +(symbol? "abc") +;=>false +(symbol? (symbol "abc")) +;=>true +(keyword? :abc) +;=>true +(keyword? 'abc) +;=>false +(keyword? "abc") +;=>false +(keyword? (keyword "abc")) +;=>true + +(symbol "abc") +;=>abc +;;;TODO: all implementations should suppport this too +;;;(keyword :abc) +;;;;=>:abc +(keyword "abc") +;=>:abc + +;; Testing sequential? function + +(sequential? (list 1 2 3)) +;=>true +(sequential? [15]) +;=>true +(sequential? sequential?) +;=>false +(sequential? nil) +;=>false +(sequential? "abc") +;=>false + +;; Testing apply function with core functions and arguments in vector +(apply + 4 [5]) +;=>9 +(apply prn 1 2 ["3" 4]) +; 1 2 "3" 4 +;=>nil +;; Testing apply function with user functions and arguments in vector +(apply (fn* (a b) (+ a b)) [2 3]) +;=>5 +(apply (fn* (a b) (+ a b)) 4 [5]) +;=>9 + + +;; Testing map function with vectors +(map (fn* (a) (* 2 a)) [1 2 3]) +;=>(2 4 6) + +;; Testing vector functions + +(vector? [10 11]) +;=>true +(vector? '(12 13)) +;=>false +(vector 3 4 5) +;=>[3 4 5] + +(map? {}) +;=>true +(map? '()) +;=>false +(map? []) +;=>false +(map? 'abc) +;=>false +(map? :abc) +;=>false + +;; +;; Testing hash-maps +(hash-map "a" 1) +;=>{"a" 1} + +{"a" 1} +;=>{"a" 1} + +(assoc {} "a" 1) +;=>{"a" 1} + +(get (assoc (assoc {"a" 1 } "b" 2) "c" 3) "a") +;=>1 + +(def! hm1 (hash-map)) +;=>{} + +(map? hm1) +;=>true +(map? 1) +;=>false +(map? "abc") +;=>false + +(get nil "a") +;=>nil + +(get hm1 "a") +;=>nil + +(contains? hm1 "a") +;=>false + +(def! hm2 (assoc hm1 "a" 1)) +;=>{"a" 1} + +(get hm1 "a") +;=>nil + +(contains? hm1 "a") +;=>false + +(get hm2 "a") +;=>1 + +(contains? hm2 "a") +;=>true + + +;;; TODO: fix. Clojure returns nil but this breaks mal impl +(keys hm1) +;=>() + +(keys hm2) +;=>("a") + +;;; TODO: fix. Clojure returns nil but this breaks mal impl +(vals hm1) +;=>() + +(vals hm2) +;=>(1) + +(count (keys (assoc hm2 "b" 2 "c" 3))) +;=>3 + +(def! hm3 (assoc hm2 "b" 2)) +(count (keys hm3)) +;=>2 +(count (vals hm3)) +;=>2 + +(dissoc hm3 "a") +;=>{"b" 2} + +(dissoc hm3 "a" "b") +;=>{} + +(dissoc hm3 "a" "b" "c") +;=>{} + +(count (keys hm3)) +;=>2 + +;; Testing keywords as hash-map keys +(get {:abc 123} :abc) +;=>123 +(contains? {:abc 123} :abc) +;=>true +(contains? {:abcd 123} :abc) +;=>false +(assoc {} :bcd 234) +;=>{:bcd 234} +(dissoc {:cde 345 :fgh 456} :cde) +;=>{:fgh 456} +(keyword? (nth (keys {:abc 123 :def 456}) 0)) +;=>true +;;; TODO: support : in strings in make impl +;;;(keyword? (nth (keys {":abc" 123 ":def" 456}) 0)) +;;;;=>false +(keyword? (nth (vals {"a" :abc "b" :def}) 0)) +;=>true + + + diff --git a/spec/crisp/mal_specs/tests/stepA_mal.mal b/spec/crisp/mal_specs/tests/stepA_mal.mal new file mode 100644 index 0000000..b42b6e9 --- /dev/null +++ b/spec/crisp/mal_specs/tests/stepA_mal.mal @@ -0,0 +1,225 @@ +;;; +;;; See IMPL/tests/stepA_mal.mal for implementation specific +;;; interop tests. +;;; + + +;; +;; Testing readline +(readline "mal-user> ") +"hello" +;=>"\"hello\"" + +;; +;; Testing *host-language* +;;; each impl is different, but this should return false +;;; rather than throwing an exception +(= "something bogus" *host-language*) +;=>false + + +;; +;; ------- Optional Functionality ---------- +;; ------- (Needed for self-hosting) ------- + +;; +;; Testing metadata on functions + +;; +;; Testing metadata on mal functions + +(meta (fn* (a) a)) +;=>nil + +(meta (with-meta (fn* (a) a) {"b" 1})) +;=>{"b" 1} + +(meta (with-meta (fn* (a) a) "abc")) +;=>"abc" + +(def! l-wm (with-meta (fn* (a) a) {"b" 2})) +(meta l-wm) +;=>{"b" 2} + +(meta (with-meta l-wm {"new_meta" 123})) +;=>{"new_meta" 123} +(meta l-wm) +;=>{"b" 2} + +(def! f-wm (with-meta (fn* [a] (+ 1 a)) {"abc" 1})) +(meta f-wm) +;=>{"abc" 1} + +(meta (with-meta f-wm {"new_meta" 123})) +;=>{"new_meta" 123} +(meta f-wm) +;=>{"abc" 1} + +(def! f-wm2 ^{"abc" 1} (fn* [a] (+ 1 a))) +(meta f-wm2) +;=>{"abc" 1} + +;; Meta of native functions should return nil (not fail) +(meta +) +;=>nil + + +;; +;; Make sure closures and metadata co-exist +(def! gen-plusX (fn* (x) (with-meta (fn* (b) (+ x b)) {"meta" 1}))) +(def! plus7 (gen-plusX 7)) +(def! plus8 (gen-plusX 8)) +(plus7 8) +;=>15 +(meta plus7) +;=>{"meta" 1} +(meta plus8) +;=>{"meta" 1} +(meta (with-meta plus7 {"meta" 2})) +;=>{"meta" 2} +(meta plus8) +;=>{"meta" 1} + + +;; +;; Testing atoms + +(def! inc3 (fn* (a) (+ 3 a))) + +(def! a (atom 2)) +;=>(atom 2) + +;;;(type a) +;;;;=>"atom" + +(deref a) +;=>2 + +@a +;=>2 + +(reset! a 3) +;=>3 + +@a +;=>3 + +(swap! a inc3) +;=>6 + +@a +;=>6 + +(swap! a (fn* (a) a)) +;=>6 + +(swap! a (fn* (a) (* 2 a))) +;=>12 + +(swap! a (fn* (a b) (* a b)) 10) +;=>120 + +(swap! a + 3) +;=>123 + +;; Testing swap!/closure interaction +(def! inc-it (fn* (a) (+ 1 a))) +(def! atm (atom 7)) +(def! f (fn* [] (swap! atm inc-it))) +(f) +;=>8 +(f) +;=>9 + +;; Testing hash-map evaluation and atoms (i.e. an env) +(def! e (atom {"+" +})) +(swap! e assoc "-" -) +( (get @e "+") 7 8) +;=>15 +( (get @e "-") 11 8) +;=>3 + + +;; +;; ------- Optional Functionality -------------- +;; ------- (Not needed for self-hosting) ------- + +;; +;; Testing conj function +(conj (list) 1) +;=>(1) +(conj (list 1) 2) +;=>(2 1) +(conj (list 2 3) 4) +;=>(4 2 3) +(conj (list 2 3) 4 5 6) +;=>(6 5 4 2 3) +(conj (list 1) (list 2 3)) +;=>((2 3) 1) + +(conj [] 1) +;=>[1] +(conj [1] 2) +;=>[1 2] +(conj [2 3] 4) +;=>[2 3 4] +(conj [2 3] 4 5 6) +;=>[2 3 4 5 6] +(conj [1] [2 3]) +;=>[1 [2 3]] + + +;; +;; Testing metadata on collections + +(meta [1 2 3]) +;=>nil + +(with-meta [1 2 3] {"a" 1}) +;=>[1 2 3] + +(meta (with-meta [1 2 3] {"a" 1})) +;=>{"a" 1} + +(vector? (with-meta [1 2 3] {"a" 1})) +;=>true + +(meta (with-meta [1 2 3] "abc")) +;=>"abc" + +(meta (with-meta (list 1 2 3) {"a" 1})) +;=>{"a" 1} + +(list? (with-meta (list 1 2 3) {"a" 1})) +;=>true + +(meta (with-meta {"abc" 123} {"a" 1})) +;=>{"a" 1} + +(map? (with-meta {"abc" 123} {"a" 1})) +;=>true + +;;; Not actually supported by Clojure +;;;(meta (with-meta (atom 7) {"a" 1})) +;;;;=>{"a" 1} + +(def! l-wm (with-meta [4 5 6] {"b" 2})) +;=>[4 5 6] +(meta l-wm) +;=>{"b" 2} + +(meta (with-meta l-wm {"new_meta" 123})) +;=>{"new_meta" 123} +(meta l-wm) +;=>{"b" 2} + +;; +;; Testing metadata on builtin functions +(meta +) +;=>nil +(def! f-wm3 ^{"def" 2} +) +(meta f-wm3) +;=>{"def" 2} +(meta +) +;=>nil + diff --git a/spec/crisp/mal_specs/tests/test.txt b/spec/crisp/mal_specs/tests/test.txt new file mode 100644 index 0000000..0f24bc0 --- /dev/null +++ b/spec/crisp/mal_specs/tests/test.txt @@ -0,0 +1 @@ +A line of text