Merge branch 'master' into pr/237

This commit is contained in:
Paul Tagliamonte 2013-07-16 21:05:31 -04:00
commit 967bb95534
16 changed files with 252 additions and 71 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
*.pyc *.pyc
*swp *swp
*hy*egg* *hy*egg*
*pyreadline*egg*
.tox .tox
*pycache* *pycache*
dist dist

View File

@ -8,7 +8,7 @@ python:
# command to install dependencies # command to install dependencies
install: install:
- pip install -r requirements.txt --use-mirrors - pip install -r requirements.txt --use-mirrors
- if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install importlib unittest2 astor --use-mirrors; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.6' ]]; then pip install argparse importlib unittest2 astor --use-mirrors; fi
- if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install astor --use-mirrors; fi - if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]]; then pip install astor --use-mirrors; fi
- if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then pip install astor --use-mirrors; fi - if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then pip install astor --use-mirrors; fi
- python setup.py -q install - python setup.py -q install

View File

@ -14,4 +14,5 @@
* Thomas Ballinger <thomasballinger@gmail.com> * Thomas Ballinger <thomasballinger@gmail.com>
* Morten Linderud <mcfoxax@gmail.com> * Morten Linderud <mcfoxax@gmail.com>
* Guillermo Vayá <guivaya@gmail.com> * Guillermo Vayá <guivaya@gmail.com>
* Bob Tolbert <bob@tolbert.org>
* Ralph Möritz <ralph.moeritz@outlook.com> * Ralph Möritz <ralph.moeritz@outlook.com>

8
bin/hy
View File

@ -1,8 +0,0 @@
#!/usr/bin/env python
import sys
from hy.cmdline import cmdline_handler
if __name__ == '__main__':
sys.exit(cmdline_handler("hy", sys.argv))

View File

@ -1,6 +0,0 @@
#!/usr/bin/env hy
(import sys)
(import [hy.importer [write-hy-as-pyc]])
(write-hy-as-pyc (get sys.argv 1))

View File

@ -177,7 +177,7 @@ Some example usage:
`do` can accept any number of arguments, from 1 to n. `do` can accept any number of arguments, from 1 to n.
def / setf / setv def / setv
----------------- -----------------
`def` and `setv` are used to bind value, object or a function to a symbol. For `def` and `setv` are used to bind value, object or a function to a symbol. For

View File

@ -6,6 +6,6 @@
(with-as (ThreadPoolExecutor 10) executor (with-as (ThreadPoolExecutor 10) executor
(setf jobs (list-comp (.submit executor task-to-do) (x (range 0 10)))) (setv jobs (list-comp (.submit executor task-to-do) (x (range 0 10))))
(for (future (as-completed jobs)) (for (future (as-completed jobs))
(.result future))) (.result future)))

View File

@ -24,7 +24,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE. # DEALINGS IN THE SOFTWARE.
import optparse import argparse
import code import code
import ast import ast
import sys import sys
@ -198,26 +198,40 @@ def run_icommand(source):
return run_repl(hr) return run_repl(hr)
USAGE = "usage: %prog [-h | -i cmd | -c cmd | file | -]" USAGE = "%(prog)s [-h | -i cmd | -c cmd | file | -] [arg] ..."
VERSION = "%prog " + hy.__version__ VERSION = "%(prog)s " + hy.__version__
EPILOG = """ file program read from script EPILOG = """ file program read from script
- program read from stdin - program read from stdin
[arg] ... arguments passed to program in sys.argv[1:]
""" """
def cmdline_handler(scriptname, argv): def cmdline_handler(scriptname, argv):
parser = optparse.OptionParser(usage=USAGE, version=VERSION) parser = argparse.ArgumentParser(
parser.add_option( prog="hy",
"-c", dest="command", metavar="COMMAND", usage=USAGE,
help="program passed in as string") formatter_class=argparse.RawDescriptionHelpFormatter,
parser.add_option( epilog=EPILOG)
"-i", dest="icommand", metavar="ICOMMAND", parser.add_argument("-c", dest="command",
help="program passed in as string, then stay in repl") help="program passed in as a string")
parser.add_argument(
"-i", dest="icommand",
help="program passed in as a string, then stay in REPL")
# Hylarious way of adding non-option options to help text parser.add_argument("-v", action="version", version=VERSION)
parser.format_epilog = lambda self: EPILOG
(options, args) = parser.parse_args() # this will contain the script/program name and any arguments for it.
parser.add_argument('args', nargs=argparse.REMAINDER,
help=argparse.SUPPRESS)
# stash the hy exectuable in case we need it later
# mimics Python sys.executable
hy.executable = argv[0]
options = parser.parse_args(argv[1:])
# reset sys.argv like Python
sys.argv = options.args
if options.command: if options.command:
# User did "hy -c ..." # User did "hy -c ..."
@ -227,14 +241,25 @@ def cmdline_handler(scriptname, argv):
# User did "hy -i ..." # User did "hy -i ..."
return run_icommand(options.icommand) return run_icommand(options.icommand)
if args: if options.args:
if args[0] == "-": if options.args[0] == "-":
# Read the program from stdin # Read the program from stdin
return run_command(sys.stdin.read()) return run_command(sys.stdin.read())
else: else:
# User did "hy <filename>" # User did "hy <filename>"
return run_file(args[0]) return run_file(options.args[0])
# User did NOTHING! # User did NOTHING!
return run_repl() return run_repl()
# entry point for cmd line script "hy"
def hy_main():
sys.exit(cmdline_handler("hy", sys.argv))
# entry point for cmd line script "hyc"
def hyc_main():
from hy.importer import write_hy_as_pyc
write_hy_as_pyc(sys.argv[1])

View File

@ -1481,7 +1481,6 @@ class HyASTCompiler(object):
return func + ret return func + ret
@builds("def") @builds("def")
@builds("setf")
@builds("setv") @builds("setv")
@checkargs(2) @checkargs(2)
def compile_def_expression(self, expression): def compile_def_expression(self, expression):

View File

@ -128,10 +128,10 @@ def let_macro(variables, *body):
for var in variables: for var in variables:
if isinstance(var, list): if isinstance(var, list):
expr.append(HyExpression([HySymbol("setf"), expr.append(HyExpression([HySymbol("setv"),
var[0], var[1]])) var[0], var[1]]))
else: else:
expr.append(HyExpression([HySymbol("setf"), expr.append(HyExpression([HySymbol("setv"),
var, HySymbol("None")])) var, HySymbol("None")]))
return HyExpression([expr + list(body)]) return HyExpression([expr + list(body)])

116
make.bat Normal file
View File

@ -0,0 +1,116 @@
@ECHO OFF
REM Make batch file for Hy development
if "%1" == "" goto help
if "%1" == "help" (
:help
echo. No default step. Use setup.py
echo.
echo. Other targets:
echo.
echo. - docs
echo. - full
echo.
echo. - dev "test & flake"
echo. - flake
echo. - test
echo. - diff
echo. - tox
echo. - d
echo. - r
echo.
goto end
)
if "%1" == "docs" (
:docs
echo.docs not yet supported under Windows
goto :EOF
)
if "%1" == "upload" (
:upload
python setup.py sdist upload
goto :EOF
)
if "%1" == "clear" (
:clear
cls
goto :EOF
)
if "%1" == "d" (
:d
call :clear
call :dev
goto :EOF
)
if "%1" == "test" (
:test
call :venv
nosetests -sv
goto :EOF
)
if "%1" == "venv" (
:venv
echo.%VIRTUAL_ENV% | findstr /C:"hy" 1>nul
if errorlevel 1 (
echo.You're not in a Hy virtualenv. FOR SHAME
) ELSE (
echo.We're properly in a virtualenv. Going ahead.
)
goto :EOF
)
if "%1" == "flake" (
:flake
echo.flake8 hy
flake8 hy
goto :EOF
)
if "%1" == "dev" (
:dev
call :test
call :flake
goto :EOF
)
if "%1" == "tox" (
:tox
call :venv
tox -e "py26,py27,py32,py33,flake8"
goto :EOF
)
if "%1" == "d" (
:d
call :clear
call :dev
goto :EOF
)
if "%i" == "diff" (
:diff
git diff --color
goto :EOF
)
if "%1" == "r" (
:r
call :d
call :tox
call :diff
goto :EOF
)
if "%1" == full (
call :docs
call :d
call :tox
)

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# Copyright (c) 2012 Paul Tagliamonte <paultag@debian.org> # Copyright (c) 2012, 2013 Paul Tagliamonte <paultag@debian.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,12 +23,15 @@
from hy import __appname__, __version__ from hy import __appname__, __version__
from setuptools import setup from setuptools import setup
import os import os
import sys
long_description = """Hy is a Python <--> Lisp layer. It helps long_description = """Hy is a Python <--> Lisp layer. It helps
make things work nicer, and lets Python and the Hy lisp variant play make things work nicer, and lets Python and the Hy lisp variant play
nice together. """ nice together. """
install_requires = [] install_requires = []
if sys.version_info[0] == 2:
install_requires.append('argparse>=1.2.1')
if os.name == 'nt': if os.name == 'nt':
install_requires.append('pyreadline==2.0') install_requires.append('pyreadline==2.0')
@ -36,10 +39,12 @@ setup(
name=__appname__, name=__appname__,
version=__version__, version=__version__,
install_requires=install_requires, install_requires=install_requires,
scripts=[ entry_points={
"bin/hy", 'console_scripts': [
"bin/hyc", 'hy = hy.cmdline:hy_main',
], 'hyc = hy.cmdline:hyc_main'
]
},
packages=[ packages=[
'hy', 'hy',
'hy.lex', 'hy.lex',

View File

@ -408,11 +408,11 @@
(defn test-for-doodle [] (defn test-for-doodle []
"NATIVE: test for-do" "NATIVE: test for-do"
(do (do (do (do (do (do (do (do (do (setf (, x y) (, 0 0))))))))))) (do (do (do (do (do (do (do (do (do (setv (, x y) (, 0 0)))))))))))
(foreach [- [1 2]] (foreach [- [1 2]]
(do (do
(setf x (+ x 1)) (setv x (+ x 1))
(setf y (+ y 1)))) (setv y (+ y 1))))
(assert (= y x 2))) (assert (= y x 2)))
@ -597,10 +597,10 @@
(defn test-eval [] (defn test-eval []
"NATIVE: test eval" "NATIVE: test eval"
(assert (= 2 (eval (quote (+ 1 1))))) (assert (= 2 (eval (quote (+ 1 1)))))
(setf x 2) (setv x 2)
(assert (= 4 (eval (quote (+ x 2))))) (assert (= 4 (eval (quote (+ x 2)))))
(setf test-payload (quote (+ x 2))) (setv test-payload (quote (+ x 2)))
(setf x 4) (setv x 4)
(assert (= 6 (eval test-payload))) (assert (= 6 (eval test-payload)))
(assert (= 9 ((eval (quote (fn [x] (+ 3 3 x)))) 3))) (assert (= 9 ((eval (quote (fn [x] (+ 3 3 x)))) 3)))
(assert (= 1 (eval (quote 1)))) (assert (= 1 (eval (quote 1))))
@ -689,9 +689,9 @@
(defn test-try-except-return [] (defn test-try-except-return []
"NATIVE: test we can return from in a try except" "NATIVE: test we can return from in a try except"
(assert (= ((fn [] (try xxx (except [NameError] (+ 1 1))))) 2)) (assert (= ((fn [] (try xxx (except [NameError] (+ 1 1))))) 2))
(setf foo (try xxx (except [NameError] (+ 1 1)))) (setv foo (try xxx (except [NameError] (+ 1 1))))
(assert (= foo 2)) (assert (= foo 2))
(setf foo (try (+ 2 2) (except [NameError] (+ 1 1)))) (setv foo (try (+ 2 2) (except [NameError] (+ 1 1))))
(assert (= foo 4))) (assert (= foo 4)))

View File

@ -3,22 +3,22 @@
(defn test-quote [] (defn test-quote []
"NATIVE: test for quoting functionality" "NATIVE: test for quoting functionality"
(setf q (quote (a b c))) (setv q (quote (a b c)))
(assert (= (len q) 3)) (assert (= (len q) 3))
(assert (= q [(quote a) (quote b) (quote c)]))) (assert (= q [(quote a) (quote b) (quote c)])))
(defn test-quoted-hoistable [] (defn test-quoted-hoistable []
"NATIVE: check whether quote works on hoisted things" "NATIVE: check whether quote works on hoisted things"
(setf f (quote (if true true true))) (setv f (quote (if true true true)))
(assert (= (car f) (quote if))) (assert (= (car f) (quote if)))
(assert (= (cdr f) (quote (true true true))))) (assert (= (cdr f) (quote (true true true)))))
(defn test-quoted-macroexpand [] (defn test-quoted-macroexpand []
"NATIVE: check that we don't expand macros in quoted expressions" "NATIVE: check that we don't expand macros in quoted expressions"
(setf q1 (quote (-> a b c))) (setv q1 (quote (-> a b c)))
(setf q2 (quasiquote (-> a b c))) (setv q2 (quasiquote (-> a b c)))
(assert (= q1 q2)) (assert (= q1 q2))
(assert (= (car q1) (quote ->))) (assert (= (car q1) (quote ->)))
(assert (= (cdr q1) (quote (a b c))))) (assert (= (cdr q1) (quote (a b c)))))
@ -26,7 +26,7 @@
(defn test-quote-dicts [] (defn test-quote-dicts []
"NATIVE: test quoting dicts" "NATIVE: test quoting dicts"
(setf q (quote {foo bar baz quux})) (setv q (quote {foo bar baz quux}))
(assert (= (len q) 4)) (assert (= (len q) 4))
(assert (= (get q 0) (quote foo))) (assert (= (get q 0) (quote foo)))
(assert (= (get q 1) (quote bar))) (assert (= (get q 1) (quote bar)))
@ -37,41 +37,41 @@
(defn test-quote-expr-in-dict [] (defn test-quote-expr-in-dict []
"NATIVE: test quoting nested exprs in dict" "NATIVE: test quoting nested exprs in dict"
(setf q (quote {(foo bar) 0})) (setv q (quote {(foo bar) 0}))
(assert (= (len q) 2)) (assert (= (len q) 2))
(setf qq (get q 0)) (setv qq (get q 0))
(assert (= qq (quote (foo bar))))) (assert (= qq (quote (foo bar)))))
(defn test-quasiquote [] (defn test-quasiquote []
"NATIVE: test that quasiquote and quote are equivalent for simple cases" "NATIVE: test that quasiquote and quote are equivalent for simple cases"
(setf q (quote (a b c))) (setv q (quote (a b c)))
(setf qq (quasiquote (a b c))) (setv qq (quasiquote (a b c)))
(assert (= q qq))) (assert (= q qq)))
(defn test-unquote [] (defn test-unquote []
"NATIVE: test that unquote works as expected" "NATIVE: test that unquote works as expected"
(setf q (quote (unquote foo))) (setv q (quote (unquote foo)))
(assert (= (len q) 2)) (assert (= (len q) 2))
(assert (= (get q 1) (quote foo))) (assert (= (get q 1) (quote foo)))
(setf qq (quasiquote (a b c (unquote (+ 1 2))))) (setv qq (quasiquote (a b c (unquote (+ 1 2)))))
(assert (= (len qq) 4)) (assert (= (len qq) 4))
(assert (= qq (quote (a b c 3))))) (assert (= qq (quote (a b c 3)))))
(defn test-unquote-splice [] (defn test-unquote-splice []
"NATIVE: test splicing unquotes" "NATIVE: test splicing unquotes"
(setf q (quote (c d e))) (setv q (quote (c d e)))
(setf qq (quasiquote (a b (unquote-splice q) f (unquote-splice q)))) (setv qq (quasiquote (a b (unquote-splice q) f (unquote-splice q))))
(assert (= (len qq) 9)) (assert (= (len qq) 9))
(assert (= qq (quote (a b c d e f c d e))))) (assert (= qq (quote (a b c d e f c d e)))))
(defn test-nested-quasiquote [] (defn test-nested-quasiquote []
"NATIVE: test nested quasiquotes" "NATIVE: test nested quasiquotes"
(setf qq (quasiquote (1 (quasiquote (unquote (+ 1 (unquote (+ 2 3))))) 4))) (setv qq (quasiquote (1 (quasiquote (unquote (+ 1 (unquote (+ 2 3))))) 4)))
(setf q (quote (1 (quasiquote (unquote (+ 1 5))) 4))) (setv q (quote (1 (quasiquote (unquote (+ 1 5))) 4)))
(assert (= (len q) 3)) (assert (= (len q) 3))
(assert (= (get qq 1) (quote (quasiquote (unquote (+ 1 5)))))) (assert (= (get qq 1) (quote (quasiquote (unquote (+ 1 5))))))
(assert (= q qq))) (assert (= q qq)))

18
tests/resources/argparse_ex.hy Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env hy
(import sys)
(import argparse)
(setv parser (argparse.ArgumentParser))
(.add_argument parser "-i")
(.add_argument parser "-c")
(setv args (.parse_args parser))
;; using (cond) allows -i to take precedence over -c
(cond (args.i
(print (str args.i)))
(args.c
(print (str "got c"))))

View File

@ -25,13 +25,18 @@ import subprocess
import sys import sys
def run_cmd(cmd): def run_cmd(cmd, stdin_data=None):
p = subprocess.Popen(cmd, p = subprocess.Popen(cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
shell=True) shell=True)
stdout = "" stdout = ""
stderr = "" stderr = ""
if stdin_data is not None:
p.stdin.write(stdin_data.encode('ASCII'))
p.stdin.flush()
p.stdin.close()
# Read stdout and stderr otherwise if the PIPE buffer is full, we might # Read stdout and stderr otherwise if the PIPE buffer is full, we might
# wait for ever… # wait for ever…
while p.poll() is None: while p.poll() is None:
@ -41,28 +46,28 @@ def run_cmd(cmd):
def test_bin_hy(): def test_bin_hy():
ret = run_cmd("echo | bin/hy") ret = run_cmd("hy", "")
assert ret[0] == 0 assert ret[0] == 0
def test_bin_hy_stdin(): def test_bin_hy_stdin():
ret = run_cmd("echo \"(koan)\" | bin/hy") ret = run_cmd("hy", '(koan)')
assert ret[0] == 0 assert ret[0] == 0
assert "monk" in ret[1] assert "monk" in ret[1]
def test_bin_hy_cmd(): def test_bin_hy_cmd():
ret = run_cmd("bin/hy -c \"(koan)\"") ret = run_cmd("hy -c \"(koan)\"")
assert ret[0] == 0 assert ret[0] == 0
assert "monk" in ret[1] assert "monk" in ret[1]
ret = run_cmd("bin/hy -c \"(koan\"") ret = run_cmd("hy -c \"(koan\"")
assert ret[0] == 1 assert ret[0] == 1
assert "LexException" in ret[1] assert "LexException" in ret[1]
def test_bin_hy_icmd(): def test_bin_hy_icmd():
ret = run_cmd("echo \"(ideas)\" | bin/hy -i \"(koan)\"") ret = run_cmd("hy -i \"(koan)\"", "(ideas)")
assert ret[0] == 0 assert ret[0] == 0
output = ret[1] output = ret[1]
@ -71,16 +76,41 @@ def test_bin_hy_icmd():
def test_bin_hy_file(): def test_bin_hy_file():
ret = run_cmd("bin/hy eg/nonfree/halting-problem/halting.hy") ret = run_cmd("hy eg/nonfree/halting-problem/halting.hy")
assert ret[0] == 0 assert ret[0] == 0
assert "27" in ret[1] assert "27" in ret[1]
def test_bin_hy_missing_file():
ret = run_cmd("hy foobarbaz")
assert ret[0] == 1
assert "No such file" in ret[2]
def test_bin_hy_file_with_args():
ret = run_cmd("hy tests/resources/argparse_ex.hy -h")
assert ret[0] == 0
assert "usage" in ret[1]
ret = run_cmd("hy tests/resources/argparse_ex.hy -c bar")
assert ret[0] == 0
assert "got c" in ret[1]
ret = run_cmd("hy tests/resources/argparse_ex.hy -i foo")
assert ret[0] == 0
assert "foo" in ret[1]
ret = run_cmd("hy tests/resources/argparse_ex.hy -i foo -c bar")
assert ret[0] == 0
assert "foo" in ret[1]
def test_hy2py(): def test_hy2py():
# XXX Astor doesn't seem to support Python3 :( # XXX Astor doesn't seem to support Python3 :(
if sys.version_info[0] == 3: if sys.version_info[0] == 3:
return return
# and running this script this way doesn't work on Windows
if os.name == "nt":
return
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: