aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-03-24 16:32:24 -0500
committerJoel Martin <github@martintribe.org>2014-03-24 16:32:24 -0500
commit3169070063b2cb877200117ebb384269d73bcb93 (patch)
tree23de3db1ea5c37afd21a45b6ed7771f56a08c0c4 /tests
downloadmal-3169070063b2cb877200117ebb384269d73bcb93.tar.gz
mal-3169070063b2cb877200117ebb384269d73bcb93.zip
Current state of mal for Clojure West lighting talk.
Diffstat (limited to 'tests')
-rw-r--r--tests/inc.mal4
-rw-r--r--tests/incB.mal14
-rw-r--r--tests/step1_read_print.mal112
-rw-r--r--tests/step2_eval.mal19
-rw-r--r--tests/step3_env.mal38
-rw-r--r--tests/step4_if_fn_do.mal345
-rw-r--r--tests/step6_file.mal17
-rw-r--r--tests/step7_quote.mal69
-rw-r--r--tests/step8_macros.mal94
-rw-r--r--tests/stepA_more.mal294
10 files changed, 1006 insertions, 0 deletions
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