Merge branch 'master' into pr/1081
This commit is contained in:
commit
d969ed63d6
@ -4,6 +4,8 @@ matrix:
|
|||||||
include:
|
include:
|
||||||
- python: 3.5
|
- python: 3.5
|
||||||
env: TOXENV=py35
|
env: TOXENV=py35
|
||||||
|
- python: 3.6-dev
|
||||||
|
env: TOXENV=py36
|
||||||
env:
|
env:
|
||||||
- TOXENV=py27
|
- TOXENV=py27
|
||||||
- TOXENV=py33
|
- TOXENV=py33
|
||||||
|
@ -7,7 +7,9 @@ helps in making Hy more awesome.
|
|||||||
Pull requests are great! We love them; here is a quick guide:
|
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
|
- `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`_)
|
(If you're new to Git: `Start Here`_)
|
||||||
|
|
||||||
- All incoming features should be accompanied with tests.
|
- All incoming features should be accompanied with tests.
|
||||||
@ -93,4 +95,5 @@ http://contributor-covenant.org/version/1/1/0/.
|
|||||||
.. _Contributor Covenant: http://contributor-covenant.org
|
.. _Contributor Covenant: http://contributor-covenant.org
|
||||||
.. _issue tracker: https://github.com/hylang/hy/issues
|
.. _issue tracker: https://github.com/hylang/hy/issues
|
||||||
.. _Fork the Repo: https://help.github.com/articles/fork-a-repo/
|
.. _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 ""
|
@echo ""
|
||||||
|
|
||||||
docs:
|
docs:
|
||||||
make -C docs html
|
$(MAKE) -C docs html
|
||||||
|
|
||||||
upload: r
|
upload: r
|
||||||
python setup.py sdist upload
|
python setup.py sdist upload
|
||||||
@ -72,10 +72,10 @@ coveralls:
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
@find . -name "*.pyc" -exec rm {} \;
|
@find . -name "*.pyc" -exec rm {} \;
|
||||||
@find -name __pycache__ -delete
|
@find . -name __pycache__ -delete
|
||||||
@${RM} -r -f .tox
|
@${RM} -r -f .tox
|
||||||
@${RM} -r -f dist
|
@${RM} -r -f dist
|
||||||
@${RM} -r -f *.egg-info
|
@${RM} -r -f *.egg-info
|
||||||
@${RM} -r -f docs/_build
|
@${RM} -r -f docs/_build
|
||||||
|
|
||||||
.PHONY: docs
|
.PHONY: all docs upload full venv dev test tox flake clear d diff r python coveralls clean
|
||||||
|
@ -11,7 +11,7 @@ concise and easy to read.
|
|||||||
deliberately captures some form supplied to the macro which may be
|
deliberately captures some form supplied to the macro which may be
|
||||||
referred to by an anaphor (an expression referring to another).
|
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:
|
To use these macros you need to require the hy.contrib.anaphoric module like so:
|
||||||
|
|
||||||
|
@ -7,8 +7,9 @@ Contents:
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 3
|
:maxdepth: 3
|
||||||
|
|
||||||
|
alias
|
||||||
anaphoric
|
anaphoric
|
||||||
|
flow
|
||||||
loop
|
loop
|
||||||
multi
|
multi
|
||||||
flow
|
walk
|
||||||
alias
|
|
||||||
|
@ -24,7 +24,7 @@ tail-call optimization (TCO) in their Hy code.
|
|||||||
position to be implemented as efficiently as goto statements, thus
|
position to be implemented as efficiently as goto statements, thus
|
||||||
allowing efficient structured programming.
|
allowing efficient structured programming.
|
||||||
|
|
||||||
-- Wikipedia (http://en.wikipedia.org/wiki/Tail_call)
|
-- Wikipedia (https://en.wikipedia.org/wiki/Tail_call)
|
||||||
|
|
||||||
Macros
|
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
|
execution back to that recursion point. If ``recur`` is used in a
|
||||||
non-tail position, an exception is raised.
|
non-tail position, an exception is raised.
|
||||||
|
|
||||||
Usage: `(loop bindings &rest body)`
|
Usage: ``(loop bindings &rest body)``
|
||||||
|
|
||||||
Example:
|
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]]])
|
@ -22,7 +22,7 @@ languages.
|
|||||||
string. For example, ``foo`` will become ``FOO``.
|
string. For example, ``foo`` will become ``FOO``.
|
||||||
|
|
||||||
* UTF-8 entities will be encoded using
|
* 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_``. For instance, ``⚘`` will become ``hy_w7h``, ``♥`` will become
|
||||||
``hy_g6h``, and ``i♥u`` will become ``hy_iu_t0x``.
|
``hy_g6h``, and ``i♥u`` will become ``hy_iu_t0x``.
|
||||||
|
|
||||||
@ -953,11 +953,20 @@ that ``import`` can be used.
|
|||||||
(import [sys :as systest])
|
(import [sys :as systest])
|
||||||
|
|
||||||
;; You can list as many imports as you like of different types.
|
;; 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]]
|
(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])
|
[sys :as systest])
|
||||||
|
|
||||||
;; Import all module functions into current namespace
|
;; Import all module functions into current namespace
|
||||||
|
;;
|
||||||
|
;; Python: from sys import *
|
||||||
(import [sys [*]])
|
(import [sys [*]])
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ Command Line Options
|
|||||||
|
|
||||||
.. cmdoption:: --spy
|
.. 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 "!")))
|
=> (defn salutationsnm [name] (print (+ "Hy " name "!")))
|
||||||
def salutationsnm(name):
|
def salutationsnm(name):
|
||||||
@ -45,6 +45,7 @@ Command Line Options
|
|||||||
Hy YourName!
|
Hy YourName!
|
||||||
=>
|
=>
|
||||||
|
|
||||||
|
`--spy` only works on REPL mode.
|
||||||
.. versionadded:: 0.9.11
|
.. versionadded:: 0.9.11
|
||||||
|
|
||||||
.. cmdoption:: --show-tracebacks
|
.. cmdoption:: --show-tracebacks
|
||||||
|
@ -170,7 +170,7 @@ Cons Cells
|
|||||||
cells`_. Cons cells are especially useful to mimic features of "usual"
|
cells`_. Cons cells are especially useful to mimic features of "usual"
|
||||||
LISP variants such as Scheme or Common Lisp.
|
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
|
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
|
``cdr`` (tail). In some Lisp variants, the cons cell is the fundamental
|
||||||
|
@ -13,7 +13,7 @@ Quickstart
|
|||||||
1. Create a `Virtual Python Environment
|
1. Create a `Virtual Python Environment
|
||||||
<https://pypi.python.org/pypi/virtualenv>`_.
|
<https://pypi.python.org/pypi/virtualenv>`_.
|
||||||
2. Activate your Virtual Python Environment.
|
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``.
|
4. Start a REPL with ``hy``.
|
||||||
5. Type stuff in the REPL::
|
5. Type stuff in the REPL::
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ You can do the following:
|
|||||||
(if (try-some-thing)
|
(if (try-some-thing)
|
||||||
(do
|
(do
|
||||||
(print "this is if true")
|
(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"))
|
(print "this one's still simply just false"))
|
||||||
|
|
||||||
You can see that we used ``do`` to wrap multiple statements. If you're
|
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",
|
parser.add_argument("--spy", action="store_true",
|
||||||
help="print equivalent Python code before executing")
|
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",
|
parser.add_argument("--show-tracebacks", action="store_true",
|
||||||
help="show complete tracebacks for Hy exceptions")
|
help="show complete tracebacks for Hy exceptions")
|
||||||
|
@ -503,19 +503,13 @@ class HyASTCompiler(object):
|
|||||||
for expr in exprs:
|
for expr in exprs:
|
||||||
|
|
||||||
if expr in ll_keywords:
|
if expr in ll_keywords:
|
||||||
if expr == "&rest" and lambda_keyword is None:
|
if expr == "&optional":
|
||||||
lambda_keyword = expr
|
|
||||||
elif expr == "&optional":
|
|
||||||
if len(defaults) > 0:
|
if len(defaults) > 0:
|
||||||
raise HyTypeError(expr,
|
raise HyTypeError(expr,
|
||||||
"There can only be &optional "
|
"There can only be &optional "
|
||||||
"arguments or one &key argument")
|
"arguments or one &key argument")
|
||||||
lambda_keyword = expr
|
lambda_keyword = expr
|
||||||
elif expr == "&key":
|
elif expr in ("&rest", "&key", "&kwonly", "&kwargs"):
|
||||||
lambda_keyword = expr
|
|
||||||
elif expr == "&kwonly":
|
|
||||||
lambda_keyword = expr
|
|
||||||
elif expr == "&kwargs":
|
|
||||||
lambda_keyword = expr
|
lambda_keyword = expr
|
||||||
else:
|
else:
|
||||||
raise HyTypeError(expr,
|
raise HyTypeError(expr,
|
||||||
@ -1516,7 +1510,8 @@ class HyASTCompiler(object):
|
|||||||
gen.append(ast.comprehension(
|
gen.append(ast.comprehension(
|
||||||
target=target,
|
target=target,
|
||||||
iter=gen_res.force_expr,
|
iter=gen_res.force_expr,
|
||||||
ifs=[]))
|
ifs=[],
|
||||||
|
is_async=False))
|
||||||
|
|
||||||
if cond.expr:
|
if cond.expr:
|
||||||
gen[-1].ifs.append(cond.expr)
|
gen[-1].ifs.append(cond.expr)
|
||||||
@ -1910,7 +1905,6 @@ class HyASTCompiler(object):
|
|||||||
col_offset=child.start_column)
|
col_offset=child.start_column)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@builds("+")
|
|
||||||
@builds("*")
|
@builds("*")
|
||||||
@builds("/")
|
@builds("/")
|
||||||
@builds("//")
|
@builds("//")
|
||||||
@ -1918,8 +1912,7 @@ class HyASTCompiler(object):
|
|||||||
if len(expression) > 2:
|
if len(expression) > 2:
|
||||||
return self.compile_maths_expression(expression)
|
return self.compile_maths_expression(expression)
|
||||||
else:
|
else:
|
||||||
id_op = {"+": HyInteger(0), "*": HyInteger(1), "/": HyInteger(1),
|
id_op = {"*": HyInteger(1), "/": HyInteger(1), "//": HyInteger(1)}
|
||||||
"//": HyInteger(1)}
|
|
||||||
|
|
||||||
op = expression.pop(0)
|
op = expression.pop(0)
|
||||||
arg = expression.pop(0) if expression else id_op[op]
|
arg = expression.pop(0) if expression else id_op[op]
|
||||||
@ -1930,20 +1923,34 @@ class HyASTCompiler(object):
|
|||||||
]).replace(expression)
|
]).replace(expression)
|
||||||
return self.compile_maths_expression(expr)
|
return self.compile_maths_expression(expr)
|
||||||
|
|
||||||
@builds("-")
|
def compile_maths_expression_additive(self, expression):
|
||||||
@checkargs(min=1)
|
|
||||||
def compile_maths_expression_sub(self, expression):
|
|
||||||
if len(expression) > 2:
|
if len(expression) > 2:
|
||||||
return self.compile_maths_expression(expression)
|
return self.compile_maths_expression(expression)
|
||||||
else:
|
else:
|
||||||
arg = expression[1]
|
op = {"+": ast.UAdd, "-": ast.USub}[expression.pop(0)]()
|
||||||
|
arg = expression.pop(0)
|
||||||
ret = self.compile(arg)
|
ret = self.compile(arg)
|
||||||
ret += ast.UnaryOp(op=ast.USub(),
|
ret += ast.UnaryOp(op=op,
|
||||||
operand=ret.force_expr,
|
operand=ret.force_expr,
|
||||||
lineno=arg.start_line,
|
lineno=arg.start_line,
|
||||||
col_offset=arg.start_column)
|
col_offset=arg.start_column)
|
||||||
return ret
|
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("/=")
|
@builds("/=")
|
||||||
@builds("//=")
|
@builds("//=")
|
||||||
@ -2449,6 +2456,9 @@ class HyASTCompiler(object):
|
|||||||
raise HyTypeError(name, ("received a `%s' instead of a symbol "
|
raise HyTypeError(name, ("received a `%s' instead of a symbol "
|
||||||
"for macro name" % type(name).__name__))
|
"for macro name" % type(name).__name__))
|
||||||
name = HyString(name).replace(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([
|
new_expression = HyExpression([
|
||||||
HySymbol("with_decorator"),
|
HySymbol("with_decorator"),
|
||||||
HyExpression([HySymbol("hy.macros.macro"), name]),
|
HyExpression([HySymbol("hy.macros.macro"), name]),
|
||||||
|
@ -39,10 +39,6 @@
|
|||||||
(import [hy.lex [LexException PrematureEndOfInput tokenize]])
|
(import [hy.lex [LexException PrematureEndOfInput tokenize]])
|
||||||
(import [hy.compiler [HyASTCompiler]])
|
(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]
|
(defn butlast [coll]
|
||||||
"Returns coll except of last element."
|
"Returns coll except of last element."
|
||||||
(drop-last 1 coll))
|
(drop-last 1 coll))
|
||||||
@ -66,7 +62,6 @@
|
|||||||
|
|
||||||
(defn dec [n]
|
(defn dec [n]
|
||||||
"Decrement n by 1"
|
"Decrement n by 1"
|
||||||
(_numeric-check n)
|
|
||||||
(- n 1))
|
(- n 1))
|
||||||
|
|
||||||
(defn disassemble [tree &optional [codegen false]]
|
(defn disassemble [tree &optional [codegen false]]
|
||||||
@ -170,7 +165,6 @@
|
|||||||
|
|
||||||
(defn even? [n]
|
(defn even? [n]
|
||||||
"Return true if n is an even number"
|
"Return true if n is an even number"
|
||||||
(_numeric-check n)
|
|
||||||
(= (% n 2) 0))
|
(= (% n 2) 0))
|
||||||
|
|
||||||
(defn every? [pred coll]
|
(defn every? [pred coll]
|
||||||
@ -239,7 +233,6 @@
|
|||||||
|
|
||||||
(defn inc [n]
|
(defn inc [n]
|
||||||
"Increment n by 1"
|
"Increment n by 1"
|
||||||
(_numeric-check n)
|
|
||||||
(+ n 1))
|
(+ n 1))
|
||||||
|
|
||||||
(defn instance? [klass x]
|
(defn instance? [klass x]
|
||||||
@ -325,7 +318,6 @@
|
|||||||
|
|
||||||
(defn neg? [n]
|
(defn neg? [n]
|
||||||
"Return true if n is < 0"
|
"Return true if n is < 0"
|
||||||
(_numeric-check n)
|
|
||||||
(< n 0))
|
(< n 0))
|
||||||
|
|
||||||
(defn none? [x]
|
(defn none? [x]
|
||||||
@ -347,7 +339,6 @@
|
|||||||
|
|
||||||
(defn odd? [n]
|
(defn odd? [n]
|
||||||
"Return true if n is an odd number"
|
"Return true if n is an odd number"
|
||||||
(_numeric-check n)
|
|
||||||
(= (% n 2) 1))
|
(= (% n 2) 1))
|
||||||
|
|
||||||
(def -sentinel (object))
|
(def -sentinel (object))
|
||||||
@ -364,7 +355,6 @@
|
|||||||
|
|
||||||
(defn pos? [n]
|
(defn pos? [n]
|
||||||
"Return true if n is > 0"
|
"Return true if n is > 0"
|
||||||
(_numeric_check n)
|
|
||||||
(> n 0))
|
(> n 0))
|
||||||
|
|
||||||
(defn rest [coll]
|
(defn rest [coll]
|
||||||
@ -415,7 +405,6 @@
|
|||||||
|
|
||||||
(defn zero? [n]
|
(defn zero? [n]
|
||||||
"Return true if n is 0"
|
"Return true if n is 0"
|
||||||
(_numeric_check n)
|
|
||||||
(= n 0))
|
(= n 0))
|
||||||
|
|
||||||
(defn read [&optional [from-file sys.stdin]
|
(defn read [&optional [from-file sys.stdin]
|
||||||
|
@ -30,6 +30,16 @@
|
|||||||
[hy.models.symbol [HySymbol]]
|
[hy.models.symbol [HySymbol]]
|
||||||
[hy._compat [PY33 PY34]])
|
[hy._compat [PY33 PY34]])
|
||||||
|
|
||||||
|
(defmacro as-> [head name &rest rest]
|
||||||
|
"Expands to sequence of assignments to the provided name, starting with head.
|
||||||
|
The previous result is thus available in the subsequent form. Returns the
|
||||||
|
final result, and leaves the name bound to it in the local scope. This behaves
|
||||||
|
much like the other threading macros, but requires you to specify the threading
|
||||||
|
point per form via the name instead of always the first or last arument."
|
||||||
|
`(do (setv
|
||||||
|
~name ~head
|
||||||
|
~@(interleave (repeat name) rest))
|
||||||
|
~name))
|
||||||
|
|
||||||
(defmacro with [args &rest body]
|
(defmacro with [args &rest body]
|
||||||
"shorthand for nested with* loops:
|
"shorthand for nested with* loops:
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
(if (zero? count)
|
(if (zero? count)
|
||||||
(raise (TypeError "Need at least 1 argument to add/concatenate"))
|
(raise (TypeError "Need at least 1 argument to add/concatenate"))
|
||||||
(if (= count 1)
|
(if (= count 1)
|
||||||
(get args 0)
|
(operator.pos (get args 0))
|
||||||
(reduce operator.add args)))))
|
(reduce operator.add args)))))
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,19 +18,16 @@
|
|||||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
# DEALINGS IN THE SOFTWARE.
|
# DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
from hy.models import _wrappers, wrap_value
|
||||||
from hy.models.list import HyList
|
from hy.models.list import HyList
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
|
|
||||||
class HySet(HyList):
|
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):
|
def __repr__(self):
|
||||||
return "#{%s}" % (" ".join([repr(x) for x in 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."""
|
""" Ensure we can compile functions with lambda list keywords."""
|
||||||
can_compile("(fn (x &rest xs) (print xs))")
|
can_compile("(fn (x &rest xs) (print xs))")
|
||||||
cant_compile("(fn (x &rest xs &rest ys) (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():
|
def test_lambda_list_keywords_key():
|
||||||
@ -410,6 +411,7 @@ def test_lambda_list_keywords_kwargs():
|
|||||||
""" Ensure we can compile functions with &kwargs."""
|
""" Ensure we can compile functions with &kwargs."""
|
||||||
can_compile("(fn (x &kwargs kw) (list x kw))")
|
can_compile("(fn (x &kwargs kw) (list x kw))")
|
||||||
cant_compile("(fn (x &kwargs xs &kwargs ys) (list x xs ys))")
|
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():
|
def test_lambda_list_keywords_kwonly():
|
||||||
|
@ -230,6 +230,16 @@ def test_sets():
|
|||||||
HyExpression([HySymbol("baz"), HySymbol("quux")])
|
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():
|
def test_nospace():
|
||||||
""" Ensure we can tokenize without spaces if we have to """
|
""" Ensure we can tokenize without spaces if we have to """
|
||||||
|
@ -5,4 +5,4 @@ hyset = HySet([3, 1, 2, 2])
|
|||||||
|
|
||||||
|
|
||||||
def test_set():
|
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
|
;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
;; DEALINGS IN THE SOFTWARE.
|
;; DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
(import [hy._compat [PY3]])
|
||||||
|
|
||||||
;;;; some simple helpers
|
;;;; some simple helpers
|
||||||
|
|
||||||
(defn assert-true [x]
|
(defn assert-true [x]
|
||||||
@ -33,6 +35,12 @@
|
|||||||
(defn assert-nil [x]
|
(defn assert-nil [x]
|
||||||
(assert (is x nil)))
|
(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? []
|
(defn test-coll? []
|
||||||
"NATIVE: testing coll?"
|
"NATIVE: testing coll?"
|
||||||
(assert-true (coll? [1 2 3]))
|
(assert-true (coll? [1 2 3]))
|
||||||
@ -66,12 +74,7 @@
|
|||||||
(assert-equal 0 (dec 1))
|
(assert-equal 0 (dec 1))
|
||||||
(assert-equal -1 (dec 0))
|
(assert-equal -1 (dec 0))
|
||||||
(assert-equal 0 (dec (dec 2)))
|
(assert-equal 0 (dec (dec 2)))
|
||||||
(try (do (dec "foo") (assert False))
|
(assert-requires-num dec))
|
||||||
(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))))))
|
|
||||||
|
|
||||||
(defn test-setv []
|
(defn test-setv []
|
||||||
"NATIVE: testing setv mutation"
|
"NATIVE: testing setv mutation"
|
||||||
@ -173,12 +176,7 @@
|
|||||||
(assert-true (even? -2))
|
(assert-true (even? -2))
|
||||||
(assert-false (even? 1))
|
(assert-false (even? 1))
|
||||||
(assert-true (even? 0))
|
(assert-true (even? 0))
|
||||||
(try (even? "foo")
|
(assert-requires-num even?))
|
||||||
(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))))))
|
|
||||||
|
|
||||||
(defn test-every? []
|
(defn test-every? []
|
||||||
"NATIVE: testing the every? function"
|
"NATIVE: testing the every? function"
|
||||||
@ -263,12 +261,11 @@
|
|||||||
"NATIVE: testing the inc function"
|
"NATIVE: testing the inc function"
|
||||||
(assert-equal 3 (inc 2))
|
(assert-equal 3 (inc 2))
|
||||||
(assert-equal 0 (inc -1))
|
(assert-equal 0 (inc -1))
|
||||||
(try (do (inc "foo") (assert False))
|
(assert-requires-num inc)
|
||||||
(except [e [TypeError]] (assert (in "not a number" (str e)))))
|
|
||||||
(try (do (inc []) (assert False))
|
(defclass X [object]
|
||||||
(except [e [TypeError]] (assert (in "not a number" (str e)))))
|
[__add__ (fn [self other] (.format "__add__ got {}" other))])
|
||||||
(try (do (inc None) (assert False))
|
(assert-equal (inc (X)) "__add__ got 1"))
|
||||||
(except [e [TypeError]] (assert (in "not a number" (str e))))))
|
|
||||||
|
|
||||||
(defn test-instance []
|
(defn test-instance []
|
||||||
"NATIVE: testing instance? function"
|
"NATIVE: testing instance? function"
|
||||||
@ -394,24 +391,14 @@
|
|||||||
(assert-true (neg? -2))
|
(assert-true (neg? -2))
|
||||||
(assert-false (neg? 1))
|
(assert-false (neg? 1))
|
||||||
(assert-false (neg? 0))
|
(assert-false (neg? 0))
|
||||||
(try (do (neg? "foo") (assert False))
|
(when PY3
|
||||||
(except [e [TypeError]] (assert (in "not a number" (str e)))))
|
(assert-requires-num neg?)))
|
||||||
(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))))))
|
|
||||||
|
|
||||||
(defn test-zero []
|
(defn test-zero []
|
||||||
"NATIVE: testing the zero? function"
|
"NATIVE: testing the zero? function"
|
||||||
(assert-false (zero? -2))
|
(assert-false (zero? -2))
|
||||||
(assert-false (zero? 1))
|
(assert-false (zero? 1))
|
||||||
(assert-true (zero? 0))
|
(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))))))
|
|
||||||
|
|
||||||
(defn test-none []
|
(defn test-none []
|
||||||
"NATIVE: testing for `is None`"
|
"NATIVE: testing for `is None`"
|
||||||
@ -463,12 +450,7 @@
|
|||||||
(assert-true (odd? -3))
|
(assert-true (odd? -3))
|
||||||
(assert-true (odd? 1))
|
(assert-true (odd? 1))
|
||||||
(assert-false (odd? 0))
|
(assert-false (odd? 0))
|
||||||
(try (do (odd? "foo") (assert False))
|
(assert-requires-num odd?))
|
||||||
(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))))))
|
|
||||||
|
|
||||||
(defn test-partition []
|
(defn test-partition []
|
||||||
"NATIVE: testing the partition function"
|
"NATIVE: testing the partition function"
|
||||||
@ -500,12 +482,8 @@
|
|||||||
(assert-true (pos? 2))
|
(assert-true (pos? 2))
|
||||||
(assert-false (pos? -1))
|
(assert-false (pos? -1))
|
||||||
(assert-false (pos? 0))
|
(assert-false (pos? 0))
|
||||||
(try (do (pos? "foo") (assert False))
|
(when PY3
|
||||||
(except [e [TypeError]] (assert (in "not a number" (str e)))))
|
(assert-requires-num pos?)))
|
||||||
(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))))))
|
|
||||||
|
|
||||||
(defn test-remove []
|
(defn test-remove []
|
||||||
"NATIVE: testing the remove function"
|
"NATIVE: testing the remove function"
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
(defn test-sets []
|
(defn test-sets []
|
||||||
"NATIVE: test sets work right"
|
"NATIVE: test sets work right"
|
||||||
(assert (= #{1 2 3 4} (| #{1 2} #{3 4})))
|
(assert (= #{1 2 3 4} (| #{1 2} #{3 4})))
|
||||||
|
(assert (= (type #{1 2 3 4}) set))
|
||||||
(assert (= #{} (set))))
|
(assert (= #{} (set))))
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,18 @@
|
|||||||
(assert (= 0 (+)))))
|
(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 []
|
(setv test_div (fn []
|
||||||
"NATIVE: Test division"
|
"NATIVE: Test division"
|
||||||
(assert (= 25 (/ 100 2 2)))
|
(assert (= 25 (/ 100 2 2)))
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
(import [hy.errors [HyTypeError]])
|
||||||
|
|
||||||
(defmacro rev [&rest body]
|
(defmacro rev [&rest body]
|
||||||
"Execute the `body` statements in reverse"
|
"Execute the `body` statements in reverse"
|
||||||
(quasiquote (do (unquote-splice (list (reversed body))))))
|
(quasiquote (do (unquote-splice (list (reversed body))))))
|
||||||
@ -37,6 +39,9 @@
|
|||||||
(defmacro a-dict [] {1 2})
|
(defmacro a-dict [] {1 2})
|
||||||
(assert (= (a-dict) {1 2}))
|
(assert (= (a-dict) {1 2}))
|
||||||
|
|
||||||
|
(defmacro a-set [] #{1 2})
|
||||||
|
(assert (= (a-set) #{1 2}))
|
||||||
|
|
||||||
(defmacro a-none [])
|
(defmacro a-none [])
|
||||||
(assert (= (a-none) None))
|
(assert (= (a-none) None))
|
||||||
|
|
||||||
@ -48,6 +53,26 @@
|
|||||||
(defmacro bar [x y]
|
(defmacro bar [x y]
|
||||||
(foo 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 []
|
(defn test-fn-calling-macro []
|
||||||
"NATIVE: test macro calling a plain function"
|
"NATIVE: test macro calling a plain function"
|
||||||
(assert (= 3 (bar 1 2))))
|
(assert (= 3 (bar 1 2))))
|
||||||
|
@ -8,13 +8,9 @@
|
|||||||
(assert (= (x 1 2 3 4) 10))
|
(assert (= (x 1 2 3 4) 10))
|
||||||
(assert (= (x 1 2 3 4 5) 15))
|
(assert (= (x 1 2 3 4 5) 15))
|
||||||
; with strings
|
; with strings
|
||||||
(assert (= (x "a")
|
|
||||||
"a"))
|
|
||||||
(assert (= (x "a" "b" "c")
|
(assert (= (x "a" "b" "c")
|
||||||
"abc"))
|
"abc"))
|
||||||
; with lists
|
; with lists
|
||||||
(assert (= (x ["a"])
|
|
||||||
["a"]))
|
|
||||||
(assert (= (x ["a"] ["b"] ["c"])
|
(assert (= (x ["a"] ["b"] ["c"])
|
||||||
["a" "b" "c"]))))
|
["a" "b" "c"]))))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user