From 41a50b5e46c98f0c245295de8f466a55864a4a07 Mon Sep 17 00:00:00 2001 From: rocky Date: Wed, 25 Apr 2018 12:57:09 -0400 Subject: [PATCH] Handle if not else in lambdas... Fixes #170 --- test/bytecode_2.6/02_ifelse_lambda.pyc | Bin 846 -> 0 bytes test/bytecode_2.6_run/02_ifelse_lambda.pyc | Bin 0 -> 1257 bytes test/bytecode_2.7/02_ifelse_lambda.pyc | Bin 843 -> 0 bytes test/bytecode_2.7_run/02_ifelse_lambda.pyc | Bin 0 -> 1237 bytes test/bytecode_3.5_run/02_ifelse_lambda.pyc | Bin 0 -> 953 bytes test/bytecode_3.6/02_ifelse_lambda.pyc | Bin 603 -> 0 bytes test/bytecode_3.6_run/02_ifelse_lambda.pyc | Bin 0 -> 861 bytes test/bytecode_3.7/04_withas.pyc | Bin 0 -> 476 bytes test/bytecode_3.7/05_36lambda.pyc | Bin 0 -> 1159 bytes test/bytecode_3.7/05_call_function_kw2.pyc | Bin 0 -> 275 bytes .../branching/02_ifelse_lambda.py | 17 ++- uncompyle6/parsers/parse25.py | 4 + uncompyle6/parsers/parse26.py | 6 +- uncompyle6/parsers/parse27.py | 4 + uncompyle6/parsers/parse3.py | 23 +++- uncompyle6/parsers/parse36.py | 7 -- uncompyle6/semantics/consts.py | 105 +++++++++--------- 17 files changed, 99 insertions(+), 67 deletions(-) delete mode 100644 test/bytecode_2.6/02_ifelse_lambda.pyc create mode 100644 test/bytecode_2.6_run/02_ifelse_lambda.pyc delete mode 100644 test/bytecode_2.7/02_ifelse_lambda.pyc create mode 100644 test/bytecode_2.7_run/02_ifelse_lambda.pyc create mode 100644 test/bytecode_3.5_run/02_ifelse_lambda.pyc delete mode 100644 test/bytecode_3.6/02_ifelse_lambda.pyc create mode 100644 test/bytecode_3.6_run/02_ifelse_lambda.pyc create mode 100644 test/bytecode_3.7/04_withas.pyc create mode 100644 test/bytecode_3.7/05_36lambda.pyc create mode 100644 test/bytecode_3.7/05_call_function_kw2.pyc diff --git a/test/bytecode_2.6/02_ifelse_lambda.pyc b/test/bytecode_2.6/02_ifelse_lambda.pyc deleted file mode 100644 index 88a52e4246def3600a34c19d2d9a03f406349a31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 846 zcmb_aO-sW-5S`t$_CrNM5WIN|Dzfa7x-qj zSnyVL;l0dDHZyN$_TzKAeR9<8Wwcxx&r6`X1{tDvq8^b&tmsXVGFo0Kvd{z_iPmIw z&^6YkPPxX%4NBq$5@ia+;Ph8OwGVog3S*+8j=hQ!&Yr{(J~`g#_z%Z21}J7ZXL<^n zUslIVZZh+>UlofovzZ diff --git a/test/bytecode_2.6_run/02_ifelse_lambda.pyc b/test/bytecode_2.6_run/02_ifelse_lambda.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b53e7ea994baa8c2d2e467e99db31bc2710b2314 GIT binary patch literal 1257 zcmb`G&2G~`5Xb-Pk9@S0_JDxqP;s<`L=oqzqCy}}9AYG-Tq4)IX&pInWIGa6JyG6= zXW$GEQgd#8;w9>Rqh?`F2K#BC3=0FwwVg6(794y2fi zJH`G)hZ^m5qIOG5_2Kx7Z%@ET@Al2xNRtO_NzRTyM0)gw(mbZRBqJ~fsu+gtNe%mv zCLu$GEG%S4A#OrJA})IeeD=P)Y@UlM7OT=tn`&L>?(nqEmic+HJUe{(YFf-(*|=$$ zElzFrV)dmRaQ%^Yk0aSj@kO*;F0MRMM@jc+wAYLfMuH|CJSCHCAM3T-z^Qdt!m%XV zp(xoscw**wm+|ZW2at5Z0|}mp%taftPlI#hG^22CPz`jLw9>%%PU+Ax)fXN{8zw5> z!2MIB9x;b&msC3s4Rp&6M`e`uZrlyKJ^n1e{({RYY+)F}V} literal 0 HcmV?d00001 diff --git a/test/bytecode_2.7/02_ifelse_lambda.pyc b/test/bytecode_2.7/02_ifelse_lambda.pyc deleted file mode 100644 index a1288bfbc30214684c00fa2ef1b6a07916bd6f55..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 843 zcmb_aO-sW-5S`tm*2Ygz!K25ZVvA=HK@m?q7(wWzq{+5jx@}6f1r=}lkNpF_nUvOR zi-Gqtlikd`eY3&OUUYfh>SVNdG~RcBe*on~-$WfEgILj*B9&|Tq{tvA@_kceJeM;34QF%zHo1j(_hgfJ^-e>s-8-QYfVoqmFZ&l78 z{RNX9Po3%dVqRvZ*(=jYHnfvLvvu9IedE08x^&#j)2r$GY#aM;s`Qpyd4OyUw6uU* zh{k;cGpLLB@Chr7Sxx(oFww+yUdp*y$&zSYZO>e67Z6RG%i+U3ra1P0=s8&GVRa0) zKK+PI!n260H_S$+S}8k4lXA#gwhYZRFDtYKTvM2ho#pt~h%wN|(1~ kM$)q{JP;nP`bo5I)9T`ki+t`(b#Zu74HeZJs;+_H7upq-WdHyG diff --git a/test/bytecode_2.7_run/02_ifelse_lambda.pyc b/test/bytecode_2.7_run/02_ifelse_lambda.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e71776f4c2fdc3f6459776cd10a0c3d47da52f7 GIT binary patch literal 1237 zcmb_b&2G~`5T3Q2-%{wIl>+JkZkCWJ;)a9}6)NJCLyS}@m&mm@t%(y?UPl7N33w3R zpfAu@LE;?{2X1`xIZkqI!Sak}XLe@3{bud|+U=XGpW{SUkB9Foi2DPTihL6pi&)r3 zz8cjtPuwG^jC?Wld-QwsKVSJ%pNXDWM3GxZPn&4Ks4v!Mw63{qqAiW4ZJBy94#WnM zcI1BA)i$=pHs71}t5}b*He=UKnLe9z#NusjCI4uW;cssx{%#U?Bnt1~^ofB|QBGb% z+&e!AWtx!rP$5J@U4ko-5A|A|?y;(Dewo{eE0$$qkIu?? zkz8bp^P{KFCfU^H&Q9`pewM~hE20XxAh;OBkY-h8FYH)z=Qbr%%M39)b|%f$l4(Q literal 0 HcmV?d00001 diff --git a/test/bytecode_3.5_run/02_ifelse_lambda.pyc b/test/bytecode_3.5_run/02_ifelse_lambda.pyc new file mode 100644 index 0000000000000000000000000000000000000000..36bd11c5fda265efd17d01e8d66631d41cdf881c GIT binary patch literal 953 zcma)4!Ac`R5UrXSlNgh%h_YGn;K9ovsO(upSqyv1WdcG#LY(R7m`O&u6;#B-u0OM| zu;1X#Z|Kv)o&x&?d$Ot~lN})kn{=mAUGKfB*ZEklSMk^H?z02%2MUXR!y#=`L4b%p z2u}cA07bC_-;vLu17-`Z5x$}1UCFzW-=F3qFULBd2uSd(;508-$O~Lh#3204{FoP% zrUg+M1`c#RP{dh*Ptl_2RYmV--pBNAN$zTL_mVT!bEySTBwH=u|K@ng*9uqpiJ?9mt6W|fWy@n{I3m)V+trVMjAWS5I6zet?e_Z?#9U9RIdWJi1C$ z&!jgxRJ&)oKMpVA@%irF=UzNeiBY|zKRS#0J6CtMvY*8Vj5oAFm-%37%}OEd*8nbTbn_(DNi?A>Xttzd@u>CYMQ4ujXe4cD zG?HZRNVCIr(D;yS@ZvF(>E4s7Gd7^Sb{bbPFJsx6*dys#Ksyez=w4cK&g-%%Rf aBr1DfwxEVhY?f=d=FoOma053y&bg5TmVZEJPE zVCBq)=oKj(n0GVm?3=gmZkx@6tBX$m0|CCE5`yY`%A!l4K;b*|L4y(-L{Ne6QR4=v z3wU_YI4NAXYKP?|Cw6a3|_+RRyU+SunEXgZA^VDky zA%H37CrV7QM?NEvp+W30ak%o5*~)aE_|x5n)!~yiCO?14tx<6+a5!=}b~vfr^1p)L WP43QewKRI`E1gh5T4mP+lO;DR^%c{MTvz(5VR;FLRhKX*is}nmUFvK4xfF|t|LL@ics(v zv{Xrv7szXDg+%37pkijuIEUndm1b_|yKlbv**A?w9dCaQ9~8hZC>@I79hti)r$OUa z7=i(f)oc72NXZ&Sck$>M%~aKLXQNk2pX7xP|h6)T4hw%CTbX(P)GZq zpO99a{x3wkz;+0W3Hv5F4N%E}dOwX5{iKo0!8hJDw*O>HPfg)$36@ zF_|-?Y&<*DtEs{2kJho)3L>Ju# zU8Kr(*_dU~MkVR)|4Q?^3hDATc@F7#Po$R+LI6|DcjK2tp+`hV~^L;GVe3l z)_nVKh3lOYlV$m{)7)lyMJQNa$iU-q_n)`i?289mf{QfOr_2XeDl~jV;5;Y|6pxyJ)V2K@R)l1SW1`u^TO$EXSu%0O!2n7fCyXIszumTWI>E= IY=?~f0ca4B=>Px# literal 0 HcmV?d00001 diff --git a/test/bytecode_3.7/04_withas.pyc b/test/bytecode_3.7/04_withas.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7551c4b17a384f5b42f7cbb4121926dd441adee GIT binary patch literal 476 zcmYjNJxc>Y5S`ikAcjOyQrT#GpvJ;dB%-zflR`O!aJk*Y!`xliy%+SUI~v;=r4k$Ii^Ynag^;3S?gg$Ke|T_%`Ivh(n8@8ss=|e1#A=;|@jSZWjVC zMtU-4YPSei1Y2Li(w}3AUATn~+*3c*WBU^Vrd=gQ16>hWobx0bN;AZ|pF@?TgsyGUVk#&A+C&ez#2AC fZd29{nBC2if4%l@c0lDk&G}>`F6=?fw-xUfSs7vr literal 0 HcmV?d00001 diff --git a/test/bytecode_3.7/05_36lambda.pyc b/test/bytecode_3.7/05_36lambda.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e595ddec7283664136804b077a5dbd21db7a8e67 GIT binary patch literal 1159 zcmaJ=&2G~`5Z)g{F%evNmn5d5E7~Fe3lrom342k74k)O-mDcwF2yaeua2NctQP2R||-qp*vD z8r|-~(3ny~7NjOi3Xy3PQp3mc1QZo8bwn|gdOE7ack+8j7o$lj6J5k#q!<^|B-!nkRhE`|0Khs7LaH#Gkj6cCQIb_- z9dhGoS>}e1^iW|S<=ayZw*Z@99TcCUflqjt!q;R7*K$S8Hdq9=)F8K=uZ|cm%B(Bw zqQ0VK6Bctar#Z8w2!I+M{f9x?0E1tcWpI_Np?Sy*&q{3qC5MHcN@cec=C9f?^KT6)RfK@BcG86x-#4+^&+gv1|~- z!Krf{MBN7b3y&UVIHTYj@G-UoeE_wmo}cd2-hwR28}i}7dv@VpwCYwv8n&RdzodQg zdGnp6cFuC{$X(Uq2EiEIw&)`O4f{wIv|$acpi!?g-vb)z8IC6=^+og`kg6H8gqqYF)#~=<2FasG5KwQiRBvP1D7*m*97^4_c7=jrzS^ScjfTAD( zqFI308HmA3YZ$T^QW$H1%6plBN}2saG?}89Q}fbqu_x!}m84dbXfobnkB=`dDT
BlA#D>(l71e%-n*U)cE53(xT*4{iM=#V>5jN)A;1XoSgWy(!Au7 z%>2Cg>~bT$g34RGCHe6{!$HPn=B0xiT?}>_V-XvWt;y)831NYaMj}{&vbQ*Fa`RJ4 Mb5iZV`hX$~0Dg-)_W%F@ literal 0 HcmV?d00001 diff --git a/test/simple_source/branching/02_ifelse_lambda.py b/test/simple_source/branching/02_ifelse_lambda.py index 5bc996fd..75dc2a0f 100644 --- a/test/simple_source/branching/02_ifelse_lambda.py +++ b/test/simple_source/branching/02_ifelse_lambda.py @@ -2,7 +2,8 @@ # lambda's have to be more or less on a line f = lambda x: 1 if x<2 else 3 -f(5) +assert f(3) == 3 +assert f(1) == 1 # If that wasn't enough ... # Python will create dead code @@ -10,10 +11,18 @@ f(5) # not to include the else expression g = lambda: 1 if True else 3 -g() +assert g() == 1 h = lambda: 1 if False else 3 -h() +assert h() == 3 # From 2.7 test_builtin -lambda c: 'a' <= c <= 'z', 'Hello World' +i = lambda c: 'a' <= c <= 'z', 'Hello World' +assert i[0]('a') == True +assert i[0]('A') == False + +# Issue #170. Bug is needing an "conditional_not_lambda" grammar rule +# in addition the the "conditional_lambda" rule +j = lambda a: False if not a else True +assert j(True) == True +assert j(False) == False diff --git a/uncompyle6/parsers/parse25.py b/uncompyle6/parsers/parse25.py index a60ce46b..7451c418 100644 --- a/uncompyle6/parsers/parse25.py +++ b/uncompyle6/parsers/parse25.py @@ -75,8 +75,12 @@ class Python25Parser(Python26Parser): setupwithas ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 setup_finally stmt ::= classdefdeco stmt ::= conditional_lambda + stmt ::= conditional_not_lambda conditional_lambda ::= expr jmp_false_then expr return_if_lambda return_stmt_lambda LAMBDA_MARKER + conditional_not_lambda + ::= expr jmp_true_then expr return_if_lambda + return_stmt_lambda LAMBDA_MARKER """) super(Python25Parser, self).customize_grammar_rules(tokens, customize) if self.version == 2.5: diff --git a/uncompyle6/parsers/parse26.py b/uncompyle6/parsers/parse26.py index 0b680d27..c935e3b7 100644 --- a/uncompyle6/parsers/parse26.py +++ b/uncompyle6/parsers/parse26.py @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Rocky Bernstein +# Copyright (c) 2017-2018 Rocky Bernstein """ spark grammar differences over Python2 for Python 2.6. """ @@ -289,8 +289,12 @@ class Python26Parser(Python2Parser): return_if_lambda ::= RETURN_END_IF_LAMBDA POP_TOP stmt ::= conditional_lambda + stmt ::= conditional_not_lambda conditional_lambda ::= expr jmp_false_then expr return_if_lambda return_stmt_lambda LAMBDA_MARKER + conditional_not_lambda ::= + expr jmp_true_then expr return_if_lambda + return_stmt_lambda LAMBDA_MARKER # conditional_true are for conditions which always evaluate true # There is dead or non-optional remnants of the condition code though, diff --git a/uncompyle6/parsers/parse27.py b/uncompyle6/parsers/parse27.py index 9b5c1819..c9b0bca5 100644 --- a/uncompyle6/parsers/parse27.py +++ b/uncompyle6/parsers/parse27.py @@ -158,8 +158,12 @@ class Python27Parser(Python2Parser): # Common with 2.6 return_if_lambda ::= RETURN_END_IF_LAMBDA COME_FROM stmt ::= conditional_lambda + stmt ::= conditional_not_lambda conditional_lambda ::= expr jmp_false expr return_if_lambda return_stmt_lambda LAMBDA_MARKER + conditional_not_lambda + ::= expr jmp_true expr return_if_lambda + return_stmt_lambda LAMBDA_MARKER kv3 ::= expr expr STORE_MAP """ diff --git a/uncompyle6/parsers/parse3.py b/uncompyle6/parsers/parse3.py index a214c82a..884d3e1f 100644 --- a/uncompyle6/parsers/parse3.py +++ b/uncompyle6/parsers/parse3.py @@ -334,6 +334,17 @@ class Python3Parser(PythonParser): def p_stmt3(self, args): """ + stmt ::= conditional_lambda + stmt ::= conditional_not_lambda + conditional_lambda ::= expr jmp_false expr return_if_lambda + return_stmt_lambda LAMBDA_MARKER + conditional_not_lambda + ::= expr jmp_true expr return_if_lambda + return_stmt_lambda LAMBDA_MARKER + + return_stmt_lambda ::= ret_expr RETURN_VALUE_LAMBDA + return_if_lambda ::= RETURN_END_IF_LAMBDA + stmt ::= return_closure return_closure ::= LOAD_CLOSURE RETURN_VALUE RETURN_LAST @@ -580,12 +591,16 @@ class Python3Parser(PythonParser): self.addRule(""" stmt ::= assign3_pypy stmt ::= assign2_pypy - assign3_pypy ::= expr expr expr store store store - assign2_pypy ::= expr expr store store - return_if_lambda ::= RETURN_END_IF_LAMBDA - stmt ::= conditional_lambda + assign3_pypy ::= expr expr expr store store store + assign2_pypy ::= expr expr store store + return_if_lambda ::= RETURN_END_IF_LAMBDA + stmt ::= conditional_lambda + stmt ::= conditional_not_lambda conditional_lambda ::= expr jmp_false expr return_if_lambda return_lambda LAMBDA_MARKER + conditional_not_lambda + ::= expr jmp_true expr return_if_lambda + return_lambda LAMBDA_MARKER """, nop_func) n = len(tokens) diff --git a/uncompyle6/parsers/parse36.py b/uncompyle6/parsers/parse36.py index 1445e6b1..d0bf2059 100644 --- a/uncompyle6/parsers/parse36.py +++ b/uncompyle6/parsers/parse36.py @@ -36,13 +36,6 @@ class Python36Parser(Python35Parser): # 3.6 redoes how return_closure works. FIXME: Isolate to LOAD_CLOSURE return_closure ::= LOAD_CLOSURE DUP_TOP STORE_NAME RETURN_VALUE RETURN_LAST - stmt ::= conditional_lambda - conditional_lambda ::= expr jmp_false expr return_if_lambda - return_stmt_lambda LAMBDA_MARKER - return_stmt_lambda ::= ret_expr RETURN_VALUE_LAMBDA - return_if_lambda ::= RETURN_END_IF_LAMBDA - - for_block ::= l_stmts_opt come_from_loops JUMP_BACK come_from_loops ::= COME_FROM_LOOP* diff --git a/uncompyle6/semantics/consts.py b/uncompyle6/semantics/consts.py index 34ae5152..d83c6c26 100644 --- a/uncompyle6/semantics/consts.py +++ b/uncompyle6/semantics/consts.py @@ -209,7 +209,12 @@ TABLE_DIRECT = { 'ret_cond': ( '%p if %p else %p', (2, 27), (0, 27), (-1, 27) ), 'conditionalnot': ( '%p if not %p else %p', (2, 27), (0, 22), (4, 27) ), 'ret_cond_not': ( '%p if not %p else %p', (2, 27), (0, 22), (-1, 27) ), - 'conditional_lambda': ( '%c if %c else %c', 2, 0, 4), + 'conditional_lambda': + ( '%c if %c else %c', + (2, 'expr'), 0, 4 ), + 'conditional_not_lambda': + ( '%c if not %c else %c', + (2, 'expr'), 0, 4 ), 'compare_single': ( '%p %[-1]{pattr.replace("-", " ")} %p', (0, 19), (1, 19) ), 'compare_chained': ( '%p %p', (0, 29), (1, 30)), @@ -321,71 +326,69 @@ MAP = { # or https://docs.python.org/3/reference/expressions.html # for a list. -# Things at the top of this list below with low-value precidence will +# Things at the top of this lnist below with low-value precidence will # tend to have parenthesis around them. Things at the bottom # of the list will tend not to have parenthesis around them. PRECEDENCE = { - 'list': 0, - 'dict': 0, - 'unary_convert': 0, - 'dict_comp': 0, - 'set_comp': 0, - 'set_comp_expr': 0, - 'list_comp': 0, - 'generator_exp': 0, + 'list': 0, + 'dict': 0, + 'unary_convert': 0, + 'dict_comp': 0, + 'set_comp': 0, + 'set_comp_expr': 0, + 'list_comp': 0, + 'generator_exp': 0, - 'attribute': 2, - 'subscript': 2, - 'subscript2': 2, - 'slice0': 2, - 'slice1': 2, - 'slice2': 2, - 'slice3': 2, - 'buildslice2': 2, - 'buildslice3': 2, - 'call': 2, + 'attribute': 2, + 'subscript': 2, + 'subscript2': 2, + 'slice0': 2, + 'slice1': 2, + 'slice2': 2, + 'slice3': 2, + 'buildslice2': 2, + 'buildslice3': 2, + 'call': 2, - 'BINARY_POWER': 4, + 'BINARY_POWER': 4, - 'unary_expr': 6, + 'unary_expr': 6, - 'BINARY_MULTIPLY': 8, - 'BINARY_DIVIDE': 8, - 'BINARY_TRUE_DIVIDE': 8, - 'BINARY_FLOOR_DIVIDE': 8, - 'BINARY_MODULO': 8, + 'BINARY_MULTIPLY': 8, + 'BINARY_DIVIDE': 8, + 'BINARY_TRUE_DIVIDE': 8, + 'BINARY_FLOOR_DIVIDE': 8, + 'BINARY_MODULO': 8, - 'BINARY_ADD': 10, - 'BINARY_SUBTRACT': 10, + 'BINARY_ADD': 10, + 'BINARY_SUBTRACT': 10, - 'BINARY_LSHIFT': 12, - 'BINARY_RSHIFT': 12, + 'BINARY_LSHIFT': 12, + 'BINARY_RSHIFT': 12, - 'BINARY_AND': 14, + 'BINARY_AND': 14, + 'BINARY_XOR': 16, + 'BINARY_OR': 18, - 'BINARY_XOR': 16, + 'compare': 20, + 'unary_not': 22, + 'and': 24, + 'ret_and': 24, - 'BINARY_OR': 18, + 'or': 26, + 'ret_or': 26, - 'compare': 20, + 'conditional': 28, + 'conditional_lamdba': 28, + 'conditional_not_lamdba': 28, + 'conditionalnot': 28, + 'ret_cond': 28, + 'ret_cond_not': 28, - 'unary_not': 22, + '_mklambda': 30, - 'and': 24, - 'ret_and': 24, - - 'or': 26, - 'ret_or': 26, - - 'conditional': 28, - 'conditional_lamdba': 28, - 'conditionalnot': 28, - 'ret_cond': 28, - 'ret_cond_not': 28, - - '_mklambda': 30, - 'yield': 101, - 'yield_from': 101 + 'yield': 101, + 'yield_from': 101 } ASSIGN_TUPLE_PARAM = lambda param_name: \