Merge branch 'master' into pr/1048

This commit is contained in:
Tuukka Turto 2016-10-20 19:19:21 +03:00
commit 1459eea697
33 changed files with 243 additions and 112 deletions

View File

@ -4,6 +4,8 @@ matrix:
include:
- python: 3.5
env: TOXENV=py35
- python: 3.6-dev
env: TOXENV=py36
env:
- TOXENV=py27
- TOXENV=py33

View File

@ -69,3 +69,4 @@
* Andrew Savchyn <dev@scorpil.com>
* Lev Kravinsky <kravinskylev@gmail.com>
* Luna Lunapiena <lunacodes@gmail.com>
* Jakub Wilk <jwilk@jwilk.net>

View File

@ -7,7 +7,9 @@ helps in making Hy more awesome.
Pull requests are great! We love them; here is a quick guide:
- `Fork the repo`_ and create a topic branch for a feature/fix. Avoid
making changes directly on the master branch.
making changes directly on the master branch. If you would like to
contribute but don't know how to begin, the `good-first-bug`_ label
of the `issue tracker`_ is the place to go.
(If you're new to Git: `Start Here`_)
- All incoming features should be accompanied with tests.
@ -36,7 +38,7 @@ Pull requests are great! We love them; here is a quick guide:
+ Try sticking to the 50 character limit for the first line of Git
commit messages.
+ For more detail/explainations, follow this up with a blank line and
+ For more detail/explanations, follow this up with a blank line and
continue describing the commit in detail.
- Finally, add yourself to the AUTHORS file (as a separate commit): you
@ -93,4 +95,5 @@ http://contributor-covenant.org/version/1/1/0/.
.. _Contributor Covenant: http://contributor-covenant.org
.. _issue tracker: https://github.com/hylang/hy/issues
.. _Fork the Repo: https://help.github.com/articles/fork-a-repo/
.. _Start Here: http://rogerdudler.github.io/git-guide/)
.. _Start Here: http://rogerdudler.github.io/git-guide/
.. _good-first-bug: http://github.com/hylang/hy/issues?q=is%3Aissue+is%3Aopen+label%3Agood-first-bug

View File

@ -23,7 +23,7 @@ all:
@echo ""
docs:
make -C docs html
$(MAKE) -C docs html
upload: r
python setup.py sdist upload
@ -72,10 +72,10 @@ coveralls:
clean:
@find . -name "*.pyc" -exec rm {} \;
@find -name __pycache__ -delete
@find . -name __pycache__ -delete
@${RM} -r -f .tox
@${RM} -r -f dist
@${RM} -r -f *.egg-info
@${RM} -r -f docs/_build
.PHONY: docs
.PHONY: all docs upload full venv dev test tox flake clear d diff r python coveralls clean

2
NEWS
View File

@ -280,7 +280,7 @@ Changes from Hy 0.9.10
* Clarified rest / cdr, cleaned up require
* Make with return the last expression from its branch
* Fix yielding to not suck (#151)
* Make assoc accept multiple values, also added a even/odd check for
* Make assoc accept multiple values, also added an even/odd check for
checkargs
* Added ability to parse doc strings set in defclass declarations,
* Provide bin scripts for both Windows and *nix

View File

@ -6,7 +6,7 @@ Hy
[![Version](https://img.shields.io/pypi/v/hy.svg)](https://pypi.python.org/pypi/hy)
[![Coverage Status](https://img.shields.io/coveralls/hylang/hy/master.svg)](https://coveralls.io/r/hylang/hy)
[![XKCD #224](https://raw.github.com/hylang/shyte/18f6925e08684b0e1f52b2cc2c803989cd62cd91/imgs/xkcd.png)](https://xkcd.com/224/)
<a href="https://xkcd.com/224/"><img title="We lost the documentation on quantum mechanics. You'll have to decode the regexes yourself." alt="XKCD #224" src="https://raw.github.com/hylang/shyte/18f6925e08684b0e1f52b2cc2c803989cd62cd91/imgs/xkcd.png"></a>
Lisp and Python should love each other. Let's make it happen. [Try it](http://try-hy.appspot.com/).

View File

@ -11,7 +11,7 @@ concise and easy to read.
deliberately captures some form supplied to the macro which may be
referred to by an anaphor (an expression referring to another).
-- Wikipedia (http://en.wikipedia.org/wiki/Anaphoric_macro)
-- Wikipedia (https://en.wikipedia.org/wiki/Anaphoric_macro)
To use these macros you need to require the hy.contrib.anaphoric module like so:

View File

@ -7,8 +7,9 @@ Contents:
.. toctree::
:maxdepth: 3
alias
anaphoric
flow
loop
multi
flow
alias
walk

View File

@ -24,7 +24,7 @@ tail-call optimization (TCO) in their Hy code.
position to be implemented as efficiently as goto statements, thus
allowing efficient structured programming.
-- Wikipedia (http://en.wikipedia.org/wiki/Tail_call)
-- Wikipedia (https://en.wikipedia.org/wiki/Tail_call)
Macros
======
@ -39,7 +39,7 @@ rebinds the variables set in the recursion point and sends code
execution back to that recursion point. If ``recur`` is used in a
non-tail position, an exception is raised.
Usage: `(loop bindings &rest body)`
Usage: ``(loop bindings &rest body)``
Example:

94
docs/contrib/walk.rst Normal file
View File

@ -0,0 +1,94 @@
====
walk
====
.. versionadded:: 0.11.0
Functions
=========
.. _walk:
walk
-----
Usage: `(walk inner outer form)`
``walk`` traverses ``form``, an arbitrary data structure. Applies
``inner`` to each element of form, building up a data structure of the
same type. Applies ``outer`` to the result.
Example:
.. code-block:: hy
=> (import [hy.contrib.walk [walk]])
=> (setv a '(a b c d e f))
=> (walk ord identity a)
(97 98 99 100 101 102)
=> (walk ord first a)
97
postwalk
---------
.. _postwalk:
Usage: `(postwalk f form)`
Performs depth-first, post-order traversal of ``form``. Calls ``f`` on
each sub-form, uses ``f`` 's return value in place of the original.
.. code-block:: hy
=> (import [hy.contrib.walk [postwalk]])
=> (def trail '([1 2 3] [4 [5 6 [7]]]))
=> (defn walking [x]
(print "Walking:" x)
x )
=> (postwalk walking trail)
Walking: 1
Walking: 2
Walking: 3
Walking: (1 2 3)
Walking: 4
Walking: 5
Walking: 6
Walking: 7
Walking: (7)
Walking: (5 6 [7])
Walking: (4 [5 6 [7]])
Walking: ([1 2 3] [4 [5 6 [7]]])
([1 2 3] [4 [5 6 [7]]])
prewalk
--------
.. _prewalk:
Usage: `(prewalk f form)`
Performs depth-first, pre-order traversal of ``form``. Calls ``f`` on
each sub-form, uses ``f`` 's return value in place of the original.
.. code-block:: hy
=> (import [hy.contrib.walk [prewalk]])
=> (def trail '([1 2 3] [4 [5 6 [7]]]))
=> (defn walking [x]
(print "Walking:" x)
x )
=> (prewalk walking trail)
Walking: ([1 2 3] [4 [5 6 [7]]])
Walking: [1 2 3]
Walking: 1
Walking: 2
Walking: 3
Walking: [4 [5 6 [7]]]
Walking: 4
Walking: [5 6 [7]]
Walking: 5
Walking: 6
Walking: [7]
Walking: 7
([1 2 3] [4 [5 6 [7]]])

View File

@ -32,7 +32,7 @@ Do this:
$ . venv/bin/activate
or use `virtualenvwrapper <http://virtualenvwrapper.readthedocs.org/en/latest/#introduction>`_
or use `virtualenvwrapper <https://virtualenvwrapper.readthedocs.io/en/latest/#introduction>`_
to create and manage your virtual environment::
$ mkvirtualenv hy
@ -63,7 +63,7 @@ Test!
=====
Tests are located in ``tests/``. We use `nose
<https://nose.readthedocs.org/en/latest/>`_.
<https://nose.readthedocs.io/en/latest/>`_.
To run the tests::

View File

@ -22,7 +22,7 @@ languages.
string. For example, ``foo`` will become ``FOO``.
* UTF-8 entities will be encoded using
`punycode <http://en.wikipedia.org/wiki/Punycode>`_ and prefixed with
`punycode <https://en.wikipedia.org/wiki/Punycode>`_ and prefixed with
``hy_``. For instance, ```` will become ``hy_w7h``, ```` will become
``hy_g6h``, and ``i♥u`` will become ``hy_iu_t0x``.
@ -953,11 +953,20 @@ that ``import`` can be used.
(import [sys :as systest])
;; You can list as many imports as you like of different types.
;;
;; Python:
;; from tests.resources import kwtest, function_with_a_dash
;; from os.path import exists, isdir as is_dir, isfile as is_file
;; import sys as systest
(import [tests.resources [kwtest function-with-a-dash]]
[os.path [exists isdir isfile]]
[os.path [exists
isdir :as dir?
isfile :as file?]]
[sys :as systest])
;; Import all module functions into current namespace
;;
;; Python: from sys import *
(import [sys [*]])

View File

@ -35,7 +35,7 @@ Command Line Options
.. cmdoption:: --spy
Print equivalent Python code before executing. For example::
Print equivalent Python code before executing in REPL. For example::
=> (defn salutationsnm [name] (print (+ "Hy " name "!")))
def salutationsnm(name):
@ -45,6 +45,7 @@ Command Line Options
Hy YourName!
=>
`--spy` only works on REPL mode.
.. versionadded:: 0.9.11
.. cmdoption:: --show-tracebacks

View File

@ -141,7 +141,7 @@ is ``True``, the function prints Python code instead.
print('Hello World!')
.. _emtpy?-fn:
.. _empty?-fn:
empty?
------

View File

@ -170,7 +170,7 @@ Cons Cells
cells`_. Cons cells are especially useful to mimic features of "usual"
LISP variants such as Scheme or Common Lisp.
.. _cons cells: http://en.wikipedia.org/wiki/Cons
.. _cons cells: https://en.wikipedia.org/wiki/Cons
A cons cell is a 2-item object, containing a ``car`` (head) and a
``cdr`` (tail). In some Lisp variants, the cons cell is the fundamental

View File

@ -13,7 +13,7 @@ Quickstart
1. Create a `Virtual Python Environment
<https://pypi.python.org/pypi/virtualenv>`_.
2. Activate your Virtual Python Environment.
3. Install `hy from PyPI <https://pypi.python.org/pypi/hy>`_ with ``pip install hy``.
3. Install `hy from GitHub <https://github.com/hylang/hy>`_ with ``$ pip install git+https://github.com/hylang/hy.git``.
4. Start a REPL with ``hy``.
5. Type stuff in the REPL::

View File

@ -105,7 +105,7 @@ Layout & Indentation
.. code-block:: clj
(let [foo (bar)]
(let [foo (bar)
qux (baz)]
(foo qux))

View File

@ -267,7 +267,7 @@ In Hy, you would do:
[true
(print "That variable is jussssst right!")])
What you'll notice is that ``cond`` switches off between a some statement
What you'll notice is that ``cond`` switches off between a statement
that is executed and checked conditionally for true or falseness, and
then a bit of code to execute if it turns out to be true. You'll also
notice that the ``else`` is implemented at the end simply by checking
@ -292,7 +292,7 @@ You can do the following:
(if (try-some-thing)
(do
(print "this is if true")
(print "and why not, let's keep talking about how true it is!))
(print "and why not, let's keep talking about how true it is!"))
(print "this one's still simply just false"))
You can see that we used ``do`` to wrap multiple statements. If you're

View File

@ -274,7 +274,7 @@ def cmdline_handler(scriptname, argv):
parser.add_argument("--spy", action="store_true",
help="print equivalent Python code before executing")
parser.add_argument("-v", action="version", version=VERSION)
parser.add_argument("-v", "--version", action="version", version=VERSION)
parser.add_argument("--show-tracebacks", action="store_true",
help="show complete tracebacks for Hy exceptions")

View File

@ -503,19 +503,13 @@ class HyASTCompiler(object):
for expr in exprs:
if expr in ll_keywords:
if expr == "&rest" and lambda_keyword is None:
lambda_keyword = expr
elif expr == "&optional":
if expr == "&optional":
if len(defaults) > 0:
raise HyTypeError(expr,
"There can only be &optional "
"arguments or one &key argument")
lambda_keyword = expr
elif expr == "&key":
lambda_keyword = expr
elif expr == "&kwonly":
lambda_keyword = expr
elif expr == "&kwargs":
elif expr in ("&rest", "&key", "&kwonly", "&kwargs"):
lambda_keyword = expr
else:
raise HyTypeError(expr,
@ -1516,7 +1510,8 @@ class HyASTCompiler(object):
gen.append(ast.comprehension(
target=target,
iter=gen_res.force_expr,
ifs=[]))
ifs=[],
is_async=False))
if cond.expr:
gen[-1].ifs.append(cond.expr)
@ -1910,7 +1905,6 @@ class HyASTCompiler(object):
col_offset=child.start_column)
return ret
@builds("+")
@builds("*")
@builds("/")
@builds("//")
@ -1918,8 +1912,7 @@ class HyASTCompiler(object):
if len(expression) > 2:
return self.compile_maths_expression(expression)
else:
id_op = {"+": HyInteger(0), "*": HyInteger(1), "/": HyInteger(1),
"//": HyInteger(1)}
id_op = {"*": HyInteger(1), "/": HyInteger(1), "//": HyInteger(1)}
op = expression.pop(0)
arg = expression.pop(0) if expression else id_op[op]
@ -1930,20 +1923,34 @@ class HyASTCompiler(object):
]).replace(expression)
return self.compile_maths_expression(expr)
@builds("-")
@checkargs(min=1)
def compile_maths_expression_sub(self, expression):
def compile_maths_expression_additive(self, expression):
if len(expression) > 2:
return self.compile_maths_expression(expression)
else:
arg = expression[1]
op = {"+": ast.UAdd, "-": ast.USub}[expression.pop(0)]()
arg = expression.pop(0)
ret = self.compile(arg)
ret += ast.UnaryOp(op=ast.USub(),
ret += ast.UnaryOp(op=op,
operand=ret.force_expr,
lineno=arg.start_line,
col_offset=arg.start_column)
return ret
@builds("+")
def compile_maths_expression_add(self, expression):
if len(expression) == 1:
# Nullary +
return ast.Num(n=long_type(0),
lineno=expression.start_line,
col_offset=expression.start_column)
else:
return self.compile_maths_expression_additive(expression)
@builds("-")
@checkargs(min=1)
def compile_maths_expression_sub(self, expression):
return self.compile_maths_expression_additive(expression)
@builds("+=")
@builds("/=")
@builds("//=")
@ -2449,6 +2456,9 @@ class HyASTCompiler(object):
raise HyTypeError(name, ("received a `%s' instead of a symbol "
"for macro name" % type(name).__name__))
name = HyString(name).replace(name)
for kw in ("&kwonly", "&kwargs", "&key"):
if kw in expression[0]:
raise HyTypeError(name, "macros cannot use %s" % kw)
new_expression = HyExpression([
HySymbol("with_decorator"),
HyExpression([HySymbol("hy.macros.macro"), name]),

View File

@ -39,10 +39,6 @@
(import [hy.lex [LexException PrematureEndOfInput tokenize]])
(import [hy.compiler [HyASTCompiler]])
(defn _numeric-check [x]
(if (not (numeric? x))
(raise (TypeError (.format "{0!r} is not a number" x)))))
(defn butlast [coll]
"Returns coll except of last element."
(drop-last 1 coll))
@ -66,7 +62,6 @@
(defn dec [n]
"Decrement n by 1"
(_numeric-check n)
(- n 1))
(defn disassemble [tree &optional [codegen false]]
@ -170,7 +165,6 @@
(defn even? [n]
"Return true if n is an even number"
(_numeric-check n)
(= (% n 2) 0))
(defn every? [pred coll]
@ -239,7 +233,6 @@
(defn inc [n]
"Increment n by 1"
(_numeric-check n)
(+ n 1))
(defn instance? [klass x]
@ -325,7 +318,6 @@
(defn neg? [n]
"Return true if n is < 0"
(_numeric-check n)
(< n 0))
(defn none? [x]
@ -347,7 +339,6 @@
(defn odd? [n]
"Return true if n is an odd number"
(_numeric-check n)
(= (% n 2) 1))
(def -sentinel (object))
@ -364,7 +355,6 @@
(defn pos? [n]
"Return true if n is > 0"
(_numeric_check n)
(> n 0))
(defn rest [coll]
@ -415,7 +405,6 @@
(defn zero? [n]
"Return true if n is 0"
(_numeric_check n)
(= n 0))
(defn read [&optional [from-file sys.stdin]

View File

@ -30,7 +30,7 @@
(if (zero? count)
(raise (TypeError "Need at least 1 argument to add/concatenate"))
(if (= count 1)
(get args 0)
(operator.pos (get args 0))
(reduce operator.add args)))))

View File

@ -45,12 +45,12 @@ def ast_compile(ast, filename, mode):
def import_buffer_to_hst(buf):
"""Import content from buf and return an Hy AST."""
"""Import content from buf and return a Hy AST."""
return tokenize(buf + "\n")
def import_file_to_hst(fpath):
"""Import content from fpath and return an Hy AST."""
"""Import content from fpath and return a Hy AST."""
try:
with open(fpath, 'r', encoding='utf-8') as f:
return import_buffer_to_hst(f.read())

View File

@ -18,19 +18,16 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
from hy.models import _wrappers, wrap_value
from hy.models.list import HyList
from functools import reduce
class HySet(HyList):
"""
Hy set (actually a list that pretends to be a set)
Hy set (just a representation of a set)
"""
def __init__(self, items):
items = sorted(items)
items = list(reduce(lambda r, v: v in r and r or r+[v], items, []))
super(HySet, self).__init__(items)
def __repr__(self):
return "#{%s}" % (" ".join([repr(x) for x in self]))
_wrappers[set] = lambda s: HySet(wrap_value(x) for x in s)

View File

@ -397,6 +397,7 @@ def test_lambda_list_keywords_rest():
""" Ensure we can compile functions with lambda list keywords."""
can_compile("(fn (x &rest xs) (print xs))")
cant_compile("(fn (x &rest xs &rest ys) (print xs))")
can_compile("(fn (&optional a &rest xs) (print xs))")
def test_lambda_list_keywords_key():
@ -410,6 +411,7 @@ def test_lambda_list_keywords_kwargs():
""" Ensure we can compile functions with &kwargs."""
can_compile("(fn (x &kwargs kw) (list x kw))")
cant_compile("(fn (x &kwargs xs &kwargs ys) (list x xs ys))")
can_compile("(fn (&optional x &kwargs kw) (list x kw))")
def test_lambda_list_keywords_kwonly():

View File

@ -230,6 +230,16 @@ def test_sets():
HyExpression([HySymbol("baz"), HySymbol("quux")])
])]
# Duplicate items in a literal set should be okay (and should
# be preserved).
objs = tokenize("#{1 2 1 1 2 1}")
assert objs == [HySet([HyInteger(n) for n in [1, 2, 1, 1, 2, 1]])]
assert len(objs[0]) == 6
# https://github.com/hylang/hy/issues/1120
objs = tokenize("#{a 1}")
assert objs == [HySet([HySymbol("a"), HyInteger(1)])]
def test_nospace():
""" Ensure we can tokenize without spaces if we have to """

View File

@ -5,4 +5,4 @@ hyset = HySet([3, 1, 2, 2])
def test_set():
assert hyset == [1, 2, 3]
assert hyset == [3, 1, 2, 2]

View File

@ -19,6 +19,8 @@
;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
;; DEALINGS IN THE SOFTWARE.
(import [hy._compat [PY3]])
;;;; some simple helpers
(defn assert-true [x]
@ -33,6 +35,12 @@
(defn assert-nil [x]
(assert (is x nil)))
(defn assert-requires-num [f]
(for [x ["foo" [] None]]
(try (f x)
(except [TypeError] True)
(else (assert False)))))
(defn test-coll? []
"NATIVE: testing coll?"
(assert-true (coll? [1 2 3]))
@ -66,12 +74,7 @@
(assert-equal 0 (dec 1))
(assert-equal -1 (dec 0))
(assert-equal 0 (dec (dec 2)))
(try (do (dec "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (dec []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (dec None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num dec))
(defn test-setv []
"NATIVE: testing setv mutation"
@ -173,12 +176,7 @@
(assert-true (even? -2))
(assert-false (even? 1))
(assert-true (even? 0))
(try (even? "foo")
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (even? [])
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (even? None)
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num even?))
(defn test-every? []
"NATIVE: testing the every? function"
@ -263,12 +261,11 @@
"NATIVE: testing the inc function"
(assert-equal 3 (inc 2))
(assert-equal 0 (inc -1))
(try (do (inc "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (inc []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (inc None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num inc)
(defclass X [object]
[__add__ (fn [self other] (.format "__add__ got {}" other))])
(assert-equal (inc (X)) "__add__ got 1"))
(defn test-instance []
"NATIVE: testing instance? function"
@ -394,24 +391,14 @@
(assert-true (neg? -2))
(assert-false (neg? 1))
(assert-false (neg? 0))
(try (do (neg? "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (neg? []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (neg? None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(when PY3
(assert-requires-num neg?)))
(defn test-zero []
"NATIVE: testing the zero? function"
(assert-false (zero? -2))
(assert-false (zero? 1))
(assert-true (zero? 0))
(try (do (zero? "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (zero? []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (zero? None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-true (zero? 0)))
(defn test-none []
"NATIVE: testing for `is None`"
@ -463,12 +450,7 @@
(assert-true (odd? -3))
(assert-true (odd? 1))
(assert-false (odd? 0))
(try (do (odd? "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (odd? []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (odd? None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(assert-requires-num odd?))
(defn test-partition []
"NATIVE: testing the partition function"
@ -500,12 +482,8 @@
(assert-true (pos? 2))
(assert-false (pos? -1))
(assert-false (pos? 0))
(try (do (pos? "foo") (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (pos? []) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e)))))
(try (do (pos? None) (assert False))
(except [e [TypeError]] (assert (in "not a number" (str e))))))
(when PY3
(assert-requires-num pos?)))
(defn test-remove []
"NATIVE: testing the remove function"

View File

@ -47,6 +47,7 @@
(defn test-sets []
"NATIVE: test sets work right"
(assert (= #{1 2 3 4} (| #{1 2} #{3 4})))
(assert (= (type #{1 2 3 4}) set))
(assert (= #{} (set))))

View File

@ -28,6 +28,18 @@
(assert (= 0 (+)))))
(defn test-add-unary []
"NATIVE: test that unary + calls __pos__"
(defclass X [object]
[__pos__ (fn [self] "called __pos__")])
(assert (= (+ (X)) "called __pos__"))
; Make sure the shadowed version works, too.
(setv f +)
(assert (= (f (X)) "called __pos__")))
(setv test_div (fn []
"NATIVE: Test division"
(assert (= 25 (/ 100 2 2)))

View File

@ -1,3 +1,5 @@
(import [hy.errors [HyTypeError]])
(defmacro rev [&rest body]
"Execute the `body` statements in reverse"
(quasiquote (do (unquote-splice (list (reversed body))))))
@ -37,6 +39,9 @@
(defmacro a-dict [] {1 2})
(assert (= (a-dict) {1 2}))
(defmacro a-set [] #{1 2})
(assert (= (a-set) #{1 2}))
(defmacro a-none [])
(assert (= (a-none) None))
@ -48,6 +53,26 @@
(defmacro bar [x y]
(foo x y))
(defn test-macro-kw []
"NATIVE: test that an error is raised when &kwonly, &kwargs, or &key is used in a macro"
(try
(eval '(defmacro f [&kwonly a b]))
(except [e HyTypeError]
(assert (= e.message "macros cannot use &kwonly")))
(else (assert false)))
(try
(eval '(defmacro f [&kwargs kw]))
(except [e HyTypeError]
(assert (= e.message "macros cannot use &kwargs")))
(else (assert false)))
(try
(eval '(defmacro f [&key {"kw" "xyz"}]))
(except [e HyTypeError]
(assert (= e.message "macros cannot use &key")))
(else (assert false))))
(defn test-fn-calling-macro []
"NATIVE: test macro calling a plain function"
(assert (= 3 (bar 1 2))))

View File

@ -8,13 +8,9 @@
(assert (= (x 1 2 3 4) 10))
(assert (= (x 1 2 3 4 5) 15))
; with strings
(assert (= (x "a")
"a"))
(assert (= (x "a" "b" "c")
"abc"))
; with lists
(assert (= (x ["a"])
["a"]))
(assert (= (x ["a"] ["b"] ["c"])
["a" "b" "c"]))))

View File

@ -1,5 +1,5 @@
[tox]
envlist = py27,pypy,py33,py34,py35,flake8
envlist = py27,pypy,py33,py34,py35,py36,flake8
skipsdist = True
[testenv]