2013-05-11 20:57:46 +02:00
|
|
|
(defmacro rev [&rest body]
|
|
|
|
"Execute the `body` statements in reverse"
|
|
|
|
(quasiquote (do (unquote-splice (list (reversed body))))))
|
|
|
|
|
|
|
|
|
2013-05-11 19:40:48 +02:00
|
|
|
(defn test-rev-macro []
|
|
|
|
"NATIVE: test stararged native macros"
|
|
|
|
(setv x [])
|
|
|
|
(rev (.append x 1) (.append x 2) (.append x 3))
|
|
|
|
(assert (= x [3 2 1])))
|
2013-06-05 12:19:06 +02:00
|
|
|
|
|
|
|
; Macros returning constants
|
|
|
|
|
|
|
|
(defmacro an-int [] 42)
|
|
|
|
(assert (= (an-int) 42))
|
|
|
|
|
2013-06-07 16:35:28 +02:00
|
|
|
(defmacro a-true [] True)
|
|
|
|
(assert (= (a-true) True))
|
|
|
|
(defmacro a-false [] False)
|
|
|
|
(assert (= (a-false) False))
|
|
|
|
|
2013-06-05 12:19:06 +02:00
|
|
|
(defmacro a-float [] 42.)
|
|
|
|
(assert (= (a-float) 42.))
|
|
|
|
|
|
|
|
(defmacro a-complex [] 42j)
|
|
|
|
(assert (= (a-complex) 42j))
|
|
|
|
|
|
|
|
(defmacro a-string [] "foo")
|
|
|
|
(assert (= (a-string) "foo"))
|
|
|
|
|
|
|
|
(defmacro a-list [] [1 2])
|
|
|
|
(assert (= (a-list) [1 2]))
|
|
|
|
|
2014-02-19 06:09:37 +01:00
|
|
|
(defmacro a-tuple [&rest b] b)
|
|
|
|
(assert (= (a-tuple 1 2) [1 2]))
|
|
|
|
|
2013-06-05 12:19:06 +02:00
|
|
|
(defmacro a-dict [] {1 2})
|
|
|
|
(assert (= (a-dict) {1 2}))
|
2013-06-02 17:21:03 +02:00
|
|
|
|
2013-12-04 22:59:49 +01:00
|
|
|
(defmacro a-none [])
|
|
|
|
(assert (= (a-none) None))
|
|
|
|
|
2013-06-02 17:21:03 +02:00
|
|
|
; A macro calling a previously defined function
|
|
|
|
(eval-when-compile
|
|
|
|
(defn foo [x y]
|
|
|
|
(quasiquote (+ (unquote x) (unquote y)))))
|
|
|
|
|
|
|
|
(defmacro bar [x y]
|
|
|
|
(foo x y))
|
|
|
|
|
|
|
|
(defn test-fn-calling-macro []
|
|
|
|
"NATIVE: test macro calling a plain function"
|
|
|
|
(assert (= 3 (bar 1 2))))
|
2013-06-05 11:41:58 +02:00
|
|
|
|
2013-07-14 19:03:08 +02:00
|
|
|
(defn test-midtree-yield []
|
|
|
|
"NATIVE: test yielding with a returnable"
|
|
|
|
(defn kruft [] (yield) (+ 1 1)))
|
|
|
|
|
|
|
|
(defn test-midtree-yield-in-for []
|
|
|
|
"NATIVE: test yielding in a for with a return"
|
|
|
|
(defn kruft-in-for []
|
2013-11-10 19:00:01 +01:00
|
|
|
(for* [i (range 5)]
|
2013-07-14 19:03:08 +02:00
|
|
|
(yield i))
|
|
|
|
(+ 1 2)))
|
|
|
|
|
|
|
|
(defn test-midtree-yield-in-while []
|
|
|
|
"NATIVE: test yielding in a while with a return"
|
|
|
|
(defn kruft-in-while []
|
|
|
|
(setv i 0)
|
|
|
|
(while (< i 5)
|
|
|
|
(yield i)
|
|
|
|
(setv i (+ i 1)))
|
|
|
|
(+ 2 3)))
|
|
|
|
|
|
|
|
(defn test-multi-yield []
|
|
|
|
"NATIVE: testing multiple yields"
|
|
|
|
(defn multi-yield []
|
2013-11-10 19:00:01 +01:00
|
|
|
(for* [i (range 3)]
|
2013-07-14 19:03:08 +02:00
|
|
|
(yield i))
|
|
|
|
(yield "a")
|
|
|
|
(yield "end"))
|
|
|
|
(assert (= (list (multi-yield)) [0 1 2 "a" "end"])))
|
|
|
|
|
|
|
|
|
2013-06-05 11:41:58 +02:00
|
|
|
; Macro that checks a variable defined at compile or load time
|
|
|
|
(setv phase "load")
|
|
|
|
(eval-when-compile
|
|
|
|
(setv phase "compile"))
|
|
|
|
(defmacro phase-when-compiling [] phase)
|
|
|
|
(assert (= phase "load"))
|
|
|
|
(assert (= (phase-when-compiling) "compile"))
|
|
|
|
|
2013-06-07 16:30:00 +02:00
|
|
|
(setv initialized False)
|
|
|
|
(eval-and-compile
|
|
|
|
(setv initialized True))
|
|
|
|
(defmacro test-initialized [] initialized)
|
|
|
|
(assert initialized)
|
|
|
|
(assert (test-initialized))
|
|
|
|
|
2013-09-02 09:58:35 +02:00
|
|
|
(defn test-if-python2 []
|
|
|
|
(import sys)
|
|
|
|
(assert (= (get sys.version_info 0)
|
|
|
|
(if-python2 2 3))))
|
2013-12-15 01:33:56 +01:00
|
|
|
|
|
|
|
(defn test-gensym-in-macros []
|
|
|
|
(import ast)
|
|
|
|
(import [astor.codegen [to_source]])
|
|
|
|
(import [hy.importer [import_buffer_to_ast]])
|
|
|
|
(setv macro1 "(defmacro nif [expr pos zero neg]
|
|
|
|
(let [[g (gensym)]]
|
|
|
|
`(let [[~g ~expr]]
|
|
|
|
(cond [(pos? ~g) ~pos]
|
|
|
|
[(zero? ~g) ~zero]
|
|
|
|
[(neg? ~g) ~neg]))))
|
|
|
|
|
|
|
|
(print (nif (inc -1) 1 0 -1))
|
|
|
|
")
|
|
|
|
;; expand the macro twice, should use a different
|
|
|
|
;; gensym each time
|
|
|
|
(setv _ast1 (import_buffer_to_ast macro1 "foo"))
|
|
|
|
(setv _ast2 (import_buffer_to_ast macro1 "foo"))
|
|
|
|
(setv s1 (to_source _ast1))
|
|
|
|
(setv s2 (to_source _ast2))
|
|
|
|
;; and make sure there is something new that starts with :G_
|
|
|
|
(assert (in ":G_" s1))
|
|
|
|
(assert (in ":G_" s2))
|
|
|
|
;; but make sure the two don't match each other
|
|
|
|
(assert (not (= s1 s2))))
|
2013-12-16 02:47:46 +01:00
|
|
|
|
|
|
|
(defn test-with-gensym []
|
|
|
|
(import ast)
|
|
|
|
(import [astor.codegen [to_source]])
|
|
|
|
(import [hy.importer [import_buffer_to_ast]])
|
|
|
|
(setv macro1 "(defmacro nif [expr pos zero neg]
|
|
|
|
(with-gensyms [a]
|
|
|
|
`(let [[~a ~expr]]
|
|
|
|
(cond [(pos? ~a) ~pos]
|
|
|
|
[(zero? ~a) ~zero]
|
|
|
|
[(neg? ~a) ~neg]))))
|
|
|
|
|
|
|
|
(print (nif (inc -1) 1 0 -1))
|
|
|
|
")
|
|
|
|
;; expand the macro twice, should use a different
|
|
|
|
;; gensym each time
|
|
|
|
(setv _ast1 (import_buffer_to_ast macro1 "foo"))
|
|
|
|
(setv _ast2 (import_buffer_to_ast macro1 "foo"))
|
|
|
|
(setv s1 (to_source _ast1))
|
|
|
|
(setv s2 (to_source _ast2))
|
|
|
|
(assert (in ":a_" s1))
|
|
|
|
(assert (in ":a_" s2))
|
|
|
|
(assert (not (= s1 s2))))
|
|
|
|
|
|
|
|
(defn test-defmacro-g! []
|
|
|
|
(import ast)
|
|
|
|
(import [astor.codegen [to_source]])
|
|
|
|
(import [hy.importer [import_buffer_to_ast]])
|
|
|
|
(setv macro1 "(defmacro/g! nif [expr pos zero neg]
|
|
|
|
`(let [[~g!res ~expr]]
|
|
|
|
(cond [(pos? ~g!res) ~pos]
|
|
|
|
[(zero? ~g!res) ~zero]
|
|
|
|
[(neg? ~g!res) ~neg])))
|
|
|
|
|
|
|
|
(print (nif (inc -1) 1 0 -1))
|
|
|
|
")
|
|
|
|
;; expand the macro twice, should use a different
|
|
|
|
;; gensym each time
|
|
|
|
(setv _ast1 (import_buffer_to_ast macro1 "foo"))
|
|
|
|
(setv _ast2 (import_buffer_to_ast macro1 "foo"))
|
|
|
|
(setv s1 (to_source _ast1))
|
|
|
|
(setv s2 (to_source _ast2))
|
|
|
|
(assert (in ":res_" s1))
|
|
|
|
(assert (in ":res_" s2))
|
2014-05-06 20:48:17 +02:00
|
|
|
(assert (not (= s1 s2)))
|
|
|
|
|
|
|
|
;; defmacro/g! didn't like numbers initially because they
|
|
|
|
;; don't have a startswith method and blew up during expansion
|
|
|
|
(setv macro2 "(defmacro/g! two-point-zero [] `(+ (float 1) 1.0))")
|
|
|
|
(assert (import_buffer_to_ast macro2 "foo")))
|
2014-01-18 16:27:26 +01:00
|
|
|
|
2014-01-23 21:57:17 +01:00
|
|
|
|
2014-01-18 16:27:26 +01:00
|
|
|
(defn test-if-not []
|
|
|
|
(assert (= (if-not True :yes :no)
|
|
|
|
:no))
|
|
|
|
(assert (= (if-not False :yes :no)
|
|
|
|
:yes))
|
|
|
|
(assert (nil? (if-not True :yes)))
|
|
|
|
(assert (= (if-not False :yes)
|
|
|
|
:yes)))
|
2014-01-23 21:57:17 +01:00
|
|
|
|
|
|
|
|
2015-08-09 09:21:12 +02:00
|
|
|
(defn test-lif []
|
|
|
|
"test that lif works as expected"
|
2014-02-24 16:39:45 +01:00
|
|
|
; nil is false
|
2015-08-09 09:21:12 +02:00
|
|
|
(assert (= (lif None "true" "false") "false"))
|
|
|
|
(assert (= (lif nil "true" "false") "false"))
|
2014-02-24 16:39:45 +01:00
|
|
|
|
|
|
|
; But everything else is True! Even falsey things.
|
2015-08-09 09:21:12 +02:00
|
|
|
(assert (= (lif True "true" "false") "true"))
|
|
|
|
(assert (= (lif False "true" "false") "true"))
|
|
|
|
(assert (= (lif 0 "true" "false") "true"))
|
|
|
|
(assert (= (lif "some-string" "true" "false") "true"))
|
|
|
|
(assert (= (lif "" "true" "false") "true"))
|
|
|
|
(assert (= (lif (+ 1 2 3) "true" "false") "true"))
|
2014-02-24 16:39:45 +01:00
|
|
|
(assert (= (lif nil "true" "false") "false"))
|
|
|
|
(assert (= (lif 0 "true" "false") "true")))
|
|
|
|
|
2015-08-09 09:21:12 +02:00
|
|
|
(defn test-lif-not []
|
|
|
|
"test that lif-not works as expected"
|
2014-09-10 18:55:11 +02:00
|
|
|
; nil is false
|
2015-08-09 09:21:12 +02:00
|
|
|
(assert (= (lif-not None "false" "true") "false"))
|
|
|
|
(assert (= (lif-not nil "false" "true") "false"))
|
2014-09-10 18:55:11 +02:00
|
|
|
|
|
|
|
; But everything else is True! Even falsey things.
|
2015-08-09 09:21:12 +02:00
|
|
|
(assert (= (lif-not True "false" "true") "true"))
|
|
|
|
(assert (= (lif-not False "false" "true") "true"))
|
|
|
|
(assert (= (lif-not 0 "false" "true") "true"))
|
|
|
|
(assert (= (lif-not "some-string" "false" "true") "true"))
|
|
|
|
(assert (= (lif-not "" "false" "true") "true"))
|
|
|
|
(assert (= (lif-not (+ 1 2 3) "false" "true") "true"))
|
2014-09-10 18:55:11 +02:00
|
|
|
(assert (= (lif-not nil "false" "true") "false"))
|
|
|
|
(assert (= (lif-not 0 "false" "true") "true")))
|
|
|
|
|
2014-02-24 16:39:45 +01:00
|
|
|
|
2014-11-15 14:33:04 +01:00
|
|
|
(defn test-yield-from []
|
2014-11-21 03:39:31 +01:00
|
|
|
"NATIVE: testing yield from"
|
2014-11-15 14:33:04 +01:00
|
|
|
(defn yield-from-test []
|
|
|
|
(for* [i (range 3)]
|
2014-11-21 03:39:31 +01:00
|
|
|
(yield i))
|
|
|
|
(yield-from [1 2 3]))
|
2014-11-15 14:33:04 +01:00
|
|
|
(assert (= (list (yield-from-test)) [0 1 2 1 2 3])))
|
|
|
|
|
2014-11-21 03:40:22 +01:00
|
|
|
(defn test-yield-from-exception-handling []
|
|
|
|
"NATIVE: Ensure exception handling in yield from works right"
|
|
|
|
(defn yield-from-subgenerator-test []
|
|
|
|
(yield 1)
|
|
|
|
(yield 2)
|
|
|
|
(yield 3)
|
|
|
|
(assert 0))
|
|
|
|
(defn yield-from-test []
|
|
|
|
(for* [i (range 3)]
|
|
|
|
(yield i))
|
|
|
|
(try
|
|
|
|
(yield-from (yield-from-subgenerator-test))
|
2015-08-09 08:41:11 +02:00
|
|
|
(except [e AssertionError]
|
2014-11-21 03:40:22 +01:00
|
|
|
(yield 4))))
|
|
|
|
(assert (= (list (yield-from-test)) [0 1 2 1 2 3 4])))
|
|
|
|
|
2015-06-15 21:11:48 +02:00
|
|
|
|
|
|
|
(defn test-defmain []
|
|
|
|
"NATIVE: make sure defmain is clean"
|
|
|
|
(global --name--)
|
|
|
|
(setv oldname --name--)
|
|
|
|
(setv --name-- "__main__")
|
|
|
|
(defn main []
|
|
|
|
(print 'Hy)
|
|
|
|
42)
|
|
|
|
(try
|
|
|
|
(defmain [&rest args]
|
|
|
|
(main))
|
|
|
|
(except [e SystemExit]
|
|
|
|
(assert (= (str e) "42"))))
|
|
|
|
(setv --name-- oldname))
|