@ -0,0 +1,4 @@ | |||
(def! inc1 (fn* (a) (+ 1 a))) | |||
(def! inc2 (fn* (a) (+ 2 a))) | |||
(def! inc3 (fn* (a) | |||
(+ 3 a))) |
@ -0,0 +1,3 @@ | |||
(def! inc4 (fn* (a) (+ 4 a))) | |||
(prn (inc4 5)) |
@ -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 | |||
@ -0,0 +1,6 @@ | |||
(def! mymap {"a" | |||
1}) | |||
(prn "incC.mal finished") | |||
"incC.mal return string" | |||
@ -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") |
@ -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") |
@ -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") |
@ -0,0 +1,14 @@ | |||
hello world | |||
;=>hello world | |||
abcABC123 | |||
;=>abcABC123 | |||
;:() []{}"'* | |||
;=>;:() []{}"'* | |||
;;; Test long line | |||
hello world abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 (;:() []{}"'* ;:() []{}"'* ;:() []{}"'*) | |||
;=>hello world abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 (;:() []{}"'* ;:() []{}"'* ;:() []{}"'*) | |||
@ -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) |
@ -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} |
@ -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] |
@ -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 |
@ -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 | |||
@ -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 | |||
@ -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] | |||
@ -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" | |||
@ -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 | |||
@ -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 | |||
@ -0,0 +1 @@ | |||
A line of text |