Merge branch 'master' into pr/450

This commit is contained in:
Nicolas Dandrimont 2014-01-17 20:31:01 +01:00
commit 331165da32
23 changed files with 370 additions and 146 deletions

View File

@ -35,3 +35,5 @@
* Thom Neale <twneale@gmail.com>
* Tuukka Turto <tuukka.turto@oktaeder.net>
* Vasudev Kamath <kamathvasudev@gmail.com>
* Yuval Langer <yuval.langer@gmail.com>
* Fatih Kadir Akın <fka@fatihak.in>

View File

@ -1,24 +1,39 @@
#!/usr/bin/env python
from __future__ import print_function
from hy.importer import (import_file_to_ast, import_file_to_hst)
from hy.importer import (import_file_to_ast, import_file_to_module,
import_file_to_hst)
import argparse
import sys
import astor.codegen
import sys
module_name = "<STDIN>"
hst = import_file_to_hst(sys.argv[1])
print(str(hst).encode("utf-8"))
print("")
print("")
_ast = import_file_to_ast(sys.argv[1], module_name)
print("")
print("")
print(astor.dump(_ast).encode("utf-8"))
print("")
print("")
print(astor.codegen.to_source(_ast).encode("utf-8"))
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)
import_file_to_module(module_name, sys.argv[1])
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"))

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
docs/_static/cuddles-transparent.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -97,7 +97,7 @@ core team. Additional review is clearly welcome, but we need a minimum of
2 signoffs for any change.
If a core member is sending in a PR, please find 2 core members that don't
include them PR submitter. The idea here is that one can work with the PR
include the PR submitter. The idea here is that one can work with the PR
author, and a second acks the entire change set.
If the change is adding documentation, feel free to just merge after one

View File

@ -36,7 +36,7 @@ languages.
Builtins
========
Hy features a number special forms that are used to help generate
Hy features a number of special forms that are used to help generate
correct Python AST. The following are "special" forms, which may have
behavior that's slightly unexpected in some situations.
@ -89,7 +89,7 @@ The following code demonstrates this:
---
`->>` or `threading tail macro` is similar to `threading macro` but instead of
inserting each expression into the next expressions first argument place it
inserting each expression into the next expressions first argument place, it
appends it as the last argument. The following code demonstrates this:
.. code-block:: clj
@ -283,7 +283,7 @@ do / progn
the `do` and `progn` forms are used to evaluate each of their arguments and
return the last one. Return values from every other than the last argument are
discarded. It can be used in `lambda` or `list-comp` to perform more complex
logic as show by one of the examples.
logic as shown by one of the examples.
Some example usage:
@ -430,7 +430,7 @@ defmacro
`defmacro` is used to define macros. The general format is
`(defmacro [parameters] expr)`.
Following example defines a macro that can be used to swap order of elements in
The following example defines a macro that can be used to swap order of elements in
code, allowing the user to write code in infix notation, where operator is in
between the operands.
@ -1169,7 +1169,7 @@ yield
The generator is iterable and therefore can be used in loops, list
comprehensions and other similar constructs.
Especially the second example shows how generators can be used to generate
The function random-numbers shows how generators can be used to generate
infinite series without consuming infinite amount of memory.
.. code-block:: clj

View File

@ -9,7 +9,7 @@ Core Functions
.. _is-coll-fn:
coll?
----
-----
.. versionadded:: 0.9.13

View File

@ -24,19 +24,28 @@ Syntax
=> #^1+2+3+4+3+2
1+2+3+4+3+2
Hy has no literal for tuples. Lets say you dislike `(, ...)` and want something
else. This is a problem reader macros are able to solve in a neat way.
::
=> (defreader t [expr] `(, ~@expr))
=> #t(1 2 3)
(1, 2, 3)
You could even do like clojure, and have a literal for regular expressions!
::
=> (import re)
=> (defreader r [expr] `(re.compile ~expr))
=> #r".*"
<_sre.SRE_Pattern object at 0xcv7713ph15#>
Implementation
==============
Hy uses ``defreader`` to define the reader symbol, and ``#`` as the dispatch
character. ``#`` expands into ``(dispatch_reader_macro ...)`` where the symbol
and expression is quoted, and then passed along to the correct function::
=> (defreader ^ ...)
=> #^()
;=> (dispatch_reader_macro '^ '())
``defreader`` takes a single character as symbol name for the reader macro,
anything longer will return an error. Implementation wise, ``defreader``
expands into a lambda covered with a decorator, this decorater saves the
@ -47,14 +56,17 @@ lambda in a dict with its module name and symbol.
=> (defreader ^ [expr] (print expr))
;=> (with_decorator (hy.macros.reader ^) (fn [expr] (print expr)))
Anything passed along is quoted, thus given to the function defined.
``#`` expands into ``(dispatch_reader_macro ...)`` where the symbol
and expression is passed to the correct function.
::
=> #^()
;=> (dispatch_reader_macro ^ ())
=> #^"Hello"
"Hello"
.. warning::
Because of a limitation in Hy's lexer and parser, reader macros can't
redefine defined syntax such as ``()[]{}``. This will most likely be

View File

@ -2,20 +2,20 @@
Quickstart
==========
.. image:: _static/cuddles.png
.. image:: _static/cuddles-transparent-small.png
:alt: Karen Rustard's Cuddles
(thanks to Karen Rustad for Cuddles!)
(Thanks to Karen Rustad for Cuddles!)
HOW TO GET HY REAL FAST:
**HOW TO GET HY REAL FAST**:
1. create a `Python virtual environment
1. Create a `Virtual Python Environment
<https://pypi.python.org/pypi/virtualenv>`_
2. activate your Python virtual environment
3. ``pip install hy``
4. start a REPL with ``hy``
5. type stuff in the REPL::
2. Activate your Virtual Python Environment
3. Install `hy from PyPI <https://pypi.python.org/pypi/hy>`_ with ``pip install hy``
4. Start a REPL with ``hy``
5. Type stuff in the REPL::
=> (print "Hy!")
Hy!
@ -25,20 +25,19 @@ HOW TO GET HY REAL FAST:
etc
6. hit CTRL-D when you're done
6. Hit CTRL-D when you're done
OMG! That's amazing! I want to write a hy program.
7. open up an elite programming editor
8. type::
7. Open up an elite programming editor and type::
(print "i was going to code in python syntax, but then i got hy")
(print "I was going to code in python syntax, but then I got hy.")
9. save as ``test_program_of_awesome.hy``
10. run::
8. Save as ``awesome.hy``
9. And run your first Hy program::
hy test_program_of_awesome.hy
hy awesome.hy
11. take a deep breath so as to not hyperventilate
12. smile villainously and sneak off to your hydeaway and do
10. Take a deep breath so as to not hyperventilate
11. Smile villainously and sneak off to your hydeaway and do
unspeakable things

View File

@ -406,7 +406,7 @@ The same thing in Hy::
...
[3, 2, 1, 4]
See how we use kwapply to handle the fancy pssing? :)
See how we use kwapply to handle the fancy passing? :)
There's also a dictionary-style keyword arguments construction that
looks like:

27
eg/flask/meth_example.hy Normal file
View File

@ -0,0 +1,27 @@
;;; Simple Flask application
;;;
;;; Requires to have Flask installed
;;;
;;; You can test it via:
;;;
;;; $ curl 127.0.0.1:5151
;;; $ curl -X POST 127.0.0.1:5151/post
;;; $ curl -X POST 127.0.0.1:5151/both
;;; $ curl 127.0.0.1:5151/both
(import [flask [Flask]])
(require hy.contrib.meth)
(setv app (Flask "__main__"))
(route get-index "/" []
(str "Hy world!"))
(post-route post-index "/post" []
(str "Hy post world!"))
(route-with-methods both-index "/both" ["GET" "POST"] []
(str "Hy to both worlds!"))
(apply app.run [] {"port" 5151})

View File

@ -38,6 +38,7 @@ except ImportError:
(x >> 24) & 0xff]))
import sys
PY27 = sys.version_info >= (2, 7)
PY3 = sys.version_info[0] >= 3
PY33 = sys.version_info >= (3, 3)
PY34 = sys.version_info >= (3, 4)

View File

@ -214,8 +214,8 @@ def run_repl(hr=None, spy=False):
return 0
def run_icommand(source):
hr = HyREPL()
def run_icommand(source, spy=False):
hr = HyREPL(spy)
hr.runsource(source, filename='<input>', symbol='single')
return run_repl(hr)
@ -270,7 +270,7 @@ def cmdline_handler(scriptname, argv):
if options.icommand:
# User did "hy -i ..."
return run_icommand(options.icommand)
return run_icommand(options.icommand, spy=options.spy)
if options.args:
if options.args[0] == "-":

View File

@ -38,8 +38,8 @@ from hy.models.dict import HyDict
from hy.errors import HyCompileError, HyTypeError
import hy.macros
from hy.macros import require, macroexpand
from hy._compat import str_type, long_type, PY33, PY3, PY34
from hy._compat import str_type, long_type, PY27, PY33, PY3, PY34
from hy.macros import require, macroexpand, reader_macroexpand
import hy.importer
import traceback
@ -1265,41 +1265,114 @@ class HyASTCompiler(object):
ctx=ast.Load())
return ret
def _compile_generator_iterables(self, trailers):
"""Helper to compile the "trailing" parts of comprehensions:
generators and conditions"""
generators = trailers.pop(0)
cond = self.compile(trailers.pop(0)) if trailers != [] else Result()
gen_it = iter(generators)
paired_gens = zip(gen_it, gen_it)
gen_res = Result()
gen = []
for target, iterable in paired_gens:
comp_target = self.compile(target)
target = self._storeize(comp_target)
gen_res += self.compile(iterable)
gen.append(ast.comprehension(
target=target,
iter=gen_res.force_expr,
ifs=[]))
if cond.expr:
gen[-1].ifs.append(cond.expr)
return gen_res + cond, gen
@builds("list_comp")
@checkargs(min=2, max=3)
def compile_list_comprehension(self, expr):
# (list-comp expr (target iter) cond?)
expr.pop(0)
expression = expr.pop(0)
tar_it = iter(expr.pop(0))
targets = zip(tar_it, tar_it)
cond = self.compile(expr.pop(0)) if expr != [] else Result()
generator_res = Result()
generators = []
for target, iterable in targets:
comp_target = self.compile(target)
target = self._storeize(comp_target)
generator_res += self.compile(iterable)
generators.append(ast.comprehension(
target=target,
iter=generator_res.force_expr,
ifs=[]))
if cond.expr:
generators[-1].ifs.append(cond.expr)
gen_res, gen = self._compile_generator_iterables(expr)
compiled_expression = self.compile(expression)
ret = compiled_expression + generator_res + cond
ret = compiled_expression + gen_res
ret += ast.ListComp(
lineno=expr.start_line,
col_offset=expr.start_column,
elt=compiled_expression.force_expr,
generators=generators)
generators=gen)
return ret
@builds("set_comp")
@checkargs(min=2, max=3)
def compile_set_comprehension(self, expr):
if PY27:
ret = self.compile_list_comprehension(expr)
expr = ret.expr
ret.expr = ast.SetComp(
lineno=expr.lineno,
col_offset=expr.col_offset,
elt=expr.elt,
generators=expr.generators)
return ret
expr[0] = HySymbol("list_comp").replace(expr[0])
expr = HyExpression([HySymbol("set"), expr]).replace(expr)
return self.compile(expr)
@builds("dict_comp")
@checkargs(min=3, max=4)
def compile_dict_comprehension(self, expr):
if PY27:
expr.pop(0) # dict-comp
key = expr.pop(0)
value = expr.pop(0)
gen_res, gen = self._compile_generator_iterables(expr)
compiled_key = self.compile(key)
compiled_value = self.compile(value)
ret = compiled_key + compiled_value + gen_res
ret += ast.DictComp(
lineno=expr.start_line,
col_offset=expr.start_column,
key=compiled_key.force_expr,
value=compiled_value.force_expr,
generators=gen)
return ret
# In Python 2.6, turn (dict-comp key value [foo]) into
# (dict (list-comp (, key value) [foo]))
expr[0] = HySymbol("list_comp").replace(expr[0])
expr[1:3] = [HyExpression(
[HySymbol(",")] +
expr[1:3]
).replace(expr[1])]
expr = HyExpression([HySymbol("dict"), expr]).replace(expr)
return self.compile(expr)
@builds("genexpr")
def compile_genexpr(self, expr):
ret = self.compile_list_comprehension(expr)
expr = ret.expr
ret.expr = ast.GeneratorExp(
lineno=expr.lineno,
col_offset=expr.col_offset,
elt=expr.elt,
generators=expr.generators)
return ret
@builds("apply")
@checkargs(min=1, max=3)
def compile_apply_expression(self, expr):
@ -1907,7 +1980,7 @@ class HyASTCompiler(object):
return ret
@builds("defreader")
@checkargs(min=2, max=3)
@checkargs(min=2)
def compile_reader(self, expression):
expression.pop(0)
name = expression.pop(0)
@ -1929,6 +2002,23 @@ class HyASTCompiler(object):
return ret
@builds("dispatch_reader_macro")
@checkargs(exact=2)
def compile_dispatch_reader_macro(self, expression):
expression.pop(0) # dispatch-reader-macro
str_char = expression.pop(0)
if not type(str_char) == HyString:
raise HyTypeError(
str_char,
"Trying to expand a reader macro using `{0}' instead "
"of string".format(type(str_char).__name__),
)
module = self.module_name
expr = reader_macroexpand(str_char, expression.pop(0), module)
return self.compile(expr)
@builds("eval_and_compile")
def compile_eval_and_compile(self, expression):
expression[0] = HySymbol("progn")

View File

@ -1,6 +1,7 @@
;;; Hy tail-call optimization
;;
;; Copyright (c) 2014 Clinton Dreisbach <clinton@dreisbach.us>
;; Copyright (c) 2014 Paul R. Tagliamonte <tag@pault.ag>
;;
;; Permission is hereby granted, free of charge, to any person obtaining a
;; copy of this software and associated documentation files (the "Software"),
@ -55,7 +56,24 @@
(recursive-replace old-term new-term term)]
[True term]) [term body])))
(defmacro loop [bindings &rest body]
(defmacro/g! fnr [signature &rest body]
(let [[new-body (recursive-replace 'recur g!recur-fn body)]]
`(do
(import [hy.contrib.loop [--trampoline--]])
(with-decorator
--trampoline--
(def ~g!recur-fn (fn [~@signature] ~@new-body)))
~g!recur-fn)))
(defmacro defnr [name lambda-list &rest body]
(if (not (= (type name) HySymbol))
(macro-error name "defnr takes a name as first argument"))
`(setv ~name (fnr ~lambda-list ~@body)))
(defmacro/g! loop [bindings &rest body]
;; Use inside functions like so:
;; (defun factorial [n]
;; (loop [[i n]
@ -67,13 +85,7 @@
;; If recur is used in a non-tail-call position, None is returned, which
;; causes chaos. Fixing this to detect if recur is in a tail-call position
;; and erroring if not is a giant TODO.
(with-gensyms [recur-fn]
(let [[fnargs (map (fn [x] (first x)) bindings)]
[initargs (map second bindings)]
[new-body (recursive-replace 'recur recur-fn body)]]
`(do
(import [hy.contrib.loop [--trampoline--]])
(def ~recur-fn
(--trampoline-- (fn [~@fnargs]
~@new-body)))
(~recur-fn ~@initargs)))))
(let [[fnargs (map (fn [x] (first x)) bindings)]
[initargs (map second bindings)]]
`(do (defnr ~g!recur-fn [~@fnargs] ~@body)
(~g!recur-fn ~@initargs))))

View File

@ -1,5 +1,5 @@
;;; Meth
;; based on paultag's meth library to access a Flask based application
;;; Hy on Meth
;;; based on paultag's meth library to access a Flask based application
(defmacro route-with-methods [name path methods params &rest code]
"Same as route but with an extra methods array to specify HTTP methods"
@ -25,29 +25,3 @@
(defmacro delete-route [name path params &rest code]
"Delete request"
`(route-with-methods ~name ~path ["DELETE"] ~params ~@code))
;;; Simple example application
;;; Requires to have Flask installed
;; (import [flask [Flask]])
;; (setv app (Flask "__main__"))
;; (require hy.contrib.meth)
;; (print "setup / with GET")
;; (route get-index "/" [] (str "Hy world!"))
;; (print "setup /post with POST")
;; (post-route post-index "/post" [] (str "Hy post world!"))
;; (route-with-methods both-index "/both" []
;; (str "Hy to both worlds!") ["GET" "POST"])
;; (.run app)
;;; Now you can do:
;;; curl 127.0.0.1:5000
;;; curl -X POST 127.0.0.1:5000/post
;;; curl -X POST 127.0.0.1:5000/both
;;; curl 127.0.0.1:5000/both

View File

@ -181,13 +181,3 @@
(setv -args (cdr (car -args))))
`(apply ~-fun [~@-args] (dict (sum ~-okwargs [])))))
(defmacro dispatch-reader-macro [char &rest body]
"Dispatch a reader macro based on the character"
(import [hy.macros])
(setv str_char (get char 1))
(if (not (in str_char hy.macros._hy_reader_chars))
(raise (hy.compiler.HyTypeError char (.format "There is no reader macro with the character `{0}`" str_char))))
`(do (import [hy.macros [_hy_reader]])
((get (get _hy_reader --name--) ~char) ~(get body 0))))

View File

@ -154,8 +154,8 @@ def term_unquote_splice(p):
@set_quote_boundaries
def hash_reader(p):
st = p[0].getstr()[1]
str_object = HyExpression([HySymbol("quote"), HyString(st)])
expr = HyExpression([HySymbol("quote"), p[1]])
str_object = HyString(st)
expr = p[1]
return HyExpression([HySymbol("dispatch_reader_macro"), str_object, expr])
@ -242,14 +242,19 @@ def t_identifier(p):
if obj.startswith("&"):
return HyLambdaListKeyword(obj)
if obj.startswith("*") and obj.endswith("*") and obj not in ("*", "**"):
obj = obj[1:-1].upper()
def mangle(p):
if p.startswith("*") and p.endswith("*") and p not in ("*", "**"):
p = p[1:-1].upper()
if "-" in obj and obj != "-":
obj = obj.replace("-", "_")
if "-" in p and p != "-":
p = p.replace("-", "_")
if obj.endswith("?") and obj != "?":
obj = "is_%s" % (obj[:-1])
if p.endswith("?") and p != "?":
p = "is_%s" % (p[:-1])
return p
obj = ".".join([mangle(part) for part in obj.split(".")])
return HySymbol(obj)

View File

@ -43,7 +43,6 @@ EXTRA_MACROS = [
_hy_macros = defaultdict(dict)
_hy_reader = defaultdict(dict)
_hy_reader_chars = set()
def macro(name):
@ -85,8 +84,6 @@ def reader(name):
module_name = None
_hy_reader[module_name][name] = fn
# Ugly hack to get some error handling
_hy_reader_chars.add(name)
return fn
return _
@ -209,3 +206,20 @@ def macroexpand_1(tree, module_name):
return ntree
return tree
def reader_macroexpand(char, tree, module_name):
"""Expand the reader macro "char" with argument `tree`."""
load_macros(module_name)
if not char in _hy_reader[module_name]:
raise HyTypeError(
char,
"`{0}' is not a reader macro in module '{1}'".format(
char,
module_name,
),
)
expr = _hy_reader[module_name][char](tree)
return _wrap_value(expr).replace(tree)

View File

@ -258,7 +258,7 @@ def test_reader_macro():
"""Ensure reader macros are handles properly"""
entry = tokenize("#^()")
assert entry[0][0] == HySymbol("dispatch_reader_macro")
assert entry[0][1] == HyExpression([HySymbol("quote"), HyString("^")])
assert entry[0][1] == HyString("^")
assert len(entry[0]) == 3
@ -266,3 +266,39 @@ def test_lex_comment_382():
"""Ensure that we can tokenize sources with a comment at the end"""
entry = tokenize("foo ;bar\n;baz")
assert entry == [HySymbol("foo")]
def test_lex_mangling_star():
"""Ensure that mangling starred identifiers works according to plan"""
entry = tokenize("*foo*")
assert entry == [HySymbol("FOO")]
entry = tokenize("*")
assert entry == [HySymbol("*")]
entry = tokenize("*foo")
assert entry == [HySymbol("*foo")]
def test_lex_mangling_hyphen():
"""Ensure that hyphens get translated to underscores during mangling"""
entry = tokenize("foo-bar")
assert entry == [HySymbol("foo_bar")]
entry = tokenize("-")
assert entry == [HySymbol("-")]
def test_lex_mangling_qmark():
"""Ensure that identifiers ending with a question mark get mangled ok"""
entry = tokenize("foo?")
assert entry == [HySymbol("is_foo")]
entry = tokenize("?")
assert entry == [HySymbol("?")]
entry = tokenize("im?foo")
assert entry == [HySymbol("im?foo")]
entry = tokenize(".foo?")
assert entry == [HySymbol(".is_foo")]
entry = tokenize("foo.bar?")
assert entry == [HySymbol("foo.is_bar")]
entry = tokenize("foo?.bar")
assert entry == [HySymbol("is_foo.bar")]
entry = tokenize(".foo?.bar.baz?")
assert entry == [HySymbol(".is_foo.bar.is_baz")]

View File

@ -525,7 +525,7 @@
(assert (= x 3))))
(defn test-comprehensions []
(defn test-list-comprehensions []
"NATIVE: test list comprehensions"
(assert (= (list-comp (* x 2) (x (range 2))) [0 2]))
(assert (= (list-comp (* x 2) (x (range 4)) (% x 2)) [2 6]))
@ -536,6 +536,41 @@
(assert (= (list-comp j (j [1 2])) [1 2])))
(defn test-set-comprehensions []
"NATIVE: test set comprehensions"
(assert (instance? set (set-comp x [x (range 2)])))
(assert (= (set-comp (* x 2) (x (range 2))) (set [0 2])))
(assert (= (set-comp (* x 2) (x (range 4)) (% x 2)) (set [2 6])))
(assert (= (set-comp (* y 2) ((, x y) (.items {"1" 1 "2" 2})))
(set [2 4])))
(assert (= (set-comp (, x y) (x (range 2) y (range 2)))
(set [(, 0 0) (, 0 1) (, 1 0) (, 1 1)])))
(assert (= (set-comp j (j [1 2])) (set [1 2]))))
(defn test-dict-comprehensions []
"NATIVE: test dict comprehensions"
(assert (instance? dict (dict-comp x x [x (range 2)])))
(assert (= (dict-comp x (* x 2) (x (range 2))) {1 2 0 0}))
(assert (= (dict-comp x (* x 2) (x (range 4)) (% x 2)) {3 6 1 2}))
(assert (= (dict-comp x (* y 2) ((, x y) (.items {"1" 1 "2" 2})))
{"2" 4 "1" 2}))
(assert (= (dict-comp (, x y) (+ x y) (x (range 2) y (range 2)))
{(, 0 0) 0 (, 1 0) 1 (, 0 1) 1 (, 1 1) 2})))
(defn test-generator-expressions []
"NATIVE: test generator expressions"
(assert (not (instance? list (genexpr x [x (range 2)]))))
(assert (= (list (genexpr (* x 2) (x (range 2)))) [0 2]))
(assert (= (list (genexpr (* x 2) (x (range 4)) (% x 2))) [2 6]))
(assert (= (list (sorted (genexpr (* y 2) ((, x y) (.items {"1" 1 "2" 2})))))
[2 4]))
(assert (= (list (genexpr (, x y) (x (range 2) y (range 2))))
[(, 0 0) (, 0 1) (, 1 0) (, 1 1)]))
(assert (= (list (genexpr j (j [1 2]))) [1 2])))
(defn test-defn-order []
"NATIVE: test defn evaluation order"
(setv acc [])

View File

@ -23,10 +23,14 @@
(assert (= #+2 3)))
(defn test-reader-macro-compile-docstring []
"Test if we can compile with a docstring"
(try
(defreader d []
"Compiles with docstrings")
(except [Exception]
(assert False))))
(defn test-reader-macros-macros []
"Test if defreader is actually a macro"
(defreader t [expr]
`(, ~@expr))
(def a #t[1 2 3])
(assert (= (type a) tuple))
(assert (= (, 1 2 3) a)))

View File

@ -76,6 +76,14 @@ def test_bin_hy_icmd():
assert "figlet" in output
def test_bin_hy_icmd_and_spy():
ret = run_cmd("hy -i \"(+ [] [])\" --spy", "(+ 1 1)")
assert ret[0] == 0
output = ret[1]
assert "([] + [])" in output
def test_bin_hy_missing_file():
ret = run_cmd("hy foobarbaz")
assert ret[0] == 2
@ -126,7 +134,7 @@ def test_hy2py():
for f in filenames:
if f.endswith(".hy"):
i += 1
ret = run_cmd("bin/hy2py " + os.path.join(dirpath, f))
ret = run_cmd("bin/hy2py -s -a " + os.path.join(dirpath, f))
assert ret[0] == 0, f
assert len(ret[1]) > 1, f
assert len(ret[2]) == 0, f