Can't decompile chained conditional
This won't decompile:
lambda: 1 if x else 2 if y else 3
Thanks for testing this.
I'm glad to know it is being used. (I'll put some more effort into the test suite) You will have to wait until after the weekend though.
Thanks for fast response, but your fix doesn't work for me. I pulled your development branch and tests work, but when I do:
In [1]: from meta.decompiler import decompile_func
In [2]: decompile_func(lambda: 1 if x else 2)
Out[2]: <_ast.Lambda at 0x23bdbd0>
In [3]: decompile_func(lambda: 1 if x else 2 if y else 3)
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-3-e268d849301c> in <module>()
----> 1 decompile_func(lambda: 1 if x else 2 if y else 3)
/home/suor/projects/xxauto.ru/Meta/meta/decompiler/__init__.pyc in decompile_func(func)
35 # default_names = []
36 # defaults = [_ast.Name(id='%s_default' % name, ctx=_ast.Load() , lineno=0, col_offset=0) for name in default_names]
---> 37 ast_node = make_function(code, defaults=[], lineno=code.co_firstlineno)
38
39 return ast_node
/home/suor/projects/xxauto.ru/Meta/meta/decompiler/instructions.pyc in make_function(code, defaults, lineno)
100 stmnts = [_ast.Return(_ast.IfExp(stmnts[0].test, stmnts[0].body[0].value, stmnts[1].value))]
101
--> 102 assert len(stmnts) == 1, stmnts
103 assert isinstance(stmnts[0], _ast.Return)
104
AssertionError: [<_ast.If object at 0x23c40d0>, <_ast.If object at 0x23c4210>, <_ast.Return object at 0x23c41d0>]
Also It looks like it works for not lambda functions, but resulting ast contain If and Return nodes not IfExp and single Return:
In [11]: def hi(x,y): return 1 if x else 2 if y else 3
In [12]: print_ast(decompile_func(hi))
FunctionDef(args=arguments(args=[Name(ctx=Param(),
id='x'),
Name(ctx=Param(),
id='y')],
defaults=[],
kwarg=None,
vararg=None),
body=[If(body=[Return(value=Num(n=1))],
orelse=[],
test=Name(ctx=Load(),
id='x')),
If(body=[Return(value=Num(n=2))],
orelse=[],
test=Name(ctx=Load(),
id='y')),
Return(value=Num(n=3))],
decorator_list=[],
name='hi')
That's what I expect to get:
In [19]: print_ast(ast.parse(inspect.getsource(hi)))
Module(body=[FunctionDef(args=arguments(args=[Name(ctx=Param(),
id='x'),
Name(ctx=Param(),
id='y')],
defaults=[],
kwarg=None,
vararg=None),
body=[Return(value=IfExp(body=Num(n=1),
orelse=IfExp(body=Num(n=2),
orelse=Num(n=3),
test=Name(ctx=Load(),
id='y')),
test=Name(ctx=Load(),
id='x')))],
decorator_list=[],
name='hi')])
Sure it's kind of equivalent but surely won't work with lambdas
Right. Thanks
FYI: If you look at the byte-code generated either of these two AST's they are identical.
dis.dis(compile(_ast.Module([decompile_func(hi)]),'<>','exec').co_consts[0])
dis.dis(hi)
Thanks. And it was fast ;)