From 3169070063b2cb877200117ebb384269d73bcb93 Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Mon, 24 Mar 2014 16:32:24 -0500 Subject: Current state of mal for Clojure West lighting talk. --- tests/inc.mal | 4 + tests/incB.mal | 14 ++ tests/step1_read_print.mal | 112 +++++++++++++++ tests/step2_eval.mal | 19 +++ tests/step3_env.mal | 38 +++++ tests/step4_if_fn_do.mal | 345 +++++++++++++++++++++++++++++++++++++++++++++ tests/step6_file.mal | 17 +++ tests/step7_quote.mal | 69 +++++++++ tests/step8_macros.mal | 94 ++++++++++++ tests/stepA_more.mal | 294 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 1006 insertions(+) create mode 100644 tests/inc.mal create mode 100644 tests/incB.mal create mode 100644 tests/step1_read_print.mal create mode 100644 tests/step2_eval.mal create mode 100644 tests/step3_env.mal create mode 100644 tests/step4_if_fn_do.mal create mode 100644 tests/step6_file.mal create mode 100644 tests/step7_quote.mal create mode 100644 tests/step8_macros.mal create mode 100644 tests/stepA_more.mal (limited to 'tests') diff --git a/tests/inc.mal b/tests/inc.mal new file mode 100644 index 0000000..39ebc55 --- /dev/null +++ b/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/tests/incB.mal b/tests/incB.mal new file mode 100644 index 0000000..ed28734 --- /dev/null +++ b/tests/incB.mal @@ -0,0 +1,14 @@ +;; A comment in a file +(def! inc4 (fn* (a) (+ 4 a))) +(def! inc5 (fn* (a) ;; a comment after code + (+ 5 a))) + +;; Test map split across lines +(def! mymap {"a" + 1}) + +;; Test commas as whitespace +(def! myvec [1 2, 3]) + +(prn "incB.mal finished") +"incB.mal return string" diff --git a/tests/step1_read_print.mal b/tests/step1_read_print.mal new file mode 100644 index 0000000..f0d7a9a --- /dev/null +++ b/tests/step1_read_print.mal @@ -0,0 +1,112 @@ +;; Testing read of comments + ;; whole line comment (not an exception) +1 ; comment after expression +;=>1 +1; comment after expression +;=>1 + + +;; 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)) + + +;; 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}}} + + +;; 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 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/tests/step2_eval.mal b/tests/step2_eval.mal new file mode 100644 index 0000000..33c7b17 --- /dev/null +++ b/tests/step2_eval.mal @@ -0,0 +1,19 @@ +;; Testing evaluation of arithmetic operations +(+ 1 2) +;=>3 + +(+ 5 (* 2 3)) +;=>11 + +(- (+ 5 (* 2 3)) 3) +;=>8 + +(/ (- (+ 5 (* 2 3)) 3) 4) +;=>2 + +;; Testing evaluation within collection literals +[1 2 (+ 1 2)] +;=>[1 2 3] + +{"a" (+ 7 8)} +;=>{"a" 15} diff --git a/tests/step3_env.mal b/tests/step3_env.mal new file mode 100644 index 0000000..448a446 --- /dev/null +++ b/tests/step3_env.mal @@ -0,0 +1,38 @@ +;; 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 vector evaluation +(let* (a 5 b 6) [3 4 a [b 7] 8]) +;=>[3 4 5 [6 7] 8] diff --git a/tests/step4_if_fn_do.mal b/tests/step4_if_fn_do.mal new file mode 100644 index 0000000..a4ce46f --- /dev/null +++ b/tests/step4_if_fn_do.mal @@ -0,0 +1,345 @@ +;; ----------------------------------------------------- + +;; 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 + +;; ----------------------------------------------------- + + +;; 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 +(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 +(if [] 7 8) +;=>7 + + +;; 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 + +(> 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 + +(= [] (list)) +;=>true +(= (list 1 2) [1 2]) +;=>true +(= (list 1) []) +;=>false +(= [] [1]) +;=>false +(= 0 []) +;=>false +(= [] 0) +;=>false +(= [] "") +;=>false +(= "" []) +;=>false + + +;; Testing builtin and user defined functions +(+ 1 2) +;=>3 +( (fn* (a b) (+ b a)) 3 4) +;=>7 +( (fn* () 4) ) +;=>4 + + +;; 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 diff --git a/tests/step6_file.mal b/tests/step6_file.mal new file mode 100644 index 0000000..c6df3eb --- /dev/null +++ b/tests/step6_file.mal @@ -0,0 +1,17 @@ +;; Testing load-file + +(load-file "../tests/inc.mal") +(inc1 7) +;=>8 +(inc2 7) +;=>9 +(inc3 9) +;=>12 + +(load-file "../tests/incB.mal") +; "incB.mal finished" +;=>"incB.mal return string" +(inc4 7) +;=>11 +(inc5 7) +;=>12 diff --git a/tests/step7_quote.mal b/tests/step7_quote.mal new file mode 100644 index 0000000..c41c7e2 --- /dev/null +++ b/tests/step7_quote.mal @@ -0,0 +1,69 @@ +;; 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 diff --git a/tests/step8_macros.mal b/tests/step8_macros.mal new file mode 100644 index 0000000..351e0ca --- /dev/null +++ b/tests/step8_macros.mal @@ -0,0 +1,94 @@ +;; 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) + +;; +;; 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 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 + +;; 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 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 + +;Testing all EVAL of non-default locations +(let* [x (or nil "yes")] x) +;=>"yes" + diff --git a/tests/stepA_more.mal b/tests/stepA_more.mal new file mode 100644 index 0000000..bae226d --- /dev/null +++ b/tests/stepA_more.mal @@ -0,0 +1,294 @@ +;; +;; Testing try*/catch* + +(try* (abc 1 2) (catch* exc (prn exc)))) +; "'abc' not found" +;=>nil + +;;;TODO: fix so long lines don't trigger ANSI escape codes +;;;(try* (throw {"data" "foo"}) (catch* exc (do (prn "exc is:" exc) 7))) +;;;; "exc is:" {"data" "foo"} +;;;;=>7 + +(try* (throw "my exception") (catch* exc (do (prn "exc:" exc) 7))) +; "exc:" "my exception" +;=>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 + +(sequential? (list 1 2 3)) +;=>true +(sequential? [15]) +;=>true +(sequential? sequential?) +;=>false +(sequential? nil) +;=>false +(sequential? "abc") +;=>false + + +;; Testing apply function +(apply + (list 2 3)) +;=>5 +(apply + 4 (list 5)) +;=>9 +(apply prn (list 1 2 "3" (list))) +; 1 2 "3" () +;=>nil + + +;; Testing map function +(def! nums (list 1 2 3)) +(def! double (fn* (a) (* 2 a))) +(double 3) +;=>6 +(map double nums) +;=>(2 4 6) + + +;; 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 [1 2] (list 3 4) [5 6]) +;=>(1 2 3 4 5 6) +(concat (concat)) +;=>() + +;; 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) +(cons [1] [2 3]) +;=>([1] 2 3) +(cons 1 [2 3]) +;=>(1 2 3) + +;; Testing conj function +(conj (list) 1) +;=>(1) +(conj (list 1) 2) +;=>(1 2) +(conj (list 2 3) 4) +;=>(2 3 4) +(conj (list 2 3) 4 5 6) +;=>(2 3 4 5 6) +(conj (list 1) (list 2 3)) +;=>(1 (2 3)) +(conj [1 2] [3 4] ) +;=>(1 2 [3 4]) + +;; Testing first/rest functions +(first '()) +;=>nil +(first '(6)) +;=>6 +(first '(7 8 9)) +;=>7 +(first []) +;=>nil +(first [10]) +;=>10 +(first [10 11 12]) +;=>10 + +(rest '()) +;=>() +(rest '(6)) +;=>() +(rest '(7 8 9)) +;=>(8 9) +(rest []) +;=>() +(rest [10]) +;=>() +(rest [10 11 12]) +;=>(11 12) + + + +;; +;; Testing hash-maps +(hash-map "a" 1) +;=>{"a" 1} + +{"a" 1} +;=>{"a" 1} + +(assoc {} "a" 1) +;=>{"a" 1} + +(def! hm1 (hash-map)) +;=>{} + +(map? hm1) +;=>true +(map? 1) +;=>false +(map? []) +;=>false + +(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 + +(keys hm2) +;=>("a") + +(vals hm2) +;=>(1) + +(def! hm3 (assoc hm2 "b" 2)) +(count (keys hm3)) +;=>2 +(count (vals hm3)) +;=>2 + +(dissoc hm3 "a") +;=>{"b" 2} + +(dissoc hm3 "a" "b") +;=>{} + +(count (keys hm3)) +;=>2 + + +;; +;; Testing metadata +(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} + +(def! lst (with-meta [4 5 6] {"b" 2})) +;=>[4 5 6] + +(def! f-wm (with-meta (fn* [a] (+ 1 a)) {"abc" 1})) +(meta f-wm) +;=>{"abc" 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 + + +;; +;; Testing read-str and eval +(read-string "[1 2 (3 4) nil]") +;=>[1 2 (3 4) nil] + +(eval (read-string "(+ 4 5)")) +;=>9 + +;; +;; Testing readline +(readline "mal-user> ") +"hello" +;=>"\"hello\"" + +;; +;; Testing macros cond and or +(cond 1 2 3 4) +;=>2 +(cond false 2 3 4) +;=>4 +(cond false 2 false 4) +;=>nil + +(or) +;=>nil +(or 1) +;=>1 +(or 1 2) +;=>1 +(or nil 2) +;=>2 -- cgit v1.2.3