2011/1/25 Stefan Behnel <stefan...@behnel.de>: > Vitja Makarov, 25.01.2011 08:15: >> I want to write simple code to find unbound variables. > > There is some code that does (part of) that already, in a transform IIRC. > It's used to detect if we need to initialise a local variable to None or > can safely set it to NULL. >
Is it disabled by default? def foo(): a = "xxx" print a is transformed into: static PyObject *__pyx_pf_1f_0foo(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) { PyObject *__pyx_v_a; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclareContext; __Pyx_RefNannySetupContext("foo"); __pyx_self = __pyx_self; __pyx_v_a = Py_None; __Pyx_INCREF(Py_None); __Pyx_INCREF(((PyObject *)__pyx_n_s__xxx)); __Pyx_DECREF(__pyx_v_a); __pyx_v_a = ((PyObject *)__pyx_n_s__xxx); ... } > >> As it's hard to detect them in common case it will mark them as: >> - bound (defenitley bound) >> def foo(): >> a = 1 >> print a >> >> Bound variables should be initialized to NULL >> >> - unbound (defenitley unbound) >> def foo(): >> print a >> a = 1 >> >> Unbound variables should be initialized to Py_None. >> And user may be warned (should depend on command line flags) >> >> - don't know (not sure here) >> def foo(x): >> if x: >> a = 1 >> [else: # optional >> a = 2] >> print a >> >> Algo is too stupid it don't know much about branches, so it's not sure here. > > Well, it *can't* know what will happen at runtime. That's not being stupid > at all, it's just the correct way to do it. > > Ok. But I guess that we can detect more cases in compile time. >> This ones will be initialized to Py_None. > > To be correct, they'd have to get initialised to NULL and a check needs to > get generated on read access as long as we don't know for sure if it has > been initialised or not. CPython raises an exception on unbound locals, so > Cython should do the same and should do it efficiently. When we get to the > point that we safely know which variables are being initialised and for > which only the runtime behaviour can tell us if they are or not, I think > it's fine to add the little performance penalty of checking for NULL in > exactly the unsafe cases. > Ok. At the point we aren't sure variable is intialized we can insert small check for NULL. Also this can help for local variable deletion support. > >> Also I would like to check for unused variables and unreachable code >> (this should be removed). > > Some unreachable code is getting dropped during constant folding, usually > stuff like "if False: ...", but I agree that there's always more that can > be done. Think of this: > > def x(): > do_some_stuff() > > return # disable rest of code, e.g. during debugging > > unreachable_code() > > Cython shouldn't bother generating dead code here (even if the C compiler > would drop it anyway). > That should be rather easy to do: remove all the nodes in StatList after: break, continue, return, raise, something else? > Knowing where a function returns and if it has trailing code with a default > None return would also be good to know. It would be a step towards > inferring the return type of functions automatically. > -- vitja. _______________________________________________ Cython-dev mailing list Cython-dev@codespeak.net http://codespeak.net/mailman/listinfo/cython-dev