Lichen

Changeset

868:d2c64260113c
2019-01-24 Paul Boddie raw files shortlog changelog graph Fixed loop termination by using a dedicated exception instead of StopIteration.
common.py (file) lib/__builtins__/__init__.py (file) lib/__builtins__/exception/__init__.py (file) lib/__builtins__/exception/base.py (file) tests/for.py (file)
     1.1 --- a/common.py	Thu Jan 24 18:28:15 2019 +0100
     1.2 +++ b/common.py	Thu Jan 24 19:12:29 2019 +0100
     1.3 @@ -579,10 +579,14 @@
     1.4              # <t2> = <t1>.next
     1.5              # try:
     1.6              #     while True:
     1.7 -            #         <var>... = <t2>()
     1.8 -            #         ...
     1.9 -            # except StopIteration:
    1.10 +            #         try:
    1.11 +            #             <var>... = <t2>()
    1.12 +            #         except StopIteration:
    1.13 +            #             raise LoopExit
    1.14 +            #         {n.body}
    1.15 +            # except LoopExit:
    1.16              #     {n.else_}
    1.17 +            #     pass
    1.18  
    1.19              compiler.ast.Assign(
    1.20                  [compiler.ast.AssName(t2, "OP_ASSIGN")],
    1.21 @@ -592,15 +596,18 @@
    1.22                  compiler.ast.While(
    1.23                      compiler.ast.Name("True"),
    1.24                      compiler.ast.Stmt([
    1.25 -                        compiler.ast.Assign(
    1.26 -                            [n.assign],
    1.27 -                            compiler.ast.CallFunc(
    1.28 -                                compiler.ast.Name(t2),
    1.29 -                                []
    1.30 -                                )),
    1.31 +                        compiler.ast.TryExcept(
    1.32 +                            compiler.ast.Assign(
    1.33 +                                [n.assign],
    1.34 +                                compiler.ast.CallFunc(
    1.35 +                                    compiler.ast.Name(t2),
    1.36 +                                    [])),
    1.37 +                            [(compiler.ast.Name("StopIteration"), None,
    1.38 +                              compiler.ast.Raise(compiler.ast.Name("LoopExit")))],
    1.39 +                            None),
    1.40                          n.body]),
    1.41                      None),
    1.42 -                [(compiler.ast.Name("StopIteration"), None, n.else_ or compiler.ast.Pass())],
    1.43 +                [(compiler.ast.Name("LoopExit"), None, n.else_ or compiler.ast.Pass())],
    1.44                  None)
    1.45              ])
    1.46  
     2.1 --- a/lib/__builtins__/__init__.py	Thu Jan 24 18:28:15 2019 +0100
     2.2 +++ b/lib/__builtins__/__init__.py	Thu Jan 24 19:12:29 2019 +0100
     2.3 @@ -3,7 +3,7 @@
     2.4  """
     2.5  Simple built-in classes and functions.
     2.6  
     2.7 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
     2.8 +Copyright (C) 2015, 2016, 2017, 2019 Paul Boddie <paul@boddie.org.uk>
     2.9  
    2.10  This program is free software; you can redistribute it and/or modify it under
    2.11  the terms of the GNU General Public License as published by the Free Software
    2.12 @@ -35,6 +35,7 @@
    2.13      IndentationError,
    2.14      IndexError,
    2.15      IOError,
    2.16 +    LoopExit,
    2.17      KeyError,
    2.18      KeyboardInterrupt,
    2.19      NotImplementedError,
     3.1 --- a/lib/__builtins__/exception/__init__.py	Thu Jan 24 18:28:15 2019 +0100
     3.2 +++ b/lib/__builtins__/exception/__init__.py	Thu Jan 24 19:12:29 2019 +0100
     3.3 @@ -3,7 +3,7 @@
     3.4  """
     3.5  Exception objects.
     3.6  
     3.7 -Copyright (C) 2015, 2016, 2017 Paul Boddie <paul@boddie.org.uk>
     3.8 +Copyright (C) 2015, 2016, 2017, 2019 Paul Boddie <paul@boddie.org.uk>
     3.9  
    3.10  This program is free software; you can redistribute it and/or modify it under
    3.11  the terms of the GNU General Public License as published by the Free Software
    3.12 @@ -25,6 +25,7 @@
    3.13  
    3.14  from __builtins__.exception.base import (
    3.15      IndexError,
    3.16 +    LoopExit,
    3.17      KeyError,
    3.18      NotImplementedError,
    3.19      RuntimeError,
     4.1 --- a/lib/__builtins__/exception/base.py	Thu Jan 24 18:28:15 2019 +0100
     4.2 +++ b/lib/__builtins__/exception/base.py	Thu Jan 24 19:12:29 2019 +0100
     4.3 @@ -3,7 +3,7 @@
     4.4  """
     4.5  Base exception objects. See __builtins__.core for the core exceptions.
     4.6  
     4.7 -Copyright (C) 2015, 2016, 2018 Paul Boddie <paul@boddie.org.uk>
     4.8 +Copyright (C) 2015, 2016, 2018, 2019 Paul Boddie <paul@boddie.org.uk>
     4.9  
    4.10  This program is free software; you can redistribute it and/or modify it under
    4.11  the terms of the GNU General Public License as published by the Free Software
    4.12 @@ -61,6 +61,12 @@
    4.13  
    4.14          pass
    4.15  
    4.16 +class LoopExit(Exception):
    4.17 +
    4.18 +    "An exception signalling the end of iteration in a loop."
    4.19 +
    4.20 +    pass
    4.21 +
    4.22  class StopIteration(Exception):
    4.23  
    4.24      "An exception signalling the end of iteration."
     5.1 --- a/tests/for.py	Thu Jan 24 18:28:15 2019 +0100
     5.2 +++ b/tests/for.py	Thu Jan 24 19:12:29 2019 +0100
     5.3 @@ -1,5 +1,7 @@
     5.4  l = [1, 2, 3]
     5.5  
     5.6 +# Test else clause.
     5.7 +
     5.8  for i in l:
     5.9      print i             # 1
    5.10                          # 2
    5.11 @@ -7,6 +9,8 @@
    5.12  else:
    5.13      print 4             # 4
    5.14  
    5.15 +# Test break versus else clause.
    5.16 +
    5.17  for i in l:
    5.18      print i             # 1
    5.19                          # 2
    5.20 @@ -14,3 +18,17 @@
    5.21          break
    5.22  else:
    5.23      print 3
    5.24 +
    5.25 +# Test StopIteration in loop.
    5.26 +
    5.27 +try:
    5.28 +    for i in l:
    5.29 +        print i         # 1
    5.30 +                        # 2
    5.31 +        if i == 2:
    5.32 +            raise StopIteration
    5.33 +    else:
    5.34 +        print 3
    5.35 +
    5.36 +except StopIteration:
    5.37 +    print "stopped"     # stopped