2018-01-01 16:38:33 +01:00
|
|
|
;; Copyright 2018 the authors.
|
2017-04-27 23:16:57 +02:00
|
|
|
;; This file is part of Hy, which is free software licensed under the Expat
|
|
|
|
;; license. See the LICENSE.
|
|
|
|
|
2015-07-26 23:19:10 +02:00
|
|
|
(import [functools [wraps]])
|
|
|
|
|
|
|
|
|
2017-06-21 05:48:54 +02:00
|
|
|
(defn test-tag-macro []
|
|
|
|
"Test a basic tag macro"
|
|
|
|
(deftag ^ [expr]
|
2013-12-15 17:47:24 +01:00
|
|
|
expr)
|
|
|
|
|
|
|
|
(assert (= #^"works" "works")))
|
|
|
|
|
|
|
|
|
2017-06-22 19:09:01 +02:00
|
|
|
(defn test-long-tag-macro []
|
|
|
|
"Test a tag macro with a name longer than one character"
|
|
|
|
(deftag foo [expr]
|
|
|
|
`['foo ~expr])
|
|
|
|
(assert (= #foo'bar ['foo 'bar]))
|
|
|
|
(assert (= #foo"baz" ['foo "baz"]))
|
|
|
|
(assert (= #foo(- 44 2) ['foo 42]))
|
|
|
|
(assert (= #foo(, 42) ['foo (, 42)]))
|
|
|
|
(assert (= #foo[42] ['foo [42]]))
|
|
|
|
(assert (= #foo{4 2} ['foo {4 2}])))
|
|
|
|
|
|
|
|
(defn test-hyphenated-tag-macro []
|
|
|
|
"Test if hyphens translate properly"
|
|
|
|
(deftag foo-bar [x]
|
|
|
|
`['foo ~x 'bar])
|
|
|
|
(assert (= #foo-bar 42) ['foo 42 'bar])
|
|
|
|
(assert (= #foo_bar 42) ['foo 42 'bar])
|
|
|
|
(deftag spam_eggs [x]
|
|
|
|
`['spam ~x 'eggs])
|
|
|
|
(assert (= #spam-eggs 42 ['spam 42 'eggs]))
|
|
|
|
(assert (= #spam_eggs 42 ['spam 42 'eggs])))
|
|
|
|
|
|
|
|
|
2017-07-23 20:43:19 +02:00
|
|
|
(defn test-bang-tag-macro []
|
|
|
|
"Test tag macros whose names start with `!`"
|
|
|
|
; https://github.com/hylang/hy/issues/1334
|
|
|
|
(deftag !a [x] `["foo" ~x])
|
|
|
|
(assert (= #!a 3 ["foo" 3]))
|
|
|
|
(deftag ! [x] `["bar" ~x])
|
|
|
|
(assert (= #! 4 ["bar" 4])))
|
|
|
|
|
|
|
|
|
2017-06-22 19:09:01 +02:00
|
|
|
(defn test-tag-macro-whitespace []
|
|
|
|
"Test whitespace after a tag macro"
|
|
|
|
(deftag foo [expr]
|
|
|
|
`['foo ~expr])
|
|
|
|
(assert (= #foo 42) ['foo 42])
|
|
|
|
(assert (= #foo (- 44 2) ['foo 42]))
|
|
|
|
(deftag b [x]
|
|
|
|
`['bar ~x])
|
|
|
|
(assert (= #b 42) ['bar 42])
|
|
|
|
; # is allowed in tags, so this must be separated
|
|
|
|
(assert (= #b #{42} ['bar #{42}]))
|
|
|
|
; multiple tags must likewise be separated
|
|
|
|
(assert (= #b #foo 42 ['bar ['foo 42]]))
|
|
|
|
; newlines are also whitespace
|
|
|
|
(assert (= #foo
|
|
|
|
|
|
|
|
42 ['foo 42]))
|
|
|
|
(assert (= #foo; a semicolon/comment should count as whitespace
|
|
|
|
42
|
|
|
|
['foo 42])))
|
|
|
|
|
|
|
|
|
2017-06-21 05:48:54 +02:00
|
|
|
(defn test-tag-macro-expr []
|
2013-12-15 17:47:24 +01:00
|
|
|
"Test basic exprs like lists and arrays"
|
2017-06-21 05:48:54 +02:00
|
|
|
(deftag n [expr]
|
2013-12-15 17:47:24 +01:00
|
|
|
(get expr 1))
|
|
|
|
|
|
|
|
(assert (= #n[1 2] 2))
|
|
|
|
(assert (= #n(1 2) 2)))
|
|
|
|
|
|
|
|
|
2017-06-21 05:48:54 +02:00
|
|
|
(defn test-tag-macro-override []
|
2013-12-15 17:47:24 +01:00
|
|
|
"Test if we can override function symbols"
|
2017-06-21 05:48:54 +02:00
|
|
|
(deftag + [n]
|
2013-12-15 17:47:24 +01:00
|
|
|
(+ n 1))
|
|
|
|
|
2018-02-28 01:21:42 +01:00
|
|
|
(assert (= #+ 2 3)))
|
2013-12-15 17:47:24 +01:00
|
|
|
|
|
|
|
|
2017-06-21 05:48:54 +02:00
|
|
|
(defn test-tag-macros-macros []
|
|
|
|
"Test if deftag is actually a macro"
|
|
|
|
(deftag t [expr]
|
2014-01-14 02:38:16 +01:00
|
|
|
`(, ~@expr))
|
|
|
|
|
2018-01-05 21:51:00 +01:00
|
|
|
(setv a #t[1 2 3])
|
2014-01-14 02:38:16 +01:00
|
|
|
|
|
|
|
(assert (= (type a) tuple))
|
|
|
|
(assert (= (, 1 2 3) a)))
|
|
|
|
|
|
|
|
|
2017-06-21 05:48:54 +02:00
|
|
|
(defn test-tag-macro-string-name []
|
|
|
|
"Test if deftag accepts a string as a macro name."
|
2015-12-17 12:59:33 +01:00
|
|
|
|
2017-06-21 05:48:54 +02:00
|
|
|
(deftag "." [expr]
|
2015-12-17 12:59:33 +01:00
|
|
|
expr)
|
|
|
|
|
|
|
|
(assert (= #."works" "works")))
|
|
|
|
|
|
|
|
|
2017-06-21 05:48:54 +02:00
|
|
|
(defn test-builtin-decorator-tag []
|
2015-07-26 23:19:10 +02:00
|
|
|
(defn increment-arguments [func]
|
|
|
|
"Increments each argument passed to the decorated function."
|
2017-03-23 23:11:55 +01:00
|
|
|
((wraps func)
|
|
|
|
(fn [&rest args &kwargs kwargs]
|
2017-07-16 01:54:43 +02:00
|
|
|
(func #* (map inc args)
|
|
|
|
#** (dict-comp k (inc v) [[k v] (.items kwargs)])))))
|
2015-07-26 23:19:10 +02:00
|
|
|
|
|
|
|
#@(increment-arguments
|
|
|
|
(defn foo [&rest args &kwargs kwargs]
|
|
|
|
"Bar."
|
|
|
|
(, args kwargs)))
|
|
|
|
|
|
|
|
;; The decorator did what it was supposed to
|
|
|
|
(assert (= (, (, 2 3 4) {"quux" 5 "baz" 6})
|
|
|
|
(foo 1 2 3 :quux 4 :baz 5)))
|
|
|
|
|
2015-12-08 14:43:47 +01:00
|
|
|
;; @wraps preserved the docstring and __name__
|
2015-07-26 23:19:10 +02:00
|
|
|
(assert (= "foo" (. foo --name--)))
|
|
|
|
(assert (= "Bar." (. foo --doc--)))
|
|
|
|
|
2017-06-21 05:48:54 +02:00
|
|
|
;; We can use the #@ tag macro to apply more than one decorator
|
2015-07-26 23:19:10 +02:00
|
|
|
#@(increment-arguments
|
|
|
|
increment-arguments
|
|
|
|
(defn double-foo [&rest args &kwargs kwargs]
|
|
|
|
"Bar."
|
|
|
|
(, args kwargs)))
|
|
|
|
|
|
|
|
(assert (= (, (, 3 4 5) {"quux" 6 "baz" 7})
|
|
|
|
(double-foo 1 2 3 :quux 4 :baz 5))))
|