diff options
-rw-r--r-- | Include/opcode.h | 1 | ||||
-rw-r--r-- | Include/symtable.h | 1 | ||||
-rw-r--r-- | Lib/test/test_line_tracing.py (renamed from Lib/test/test_trace.py) | 0 | ||||
-rw-r--r-- | Lib/test/test_scope.py | 8 | ||||
-rw-r--r-- | Objects/typeobject.c | 1 | ||||
-rw-r--r-- | Python/ceval.c | 16 | ||||
-rw-r--r-- | Python/compile.c | 4 | ||||
-rw-r--r-- | Python/symtable.c | 11 |
8 files changed, 31 insertions, 11 deletions
diff --git a/Include/opcode.h b/Include/opcode.h index 7ffa359..facadc2 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -123,6 +123,7 @@ extern "C" { #define LOAD_CLOSURE 135 /* Load free variable from closure */ #define LOAD_DEREF 136 /* Load and dereference from closure cell */ #define STORE_DEREF 137 /* Store into cell */ +#define LOAD_NAME_LOCAL_ONLY 138 /* The next 3 opcodes must be contiguous and satisfy (CALL_FUNCTION_VAR - CALL_FUNCTION) & 3 == 1 */ diff --git a/Include/symtable.h b/Include/symtable.h index d5ef96f..22075f0 100644 --- a/Include/symtable.h +++ b/Include/symtable.h @@ -88,6 +88,7 @@ PyAPI_FUNC(void) PySymtable_Free(struct symtable *); #define GLOBAL_IMPLICIT 3 #define FREE 4 #define CELL 5 +#define LOCAL_ONLY 6 /* The following two names are used for the ste_unoptimized bit field */ #define OPT_IMPORT_STAR 1 diff --git a/Lib/test/test_trace.py b/Lib/test/test_line_tracing.py index 43134e9..43134e9 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_line_tracing.py diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py index 643dcbc..1961e6e 100644 --- a/Lib/test/test_scope.py +++ b/Lib/test/test_scope.py @@ -690,6 +690,14 @@ result2 = h() h = g() self.assertEqual(h(), 3) + def testLocalClosureShadowing(self): + exec(""" +x = 4 +def f(x): + class C: + x = x +raises(NameError, f, 3)""", {"raises" : self.assertRaises}) + def test_main(): run_unittest(ScopeTests) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 268a924..505ca68 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6094,6 +6094,7 @@ supercheck(PyTypeObject *type, PyObject *obj) PyErr_SetString(PyExc_TypeError, "super(type, obj): " "obj must be an instance or subtype of type"); + printf("%s\n", type->tp_name); return NULL; } diff --git a/Python/ceval.c b/Python/ceval.c index 2d4b16a..368ad69 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2052,6 +2052,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; TARGET(LOAD_NAME) + TARGET(LOAD_NAME_LOCAL_ONLY) w = GETITEM(names, oparg); if ((v = f->f_locals) == NULL) { PyErr_Format(PyExc_SystemError, @@ -2073,15 +2074,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } } if (x == NULL) { - x = PyDict_GetItem(f->f_globals, w); + if (opcode != LOAD_NAME_LOCAL_ONLY) { + x = PyDict_GetItem(f->f_globals, w); + if (x == NULL) + x = PyDict_GetItem(f->f_builtins, w); + } if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); - if (x == NULL) { - format_exc_check_arg( - PyExc_NameError, - NAME_ERROR_MSG, w); - break; - } + format_exc_check_arg(PyExc_NameError, NAME_ERROR_MSG, w); + break; } Py_INCREF(x); } diff --git a/Python/compile.c b/Python/compile.c index aae0339..83c9e02 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -787,6 +787,7 @@ opcode_stack_effect(int opcode, int oparg) case LOAD_CONST: return 1; case LOAD_NAME: + case LOAD_NAME_LOCAL_ONLY: return 1; case BUILD_TUPLE: case BUILD_LIST: @@ -2481,6 +2482,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) optype = OP_DEREF; break; case LOCAL: + case LOCAL_ONLY: if (c->u->u_ste->ste_type == FunctionBlock) optype = OP_FAST; break; @@ -2556,7 +2558,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) break; case OP_NAME: switch (ctx) { - case Load: op = LOAD_NAME; break; + case Load: op = (scope == LOCAL_ONLY) ? LOAD_NAME_LOCAL_ONLY : LOAD_NAME; break; case Store: op = STORE_NAME; break; case Del: op = DELETE_NAME; break; case AugLoad: diff --git a/Python/symtable.c b/Python/symtable.c index 55c9f47..37bdf2a 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -432,7 +432,14 @@ analyze_name(PySTEntryObject *ste, PyObject *scopes, PyObject *name, long flags, return PySet_Add(free, name) >= 0; } if (flags & DEF_BOUND) { - SET_SCOPE(scopes, name, LOCAL); + if (ste->ste_type == ClassBlock && + !(flags & DEF_PARAM) && + bound && PySet_Contains(bound, name)) { + SET_SCOPE(scopes, name, LOCAL_ONLY); + } + else { + SET_SCOPE(scopes, name, LOCAL); + } if (PySet_Add(local, name) < 0) return 0; if (PySet_Discard(global, name) < 0) @@ -489,7 +496,7 @@ analyze_cells(PyObject *scopes, PyObject *free, const char *restricted) long scope; assert(PyLong_Check(v)); scope = PyLong_AS_LONG(v); - if (scope != LOCAL) + if (scope != LOCAL && scope != LOCAL_ONLY) continue; if (!PySet_Contains(free, name)) continue; |