# HG changeset patch # User Paul Boddie # Date 1693600159 -7200 # Node ID 51ec9d93d6489cedf8106a7c5956a34a2c5bad1f # Parent ab30a18f95865c91ce16129df750b371db4b3c5e# Parent 2957d8a7ccfb343e7eb4fcd9f24682d428e3afc3 Merged changes from the well-defined-instances branch. diff -r ab30a18f9586 -r 51ec9d93d648 common.py --- a/common.py Fri Sep 01 22:22:37 2023 +0200 +++ b/common.py Fri Sep 01 22:29:19 2023 +0200 @@ -3,7 +3,7 @@ """ Common functions. -Copyright (C) 2007-2019, 2021 Paul Boddie +Copyright (C) 2007-2019, 2021, 2023 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -623,7 +623,7 @@ # raise LoopExit [(compiler.ast.Name("StopIteration"), None, - compiler.ast.Raise(compiler.ast.Name("LoopExit")))], + compiler.ast.Raise(compiler.ast.Name("$loop_exit")))], None), # ... = diff -r ab30a18f9586 -r 51ec9d93d648 inspector.py --- a/inspector.py Fri Sep 01 22:22:37 2023 +0200 +++ b/inspector.py Fri Sep 01 22:29:19 2023 +0200 @@ -907,6 +907,20 @@ self.set_special(n.name, value) return value + # Special case for loops. + + elif n.name == "$loop_exit": + + # Attempt to get a reference. + + ref = self.get_builtin("__loop_exit") + + # Record the imported name and provide the resolved name reference. + + value = ResolvedNameRef(n.name, ref) + self.set_special(n.name, value) + return value + # Test for self usage, which is only allowed in methods. if n.name == "self" and not (self.in_function and self.in_class): diff -r ab30a18f9586 -r 51ec9d93d648 lib/__builtins__/__init__.py --- a/lib/__builtins__/__init__.py Fri Sep 01 22:22:37 2023 +0200 +++ b/lib/__builtins__/__init__.py Fri Sep 01 22:29:19 2023 +0200 @@ -3,7 +3,7 @@ """ Simple built-in classes and functions. -Copyright (C) 2015, 2016, 2017, 2019, 2021 Paul Boddie +Copyright (C) 2015-2017, 2019, 2021, 2023 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -50,7 +50,8 @@ UnicodeEncodeError, UnicodeError, UnicodeTranslateError, - ValueError + ValueError, + __loop_exit ) # Classes. diff -r ab30a18f9586 -r 51ec9d93d648 lib/__builtins__/exception/__init__.py --- a/lib/__builtins__/exception/__init__.py Fri Sep 01 22:22:37 2023 +0200 +++ b/lib/__builtins__/exception/__init__.py Fri Sep 01 22:29:19 2023 +0200 @@ -3,7 +3,7 @@ """ Exception objects. -Copyright (C) 2015, 2016, 2017, 2019 Paul Boddie +Copyright (C) 2015, 2016, 2017, 2019, 2023 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -30,7 +30,8 @@ NotImplementedError, RuntimeError, StopIteration, - ValueError + ValueError, + __loop_exit ) from __builtins__.exception.io import ( diff -r ab30a18f9586 -r 51ec9d93d648 lib/__builtins__/exception/base.py --- a/lib/__builtins__/exception/base.py Fri Sep 01 22:22:37 2023 +0200 +++ b/lib/__builtins__/exception/base.py Fri Sep 01 22:29:19 2023 +0200 @@ -3,7 +3,7 @@ """ Base exception objects. See __builtins__.core for the core exceptions. -Copyright (C) 2015, 2016, 2018, 2019 Paul Boddie +Copyright (C) 2015, 2016, 2018, 2019, 2023 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -87,4 +87,8 @@ pass +# Common loop exit instance. + +__loop_exit = LoopExit() + # vim: tabstop=4 expandtab shiftwidth=4 diff -r ab30a18f9586 -r 51ec9d93d648 referencing.py --- a/referencing.py Fri Sep 01 22:22:37 2023 +0200 +++ b/referencing.py Fri Sep 01 22:29:19 2023 +0200 @@ -3,7 +3,7 @@ """ Reference abstractions. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2023 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -222,6 +222,12 @@ name = self.get_name() return name and name.rsplit(".")[-1].startswith("$c") + def is_well_defined_instance(self): + + "Return whether this reference involves a well-defined instance." + + return self.get_kind() == "" + def is_predefined_value(self): "Return whether this reference identifies a predefined value." diff -r ab30a18f9586 -r 51ec9d93d648 resolving.py --- a/resolving.py Fri Sep 01 22:22:37 2023 +0200 +++ b/resolving.py Fri Sep 01 22:29:19 2023 +0200 @@ -3,7 +3,7 @@ """ Name resolution. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2023 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -73,7 +73,11 @@ for name, value in self.special.items(): ref, paths = value - self.special[name] = self.importer.identify(ref.get_origin()), paths + + # Handle special instances. + + origin = ref.is_well_defined_instance() and ref.get_name() or ref.get_origin() + self.special[name] = self.importer.identify(origin), paths def check_names_used(self): diff -r ab30a18f9586 -r 51ec9d93d648 results.py --- a/results.py Fri Sep 01 22:22:37 2023 +0200 +++ b/results.py Fri Sep 01 22:29:19 2023 +0200 @@ -3,7 +3,7 @@ """ Result abstractions. -Copyright (C) 2016, 2017 Paul Boddie +Copyright (C) 2016, 2017, 2023 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -164,6 +164,9 @@ def is_constant_alias(self): return self.ref and self.ref.is_constant_alias() + def is_well_defined_instance(self): + return self.ref and self.ref.is_well_defined_instance() + class ResolvedNameRef(ResolvedRef, NameRef): "A resolved name-based reference." diff -r ab30a18f9586 -r 51ec9d93d648 translator.py --- a/translator.py Fri Sep 01 22:22:37 2023 +0200 +++ b/translator.py Fri Sep 01 22:29:19 2023 +0200 @@ -1619,7 +1619,8 @@ # function names to references. elif n.name.startswith("$L") or n.name.startswith("$op") or \ - n.name.startswith("$seq") or n.name.startswith("$print"): + n.name.startswith("$seq") or n.name.startswith("$print") or \ + n.name == "$loop_exit": ref, paths = self.importer.get_module(self.name).special[n.name] return TrResolvedNameRef(n.name, ref) @@ -1736,7 +1737,7 @@ else: exc = self.process_structure_node(n.expr1) - if isinstance(exc, TrInstanceRef): + if isinstance(exc, TrInstanceRef) or exc.is_well_defined_instance(): self.writestmt("__Raise(%s);" % exc) else: self.writestmt("__Raise(__ensure_instance(%s));" % exc)