Check that compiler error are user always user friendly

Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
Julien Danjou 2013-05-13 18:09:05 +02:00
parent de85940114
commit 4e202aa1a5
2 changed files with 34 additions and 20 deletions

View File

@ -419,22 +419,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
@ -443,17 +445,20 @@ 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():
@ -463,8 +468,9 @@ class HyASTCompiler(object):
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
@ -474,8 +480,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
@ -760,7 +767,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
@ -792,6 +800,9 @@ 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.

View File

@ -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
@ -43,8 +43,11 @@ def cant_compile(expr):
try:
hy_compile(expr)
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():