From 13bbefdd4ee631ba4943d93931e1c0a73d553408 Mon Sep 17 00:00:00 2001 From: snowapril Date: Tue, 17 Aug 2021 19:58:37 +0900 Subject: [PATCH 1/2] compiler: impl syntax error detect for global kind This commit fixes `test_global_parap_err_first` test in [test_syntax.py](https://github.com/RustPython/RustPython/blob/master/Lib/test/test_syntax.py#L678) and implement the other syntax errors detection as cpython 3.8 provided for global symbol. Below syntax error conditions are added. * name {} is parameter and global ```python >>>>> def test(a): ..... global a ..... SyntaxError: name 'a' is parameter and global at line 2 column 2 global a ``` * annotated name {} can't be global ```python >>>>> def test(): ..... a: int ..... global a ..... SyntaxError: annotated name 'a' can't be global at line 3 column 2 global a ``` * name {} is assigned to before global description ```python >>>>> a = 100 >>>>> def test(): ..... a = 10 ..... global a ..... SyntaxError: name 'a' is assigned to before global declaration at line 3 column 2 global a ``` * name {} is used prior to global declaration ```python >>>>> a = 10 >>>>> def test(): ..... print(a) ..... global a ..... SyntaxError: name 'a' is used prior to global declaration at line 3 column 2 global a ``` Signed-off-by: snowapril --- Lib/test/test_syntax.py | 2 -- compiler/src/symboltable.rs | 23 ++++++++++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index a87ef0f72..7067a6e4d 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -673,8 +673,6 @@ class SyntaxTestCase(unittest.TestCase): def test_assign_del(self): self._check_error("del f()", "delete") - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_global_param_err_first(self): source = """if 1: def error(a): diff --git a/compiler/src/symboltable.rs b/compiler/src/symboltable.rs index 10c13ba55..8dc120e26 100644 --- a/compiler/src/symboltable.rs +++ b/compiler/src/symboltable.rs @@ -1120,12 +1120,33 @@ impl SymbolTableBuilder { // Role already set.. match role { SymbolUsage::Global => { - if !symbol.is_global() { + if symbol.is_parameter { + return Err(SymbolTableError { + error: format!("name '{}' is parameter and global", name), + location, + }); + } + if symbol.is_referenced { return Err(SymbolTableError { error: format!("name '{}' is used prior to global declaration", name), location, }); } + if symbol.is_annotated { + return Err(SymbolTableError { + error: format!("annotated name '{}' can't be global", name), + location, + }); + } + if symbol.is_assigned { + return Err(SymbolTableError { + error: format!( + "name '{}' is assigned to before global declaration", + name + ), + location, + }); + } } SymbolUsage::Nonlocal => { if symbol.is_parameter { From 38237c30d3f1e0c3405a939c8bc9ce537ad5871f Mon Sep 17 00:00:00 2001 From: snowapril Date: Wed, 18 Aug 2021 00:35:14 +0900 Subject: [PATCH 2/2] compiler: add is_global() check at top of errors add `!symbol.is_global()` condition check before entrying global symbol errors This change will decrease hot path cost. Signed-off-by: snowapril --- compiler/src/symboltable.rs | 57 ++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/compiler/src/symboltable.rs b/compiler/src/symboltable.rs index 8dc120e26..1bdd1a2d3 100644 --- a/compiler/src/symboltable.rs +++ b/compiler/src/symboltable.rs @@ -1120,32 +1120,37 @@ impl SymbolTableBuilder { // Role already set.. match role { SymbolUsage::Global => { - if symbol.is_parameter { - return Err(SymbolTableError { - error: format!("name '{}' is parameter and global", name), - location, - }); - } - if symbol.is_referenced { - return Err(SymbolTableError { - error: format!("name '{}' is used prior to global declaration", name), - location, - }); - } - if symbol.is_annotated { - return Err(SymbolTableError { - error: format!("annotated name '{}' can't be global", name), - location, - }); - } - if symbol.is_assigned { - return Err(SymbolTableError { - error: format!( - "name '{}' is assigned to before global declaration", - name - ), - location, - }); + if !symbol.is_global() { + if symbol.is_parameter { + return Err(SymbolTableError { + error: format!("name '{}' is parameter and global", name), + location, + }); + } + if symbol.is_referenced { + return Err(SymbolTableError { + error: format!( + "name '{}' is used prior to global declaration", + name + ), + location, + }); + } + if symbol.is_annotated { + return Err(SymbolTableError { + error: format!("annotated name '{}' can't be global", name), + location, + }); + } + if symbol.is_assigned { + return Err(SymbolTableError { + error: format!( + "name '{}' is assigned to before global declaration", + name + ), + location, + }); + } } } SymbolUsage::Nonlocal => {