;;
;; 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
+;;;(try* (throw ["data" "foo"]) (catch* exc (do (prn "exc is:" exc) 7))) ;;;;
+;;;; "exc is:" ["data" "foo"] ;;;;=>7
;;;;=>7
-(try* (throw {"data" "foo"}) (catch* exc (do (prn "err:" exc) 7)))
-; "err:" {"data" "foo"}
+(try* (throw (list "data" "foo")) (catch* exc (do (prn "err:" exc) 7)))
+; "err:" ("data" "foo")
;=>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 [7]) (catch* exc exc))
+;=>7
+
;;
;; Testing builtin functions
;=>9
(apply prn (list 1 2 "3" (list)))
; 1 2 "3" ()
+(apply prn 1 2 (list "3" (list)))
+; 1 2 "3" ()
;=>nil
;=>6
(map double nums)
;=>(2 4 6)
+(map (fn* (x) (symbol? x)) (list 1 (symbol "two") "three"))
+;=>(false true false)
;;
;; Testing read-str and eval
;=>"\"hello\""
;;
-;; -------- Optional Functionality --------
+;; ------- 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
;; Testing sequential? function
(sequential? "abc")
;=>false
+
+;; Testing map function with vectors
+(map (fn* (a) (* 2 a)) [1 2 3])
+;=>(2 4 6)
+
;; Testing vector functions
(vector? [10 11])
(vector 3 4 5)
;=>[3 4 5]
-;; 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]]
-
+(map? {})
+;=>true
+(map? '())
+;=>false
(map? [])
;=>false
+(map? 'abc)
+;=>false
+(map? :abc)
+;=>false
;;
;; Testing hash-maps
(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 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
+
+
;;
-;; Testing metadata
-(meta [1 2 3])
-;=>nil
+;; Testing metadata on functions
+
+;;
+;; Testing metadata on mal functions
(meta (fn* (a) a))
;=>nil
-(with-meta [1 2 3] {"a" 1})
-;=>[1 2 3]
-
-(meta (with-meta [1 2 3] {"a" 1}))
-;=>{"a" 1}
+(meta (with-meta (fn* (a) a) {"b" 1}))
+;=>{"b" 1}
-(meta (with-meta [1 2 3] "abc"))
+(meta (with-meta (fn* (a) a) "abc"))
;=>"abc"
-(meta (with-meta (list 1 2 3) {"a" 1}))
-;=>{"a" 1}
-
-(meta (with-meta {"abc" 123} {"a" 1}))
-;=>{"a" 1}
-
-;;; 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]
+(def! l-wm (with-meta (fn* (a) a) {"b" 2}))
(meta l-wm)
;=>{"b" 2}
(meta l-wm)
;=>{"b" 2}
-;; Testing metadata on functions
(def! f-wm (with-meta (fn* [a] (+ 1 a)) {"abc" 1}))
(meta f-wm)
;=>{"abc" 1}
(meta f-wm)
;=>{"abc" 1}
-
(def! f-wm2 ^{"abc" 1} (fn* [a] (+ 1 a)))
(meta f-wm2)
;=>{"abc" 1}
-;; Testing metadata on builtin functions
-(meta +)
-;=>nil
-(def! f-wm3 ^{"def" 2} +)
-(meta f-wm3)
-;=>{"def" 2}
-(meta +)
-;=>nil
-
;;
;; Make sure closures and metadata co-exist
(def! gen-plusX (fn* (x) (with-meta (fn* (b) (+ x b)) {"meta" 1})))
(f)
;=>9
+
+;;
+;; ------- 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}
+
+(meta (with-meta [1 2 3] "abc"))
+;=>"abc"
+
+(meta (with-meta (list 1 2 3) {"a" 1}))
+;=>{"a" 1}
+
+(meta (with-meta {"abc" 123} {"a" 1}))
+;=>{"a" 1}
+
+;;; 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
+