Very nice. One case I would like to see covered is that of a global that is deleted. Something like:
import eggs
i = -2 max = 3 j = 4
def foo(n): y = abs(i) + max return eggs.ham(y + n)
del j
I presume there would still be an entry in spam's module dict with a NULL objptr.
Yes.
The whole think makes sense to me if it avoids the possible two PyDict_GetItem calls in the LOAD_GLOBAL opcode. As I understand it, if accessed inside a function, LOAD_GLOBAL could be implemented something like this:
case LOAD_GLOBAL:
Surely you meant LOAD_GLOBAL_CELL.
cell = func_cells[oparg]; if (cell.objptr) x = cell->objptr; else x = cell->cellptr->objptr; if (x == NULL) { ... error recovery ... break; } Py_INCREF(x); continue;
This looks a lot better to me (no complex function calls).
Here's my version: case LOAD_GLOBAL_CELL: cell = func_cells[oparg]; x = cell->objptr; if (x == NULL) { x = cell->cellptr->objptr; if (x == NULL) { ... error recovery ... break; } } Py_INCREF(x); continue;
What happens in the module's top-level code where there is presumably no func_cells array? Do we simply have two different opcodes, one for use at the global level and one for use in functions?
It could use LOAD_GLOBAL which should use PyMapping_GetItem on the globals dict. Or maybe even LOAD_NAME which should do the same. But we could also somehow create a func_cells array (hm, it would have to be called differently then I suppose). (I've added these to the FAQs in PEP 280 too.) --Guido van Rossum (home page: http://www.python.org/~guido/)