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

Reply via email to