Skip to content

Instantly share code, notes, and snippets.

@rhysd
Created June 2, 2015 17:27
Show Gist options
  • Save rhysd/ec6c27bb54ceeccad406 to your computer and use it in GitHub Desktop.
Save rhysd/ec6c27bb54ceeccad406 to your computer and use it in GitHub Desktop.
----------------------------------------------
Testing test^crystal^step0, step file: crystal/step0_repl, test file: tests/step0_repl.mal
Running: ../runtest.py ../tests/step0_repl.mal -- ../crystal/step0_repl
TEST: hello world -> ['','hello world'] -> SUCCESS
TEST: abcABC123 -> ['','abcABC123'] -> SUCCESS
TEST: ;:() []{}"'* -> ['',';:() []{}"\'*'] -> SUCCESS
TEST: hello world abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 (;:() []{}"'* ;:() []{}"'* ;:() []{}"'*) -> ['','hello world abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 (;:() []{}"\'* ;:() []{}"\'* ;:() []{}"\'*)'] -> SUCCESS
----------------------------------------------
Testing test^crystal^step1, step file: crystal/step1_read_print, test file: tests/step1_read_print.mal
Running: ../runtest.py ../tests/step1_read_print.mal -- ../crystal/step1_read_print
Testing read of nil/true/false
TEST: nil -> ['','nil'] -> SUCCESS
TEST: true -> ['','true'] -> SUCCESS
TEST: false -> ['','false'] -> SUCCESS
Testing read of numbers
TEST: 1 -> ['','1'] -> SUCCESS
TEST: 7 -> ['','7'] -> SUCCESS
TEST: 7 -> ['','7'] -> SUCCESS
Testing read of symbols
TEST: + -> ['','+'] -> SUCCESS
TEST: abc -> ['','abc'] -> SUCCESS
TEST: abc -> ['','abc'] -> SUCCESS
TEST: abc5 -> ['','abc5'] -> SUCCESS
TEST: abc-def -> ['','abc-def'] -> SUCCESS
Testing read of strings
TEST: "abc" -> ['','"abc"'] -> SUCCESS
TEST: "abc" -> ['','"abc"'] -> SUCCESS
TEST: "abc (with parens)" -> ['','"abc (with parens)"'] -> SUCCESS
TEST: "abc\"def" -> ['','"abc\\"def"'] -> SUCCESS
TEST: "" -> ['','""'] -> SUCCESS
Testing read of lists
TEST: (+ 1 2) -> ['','(+ 1 2)'] -> SUCCESS
TEST: ((3 4)) -> ['','((3 4))'] -> SUCCESS
TEST: (+ 1 (+ 2 3)) -> ['','(+ 1 (+ 2 3))'] -> SUCCESS
TEST: ( + 1 (+ 2 3 ) ) -> ['','(+ 1 (+ 2 3))'] -> SUCCESS
TEST: (* 1 2) -> ['','(* 1 2)'] -> SUCCESS
TEST: (** 1 2) -> ['','(** 1 2)'] -> SUCCESS
Test commas as whitespace
TEST: (1 2, 3,,,,),, -> ['','(1 2 3)'] -> SUCCESS
Testing read of quoting
TEST: '1 -> ['','(quote 1)'] -> SUCCESS
TEST: '(1 2 3) -> ['','(quote (1 2 3))'] -> SUCCESS
TEST: `1 -> ['','(quasiquote 1)'] -> SUCCESS
TEST: `(1 2 3) -> ['','(quasiquote (1 2 3))'] -> SUCCESS
TEST: ~1 -> ['','(unquote 1)'] -> SUCCESS
TEST: ~(1 2 3) -> ['','(unquote (1 2 3))'] -> SUCCESS
TEST: ~@(1 2 3) -> ['','(splice-unquote (1 2 3))'] -> SUCCESS
Testing reader errors
TEST: (1 2 -> ["expected ')', got EOF\r\n",'*'] -> SUCCESS
TEST: [1 2 -> ["expected ']', got EOF\r\n",'*'] -> SUCCESS
TEST: "abc -> ['expected \'"\', got EOF\r\n','*'] -> SUCCESS
-------- Optional Functionality --------
Testing keywords
TEST: :kw -> ['',':kw'] -> SUCCESS
TEST: (:kw1 :kw2 :kw3) -> ['','(:kw1 :kw2 :kw3)'] -> SUCCESS
Testing read of vectors
TEST: [+ 1 2] -> ['','[+ 1 2]'] -> SUCCESS
TEST: [[3 4]] -> ['','[[3 4]]'] -> SUCCESS
TEST: [+ 1 [+ 2 3]] -> ['','[+ 1 [+ 2 3]]'] -> SUCCESS
TEST: [ + 1 [+ 2 3 ] ] -> ['','[+ 1 [+ 2 3]]'] -> SUCCESS
Testing read of hash maps
TEST: {"abc" 1} -> ['','{"abc" 1}'] -> SUCCESS
TEST: {"a" {"b" 2}} -> ['','{"a" {"b" 2}}'] -> SUCCESS
TEST: {"a" {"b" {"c" 3}}} -> ['','{"a" {"b" {"c" 3}}}'] -> SUCCESS
TEST: { "a" {"b" { "cde" 3 } }} -> ['','{"a" {"b" {"cde" 3}}}'] -> SUCCESS
TEST: { :a {:b { :cde 3 } }} -> ['','{:a {:b {:cde 3}}}'] -> SUCCESS
Testing read of comments
TEST: ;; whole line comment (not an exception) -> ['','*'] -> SUCCESS
TEST: 1 ; comment after expression -> ['','1'] -> SUCCESS
TEST: 1; comment after expression -> ['','1'] -> SUCCESS
Testing read of ^/metadata
TEST: ^{"a" 1} [1 2 3] -> ['','(with-meta [1 2 3] {"a" 1})'] -> SUCCESS
Testing read of @/deref
TEST: @a -> ['','(deref a)'] -> SUCCESS
----------------------------------------------
Testing test^crystal^step2, step file: crystal/step2_eval, test file: tests/step2_eval.mal
Running: ../runtest.py ../tests/step2_eval.mal -- ../crystal/step2_eval
Testing evaluation of arithmetic operations
TEST: (+ 1 2) -> ['','3'] -> SUCCESS
TEST: (+ 5 (* 2 3)) -> ['','11'] -> SUCCESS
TEST: (- (+ 5 (* 2 3)) 3) -> ['','8'] -> SUCCESS
TEST: (/ (- (+ 5 (* 2 3)) 3) 4) -> ['','2'] -> SUCCESS
TEST: (/ (- (+ 515 (* 222 311)) 302) 27) -> ['','2565'] -> SUCCESS
TEST: (abc 1 2 3) -> [".*\\'abc\\' not found.*\r\n",'*'] -> SUCCESS
-------- Optional Functionality --------
Testing evaluation within collection literals
TEST: [1 2 (+ 1 2)] -> ['','[1 2 3]'] -> SUCCESS
TEST: {"a" (+ 7 8)} -> ['','{"a" 15}'] -> SUCCESS
TEST: {:a (+ 7 8)} -> ['','{:a 15}'] -> SUCCESS
----------------------------------------------
Testing test^crystal^step3, step file: crystal/step3_env, test file: tests/step3_env.mal
Running: ../runtest.py ../tests/step3_env.mal -- ../crystal/step3_env
Testing REPL_ENV
TEST: (+ 1 2) -> ['','3'] -> SUCCESS
TEST: (/ (- (+ 5 (* 2 3)) 3) 4) -> ['','2'] -> SUCCESS
Testing def!
TEST: (def! x 3) -> ['','3'] -> SUCCESS
TEST: x -> ['','3'] -> SUCCESS
TEST: (def! x 4) -> ['','4'] -> SUCCESS
TEST: x -> ['','4'] -> SUCCESS
TEST: (def! y (+ 1 7)) -> ['','8'] -> SUCCESS
TEST: y -> ['','8'] -> SUCCESS
Testing let*
TEST: (let* (z 9) z) -> ['','9'] -> SUCCESS
TEST: (let* (x 9) x) -> ['','9'] -> SUCCESS
TEST: x -> ['','4'] -> SUCCESS
TEST: (let* (z (+ 2 3)) (+ 1 z)) -> ['','6'] -> SUCCESS
TEST: (let* (p (+ 2 3) q (+ 2 p)) (+ p q)) -> ['','12'] -> SUCCESS
Testing outer environment
TEST: (def! a 4) -> ['','4'] -> SUCCESS
TEST: (let* (q 9) q) -> ['','9'] -> SUCCESS
TEST: (let* (q 9) a) -> ['','4'] -> SUCCESS
TEST: (let* (z 2) (let* (q 9) a)) -> ['','4'] -> SUCCESS
-------- Optional Functionality --------
Testing let* with vector bindings
TEST: (let* [z 9] z) -> ['','9'] -> SUCCESS
TEST: (let* [p (+ 2 3) q (+ 2 p)] (+ p q)) -> ['','12'] -> SUCCESS
Testing vector evaluation
TEST: (let* (a 5 b 6) [3 4 a [b 7] 8]) -> ['','[3 4 5 [6 7] 8]'] -> SUCCESS
----------------------------------------------
Testing test^crystal^step4, step file: crystal/step4_if_fn_do, test file: tests/step4_if_fn_do.mal
Running: ../runtest.py ../tests/step4_if_fn_do.mal -- ../crystal/step4_if_fn_do
-----------------------------------------------------
Testing list functions
TEST: (list) -> ['','()'] -> SUCCESS
TEST: (list? (list)) -> ['','true'] -> SUCCESS
TEST: (empty? (list)) -> ['','true'] -> SUCCESS
TEST: (empty? (list 1)) -> ['','false'] -> SUCCESS
TEST: (list 1 2 3) -> ['','(1 2 3)'] -> SUCCESS
TEST: (count (list 1 2 3)) -> ['','3'] -> SUCCESS
TEST: (count (list)) -> ['','0'] -> SUCCESS
TEST: (count nil) -> ['','0'] -> SUCCESS
TEST: (if (> (count (list 1 2 3)) 3) "yes" "no") -> ['','"no"'] -> SUCCESS
TEST: (if (>= (count (list 1 2 3)) 3) "yes" "no") -> ['','"yes"'] -> SUCCESS
Testing if form
TEST: (if true 7 8) -> ['','7'] -> SUCCESS
TEST: (if false 7 8) -> ['','8'] -> SUCCESS
TEST: (if true (+ 1 7) (+ 1 8)) -> ['','8'] -> SUCCESS
TEST: (if false (+ 1 7) (+ 1 8)) -> ['','9'] -> SUCCESS
TEST: (if nil 7 8) -> ['','8'] -> SUCCESS
TEST: (if 0 7 8) -> ['','7'] -> SUCCESS
TEST: (if "" 7 8) -> ['','7'] -> SUCCESS
TEST: (if (list) 7 8) -> ['','7'] -> SUCCESS
TEST: (if (list 1 2 3) 7 8) -> ['','7'] -> SUCCESS
TEST: (= (list) nil) -> ['','false'] -> SUCCESS
Testing 1-way if form
TEST: (if false (+ 1 7)) -> ['','nil'] -> SUCCESS
TEST: (if nil 8 7) -> ['','7'] -> SUCCESS
TEST: (if true (+ 1 7)) -> ['','8'] -> SUCCESS
Testing basic conditionals
TEST: (= 2 1) -> ['','false'] -> SUCCESS
TEST: (= 1 1) -> ['','true'] -> SUCCESS
TEST: (= 1 2) -> ['','false'] -> SUCCESS
TEST: (= 1 (+ 1 1)) -> ['','false'] -> SUCCESS
TEST: (= 2 (+ 1 1)) -> ['','true'] -> SUCCESS
TEST: (= nil 1) -> ['','false'] -> SUCCESS
TEST: (= nil nil) -> ['','true'] -> SUCCESS
TEST: (> 2 1) -> ['','true'] -> SUCCESS
TEST: (> 1 1) -> ['','false'] -> SUCCESS
TEST: (> 1 2) -> ['','false'] -> SUCCESS
TEST: (>= 2 1) -> ['','true'] -> SUCCESS
TEST: (>= 1 1) -> ['','true'] -> SUCCESS
TEST: (>= 1 2) -> ['','false'] -> SUCCESS
TEST: (< 2 1) -> ['','false'] -> SUCCESS
TEST: (< 1 1) -> ['','false'] -> SUCCESS
TEST: (< 1 2) -> ['','true'] -> SUCCESS
TEST: (<= 2 1) -> ['','false'] -> SUCCESS
TEST: (<= 1 1) -> ['','true'] -> SUCCESS
TEST: (<= 1 2) -> ['','true'] -> SUCCESS
Testing equality
TEST: (= 1 1) -> ['','true'] -> SUCCESS
TEST: (= 0 0) -> ['','true'] -> SUCCESS
TEST: (= 1 0) -> ['','false'] -> SUCCESS
TEST: (= "" "") -> ['','true'] -> SUCCESS
TEST: (= "abc" "") -> ['','false'] -> SUCCESS
TEST: (= "" "abc") -> ['','false'] -> SUCCESS
TEST: (= "abc" "def") -> ['','false'] -> SUCCESS
TEST: (= (list) (list)) -> ['','true'] -> SUCCESS
TEST: (= (list 1 2) (list 1 2)) -> ['','true'] -> SUCCESS
TEST: (= (list 1) (list)) -> ['','false'] -> SUCCESS
TEST: (= (list) (list 1)) -> ['','false'] -> SUCCESS
TEST: (= 0 (list)) -> ['','false'] -> SUCCESS
TEST: (= (list) 0) -> ['','false'] -> SUCCESS
TEST: (= (list) "") -> ['','false'] -> SUCCESS
TEST: (= "" (list)) -> ['','false'] -> SUCCESS
Testing builtin and user defined functions
TEST: (+ 1 2) -> ['','3'] -> SUCCESS
TEST: ( (fn* (a b) (+ b a)) 3 4) -> ['','7'] -> SUCCESS
TEST: ( (fn* () 4) ) -> ['','4'] -> SUCCESS
TEST: ( (fn* (f x) (f x)) (fn* (a) (+ 1 a)) 7) -> ['','8'] -> SUCCESS
Testing closures
TEST: ( ( (fn* (a) (fn* (b) (+ a b))) 5) 7) -> ['','12'] -> SUCCESS
TEST: (def! gen-plus5 (fn* () (fn* (b) (+ 5 b)))) -> ['','*'] -> SUCCESS
TEST: (def! plus5 (gen-plus5)) -> ['','*'] -> SUCCESS
TEST: (plus5 7) -> ['','12'] -> SUCCESS
TEST: (def! gen-plusX (fn* (x) (fn* (b) (+ x b)))) -> ['','*'] -> SUCCESS
TEST: (def! plus7 (gen-plusX 7)) -> ['','*'] -> SUCCESS
TEST: (plus7 8) -> ['','15'] -> SUCCESS
Testing variable length arguments
TEST: ( (fn* (& more) (count more)) 1 2 3) -> ['','3'] -> SUCCESS
TEST: ( (fn* (& more) (count more)) 1) -> ['','1'] -> SUCCESS
TEST: ( (fn* (& more) (count more)) ) -> ['','0'] -> SUCCESS
TEST: ( (fn* (a & more) (count more)) 1 2 3) -> ['','2'] -> SUCCESS
TEST: ( (fn* (a & more) (count more)) 1) -> ['','0'] -> SUCCESS
Testing language defined not function
TEST: (not false) -> ['','true'] -> SUCCESS
TEST: (not true) -> ['','false'] -> SUCCESS
TEST: (not "a") -> ['','false'] -> SUCCESS
TEST: (not 0) -> ['','false'] -> SUCCESS
Testing do form
TEST: (do (prn "prn output1")) -> ['"prn output1"\r\n','nil'] -> SUCCESS
TEST: (do (prn "prn output2") 7) -> ['"prn output2"\r\n','7'] -> SUCCESS
TEST: (do (prn "prn output1") (prn "prn output2") (+ 1 2)) -> ['"prn output1"\r\n"prn output2"\r\n','3'] -> SUCCESS
TEST: (do (def! a 6) 7 (+ a 8)) -> ['','14'] -> SUCCESS
TEST: a -> ['','6'] -> SUCCESS
Testing recursive sumdown function
TEST: (def! sumdown (fn* (N) (if (> N 0) (+ N (sumdown (- N 1))) 0))) -> ['','*'] -> SUCCESS
TEST: (sumdown 1) -> ['','1'] -> SUCCESS
TEST: (sumdown 2) -> ['','3'] -> SUCCESS
TEST: (sumdown 6) -> ['','21'] -> SUCCESS
Testing recursive fibonacci function
TEST: (def! fib (fn* (N) (if (= N 0) 1 (if (= N 1) 1 (+ (fib (- N 1)) (fib (- N 2))))))) -> ['','*'] -> SUCCESS
TEST: (fib 1) -> ['','1'] -> SUCCESS
TEST: (fib 2) -> ['','2'] -> SUCCESS
TEST: (fib 4) -> ['','5'] -> SUCCESS
TEST: (fib 10) -> ['','89'] -> SUCCESS
-----------------------------------------------------
Testing string quoting
TEST: "" -> ['','""'] -> SUCCESS
TEST: "abc" -> ['','"abc"'] -> SUCCESS
TEST: "abc def" -> ['','"abc def"'] -> SUCCESS
TEST: "\"" -> ['','"\\""'] -> SUCCESS
Testing pr-str
TEST: (pr-str) -> ['','""'] -> SUCCESS
TEST: (pr-str "") -> ['','"\\"\\""'] -> SUCCESS
TEST: (pr-str "abc") -> ['','"\\"abc\\""'] -> SUCCESS
TEST: (pr-str "abc def" "ghi jkl") -> ['','"\\"abc def\\" \\"ghi jkl\\""'] -> SUCCESS
TEST: (pr-str "\"") -> ['','"\\"\\\\\\"\\""'] -> SUCCESS
TEST: (pr-str (list 1 2 "abc" "\"") "def") -> ['','"(1 2 \\"abc\\" \\"\\\\\\"\\") \\"def\\""'] -> SUCCESS
Testing str
TEST: (str) -> ['','""'] -> SUCCESS
TEST: (str "") -> ['','""'] -> SUCCESS
TEST: (str "abc") -> ['','"abc"'] -> SUCCESS
TEST: (str "\"") -> ['','"\\""'] -> SUCCESS
TEST: (str 1 "abc" 3) -> ['','"1abc3"'] -> SUCCESS
TEST: (str "abc def" "ghi jkl") -> ['','"abc defghi jkl"'] -> SUCCESS
Testing prn
TEST: (prn) -> ['\r\n','nil'] -> SUCCESS
TEST: (prn "") -> ['""\r\n','nil'] -> SUCCESS
TEST: (prn "abc") -> ['"abc"\r\n','nil'] -> SUCCESS
TEST: (prn "abc def" "ghi jkl") -> ['"abc def" "ghi jkl"\r\n','*'] -> SUCCESS
TEST: (prn "\"") -> ['"\\""\r\n','nil'] -> SUCCESS
TEST: (prn (list 1 2 "abc" "\"") "def") -> ['(1 2 "abc" "\\"") "def"\r\n','nil'] -> SUCCESS
Testing println
TEST: (println) -> ['\r\n','nil'] -> SUCCESS
TEST: (println "") -> ['\r\n','nil'] -> SUCCESS
TEST: (println "abc") -> ['abc\r\n','nil'] -> SUCCESS
TEST: (println "abc def" "ghi jkl") -> ['abc def ghi jkl\r\n','*'] -> SUCCESS
TEST: (println "\"") -> ['"\r\n','nil'] -> SUCCESS
TEST: (println (list 1 2 "abc" "\"") "def") -> ['(1 2 abc ") def\r\n','nil'] -> SUCCESS
-------- Optional Functionality --------
Testing keywords
TEST: (= :abc :abc) -> ['','true'] -> SUCCESS
TEST: (= :abc :def) -> ['','false'] -> SUCCESS
TEST: (= :abc ":abc") -> ['','false'] -> SUCCESS
Testing vector truthiness
TEST: (if [] 7 8) -> ['','7'] -> SUCCESS
Testing vector functions
TEST: (count [1 2 3]) -> ['','3'] -> SUCCESS
TEST: (empty? [1 2 3]) -> ['','false'] -> SUCCESS
TEST: (empty? []) -> ['','true'] -> SUCCESS
TEST: (list? [4 5 6]) -> ['','false'] -> SUCCESS
Testing vector equality
TEST: (= [] (list)) -> ['','true'] -> SUCCESS
TEST: (= (list 1 2) [1 2]) -> ['','true'] -> SUCCESS
TEST: (= (list 1) []) -> ['','false'] -> SUCCESS
TEST: (= [] [1]) -> ['','false'] -> SUCCESS
TEST: (= 0 []) -> ['','false'] -> SUCCESS
TEST: (= [] 0) -> ['','false'] -> SUCCESS
TEST: (= [] "") -> ['','false'] -> SUCCESS
TEST: (= "" []) -> ['','false'] -> SUCCESS
Testing vector parameter lists
TEST: ( (fn* [] 4) ) -> ['','4'] -> SUCCESS
TEST: ( (fn* [f x] (f x)) (fn* [a] (+ 1 a)) 7) -> ['','8'] -> SUCCESS
----------------------------------------------
Testing test^crystal^step6, step file: crystal/step6_file, test file: tests/step6_file.mal
Running: ../runtest.py ../tests/step6_file.mal -- ../crystal/step6_file
Testing that (do (do)) not broken by TCO
TEST: (do (do 1 2)) -> ['','2'] -> SUCCESS
Testing read-string, eval and slurp
TEST: (read-string "(1 2 (3 4) nil)") -> ['','(1 2 (3 4) nil)'] -> SUCCESS
TEST: (read-string "(+ 2 3)") -> ['','(+ 2 3)'] -> SUCCESS
TEST: (read-string "7 ;; comment") -> ['','7'] -> SUCCESS
TEST: (read-string ";; comment") -> ['','*'] -> SUCCESS
TEST: (eval (read-string "(+ 2 3)")) -> ['','5'] -> SUCCESS
Testing load-file
TEST: (load-file "../tests/inc.mal") -> ['','*'] -> SUCCESS
TEST: (inc1 7) -> ['','8'] -> SUCCESS
TEST: (inc2 7) -> ['','9'] -> SUCCESS
TEST: (inc3 9) -> ['','12'] -> SUCCESS
Testing that *ARGV* exists and is an empty list
TEST: (list? *ARGV*) -> ['','true'] -> SUCCESS
TEST: *ARGV* -> ['','()'] -> SUCCESS
-------- Optional Functionality --------
Testing comments in a file
TEST: (load-file "../tests/incB.mal") -> ['"incB.mal finished"\r\n','"incB.mal return string"'] -> SUCCESS
TEST: (inc4 7) -> ['','11'] -> SUCCESS
TEST: (inc5 7) -> ['','12'] -> SUCCESS
Testing map literal across multiple lines in a file
TEST: (load-file "../tests/incC.mal") -> ['','*'] -> SUCCESS
TEST: mymap -> ['','{"a" 1}'] -> SUCCESS
Testing that vector params not broken by TCO
TEST: (def! g (fn* [] 78)) -> ['','*'] -> SUCCESS
TEST: (g) -> ['','78'] -> SUCCESS
TEST: (def! g (fn* [a] (+ a 78))) -> ['','*'] -> SUCCESS
TEST: (g 3) -> ['','81'] -> SUCCESS
----------------------------------------------
Testing test^crystal^step7, step file: crystal/step7_quote, test file: tests/step7_quote.mal
Running: ../runtest.py ../tests/step7_quote.mal -- ../crystal/step7_quote
Testing cons function
TEST: (cons 1 (list)) -> ['','(1)'] -> SUCCESS
TEST: (cons 1 (list 2)) -> ['','(1 2)'] -> SUCCESS
TEST: (cons 1 (list 2 3)) -> ['','(1 2 3)'] -> SUCCESS
TEST: (cons (list 1) (list 2 3)) -> ['','((1) 2 3)'] -> SUCCESS
Testing concat function
TEST: (concat) -> ['','()'] -> SUCCESS
TEST: (concat (list 1 2)) -> ['','(1 2)'] -> SUCCESS
TEST: (concat (list 1 2) (list 3 4)) -> ['','(1 2 3 4)'] -> SUCCESS
TEST: (concat (list 1 2) (list 3 4) (list 5 6)) -> ['','(1 2 3 4 5 6)'] -> SUCCESS
TEST: (concat (concat)) -> ['','()'] -> SUCCESS
Testing regular quote
TEST: (quote 7) -> ['','7'] -> SUCCESS
TEST: '7 -> ['','7'] -> SUCCESS
TEST: (quote (1 2 3)) -> ['','(1 2 3)'] -> SUCCESS
TEST: '(1 2 3) -> ['','(1 2 3)'] -> SUCCESS
TEST: (quote (1 2 (3 4))) -> ['','(1 2 (3 4))'] -> SUCCESS
TEST: '(1 2 (3 4)) -> ['','(1 2 (3 4))'] -> SUCCESS
Testing simple quasiquote
TEST: (quasiquote 7) -> ['','7'] -> SUCCESS
TEST: `7 -> ['','7'] -> SUCCESS
TEST: (quasiquote (1 2 3)) -> ['','(1 2 3)'] -> SUCCESS
TEST: `(1 2 3) -> ['','(1 2 3)'] -> SUCCESS
TEST: (quasiquote (1 2 (3 4))) -> ['','(1 2 (3 4))'] -> SUCCESS
TEST: `(1 2 (3 4)) -> ['','(1 2 (3 4))'] -> SUCCESS
Testing unquote
TEST: `~7 -> ['','7'] -> SUCCESS
TEST: (def! a 8) -> ['','8'] -> SUCCESS
TEST: `a -> ['','a'] -> SUCCESS
TEST: `~a -> ['','8'] -> SUCCESS
TEST: `(1 a 3) -> ['','(1 a 3)'] -> SUCCESS
TEST: `(1 ~a 3) -> ['','(1 8 3)'] -> SUCCESS
TEST: (def! b '(1 "b" "d")) -> ['','(1 "b" "d")'] -> SUCCESS
TEST: `(1 b 3) -> ['','(1 b 3)'] -> SUCCESS
TEST: `(1 ~b 3) -> ['','(1 (1 "b" "d") 3)'] -> SUCCESS
Testing splice-unquote
TEST: (def! c '(1 "b" "d")) -> ['','(1 "b" "d")'] -> SUCCESS
TEST: `(1 c 3) -> ['','(1 c 3)'] -> SUCCESS
TEST: `(1 ~@c 3) -> ['','(1 1 "b" "d" 3)'] -> SUCCESS
Testing symbol equality
TEST: (= 'abc 'abc) -> ['','true'] -> SUCCESS
TEST: (= 'abc 'abcd) -> ['','false'] -> SUCCESS
TEST: (= 'abc "abc") -> ['','false'] -> SUCCESS
TEST: (= "abc" 'abc) -> ['','false'] -> SUCCESS
-------- Optional Functionality --------
Testing cons, concat, first, rest with vectors
TEST: (cons [1] [2 3]) -> ['','([1] 2 3)'] -> SUCCESS
TEST: (cons 1 [2 3]) -> ['','(1 2 3)'] -> SUCCESS
TEST: (concat [1 2] (list 3 4) [5 6]) -> ['','(1 2 3 4 5 6)'] -> SUCCESS
Testing unquote with vectors
TEST: (def! a 8) -> ['','8'] -> SUCCESS
TEST: `[1 a 3] -> ['','(1 a 3)'] -> SUCCESS
Testing splice-unquote with vectors
TEST: (def! c '(1 "b" "d")) -> ['','(1 "b" "d")'] -> SUCCESS
TEST: `[1 ~@c 3] -> ['','(1 1 "b" "d" 3)'] -> SUCCESS
----------------------------------------------
Testing test^crystal^step8, step file: crystal/step8_macros, test file: tests/step8_macros.mal
Running: ../runtest.py ../tests/step8_macros.mal -- ../crystal/step8_macros
Testing non-macro function
TEST: (not (= 1 1)) -> ['','false'] -> SUCCESS
TEST: (not (= 1 2)) -> ['','true'] -> SUCCESS
Testing trivial macros
TEST: (defmacro! one (fn* () 1)) -> ['','*'] -> SUCCESS
TEST: (one) -> ['','1'] -> SUCCESS
TEST: (defmacro! two (fn* () 2)) -> ['','*'] -> SUCCESS
TEST: (two) -> ['','2'] -> SUCCESS
Testing unless macros
TEST: (defmacro! unless (fn* (pred a b) `(if ~pred ~b ~a))) -> ['','*'] -> SUCCESS
TEST: (unless false 7 8) -> ['','7'] -> SUCCESS
TEST: (unless true 7 8) -> ['','8'] -> SUCCESS
TEST: (defmacro! unless2 (fn* (pred a b) `(if (not ~pred) ~a ~b))) -> ['','*'] -> SUCCESS
TEST: (unless2 false 7 8) -> ['','7'] -> SUCCESS
TEST: (unless2 true 7 8) -> ['','8'] -> SUCCESS
Testing macroexpand
TEST: (macroexpand (unless2 2 3 4)) -> ['','(if (not 2) 3 4)'] -> SUCCESS
Testing nth, first and rest functions
TEST: (nth '(1) 0) -> ['','1'] -> SUCCESS
TEST: (nth '(1 2) 1) -> ['','2'] -> SUCCESS
TEST: (def! x "x") -> ['','*'] -> SUCCESS
TEST: (def! x (nth '(1 2) 2)) -> ['','*'] -> SUCCESS
TEST: x -> ['','"x"'] -> SUCCESS
TEST: (first '()) -> ['','nil'] -> SUCCESS
TEST: (first '(6)) -> ['','6'] -> SUCCESS
TEST: (first '(7 8 9)) -> ['','7'] -> SUCCESS
TEST: (rest '()) -> ['','()'] -> SUCCESS
TEST: (rest '(6)) -> ['','()'] -> SUCCESS
TEST: (rest '(7 8 9)) -> ['','(8 9)'] -> SUCCESS
Testing or macro
TEST: (or) -> ['','nil'] -> SUCCESS
TEST: (or 1) -> ['','1'] -> SUCCESS
TEST: (or 1 2 3 4) -> ['','1'] -> SUCCESS
TEST: (or false 2) -> ['','2'] -> SUCCESS
TEST: (or false nil 3) -> ['','3'] -> SUCCESS
TEST: (or false nil false false nil 4) -> ['','4'] -> SUCCESS
TEST: (or false nil 3 false nil 4) -> ['','3'] -> SUCCESS
TEST: (or (or false 4)) -> ['','4'] -> SUCCESS
Testing cond macro
TEST: (cond) -> ['','nil'] -> SUCCESS
TEST: (cond true 7) -> ['','7'] -> SUCCESS
TEST: (cond true 7 true 8) -> ['','7'] -> SUCCESS
TEST: (cond false 7 true 8) -> ['','8'] -> SUCCESS
TEST: (cond false 7 false 8 "else" 9) -> ['','9'] -> SUCCESS
TEST: (cond false 7 (= 2 2) 8 "else" 9) -> ['','8'] -> SUCCESS
TEST: (cond false 7 false 8 false 9) -> ['','nil'] -> SUCCESS
Loading core.mal
TEST: (load-file "../core.mal") -> ['','*'] -> SUCCESS
Testing and macro
TEST: (and) -> ['','true'] -> SUCCESS
TEST: (and 1) -> ['','1'] -> SUCCESS
TEST: (and 1 2) -> ['','2'] -> SUCCESS
TEST: (and 1 2 3) -> ['','3'] -> SUCCESS
TEST: (and 1 2 3 4) -> ['','4'] -> SUCCESS
TEST: (and 1 2 3 4 false) -> ['','false'] -> SUCCESS
TEST: (and 1 2 3 4 false 5) -> ['','false'] -> SUCCESS
Testing -> macro
TEST: (-> 7) -> ['','7'] -> SUCCESS
TEST: (-> (list 7 8 9) first) -> ['','7'] -> SUCCESS
TEST: (-> (list 7 8 9) (first)) -> ['','7'] -> SUCCESS
TEST: (-> (list 7 8 9) first (+ 7)) -> ['','14'] -> SUCCESS
TEST: (-> (list 7 8 9) rest (rest) first (+ 7)) -> ['','16'] -> SUCCESS
Testing EVAL in let*
TEST: (let* (x (or nil "yes")) x) -> ['','"yes"'] -> SUCCESS
-------- Optional Functionality --------
Testing nth, first, rest with vectors
TEST: (nth [1] 0) -> ['','1'] -> SUCCESS
TEST: (nth [1 2] 1) -> ['','2'] -> SUCCESS
TEST: (def! x "x") -> ['','*'] -> SUCCESS
TEST: (def! x (nth [1 2] 2)) -> ['','*'] -> SUCCESS
TEST: x -> ['','"x"'] -> SUCCESS
TEST: (first []) -> ['','nil'] -> SUCCESS
TEST: (first [10]) -> ['','10'] -> SUCCESS
TEST: (first [10 11 12]) -> ['','10'] -> SUCCESS
TEST: (rest []) -> ['','()'] -> SUCCESS
TEST: (rest [10]) -> ['','()'] -> SUCCESS
TEST: (rest [10 11 12]) -> ['','(11 12)'] -> SUCCESS
Testing EVAL in vector let*
TEST: (let* [x (or nil "yes")] x) -> ['','"yes"'] -> SUCCESS
----------------------------------------------
Testing test^crystal^step9, step file: crystal/step9_try, test file: tests/step9_try.mal
Running: ../runtest.py ../tests/step9_try.mal -- ../crystal/step9_try
Testing try*/catch*
TEST: (try* 123 (catch* e 456)) -> ['','123'] -> SUCCESS
TEST: (try* (abc 1 2) (catch* exc (prn "exc is:" exc))) -> ['"exc is:" "\'abc\' not found"\r\n','nil'] -> SUCCESS
TEST: (try* (throw (list 1 2 3)) (catch* exc (do (prn "err:" exc) 7))) -> ['"err:" (1 2 3)\r\n','7'] -> SUCCESS
TEST: (try* (throw "my exception") (catch* exc (do (prn "exc:" exc) 7))) -> ['"exc:" "my exception"\r\n','7'] -> SUCCESS
TEST: (try* (map throw (list 7)) (catch* exc exc)) -> ['','7'] -> SUCCESS
Testing builtin functions
TEST: (symbol? 'abc) -> ['','true'] -> SUCCESS
TEST: (symbol? "abc") -> ['','false'] -> SUCCESS
TEST: (nil? nil) -> ['','true'] -> SUCCESS
TEST: (nil? true) -> ['','false'] -> SUCCESS
TEST: (true? true) -> ['','true'] -> SUCCESS
TEST: (true? false) -> ['','false'] -> SUCCESS
TEST: (true? true?) -> ['','false'] -> SUCCESS
TEST: (false? false) -> ['','true'] -> SUCCESS
TEST: (false? true) -> ['','false'] -> SUCCESS
Testing apply function with core functions
TEST: (apply + (list 2 3)) -> ['','5'] -> SUCCESS
TEST: (apply + 4 (list 5)) -> ['','9'] -> SUCCESS
TEST: (apply prn (list 1 2 "3" (list))) -> ['1 2 "3" ()\r\n','*'] -> SUCCESS
TEST: (apply prn 1 2 (list "3" (list))) -> ['1 2 "3" ()\r\n','*'] -> SUCCESS
Testing apply function with user functions
TEST: (apply (fn* (a b) (+ a b)) (list 2 3)) -> ['','5'] -> SUCCESS
TEST: (apply (fn* (a b) (+ a b)) 4 (list 5)) -> ['','9'] -> SUCCESS
Testing map function
TEST: (def! nums (list 1 2 3)) -> ['','*'] -> SUCCESS
TEST: (def! double (fn* (a) (* 2 a))) -> ['','*'] -> SUCCESS
TEST: (double 3) -> ['','6'] -> SUCCESS
TEST: (map double nums) -> ['','(2 4 6)'] -> SUCCESS
TEST: (map (fn* (x) (symbol? x)) (list 1 (symbol "two") "three")) -> ['','(false true false)'] -> SUCCESS
------- Optional Functionality ----------
------- (Needed for self-hosting) -------
Testing symbol and keyword functions
TEST: (symbol? :abc) -> ['','false'] -> SUCCESS
TEST: (symbol? 'abc) -> ['','true'] -> SUCCESS
TEST: (symbol? "abc") -> ['','false'] -> SUCCESS
TEST: (symbol? (symbol "abc")) -> ['','true'] -> SUCCESS
TEST: (keyword? :abc) -> ['','true'] -> SUCCESS
TEST: (keyword? 'abc) -> ['','false'] -> SUCCESS
TEST: (keyword? "abc") -> ['','false'] -> SUCCESS
TEST: (keyword? (keyword "abc")) -> ['','true'] -> SUCCESS
TEST: (symbol "abc") -> ['','abc'] -> SUCCESS
TEST: (keyword "abc") -> ['',':abc'] -> SUCCESS
Testing sequential? function
TEST: (sequential? (list 1 2 3)) -> ['','true'] -> SUCCESS
TEST: (sequential? [15]) -> ['','true'] -> SUCCESS
TEST: (sequential? sequential?) -> ['','false'] -> SUCCESS
TEST: (sequential? nil) -> ['','false'] -> SUCCESS
TEST: (sequential? "abc") -> ['','false'] -> SUCCESS
Testing apply function with core functions and arguments in vector
TEST: (apply + 4 [5]) -> ['','9'] -> SUCCESS
TEST: (apply prn 1 2 ["3" 4]) -> ['1 2 "3" 4\r\n','nil'] -> SUCCESS
Testing apply function with user functions and arguments in vector
TEST: (apply (fn* (a b) (+ a b)) [2 3]) -> ['','5'] -> SUCCESS
TEST: (apply (fn* (a b) (+ a b)) 4 [5]) -> ['','9'] -> SUCCESS
Testing map function with vectors
TEST: (map (fn* (a) (* 2 a)) [1 2 3]) -> ['','(2 4 6)'] -> SUCCESS
Testing vector functions
TEST: (vector? [10 11]) -> ['','true'] -> SUCCESS
TEST: (vector? '(12 13)) -> ['','false'] -> SUCCESS
TEST: (vector 3 4 5) -> ['','[3 4 5]'] -> SUCCESS
TEST: (map? {}) -> ['','true'] -> SUCCESS
TEST: (map? '()) -> ['','false'] -> SUCCESS
TEST: (map? []) -> ['','false'] -> SUCCESS
TEST: (map? 'abc) -> ['','false'] -> SUCCESS
TEST: (map? :abc) -> ['','false'] -> SUCCESS
Testing hash-maps
TEST: (hash-map "a" 1) -> ['','{"a" 1}'] -> SUCCESS
TEST: {"a" 1} -> ['','{"a" 1}'] -> SUCCESS
TEST: (assoc {} "a" 1) -> ['','{"a" 1}'] -> SUCCESS
TEST: (get (assoc (assoc {"a" 1 } "b" 2) "c" 3) "a") -> ['','1'] -> SUCCESS
TEST: (def! hm1 (hash-map)) -> ['','{}'] -> SUCCESS
TEST: (map? hm1) -> ['','true'] -> SUCCESS
TEST: (map? 1) -> ['','false'] -> SUCCESS
TEST: (map? "abc") -> ['','false'] -> SUCCESS
TEST: (get nil "a") -> ['','nil'] -> SUCCESS
TEST: (get hm1 "a") -> ['','nil'] -> SUCCESS
TEST: (contains? hm1 "a") -> ['','false'] -> SUCCESS
TEST: (def! hm2 (assoc hm1 "a" 1)) -> ['','{"a" 1}'] -> SUCCESS
TEST: (get hm1 "a") -> ['','nil'] -> SUCCESS
TEST: (contains? hm1 "a") -> ['','false'] -> SUCCESS
TEST: (get hm2 "a") -> ['','1'] -> SUCCESS
TEST: (contains? hm2 "a") -> ['','true'] -> SUCCESS
TEST: (keys hm1) -> ['','()'] -> SUCCESS
TEST: (keys hm2) -> ['','("a")'] -> SUCCESS
TEST: (vals hm1) -> ['','()'] -> SUCCESS
TEST: (vals hm2) -> ['','(1)'] -> SUCCESS
TEST: (count (keys (assoc hm2 "b" 2 "c" 3))) -> ['','3'] -> SUCCESS
TEST: (def! hm3 (assoc hm2 "b" 2)) -> ['','*'] -> SUCCESS
TEST: (count (keys hm3)) -> ['','2'] -> SUCCESS
TEST: (count (vals hm3)) -> ['','2'] -> SUCCESS
TEST: (dissoc hm3 "a") -> ['','{"b" 2}'] -> SUCCESS
TEST: (dissoc hm3 "a" "b") -> ['','{}'] -> SUCCESS
TEST: (dissoc hm3 "a" "b" "c") -> ['','{}'] -> SUCCESS
TEST: (count (keys hm3)) -> ['','2'] -> SUCCESS
Testing keywords as hash-map keys
TEST: (get {:abc 123} :abc) -> ['','123'] -> SUCCESS
TEST: (contains? {:abc 123} :abc) -> ['','true'] -> SUCCESS
TEST: (contains? {:abcd 123} :abc) -> ['','false'] -> SUCCESS
TEST: (assoc {} :bcd 234) -> ['','{:bcd 234}'] -> SUCCESS
TEST: (dissoc {:cde 345 :fgh 456} :cde) -> ['','{:fgh 456}'] -> SUCCESS
TEST: (keyword? (nth (keys {:abc 123 :def 456}) 0)) -> ['','true'] -> SUCCESS
TEST: (keyword? (nth (vals {"a" :abc "b" :def}) 0)) -> ['','true'] -> SUCCESS
----------------------------------------------
Testing test^crystal^stepA, step file: crystal/stepA_mal, test file: tests/stepA_mal.mal
Running: ../runtest.py ../tests/stepA_mal.mal -- ../crystal/stepA_mal
Started with:
Mal [crystal]
Testing readline
TEST: (readline "mal-user> ") -> ['','*'] -> SUCCESS
TEST: "hello" -> ['','"\\"hello\\""'] -> SUCCESS
Testing *host-language*
TEST: (= "something bogus" *host-language*) -> ['','false'] -> SUCCESS
------- Optional Functionality ----------
------- (Needed for self-hosting) -------
Testing metadata on functions
Testing metadata on mal functions
TEST: (meta (fn* (a) a)) -> ['','nil'] -> SUCCESS
TEST: (meta (with-meta (fn* (a) a) {"b" 1})) -> ['','{"b" 1}'] -> SUCCESS
TEST: (meta (with-meta (fn* (a) a) "abc")) -> ['','"abc"'] -> SUCCESS
TEST: (def! l-wm (with-meta (fn* (a) a) {"b" 2})) -> ['','*'] -> SUCCESS
TEST: (meta l-wm) -> ['','{"b" 2}'] -> SUCCESS
TEST: (meta (with-meta l-wm {"new_meta" 123})) -> ['','{"new_meta" 123}'] -> SUCCESS
TEST: (meta l-wm) -> ['','{"b" 2}'] -> SUCCESS
TEST: (def! f-wm (with-meta (fn* [a] (+ 1 a)) {"abc" 1})) -> ['','*'] -> SUCCESS
TEST: (meta f-wm) -> ['','{"abc" 1}'] -> SUCCESS
TEST: (meta (with-meta f-wm {"new_meta" 123})) -> ['','{"new_meta" 123}'] -> SUCCESS
TEST: (meta f-wm) -> ['','{"abc" 1}'] -> SUCCESS
TEST: (def! f-wm2 ^{"abc" 1} (fn* [a] (+ 1 a))) -> ['','*'] -> SUCCESS
TEST: (meta f-wm2) -> ['','{"abc" 1}'] -> SUCCESS
Meta of native functions should return nil (not fail)
TEST: (meta +) -> ['','nil'] -> SUCCESS
Make sure closures and metadata co-exist
TEST: (def! gen-plusX (fn* (x) (with-meta (fn* (b) (+ x b)) {"meta" 1}))) -> ['','*'] -> SUCCESS
TEST: (def! plus7 (gen-plusX 7)) -> ['','*'] -> SUCCESS
TEST: (def! plus8 (gen-plusX 8)) -> ['','*'] -> SUCCESS
TEST: (plus7 8) -> ['','15'] -> SUCCESS
TEST: (meta plus7) -> ['','{"meta" 1}'] -> SUCCESS
TEST: (meta plus8) -> ['','{"meta" 1}'] -> SUCCESS
TEST: (meta (with-meta plus7 {"meta" 2})) -> ['','{"meta" 2}'] -> SUCCESS
TEST: (meta plus8) -> ['','{"meta" 1}'] -> SUCCESS
Testing atoms
TEST: (def! inc3 (fn* (a) (+ 3 a))) -> ['','*'] -> SUCCESS
TEST: (def! a (atom 2)) -> ['','(atom 2)'] -> SUCCESS
TEST: (deref a) -> ['','2'] -> SUCCESS
TEST: @a -> ['','2'] -> SUCCESS
TEST: (reset! a 3) -> ['','3'] -> SUCCESS
TEST: @a -> ['','3'] -> SUCCESS
TEST: (swap! a inc3) -> ['','6'] -> SUCCESS
TEST: @a -> ['','6'] -> SUCCESS
TEST: (swap! a (fn* (a) a)) -> ['','6'] -> SUCCESS
TEST: (swap! a (fn* (a) (* 2 a))) -> ['','12'] -> SUCCESS
TEST: (swap! a (fn* (a b) (* a b)) 10) -> ['','120'] -> SUCCESS
TEST: (swap! a + 3) -> ['','123'] -> SUCCESS
Testing swap!/closure interaction
TEST: (def! inc-it (fn* (a) (+ 1 a))) -> ['','*'] -> SUCCESS
TEST: (def! atm (atom 7)) -> ['','*'] -> SUCCESS
TEST: (def! f (fn* [] (swap! atm inc-it))) -> ['','*'] -> SUCCESS
TEST: (f) -> ['','8'] -> SUCCESS
TEST: (f) -> ['','9'] -> SUCCESS
Testing hash-map evaluation and atoms (i.e. an env)
TEST: (def! e (atom {"+" +})) -> ['','*'] -> SUCCESS
TEST: (swap! e assoc "-" -) -> ['','*'] -> SUCCESS
TEST: ( (get @e "+") 7 8) -> ['','15'] -> SUCCESS
TEST: ( (get @e "-") 11 8) -> ['','3'] -> SUCCESS
------- Optional Functionality --------------
------- (Not needed for self-hosting) -------
Testing conj function
TEST: (conj (list) 1) -> ['','(1)'] -> SUCCESS
TEST: (conj (list 1) 2) -> ['','(2 1)'] -> SUCCESS
TEST: (conj (list 2 3) 4) -> ['','(4 2 3)'] -> SUCCESS
TEST: (conj (list 2 3) 4 5 6) -> ['','(6 5 4 2 3)'] -> SUCCESS
TEST: (conj (list 1) (list 2 3)) -> ['','((2 3) 1)'] -> SUCCESS
TEST: (conj [] 1) -> ['','[1]'] -> SUCCESS
TEST: (conj [1] 2) -> ['','[1 2]'] -> SUCCESS
TEST: (conj [2 3] 4) -> ['','[2 3 4]'] -> SUCCESS
TEST: (conj [2 3] 4 5 6) -> ['','[2 3 4 5 6]'] -> SUCCESS
TEST: (conj [1] [2 3]) -> ['','[1 [2 3]]'] -> SUCCESS
Testing metadata on collections
TEST: (meta [1 2 3]) -> ['','nil'] -> SUCCESS
TEST: (with-meta [1 2 3] {"a" 1}) -> ['','[1 2 3]'] -> SUCCESS
TEST: (meta (with-meta [1 2 3] {"a" 1})) -> ['','{"a" 1}'] -> SUCCESS
TEST: (vector? (with-meta [1 2 3] {"a" 1})) -> ['','true'] -> SUCCESS
TEST: (meta (with-meta [1 2 3] "abc")) -> ['','"abc"'] -> SUCCESS
TEST: (meta (with-meta (list 1 2 3) {"a" 1})) -> ['','{"a" 1}'] -> SUCCESS
TEST: (list? (with-meta (list 1 2 3) {"a" 1})) -> ['','true'] -> SUCCESS
TEST: (meta (with-meta {"abc" 123} {"a" 1})) -> ['','{"a" 1}'] -> SUCCESS
TEST: (map? (with-meta {"abc" 123} {"a" 1})) -> ['','true'] -> SUCCESS
TEST: (def! l-wm (with-meta [4 5 6] {"b" 2})) -> ['','[4 5 6]'] -> SUCCESS
TEST: (meta l-wm) -> ['','{"b" 2}'] -> SUCCESS
TEST: (meta (with-meta l-wm {"new_meta" 123})) -> ['','{"new_meta" 123}'] -> SUCCESS
TEST: (meta l-wm) -> ['','{"b" 2}'] -> SUCCESS
Testing metadata on builtin functions
TEST: (meta +) -> ['','nil'] -> SUCCESS
TEST: (def! f-wm3 ^{"def" 2} +) -> ['','*'] -> SUCCESS
TEST: (meta f-wm3) -> ['','{"def" 2}'] -> SUCCESS
TEST: (meta +) -> ['','nil'] -> SUCCESS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment