diff --git a/hy/lex/states.py b/hy/lex/states.py index 6966a39..8e5951c 100644 --- a/hy/lex/states.py +++ b/hy/lex/states.py @@ -20,6 +20,7 @@ from hy.models.expression import HyExpression from hy.models.integer import HyInteger +from hy.models.lambdalist import HyLambdaListKeyword from hy.models.symbol import HySymbol from hy.models.string import HyString from hy.models.dict import HyDict @@ -45,6 +46,7 @@ def _resolve_atom(obj): Resolve a bare atom into one of the following (in order): - Integer + - LambdaListKeyword - Symbol """ try: @@ -52,6 +54,9 @@ def _resolve_atom(obj): except ValueError: pass + if obj.startswith("&"): + return HyLambdaListKeyword(obj) + table = { "true": "True", "false": "False", diff --git a/hy/models/lambdalist.py b/hy/models/lambdalist.py new file mode 100644 index 0000000..b5da9e7 --- /dev/null +++ b/hy/models/lambdalist.py @@ -0,0 +1,39 @@ +# Copyright (c) 2013 James King +# +# 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 hy.models.string import HyString + + +class HyLambdaListKeyword(HyString): + """ + Hy LambdaListKeyword. Demarcates arguments in an argument list. + + (defun my-fun (x &rest xs &optional (foo "default string"))) + + becomes: + + def my_fun(x, *xs, foo="default string"): + pass + """ + + _valid_types = ["&rest", "&optional", "&kwargs"] + + def __init__(self, string): + self += string diff --git a/tests/lex/test_lex.py b/tests/lex/test_lex.py index 7740fed..5660418 100644 --- a/tests/lex/test_lex.py +++ b/tests/lex/test_lex.py @@ -20,6 +20,7 @@ from hy.models.expression import HyExpression from hy.models.integer import HyInteger +from hy.models.lambdalist import HyLambdaListKeyword from hy.models.symbol import HySymbol from hy.models.string import HyString from hy.models.dict import HyDict @@ -62,6 +63,14 @@ def test_lex_expression_integer(): assert objs == [HyExpression([HySymbol("foo"), HyInteger(2)])] +def test_lex_lambda_list_keyword(): + """ Make sure expressions can produce lambda list keywords """ + objs = tokenize("(x &rest xs)") + assert objs == [HyExpression([HySymbol("x"), + HyLambdaListKeyword("&rest"), + HySymbol("xs")])] + + def test_lex_line_counting(): """ Make sure we can count lines / columns """ entry = tokenize("(foo (one two))")[0]