Merge branch 'master' into pr/185
Conflicts: hy/macros.py tests/compilers/test_compiler.py Hoodoggy!
This commit is contained in:
commit
9c28e0292d
@ -99,7 +99,7 @@ def builds(_type):
|
||||
|
||||
unpythonic_chars = ["-"]
|
||||
really_ok = ["-"]
|
||||
if True in (x in str_type(_type) for x in unpythonic_chars):
|
||||
if any(x in unpythonic_chars for x in str_type(_type)):
|
||||
if _type not in really_ok:
|
||||
raise TypeError("`build' needs to be *post* translated strings, "
|
||||
"Mr. / Mrs. Hypser. -- `%s' sucks." % (_type))
|
||||
@ -422,22 +422,24 @@ class HyASTCompiler(object):
|
||||
|
||||
if isinstance(expr, HyLambdaListKeyword):
|
||||
if expr not in expr._valid_types:
|
||||
raise HyCompileError("{0} is not a valid "
|
||||
"lambda-keyword.".format(repr(expr)))
|
||||
raise HyTypeError(expr, "{0} is not a valid "
|
||||
"lambda-keyword.".format(repr(expr)))
|
||||
if expr == "&rest" and lambda_keyword is None:
|
||||
lambda_keyword = expr
|
||||
elif expr == "&optional":
|
||||
if len(defaults) > 0:
|
||||
raise HyCompileError("There can only be &optional "
|
||||
"arguments or one &key argument")
|
||||
raise HyTypeError(expr,
|
||||
"There can only be &optional "
|
||||
"arguments or one &key argument")
|
||||
lambda_keyword = expr
|
||||
elif expr == "&key":
|
||||
lambda_keyword = expr
|
||||
elif expr == "&kwargs":
|
||||
lambda_keyword = expr
|
||||
else:
|
||||
raise HyCompileError("{0} is in an invalid "
|
||||
"position.".format(repr(expr)))
|
||||
raise HyTypeError(expr,
|
||||
"{0} is in an invalid "
|
||||
"position.".format(repr(expr)))
|
||||
# we don't actually care about this token, so we set
|
||||
# our state and continue to the next token...
|
||||
continue
|
||||
@ -446,28 +448,33 @@ class HyASTCompiler(object):
|
||||
args.append(expr)
|
||||
elif lambda_keyword == "&rest":
|
||||
if varargs:
|
||||
raise HyCompileError("There can only be one "
|
||||
"&rest argument")
|
||||
raise HyTypeError(expr,
|
||||
"There can only be one "
|
||||
"&rest argument")
|
||||
varargs = str(expr)
|
||||
elif lambda_keyword == "&key":
|
||||
if type(expr) != HyDict:
|
||||
raise TypeError("There can only be one &key "
|
||||
"argument")
|
||||
raise HyTypeError(expr,
|
||||
"There can only be one &key "
|
||||
"argument")
|
||||
else:
|
||||
if len(defaults) > 0:
|
||||
raise HyCompileError("There can only be &optional "
|
||||
"arguments or one &key argument")
|
||||
raise HyTypeError(expr,
|
||||
"There can only be &optional "
|
||||
"arguments or one &key argument")
|
||||
# As you can see, Python has a funny way of
|
||||
# defining keyword arguments.
|
||||
for k, v in expr.items():
|
||||
it = iter(expr)
|
||||
for k, v in zip(it, it):
|
||||
args.append(k)
|
||||
ret += self.compile(v)
|
||||
defaults.append(ret.force_expr)
|
||||
elif lambda_keyword == "&optional":
|
||||
if isinstance(expr, HyList):
|
||||
if not len(expr) == 2:
|
||||
raise TypeError("optional args should be bare names "
|
||||
"or 2-item lists")
|
||||
raise HyTypeError(expr,
|
||||
"optional args should be bare names "
|
||||
"or 2-item lists")
|
||||
k, v = expr
|
||||
else:
|
||||
k = expr
|
||||
@ -477,8 +484,9 @@ class HyASTCompiler(object):
|
||||
defaults.append(ret.force_expr)
|
||||
elif lambda_keyword == "&kwargs":
|
||||
if kwargs:
|
||||
raise HyCompileError("There can only be one "
|
||||
"&kwargs argument")
|
||||
raise HyTypeError(expr,
|
||||
"There can only be one "
|
||||
"&kwargs argument")
|
||||
kwargs = str(expr)
|
||||
|
||||
return ret, args, defaults, varargs, kwargs
|
||||
@ -546,7 +554,7 @@ class HyASTCompiler(object):
|
||||
name = form.__class__.__name__
|
||||
imports = set([name])
|
||||
|
||||
if isinstance(form, HyList):
|
||||
if isinstance(form, (HyList, HyDict)):
|
||||
if not form:
|
||||
contents = HyList()
|
||||
else:
|
||||
@ -764,7 +772,8 @@ class HyASTCompiler(object):
|
||||
@builds("except")
|
||||
@builds("catch")
|
||||
def magic_internal_form(self, expr):
|
||||
raise TypeError("Error: `%s' can't be used like that." % (expr[0]))
|
||||
raise HyTypeError(expr,
|
||||
"Error: `%s' can't be used like that." % (expr[0]))
|
||||
|
||||
def _compile_catch_expression(self, expr, var):
|
||||
catch = expr.pop(0) # catch
|
||||
@ -796,6 +805,11 @@ class HyASTCompiler(object):
|
||||
# let's pop variable and use it as name
|
||||
if len(exceptions) == 2:
|
||||
name = exceptions.pop(0)
|
||||
if not isinstance(name, HySymbol):
|
||||
raise HyTypeError(
|
||||
exceptions,
|
||||
"Exception storage target name must be a symbol.")
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
# Python3 features a change where the Exception handler
|
||||
# moved the name from a Name() to a pure Python String type.
|
||||
@ -1694,7 +1708,7 @@ class HyASTCompiler(object):
|
||||
|
||||
@builds(HyDict)
|
||||
def compile_dict(self, m):
|
||||
keyvalues, ret = self._compile_collect(sum(m.items(), ()))
|
||||
keyvalues, ret = self._compile_collect(m)
|
||||
|
||||
ret += ast.Dict(lineno=m.start_line,
|
||||
col_offset=m.start_column,
|
||||
|
@ -228,9 +228,7 @@ class Dict(ListeyThing):
|
||||
|
||||
def exit(self):
|
||||
self.commit()
|
||||
it = iter(self.nodes)
|
||||
result = dict(zip(it, it))
|
||||
self.result = HyDict(result)
|
||||
self.result = HyDict(self.nodes)
|
||||
|
||||
end_char = "}"
|
||||
|
||||
|
10
hy/macros.py
10
hy/macros.py
@ -20,7 +20,6 @@
|
||||
|
||||
from hy.models.expression import HyExpression
|
||||
from hy.models.string import HyString
|
||||
from hy.models.dict import HyDict
|
||||
from hy.models.list import HyList
|
||||
|
||||
from collections import defaultdict
|
||||
@ -65,15 +64,8 @@ def process(tree, module_name):
|
||||
ntree.replace(tree)
|
||||
return ntree
|
||||
|
||||
if isinstance(tree, HyDict):
|
||||
obj = HyDict(dict((process(x, module_name),
|
||||
process(tree[x], module_name))
|
||||
for x in tree))
|
||||
obj.replace(tree)
|
||||
return obj
|
||||
|
||||
if isinstance(tree, HyList):
|
||||
obj = HyList([process(x, module_name) for x in tree]) # NOQA
|
||||
obj = tree.__class__([process(x, module_name) for x in tree]) # NOQA
|
||||
# flake8 thinks we're redefining from 52.
|
||||
obj.replace(tree)
|
||||
return obj
|
||||
|
@ -18,17 +18,13 @@
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
|
||||
from hy.models import HyObject
|
||||
from hy.models.list import HyList
|
||||
|
||||
|
||||
class HyDict(HyObject, dict):
|
||||
class HyDict(HyList):
|
||||
"""
|
||||
HyDict (just a dict)
|
||||
HyDict (just a representation of a dict)
|
||||
"""
|
||||
|
||||
def replace(self, other):
|
||||
for x in self:
|
||||
self[x].replace(other)
|
||||
x.replace(other)
|
||||
|
||||
HyObject.replace(self, other)
|
||||
def __repr__(self):
|
||||
return "{%s}" % (" ".join([repr(x) for x in self]))
|
||||
|
@ -22,7 +22,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from hy import HyString
|
||||
from hy.compiler import hy_compile, HyCompileError
|
||||
from hy.compiler import hy_compile, HyCompileError, HyTypeError
|
||||
from hy.lex import tokenize
|
||||
|
||||
import ast
|
||||
@ -47,8 +47,11 @@ def cant_compile(expr):
|
||||
try:
|
||||
hy_compile(expr, "__main__")
|
||||
assert False
|
||||
except HyCompileError:
|
||||
pass
|
||||
except HyCompileError as e:
|
||||
# Anything that can't be compiled should raise a user friendly
|
||||
# error, otherwise it's a compiler bug.
|
||||
assert isinstance(e.exception, HyTypeError)
|
||||
assert e.traceback
|
||||
|
||||
|
||||
def test_ast_bad_type():
|
||||
|
@ -27,11 +27,21 @@ if sys.version_info[0] <= 2 and sys.version_info[1] <= 6:
|
||||
else:
|
||||
import unittest
|
||||
|
||||
|
||||
from hy import compiler
|
||||
from hy.models.expression import HyExpression
|
||||
from hy.models.list import HyList
|
||||
from hy.models.symbol import HySymbol
|
||||
from hy.compiler import HyASTCompiler
|
||||
|
||||
|
||||
class CompilerTest(unittest.TestCase):
|
||||
|
||||
def test_builds_with_dash(self):
|
||||
self.assert_(callable(compiler.builds("foobar")))
|
||||
self.assert_(callable(compiler.builds("foo_bar")))
|
||||
self.assert_(callable(compiler.builds("-")))
|
||||
self.assertRaisesRegexp(TypeError,
|
||||
"\*post\* translated strings",
|
||||
compiler.builds, "foobar-with-dash-")
|
||||
|
||||
|
||||
class HyASTCompilerTest(unittest.TestCase):
|
||||
@ -46,7 +56,7 @@ class HyASTCompilerTest(unittest.TestCase):
|
||||
return h
|
||||
|
||||
def setUp(self):
|
||||
self.c = HyASTCompiler('')
|
||||
self.c = compiler.HyASTCompiler('test')
|
||||
|
||||
def test_fn_compiler_empty_function(self):
|
||||
ret = self.c.compile_function_def(
|
||||
|
@ -185,15 +185,18 @@ def test_lex_line_counting_multi_inner():
|
||||
def test_dicts():
|
||||
""" Ensure that we can tokenize a dict. """
|
||||
objs = tokenize("{foo bar bar baz}")
|
||||
assert objs == [HyDict({
|
||||
"foo": "bar",
|
||||
"bar": "baz"
|
||||
})]
|
||||
assert objs == [HyDict(["foo", "bar", "bar", "baz"])]
|
||||
|
||||
objs = tokenize("(bar {foo bar bar baz})")
|
||||
assert objs == [HyExpression([HySymbol("bar"),
|
||||
HyDict({"foo": "bar",
|
||||
"bar": "baz"})])]
|
||||
HyDict(["foo", "bar",
|
||||
"bar", "baz"])])]
|
||||
|
||||
objs = tokenize("{(foo bar) (baz quux)}")
|
||||
assert objs == [HyDict([
|
||||
HyExpression([HySymbol("foo"), HySymbol("bar")]),
|
||||
HyExpression([HySymbol("baz"), HySymbol("quux")])
|
||||
])]
|
||||
|
||||
|
||||
def test_nospace():
|
||||
|
@ -15,6 +15,12 @@
|
||||
(assert (= [1 2 3 4] (+ [1 2] [3 4]))))
|
||||
|
||||
|
||||
(defn test-dicts []
|
||||
"NATIVE: test dicts work right"
|
||||
(assert (= {1 2 3 4} {3 4 1 2}))
|
||||
(assert (= {1 2 3 4} {1 (+ 1 1) 3 (+ 2 2)})))
|
||||
|
||||
|
||||
(defn test-setv-get []
|
||||
"NATIVE: test setv works on a get expression"
|
||||
(setv foo [0 1 2])
|
||||
|
@ -1,3 +1,6 @@
|
||||
(import hy)
|
||||
|
||||
|
||||
(defn test-quote []
|
||||
"NATIVE: test for quoting functionality"
|
||||
(setf q (quote (a b c)))
|
||||
@ -21,6 +24,25 @@
|
||||
(assert (= (cdr q1) (quote (a b c)))))
|
||||
|
||||
|
||||
(defn test-quote-dicts []
|
||||
"NATIVE: test quoting dicts"
|
||||
(setf q (quote {foo bar baz quux}))
|
||||
(assert (= (len q) 4))
|
||||
(assert (= (get q 0) (quote foo)))
|
||||
(assert (= (get q 1) (quote bar)))
|
||||
(assert (= (get q 2) (quote baz)))
|
||||
(assert (= (get q 3) (quote quux)))
|
||||
(assert (= (type q) hy.HyDict)))
|
||||
|
||||
|
||||
(defn test-quote-expr-in-dict []
|
||||
"NATIVE: test quoting nested exprs in dict"
|
||||
(setf q (quote {(foo bar) 0}))
|
||||
(assert (= (len q) 2))
|
||||
(setf qq (get q 0))
|
||||
(assert (= qq (quote (foo bar)))))
|
||||
|
||||
|
||||
(defn test-quasiquote []
|
||||
"NATIVE: test that quasiquote and quote are equivalent for simple cases"
|
||||
(setf q (quote (a b c)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user