Merge branch 'master' into pr/1048
This commit is contained in:
commit
1459eea697
@ -4,6 +4,8 @@ matrix:
|
||||
include:
|
||||
- python: 3.5
|
||||
env: TOXENV=py35
|
||||
- python: 3.6-dev
|
||||
env: TOXENV=py36
|
||||
env:
|
||||
- TOXENV=py27
|
||||
- TOXENV=py33
|
||||
|
1
AUTHORS
1
AUTHORS
@ -69,3 +69,4 @@
|
||||
* Andrew Savchyn <dev@scorpil.com>
|
||||
* Lev Kravinsky <kravinskylev@gmail.com>
|
||||
* Luna Lunapiena <lunacodes@gmail.com>
|
||||
* Jakub Wilk <jwilk@jwilk.net>
|
||||
|
@ -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
|
||||
|
6
Makefile
6
Makefile
@ -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
2
NEWS
@ -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
|
||||
|
@ -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/).
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -7,8 +7,9 @@ Contents:
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
alias
|
||||
anaphoric
|
||||
flow
|
||||
loop
|
||||
multi
|
||||
flow
|
||||
alias
|
||||
walk
|
||||
|
@ -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
94
docs/contrib/walk.rst
Normal 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]]])
|
@ -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::
|
||||
|
||||
|
@ -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 [*]])
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -141,7 +141,7 @@ is ``True``, the function prints Python code instead.
|
||||
print('Hello World!')
|
||||
|
||||
|
||||
.. _emtpy?-fn:
|
||||
.. _empty?-fn:
|
||||
|
||||
empty?
|
||||
------
|
||||
|
@ -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
|
||||
|
@ -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::
|
||||
|
||||
|
@ -105,7 +105,7 @@ Layout & Indentation
|
||||
|
||||
.. code-block:: clj
|
||||
|
||||
(let [foo (bar)]
|
||||
(let [foo (bar)
|
||||
qux (baz)]
|
||||
(foo qux))
|
||||
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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]),
|
||||
|
@ -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]
|
||||
|
@ -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)))))
|
||||
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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)
|
||||
|
@ -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():
|
||||
|
@ -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 """
|
||||
|
@ -5,4 +5,4 @@ hyset = HySet([3, 1, 2, 2])
|
||||
|
||||
|
||||
def test_set():
|
||||
assert hyset == [1, 2, 3]
|
||||
assert hyset == [3, 1, 2, 2]
|
||||
|
@ -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"
|
||||
|
@ -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))))
|
||||
|
||||
|
||||
|
@ -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)))
|
||||
|
@ -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))))
|
||||
|
@ -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"]))))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user