diff --git a/toy-impl/parse_expr.py b/toy-impl/parse_expr.py index e699ca1..98e34d8 100644 --- a/toy-impl/parse_expr.py +++ b/toy-impl/parse_expr.py @@ -208,6 +208,8 @@ def parse_if_expr(ctx: Context, def parse_binding(name, ty): if isinstance(name, ast.Name): + if name.id == '_': + return {} return {name.id: ty} elif isinstance(name, ast.Tuple): if not isinstance(ty, TupleType): @@ -216,7 +218,11 @@ def parse_binding(name, ty): raise CustomError(f'pattern matching length mismatch') result = {} for x, y in zip(name.elts, ty.params): + binding = parse_binding(x, y) + expected = len(result) + len(binding) result |= parse_binding(x, y) + if len(result) != expected: + raise CustomError('variable name clash') return result else: raise CustomError(f'binding to {name} is not supported') diff --git a/toy-impl/test_expr.py b/toy-impl/test_expr.py index 102f928..d2c5c4a 100644 --- a/toy-impl/test_expr.py +++ b/toy-impl/test_expr.py @@ -83,6 +83,8 @@ test_expr('[x for x in [1, 2, 3]]', {}) test_expr('[1 for x in [1, 2, 3] if x > 2]', {}) test_expr('[a + a for x in [1, 2, 3] if x > 2]', {'a': I}) test_expr('[a for a, b in [(1, 2), (2, 3), (3, 4)] if b > 2]', {}) +test_expr('[a for a, a in [(1, 2), (2, 3), (3, 4)] if b > 2]', {}) +test_expr('[1 for _, _ in [(1, 2), (2, 3), (3, 4)]]', {}) test_expr('[b for a, b in [(1, (2, 3)), (2, (3, 4)), (3, (4, 5))] if b > 2]', {}) test_expr('[b for a, b in [(1, (2, 3)), (2, (3, 4)), (3, (4, 5))]]', {}) test_expr('[b for a, (b, c) in [(1, (2, 3)), (2, (3, 4)), (3, (4, 5))] if b > 2]', {})