Fix butlast and test for disassemble. Conflicts: hy/core/language.hy
This commit is contained in:
commit
01ee54cf62
13
.travis.yml
13
.travis.yml
@ -1,19 +1,18 @@
|
|||||||
language: python
|
language: python
|
||||||
python:
|
python:
|
||||||
- "pypy"
|
- "pypy"
|
||||||
|
- "2.6"
|
||||||
- "2.7"
|
- "2.7"
|
||||||
- "3.2"
|
- "3.2"
|
||||||
- "3.3"
|
- "3.3"
|
||||||
- "2.6"
|
- "3.4"
|
||||||
# command to install dependencies
|
# command to install dependencies
|
||||||
install:
|
install:
|
||||||
- pip install -r requirements.txt
|
- pip install -r requirements-dev.txt
|
||||||
- pip install coveralls
|
- pip install coveralls
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install argparse importlib unittest2 astor; fi
|
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install unittest2; fi # needs for running tests
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install astor; fi
|
- pip install --allow-all-external -e .
|
||||||
- if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then pip install astor; fi
|
# command to run tests
|
||||||
- python setup.py -q install
|
|
||||||
# # command to run tests
|
|
||||||
script: make travis
|
script: make travis
|
||||||
after_success: coveralls
|
after_success: coveralls
|
||||||
notifications:
|
notifications:
|
||||||
|
3
AUTHORS
3
AUTHORS
@ -43,3 +43,6 @@
|
|||||||
* Richard Parsons <richard.lee.parsons@gmail.com>
|
* Richard Parsons <richard.lee.parsons@gmail.com>
|
||||||
* han semaj <sangho.nah@gmail.com>
|
* han semaj <sangho.nah@gmail.com>
|
||||||
* kirbyfan64 <kirbyfan64@users.noreply.github.com>
|
* kirbyfan64 <kirbyfan64@users.noreply.github.com>
|
||||||
|
* Brendan Curran-Johnson <brendan@bcjbcj.ca>
|
||||||
|
* Ivan Kozik <ivan@ludios.org>
|
||||||
|
* Allison Kaptur <allison.kaptur@gmail.com>
|
||||||
|
2
Makefile
2
Makefile
@ -41,7 +41,7 @@ tox: venv
|
|||||||
tox
|
tox
|
||||||
|
|
||||||
flake:
|
flake:
|
||||||
flake8 hy
|
flake8 hy tests
|
||||||
|
|
||||||
clear:
|
clear:
|
||||||
clear
|
clear
|
||||||
|
80
NEWS
80
NEWS
@ -1,3 +1,83 @@
|
|||||||
|
Changes from 0.9.12
|
||||||
|
|
||||||
|
0.10.0 - the "oh man I'm late for PyCon" release
|
||||||
|
|
||||||
|
Thanks to theanalyst (Abhi) for getting the release notes
|
||||||
|
together. You're the best!
|
||||||
|
- Hy Society
|
||||||
|
|
||||||
|
[ Breaking Changes ]
|
||||||
|
|
||||||
|
We're calling this release 0.10 because we broke
|
||||||
|
API. Sorry about that. We've removed kwapply in
|
||||||
|
favor of using `apply`. Please be sure to upgrade
|
||||||
|
all code to work with `apply`.
|
||||||
|
|
||||||
|
(apply function-call args kwargs) ; is the signature
|
||||||
|
|
||||||
|
[Thanks]
|
||||||
|
|
||||||
|
Major shoutout to Clinton Dreisbach for implementing loop/recur.
|
||||||
|
As always, massive hugs to olasd for the constant reviews and for
|
||||||
|
implementing HyCons cells. Thanks to @kenanb for redesigning the
|
||||||
|
new Hy logo.
|
||||||
|
|
||||||
|
Many thanks to algernon for working on adderall, which helped
|
||||||
|
push Hy further this cycle. Adderall is an implementation of miniKanren
|
||||||
|
in Hy. If you're interested in using Adderall, check out hydiomatic,
|
||||||
|
which prettfies Hy source using Adderall rules.
|
||||||
|
|
||||||
|
This release saw an increase of about 11 contributors for a point
|
||||||
|
release, you guys rock!
|
||||||
|
|
||||||
|
-Hy Society
|
||||||
|
|
||||||
|
[ Language Changes ]
|
||||||
|
|
||||||
|
* `for' revamped again (Last time, we hope!), this time using a saner
|
||||||
|
itertools.product when nesting
|
||||||
|
* `lisp-if'/`lif' added for the lisp-like everything is true if, giving
|
||||||
|
seasoned lispers a better if check (0 is a value, etc)
|
||||||
|
* Reader Macros are macros now!
|
||||||
|
* yield-from is now a proper yield from on Python 3. It also now breaks on
|
||||||
|
Python 2.x.
|
||||||
|
* Added if-not macro
|
||||||
|
* We finally have a lisp like cons cells
|
||||||
|
* Generator expressions, set & dict comprehensions are now supported
|
||||||
|
* (.) is a mini DSL for attribute access
|
||||||
|
* `macroexpand' & `macroexpand-1' added to core
|
||||||
|
* `disassemble' added to core, which dumps the AST or equivalent python code
|
||||||
|
* `coll?' added to core to check for a collection
|
||||||
|
* `identity' function added to core
|
||||||
|
|
||||||
|
[ Misc. Fixes ]
|
||||||
|
* Lots of doc fixes. Reorganization as well as better docs on Hy internals
|
||||||
|
* Universal Wheel Support
|
||||||
|
* Pygments > 1.6 supports Hy now. All codeblocks in docs have been changed
|
||||||
|
from clojure to hy
|
||||||
|
* Hy REPL supports invoking with --spy & -i options [reword]
|
||||||
|
* `first' and `rest' are functions and not macros anymore
|
||||||
|
* "clean" target added to Makefile
|
||||||
|
* hy2py supports a bunch of commandline options to show AST, source etc.
|
||||||
|
* Sub-object mangling: every identifier is split along the dots & mangled
|
||||||
|
seperately
|
||||||
|
|
||||||
|
[ Bug Fixes ]
|
||||||
|
* Empty MacroExpansions work as expected
|
||||||
|
* Python 3.4 port. Sorry this wasn't in a 3.4 release time, we forgot to do
|
||||||
|
a release. Whoops.
|
||||||
|
* eg/lxml/parse-tumblr.hy works with Python 3
|
||||||
|
* hy2py works on Windows
|
||||||
|
* Fixed unicode encoding issue in REPL during unicode exceptions
|
||||||
|
* Fixed handling of comments at end of input (#382)
|
||||||
|
|
||||||
|
[ Contrib changes ]
|
||||||
|
* Curry module added to contrib
|
||||||
|
* Loop/recur module added which provides TCO at tail position
|
||||||
|
* defmulti has been added - check out more in the docs -- thanks to Foxboron for this one!
|
||||||
|
* Walk module for walking the Hy AST, features a `macroexpand-all` as well
|
||||||
|
|
||||||
|
|
||||||
Changes from Hy 0.9.11
|
Changes from Hy 0.9.11
|
||||||
|
|
||||||
tl;dr:
|
tl;dr:
|
||||||
|
39
bin/hy2py
39
bin/hy2py
@ -1,39 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
from __future__ import print_function
|
|
||||||
from hy.importer import (import_file_to_ast, import_file_to_hst)
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import astor.codegen
|
|
||||||
|
|
||||||
module_name = "<STDIN>"
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
prog="hy2py",
|
|
||||||
usage="%(prog)s [options] FILE",
|
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
||||||
parser.add_argument("--with-source", "-s", action="store_true",
|
|
||||||
help="Show the parsed source structure")
|
|
||||||
parser.add_argument("--with-ast", "-a", action="store_true",
|
|
||||||
help="Show the generated AST")
|
|
||||||
parser.add_argument("--without-python", "-np", action="store_true",
|
|
||||||
help="Do not show the python code generated from the AST")
|
|
||||||
parser.add_argument('args', nargs=argparse.REMAINDER, help=argparse.SUPPRESS)
|
|
||||||
|
|
||||||
options = parser.parse_args(sys.argv[1:])
|
|
||||||
|
|
||||||
if options.with_source:
|
|
||||||
hst = import_file_to_hst(options.args[0])
|
|
||||||
print(str(hst).encode("utf-8"))
|
|
||||||
print()
|
|
||||||
print()
|
|
||||||
|
|
||||||
_ast = import_file_to_ast(options.args[0], module_name)
|
|
||||||
if options.with_ast:
|
|
||||||
print(astor.dump(_ast).encode("utf-8"))
|
|
||||||
print()
|
|
||||||
print()
|
|
||||||
|
|
||||||
if not options.without_python:
|
|
||||||
print(astor.codegen.to_source(_ast).encode("utf-8"))
|
|
@ -96,7 +96,13 @@ pygments_style = 'sphinx'
|
|||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
html_theme = 'default'
|
try:
|
||||||
|
import sphinx_rtd_theme
|
||||||
|
except ImportError:
|
||||||
|
html_theme = 'default'
|
||||||
|
else:
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
|
@ -48,7 +48,7 @@ Usage: ``(ap-each-while list pred body)``
|
|||||||
Evaluate the form for each element where the predicate form returns
|
Evaluate the form for each element where the predicate form returns
|
||||||
True.
|
True.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (ap-each-while [1 2 3 4 5 6] (< it 4) (print it))
|
=> (ap-each-while [1 2 3 4 5 6] (< it 4) (print it))
|
||||||
1
|
1
|
||||||
@ -66,7 +66,7 @@ The anaphoric form of map works just like regular map except that
|
|||||||
instead of a function object it takes a Hy form. The special name,
|
instead of a function object it takes a Hy form. The special name,
|
||||||
``it`` is bound to the current object from the list in the iteration.
|
``it`` is bound to the current object from the list in the iteration.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (ap-map (* it 2) [1 2 3]))
|
=> (list (ap-map (* it 2) [1 2 3]))
|
||||||
[2, 4, 6]
|
[2, 4, 6]
|
||||||
@ -82,7 +82,7 @@ Usage: ``(ap-map-when predfn rep list)``
|
|||||||
Evaluate a mapping over the list using a predicate function to
|
Evaluate a mapping over the list using a predicate function to
|
||||||
determin when to apply the form.
|
determin when to apply the form.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (ap-map-when odd? (* it 2) [1 2 3 4]))
|
=> (list (ap-map-when odd? (* it 2) [1 2 3 4]))
|
||||||
[2, 2, 6, 4]
|
[2, 2, 6, 4]
|
||||||
@ -102,7 +102,7 @@ As with ``ap-map`` we take a special form instead of a function to
|
|||||||
filter the elements of the list. The special name ``it`` is bound to
|
filter the elements of the list. The special name ``it`` is bound to
|
||||||
the current element in the iteration.
|
the current element in the iteration.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (ap-filter (> (* it 2) 6) [1 2 3 4 5]))
|
=> (list (ap-filter (> (* it 2) 6) [1 2 3 4 5]))
|
||||||
[4, 5]
|
[4, 5]
|
||||||
@ -119,7 +119,7 @@ This function does the opposite of ``ap-filter``, it rejects the
|
|||||||
elements passing the predicate . The special name ``it`` is bound to
|
elements passing the predicate . The special name ``it`` is bound to
|
||||||
the current element in the iteration.
|
the current element in the iteration.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (ap-reject (> (* it 2) 6) [1 2 3 4 5]))
|
=> (list (ap-reject (> (* it 2) 6) [1 2 3 4 5]))
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
@ -135,7 +135,7 @@ Usage ``(ap-dotimes n body)``
|
|||||||
This function evaluates the body *n* times, with the special
|
This function evaluates the body *n* times, with the special
|
||||||
variable ``it`` bound from *0* to *1-n*. It is useful for side-effects.
|
variable ``it`` bound from *0* to *1-n*. It is useful for side-effects.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (setv n [])
|
=> (setv n [])
|
||||||
=> (ap-dotimes 3 (.append n it))
|
=> (ap-dotimes 3 (.append n it))
|
||||||
@ -154,7 +154,7 @@ This function returns the first element that passes the predicate or
|
|||||||
``None``, with the special variable ``it`` bound to the current element in
|
``None``, with the special variable ``it`` bound to the current element in
|
||||||
iteration.
|
iteration.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=>(ap-first (> it 5) (range 10))
|
=>(ap-first (> it 5) (range 10))
|
||||||
6
|
6
|
||||||
@ -171,7 +171,7 @@ This function returns the last element that passes the predicate or
|
|||||||
``None``, with the special variable ``it`` bound to the current element in
|
``None``, with the special variable ``it`` bound to the current element in
|
||||||
iteration.
|
iteration.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=>(ap-last (> it 5) (range 10))
|
=>(ap-last (> it 5) (range 10))
|
||||||
9
|
9
|
||||||
@ -191,7 +191,7 @@ supplied so the function will be applied to initial value and the
|
|||||||
first element instead. This exposes the element being iterated as
|
first element instead. This exposes the element being iterated as
|
||||||
``it`` and the current accumulated value as ``acc``.
|
``it`` and the current accumulated value as ``acc``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=>(ap-reduce (+ it acc) (range 10))
|
=>(ap-reduce (+ it acc) (range 10))
|
||||||
45
|
45
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
loop/recur
|
loop/recur
|
||||||
==========
|
==========
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
The loop/recur macro gives programmers a simple way to use tail-call
|
The loop/recur macro gives programmers a simple way to use tail-call
|
||||||
optimization (TCO) in their Hy code.
|
optimization (TCO) in their Hy code.
|
||||||
@ -43,7 +43,7 @@ Usage: `(loop bindings &rest body)`
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(require hy.contrib.loop)
|
(require hy.contrib.loop)
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
defmulti
|
defmulti
|
||||||
========
|
========
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
`defmulti` lets you arity-overload a function by the given number of
|
`defmulti` lets you arity-overload a function by the given number of
|
||||||
args and/or kwargs. Inspired by clojures take on `defn`.
|
args and/or kwargs. Inspired by clojures take on `defn`.
|
||||||
|
@ -92,6 +92,12 @@ Write docs---docs are good! Even this doc!
|
|||||||
Core Development Rules
|
Core Development Rules
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
Pull requests are good!
|
||||||
|
|
||||||
|
Before you submit a PR, please run the tests and check your code against the style guide. You can do both these things at once::
|
||||||
|
|
||||||
|
$ make d
|
||||||
|
|
||||||
All incoming changes need to be acked by 2 different members of Hylang's
|
All incoming changes need to be acked by 2 different members of Hylang's
|
||||||
core team. Additional review is clearly welcome, but we need a minimum of
|
core team. Additional review is clearly welcome, but we need a minimum of
|
||||||
2 signoffs for any change.
|
2 signoffs for any change.
|
||||||
|
@ -43,7 +43,7 @@ behavior that's slightly unexpected in some situations.
|
|||||||
.
|
.
|
||||||
-
|
-
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
|
|
||||||
`.` is used to perform attribute access on objects. It uses a small DSL
|
`.` is used to perform attribute access on objects. It uses a small DSL
|
||||||
@ -151,20 +151,14 @@ case the first false value will be returned. Examples of usage:
|
|||||||
=> (and True [] False True)
|
=> (and True [] False True)
|
||||||
[]
|
[]
|
||||||
|
|
||||||
.. note:: `and` shortcuts and stops evaluating parameters as soon as the first
|
.. note::
|
||||||
false is encountered. However, in the current implementation of Hy
|
|
||||||
statements are executed as soon as they are converted to expressions.
|
`and` shortcuts and stops evaluating parameters as soon as the first
|
||||||
The following two examples demonstrates the difference.
|
false is encountered.
|
||||||
|
|
||||||
.. code-block:: clj
|
.. code-block:: clj
|
||||||
|
|
||||||
=> (and False (print "hello"))
|
=> (and False (print "hello"))
|
||||||
hello
|
|
||||||
False
|
|
||||||
|
|
||||||
=> (defn side-effects [x] (print "I can has" x) x)
|
|
||||||
=> (and (side-effects false) (side-effects 42))
|
|
||||||
I can has False
|
|
||||||
False
|
False
|
||||||
|
|
||||||
|
|
||||||
@ -277,6 +271,21 @@ however is called only for every other value in the list.
|
|||||||
(side-effect2 x)))
|
(side-effect2 x)))
|
||||||
|
|
||||||
|
|
||||||
|
dict-comp
|
||||||
|
---------
|
||||||
|
|
||||||
|
`dict-comp` is used to create dictionaries. It takes three or four parameters.
|
||||||
|
The first two parameters are for controlling the return value
|
||||||
|
(key-value pair), while the third is used to select items from a sequence. The
|
||||||
|
fourth and optional parameter can be used to filter out some of the items in
|
||||||
|
the sequence based on a conditional expression.
|
||||||
|
|
||||||
|
.. code-block:: hy
|
||||||
|
|
||||||
|
=> (dict-comp x (* x 2) [x (range 10)] (odd? x))
|
||||||
|
{1: 2, 3: 6, 9: 18, 5: 10, 7: 14}
|
||||||
|
|
||||||
|
|
||||||
do / progn
|
do / progn
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@ -398,7 +407,7 @@ Parameters may have following keywords in front of them:
|
|||||||
=> (defn print-parameters [&kwargs kwargs]
|
=> (defn print-parameters [&kwargs kwargs]
|
||||||
... (for [(, k v) (.items kwargs)] (print k v)))
|
... (for [(, k v) (.items kwargs)] (print k v)))
|
||||||
|
|
||||||
=> (kwapply (print-parameters) {"parameter-1" 1 "parameter-2" 2})
|
=> (apply print-parameters [] {"parameter-1" 1 "parameter-2" 2})
|
||||||
parameter-2 2
|
parameter-2 2
|
||||||
parameter-1 1
|
parameter-1 1
|
||||||
|
|
||||||
@ -429,7 +438,7 @@ Parameters may have following keywords in front of them:
|
|||||||
defn-alias / defun-alias
|
defn-alias / defun-alias
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
The `defn-alias` and `defun-alias` macros are much like `defn`_ above,
|
The `defn-alias` and `defun-alias` macros are much like `defn`_ above,
|
||||||
with the difference that instead of defining a function with a single
|
with the difference that instead of defining a function with a single
|
||||||
@ -447,6 +456,44 @@ symbols for function names as the first parameter, `defn-alias` and
|
|||||||
=> (alias)
|
=> (alias)
|
||||||
"Hello!"
|
"Hello!"
|
||||||
|
|
||||||
|
|
||||||
|
defmain
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. versionadded:: 0.10.1
|
||||||
|
|
||||||
|
The `defmain` macro defines a main function that is immediately called
|
||||||
|
with sys.argv as arguments if and only if this file is being executed
|
||||||
|
as a script. In other words this:
|
||||||
|
|
||||||
|
.. code-block:: clj
|
||||||
|
|
||||||
|
(defmain [&rest args]
|
||||||
|
(do-something-with args))
|
||||||
|
|
||||||
|
is the equivalent of::
|
||||||
|
|
||||||
|
def main(*args):
|
||||||
|
do_something_with(args)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
retval = main(*sys.arg)
|
||||||
|
|
||||||
|
if isinstance(retval, int):
|
||||||
|
sys.exit(retval)
|
||||||
|
|
||||||
|
Note, as you can see above, if you return an integer from this
|
||||||
|
function, this will be used as the exit status for your script.
|
||||||
|
(Python defaults to exit status 0 otherwise, which means everything's
|
||||||
|
okay!)
|
||||||
|
|
||||||
|
(Since (sys.exit 0) is not run explicitly in case of a non-integer
|
||||||
|
return from defmain, it's good to put (defmain) as the last bit of
|
||||||
|
code in your file.)
|
||||||
|
|
||||||
|
|
||||||
.. _defmacro:
|
.. _defmacro:
|
||||||
|
|
||||||
defmacro
|
defmacro
|
||||||
@ -635,6 +682,24 @@ normally. If the execution is halted with `break`, the `else` does not execute.
|
|||||||
loop finished
|
loop finished
|
||||||
|
|
||||||
|
|
||||||
|
genexpr
|
||||||
|
-------
|
||||||
|
|
||||||
|
`genexpr` is used to create generator expressions. It takes two or three parameters.
|
||||||
|
The first parameter is the expression controlling the return value, while
|
||||||
|
the second is used to select items from a list. The third and optional
|
||||||
|
parameter can be used to filter out some of the items in the list based on a
|
||||||
|
conditional expression. `genexpr` is similar to `list-comp`, except that it returns
|
||||||
|
an iterable that evaluates values one by one instead of evaluating them immediately.
|
||||||
|
|
||||||
|
.. code-block:: hy
|
||||||
|
|
||||||
|
=> (def collection (range 10))
|
||||||
|
=> (def filtered (genexpr x [x collection] (even? x)))
|
||||||
|
=> (list filtered)
|
||||||
|
[0, 2, 4, 6, 8]
|
||||||
|
|
||||||
|
|
||||||
.. _gensym:
|
.. _gensym:
|
||||||
|
|
||||||
gensym
|
gensym
|
||||||
@ -711,7 +776,7 @@ the `if` form is used to conditionally select code to be executed. It has to
|
|||||||
contain the condition block and the block to be executed if the condition
|
contain the condition block and the block to be executed if the condition
|
||||||
evaluates `True`. Optionally it may contain a block that is executed in case
|
evaluates `True`. Optionally it may contain a block that is executed in case
|
||||||
the evaluation of the condition is `False`. The `if-not` form (*new in
|
the evaluation of the condition is `False`. The `if-not` form (*new in
|
||||||
0.9.13*) is similar, but the first block after the test will be
|
0.10.0*) is similar, but the first block after the test will be
|
||||||
executed when the test fails, while the other, conditional one, when
|
executed when the test fails, while the other, conditional one, when
|
||||||
the test succeeds - opposite of the order of the `if` form.
|
the test succeeds - opposite of the order of the `if` form.
|
||||||
|
|
||||||
@ -732,6 +797,36 @@ any numeric type, empty sequence and empty dictionary are considered `False`.
|
|||||||
Everything else is considered `True`.
|
Everything else is considered `True`.
|
||||||
|
|
||||||
|
|
||||||
|
lisp-if / lif
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
|
For those that prefer a more lisp-y if clause, we have lisp-if, or lif. This
|
||||||
|
*only* considers None/nil as false! All other values of python
|
||||||
|
"falseiness" are considered true.
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: clj
|
||||||
|
|
||||||
|
=> (lisp-if True "true" "false")
|
||||||
|
"true"
|
||||||
|
=> (lisp-if False "true" "false")
|
||||||
|
"true"
|
||||||
|
=> (lisp-if 0 "true" "false")
|
||||||
|
"true"
|
||||||
|
=> (lisp-if nil "true" "false")
|
||||||
|
"false"
|
||||||
|
=> (lisp-if None "true" "false")
|
||||||
|
"false"
|
||||||
|
|
||||||
|
; And, same thing
|
||||||
|
=> (lif True "true" "false")
|
||||||
|
"true"
|
||||||
|
=> (lif nil "true" "false")
|
||||||
|
"false"
|
||||||
|
|
||||||
|
|
||||||
import
|
import
|
||||||
------
|
------
|
||||||
|
|
||||||
@ -766,32 +861,6 @@ of import you can use.
|
|||||||
(import [sys [*]])
|
(import [sys [*]])
|
||||||
|
|
||||||
|
|
||||||
kwapply
|
|
||||||
-------
|
|
||||||
|
|
||||||
`kwapply` can be used to supply keyword arguments to a function.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
.. code-block:: clj
|
|
||||||
|
|
||||||
=> (defn rent-car [&kwargs kwargs]
|
|
||||||
... (cond [(in :brand kwargs) (print "brand:" (:brand kwargs))]
|
|
||||||
... [(in :model kwargs) (print "model:" (:model kwargs))]))
|
|
||||||
|
|
||||||
=> (kwapply (rent-car) {:model "T-Model"})
|
|
||||||
model: T-Model
|
|
||||||
|
|
||||||
=> (defn total-purchase [price amount &optional [fees 1.05] [vat 1.1]]
|
|
||||||
... (* price amount fees vat))
|
|
||||||
|
|
||||||
=> (total-purchase 10 15)
|
|
||||||
173.25
|
|
||||||
|
|
||||||
=> (kwapply (total-purchase 10 15) {"vat" 1.05})
|
|
||||||
165.375
|
|
||||||
|
|
||||||
|
|
||||||
lambda / fn
|
lambda / fn
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
@ -818,11 +887,15 @@ Just as in normal function definitions, if the first element of the
|
|||||||
body is a string, it serves as docstring. This is useful for giving
|
body is a string, it serves as docstring. This is useful for giving
|
||||||
class methods docstrings.
|
class methods docstrings.
|
||||||
|
|
||||||
|
.. code-block:: clj
|
||||||
|
|
||||||
=> (setv times-three
|
=> (setv times-three
|
||||||
... (fn [x]
|
... (fn [x]
|
||||||
... "Multiplies input by three and returns the result."
|
... "Multiplies input by three and returns the result."
|
||||||
... (* x 3)))
|
... (* x 3)))
|
||||||
|
|
||||||
|
Then test it via the Python built-in ``help`` function::
|
||||||
|
|
||||||
=> (help times-three)
|
=> (help times-three)
|
||||||
Help on function times_three:
|
Help on function times_three:
|
||||||
|
|
||||||
@ -919,21 +992,13 @@ parameter will be returned.
|
|||||||
1
|
1
|
||||||
|
|
||||||
.. note:: `or` shortcuts and stops evaluating parameters as soon as the first
|
.. note:: `or` shortcuts and stops evaluating parameters as soon as the first
|
||||||
true is encountered. However, in the current implementation of Hy
|
true is encountered.
|
||||||
statements are executed as soon as they are converted to expressions.
|
|
||||||
The following two examples demonstrates the difference.
|
|
||||||
|
|
||||||
.. code-block:: clj
|
.. code-block:: clj
|
||||||
|
|
||||||
=> (or True (print "hello"))
|
=> (or True (print "hello"))
|
||||||
hello
|
|
||||||
True
|
True
|
||||||
|
|
||||||
=> (defn side-effects [x] (print "I can has" x) x)
|
|
||||||
=> (or (side-effects 42) (side-effects False))
|
|
||||||
I can has 42
|
|
||||||
42
|
|
||||||
|
|
||||||
|
|
||||||
print
|
print
|
||||||
-----
|
-----
|
||||||
@ -1009,6 +1074,22 @@ element:
|
|||||||
[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
|
||||||
|
|
||||||
|
set-comp
|
||||||
|
--------
|
||||||
|
|
||||||
|
`set-comp` is used to create sets. It takes two or three parameters.
|
||||||
|
The first parameter is for controlling the return value, while the second is
|
||||||
|
used to select items from a sequence. The third and optional parameter can be
|
||||||
|
used to filter out some of the items in the sequence based on a conditional
|
||||||
|
expression.
|
||||||
|
|
||||||
|
.. code-block:: hy
|
||||||
|
|
||||||
|
=> (setv data [1 2 3 4 5 2 3 4 5 3 4 5])
|
||||||
|
=> (set-comp x [x data] (odd? x))
|
||||||
|
{1, 3, 5}
|
||||||
|
|
||||||
|
|
||||||
slice
|
slice
|
||||||
-----
|
-----
|
||||||
|
|
||||||
@ -1220,14 +1301,14 @@ with-gensyms
|
|||||||
`with-gensym` form is used to generate a set of :ref:`gensym` for use
|
`with-gensym` form is used to generate a set of :ref:`gensym` for use
|
||||||
in a macro.
|
in a macro.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(with-gensyms [a b c]
|
(with-gensyms [a b c]
|
||||||
...)
|
...)
|
||||||
|
|
||||||
expands to:
|
expands to:
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(let [[a (gensym)
|
(let [[a (gensym)
|
||||||
[b (gensym)
|
[b (gensym)
|
||||||
@ -1267,23 +1348,15 @@ infinite series without consuming infinite amount of memory.
|
|||||||
=> (list-comp x [x (take 15 (random-numbers 1 50))])])
|
=> (list-comp x [x (take 15 (random-numbers 1 50))])])
|
||||||
[7, 41, 6, 22, 32, 17, 5, 38, 18, 38, 17, 14, 23, 23, 19]
|
[7, 41, 6, 22, 32, 17, 5, 38, 18, 38, 17, 14, 23, 23, 19]
|
||||||
|
|
||||||
.. _zipwith:
|
|
||||||
|
|
||||||
zipwith
|
yield-from
|
||||||
-------
|
----------
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.9.13
|
||||||
|
|
||||||
`zipwith` zips multiple lists and maps the given function over the result. It is
|
**PYTHON 3.3 AND UP ONLY!**
|
||||||
equilavent to calling ``zip``, followed by calling ``map`` on the result.
|
|
||||||
|
|
||||||
In the following example, `zipwith` is used to add the contents of two lists
|
`yield-from` is used to call a subgenerator. This is useful if you
|
||||||
together. The equilavent ``map`` and ``zip`` calls follow.
|
want your coroutine to be able to delegate its processes to another
|
||||||
|
coroutine, say if using something fancy like
|
||||||
.. code-block:: clj
|
`asyncio <http://docs.python.org/3.4/library/asyncio.html>`_.
|
||||||
|
|
||||||
=> (import operator.add)
|
|
||||||
=> (zipwith operator.add [1 2 3] [4 5 6]) ; using zipwith
|
|
||||||
[5, 7, 9]
|
|
||||||
=> (map operator.add (zip [1 2 3] [4 5 6])) ; using map+zip
|
|
||||||
[5, 7, 9]
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
Command Line Interface
|
Command Line Interface
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
.. _hy:
|
||||||
|
|
||||||
hy
|
hy
|
||||||
--
|
--
|
||||||
|
|
||||||
@ -46,6 +48,8 @@ Command line options
|
|||||||
Print the Hy version number and exit.
|
Print the Hy version number and exit.
|
||||||
|
|
||||||
|
|
||||||
|
.. _hyc:
|
||||||
|
|
||||||
hyc
|
hyc
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -57,7 +61,7 @@ Command line options
|
|||||||
Compile Hy code to Python bytecode. For example, save the
|
Compile Hy code to Python bytecode. For example, save the
|
||||||
following code as ``hyname.hy``:
|
following code as ``hyname.hy``:
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(defn hy-hy [name]
|
(defn hy-hy [name]
|
||||||
(print (+ "Hy " name "!")))
|
(print (+ "Hy " name "!")))
|
||||||
@ -71,3 +75,29 @@ Command line options
|
|||||||
$ hyc hyname.hy
|
$ hyc hyname.hy
|
||||||
$ python hyname.pyc
|
$ python hyname.pyc
|
||||||
Hy Afroman!
|
Hy Afroman!
|
||||||
|
|
||||||
|
|
||||||
|
.. _hy2py:
|
||||||
|
|
||||||
|
hy2py
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. versionadded:: 0.10.1
|
||||||
|
|
||||||
|
Command line options
|
||||||
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. cmdoption:: -s
|
||||||
|
--with-source
|
||||||
|
|
||||||
|
Show the parsed source structure.
|
||||||
|
|
||||||
|
.. cmdoption:: -a
|
||||||
|
--with-ast
|
||||||
|
|
||||||
|
Show the generated AST.
|
||||||
|
|
||||||
|
.. cmdoption:: -np
|
||||||
|
--without-python
|
||||||
|
|
||||||
|
Do not show the Python code generated from the AST.
|
||||||
|
@ -11,13 +11,13 @@ Core Functions
|
|||||||
coll?
|
coll?
|
||||||
-----
|
-----
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
Usage: ``(coll? x)``
|
Usage: ``(coll? x)``
|
||||||
|
|
||||||
Returns true if argument is iterable and not a string.
|
Returns true if argument is iterable and not a string.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (coll? [1 2 3 4])
|
=> (coll? [1 2 3 4])
|
||||||
True
|
True
|
||||||
@ -32,13 +32,13 @@ Returns true if argument is iterable and not a string.
|
|||||||
cons
|
cons
|
||||||
----
|
----
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
Usage: ``(cons a b)``
|
Usage: ``(cons a b)``
|
||||||
|
|
||||||
Returns a fresh :ref:`cons cell <hycons>` with car `a` and cdr `b`.
|
Returns a fresh :ref:`cons cell <hycons>` with car `a` and cdr `b`.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (setv a (cons 'hd 'tl))
|
=> (setv a (cons 'hd 'tl))
|
||||||
|
|
||||||
@ -52,13 +52,13 @@ Returns a fresh :ref:`cons cell <hycons>` with car `a` and cdr `b`.
|
|||||||
cons?
|
cons?
|
||||||
-----
|
-----
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
Usage: ``(cons? foo)``
|
Usage: ``(cons? foo)``
|
||||||
|
|
||||||
Checks whether ``foo`` is a :ref:`cons cell <hycons>`.
|
Checks whether ``foo`` is a :ref:`cons cell <hycons>`.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (setv a (cons 'hd 'tl))
|
=> (setv a (cons 'hd 'tl))
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ Return one less than x. Equivalent to ``(- x 1)``.
|
|||||||
|
|
||||||
Raises ``TypeError`` if ``(not (numeric? x))``.
|
Raises ``TypeError`` if ``(not (numeric? x))``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (dec 3)
|
=> (dec 3)
|
||||||
2
|
2
|
||||||
@ -99,14 +99,14 @@ Raises ``TypeError`` if ``(not (numeric? x))``.
|
|||||||
disassemble
|
disassemble
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
Usage: ``(disassemble tree &optional [codegen false])``
|
Usage: ``(disassemble tree &optional [codegen false])``
|
||||||
|
|
||||||
Dump the Python AST for given Hy ``tree`` to standard output. If *codegen*
|
Dump the Python AST for given Hy ``tree`` to standard output. If *codegen*
|
||||||
is ``true`` function prints Python code instead.
|
is ``true`` function prints Python code instead.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (disassemble '(print "Hello World!"))
|
=> (disassemble '(print "Hello World!"))
|
||||||
Module(
|
Module(
|
||||||
@ -126,7 +126,7 @@ Usage: ``(empty? coll)``
|
|||||||
|
|
||||||
Return True if ``coll`` is empty, i.e. ``(= 0 (len coll))``.
|
Return True if ``coll`` is empty, i.e. ``(= 0 (len coll))``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (empty? [])
|
=> (empty? [])
|
||||||
True
|
True
|
||||||
@ -143,13 +143,13 @@ Return True if ``coll`` is empty, i.e. ``(= 0 (len coll))``.
|
|||||||
every?
|
every?
|
||||||
------
|
------
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
Usage: ``(every? pred coll)``
|
Usage: ``(every? pred coll)``
|
||||||
|
|
||||||
Return True if ``(pred x)`` is logical true for every ``x`` in ``coll``, otherwise False. Return True if ``coll`` is empty.
|
Return True if ``(pred x)`` is logical true for every ``x`` in ``coll``, otherwise False. Return True if ``coll`` is empty.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (every? even? [2 4 6])
|
=> (every? even? [2 4 6])
|
||||||
True
|
True
|
||||||
@ -173,7 +173,7 @@ Usage: ``(float? x)``
|
|||||||
|
|
||||||
Return True if x is a float.
|
Return True if x is a float.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (float? 3.2)
|
=> (float? 3.2)
|
||||||
True
|
True
|
||||||
@ -193,7 +193,7 @@ Return True if x is even.
|
|||||||
|
|
||||||
Raises ``TypeError`` if ``(not (numeric? x))``.
|
Raises ``TypeError`` if ``(not (numeric? x))``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (even? 2)
|
=> (even? 2)
|
||||||
True
|
True
|
||||||
@ -214,7 +214,7 @@ Usage: ``(identity x)``
|
|||||||
|
|
||||||
Returns argument supplied to the function
|
Returns argument supplied to the function
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (identity 4)
|
=> (identity 4)
|
||||||
4
|
4
|
||||||
@ -234,7 +234,7 @@ Return one more than x. Equivalent to ``(+ x 1)``.
|
|||||||
|
|
||||||
Raises ``TypeError`` if ``(not (numeric? x))``.
|
Raises ``TypeError`` if ``(not (numeric? x))``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (inc 3)
|
=> (inc 3)
|
||||||
4
|
4
|
||||||
@ -255,7 +255,7 @@ Usage: ``(instance? CLASS x)``
|
|||||||
|
|
||||||
Return True if x is an instance of CLASS.
|
Return True if x is an instance of CLASS.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (instance? float 1.0)
|
=> (instance? float 1.0)
|
||||||
True
|
True
|
||||||
@ -281,7 +281,7 @@ Usage: ``(integer? x)``
|
|||||||
Return True if x is an integer. For Python 2, this is
|
Return True if x is an integer. For Python 2, this is
|
||||||
either ``int`` or ``long``. For Python 3, this is ``int``.
|
either ``int`` or ``long``. For Python 3, this is ``int``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (integer? 3)
|
=> (integer? 3)
|
||||||
True
|
True
|
||||||
@ -300,7 +300,7 @@ Usage: ``(iterable? x)``
|
|||||||
Return True if x is iterable. Iterable objects return a new iterator
|
Return True if x is iterable. Iterable objects return a new iterator
|
||||||
when ``(iter x)`` is called. Contrast with :ref:`iterator?-fn`.
|
when ``(iter x)`` is called. Contrast with :ref:`iterator?-fn`.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> ;; works for strings
|
=> ;; works for strings
|
||||||
=> (iterable? (str "abcde"))
|
=> (iterable? (str "abcde"))
|
||||||
@ -334,7 +334,7 @@ Return True if x is an iterator. Iterators are objects that return
|
|||||||
themselves as an iterator when ``(iter x)`` is called.
|
themselves as an iterator when ``(iter x)`` is called.
|
||||||
Contrast with :ref:`iterable?-fn`.
|
Contrast with :ref:`iterable?-fn`.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> ;; doesn't work for a list
|
=> ;; doesn't work for a list
|
||||||
=> (iterator? [1 2 3 4 5])
|
=> (iterator? [1 2 3 4 5])
|
||||||
@ -360,7 +360,7 @@ Usage: ``(list* head &rest tail)``
|
|||||||
Generate a chain of nested cons cells (a dotted list) containing the
|
Generate a chain of nested cons cells (a dotted list) containing the
|
||||||
arguments. If the argument list only has one element, return it.
|
arguments. If the argument list only has one element, return it.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list* 1 2 3 4)
|
=> (list* 1 2 3 4)
|
||||||
(1 2 3 . 4)
|
(1 2 3 . 4)
|
||||||
@ -379,13 +379,13 @@ arguments. If the argument list only has one element, return it.
|
|||||||
macroexpand
|
macroexpand
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
Usage: ``(macroexpand form)``
|
Usage: ``(macroexpand form)``
|
||||||
|
|
||||||
Returns the full macro expansion of form.
|
Returns the full macro expansion of form.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (macroexpand '(-> (a b) (x y)))
|
=> (macroexpand '(-> (a b) (x y)))
|
||||||
(u'x' (u'a' u'b') u'y')
|
(u'x' (u'a' u'b') u'y')
|
||||||
@ -398,13 +398,13 @@ Returns the full macro expansion of form.
|
|||||||
macroexpand-1
|
macroexpand-1
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
Usage: ``(macroexpand-1 form)``
|
Usage: ``(macroexpand-1 form)``
|
||||||
|
|
||||||
Returns the single step macro expansion of form.
|
Returns the single step macro expansion of form.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (macroexpand-1 '(-> (a b) (-> (c d) (e f))))
|
=> (macroexpand-1 '(-> (a b) (-> (c d) (e f))))
|
||||||
(u'_>' (u'a' u'b') (u'c' u'd') (u'e' u'f'))
|
(u'_>' (u'a' u'b') (u'c' u'd') (u'e' u'f'))
|
||||||
@ -420,7 +420,7 @@ Return True if x is less than zero (0).
|
|||||||
|
|
||||||
Raises ``TypeError`` if ``(not (numeric? x))``.
|
Raises ``TypeError`` if ``(not (numeric? x))``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (neg? -2)
|
=> (neg? -2)
|
||||||
True
|
True
|
||||||
@ -441,7 +441,7 @@ Usage: ``(nil? x)``
|
|||||||
|
|
||||||
Return True if x is nil/None.
|
Return True if x is nil/None.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (nil? nil)
|
=> (nil? nil)
|
||||||
True
|
True
|
||||||
@ -470,7 +470,7 @@ Usage: ``(none? x)``
|
|||||||
|
|
||||||
Return True if x is None.
|
Return True if x is None.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (none? None)
|
=> (none? None)
|
||||||
True
|
True
|
||||||
@ -495,10 +495,10 @@ nth
|
|||||||
Usage: ``(nth coll n)``
|
Usage: ``(nth coll n)``
|
||||||
|
|
||||||
Return the `nth` item in a collection, counting from 0. Unlike
|
Return the `nth` item in a collection, counting from 0. Unlike
|
||||||
``get``, ``nth`` works on both iterators and iterables. Returns ``None``
|
``get``, ``nth`` works on both iterators and iterables. Raises ``IndexError``
|
||||||
if the `n` is outside the range of `coll`.
|
if the `n` is outside the range of ``coll`` or ``ValueError`` if it's negative.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (nth [1 2 4 7] 1)
|
=> (nth [1 2 4 7] 1)
|
||||||
2
|
2
|
||||||
@ -506,8 +506,10 @@ if the `n` is outside the range of `coll`.
|
|||||||
=> (nth [1 2 4 7] 3)
|
=> (nth [1 2 4 7] 3)
|
||||||
7
|
7
|
||||||
|
|
||||||
=> (none? (nth [1 2 4 7] 5))
|
=> (nth [1 2 4 7] 5)
|
||||||
True
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
IndexError: 5
|
||||||
|
|
||||||
=> (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2))
|
=> (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2))
|
||||||
5
|
5
|
||||||
@ -522,7 +524,7 @@ Usage: ``(numeric? x)``
|
|||||||
Return True if x is a numeric, as defined in the Python
|
Return True if x is a numeric, as defined in the Python
|
||||||
numbers module class ``numbers.Number``.
|
numbers module class ``numbers.Number``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (numeric? -2)
|
=> (numeric? -2)
|
||||||
True
|
True
|
||||||
@ -545,7 +547,7 @@ Return True if x is odd.
|
|||||||
|
|
||||||
Raises ``TypeError`` if ``(not (numeric? x))``.
|
Raises ``TypeError`` if ``(not (numeric? x))``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (odd? 13)
|
=> (odd? 13)
|
||||||
True
|
True
|
||||||
@ -568,7 +570,7 @@ Return True if x is greater than zero (0).
|
|||||||
|
|
||||||
Raises ``TypeError`` if ``(not (numeric? x))``.
|
Raises ``TypeError`` if ``(not (numeric? x))``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (pos? 3)
|
=> (pos? 3)
|
||||||
True
|
True
|
||||||
@ -590,7 +592,7 @@ Usage: ``(second coll)``
|
|||||||
Return the second member of ``coll``. Equivalent to
|
Return the second member of ``coll``. Equivalent to
|
||||||
``(get coll 1)``
|
``(get coll 1)``
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (second [0 1 2])
|
=> (second [0 1 2])
|
||||||
1
|
1
|
||||||
@ -601,13 +603,13 @@ Return the second member of ``coll``. Equivalent to
|
|||||||
some
|
some
|
||||||
----
|
----
|
||||||
|
|
||||||
.. versionadded:: 0.9.13
|
.. versionadded:: 0.10.0
|
||||||
|
|
||||||
Usage: ``(some pred coll)``
|
Usage: ``(some pred coll)``
|
||||||
|
|
||||||
Return True if ``(pred x)`` is logical true for any ``x`` in ``coll``, otherwise False. Return False if ``coll`` is empty.
|
Return True if ``(pred x)`` is logical true for any ``x`` in ``coll``, otherwise False. Return False if ``coll`` is empty.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (some even? [2 4 6])
|
=> (some even? [2 4 6])
|
||||||
True
|
True
|
||||||
@ -631,7 +633,7 @@ Usage: ``(string? x)``
|
|||||||
|
|
||||||
Return True if x is a string.
|
Return True if x is a string.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (string? "foo")
|
=> (string? "foo")
|
||||||
True
|
True
|
||||||
@ -648,7 +650,7 @@ Usage: ``(zero? x)``
|
|||||||
|
|
||||||
Return True if x is zero (0).
|
Return True if x is zero (0).
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (zero? 3)
|
=> (zero? 3)
|
||||||
False
|
False
|
||||||
@ -671,7 +673,7 @@ iterator.
|
|||||||
We can use the canonical infinite Fibonacci number generator
|
We can use the canonical infinite Fibonacci number generator
|
||||||
as an example of how to use some of these functions.
|
as an example of how to use some of these functions.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(defn fib []
|
(defn fib []
|
||||||
(setv a 0)
|
(setv a 0)
|
||||||
@ -683,7 +685,7 @@ as an example of how to use some of these functions.
|
|||||||
|
|
||||||
Note the ``(while true ...)`` loop. If we run this in the REPL,
|
Note the ``(while true ...)`` loop. If we run this in the REPL,
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (fib)
|
=> (fib)
|
||||||
<generator object fib at 0x101e642d0>
|
<generator object fib at 0x101e642d0>
|
||||||
@ -694,7 +696,7 @@ work until we consume it. Trying something like this is not recommend as
|
|||||||
the infinite loop will run until it consumes all available RAM, or
|
the infinite loop will run until it consumes all available RAM, or
|
||||||
in this case until I killed it.
|
in this case until I killed it.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (fib))
|
=> (list (fib))
|
||||||
[1] 91474 killed hy
|
[1] 91474 killed hy
|
||||||
@ -703,7 +705,7 @@ in this case until I killed it.
|
|||||||
To get the first 10 Fibonacci numbers, use :ref:`take-fn`. Note that
|
To get the first 10 Fibonacci numbers, use :ref:`take-fn`. Note that
|
||||||
:ref:`take-fn` also returns a generator, so I create a list from it.
|
:ref:`take-fn` also returns a generator, so I create a list from it.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (take 10 (fib)))
|
=> (list (take 10 (fib)))
|
||||||
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
|
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
|
||||||
@ -711,7 +713,7 @@ To get the first 10 Fibonacci numbers, use :ref:`take-fn`. Note that
|
|||||||
|
|
||||||
To get the Fibonacci number at index 9, (starting from 0):
|
To get the Fibonacci number at index 9, (starting from 0):
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (nth (fib) 9)
|
=> (nth (fib) 9)
|
||||||
34
|
34
|
||||||
@ -744,7 +746,7 @@ Usage: ``(distinct coll)``
|
|||||||
|
|
||||||
Returns an iterator containing only the unique members in ``coll``.
|
Returns an iterator containing only the unique members in ``coll``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (distinct [ 1 2 3 4 3 5 2 ]))
|
=> (list (distinct [ 1 2 3 4 3 5 2 ]))
|
||||||
[1, 2, 3, 4, 5]
|
[1, 2, 3, 4, 5]
|
||||||
@ -764,8 +766,9 @@ drop
|
|||||||
Usage: ``(drop n coll)``
|
Usage: ``(drop n coll)``
|
||||||
|
|
||||||
Return an iterator, skipping the first ``n`` members of ``coll``
|
Return an iterator, skipping the first ``n`` members of ``coll``
|
||||||
|
Raises ``ValueError`` if ``n`` is negative.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (drop 2 [1 2 3 4 5]))
|
=> (list (drop 2 [1 2 3 4 5]))
|
||||||
[3, 4, 5]
|
[3, 4, 5]
|
||||||
@ -789,7 +792,7 @@ Usage: ``(drop-while pred coll)``
|
|||||||
Return an iterator, skipping members of ``coll`` until ``pred``
|
Return an iterator, skipping members of ``coll`` until ``pred``
|
||||||
is False.
|
is False.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (drop-while even? [2 4 7 8 9]))
|
=> (list (drop-while even? [2 4 7 8 9]))
|
||||||
[7, 8, 9]
|
[7, 8, 9]
|
||||||
@ -812,7 +815,7 @@ Return an iterator for all items in ``coll`` that pass the predicate ``pred``.
|
|||||||
|
|
||||||
See also :ref:`remove-fn`.
|
See also :ref:`remove-fn`.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (filter pos? [1 2 3 -4 5 -7]))
|
=> (list (filter pos? [1 2 3 -4 5 -7]))
|
||||||
[1, 2, 3, 5]
|
[1, 2, 3, 5]
|
||||||
@ -832,7 +835,7 @@ Usage: ``(flatten coll)``
|
|||||||
Return a single list of all the items in ``coll``, by flattening all
|
Return a single list of all the items in ``coll``, by flattening all
|
||||||
contained lists and/or tuples.
|
contained lists and/or tuples.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (flatten [1 2 [3 4] 5])
|
=> (flatten [1 2 [3 4] 5])
|
||||||
[1, 2, 3, 4, 5]
|
[1, 2, 3, 4, 5]
|
||||||
@ -850,7 +853,7 @@ Usage: ``(iterate fn x)``
|
|||||||
|
|
||||||
Return an iterator of `x`, `fn(x)`, `fn(fn(x))`.
|
Return an iterator of `x`, `fn(x)`, `fn(fn(x))`.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (take 5 (iterate inc 5)))
|
=> (list (take 5 (iterate inc 5)))
|
||||||
[5, 6, 7, 8, 9]
|
[5, 6, 7, 8, 9]
|
||||||
@ -871,7 +874,7 @@ predicate, ``pred``, removed.
|
|||||||
|
|
||||||
See also :ref:`filter-fn`.
|
See also :ref:`filter-fn`.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (remove odd? [1 2 3 4 5 6 7]))
|
=> (list (remove odd? [1 2 3 4 5 6 7]))
|
||||||
[2, 4, 6]
|
[2, 4, 6]
|
||||||
@ -893,7 +896,7 @@ Usage: ``(repeat x)``
|
|||||||
|
|
||||||
Return an iterator (infinite) of ``x``.
|
Return an iterator (infinite) of ``x``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (take 6 (repeat "s")))
|
=> (list (take 6 (repeat "s")))
|
||||||
[u's', u's', u's', u's', u's', u's']
|
[u's', u's', u's', u's', u's', u's']
|
||||||
@ -908,7 +911,7 @@ Usage: ``(repeatedly fn)``
|
|||||||
|
|
||||||
Return an iterator by calling ``fn`` repeatedly.
|
Return an iterator by calling ``fn`` repeatedly.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (import [random [randint]])
|
=> (import [random [randint]])
|
||||||
|
|
||||||
@ -924,8 +927,9 @@ take
|
|||||||
Usage: ``(take n coll)``
|
Usage: ``(take n coll)``
|
||||||
|
|
||||||
Return an iterator containing the first ``n`` members of ``coll``.
|
Return an iterator containing the first ``n`` members of ``coll``.
|
||||||
|
Raises ``ValueError`` if ``n`` is negative.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (take 3 [1 2 3 4 5]))
|
=> (list (take 3 [1 2 3 4 5]))
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
@ -945,7 +949,7 @@ Usage: ``(take-nth n coll)``
|
|||||||
|
|
||||||
Return an iterator containing every ``nth`` member of ``coll``.
|
Return an iterator containing every ``nth`` member of ``coll``.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (take-nth 2 [1 2 3 4 5 6 7]))
|
=> (list (take-nth 2 [1 2 3 4 5 6 7]))
|
||||||
[1, 3, 5, 7]
|
[1, 3, 5, 7]
|
||||||
@ -969,7 +973,7 @@ Usage: ``(take-while pred coll)``
|
|||||||
|
|
||||||
Return an iterator from ``coll`` as long as predicate, ``pred`` returns True.
|
Return an iterator from ``coll`` as long as predicate, ``pred`` returns True.
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
=> (list (take-while pos? [ 1 2 3 -4 5]))
|
=> (list (take-while pos? [ 1 2 3 -4 5]))
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
@ -979,3 +983,21 @@ Return an iterator from ``coll`` as long as predicate, ``pred`` returns True.
|
|||||||
|
|
||||||
=> (list (take-while neg? [ 1 2 3 -4 5]))
|
=> (list (take-while neg? [ 1 2 3 -4 5]))
|
||||||
[]
|
[]
|
||||||
|
|
||||||
|
.. _zipwith:
|
||||||
|
|
||||||
|
zipwith
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. versionadded:: 0.9.13
|
||||||
|
|
||||||
|
Usage: ``(zipwith fn coll ...)``
|
||||||
|
|
||||||
|
Equivalent to ``zip``, but uses a multi-argument function instead of creating a tuple.
|
||||||
|
If ``zipwith`` is called with N collections, then ``fn`` must accept N arguments.
|
||||||
|
|
||||||
|
.. code-block:: clojure
|
||||||
|
|
||||||
|
=> (import operator)
|
||||||
|
=> (list (zipwith operator.add [1 2 3] [4 5 6]))
|
||||||
|
[5, 7, 9]
|
||||||
|
@ -84,7 +84,7 @@ In the input stream, double-quoted strings, respecting the Python
|
|||||||
notation for strings, are parsed as a single token, which is directly
|
notation for strings, are parsed as a single token, which is directly
|
||||||
parsed as a :ref:`HyString`.
|
parsed as a :ref:`HyString`.
|
||||||
|
|
||||||
An ininterrupted string of characters, excluding spaces, brackets,
|
An uninterrupted string of characters, excluding spaces, brackets,
|
||||||
quotes, double-quotes and comments, is parsed as an identifier.
|
quotes, double-quotes and comments, is parsed as an identifier.
|
||||||
|
|
||||||
Identifiers are resolved to atomic models during the parsing phase in
|
Identifiers are resolved to atomic models during the parsing phase in
|
||||||
@ -231,14 +231,14 @@ from source to runtime.
|
|||||||
Steps 1 and 2: Tokenizing and parsing
|
Steps 1 and 2: Tokenizing and parsing
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
The first stage of compiling hy is to lex the source into tokens that we can
|
The first stage of compiling Hy is to lex the source into tokens that we can
|
||||||
deal with. We use a project called rply, which is a really nice (and fast)
|
deal with. We use a project called rply, which is a really nice (and fast)
|
||||||
parser, written in a subset of Python called rpython.
|
parser, written in a subset of Python called rpython.
|
||||||
|
|
||||||
The lexing code is all defined in ``hy.lex.lexer``. This code is mostly just
|
The lexing code is all defined in ``hy.lex.lexer``. This code is mostly just
|
||||||
defining the Hy grammer, and all the actual hard parts are taken care of by
|
defining the Hy grammar, and all the actual hard parts are taken care of by
|
||||||
rply -- we just define "callbacks" for rply in ``hy.lex.parser``, which take
|
rply -- we just define "callbacks" for rply in ``hy.lex.parser``, which takes
|
||||||
the tokens generated, and return the Hy models.
|
the tokens generated, and returns the Hy models.
|
||||||
|
|
||||||
You can think of the Hy models as the "AST" for Hy, it's what Macros operate
|
You can think of the Hy models as the "AST" for Hy, it's what Macros operate
|
||||||
on (directly), and it's what the compiler uses when it compiles Hy down.
|
on (directly), and it's what the compiler uses when it compiles Hy down.
|
||||||
@ -389,7 +389,7 @@ expression is positive, zero or negative.
|
|||||||
|
|
||||||
A first pass might be someting like:
|
A first pass might be someting like:
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(defmacro nif [expr pos-form zero-form neg-form]
|
(defmacro nif [expr pos-form zero-form neg-form]
|
||||||
`(let [[obscure-name ~expr]]
|
`(let [[obscure-name ~expr]]
|
||||||
@ -404,7 +404,7 @@ this is no guarantee.
|
|||||||
The method :ref:`gensym` is designed to generate a new, unique symbol for just
|
The method :ref:`gensym` is designed to generate a new, unique symbol for just
|
||||||
such an occasion. A much better version of ``nif`` would be:
|
such an occasion. A much better version of ``nif`` would be:
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(defmacro nif [expr pos-form zero-form neg-form]
|
(defmacro nif [expr pos-form zero-form neg-form]
|
||||||
(let [[g (gensym)]]
|
(let [[g (gensym)]]
|
||||||
@ -417,14 +417,14 @@ This is an easy case, since there is only one symbol. But if there is
|
|||||||
a need for several gensym's there is a second macro :ref:`with-gensyms` that
|
a need for several gensym's there is a second macro :ref:`with-gensyms` that
|
||||||
basically expands to a series of ``let`` statements:
|
basically expands to a series of ``let`` statements:
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(with-gensyms [a b c]
|
(with-gensyms [a b c]
|
||||||
...)
|
...)
|
||||||
|
|
||||||
expands to:
|
expands to:
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(let [[a (gensym)
|
(let [[a (gensym)
|
||||||
[b (gensym)
|
[b (gensym)
|
||||||
@ -433,7 +433,7 @@ expands to:
|
|||||||
|
|
||||||
so our re-written ``nif`` would look like:
|
so our re-written ``nif`` would look like:
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(defmacro nif [expr pos-form zero-form neg-form]
|
(defmacro nif [expr pos-form zero-form neg-form]
|
||||||
(with-gensyms [g]
|
(with-gensyms [g]
|
||||||
@ -448,7 +448,7 @@ remainder of the symbol. So ``g!a`` would become ``(gensym "a")``.
|
|||||||
|
|
||||||
Our final version of ``nif``, built with ``defmacro/g!`` becomes:
|
Our final version of ``nif``, built with ``defmacro/g!`` becomes:
|
||||||
|
|
||||||
.. code-block:: clojure
|
.. code-block:: hy
|
||||||
|
|
||||||
(defmacro/g! nif [expr pos-form zero-form neg-form]
|
(defmacro/g! nif [expr pos-form zero-form neg-form]
|
||||||
`(let [[~g!res ~expr]]
|
`(let [[~g!res ~expr]]
|
||||||
|
242
docs/make.bat
Normal file
242
docs/make.bat
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" (
|
||||||
|
set SPHINXBUILD=sphinx-build
|
||||||
|
)
|
||||||
|
set BUILDDIR=_build
|
||||||
|
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||||
|
set I18NSPHINXOPTS=%SPHINXOPTS% .
|
||||||
|
if NOT "%PAPER%" == "" (
|
||||||
|
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||||
|
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "" goto help
|
||||||
|
|
||||||
|
if "%1" == "help" (
|
||||||
|
:help
|
||||||
|
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||||
|
echo. html to make standalone HTML files
|
||||||
|
echo. dirhtml to make HTML files named index.html in directories
|
||||||
|
echo. singlehtml to make a single large HTML file
|
||||||
|
echo. pickle to make pickle files
|
||||||
|
echo. json to make JSON files
|
||||||
|
echo. htmlhelp to make HTML files and a HTML help project
|
||||||
|
echo. qthelp to make HTML files and a qthelp project
|
||||||
|
echo. devhelp to make HTML files and a Devhelp project
|
||||||
|
echo. epub to make an epub
|
||||||
|
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||||
|
echo. text to make text files
|
||||||
|
echo. man to make manual pages
|
||||||
|
echo. texinfo to make Texinfo files
|
||||||
|
echo. gettext to make PO message catalogs
|
||||||
|
echo. changes to make an overview over all changed/added/deprecated items
|
||||||
|
echo. xml to make Docutils-native XML files
|
||||||
|
echo. pseudoxml to make pseudoxml-XML files for display purposes
|
||||||
|
echo. linkcheck to check all external links for integrity
|
||||||
|
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "clean" (
|
||||||
|
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||||
|
del /q /s %BUILDDIR%\*
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
%SPHINXBUILD% 2> nul
|
||||||
|
if errorlevel 9009 (
|
||||||
|
echo.
|
||||||
|
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||||
|
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||||
|
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||||
|
echo.may add the Sphinx directory to PATH.
|
||||||
|
echo.
|
||||||
|
echo.If you don't have Sphinx installed, grab it from
|
||||||
|
echo.http://sphinx-doc.org/
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "html" (
|
||||||
|
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "dirhtml" (
|
||||||
|
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "singlehtml" (
|
||||||
|
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "pickle" (
|
||||||
|
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can process the pickle files.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "json" (
|
||||||
|
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can process the JSON files.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "htmlhelp" (
|
||||||
|
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||||
|
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "qthelp" (
|
||||||
|
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||||
|
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||||
|
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\hy.qhcp
|
||||||
|
echo.To view the help file:
|
||||||
|
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\hy.ghc
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "devhelp" (
|
||||||
|
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "epub" (
|
||||||
|
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "latex" (
|
||||||
|
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "latexpdf" (
|
||||||
|
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||||
|
cd %BUILDDIR%/latex
|
||||||
|
make all-pdf
|
||||||
|
cd %BUILDDIR%/..
|
||||||
|
echo.
|
||||||
|
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "latexpdfja" (
|
||||||
|
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||||
|
cd %BUILDDIR%/latex
|
||||||
|
make all-pdf-ja
|
||||||
|
cd %BUILDDIR%/..
|
||||||
|
echo.
|
||||||
|
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "text" (
|
||||||
|
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "man" (
|
||||||
|
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "texinfo" (
|
||||||
|
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "gettext" (
|
||||||
|
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "changes" (
|
||||||
|
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.The overview file is in %BUILDDIR%/changes.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "linkcheck" (
|
||||||
|
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Link check complete; look for any errors in the above output ^
|
||||||
|
or in %BUILDDIR%/linkcheck/output.txt.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "doctest" (
|
||||||
|
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Testing of doctests in the sources finished, look at the ^
|
||||||
|
results in %BUILDDIR%/doctest/output.txt.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "xml" (
|
||||||
|
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "pseudoxml" (
|
||||||
|
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
||||||
|
if errorlevel 1 exit /b 1
|
||||||
|
echo.
|
||||||
|
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
||||||
|
goto end
|
||||||
|
)
|
||||||
|
|
||||||
|
:end
|
@ -181,14 +181,14 @@ for python programmers... now you too can make use of macros'
|
|||||||
incredible power (just be careful to not aim them footward)!
|
incredible power (just be careful to not aim them footward)!
|
||||||
|
|
||||||
|
|
||||||
Hy is python flavored lisp (or vice versa?)
|
Hy is a Lisp flavored Python
|
||||||
===========================================
|
============================
|
||||||
|
|
||||||
Hy converts to python's own abstract syntax tree, so you'll soon start
|
Hy converts to Python's own abstract syntax tree, so you'll soon start
|
||||||
to find that all the familiar power of python is at your fingertips.
|
to find that all the familiar power of python is at your fingertips.
|
||||||
|
|
||||||
You have full access to python's data types and standard library in
|
You have full access to Python's data types and standard library in
|
||||||
hy. Let's experiment with this in the hy interpreter::
|
Hy. Let's experiment with this in the hy interpreter::
|
||||||
|
|
||||||
=> [1 2 3]
|
=> [1 2 3]
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
@ -199,14 +199,13 @@ hy. Let's experiment with this in the hy interpreter::
|
|||||||
=> (, 1 2 3)
|
=> (, 1 2 3)
|
||||||
(1, 2, 3)
|
(1, 2, 3)
|
||||||
|
|
||||||
(You may notice that at present, the common lisp method of quoting
|
If you are familiar with other lisps, you may be interested that Hy
|
||||||
things like so:
|
supports the Common Lisp method of quoting:
|
||||||
|
|
||||||
.. code-block:: clj
|
.. code-block:: clj
|
||||||
|
|
||||||
'(1 2 3)
|
=> '(1 2 3)
|
||||||
|
(1L 2L 3L)
|
||||||
does not work. Instead, use square brackets as above.)
|
|
||||||
|
|
||||||
You also have access to all the builtin types' nice methods::
|
You also have access to all the builtin types' nice methods::
|
||||||
|
|
||||||
@ -397,7 +396,7 @@ The same thing in Hy::
|
|||||||
[1 2 None 42]
|
[1 2 None 42]
|
||||||
=> (optional_arg 1 2 3 4)
|
=> (optional_arg 1 2 3 4)
|
||||||
[1 2 3 4]
|
[1 2 3 4]
|
||||||
=> (kwapply (optional_arg)
|
=> (apply optional_arg []
|
||||||
... {"keyword1" 1
|
... {"keyword1" 1
|
||||||
... "pos2" 2
|
... "pos2" 2
|
||||||
... "pos1" 3
|
... "pos1" 3
|
||||||
@ -405,7 +404,7 @@ The same thing in Hy::
|
|||||||
...
|
...
|
||||||
[3, 2, 1, 4]
|
[3, 2, 1, 4]
|
||||||
|
|
||||||
See how we use kwapply to handle the fancy passing? :)
|
See how we use apply to handle the fancy passing? :)
|
||||||
|
|
||||||
There's also a dictionary-style keyword arguments construction that
|
There's also a dictionary-style keyword arguments construction that
|
||||||
looks like:
|
looks like:
|
||||||
@ -480,7 +479,7 @@ In Hy:
|
|||||||
.. code-block:: clj
|
.. code-block:: clj
|
||||||
|
|
||||||
(defclass Customer [models.Model]
|
(defclass Customer [models.Model]
|
||||||
[[name (kwapply (models.CharField) {"max_length" 255})]
|
[[name (apply models.CharField [] {"max_length" 255})]
|
||||||
[address (models.TextField)]
|
[address (models.TextField)]
|
||||||
[notes (models.TextField)]])
|
[notes (models.TextField)]])
|
||||||
|
|
||||||
|
12
eg/curry/ski.hy
Normal file
12
eg/curry/ski.hy
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
(require hy.contrib.curry)
|
||||||
|
|
||||||
|
|
||||||
|
(defnc s [x y z] ((x z) (y z))) ; λxyz.xz(yz)
|
||||||
|
(defnc k [x] (fn [y] x)) ; λx.λy.x
|
||||||
|
(defnc i [x] x) ;; λx.x
|
||||||
|
|
||||||
|
(defnc succ [n] (+ n 1))
|
||||||
|
|
||||||
|
|
||||||
|
(print (((((s ((((k s) k) i) i)) (i i)) ((i (i i))
|
||||||
|
((((k s) i) ((s (k s)) k)) i))) succ) 0))
|
@ -2,13 +2,16 @@
|
|||||||
;;; Copyright (c) Paul R. Tagliamonte, 2013, MIT/Expat license.
|
;;; Copyright (c) Paul R. Tagliamonte, 2013, MIT/Expat license.
|
||||||
|
|
||||||
|
|
||||||
(import [urllib2 [urlopen]]
|
(import [lxml [etree]]
|
||||||
[lxml [etree]]
|
|
||||||
[sys [argv]])
|
[sys [argv]])
|
||||||
|
|
||||||
|
(try
|
||||||
|
(import [urllib.request [urlopen]])
|
||||||
|
(catch [ImportError]
|
||||||
|
(import [urllib2 [urlopen]])))
|
||||||
|
|
||||||
(defn get-rss-feed-name [tumblr]
|
(defn get-rss-feed-name [tumblr]
|
||||||
(kwapply (.format "http://{tumblr}.tumblr.com/rss") {"tumblr" tumblr}))
|
(.format "http://{0}.tumblr.com/rss" tumblr))
|
||||||
|
|
||||||
(defn get-rss-feed [tumblr]
|
(defn get-rss-feed [tumblr]
|
||||||
(.parse etree (urlopen (get-rss-feed-name tumblr))))
|
(.parse etree (urlopen (get-rss-feed-name tumblr))))
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
|
|
||||||
(defn get-legislators [state]
|
(defn get-legislators [state]
|
||||||
(kwapply (.legislators openstates) {"state" state}))
|
(apply openstates.legislators [] {"state" state}))
|
||||||
|
|
||||||
|
|
||||||
(defn get-party-breakdown [state]
|
(defn get-party-breakdown [state]
|
||||||
|
@ -23,7 +23,7 @@ import imp
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
# This just mocks the normalish behavior of the Python interp. Helpful to aid
|
# This just mocks the normalish behavior of the Python interp. Helpful to aid
|
||||||
# with shiming existing apps that don't really "work" with Hy.
|
# with shimming existing apps that don't really "work" with Hy.
|
||||||
#
|
#
|
||||||
# You could say this script helps Hyjack a file.
|
# You could say this script helps Hyjack a file.
|
||||||
#
|
#
|
||||||
|
@ -25,16 +25,21 @@
|
|||||||
# 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 __future__ import print_function
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import code
|
import code
|
||||||
import ast
|
import ast
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import astor.codegen
|
||||||
|
|
||||||
import hy
|
import hy
|
||||||
|
|
||||||
from hy.lex import LexException, PrematureEndOfInput, tokenize
|
from hy.lex import LexException, PrematureEndOfInput, tokenize
|
||||||
from hy.compiler import hy_compile, HyTypeError
|
from hy.compiler import hy_compile, HyTypeError
|
||||||
from hy.importer import ast_compile, import_buffer_to_module
|
from hy.importer import (ast_compile, import_buffer_to_module,
|
||||||
|
import_file_to_ast, import_file_to_hst)
|
||||||
from hy.completer import completion
|
from hy.completer import completion
|
||||||
|
|
||||||
from hy.macros import macro, require
|
from hy.macros import macro, require
|
||||||
@ -66,7 +71,6 @@ builtins.exit = HyQuitter('exit')
|
|||||||
|
|
||||||
|
|
||||||
def print_python_code(_ast):
|
def print_python_code(_ast):
|
||||||
import astor.codegen
|
|
||||||
# astor cannot handle ast.Interactive, so disguise it as a module
|
# astor cannot handle ast.Interactive, so disguise it as a module
|
||||||
_ast_for_print = ast.Module()
|
_ast_for_print = ast.Module()
|
||||||
_ast_for_print.body = _ast.body
|
_ast_for_print.body = _ast.body
|
||||||
@ -313,3 +317,43 @@ def hyc_main():
|
|||||||
sys.stderr.write("hyc: Can't open file '%s': [Errno %d] %s\n" %
|
sys.stderr.write("hyc: Can't open file '%s': [Errno %d] %s\n" %
|
||||||
(x.filename, x.errno, x.strerror))
|
(x.filename, x.errno, x.strerror))
|
||||||
sys.exit(x.errno)
|
sys.exit(x.errno)
|
||||||
|
|
||||||
|
|
||||||
|
# entry point for cmd line script "hy2py"
|
||||||
|
def hy2py_main():
|
||||||
|
module_name = "<STDIN>"
|
||||||
|
|
||||||
|
options = dict(prog="hy2py", usage="%(prog)s [options] FILE",
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
parser = argparse.ArgumentParser(**options)
|
||||||
|
parser.add_argument("--with-source", "-s", action="store_true",
|
||||||
|
help="Show the parsed source structure")
|
||||||
|
parser.add_argument("--with-ast", "-a", action="store_true",
|
||||||
|
help="Show the generated AST")
|
||||||
|
parser.add_argument("--without-python", "-np", action="store_true",
|
||||||
|
help=("Do not show the Python code generated "
|
||||||
|
"from the AST"))
|
||||||
|
parser.add_argument('args', nargs=argparse.REMAINDER,
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
|
|
||||||
|
options = parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
if not options.args:
|
||||||
|
parser.exit(1, parser.format_help())
|
||||||
|
|
||||||
|
if options.with_source:
|
||||||
|
hst = import_file_to_hst(options.args[0])
|
||||||
|
print(hst)
|
||||||
|
print()
|
||||||
|
print()
|
||||||
|
|
||||||
|
_ast = import_file_to_ast(options.args[0], module_name)
|
||||||
|
if options.with_ast:
|
||||||
|
print(astor.dump(_ast))
|
||||||
|
print()
|
||||||
|
print()
|
||||||
|
|
||||||
|
if not options.without_python:
|
||||||
|
print(astor.codegen.to_source(_ast))
|
||||||
|
|
||||||
|
parser.exit(0)
|
||||||
|
@ -732,25 +732,10 @@ class HyASTCompiler(object):
|
|||||||
handler_results += self._compile_catch_expression(e, name)
|
handler_results += self._compile_catch_expression(e, name)
|
||||||
handlers.append(handler_results.stmts.pop())
|
handlers.append(handler_results.stmts.pop())
|
||||||
elif e[0] == HySymbol("else"):
|
elif e[0] == HySymbol("else"):
|
||||||
if orelse:
|
orelse = self.try_except_helper(e, HySymbol("else"), orelse)
|
||||||
raise HyTypeError(
|
|
||||||
e,
|
|
||||||
"`try' cannot have more than one `else'")
|
|
||||||
else:
|
|
||||||
orelse = self._compile_branch(e[1:])
|
|
||||||
# XXX tempvar magic
|
|
||||||
orelse += orelse.expr_as_stmt()
|
|
||||||
orelse = orelse.stmts
|
|
||||||
elif e[0] == HySymbol("finally"):
|
elif e[0] == HySymbol("finally"):
|
||||||
if finalbody:
|
finalbody = self.try_except_helper(e, HySymbol("finally"),
|
||||||
raise HyTypeError(
|
finalbody)
|
||||||
e,
|
|
||||||
"`try' cannot have more than one `finally'")
|
|
||||||
else:
|
|
||||||
finalbody = self._compile_branch(e[1:])
|
|
||||||
# XXX tempvar magic
|
|
||||||
finalbody += finalbody.expr_as_stmt()
|
|
||||||
finalbody = finalbody.stmts
|
|
||||||
else:
|
else:
|
||||||
raise HyTypeError(e, "Unknown expression in `try'")
|
raise HyTypeError(e, "Unknown expression in `try'")
|
||||||
|
|
||||||
@ -768,8 +753,8 @@ class HyASTCompiler(object):
|
|||||||
col_offset=expr.start_column,
|
col_offset=expr.start_column,
|
||||||
type=None,
|
type=None,
|
||||||
name=None,
|
name=None,
|
||||||
body=[ast.Pass(lineno=expr.start_line,
|
body=[ast.Raise(lineno=expr.start_line,
|
||||||
col_offset=expr.start_column)])]
|
col_offset=expr.start_column)])]
|
||||||
|
|
||||||
ret = handler_results
|
ret = handler_results
|
||||||
|
|
||||||
@ -809,6 +794,17 @@ class HyASTCompiler(object):
|
|||||||
body=body,
|
body=body,
|
||||||
orelse=orelse) + returnable
|
orelse=orelse) + returnable
|
||||||
|
|
||||||
|
def try_except_helper(self, hy_obj, symbol, accumulated):
|
||||||
|
if accumulated:
|
||||||
|
raise HyTypeError(
|
||||||
|
hy_obj,
|
||||||
|
"`try' cannot have more than one `%s'" % symbol)
|
||||||
|
else:
|
||||||
|
accumulated = self._compile_branch(hy_obj[1:])
|
||||||
|
accumulated += accumulated.expr_as_stmt()
|
||||||
|
accumulated = accumulated.stmts
|
||||||
|
return accumulated
|
||||||
|
|
||||||
@builds("except")
|
@builds("except")
|
||||||
@builds("catch")
|
@builds("catch")
|
||||||
def magic_internal_form(self, expr):
|
def magic_internal_form(self, expr):
|
||||||
@ -1017,6 +1013,28 @@ class HyASTCompiler(object):
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@builds("yield_from")
|
||||||
|
@checkargs(max=1)
|
||||||
|
def compile_yield_from_expression(self, expr):
|
||||||
|
if not PY33:
|
||||||
|
raise HyCompileError(
|
||||||
|
"yield-from only supported in python 3.3+!")
|
||||||
|
|
||||||
|
expr.pop(0)
|
||||||
|
ret = Result(contains_yield=True)
|
||||||
|
|
||||||
|
value = None
|
||||||
|
if expr != []:
|
||||||
|
ret += self.compile(expr.pop(0))
|
||||||
|
value = ret.force_expr
|
||||||
|
|
||||||
|
ret += ast.YieldFrom(
|
||||||
|
value=value,
|
||||||
|
lineno=expr.start_line,
|
||||||
|
col_offset=expr.start_column)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
@builds("import")
|
@builds("import")
|
||||||
def compile_import_expression(self, expr):
|
def compile_import_expression(self, expr):
|
||||||
def _compile_import(expr, module, names=None, importer=ast.Import):
|
def _compile_import(expr, module, names=None, importer=ast.Import):
|
||||||
@ -1494,7 +1512,7 @@ class HyASTCompiler(object):
|
|||||||
def compile_require(self, expression):
|
def compile_require(self, expression):
|
||||||
"""
|
"""
|
||||||
TODO: keep track of what we've imported in this run and then
|
TODO: keep track of what we've imported in this run and then
|
||||||
"unimport" it after we've completed `thing' so that we don't polute
|
"unimport" it after we've completed `thing' so that we don't pollute
|
||||||
other envs.
|
other envs.
|
||||||
"""
|
"""
|
||||||
expression.pop(0)
|
expression.pop(0)
|
||||||
|
20
hy/contrib/curry.hy
Normal file
20
hy/contrib/curry.hy
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
(import inspect functools sys)
|
||||||
|
|
||||||
|
|
||||||
|
(defn curry [func]
|
||||||
|
(let [[sig (.getargspec inspect func)]
|
||||||
|
[count (len sig.args)]]
|
||||||
|
|
||||||
|
(fn [&rest args]
|
||||||
|
(if (< (len args) count)
|
||||||
|
(apply functools.partial (+ [(curry func)] (list args)))
|
||||||
|
(apply func args)))))
|
||||||
|
|
||||||
|
|
||||||
|
(defmacro fnc [args &rest body]
|
||||||
|
`(do (import hy.contrib.curry)
|
||||||
|
(with-decorator hy.contrib.curry.curry (fn [~@args] ~@body))))
|
||||||
|
|
||||||
|
|
||||||
|
(defmacro defnc [name args &rest body]
|
||||||
|
`(def ~name (fnc [~@args] ~@body)))
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
(defmacro route-with-methods [name path methods params &rest code]
|
(defmacro route-with-methods [name path methods params &rest code]
|
||||||
"Same as route but with an extra methods array to specify HTTP methods"
|
"Same as route but with an extra methods array to specify HTTP methods"
|
||||||
`(let [[deco (kwapply (.route app ~path)
|
`(let [[deco (apply app.route [~path]
|
||||||
{"methods" ~methods})]]
|
{"methods" ~methods})]]
|
||||||
(with-decorator deco
|
(with-decorator deco
|
||||||
(defn ~name ~params
|
(defn ~name ~params
|
||||||
|
@ -46,6 +46,6 @@
|
|||||||
(.disable ~g!hy-pr)
|
(.disable ~g!hy-pr)
|
||||||
(setv ~g!hy-s (StringIO))
|
(setv ~g!hy-s (StringIO))
|
||||||
(setv ~g!hy-ps
|
(setv ~g!hy-ps
|
||||||
(.sort-stats (kwapply (.Stats pstats ~g!hy-pr) {"stream" ~g!hy-s})))
|
(.sort-stats (apply pstats.Stats [~g!hy-pr] {"stream" ~g!hy-s})))
|
||||||
(.print-stats ~g!hy-ps)
|
(.print-stats ~g!hy-ps)
|
||||||
(print (.getvalue ~g!hy-s))))
|
(print (.getvalue ~g!hy-s))))
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
;;;; to make functional programming slightly easier.
|
;;;; to make functional programming slightly easier.
|
||||||
;;;;
|
;;;;
|
||||||
|
|
||||||
|
(import itertools)
|
||||||
|
(import functools)
|
||||||
|
(import collections)
|
||||||
(import [hy._compat [long-type]]) ; long for python2, int for python3
|
(import [hy._compat [long-type]]) ; long for python2, int for python3
|
||||||
(import [hy.models.cons [HyCons]])
|
(import [hy.models.cons [HyCons]])
|
||||||
|
|
||||||
@ -34,7 +36,7 @@
|
|||||||
|
|
||||||
(defn butlast [coll]
|
(defn butlast [coll]
|
||||||
"Returns coll except of last element."
|
"Returns coll except of last element."
|
||||||
(slice coll 0 (dec (len coll))))
|
(itertools.islice coll 0 (dec (len coll))))
|
||||||
|
|
||||||
(defn coll? [coll]
|
(defn coll? [coll]
|
||||||
"Checks whether item is a collection"
|
"Checks whether item is a collection"
|
||||||
@ -48,15 +50,11 @@
|
|||||||
"Check whether c can be used as a cons object"
|
"Check whether c can be used as a cons object"
|
||||||
(instance? HyCons c))
|
(instance? HyCons c))
|
||||||
|
|
||||||
(defn cycle [coll]
|
(defn keyword? [k]
|
||||||
"Yield an infinite repetition of the items in coll"
|
"Check whether k is a keyword"
|
||||||
(setv seen [])
|
(and (instance? (type :foo) k)
|
||||||
(for* [x coll]
|
(.startswith k (get :foo 0))))
|
||||||
(yield x)
|
|
||||||
(.append seen x))
|
|
||||||
(while seen
|
|
||||||
(for* [x seen]
|
|
||||||
(yield x))))
|
|
||||||
|
|
||||||
(defn dec [n]
|
(defn dec [n]
|
||||||
"Decrement n by 1"
|
"Decrement n by 1"
|
||||||
@ -86,22 +84,36 @@
|
|||||||
(yield val)
|
(yield val)
|
||||||
(.add seen val))))))
|
(.add seen val))))))
|
||||||
|
|
||||||
|
(if-python2
|
||||||
|
(do
|
||||||
|
(setv filterfalse itertools.ifilterfalse)
|
||||||
|
(setv zip_longest itertools.izip_longest)
|
||||||
|
(setv filter itertools.ifilter)
|
||||||
|
(setv map itertools.imap)
|
||||||
|
(setv zip itertools.izip)
|
||||||
|
(setv range xrange)
|
||||||
|
(setv input raw_input))
|
||||||
|
(do
|
||||||
|
(setv reduce functools.reduce)
|
||||||
|
(setv filterfalse itertools.filterfalse)
|
||||||
|
(setv zip_longest itertools.zip_longest)
|
||||||
|
; Someone can import these directly from `hy.core.language`;
|
||||||
|
; we'll make some duplicates.
|
||||||
|
(setv filter filter)
|
||||||
|
(setv map map)
|
||||||
|
(setv zip zip)
|
||||||
|
(setv range range)
|
||||||
|
(setv input input)))
|
||||||
|
|
||||||
|
(setv cycle itertools.cycle)
|
||||||
|
(setv repeat itertools.repeat)
|
||||||
|
(setv drop-while itertools.dropwhile)
|
||||||
|
(setv take-while itertools.takewhile)
|
||||||
|
(setv zipwith map)
|
||||||
|
|
||||||
(defn drop [count coll]
|
(defn drop [count coll]
|
||||||
"Drop `count` elements from `coll` and yield back the rest"
|
"Drop `count` elements from `coll` and yield back the rest"
|
||||||
(let [[citer (iter coll)]]
|
(itertools.islice coll count nil))
|
||||||
(try (for* [i (range count)]
|
|
||||||
(next citer))
|
|
||||||
(catch [StopIteration]))
|
|
||||||
citer))
|
|
||||||
|
|
||||||
(defn drop-while [pred coll]
|
|
||||||
"Drop all elements of `coll` until `pred` is False"
|
|
||||||
(let [[citer (iter coll)]]
|
|
||||||
(for* [val citer]
|
|
||||||
(if (not (pred val))
|
|
||||||
(do (yield val) (break))))
|
|
||||||
(for* [val citer]
|
|
||||||
(yield val))))
|
|
||||||
|
|
||||||
(defn empty? [coll]
|
(defn empty? [coll]
|
||||||
"Return True if `coll` is empty"
|
"Return True if `coll` is empty"
|
||||||
@ -118,20 +130,13 @@
|
|||||||
|
|
||||||
(defn fake-source-positions [tree]
|
(defn fake-source-positions [tree]
|
||||||
"Fake the source positions for a given tree"
|
"Fake the source positions for a given tree"
|
||||||
(if (and (iterable? tree) (not (string? tree)))
|
(if (coll? tree)
|
||||||
(for* [subtree tree]
|
(for* [subtree tree]
|
||||||
(fake-source-positions subtree)))
|
(fake-source-positions subtree)))
|
||||||
(for* [attr '[start-line end-line start-column end-column]]
|
(for* [attr '[start-line end-line start-column end-column]]
|
||||||
(if (not (hasattr tree attr))
|
(if (not (hasattr tree attr))
|
||||||
(setattr tree attr 1))))
|
(setattr tree attr 1))))
|
||||||
|
|
||||||
(defn filter [pred coll]
|
|
||||||
"Return all elements from `coll` that pass `pred`"
|
|
||||||
(let [[citer (iter coll)]]
|
|
||||||
(for* [val citer]
|
|
||||||
(if (pred val)
|
|
||||||
(yield val)))))
|
|
||||||
|
|
||||||
(defn flatten [coll]
|
(defn flatten [coll]
|
||||||
"Return a single flat list expanding all members of coll"
|
"Return a single flat list expanding all members of coll"
|
||||||
(if (coll? coll)
|
(if (coll? coll)
|
||||||
@ -139,7 +144,7 @@
|
|||||||
(raise (TypeError (.format "{0!r} is not a collection" coll)))))
|
(raise (TypeError (.format "{0!r} is not a collection" coll)))))
|
||||||
|
|
||||||
(defn _flatten [coll result]
|
(defn _flatten [coll result]
|
||||||
(if (and (iterable? coll) (not (string? coll)))
|
(if (coll? coll)
|
||||||
(do (for* [b coll]
|
(do (for* [b coll]
|
||||||
(_flatten b result)))
|
(_flatten b result)))
|
||||||
(.append result coll))
|
(.append result coll))
|
||||||
@ -173,7 +178,7 @@
|
|||||||
|
|
||||||
(defn first [coll]
|
(defn first [coll]
|
||||||
"Return first item from `coll`"
|
"Return first item from `coll`"
|
||||||
(get coll 0))
|
(nth coll 0))
|
||||||
|
|
||||||
(defn identity [x]
|
(defn identity [x]
|
||||||
"Returns the argument unchanged"
|
"Returns the argument unchanged"
|
||||||
@ -198,14 +203,13 @@
|
|||||||
(defn integer-char? [x]
|
(defn integer-char? [x]
|
||||||
"Return True if char `x` parses as an integer"
|
"Return True if char `x` parses as an integer"
|
||||||
(try
|
(try
|
||||||
(integer? (int x))
|
(integer? (int x))
|
||||||
(catch [e ValueError] False)
|
(catch [e ValueError] False)
|
||||||
(catch [e TypeError] False)))
|
(catch [e TypeError] False)))
|
||||||
|
|
||||||
(defn iterable? [x]
|
(defn iterable? [x]
|
||||||
"Return true if x is iterable"
|
"Return true if x is iterable"
|
||||||
(try (do (iter x) true)
|
(isinstance x collections.Iterable))
|
||||||
(catch [Exception] false)))
|
|
||||||
|
|
||||||
(defn iterate [f x]
|
(defn iterate [f x]
|
||||||
(setv val x)
|
(setv val x)
|
||||||
@ -215,8 +219,7 @@
|
|||||||
|
|
||||||
(defn iterator? [x]
|
(defn iterator? [x]
|
||||||
"Return true if x is an iterator"
|
"Return true if x is an iterator"
|
||||||
(try (= x (iter x))
|
(isinstance x collections.Iterator))
|
||||||
(catch [TypeError] false)))
|
|
||||||
|
|
||||||
(defn list* [hd &rest tl]
|
(defn list* [hd &rest tl]
|
||||||
"Return a dotted list construed from the elements of the argument"
|
"Return a dotted list construed from the elements of the argument"
|
||||||
@ -257,13 +260,9 @@
|
|||||||
|
|
||||||
(defn nth [coll index]
|
(defn nth [coll index]
|
||||||
"Return nth item in collection or sequence, counting from 0"
|
"Return nth item in collection or sequence, counting from 0"
|
||||||
(if (not (neg? index))
|
(try
|
||||||
(if (iterable? coll)
|
(next (drop index coll))
|
||||||
(try (get (list (take 1 (drop index coll))) 0)
|
(catch [e StopIteration] (raise (IndexError index)))))
|
||||||
(catch [IndexError] None))
|
|
||||||
(try (get coll index)
|
|
||||||
(catch [IndexError] None)))
|
|
||||||
None))
|
|
||||||
|
|
||||||
(defn odd? [n]
|
(defn odd? [n]
|
||||||
"Return true if n is an odd number"
|
"Return true if n is an odd number"
|
||||||
@ -284,14 +283,7 @@
|
|||||||
|
|
||||||
(defn rest [coll]
|
(defn rest [coll]
|
||||||
"Get all the elements of a coll, except the first."
|
"Get all the elements of a coll, except the first."
|
||||||
(slice coll 1))
|
(drop 1 coll))
|
||||||
|
|
||||||
(defn repeat [x &optional n]
|
|
||||||
"Yield x forever or optionally n times"
|
|
||||||
(if (none? n)
|
|
||||||
(setv dispatch (fn [] (while true (yield x))))
|
|
||||||
(setv dispatch (fn [] (for* [_ (range n)] (yield x)))))
|
|
||||||
(dispatch))
|
|
||||||
|
|
||||||
(defn repeatedly [func]
|
(defn repeatedly [func]
|
||||||
"Yield result of running func repeatedly"
|
"Yield result of running func repeatedly"
|
||||||
@ -300,7 +292,7 @@
|
|||||||
|
|
||||||
(defn second [coll]
|
(defn second [coll]
|
||||||
"Return second item from `coll`"
|
"Return second item from `coll`"
|
||||||
(get coll 1))
|
(nth coll 1))
|
||||||
|
|
||||||
(defn some [pred coll]
|
(defn some [pred coll]
|
||||||
"Return true if (pred x) is logical true for any x in coll, else false"
|
"Return true if (pred x) is logical true for any x in coll, else false"
|
||||||
@ -321,9 +313,7 @@
|
|||||||
(defn take [count coll]
|
(defn take [count coll]
|
||||||
"Take `count` elements from `coll`, or the whole set if the total
|
"Take `count` elements from `coll`, or the whole set if the total
|
||||||
number of entries in `coll` is less than `count`."
|
number of entries in `coll` is less than `count`."
|
||||||
(let [[citer (iter coll)]]
|
(itertools.islice coll nil count))
|
||||||
(for* [_ (range count)]
|
|
||||||
(yield (next citer)))))
|
|
||||||
|
|
||||||
(defn take-nth [n coll]
|
(defn take-nth [n coll]
|
||||||
"Return every nth member of coll
|
"Return every nth member of coll
|
||||||
@ -336,30 +326,15 @@
|
|||||||
(next citer))))
|
(next citer))))
|
||||||
(raise (ValueError "n must be positive"))))
|
(raise (ValueError "n must be positive"))))
|
||||||
|
|
||||||
(defn take-while [pred coll]
|
|
||||||
"Take all elements while `pred` is true"
|
|
||||||
(let [[citer (iter coll)]]
|
|
||||||
(for* [val citer]
|
|
||||||
(if (pred val)
|
|
||||||
(yield val)
|
|
||||||
(break)))))
|
|
||||||
|
|
||||||
(defn zero? [n]
|
(defn zero? [n]
|
||||||
"Return true if n is 0"
|
"Return true if n is 0"
|
||||||
(_numeric_check n)
|
(_numeric_check n)
|
||||||
(= n 0))
|
(= n 0))
|
||||||
|
|
||||||
(defn zipwith [func &rest lists]
|
(def *exports* '[butlast calling-module-name coll? cons cons? cycle dec distinct
|
||||||
"Zip the contents of several lists and map a function to the result"
|
disassemble drop drop-while empty? even? every? first filter
|
||||||
(do
|
flatten float? gensym identity inc instance? integer
|
||||||
(import functools)
|
integer? integer-char? iterable? iterate iterator? keyword?
|
||||||
(map (functools.partial (fn [f args] (apply f args)) func) (apply zip lists))))
|
list* macroexpand macroexpand-1 map neg? nil? none? nth
|
||||||
|
numeric? odd? pos? range remove repeat repeatedly rest second
|
||||||
(def *exports* '[butlast calling-module-name coll? cons cons? cycle dec
|
some string string? take take-nth take-while zero? zip zipwith])
|
||||||
distinct disassemble drop drop-while empty?
|
|
||||||
even? every? first filter flatten float? gensym
|
|
||||||
identity inc instance? integer integer? integer-char?
|
|
||||||
iterable? iterate iterator? list* macroexpand
|
|
||||||
macroexpand-1 neg? nil? none? nth numeric? odd? pos?
|
|
||||||
remove repeat repeatedly rest second some string
|
|
||||||
string? take take-nth take-while zero? zipwith])
|
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
|
|
||||||
|
|
||||||
(import [hy.models.list [HyList]]
|
(import [hy.models.list [HyList]]
|
||||||
[hy.models.symbol [HySymbol]])
|
[hy.models.symbol [HySymbol]]
|
||||||
|
[hy._compat [PY33 PY34]])
|
||||||
|
|
||||||
|
|
||||||
(defmacro for [args &rest body]
|
(defmacro for [args &rest body]
|
||||||
@ -145,6 +145,11 @@
|
|||||||
`(if (not ~test) ~not-branch ~yes-branch)))
|
`(if (not ~test) ~not-branch ~yes-branch)))
|
||||||
|
|
||||||
|
|
||||||
|
(defmacro-alias [lisp-if lif] [test &rest branches]
|
||||||
|
"Like `if`, but anything that is not None/nil is considered true."
|
||||||
|
`(if (is-not ~test nil) ~@branches))
|
||||||
|
|
||||||
|
|
||||||
(defmacro when [test &rest body]
|
(defmacro when [test &rest body]
|
||||||
"Execute `body` when `test` is true"
|
"Execute `body` when `test` is true"
|
||||||
`(if ~test (do ~@body)))
|
`(if ~test (do ~@body)))
|
||||||
@ -155,12 +160,6 @@
|
|||||||
`(if-not ~test (do ~@body)))
|
`(if-not ~test (do ~@body)))
|
||||||
|
|
||||||
|
|
||||||
(defmacro yield-from [iterable]
|
|
||||||
"Yield all the items from iterable"
|
|
||||||
(let [[x (gensym)]]
|
|
||||||
`(for* [~x ~iterable]
|
|
||||||
(yield ~x))))
|
|
||||||
|
|
||||||
(defmacro with-gensyms [args &rest body]
|
(defmacro with-gensyms [args &rest body]
|
||||||
`(let ~(HyList (map (fn [x] `[~x (gensym '~x)]) args))
|
`(let ~(HyList (map (fn [x] `[~x (gensym '~x)]) args))
|
||||||
~@body))
|
~@body))
|
||||||
@ -172,22 +171,18 @@
|
|||||||
~@body))))
|
~@body))))
|
||||||
|
|
||||||
|
|
||||||
(defmacro kwapply [call kwargs]
|
(defmacro defmain [args &rest body]
|
||||||
"Use a dictionary as keyword arguments"
|
"Write a function named \"main\" and do the if __main__ dance"
|
||||||
(let [[-fun (car call)]
|
(let [[retval (gensym)]]
|
||||||
[-args (cdr call)]
|
`(do
|
||||||
[-okwargs `[(list (.items ~kwargs))]]]
|
(defn main [~@args]
|
||||||
(while (= -fun "kwapply") ;; join any further kw
|
~@body)
|
||||||
(if (not (= (len -args) 2))
|
|
||||||
(macro-error
|
|
||||||
call
|
|
||||||
(.format "Trying to call nested kwapply with {0} args instead of 2"
|
|
||||||
(len -args))))
|
|
||||||
(.insert -okwargs 0 `(list (.items ~(car (cdr -args)))))
|
|
||||||
(setv -fun (car (car -args)))
|
|
||||||
(setv -args (cdr (car -args))))
|
|
||||||
|
|
||||||
`(apply ~-fun [~@-args] (dict (sum ~-okwargs [])))))
|
(when (= --name-- "__main__")
|
||||||
|
(import sys)
|
||||||
|
(setv ~retval (apply main sys.argv))
|
||||||
|
(if (integer? ~retval)
|
||||||
|
(sys.exit ~retval))))))
|
||||||
|
|
||||||
|
|
||||||
(defmacro-alias [defn-alias defun-alias] [names lambda-list &rest body]
|
(defmacro-alias [defn-alias defun-alias] [names lambda-list &rest body]
|
||||||
|
@ -21,12 +21,14 @@
|
|||||||
# 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._compat import PY3
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
class HyError(Exception):
|
class HyError(Exception):
|
||||||
"""
|
"""
|
||||||
Generic Hy error. All interal Exceptions will be subclassed from this
|
Generic Hy error. All internal Exceptions will be subclassed from this
|
||||||
Exception.
|
Exception.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
@ -137,7 +139,10 @@ class HyTypeError(TypeError):
|
|||||||
(self.__class__.__name__,
|
(self.__class__.__name__,
|
||||||
self.message))
|
self.message))
|
||||||
|
|
||||||
return result.encode('utf-8')
|
if not PY3:
|
||||||
|
return result.encode('utf-8')
|
||||||
|
else:
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class HyMacroExpansionError(HyTypeError):
|
class HyMacroExpansionError(HyTypeError):
|
||||||
|
@ -213,7 +213,7 @@ def reader_macroexpand(char, tree, module_name):
|
|||||||
"""Expand the reader macro "char" with argument `tree`."""
|
"""Expand the reader macro "char" with argument `tree`."""
|
||||||
load_macros(module_name)
|
load_macros(module_name)
|
||||||
|
|
||||||
if not char in _hy_reader[module_name]:
|
if char not in _hy_reader[module_name]:
|
||||||
raise HyTypeError(
|
raise HyTypeError(
|
||||||
char,
|
char,
|
||||||
"`{0}' is not a reader macro in module '{1}'".format(
|
"`{0}' is not a reader macro in module '{1}'".format(
|
||||||
|
@ -20,4 +20,4 @@
|
|||||||
|
|
||||||
|
|
||||||
__appname__ = "hy"
|
__appname__ = "hy"
|
||||||
__version__ = "0.9.12"
|
__version__ = "0.10.0"
|
||||||
|
8
make.bat
8
make.bat
@ -27,7 +27,9 @@ if "%1" == "help" (
|
|||||||
|
|
||||||
if "%1" == "docs" (
|
if "%1" == "docs" (
|
||||||
:docs
|
:docs
|
||||||
echo.docs not yet supported under Windows
|
cd docs
|
||||||
|
make.bat html
|
||||||
|
cd ..
|
||||||
goto :EOF
|
goto :EOF
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,8 +72,8 @@ goto :EOF
|
|||||||
|
|
||||||
if "%1" == "flake" (
|
if "%1" == "flake" (
|
||||||
:flake
|
:flake
|
||||||
echo.flake8 hy
|
echo.flake8 hy tests
|
||||||
flake8 hy
|
flake8 hy tests
|
||||||
goto :EOF
|
goto :EOF
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
-r requirements.txt
|
# test tools
|
||||||
tox
|
|
||||||
nose
|
nose
|
||||||
Sphinx
|
tox
|
||||||
|
|
||||||
|
# code quality
|
||||||
|
flake8
|
||||||
coverage
|
coverage
|
||||||
|
|
||||||
|
# documentation
|
||||||
|
Pygments>=1.6
|
||||||
|
Sphinx
|
||||||
|
sphinx_rtd_theme
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
# Check site / dev for more deps!
|
|
||||||
flake8
|
|
||||||
rply>=0.7.0
|
|
@ -3,3 +3,6 @@ detailed-errors=1
|
|||||||
with-coverage=1
|
with-coverage=1
|
||||||
cover-package=hy
|
cover-package=hy
|
||||||
nocapture=1
|
nocapture=1
|
||||||
|
|
||||||
|
[wheel]
|
||||||
|
universal = 1
|
||||||
|
4
setup.py
4
setup.py
@ -59,7 +59,8 @@ setup(
|
|||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
'hy = hy.cmdline:hy_main',
|
'hy = hy.cmdline:hy_main',
|
||||||
'hyc = hy.cmdline:hyc_main'
|
'hyc = hy.cmdline:hyc_main',
|
||||||
|
'hy2py = hy.cmdline:hy2py_main',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
packages=find_packages(exclude=['tests*']),
|
packages=find_packages(exclude=['tests*']),
|
||||||
@ -88,6 +89,7 @@ setup(
|
|||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Programming Language :: Python :: 3.2",
|
"Programming Language :: Python :: 3.2",
|
||||||
"Programming Language :: Python :: 3.3",
|
"Programming Language :: Python :: 3.3",
|
||||||
|
"Programming Language :: Python :: 3.4",
|
||||||
"Topic :: Software Development :: Code Generators",
|
"Topic :: Software Development :: Code Generators",
|
||||||
"Topic :: Software Development :: Compilers",
|
"Topic :: Software Development :: Compilers",
|
||||||
"Topic :: Software Development :: Libraries",
|
"Topic :: Software Development :: Libraries",
|
||||||
|
@ -19,3 +19,4 @@ from .native_tests.contrib.loop import * # noqa
|
|||||||
from .native_tests.contrib.meth import * # noqa
|
from .native_tests.contrib.meth import * # noqa
|
||||||
from .native_tests.contrib.walk import * # noqa
|
from .native_tests.contrib.walk import * # noqa
|
||||||
from .native_tests.contrib.multi import * # noqa
|
from .native_tests.contrib.multi import * # noqa
|
||||||
|
from .native_tests.contrib.curry import * # noqa
|
||||||
|
@ -353,17 +353,6 @@ def test_ast_non_decoratable():
|
|||||||
cant_compile("(with-decorator (foo) (* x x))")
|
cant_compile("(with-decorator (foo) (* x x))")
|
||||||
|
|
||||||
|
|
||||||
def test_ast_non_kwapplyable():
|
|
||||||
""" Ensure kwapply breaks """
|
|
||||||
code = tokenize("(kwapply foo bar)")
|
|
||||||
code[0][2] = None
|
|
||||||
try:
|
|
||||||
hy_compile(code, "__main__")
|
|
||||||
assert True is False
|
|
||||||
except HyCompileError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def test_ast_lambda_lists():
|
def test_ast_lambda_lists():
|
||||||
"""Ensure the compiler chokes on invalid lambda-lists"""
|
"""Ensure the compiler chokes on invalid lambda-lists"""
|
||||||
cant_compile('(fn [&key {"a" b} &key {"foo" bar}] [a foo])')
|
cant_compile('(fn [&key {"a" b} &key {"foo" bar}] [a foo])')
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
# Copyright (c) 2013 Nicolas Dandrimont <nicolas.dandrimont@crans.org>
|
|
||||||
#
|
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
# copy of this software and associated documentation files (the "Software"),
|
|
||||||
# to deal in the Software without restriction, including without limitation
|
|
||||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
# and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
# Software is furnished to do so, subject to the following conditions:
|
|
||||||
#
|
|
||||||
# The above copyright notice and this permission notice shall be included in
|
|
||||||
# all copies or substantial portions of the Software.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
# DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
from .test_ast import can_compile, cant_compile
|
|
||||||
|
|
||||||
|
|
||||||
def test_macro_nested_kwapply():
|
|
||||||
"Make sure nested kwapply compile correctly"
|
|
||||||
can_compile("(kwapply (kwapply (foo) bar) baz)")
|
|
||||||
cant_compile("(kwapply (kwapply (foo)) bar)")
|
|
13
tests/native_tests/contrib/curry.hy
Normal file
13
tests/native_tests/contrib/curry.hy
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
(require hy.contrib.curry)
|
||||||
|
|
||||||
|
|
||||||
|
(defnc s [x y z] ((x z) (y z))) ; λxyz.xz(yz)
|
||||||
|
(defnc k [x] (fn [y] x)) ; λx.λy.x
|
||||||
|
(defnc i [x] x) ;; λx.x
|
||||||
|
|
||||||
|
(defnc succ [n] (+ n 1))
|
||||||
|
|
||||||
|
|
||||||
|
(defn test-curry []
|
||||||
|
(assert (= 16 (((((s ((((k s) k) i) i)) (i i)) ((i (i i))
|
||||||
|
((((k s) i) ((s (k s)) k)) i))) succ) 0))))
|
@ -82,8 +82,8 @@
|
|||||||
(assert-equal res [None 4 5])
|
(assert-equal res [None 4 5])
|
||||||
(setv res (list (drop 0 [1 2 3 4 5])))
|
(setv res (list (drop 0 [1 2 3 4 5])))
|
||||||
(assert-equal res [1 2 3 4 5])
|
(assert-equal res [1 2 3 4 5])
|
||||||
(setv res (list (drop -1 [1 2 3 4 5])))
|
(try (do (list (drop -1 [1 2 3 4 5])) (assert False))
|
||||||
(assert-equal res [1 2 3 4 5])
|
(catch [e [ValueError]] nil))
|
||||||
(setv res (list (drop 6 (iter [1 2 3 4 5]))))
|
(setv res (list (drop 6 (iter [1 2 3 4 5]))))
|
||||||
(assert-equal res [])
|
(assert-equal res [])
|
||||||
(setv res (list (take 5 (drop 2 (iterate inc 0)))))
|
(setv res (list (take 5 (drop 2 (iterate inc 0)))))
|
||||||
@ -335,12 +335,15 @@
|
|||||||
"NATIVE: testing the nth function"
|
"NATIVE: testing the nth function"
|
||||||
(assert-equal 2 (nth [1 2 4 7] 1))
|
(assert-equal 2 (nth [1 2 4 7] 1))
|
||||||
(assert-equal 7 (nth [1 2 4 7] 3))
|
(assert-equal 7 (nth [1 2 4 7] 3))
|
||||||
(assert-true (none? (nth [1 2 4 7] 5)))
|
(try (do (nth [1 2 4 7] 5) (assert False))
|
||||||
(assert-true (none? (nth [1 2 4 7] -1)))
|
(catch [e [IndexError]] nil))
|
||||||
|
(try (do (nth [1 2 4 7] -1) (assert False))
|
||||||
|
(catch [e [ValueError]] nil))
|
||||||
;; now for iterators
|
;; now for iterators
|
||||||
(assert-equal 2 (nth (iter [1 2 4 7]) 1))
|
(assert-equal 2 (nth (iter [1 2 4 7]) 1))
|
||||||
(assert-equal 7 (nth (iter [1 2 4 7]) 3))
|
(assert-equal 7 (nth (iter [1 2 4 7]) 3))
|
||||||
(assert-true (none? (nth (iter [1 2 4 7]) -1)))
|
(try (do (nth (iter [1 2 4 7]) -1) (assert False))
|
||||||
|
(catch [e [ValueError]] nil))
|
||||||
(assert-equal 5 (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2)))
|
(assert-equal 5 (nth (take 3 (drop 2 [1 2 3 4 5 6])) 2)))
|
||||||
|
|
||||||
(defn test-numeric? []
|
(defn test-numeric? []
|
||||||
@ -429,8 +432,8 @@
|
|||||||
(assert-equal res ["s" "s" "s" "s"])
|
(assert-equal res ["s" "s" "s" "s"])
|
||||||
(setv res (list (take 0 (repeat "s"))))
|
(setv res (list (take 0 (repeat "s"))))
|
||||||
(assert-equal res [])
|
(assert-equal res [])
|
||||||
(setv res (list (take -1 (repeat "s"))))
|
(try (do (list (take -1 (repeat "s"))) (assert False))
|
||||||
(assert-equal res [])
|
(catch [e [ValueError]] nil))
|
||||||
(setv res (list (take 6 [1 2 None 4])))
|
(setv res (list (take 6 [1 2 None 4])))
|
||||||
(assert-equal res [1 2 None 4]))
|
(assert-equal res [1 2 None 4]))
|
||||||
|
|
||||||
@ -478,3 +481,14 @@
|
|||||||
(assert-equal (list res) [4 4 4])
|
(assert-equal (list res) [4 4 4])
|
||||||
(setv res (zipwith operator.sub [3 7 9] [1 2 4]))
|
(setv res (zipwith operator.sub [3 7 9] [1 2 4]))
|
||||||
(assert-equal (list res) [2 5 5]))
|
(assert-equal (list res) [2 5 5]))
|
||||||
|
|
||||||
|
(defn test-is-keyword []
|
||||||
|
"NATIVE: testing the keyword? function"
|
||||||
|
(assert (keyword? ':bar))
|
||||||
|
(assert (keyword? ':baz))
|
||||||
|
(assert (keyword? :bar))
|
||||||
|
(assert (keyword? :baz))
|
||||||
|
(assert (not (keyword? "foo")))
|
||||||
|
(assert (not (keyword? ":foo")))
|
||||||
|
(assert (not (keyword? 1)))
|
||||||
|
(assert (not (keyword? nil))))
|
||||||
|
@ -199,20 +199,10 @@
|
|||||||
|
|
||||||
(defn test-kwargs []
|
(defn test-kwargs []
|
||||||
"NATIVE: test kwargs things."
|
"NATIVE: test kwargs things."
|
||||||
(assert (= (kwapply (kwtest) {"one" "two"}) {"one" "two"}))
|
(assert (= (apply kwtest [] {"one" "two"}) {"one" "two"}))
|
||||||
(setv mydict {"one" "three"})
|
(setv mydict {"one" "three"})
|
||||||
(assert (= (kwapply (kwtest) mydict) mydict))
|
(assert (= (apply kwtest [] mydict) mydict))
|
||||||
(assert (= (kwapply (kwtest) ((fn [] {"one" "two"}))) {"one" "two"}))
|
(assert (= (apply kwtest [] ((fn [] {"one" "two"}))) {"one" "two"})))
|
||||||
(assert (= (kwapply
|
|
||||||
(kwapply
|
|
||||||
(kwapply
|
|
||||||
(kwapply
|
|
||||||
(kwapply (kwtest) {"x" 4})
|
|
||||||
mydict)
|
|
||||||
{"x" 8})
|
|
||||||
{"x" (- 3 2) "y" 2})
|
|
||||||
{"y" 5 "z" 3})
|
|
||||||
{"x" 1 "y" 5 "z" 3 "one" "three"})))
|
|
||||||
|
|
||||||
|
|
||||||
(defn test-apply []
|
(defn test-apply []
|
||||||
@ -246,6 +236,11 @@
|
|||||||
"NATIVE: test do"
|
"NATIVE: test do"
|
||||||
(do))
|
(do))
|
||||||
|
|
||||||
|
(defn test-bare-try [] (try
|
||||||
|
(try (raise ValueError))
|
||||||
|
(except [ValueError])
|
||||||
|
(else (assert false))))
|
||||||
|
|
||||||
|
|
||||||
(defn test-exceptions []
|
(defn test-exceptions []
|
||||||
"NATIVE: test Exceptions"
|
"NATIVE: test Exceptions"
|
||||||
@ -479,7 +474,7 @@
|
|||||||
|
|
||||||
(defn test-rest []
|
(defn test-rest []
|
||||||
"NATIVE: test rest"
|
"NATIVE: test rest"
|
||||||
(assert (= (rest [1 2 3 4 5]) [2 3 4 5])))
|
(assert (= (list (rest [1 2 3 4 5])) [2 3 4 5])))
|
||||||
|
|
||||||
|
|
||||||
(defn test-importas []
|
(defn test-importas []
|
||||||
@ -785,8 +780,8 @@
|
|||||||
"NATIVE: test &key function arguments"
|
"NATIVE: test &key function arguments"
|
||||||
(defn foo [&key {"a" None "b" 1}] [a b])
|
(defn foo [&key {"a" None "b" 1}] [a b])
|
||||||
(assert (= (foo) [None 1]))
|
(assert (= (foo) [None 1]))
|
||||||
(assert (= (kwapply (foo) {"a" 2}) [2 1]))
|
(assert (= (apply foo [] {"a" 2}) [2 1]))
|
||||||
(assert (= (kwapply (foo) {"b" 42}) [None 42])))
|
(assert (= (apply foo [] {"b" 42}) [None 42])))
|
||||||
|
|
||||||
|
|
||||||
(defn test-optional-arguments []
|
(defn test-optional-arguments []
|
||||||
@ -947,22 +942,10 @@
|
|||||||
|
|
||||||
(defn test-disassemble []
|
(defn test-disassemble []
|
||||||
"NATIVE: Test the disassemble function"
|
"NATIVE: Test the disassemble function"
|
||||||
(import sys)
|
(assert (= (disassemble '(do (leaky) (leaky) (macros)))
|
||||||
(if-python2
|
"Module(\n body=[\n Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),\n Expr(value=Call(func=Name(id='leaky'), args=[], keywords=[], starargs=None, kwargs=None)),\n Expr(value=Call(func=Name(id='macros'), args=[], keywords=[], starargs=None, kwargs=None))])"))
|
||||||
(import [io [BytesIO :as StringIO]])
|
(assert (= (disassemble '(do (leaky) (leaky) (macros)) true)
|
||||||
(import [io [StringIO]]))
|
"leaky()\nleaky()\nmacros()")))
|
||||||
(setv prev-stdout sys.stdout)
|
|
||||||
(setv sys.stdout (StringIO))
|
|
||||||
(disassemble '(do (leaky) (leaky) (macros)))
|
|
||||||
(setv stdout (.getvalue sys.stdout))
|
|
||||||
(setv sys.stdout prev-stdout)
|
|
||||||
(assert (in "leaky" stdout))
|
|
||||||
(assert (in "macros" stdout))
|
|
||||||
(setv sys.stdout (StringIO))
|
|
||||||
(disassemble '(do (leaky) (leaky) (macros)) true)
|
|
||||||
(setv stdout (.getvalue sys.stdout))
|
|
||||||
(setv sys.stdout prev-stdout)
|
|
||||||
(assert (= stdout "leaky()\nleaky()\nmacros()\n")))
|
|
||||||
|
|
||||||
|
|
||||||
(defn test-attribute-access []
|
(defn test-attribute-access []
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
(import [hy._compat [PY33]])
|
||||||
|
(import [hy.errors [HyCompileError]])
|
||||||
|
|
||||||
(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))))))
|
||||||
@ -99,11 +102,18 @@
|
|||||||
|
|
||||||
(defn test-yield-from []
|
(defn test-yield-from []
|
||||||
"NATIVE: testing yield from"
|
"NATIVE: testing yield from"
|
||||||
(defn yield-from-test []
|
|
||||||
(for* [i (range 3)]
|
(try
|
||||||
(yield i))
|
(eval
|
||||||
(yield-from [1 2 3]))
|
'(do (defn yield-from-test []
|
||||||
(assert (= (list (yield-from-test)) [0 1 2 1 2 3])))
|
(for* [i (range 3)]
|
||||||
|
(yield i))
|
||||||
|
(yield-from [1 2 3]))
|
||||||
|
(assert (= (list (yield-from-test)) [0 1 2 1 2 3]))))
|
||||||
|
(catch [e HyCompileError]
|
||||||
|
;; Yup, this should happen on non-Python3.3 thingies
|
||||||
|
(assert (not PY33)))
|
||||||
|
(else (assert PY33))))
|
||||||
|
|
||||||
(defn test-if-python2 []
|
(defn test-if-python2 []
|
||||||
(import sys)
|
(import sys)
|
||||||
@ -191,6 +201,25 @@
|
|||||||
:yes)))
|
:yes)))
|
||||||
|
|
||||||
|
|
||||||
|
(defn test-lisp-if []
|
||||||
|
"test that lisp-if works as expected"
|
||||||
|
; nil is false
|
||||||
|
(assert (= (lisp-if None "true" "false") "false"))
|
||||||
|
(assert (= (lisp-if nil "true" "false") "false"))
|
||||||
|
|
||||||
|
; But everything else is True! Even falsey things.
|
||||||
|
(assert (= (lisp-if True "true" "false") "true"))
|
||||||
|
(assert (= (lisp-if False "true" "false") "true"))
|
||||||
|
(assert (= (lisp-if 0 "true" "false") "true"))
|
||||||
|
(assert (= (lisp-if "some-string" "true" "false") "true"))
|
||||||
|
(assert (= (lisp-if "" "true" "false") "true"))
|
||||||
|
(assert (= (lisp-if (+ 1 2 3) "true" "false") "true"))
|
||||||
|
|
||||||
|
; Just to be sure, test the alias lif
|
||||||
|
(assert (= (lif nil "true" "false") "false"))
|
||||||
|
(assert (= (lif 0 "true" "false") "true")))
|
||||||
|
|
||||||
|
|
||||||
(defn test-defn-alias []
|
(defn test-defn-alias []
|
||||||
(defn-alias [tda-main tda-a1 tda-a2] [] :bazinga)
|
(defn-alias [tda-main tda-a1 tda-a2] [] :bazinga)
|
||||||
(defun-alias [tda-main tda-a1 tda-a2] [] :bazinga)
|
(defun-alias [tda-main tda-a1 tda-a2] [] :bazinga)
|
||||||
|
5
tests/resources/bin/main.hy
Normal file
5
tests/resources/bin/main.hy
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
(defmain [&rest args]
|
||||||
|
(print args)
|
||||||
|
(print "Hello World")
|
||||||
|
(if (in "exit1" args)
|
||||||
|
1))
|
4
tests/resources/bin/nomain.hy
Normal file
4
tests/resources/bin/nomain.hy
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
(print "This Should Still Works")
|
||||||
|
|
||||||
|
(defn main []
|
||||||
|
(print "This Should Not Work"))
|
@ -2,6 +2,7 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
# Copyright (c) 2013 Julien Danjou <julien@danjou.info>
|
# Copyright (c) 2013 Julien Danjou <julien@danjou.info>
|
||||||
# Copyright (c) 2013 Will Kahn-Greene <willg@bluesock.org>
|
# Copyright (c) 2013 Will Kahn-Greene <willg@bluesock.org>
|
||||||
|
# Copyright (c) 2014 Bob Tolbert <bob@tolbert.org>
|
||||||
#
|
#
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
# copy of this software and associated documentation files (the "Software"),
|
# copy of this software and associated documentation files (the "Software"),
|
||||||
@ -23,8 +24,6 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from nose.plugins.skip import SkipTest
|
|
||||||
|
|
||||||
|
|
||||||
def run_cmd(cmd, stdin_data=None):
|
def run_cmd(cmd, stdin_data=None):
|
||||||
p = subprocess.Popen(cmd,
|
p = subprocess.Popen(cmd,
|
||||||
@ -125,16 +124,13 @@ def test_bin_hyc_missing_file():
|
|||||||
|
|
||||||
|
|
||||||
def test_hy2py():
|
def test_hy2py():
|
||||||
# and running this script this way doesn't work on Windows
|
|
||||||
if os.name == "nt":
|
|
||||||
raise SkipTest("doesn't work on Windows")
|
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
for dirpath, dirnames, filenames in os.walk("tests/native_tests"):
|
for dirpath, dirnames, filenames in os.walk("tests/native_tests"):
|
||||||
for f in filenames:
|
for f in filenames:
|
||||||
if f.endswith(".hy"):
|
if f.endswith(".hy"):
|
||||||
i += 1
|
i += 1
|
||||||
ret = run_cmd("bin/hy2py -s -a " + os.path.join(dirpath, f))
|
ret = run_cmd("hy2py -s -a "
|
||||||
|
+ os.path.join(dirpath, f))
|
||||||
assert ret[0] == 0, f
|
assert ret[0] == 0, f
|
||||||
assert len(ret[1]) > 1, f
|
assert len(ret[1]) > 1, f
|
||||||
assert len(ret[2]) == 0, f
|
assert len(ret[2]) == 0, f
|
||||||
@ -146,3 +142,27 @@ def test_bin_hy_builtins():
|
|||||||
|
|
||||||
assert str(exit) == "Use (exit) or Ctrl-D (i.e. EOF) to exit"
|
assert str(exit) == "Use (exit) or Ctrl-D (i.e. EOF) to exit"
|
||||||
assert str(quit) == "Use (quit) or Ctrl-D (i.e. EOF) to exit"
|
assert str(quit) == "Use (quit) or Ctrl-D (i.e. EOF) to exit"
|
||||||
|
|
||||||
|
|
||||||
|
def test_bin_hy_main():
|
||||||
|
ret = run_cmd("hy tests/resources/bin/main.hy")
|
||||||
|
assert ret[0] == 0
|
||||||
|
assert "Hello World" in ret[1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_bin_hy_main_args():
|
||||||
|
ret = run_cmd("hy tests/resources/bin/main.hy test 123")
|
||||||
|
assert ret[0] == 0
|
||||||
|
assert "test" in ret[1]
|
||||||
|
assert "123" in ret[1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_bin_hy_main_exitvalue():
|
||||||
|
ret = run_cmd("hy tests/resources/bin/main.hy exit1")
|
||||||
|
assert ret[0] == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_bin_hy_no_main():
|
||||||
|
ret = run_cmd("hy tests/resources/bin/nomain.hy")
|
||||||
|
assert ret[0] == 0
|
||||||
|
assert "This Should Still Work" in ret[1]
|
||||||
|
37
tox.ini
37
tox.ini
@ -1,39 +1,18 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = py27,pypy,py32,py33,py26,flake8
|
envlist = py26,py27,pypy,py32,py33,flake8
|
||||||
|
skipsdist = True
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
commands = nosetests
|
commands =
|
||||||
|
pip install --allow-all-external -e .
|
||||||
|
nosetests
|
||||||
deps =
|
deps =
|
||||||
nose
|
-rrequirements-dev.txt
|
||||||
setuptools
|
|
||||||
rply
|
|
||||||
|
|
||||||
[testenv:pypy]
|
|
||||||
commands = nosetests
|
|
||||||
deps =
|
|
||||||
astor
|
|
||||||
nose
|
|
||||||
setuptools
|
|
||||||
rply
|
|
||||||
|
|
||||||
[testenv:py27]
|
|
||||||
commands = nosetests
|
|
||||||
deps =
|
|
||||||
astor
|
|
||||||
nose
|
|
||||||
setuptools
|
|
||||||
rply
|
|
||||||
|
|
||||||
[testenv:py26]
|
[testenv:py26]
|
||||||
deps =
|
deps =
|
||||||
astor
|
{[testenv]deps}
|
||||||
nose
|
|
||||||
setuptools
|
|
||||||
unittest2
|
unittest2
|
||||||
importlib
|
|
||||||
rply
|
|
||||||
|
|
||||||
[testenv:flake8]
|
[testenv:flake8]
|
||||||
deps =
|
|
||||||
flake8
|
|
||||||
rply
|
|
||||||
commands = flake8 hy bin tests
|
commands = flake8 hy bin tests
|
||||||
|
Loading…
x
Reference in New Issue
Block a user