From d7b98cc9c5980a6435d6a31d40afc077a4510520 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 18 Jun 2026 19:09:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=20EnumName/value/IsSigned=20=E5=8A=A0?= =?UTF-8?q?=E5=85=A5=20FIELD=5FROUTES=EF=BC=8C=E6=B6=88=E9=99=A4=E6=89=80?= =?UTF-8?q?=E6=9C=89=E5=86=97=E4=BD=99=20hasattr/getattr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Test/CPythonTest/temp/_shared_sym.pkl | Bin 543320 -> 609790 bytes Test/TestProject/temp/_shared_sym.pkl | Bin 844720 -> 924720 bytes Test/TestProject2/temp/_shared_sym.pkl | Bin 185686 -> 194069 bytes Test/TestProject3/temp/_shared_sym.pkl | Bin 548378 -> 589991 bytes Test/ZlibTest/temp/_shared_sym.pkl | Bin 385220 -> 407049 bytes lib/core/ConstEvaluator.py | 404 ++++++++ lib/core/DiagnosticCollector.py | 79 ++ lib/core/Handles/HandlesAnnAssign.py | 2 +- lib/core/Handles/HandlesAssign.py | 102 +-- lib/core/Handles/HandlesBase.py | 74 +- lib/core/Handles/HandlesDelete.py | 4 +- lib/core/Handles/HandlesExpr.py | 6 +- lib/core/Handles/HandlesExprAttr.py | 40 +- lib/core/Handles/HandlesExprBuiltin.py | 6 +- lib/core/Handles/HandlesExprCall.py | 54 +- lib/core/Handles/HandlesIf.py | 131 +-- lib/core/Handles/HandlesImports.py | 8 +- lib/core/Handles/HandlesMatch.py | 8 +- lib/core/Handles/HandlesTypeMerge.py | 4 +- lib/core/Handles/HandlesWith.py | 2 +- lib/core/LLVMCG/BaseGen.py | 28 +- lib/core/LLVMCG/StructGen.py | 16 +- lib/core/LLVMCG/TypeConvert.py | 38 +- lib/core/SymbolData.py | 79 ++ lib/core/SymbolExtractor.py | 237 +++++ lib/core/SymbolInserter.py | 68 ++ lib/core/SymbolReexporter.py | 76 ++ lib/core/SymbolTable.py | 1121 +++++++---------------- lib/core/SymbolTypeResolver.py | 224 +++++ lib/core/SymbolUtils.py | 56 ++ lib/core/Translator/AnnotationLoader.py | 6 +- lib/core/Translator/ConstEval.py | 38 +- lib/core/TypeSpec.py | 11 + 33 files changed, 1722 insertions(+), 1200 deletions(-) create mode 100644 lib/core/ConstEvaluator.py create mode 100644 lib/core/DiagnosticCollector.py create mode 100644 lib/core/SymbolData.py create mode 100644 lib/core/SymbolExtractor.py create mode 100644 lib/core/SymbolInserter.py create mode 100644 lib/core/SymbolReexporter.py create mode 100644 lib/core/SymbolTypeResolver.py create mode 100644 lib/core/SymbolUtils.py diff --git a/Test/CPythonTest/temp/_shared_sym.pkl b/Test/CPythonTest/temp/_shared_sym.pkl index 59d9977f330c2ccf9d61d30cc1aae0e463dc2645..918d33784ce4f392b16eb4b133afd2285c6f8223 100644 GIT binary patch literal 609790 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 aFbF71u)5qMWljIBhI$*XQL8%D2mXKF!dCnM literal 543320 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 D(1dOm diff --git a/Test/TestProject/temp/_shared_sym.pkl b/Test/TestProject/temp/_shared_sym.pkl index 72361f0a2612b454404955d1c0bdeccdf00e0bf0..4229ca0867d1657ace557715d5cadf9af4df48bc 100644 GIT binary patch literal 924720 zcmeFa32+=|b|wgsI7yHM50T;_UTRsS4hR=PP*O_-3I(!MKmo!*N;0~uv#Jt6{;aA* zXI7B}+w73~U;}c^cr2H^wnOXn&Nw`7d)8r3*uA~>*zWbX5BJ($kJsz)b~qd!Z?ETw z=;_@KuXlRv81MW4tos16K>nEzS&tF?v$CpCD7^oD|GVFNr|pAXEswSEfA_N>r7{ zBBIB`DJ2qDvza4tEz%p+4YhYpJU?$ey|?u4$FdjS&GMh!lQNW~8CO!ekZ_`m{TO_Zk~ut)PDWFjo}5)vX(Ktm#$UP*pXo~*hMG+IN}ms9 zPK5K%udbz5^yGAesnL`#u9#*vl|D=7>hPJFFmH4EV6u∓nR~T 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 diff --git a/Test/TestProject2/temp/_shared_sym.pkl b/Test/TestProject2/temp/_shared_sym.pkl index 0d372ae5c6edf9de6ee14584b3adb62a5546bd69..13f33f4aa844ebb7b9813213d1d66b531ba597d0 100644 GIT binary patch literal 194069 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
    oF*cY(r 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 Q`lB)$4Ivt(VrlUI1FI#tZU6uP literal 185686 zcmeHweT*E*b>H$h`~5+3`ThNU{J6Wl<&wv*yW?@cNbYetOL3Px$)Palo$1}_y4mUV zOb?HgafX$^7jDpjF3`w95(qd03KS^r5I`}K$c_U= z4h-eJs@K!gJvBSc-I<-*VG&^W_H@;&s#m{y_1>#j)xXmIwXJPi+VJ1U#j|c-{@K#J zok=*xe8w!gyE4}NP}0tsL$mz%Iq`FE`O{a6=e}ITygg3N$mTPKW9N$Q&Qi|uUwh{K zB&B@akBr=G(q1<6#V-OO!`*qSkWD(4oqb?BgR$7nWdI|kP8o}DUWApcj2Zr2A!E^B2Mu?=o- zVltPrbF+?-{1Bfz_#=PSGn=uJ=D1yeqVBf2;&CdwV3)m}HlLW8;@z$8z-=>Y<_yP7 z2_8T>J13Xs%~Z-vjpp;#Vs;6t%y~12DN^P_=;z(zX~W9;KaS>d#xq`2%*mP9w7zL; zK4;{f-8Y;xf3ali%!H5VATFOjzkxuls`;w(r&T@nkxE3C^| zH?{cxeTVdL7!h%rB63gR(N zIsJ~?52Yj#KZ!b&Wn4)a^TWfbYgeu%hlj5vMOi&%^waOT-B_ZXU9c9{*|Ow9^6JI; zs~3kaT)F_IQp-Asc6yArEn_cQ$$GSH!7!5-M=oAWUAubm%7v6cZ7ZXno-DYB6N?#p z-pC{tXj~@%s74{C7VoCqp2?@nc8)}sFM!H^O~*@8rwielHI_iiwH4iVGh0~V@bC62$)7r*DupDJ z3!}Kp5km|g3iIi$>2|k!YT=HNO=UnZxCcrSPyCc0qWjbWP4A2s z=G~rKcCJM0U^QBh2t-pUX^C1o>Cx%?APo&GQ94|W5>E!Asw}yL+IA3jLVA=a9EB!69$tZJ)V&)e8x>luJN?LTc3xaw7Cy${%3woi)eO?}_R$ok2hT3K=lHBb9r{NM=vM9SF(VJ;yT@@RM+2x-ad&G16fSp1X~_x}O;Mlm&xf#qGm~CpH+UXwuVJXd8CP!`bHh8iROod6}(5UIC|-|#tsN+wqz{e(Gg*b*tImSv=@ zB#=VN^OmzBao^$&kt*D}?Mz{X}1}nVGgOQ5u z?6=9-6+CjcT3~w?J}J%vqhV%dd%*k$LzEl%_e{qS9l?1U;|ekq){y~2Icpd1_PQ}t zoY!fkymdL5N?m#Dl5y1-zIO4_6=65@k}>HO+PP$cv76&c{|;zSQrPzin;ZDZANX+@ zY-~U$bT1ecP|3s-BU9i=fR|Pl>kTh^#b1eel>KqHpB|~hzzT-MM%Kna7)jzA^zK&aE-HJ{`UpAvJtpoh1n&1 zx(pYnCa=~t_#5(Fhuhs=_BOtL2QTl6-*3R}<088Ww-q+ZuVZkHvvL0S1pj-IUvKeW zZo?H?FabT$}qLxhpN)NWjTOCZM3Sx*x1<2%(S{#jX3)Il>urm0ade=)l;a(9x6Ra zxqXE!de+UGp*xvCCZJCUDCPgQRJL&9uSb>OrzpdBD7t2~q0 zA4kHiI-HG-ePM1=U46jqFA3UY+Q>!FVYe#-+LCIZG>6$=M?$PRZ0$tEsx4_dp4e6@ zlEt+{8MJyLR(bBSW3NOpxzyoo?1PyH6AFvit^(+=7cM7+zi)Ltc2F6-deT*G=Cbif zU{!~$?GtJ<)a7WsI1&l1JC#9eA1SbkbC)edf~z`wZU5Y6fa~Q;k>I*ZIk+m$UA7Vl zuIli$eQx~DsLD$Pv4~dIZsnk=IA_^+B0*IhzIGu}r>ABWUMh5>+gW>*!Rt2C1k`6Q z`~66eRfn~)M>A6@8(Pufx>p&vdS;f|tYv=@399O_wSD%^%mbB0YkNKoahDPNt^1UL zs%K*<&RVv6YZU*LI(+To3{~6X+Bu7GjpTCOuMA*4RX~0Iva69Ws}5^B9x5&c+=0@< zR#ZuQKpEhA(OIf9nf;AOuvLe#-GZZP%i3*T96@xMdr%qZZucSyHi6Lnv=$3@7`fO&u z9SOVY@HVElpp7UCjwpjw&(WpXTGv4Cb}nMoRR|)E`=iR>)bny_zQ*ed)DP5NnvEDq zbWAy*YQEMNs9l_)YP$%cuXG((2Ctr-r9OMvy;zhL1a(;3iK10;#KIY9xk&2=CzL^~ z7qYE9ciD0zz^cR9&Rernzc2|wd+KhJj~1zUQaP|{&f<9j_1r7lK0P+t0#H4r3{*W6 zOY^n9K<&gJBE{8!M^Sffy{ZgcJvBgi?y~<9Nexhkv+cL0XGWEd(pt#aMwBS6Gs>XV z6RwK0mi<*Etg6G;j)|FvW78^c7qJw+2QsmE&+8I+rh{G zRdo$4w~NcxtC4nYol_35s%#x8X zs}5%cW-pE?kJ*U(xnENgvnn%~eG&Tp(I_VOj=F&lAH_v>n6R%HgWZ$-kaI-Kni zQ`d;f>THit4o0FWv~MVbT5nlaeHODHM1rk4tc}5ug(^d~1I{Ii2G=2F;Od1Ds?A#V zzal|Z9k#XuKb5w*V!9`_|>aECX#@0EEkV92z#VT6J>m?H%%&)LIeR2y2ztUP& zw1Y|CQWC0~v2}!MCu*x|$GmnT8?s#h z*$bDWVfKnLnDv&j)Mqd|6A85HuogjkaYTL4UL1)A+N&ypR&fTi_alK;9o8afFJDq0 zw3jbM1MM{xL8~}}*-|9Xs>9kY?jlqiv=5`JwAYmbt@;dRpGE?$I;`y$-a@re3zdwn z)xNC^Y)gl{Z34CSUqr&KI=tn$Rb1_IIc}pWw(ls3Tg6$-{xA}5)!{A2t>T)Oz-?6B z_FW}$t2m3<&m!Sg9p1L%Q94Qo7vT4~q6HV+PzJGHn4#j#Wrw<=cxu(*YX>q^<=_Ih z3*j1ZL*jeN;MEH;P@TQ(y-0vnhp`;6DzAhKz($OWy{RN%Rc0@nj|5nC7|TC`sQB`2 z7oJ=gas75w8OVBTVO%Fr+AqU?H4w`zMib zs}65DZWZ^$2;4?>c8x2ETg6$-em4?s)!}W2_@tD&2NuL@pSabwF-U#R9zbkeoXx`Z z<05;+Z&Ik?q4>DL{|So1?x zHkm1;%>0m3bYtVNU{m~R@!Xe-9~aNM?c;G{$tPIR+wjpfaKja zb{K9e>lj?)Y@Gi+!T+A**R>vjTMioDr01-zP3q=D z!M#6m{qe)Rnae+(GjmH;+pMWC=+(K|j zt}s-!{*HF_b@0)Ef9P$vwUl>fn=*2q?_jlung@UOf53d!=x3J!)=R_|7Z9+34W{U0#gM79C>~4$R{2$2tr9-O363=8OXN!=81!VE#LhD36rU(8p2Yc!MC+ZkRenI;#WkcD~=Bkz%_% zg0UfC;|H1|D;~ml2#1T3v9DQL$J4oinRdb1)BruG3_xiz(>#U2TetJ$ftzM7x2X|& zNI`^Zp4JPYe2%v_H9%=gVWT7ESKCq;TQaO{3otQ#y^))0R^wnda&TxP*;sQQCgWb; z&hc3%S4jHXFL~&W+jlz8e;$IvD9;zUFWB8FemWL>6~Q?i=X=TG+BaOjY4Km?2*{8Dnr0bCC?2kUIO zPwyjEEWPs}nyHP`*11sE+IlMkd_WDMzOP)UZ!pl= z?`l{4Sg zIOI(R%^C~rHv{7T-}p~(me%+5WYF@Hfg%H;|AFb`o=w~Ka-(MfKk7#N@mn64EYm$~`m98v^Xt zxwQ9!E5E^?^a^b&uh1$o00!^dADOw)Z0eq!Dr9Ue^Yw>Y{13O(S+^Ja;F~V<4|p=a zInZZ+9+35asbzi3>-mZRf9E~xshJwhK>+5G>A+WQo4a93uf)DYew`y~_;pGfW1BP- z*yy(MP|OMc2^L~+^CzwLx3b!=$T--I4jzoe=b@P!u^_9xJuk7h=a?GOzvR_#8v5C< z`4S&O@&AFA_${yeD}w#q6niG(k+pyS2tTAye~sGv8g-q0Jtq{C_)SAU`)>h>|6?uj zTVCQTg8hA^kb5J8@*cjuVl_PaUI**EL{6PkY6$sbok!OV55ZIf?|UIA z?VgdfmJ1mkfw>XNyq4=Pkz9XO4Y_{Qlk3gHJNvR0>n*RZs{!})+cnSAjz(Am&_RXe8R!Q zwOd%^us;R8XT$m1dEd6O&c%t^15DwWkPh1mOK|o>?i%=;LIO6r1Wgd)-$KNs@9BlXJbJ4)TAyMi@f zVuh}7w|uGgxM#X28m!_#Pi*|eiaY1aCe~J+2H2}0M>c*|oplN+*wa^gbSXTm(rH!| zv+6aRG;7YP`orrDvWh@#Z#5Rp+R)OrDQmFcM%%PKpR{wjH^4)tfTy78(`c*8efBF& znMTK9f3Rb2?oZL~m%10ZRatu$?E)*5j8|?2anD=?gY-H7IHRHlsbcQM{D!NCA>F%G zQO^FT8A79L)-jSF&djsg8j`}wH*H!8E8lJ`6=}Ie>wX)d`*mf_r%qzoi7-J4FJt@o zBil+9zgjGl>2B-^{`LZH#x~E*xJBJn$>yvWHN%mzC+J9NS?R<22AkkX8N?ma{9BW_ z&ODAQK^rC4Ury}|Rv4SVRsaI-Jb0NJvq2&>r*iGDQH$BKkLzLVY?yLF0Zn1u3d(B@Z!NFaEw2@UH<#D6XrSe_ zme*^S*JtHxlZ_1Tmw7}a`n86)me=c+*NVVLY}_fkUayEE2uLyX$;zV!ICQOEd0el| zRs`UCP}4?8L-?PWbnvw0sjRhO+i-NmNYl;=Xv~88kQ#FPRHd@5L9U}lUWcix4*Iqt zAm4|w`(7dASa7I}7exs|T*v$Aa43ibT!X7*SPkj@YNhnnFz1-o{*rpgZ$)6f3+49| zoCszmEeEykaU+w_Zf@=7UX$z|QA2j)$7(}vZVhoAtz8$rTM>wJp9v2mL3at9`+CbV zGbycgYpr{2TK6S2B)7z8qCu{GCUx?eC<5|6u5)Ld(Ok}ma7Jo<_Pc8@cZ+$sFRLN3 z@gw13U0XvNcfslnWNY1FqX@JIP)_p$X0@c&a9(@7_Ej|`^`S~ht--B>q}CZEr3kqD zQC7o;`*K=TYf-&+QGHzvQGKvdRBLSOb4J#;Z(R{=Z$n8fKCZ20wU*Uum(}m6A*&Bp z%4&^n9h<%0*lb16&38d^IgRU#vrev%)PdQ0k#TK{j5pMf*pgk48sR#suO3l-iXfby zHNr8?PdwYWv-tHYV~eda-c&eC_W4L$JlIeWm*XqbiT z$3^CUA0EEG*KvPl_TK2{H)@V+2oJl3oE>BDiUsr=qMhMG`0l3IIJ{Y@$G3ppuBrTl zxnO0@V)%pW+fm%w*#&EHNb?rBeH(ZVVbfEhZ{8PA({N+=@$xyitONnNeQ)Jw?7IP^ zi3gK&55BOeq1qD>s_pfIDwDBurw>xi*jpTe^}%WH*uz`5CLbhbr+#5_QzNxE8dC4I zZD}x6`M3UrJk`7fKSMpy`pW&OO%2k%Xdu0Pv-|kZesb`WY=fcN=Sx-1*m~l$ee&V- z}Y z{nqI8?B<5&wuta-+c+VrnOZMPKNf#DJ-w-?`t6FqvrKwwp4Lfv_TC$vyOWr?b!&EV zZc~GFM?{eJG+2g~nfIEt^|kJMI74U0N2fRUbUzpos;@K{s=It`RCBhjeyHxbI}avj z@61e3Y-*XhGa^t&8VuAj@4jYiJ^fHU(=#*o6Vp@orZ)HFzbhh8cQqKOWfE0$wyqMj zZ}!gAt+~YLy_tvc&5hOF5wY6n*?*5e`)l6T*<%Wt>g?UbqtWS2?l;{N5vxDnIJv4h zTUWW-JvKF$crY5jy}3=Qy%B*LYcNpDG*!*mdTOfulb^po6Q7LFCB{ZKxwn5`M67OY zFjn{a3V>!V#!uH1uLJjHCLT`DBqpXFP0h}1?xp_y5dquTV8HJ40js$SF@E($Y%h1L zCb%uIsl8SQBEq%NxfTWceyDK}>17Ke-OR_o$O@spy# z&Hx%<-^V$))$B#q)!o*1?#soGi)UFc{K-ZzS0DTpXZ`q!4Zt-$$F{+3g>C289dLcl z2H|@57<|3*5M+Um`5lJa3OmBDNBQ*_zaEFHKE1zAr}xt~mdP4BuGR(Z(59d>*xUKw z<~7{enz0wHWWoV-4>bet?6duCZ5r+{xL|Z%hZ_vRx5d-yyYcFYjq)9hjo75A2;6sj z02k+f898Uxv6mYu)X#>bI)A)S67u|Ur1WTNncu>LfcDxnTjrmX%lr)=670{o;HMG6 z{-^&mQe=P5pY(WW1K-lqG|9`O^^o>@CXn#<% z=YnIwxu7{Cf!#cS7JxSqjPs}Zjsp#U4S$LGI|xD_^`5DPv7Bjq*l5wu5w1NvUoOVc zO?9ocOD{W-Dv+ir^hxJVK<8+gZoT7ECSGwcmb))yZ#9JE@v2 z)hm5CO~E|-uUfFTydt9rgN+p&|f8V&hw45=YV#o~o;JH%MX#dQH#=q;hU$x?XkEkK@Uk%FqW)1`P zbuRC{;P=n?lMa4w#`Z{qnj+K_E!L-v#!vVS-z`_&i_>~HZo!1L>T z!k_eT(8B=^WE=(_CYb&Jk9@uiQnM=rd^4beJ9 z?4MU-MmS$#6Et-wu)IGDTqv?9dKPGTBSDdYaH!+}!fD`k!N~cOKts(0z5e?Wt^dBR zq||RR^x1#lVqPD3*~-ekBFOine7vRK68N>0FS3(-mE{yybWg(-;^E7_s}*m=$8K8i z`#nQyNcn0}K21SB8#tbn843GJLH!usGnFj``DkrlyLI?? zqThfi3O<-S1h*CTCeB=JnExGd7Q3W|$PXRI&_vj?ztn1e%d7c{pne~PE2ElEhcAe& zD_Xp3@m?44epyNJ-bC25_l{|oeXG0d)j)lEf(?Qy2B!evw@!D%pKPCa=BEN2gumnL z5M1xJvBPj%VMqA&D8DKap4iZ{8K1KU(AGGch3m&f_K4rm^HP{E6z1K%dApEHnu#Sl zRmhl$ytSBEfHUgy$j|h(^!4=H>37oa!v7oT_tH1v|7dzFJr4gT(v#_1>B)lIVPrCi zRFZeVmc78~6g!2tc6JMH_u96wG~93B>^}appB(%o%l;03YX5%s*S`JJPuX`c=@#~T zcxz)n5x2p8@YKUD;q4Xn2yY|oDc*Lme<*(Z9^QV={seC^*0vvRTiFS`b+QS(#n=Me zZol_K@n!acyVHESZ0DSW`P4CU*~CI2o6Hx#0;u^j_+&Ag!OI`^z~!}GxcsyWE?>vr zp5t#f;PR=v)5>P7tjV(`^3Rs$?F{nC-Ho*H$d5$ITrgl~c*4jn=8Ne&?%qW+Yv!zE zBAGGr`GjM_L4bzCx$Aa3GLw#-L%zAOterB8?p7o36y2_IOgv#O6u(+L_ki;iKjO>2 z4pP-^p9eiAU;H8@`_O#$k)2ENhuFNGdIrCqWuIZH?$K;^G!LDbEzxj09H^D)6h(?y z+*mUGm#;AInp80m^!eY}R%R@VqrlB&w4MeDdvI?``!9sYAD~j6{sN(LzJo`OJ?8e6LV?Cqf zIRJU8Hvr#ao#Jjs-oo=Ji!kiUlg9!Tz~tZYTk~D4c$obi88f@+q^WlQ8k2B>U4nr` zuuCw#2MGQIM8io%q5sO zzGPOgpeMkB9>D_awlxERC~gxhAd1^pV}UfsUMUNt)y1T>SP)yb?My}MdjqZS6|Dzp zC|du0=q?f!|31R7aNC#43i$!%;A4#nApu8)c$je8@7?!nRwEONoZm;f{}C_$IYOPJ z;*2V^PxKH~Xg|=#q00UUFCmaha~y#j)flZk|-q-`Q2_pO9Pxk+id3@-+Ab8j-m_5XH zD)w-o*b`7J@2IU&bDV`7b$|`k=Cwd=UiWGvgN-!D1<1i+BW)eNJqQg8GJbEMOiUAI z{EthFU(4i0Re3j1%nh$;GO;bqF)6M5#Q;@I6RN!1o=C&-L;`^oQ}~w3S(6Hn2MEtd z3%?ysW4awrj2w=FxZCsLM`Z)W?fvj0Pd(-uYx{>EiF940G~=&O%C~^mr2*9uR$@Da z5{qeTDiQ}I5FQX?txHsVz@L;k=>MW5oqT0RngixVL#U*mK^9Qbzy|UMehlq_+V#6w zy?*-x^+R2ZD>^+1KF`_p7H0_yS7faiXX>LHZNh*!P zpKI)hZGn#17U~E-;JCceKG+fp%{X zwfj#c0F>s~S!y>2U>EE=%{vARb8n*J=)4Qi{Lsp#yqShb?Gfmr!coB~6N=K}Fim~h zza!B89ijH~87|cC(i~upRq1!1gx~K(f=nzbbYHOD(qb@8ecC-3X!l^K-Dr7>0qx^m zn!|7R9e)_!g+FUbLm6MF2;vJ>3fs)3O*;rR8{}9>Z;)m}EsF$AST~6>Fp1_-0Zgh0 z3LCCjaEQk+`rL!}d^G)3HUm&m=L1CzQJa}R1Ni8X=C}$uxS}DgI=nRk5|>g1IeiUi zl#M(}Lvs@`0n(W6K*~(oIRm^g;AjCC5qN((bEZ?s!9gT(LBj3js^v1wzDs;|6rH&RG4BstwmPIk&1gk^Ugo{d ztN6;~FO~+1;r4>Lfv^Dd@FXc{Z<&uO&KBVZ(uj#ZO^{ThLkMOLCu#BUnph_o)bW5L z)2o4S-393%3AFeW(04n)(+FQAN4>7RC>jh@6G+Lv;aC5g@F)A0|Gego*c0f8J)w^9 zCuLtINOPdKg0?>!5{02nzUxuB~jcinoAUMTI9-B*Z9M!taJHNr9Cdq=Xvv4SlfEh;rTlyi^CUg zR3dqXsHP=p^ViTh;dx1#1H}oA&9%rpqIovJuaZZ|*O)8n9n5h70ab4NO6xiTb@g@4 zt)r>3g(U6@4fA;&EqW`^B2)so6qktts%tREO|Pz>U{6GH)XIb~(H;-f=C)TGnIbIB z@j1xB2dcEL;kQ9d;oI_67$OlIbeQNnfKn15-$lTN^hI}T3iY#);dmf0gb#=z3~PUD zbD_!x3Y9>bE|q{nf_JEFZBd#7*O}_zLM7Vd&ZOFS)|}MyF3oWmYQsBJT339_mp1Dm zXsCo^0)kZI;}Q55%;5`~vteYg|0|JJR4mB}Di%$^T7!BO3=9X_aKUSX%yCV{2XkBo zJ1-!nq`bKTbjt?}C87aCEx|;80L?C&aoG#@mb<0W?mrk9P6x$s>ZXReofBrxTo{F= zlaP@k&9(!wiK(Ho$Bvw+oL`8@pkOkUjY}jUK_H+huK|q<$_!RZkl)gJmc~NWx1XV+ z-#uDb40);C6mjC0(?Fs_>Akup;^NB6iIWSiphn_0P>R$*^uQ2Yu{z29}yug zQL!bJSy}|VHQC<mzGmz*UR;H%0*@b5k+G@pqW!D5>bAtnsa(z*8C_@HM-(hV3Zsa%tY3#SwAO= zB*@KBT2Z;M?+a6B-Qj*HI6u8J@&Aj+_;r9|nV zXem+h2ZpquvVl>#Hc-9#zPu)?G;pZU^Ehy%VmcY*}9wUq5HJCl;f`SA1LE^OT5so(jc8k$OI5I7Wq?ek#!Or$RmdqSL6%Mxzo42~R_i6?L(s9s5WS6@P3n7jM5zFu;u+Gtt-BbWT&r1=1_^J11&&Q^A^Z7S!oWOwlD`S zX3E!^rP;t#E*X#OsQr~d?NNB~+RGe^RE=N`bi;*3z~7fBE0lRGP~7{H%-^n_c{-4J zE^NC>+4K;KC?C0$h(<2K4imkoM)q5hdY%qwWT(X##t{}lBMVq6M2O5#B6JXS7mjsl zIq-V*l?KX1QkaOI3@b#GiWuals#65Ws{t|hs$fycuJ>W*>xt4F;5w-i`6BBVB0+Hn zR46L22Yq!>S`4PC)Na=@+|C5reJ0dyUtRLsEzMCq(o1F`5D7APsZd-#E^D{67)Vpo zr$HVD@@bS25BW6Qt$e=?I=a>!RB=vlk(R;E`IBTQCc|xqcrO!n@T^(orjjU-kV--& zh>OP`N$g;04pfNCm`!PD3MQ(M=7l0NYDucK!1H`Sa-A29EqP`9Vd?91(j05?$`By} zDHZJ-pVD&5jL(o)rozV?o}6SsHB<)8wp&l}K|S)p6BDU1<(~t)=E_iOji8G|vjiP%Tzn)RpD{`!)zN zX=EXmdai3oXpi3keWTD>W=Gl>`pGa_~rh;ca}v+SffxDHYtvLJ0Kx`E3k zSV}|PMrC7~TGK?WhQ23J_umk`NkL6-_}U0I)NSW$ffXx((oAImT;V={UosYn2AKy` zFhu7ErGd00R7m(3p|`{-qQO;>vbC%V(@us!QfgimqnDH#l#rrd%GbdtDd~)Up%sz1 zTX9?U>I-3KBd&zKDSC-?#y9<53h9iDOT9JEepC!8j8x333Zpa!_D>m}DGe!%L>1G7 zE6-<4UimP9WL-vNDg2wrz9udDr07;ZOaAjpP&#>q~S}`2hH0VG1H zfKteaEFwvo14JCz=h7OZ1pF2V23RHz2_p&%rd+hlMb&_D6jTB!6^&azRZRy*EeR)6 zR4xQqe?hQ*RkJ{vV=ZO@5hAmIiuTO{X*t!+0%9@cqN$09RxH+1Dq^vpYE63fh+rWR z8xbsAm!3@&NzW#VtLoX(91Yd8sYKGTsE(`Z+0q>A)U%1^Ss}ux7OU#n(i|0fwzRHw z(zA&+>Dg50I_cR&oAhj=JqmJ(Yi2S%TbiS!NlWV*ejCI9zAe|Yi9~RCV4@l;Da;R$ z^405$fw6W`jI~}M#wW<f5c|6zfPO;ArL?l&zsibD%)1!x{?FCOwd9Q<}JBnzl4Y zDZWcu*Sf|!QVA5fNHs=%rWXH#IefWL8967jZ>U%j1XL_8ywsW$W%dmbqsT=f1~Q_$ zeIw0L5$h=BO*qz(647{}!s`(0$Yci2rNDT)B*s&>*V3C3lSrBa=ca1bs6UK-*CG)i zrI(6DlQyg^a-}yE=SZ1pOi*S}41#fv(t4K0LAAFved457lYK*lBiRa{I2;;O!@j9d z@#TSjmqj0ud2?Cx5k#B3K%ie(AFVkmWUAs7Q4cbPuZVh-R+nW;v@{25CEPxxw*+*e z2XBq?Sj(Cls=>h;7As;OH8GnEF&Hs%dv%=38y~Qqa)uD>?8H!9l<^jpD!?&&o;ym zd{b^ z*h9kahG0)g_{l;+q&ZM^Bd5m5sfa<%M2O;OsA%pB4!rhU5ihz$Vl6`9J;5C^ zSl<)eK`3y6E8~td2L>MT9EX56;SCnj9B6O~#iQm#Arodqlg?wHdPBg3sD*4%RGOn= zEl^t5(pq4(w?Q`$^(#&LR5zqiA31(gbQzJqDZ0$tn_RXj-F^kmjfggJ2jssf6wOrDRJPmkEIzFmCfYeoFO!$wxkoatp=FC3g#(^UMmJRa{TB5^J_Y~(tzuztNzG=G znfv%R6h;&&o7J;nLybSc*Zt&@yfhq6CF7b`&%;M8^c2iXUuH$Oz3SHsLra(#z~>y2(lITO&=Q_pE_pwbhObPpIf&np&{k@me$Kn9CNq^MJ=v_fPClyF z$ZGhfjrxUjLVb3Hi!GJGg0=Q9_P@*|4i*H~0xd7nvN>0ybBt5Ge3n zloh}Vf0qk|-ZXq@u@IbnYZ?D|9e z-1M@crPr1(u3S!Bx*WfBEw*y)O6=0b$+h()z^rBRX#@Uahj+geyK?>7)vJl=>xqk3 z656zR_o4KfuBX~?`zzB^SG4$*>1p-Kjl{J}G4uArus%Ru1;UN98(j3)D3d~ zeBqRGKc&ail(J$800j_J^C?47v%pzEcL%k{acvFro|4t>Cv!%29Y1}b^7NXDMFe^C zVI`wIHk8V1aXq0G7ZQbG>G2x;4pW#_B$e&iRexDL4PsO?Y8u30PqEO436Su~Q0YsO zs{!~b`8a$ou=}84@*=*-$5!{P_7#SFEAwh5kpc-)I9?Ww=2N*zYxb?c|CZiZEPsJM z!Yakpk<~+TK2{i>)3fD!ooIG1coWF5@>|PyTUAT<8C_b1A6CB8sb+T~Zv&ZTdwYYs zO@LH1#Z38*=bGKI{MKS&fBCWbZ;kFuM30ueU-_<0?_7Rsu`prYFjsl11ZV|<5m@mG zmM5EiU;M5jAsXw=4Zh_NepA#)ra*Nx{d$%6tbS^J8~kN*vBDUBDX^BaP$-<)?7P7G zimTtK|2gCMCLY5meaphx&F+HVSX}*P{cR55+sx#XDI=LFeV-RLyOZ_a;_A2RZ$^HY zCzmeWXwx4C?<=l00Cxg^BcSE9YLxDCezPxRzO}ge%k|%f+{&+}V+qyKt<1L;SAVVk zRs?RZno5;!v?<*9jm6d9sK3oYZ+K0MC)JewR!#A?y|=jfTMh0OvAx6kVynNs`n&b- z93=|gd<&3w(=Sin2F4SJ0NZ~wSf%|XORId(ri@T}Cos!+>9O@?>%Zuj57ctjT6y@U zO-aanAKY`){vQp#>Bx+pSTBFerhJdz1$Rr^0QxZ%iB z(pW9uuIakqcfq<;-rV3;;AvD=xT%(eH-VNczqP@A#sE6aMtqws2fWW*j`BY=xZ!9> zP39_?HC4OhZNPK3w>P@mqH4q|kTtyyPW1mE?U;o|uZmt6C~G34RfI zs^5B0;?F`~0y{|H5cPr&0LIZkR!gamwFHvHTXmA`snp8_UV;Xs+`@H?;o1VgI)kbGmA zc&JJY?xYy-CirGUYerUymprkdhbq3xfNQZ)7{wP4b?{}uM1t$#gleeeSI5Ye{bd!q zRZ1dhT83Z?>RI(Z{)~}iju^8Fd=}hiKeie1V+G7q)qMAa`5eAhu$f6r$jTeD#0R!+ z1z#(vCX#Wu6~1#UX{;o*R01xC;IZ;3nE=kfZe?uU&=ft3J=WDwVHDnLensO~r3qyk7FyMlAoc^q~W34gBM*MOSIE(r5y{ ztr??0hu|SPVqW8~i;m%6GLGpdnTe~jHW#Lb9{ zqLYvd{>AX*8bm#SUVw{Ce^)8tHH3X9LgSbyhsjm>HTcJ529pf@ad7$I&V)O#?*~5ESVD`Zz!glGlnkFY7B^XmJVD+wlm^mO zQs6}v(K!65!XUOqEP7t(`9?7WY7jokqA@j1tzJPgCd63K`l$Dff zx~cu(bVA$<3p+p<1l~TN%i@-Vh`jh)^m*^-$wZm@&^&&!_aS}`-G;|9T7dBtn6`N8}k5M&Ohd9?x)LU?!p!v;#hD5ErtPl`wJ2S5LWiKtn49(g6nZ54S}GoMH}&k2E0-5 z#jn@e*#mj-tFO0aXb+YQZQ&9*a*4*vizTcDMulCTnzxK|V8UdNyZ9_u?K%%B5E{9k zQSuI$THbcR3(`s;3*ch0urGP_a`7ny>EQBG`BFo+fS5zs(&zQ-nfo;!d~XUr=R^lQ zGyV5YNAY%9qy=p+R_WkZPLMz)dJC)Ys#qmGCK>kSa10SAsMN8^NGzXTQy>b7W9?f~ zXj>TN`m60?6v!jX)-p;QKi2}I2>pu#l#WA^?lH<_#~B4B_rmr=jUMSE_67~sKn8sL zPF2WP;U4zT;@9C?aD!WMMfbSjBBR^@+e}VE+}l?amO*7PgW8$_CDl02WWUgX<1CD( z?KsZvQU4U1)IYKq3Q2wPwr3=}#{-Opd@OrO1b*6`=iVp|@m$F{#!)sA_-SuGv@^g( z_y-~v8>k&8IT``pM<|?w_?oGd=%zJ1+vKFourI7E`Q+KaQkVmDhe%j$XSHf>Ovf)J zF2SM1D==P9nB`cuNI_ZHLo*gSXs#I~PVN3c=&%_GJ=nWtnh#x!hXCWd*RLvEfIPw| z$O8bfKgb2d)}A19bUc9}_C+FoNs;7PpNEJ2S8F?vIjpf<_WR`MT@K{3wGZe7W2#%O z7~@5cH^76nvfsH_rjD^Ew8({AwziX)qvJ84;~C#AeuVM?hKbqd4^B^UAe0ZXig7R! zQo_FXBn~jPGBX?q44JOaCr5aJ_^@*_?xl(GkUt>b;sxaA9D_`ij)#^4p;=xqKEfu( z`@J6Tyo6m5$N=R-Dj#)>^ukT5A|vRz#SO@&$XLC(MX+n=x$R%!keKnsbz?+8iSm%AA-SuRDgBs>v~7Ls{Vj>NgxiO;;U` zT3FBd10EjavsFC7K~~oSRmm}C;mnP}@g}1Leb6pExIx=0fZ&9zshW4=7TUo87#>{g z4qkFh*Hm?4Nq%6w6&?h&RnEWxMN`GOWP3ogW7an}#|6~WjFR-sy@;ehmZ%hhR3r{! zOP3wvOm};5%m(xf4?tgW4m8!s|KT<0J)BnKS$z^t{qT0$9yyTJbP4-lE#6$5WMlQD z{Glqe#hLjww&HA53FSZ)+~V}St7T`7SA#9i(YL*Ab0ZS3mfzw;efxU*ZjH7$TTc^h zamwCZw2xNFZ*krplw~_x`fM#u#L0Vi3EZYC#Tk5>q%BV4yN$NZuOvA+IK<6CG?3AA z`8Kr034Pa<hO|X-09SYDYe-v^32?IuPYr2{f&s3Qwk>{AI-JVKF+NsH2iUCd65yO1 zGh?)fKm!UF&LWW8nIpn~ltE=j=s60~f14`3EynV(!oWjSNhNazyU-TK zqnTXtenv}pSJmv|4vx zoR-ZkN3?7@DQl1Ox#d|c_rTECmLpj;lMAkU;kBGWhG14lTHKgkHnjBG^0iCaMRj^* zB_5mBVk>H5a&0|X+@g0``xb7aYT*h)zFcH|O-pDi#b>$dWgLWM%o%Fd)pfj3=vA}# zFBXxpx2NZ6kz8FWU1{hg0R4j^dKo4(0RyZFUXnxj`iOZ=*60|1LaMxB9$)+La2p00 zE#Q}sA4XWoMVK~_OvV6=&rlG?g|qn>I*uRopcCY^lVm(a#?xdx10#H$b1=#1JbCH` z^C{aGmC*(A$}41i6-Kz@YcRn_zfPWe14bE5lE-h7#}3KQz8s#Sy9nlg9{>t!eZPw*l-PzJK840=lB zFO&i5DEaSall=F&tO-iAkID9Fu|?V!h7j0y92i1Y!+F*Wq4AuN0P>$?-pxZNunFnV zwl-Zm)Jd>kgs)p`b?&c#Eu1kVoH20j8pK@OGd~%1#>Oga;j$(cJ{g!GvQsJA9T5sf zeKH$U2-i%+>CAAvd#Zs^*KF8Q4KC{i;h}B1Q_>xZfKd;v-(&$dgLC$1oa;LtbiK08 z_BQu1of>X#c{y}=P0M~~dzn|R#uJHaS1zm9)r&W#FJJ5AUM6bfKKH|VF?}|x(C5n- zE$l##n(@$|9)ZY4hc?F=;oLhD2>98RH!U%SW!*Ceag=Gx`ycAbL<@@X z0Gmkn;B8P1Jct|Eg*e}O_J_=cQ+t?^>PbHTYfxq zG#&BIdqV6=4@8p699nu-1##9e9>fs)ec=eZFc(_Yg-6&F9KCk}K9+T1t1usB6Xrg~ z3q}>X``U^P?UYZZGoqh zo`KUR4zWMAJ?!0vyq6>LKFub?eT1sn^=8l?jXD=0XBfqJiE+pL@A3YiLs4;-O^gQ# z#%x<4t$K{-*o1ljQ#0d8w|G+fJfld@k*YD^{7!(4v)OTGxkHDM(L@X4`2{vn?(@%h zaP*f8j9+9E;{hDZV_at3X>AM9DmTqqpsA1X!hwapm6WbJkLSJ2CPDYJUbU{!pV0HM zl;+q6v}#MUM$i3(p0Bejo(qG7ps%;EfoN5eW)12A0`;Y<3}Zb+ux=>>;Z-&Thza)e z6!T!Wl!Rbak!F*!uU=*z?3VHntP0Ysfjwx7ktvpC_OK~OrdpBOZ?GvydLj3eWvKfh zWvmsLC)tF#4`60mH4e0znrD@XW=(uxpqW;S80eOiqE#1~MWC5hi5TdX6yhaDMF&0} zz_5r$$6DB?waP!UM$G*fW0vJJYGspUnoU9`AhRr+TM9>CW*B6a&`-%5!3OKbw&kAY@622vQrNVl|m`(=iqW;qgKLfulB`X-xD zlOwl``|5)@-?SxX-NPo>L#7B}-0;I_x8|6OTu?V5V%&ssp5(L#D9vSz-X9{TGRz-F|TUWu&PE684L|(WtKHc1X2M+`9noRw|J(T2QZK`iZ)F zZWDIN^b_UvT=yPJP>U*iu0vf?j_eoPLjz;ZYZ@|IXs@(gfWsne?}8m`0c=KV?Ule5 zCHF`N?+;+yKp&FF3K>5l&!{j$v*b8Tt09yyuU23}2oDcn*gz>5%bn*N)lx2rY*Bg7 zb&*}7Yvv2^p~V)22&2XKN_5S54L+o_05zip_(~xt*6Z-0ue5+Qqc!+SShHS=5B*dN zSTkCLuOzRTuf>NxYXNLVi||!}&GK;$^xYP~X0!-j71&G{xcI{sz-F`vU&&KvzZM_* z?^{5d(HeZExGJQpGJMbx{h$S;87;$CvakVZmQOmOzi9z#Mho%Tpk`V%?iqI;>0`7M zpABlJ72}~6pk}lfUkPebPK4o8930f-E4htkF%gEb=Abm69c!kgbt?^H7_HD}$C_zz z%|W5QlGBJSYqs~mk}c>)MoaaToJL|?vyJvAEuhV4tv(ytjF$jFKi2}D zb1ZSPG9L)ZITY#F;f_)`N(k!~gaDZfFzw;0)qZRw?STh|UIn@Hz zjF#*xS${-?ux(*6b_kM^lQh4Y#KSxEZb4XNQ}0>o42_+>F-j>o<=-va1|r zbP=aJ=bsj1XbR^*UxopCwaZV67tl3$40+PmVOr?vKvBeJ)w$R@e2*tZ{8jU@LVsFK zrS!O)$QF9l?EQJbsfrZiyt|K5xT+!SoJHPm1U+xzjx| zz6Ya>-iHxhUnUpr%gwjbgL}WyESy*f&c3xA&1u=(azx9fld|?WpIe^Qat{oBZ8?%v zGr8cp7hcO5WC&(;q{WTtWkXA^EnkgKU7WfRo4$DU%9X3}ix(%?)|16f!IlIQc}F1ZqZLc_oe?@Ym{ zpMVqmuxjX-yMR6wT+uvS$vamt>Mh^{Wtc03(;(urR=mFJoCdt}13ciS&uovFx*q07 zRPE7CcYbn4Homs*CbG6z_4QX_>!)Ob8i%o8CQQ(-G(m^S4(JXyf>ceLy1bImR@CWu zEY99W&;T%3h7xxnlbx!Wi(E~KZK2Kg;dwV~tr*D9gS=&FTL_eTHl=0UR6T_LFBUD{ zXfY5Ts>wNsww7}s0^!(R-?Sbeoj|x1?O>7os2oj4p$iT6p z9ISD}Ku%3Vx=(huutU2N(!?%lvtqGyl!LWP${ssl&!L0bVP~F$P!@bB3#%U=YuwSF z*3#6N!=6uO&o0}xTP>J_59Y9X`Z32GIHJ4S0YeH>`{6X5i0F1{rj6ANkTrI|F<8M5 zNE~&6qcdqp$b>UBbUX{IhahYGfTOOtHCLmqBJ2co*5X+}-uEC*nkOEa;|A~~a+*OW z>SXsMO2*R8{Ooo`p~SJs&PJh5v&kKUCU>}7Bcq}%1b=|u*g$Uz?NNJP{w$mPLE=z! zlBevEr%SM*UE!5&$DxGs;3E!Ybx~x^v>E{Ak=7r&deE`4?hxDo?uXMNB)mHwFS4mR zdR0S*sudHU>#f7Khu|SPVqTLF;xS?ekg_G)*d^Xk>XX=_;6pW7y)ju+4ShiTsT8x+ zFB1Rwpnj``CTrA>MgI!3#P0>IQyB2h>iJkoD}K9ZF9kvRmpZ7rC7V^ZZi-S6Y-GS% zEjL+XgudKbDoH8!O3oS)n+SW)l`HU`dz05+#pjYlLTp!_M6$Yevc?=xCncNA+@HkR z9JE4A6}BidNsCM&VoH3NPUi7E#2QmTg@_VUuyC#p{W{?o!6RL%I2b)vXHy*FbRF2= zqM|QUcy_O11f!?xY+OJsQ+(&$gXTYiL-VaA|n>(C{oRcW%R6FnJd^h za)-Y3+&1ds2+hHV=3w;1UCEqckAitbevjGn=>sS0rv5Asbmkm$ii?_esUNAXHb(Ww)8Xy8b>bJSE3 z4U;RewbzwfdyJmPgJ#NP`@3_;^3YTjlUxx@(!ItNqlfZrdW2fyROK{Y?b$q}2o~uC zi+tAG1BNC1v5|qx=o!6|d(OyFJ+vX1r4!7;29Gd$QV;s?5Ti>R*c1JCT<^cb=z+b_ z3J-{Ldm^RqY0=e`LPpQ+*%Sf0$M<@UmJgKAg8_`hk-cSrK}H{tF!P7xu|md=$TKR8 zVE)8mf=UPp^NN9{6^tI)D=7jdPVS)>f!M{ly)Lac%jmg1TwfE;?YVirn{KN@s%OA9 zZB=+jiyOMDg{>(eJ3?yG?5z3S^hzRe=~66_xN`l5s$P#zuB}5onYT?n_6|%?L#@!8 zPz`l!Qbdp8{SbJ-W!H$+@CjTa=Lh|JN(cQ#9Z4s3Bn$m;Fzddt>R@4hzGh*5(c!{u zuu*|wqj?o7M1IP3_&p0fgdNx@L{%7!t7~dJX*g(!ip1*NgY~1>7OOC%rL?q?OMdL2 ztejXLM0GQmv-zr0`FV7ga61K}BHu1o_34GNhs6Aw z*qsLj3nNm>~Z9I(hC57-cj`9=FsBXRHm|DpNPE zOsm%tvCEgPU%7bkO00obLQjGvage4a3^I^ggZ)LrRWGtxTaE2hJA4f5*p96wVaGVx zS|WAco*@^QYrok?BYdJ-r@N|dHc*Pl0;@_!d^#ua`zz$icDGM&;7 zV0~S^40Y74mX=nPbzzIKeuCB&_Bg~QdyGY-#h@}1om0ZT_aqLyKr@vHIZ(?B&!hK2 zn}V6$?u^(UH84}3CysV18Jp~YTZpcMm0}4ZIFR`^xe|hibwRY@hTUp9g-#emc8fn6 z*{u_0{@7*qtMKReuwNPV=MI$lLO6CfweA!NgNgD;4a+0BV!1Nv*i{&#a~>Z0Cl$L2 zN+g+Ww1i#7x?SZ8n=tC&9VzP%;px%w^ae|abKp%|>4FZt>GnAbo23gL3QOK-$QQY% zcp{OIZzdX%!W_VCmRH-^`KK%DRdwpp^tBsTuE(dY$FDTlsJl=Y$oQR}v>_?!W8P>c zm%IVR)%JoaZ(ixFd!9 zo?uX#-I_?4&%m;Zy8YfsSa4gK8$NhD=*t*dHlsQ@4E25Ze|v@mM|$QzXIjsUmKJF~ zdEd!lT(M9TGTIv%1pR@Pm7L}vqY!btL~Pq^!{!nRPGWnR`d6ignv>jIj*aO;|GY<@ z^~3Hzs~%8?t+c^8pI?gj79HeApvREXZy7J-^tO5mj3IJ*8y73br?)FNbKpD6q;5s| z05`iypH_{!Mz-Hr;*no}G^-j~B$;;N43W^opf?KU$n;dCCh9Q3Pt;+MX=`vi@d#_L z7S`<{(7N4l7faLj42AmujD&yevM9;+)O6o$k1!m!`qOlC6g*S==v z?lqEaeUI*Gs)G_-=21pdrd_&PE7SfShe#Y~11pj`!Ehw?Z&{A^6#5@6>KR9crarHc zWnziw$g;vPSPJWbl_gDkuysfbiDl|g2%;A+lUN{TU8X|cqj^2=L^BB%>JSSJJX%a< z@`e+SNUTxE)(Cc9^^B8Z6=ID#v_@mVN2ydYM;0n4bP}^ViJqTomh-DQDc*Z4>f>RX z_3|d}C`4;iIN`Hpg)kAS>5#DM!z%>2!dtG8P$!*Sp=q%~%&L(B;i1b8R;XQPv)C)+ zj{YsnakdUC`Z2#JbW2ivazwf%g|?;><^#|-nrZyP;JbM>5md8IazR3HEZM$26NPIh zQRio7?R=K=cYmAZowOXi0!fYPM2|;#V~4k!u><O)HL*qL@xF>?|XoC{D%L zia0u@3(z9YXupWdJ2meS0$VU7MQ5}r1KcIYV>@Iy_xpq1aD-unTNv=_nVfO<)uL0R zt!fGNTfg*VdV>xB!T=z>#2M7%Y!db8EzR(&IYY{3>Gj&$QcQ82*jo~EER{nhWdvO* z$MU7lQ+=ayETdscR8NYdT`ZErginjAz0~&BOu+A{sqSKen`|<{h&QF@G^c0ywr@FF zJW%MrqbCz!oCrSX(iW~WZ1TZ4m_Wg-9`_^?SuN*ahjsg`P_DGRcE(n*u41>h+})Vp z5O8;?h*>sSV**%XQBUMkmYVRm8Er1vO8=1XMvJzRURfRc=5_}oEKy(tyIK(3 zzP+V>uSQEjAhmAx=;z|91d%v^CUL?0*ug&^(Aw9nY`j!2bAuJA>C%5 z323MT^h046!Tx@i`p$kfnP6ltt7(=dpkNXq({FCk8WM3-K70e2O&%BnCpo;HGqkj` z0sz|&AC)|015%qr6tzn=L6A)@AREbgTulikzz%@$31V=J-!;!C#3mCQo=c`k8JLJp zMYO@265%MTD{`bu8Q#2wUR5gZ{n zVgqfvtNeRxaztM^rD4%*#XB|Bgyy!;w8Ar6ZSlYt$?ISj+9_MM7ss5^i0vX%) z1O(k*K)AkpcS-vgn{Bx6GKm;}0OJPwkUUn%_z`(Vg%P$k<1m3>NSIeEFd>A8 z2QX})6pS)T!}z3#8sZxXaY4RT<7fxuyRe5QzI}5Zf0zgPaF9^~9`wm`KG_%H0b{GJ zvjZajX5WwDkE)~?S@QTI%A5z<)9_H(@~~ri?f}+f1na=eZOI!^;J`Yog=A!>rA?l5 zj5b~MH%frUtwRFQ2nRSHag6igUaERf^m?r4w z9!*b8K1yb$r($YOn+!|dXvi12r+6ZfkZ&d$k$4d3ryGNhKF1Bysa0-lR3rBJYWTaM zD?R!T9Y_60HR_edu)E&3Y|;%D>9_!$!g%crSv-b(~cv5xElFVOM6yTDG&9&YanO6`Zwx@`XElD`g`r8?-uXBn+cUc)IBYf4lq--R1|pY`?t zeZ$`ddJi7RZk_a^!!nGPEPtt5xzrYH76r_Ohfc#oXS9I%%bRnDC}%DrSah@pqvgyG zRr7}^ZZ0xy-A@i-w77ZAp%+o=9PDsITI#$$tXnPt?dDF0C;;7!1)v!% zd|sb;UgiN&1|0%Ca7O7Rb9$MCdtB=}+8sT?7%hWd6QdPH(cKDbHY(a(Q{hCENC!dV zUWxP?v_-*mSJAGCMTqk0?$-aWDGMfwsfQ4awhJ{`l%ljcX<|VG`I>A!QD~hG!Pi6% zMA>yZu-7=Nq6j;*%Ap};YSgMI$&M30+_hwC1iL8EPKVNK0s*32JJoXSHKnXY@phVF zn3}W_QOX_X_bpH@6bBXaUx~M9OE?Z368(oQ2~v_ez~ENe>PP z5ClSto`^3XbAa|0Qthh{oPBFKn$xnm<%pI|CuQw%KDRupCyVH9U-+}2#@j_uD@dzjU zdkiC+jO7h2w>5Z(-v-X;2cuBu=sK1bo!-QGak#$c==h4^&1$NV)H9J}T63^eE4b)6 zsl?R7Y$c{9W%7YK(Hj2xU%|sS@bDCdJhggv7Z7O@fu0`6LHwT~<1;+wtE$u#CRRu( zR8Ksv<#J+OfO*_asCT+9`^|M($|em>EDJNsayaqmj-JY=wXl{=swp|2j%is3qD*L= zd#GT1^0CqLHallND}O0jDnjFwl*uRjtC#qL6lXH2mdSn($_4}{Ilvdv9+ z%9lxKkA?VS+dVQB6G^P`3zw^L*p__q^prB^lV_D#PsHQdT2;!dJJC1I z^6)ob1~<7n#Diw=b6a%)5A8 z2QX|@1&$pC4A6>L2{uAE=#f|nMpoii9Ib?i&2&h4{GM1I5c$k**o-6|g*4c|d#EKY zZf#@=8>~Y%Si!bVm&7`;%TGgb9Ez4zM|+=-VXw~WVRH=|hR4QWn1@G&v7C|3$Bnbz zRW*C|)uQvpHZr??ZO{Sy^H`9CP0ej{ccEtY^kCeRGPG<)H8iodF*JoK^)d`Vx#hlI zyL4?C3-h>I8K2V8;sp`rDK=vgri0TW%mXrwiM$XI=3!ee<+_KDAM+9Su`jDmt{~An?S@k-J6TJbWj3&wBH_79R zc+5X-7KerZB)d@e*kr81kftW^PSe)=yxULuEOV8qT1x85cD04NGL=`0DoKKcu{J#M zHYf7o;Wl0^w18hiei&hS7Gc^zG8qFfK0`qm7tWS8H`zTZ+UY~N_7mvHwfeE|v&lI_ zvdvc)U2X}|h5@(Yo#%wInK^@W}QwTl5hn~>bWQtL+t)xsMu;R8a zU)r=W<6f#gM|SIU3Bd$>Fu{E`nP6frmCvnW4w%WWtU!rHH!UW?2o29QbeD;gWRnp} zUPEMk%~h{qM?4_h1U{6(12%c!pyei1%HX=1%~E0oGnu7DyGXDCAFPnxEv(>b{z-`y z%=8n%3SF6lr8CM3)*b{Utx!%HX_VtAB1m1y8DH5goZ+gHD04=mBt^j)UC9|aHaTNt zR!eDSDGPR82oYN4!-dE*&jYTig&p}0f(Q8Efk$lez|f-puw%!fOb0?3MqOzbtuxLL zuBwD4o`UH&2!`lNhWLa{h8QVn24dQtMXYS!6049AWxWQkk080;$sK~ zsjW!aU6~tSWs^aMy!zTY&S2`i{=i2~TP~p>TyQ>I@UJn>9-Y@7f<3D08F!cV_$fBo zW5O)mGn>pp%Wyrr-U%fl${chtUwmVC@I@!Ihv17Y=8KGt$nN6NJZk4I=WmfcTS~Ze- zW@g=eHBsge;XDZE!RqevD{OMepkI$aaJ#H!6MnGik8;8|v9QYJ!pT*+8JW;6U8!4s zl}*kWj%HGVcSuhp(HV)=_AcLHlXtMg9?{ZkLDg8Lvkh+3HQ=ip+fD;ZQAdyu|NYn5 z=LtGn8`V59Ab0}WGs#c7(#HA?HhE&g(i7N0k<~N<=k~roQf>=4fd4^R7<-2V1%wbSG z-h4KzWehs!H_9QhYNKph3Pw08d^jq>@SI(hC57-cj`9=}N*U&LenX)%U2C8jaQFn_bJr>E!B9`ruk z7(Tb%anB#^?df@ztJ*RsjFrG%3i%=u2WXEwM*B8^eUm2E`%73$cO`F>3$*vQg!WmQ zXpfZ8_W1oA(Dg)1NKep2djFiyFDc=9Pe|fLW*=~j_QD>TP*2#P=0##3bdL32nphvO zVLdDPB`yT^A?INC(gb_h3)WslQe??hr-+itci1_~RK>@bg|f%L>a<9%2NAEn08|VcX;i;F* z>1FbYYfj@)=Xg_<(+47Q8tu|PbLNXRz>{vt811G4`f2lC{Y zbI7S`$mePxpZCqqN-_t4A9oHoRZUq7c=%p8A}w+N_zCBLQg%W6T$Os9Gz>YUGMHuow(U;jqNRzS-FpP#>g8>b255FgNG-$vjB&b1gtlRe{z@ z7fJSp?gb-U(E0fmK&QH2X}X_te$Oq1>@_Hn`A{HwYn}t+`~}CDcVJKcFp=s6_rM(~ z+vH2gBhLmF6_3{o)(Z#n zU1>@h(JzN?2O-0M&bW5Hzo}1U%Kqu8rV>fw1o`SGd3067E!k0>gyhXQW#` z9who}j)8`RU5bgbqXcDdG!z02%7Ml5x^tYVQu83eS(15(XuaVaW2%yRA{?1jd~z@v zQRcxA_w!(pOghF|rYSZKV5kGp2v=CY$tKo>tff#W5aNfdFR}^su|ZB9lmX{09zN|HajHR+3y-F!CLbj; z(^D%@C~IrT^}d6x4fUe2=7_y5#G;)8LTc z>FQNj^2yUvumbX|GV6(WTrG1Wj{UJ}y7y)^)gVPK zTqXJP!F{vx5jm<4mA!2x!pa3M$ZJro)$C|WuF5?n$kmmq|GT=)UPhw77axT&mKt*! zl#!*TUXl&eOH(#;Rl1eg%vQlwu$jB3TDqf~>OD5u>`1jX3u$ViL+z1l6=}9mWujGg z7uP#`pG`hGTFpmG*`#R{y15BdR#rCFDR-tMmY!gw?bPP!4u$jqn~Zd_nvtNuEY?Rs zJ()4IYzMe03byIfVu_n2@JH+%k}Y0#=xmNd#8h4y_S4T+Op7F~+tUj0wiz zgE7*(lQCS)j43h3wwjFz#^8f7^j*Oi)}99?jZxl(Z-!4laIOA-RCR2lTTb#AZ0#jlv*kHq$~L($0ncD_~f%%N~4hC zU$U^a<$8$VEgu$EewT5Ct16?!5!>=P1V`|}5s%p9h?<1oMg3vN4uP2pLzqxqX+o{< zD)w+yT{Q79Ozk1qqbu3t6E@kS#=|IS59zV1n;T^YsSZ`yuF3~S1iN%4yFA%t?9w@X zLVOd!E|(#m3c2_si>&+NykBLLU21$2ufDd9Gp#zWTkuJZr$wP#x>C1%ZC5c%=QWF9 zmM+#TKgA}q)Fknm#gAr_SuJkp+4W8+7*PzOi@D?*yOB#ep;-i%bTOCw%&y>)kd}r$ z6gs-3w6Q3*+Pj!7Hg+RhxT-u#Y$5jByO=G0mQA*(sS7lh%s`>KY>w1s*foBKsF}(~ zPRh^iJ|1yZag;X}t8;s|<#h-i;e$uM#U_u`6fePgMAjZtR3p{J8n?wFBDIkZ7Wu_p z$0BsJh+q*JpHM=gYQw^}*<_KL9d@imyeU1$Zp{XvGWbv#pRvggHTABbW<%IW%&VD1 ziV91Zg?L-6cO@JRK3L+Hb_Gkop>!%NQFg^`t%1r#;YH?ES7u)QGMgMy)5p&$^yAB{ z=-IStB=yY9y89}m%rC;}5Kf0xq~cfDRWJ$^m@!0m#fO}N9RTgoZ$Wb?3G(w$tD z+s+BS)0KMXSJ~vF=c^0MMKdYENsySofn+iUU=+_+`6-_&_xWZA%9U4&uW~`!1UtbiO(w06NH<&t|oZLFYJ1Im%XT zt!+!!2!DnTPWkQK$|-d8O*N-%OQ#4<;e%6tXIF3v?Eh2MDW$Vq;)r7xpXK`9-O3uS zDv=Uvh+~dj%o?Aw$r|;|uNL)0K1FH^(~E~y=faqN2;rLYZhwnA`oh-Y!`AxV?&KO* z)k)cVujU%lClOpD4zVo!0h?S?yL&ImQpo33LXv0J&2GH*uGF%7J($KEgZ|CFo}Qjh zd(iuk(EPl8ZwdReG_kL#dS0S>kKfM$%}=z1`vgtg zYiNGX=a-c5yeA~_BI^%0#(rTBP2g*C8*ISyBIyr0M}99&wOR zeJ@SuYtpN|U{6LQMV4H3!YCP)hn-_iRnXMflNRP4|B~lkm;>GVoO9TzN|_qi13^hv zq`SUw#3$e40QMu!Vc$nn!qnK21a@v{{it)$sfzU)jT#9>WiJ-&9MSvp&Y|z4N$)Q; zFlIcFNXRz>E-SI&1G4`f2Lk7q^97))USHUB0p@+Pvy#jK{KuWcPgTus4uAMwI3g`_ z0RIW+@KcriU)YrTXMG{b8wrGXkUuA#uK?8m&WoF_fG6ag_ub(kZhXo){!{~(n+qU0 z5L)!`5W+m|9R5#f+CQ5MAQ1k+K*+;|06OD%1r~d#T0k#vDuKL##b8JZhb1014$ro* z27@%&U~?@Hn49zaWFEA@xfT|Hsv6#04oR{%bT1g;f(OpGumn`MZyUM7bAHb)g>0xO zk@-*{dTX8oXW#|LE6{=Tg_`qHWOs$ELg0=R@_T|oE|}m&$4fvxi=mM!APXP|l$q$< z93=8^5rKZGr6r*16Eu}XA&)#8SX4Y-FIYqzNTM&av<6faawDshut8XQH!8^ypU1C+ zy&fK7b1%2F3RLaVrmJ9XwJQNx@%jT{9!%2~fO zz0ptz^e_ij(Cf}or%LHHMPUi*lFUOK?hWUNQkQDTLyj&$;U2?nv zbaVJ?_I}Gt;0*-tDR6Wpu*5~MbILjVRJCnQq_Ye^Z}I+V=lD|%?u=D!{BmH(_c#W+ zea6kR<~73$ecnJI#Dl$V#>NW4*|(OXIW3!8j%e9*5}K>#bIY?@?t!7NEl09yCKp`y z!fQE$48g39w74<7Y(Ul5+mMH)eV^7R#m8>yYS=&x<|(MU~C_8*A&Emak&1t^BxDuf#^T` zVs(|=oh_4CordiS8mvy99&NnS;3)iX7?S7wkj3uhAxvZi=YAJxxtal?N{C-uF&s!P z!3Q0ZQu`wMnphupwMbtmd4E-K5W{-De?~V9JuR4sStjbRvOn$($l(AkKLJOS;jpZk zs|4}$xxm&$Biqezmh3w)wu$L&1rZx5|Ng|IaPnhq>mP|8A1|B1*T7Ck{}`JR*l#I} z=8SAUZk)9o#@ob-Ux4uyoW4lV;I?FEN^Hz2TSt#sj@&O zF}1&Mt))>-OpT=lMSqKb3aboV7|dmtl9`15$iX7jniBt}Y)TxkObL7Jg(rKWc^C%$ zJE5=`rf>8g#PYDbJmXl632Pi&4i-0B&^fU@408{AR^Oq-qeb;`GM!JGMuo!|g)qor z|8$%6pdC6&^k~I&+-eF`A1VdvAcH#$iGG|!=&qW{AC2Nnk|WW{ZzBuz1Ey0524i=U zxnwNmB!nuN(ZO=UhYv>x9k@4E!pB*5wy>CvsC8IqO)N5Mulj3ypQ z54DUjms0OL$yO5!)tQCru--qm)xd*PM8PB3#)SZBXbVtK=X^S(~{0DK^K*8K|RH;&T12 ziG%(9U2`0&`34FqII>K|)=6hb9DT>p@(2mkq2>7}VtE+Ok468DSRR&_=U;XE@-V$6 zB7#;-XRy+Xg*XgH)B8dVGt3W$HApbYbg6Vjr>n;4kfQyhhzs07@^#zG3 zI#4~aL>}G21VKib;8s~5xXT2siT=;utS)qb^@o$QBpamk&H}?{NxF;bLu^w0!3x#W zu!02bUm!;kx{LNBY|{Sm3hjsESxw8#93mV8NU(CXoHQNB;0~i4QgICI9OCSh{`P(4#vD@EmzPK%sF1G}yOclPW0OA)SBxx^KZJS3Lc@;k(jCi;@-S>bkcsaf?Ao9uC7E}2SIZ(l<- z9yM-gSr2^{DeO&N2hW^@vZjjYkDx4$bv0eIyb|)-WfA5A(GHCSx|Eq>yN;Qb=ra>C z^^IVrmb(ykms68qlbMd!X{OHGZi1HtFHM2wMVFhX-xW4_X>2K*G&IZ1>wsN{Y+ICd zcAdFlS+eWQcZ%&xXb9DPdo!!MfPFe)$qDw^W@ynD)PztzwM`A#uhQLJ z+>>ITdxY)*yL$r#U=-Yg^L7$|#0N#R0uw@bcmTr&O2J5Z`zOOD_l#H41{NI^mTh}7 zjmXFB;z0Epqg+wh6zvdKm|Hu-&F@M#Kg%Xp9I*K*z6_k??L?%^77c3>DHBZ7l}uyo z5~k^dk0O``Tm5emtN$V%@d0$S=}tv=oDqJ=Cexe(uSCwLV_G(_Vg<&C!Xb6#929~T zPKvGUh3sBVV|OsgV>X%O=v*qFTeY)?d9KpUOd7Ha3Ds514Hr>er7JD1kJ;phiHg%6 zNg655Rqv$42)$=;3Z`I$u4IIt*d2`Es>e}cgd>6xx;NkWCmCgg%I1dq8lilc{#aGH ziERaP`R!xTU0dd#?hd|iRY8>bVnFbP2s@$c5PnPe;axaCp1=|+pmw`H>_CoTEL_3ABB3SPDgy#lWn@fs#Dv9PP6-(Jq-K z??!#z1x1?mafA3F=ZN2=iTHDtG?DH`BzYF>z&XF?R+s}4KkOXvPiX>v)B?O>c?Y7A zU^K!3kzJD$dl5T|pQF&IG@ke>E&yPEYnyMz9ut9w*BuPBTk`vCc zrm8^4ZCHn-Sq`N3N#{sYRhEZsNc&{)gTlVZJr3|baC#%);hA+XOnN1AHT>aY!Io&@$e=Xg_%Sq&{n_Y~=lB=ZoZI`150 zsEO;ZL$KVzuf5+I9|U3^B!(+ztIHuNXKzM zSBHDq8^!XU57qll6Zn6&qIWh%~von^wwk2N9)P)HvEaS~*b9y$Y=aNQJ&j^OuK*C4qfdG;Y4#|@uuF2}AkMbUy4D(VQ!&J;N zlVOBGCLDU&U2>Oq3$xT}7r`uoS!grMhio#-g*werVU~#Y*zg!eHW|wsop4?Lo@^xw z*QG06myfo`FQ4`FfT0L~?W|SUXixF=I>wnxmJ6?1apP4rtHup2+lkt%-<`47DmELN zkUe@)dld*o)Lyk}ug12=W-M_RorWmYm5oi+RH|$&xC`&AijKWx&-xmOmr~=T1e@Gd zzspmnyE+Y+YEI_CwjytKh-Bghcq=|wGb$2)ro*D1=)^XZNILD}q|>$C!X}k%+YYgb z8CMXogRYDnWZ7hs^L5(9=Ii(}a45PH4v#J7)+8P$xTq_+$k?r1)CoUFaFN&-YG{}~ zWRr^~>vR!#HgY~4)3SjTEBr=OlJro^7`YCdd=QRKLwf3tX!T<@xu!lpbuN|9t=joz zCcmbLQf(V^<44rC=}P15V>TJ2zVu%u5)ermDa}<6r^Fe(XK=Qu;Eb;1jGx%0 zoZ+h1QsRswf-|7HPhIj>cNkSaxm!4+vdQAU&L|fuI5t*3qHw8{m)2tB>-#6GYeV56 zw5Sc$&g^_TyOE#nQbuuAg_Id(KrjkE_>ZPwFCATmp?fvT*V$y0`lK>XDy7FQH{DI& zytVRal1V(c*dVDT=))A{pq8LW2E%7s5`Y%uvaDdx5FQ@Duz^xA$|wyZwK^R?%_bY1 ztc&r^Wwlc3zu*E)JTC#6!1OYq8P{q}c87cMlua(EuU1nDNi8Ka3H?!r3UFX)|Fl>- zSSGeRy4a3-#wP33pUi|3f_k~GfW4let8v}3>tQ?V0zP{6p1bWz6cxbwOgJg%I^eMI zO*Wb9#3;YM1!%wv* za8vkwa##vQl*PcTL@PuhyVvF7pmX@oqW8gCg1Fi;HXhLjFm9j^$zz3#ACYHN7$IU3 zhsj|K?ne!JAT>39-i`Xa3yL)B<7NpCIbVXCG?(BD&FoL1ML% zjxQ96di+X63N89%cwjllKKT|0g6XL9<)G>t)K?Ro^@T}nLY9_@Z|sRi0?6{F8R2yRgXDe1*)#X**f7g7YIqWLV>6}tIYVL zJopL6onuc`J=f=x+pxbCk|Z9)&k5(?Q`O4#)h}$|hoo5!B>ze0&{NgG^_$i<=zTIc zXklOE9tR6>%J~9NRlW5>f5zio;7jPAc8)z&gI@03C z^s=F)*Oph*>8m#`X;-htE>B&(apmIV+Iq4`ZIx;cBRxG1b-Z&`y@LyTLL6{_mEZZd zvO^9)e}&)K<~)puB@KXKm%fS^#C%Z!&+9lY-foX zHGXf2;r$NS_NxVFuYh`pZC?NKRf*e>AR>n4i_zsvh zgaFx13A}fS2Yju(cV>xLfK0sdcI3A=GS&8acpzfy^Z>I&EI@XXh|%XbqBQ{@0R@h5 zjhaL75FIhENeR7U@K{F2VO;1zCt%t@C&_qZn8!9`=i_Q&BHhAxLK3Z4`=yDBO6Ng*D#IIM$F3=;B4iI4@*?K>gf z$b%jRfEBMl0CjLUkj&NzGX@FzppBpf-tDb?(1@-FFORPG~JJB+85w}qOEg~3{v#CouUQSu3FKfn4aZ8WDXzk<$$WK1Evg8^i6N_-*foet9#LV9BWDC_Y@j#6$=sC@bN9Ns1leSb!LTGPC}D|*JawxsZGEhy zPWr%B!23X=E+ncqYMf(Y?2Yn}}{LvI2!{K>PNP^BC9v+C>sw3+FXu5qx zM@*ELLcRzO%^|G9u})y7Dnmw1m}e!w#0Ab)p;#w4Q>{_D9~W(0flaWaKFL*WK_?=* zeKi|vf;b!#!0b?q zQc4j1Xiux)MhWY7s71jaSE06xYEhPk7Ez1hDXtRrL7P^zP8)F$*JHGfid|TXQXj6; z^|+0$;k+UTG|g_+kLRkf7IhNvmaMz=KMvJEE)Ma#4ETW>z{MGJSH<_y8o0&bXMo#n zp<<6@^L-8){d;_(<1Qg#3K@)z&drcsPu8{p=SOJJCpek5qiEYnTO@CaI zPZ7zQh7o#_Rh^dTw&YE_ND_IRkQBjc(e6&4LZ!ncjOKCLT`!T+*;b>pQA%eW+#eJaEnAwH{pK4=I4r>Pq4wL=X~0Omm>X>*uw1#T{e<1M{Fc7GC|wi<`p$U+#XC5 zNullTtlJRs;R=y+u=Qm68+7wQH|^maRFhc_a5Yn!+3G|(>{V0od`dNR9uR)nEJVjt zuh${3o-x#92HJ3MSyX8IN60Cipn8o#fcwI$>Y9U+Wz2(nkwI|#y~%9cN%>gj(Y?wb zy1gMSZg3zLzQ`iBceMBv2iVRu#P&jA&*QCsoK@4=JD1W`SZ^hMVsSMq^bbBHZI=mkD-HH}NC2lNI=d>Ku`C_2nEP=d!8 zG@J$>Wz{uBcoBqVPm}Qsj2{%yIhbU0o;>w}`P571^fGzHwK5OgaZLXNgUm3T(DO0a zz!2;}s9vxGz1l8jYb?f0rZgNka?^L9blAuesPs;AZFUH;AA>r{L(TrP9hTsY%A*Yt zbj3MO^dYfP6f%B9q`3+sm^E>jAS#nEuU23}&8k{80(d_GSRD3jW6Dt@n8!_+#feX# z&-QddXoT`GL0KI8bPwSXla9sNPxl};Rh~Ei>YB+%k<#e8rg%x9~M>V%`sipg--npco~BLZltK>3Woe1rLdFEao0g5E>Q< zi0y3t(8z^0=~!%-kT`|dFrl|$!eSPpsW?R{Vo%Qkd!>CuDk3zhpyuQ^N<}nvg~&$~ zxg_Ck7!1`L{g$q6wS6@?WG8iYuRQjCMAv$=S^fL;sC@cp)DwD3l=jI&9n=V zo_LaQgWw6sOr~lV!-0kjELdPoldWUlx z8@bPYUOmM{cZE?C+;`C1CW*WQ6V2Gf)8joo&vI2wI}7_lnyUxtDWy7(wE`{r*?W-p z(QXDE4b-Cxy(@rpCk4iBN@i??ao?@1rcqOcvU?usIGZ#)V$!fc8KiZ4vKbpuaqmnj z&qEKE{cIBPut~%MWH)KJKd@#bbsj|VL@QM6g0bHyq)#4mL!&7e^@1%MYh|InQs@+K0ay`*wpl^G}k5Ay*NyiTv1>v0wJ)+|W6ztoy zL?4}ONGl`$CQF*M&+GRr2Hhlm_X@fTzJMqY2U)_W%?*5}_~HOIE|r*?OU9Liwvx# zNa6%UH6^GYm%J8jJKC3H^b&)jf5J}vDP3O^WG~3Ry{UCCGf4KPrEjdSX$fKJ<187G zQrh;E(pMOy`@?o|zmm_yX&$x^PA;}3Za{bzj(c?I{4SlK=W7g-zA5r8CpVr_)56pt zO>KmQ-#!cf4F>7{pk3tWjBGMhs4`PAxE2wSIHY@JIC zlKwc6`SIk6xtS&8y^#0qmG{#O61{2YV4~MjWXOr_TVdh1`JC_-1_}RAN!o*Rs{s9H zU=|`@i2U}7{A&zSz8TZOB7ZHV8Y_A>E$Cj*eS7Kt27`3Jza;UM3}mbcuNFe;B3GfU zCkWqWkm|?ERIfc=qt^UQL~^<%lJi9dY2M6E!`4k&jc0XX=bQ&wFVYoUIQRBt2C3f+ z;a8|Xm;6}E2@_u!JMA^`Jq(imbHv!GkiG_q$ttzFsKV&!7Nf_@Ann&0Ju8}OrWN1bW+Q?JqJ&`_;)i zdU`FTJr)s85#emFpBrG1@<&WLFDjUd?JO6zv)*Np;s+N!ca^a3J&Bfpcd^r?)h%_a zQZ9=4|g{?Xq0W~l>qRjXrVGe}E0cTonVUQ-o{Xw7NlOr6!d(a`g z`)I;DAjzH?zckAMzK0y*yN4#egR{OcF92I@QnwVrRE>z?ndsb{6jJ<>%mED_aYn<7 zJ#>lK8<>@pu;glib4t|#k2*t`u96#^^+Y_J0Q|f|fG22*;h}KE<6YncVXK|;mU8$k zO@t4d0XV$pJ}DX^Y@jn{e$_dcWYJ%RY`?e=m}9Xa!i0?zL~jHLDV-pzf0B%+$atEJ zf<=0Io)q&>i!tc0a)ChN0*kQN8{wplMM##GXpwJcy>i;fAxT5?Sl zu-Gx-d=owp%@YJ8xW))9HcvRwgb_p^1(Cf-e1o=TFS6K2q0TE1Efs`U;GS2&VoQZH zO_YG>u0TYfXe`q9#v&|sSEy42mTxQ?Er{%17b2uAHd;80dNu5Tz@zE9`;} zV6iE~=>|Fgo)Y~TgdyY(6R_Byp)M*US~ZC60r$2CSZvjByn!BIt!u+)`+7hs!yl4h ze&uV$C&deB9v&he9&W=RqXqmD^1}$-ix*+qKr$HvFg`;;7#Ge$R^)N~KxB|2fB`*# zVFRULlu;VSCq+c30W*v38=h~(38IsONR=Q=($-W77CSlAWzAJ;d*er&D zO&#j?2r7&q`a6i-Vi)2=EcSOeTWbwfxInae0Hayt4YfUQh{aY9n^;An>jSX|1S7Pa z5m@Z{u!&V98bAnj;DS}eVgra5YONxxC^)n}6ultC{xQ}BE^q>iy&xKGodI)*wh+QM zaDxR{YztB6B3sHpbchg|z$HzZ&^=5-X-V0w(7tlx2*xov*zc%3L`7Yl$O**2wQ}(T?k=YP2XnF+u))=B=jAa z;N;<5;;`H!<9jf+kJM|9I3^o3=AE!8{!!9cRdD|ZQ3*%%xNmQdd#e#2Q)GY8BKuV} zlSpZT@P)j0LEc;K`J)*)2NgOtMhkEjnV#7Sf~G5;JKvnGw+g5j|*c z^nk^n*@=4M7x6Q3_64W-xZqK-7(Y8z&jBKoCb~?z)@72#P};G29uQGAECWSl6pTV! z3n#J|RcmMki2$4609ULa76WXj>otIgwL$)Za0Og)1z3!=Sy5&Z2@+v9mlOUx+$8+b zix+R2@b^%Q8+ukG{0Xbwg~-i>8M>ckDdBG@7zp@z*&7*m1~Bct5mTrTjVR=cFb7?W zim@nP4%>)dh#Hqqk*#{Uu?OiX$xZCRd|@P!RPSf>oRN&@iiMM@WNb37XSK=M^3z^D zl_ExCv2du-v)?X~MoooL#eS;~pmWootn~C0hAaP5wBCB5(3jF4YN?|6j{TK)_{r1X zE*1usJR#X9-zt8i7%G}dFNChcVS$C7!a!Qf<<$FHv2gJ(e(4|m#UFh3@4ovRfAMR- za8_2++S$MS-aq^EU;Ej!FE0jlJ@xY6{PV(}|H`lZAD@2u=g)rsY;t<42z{ac48E1s zTIvVz5dH6XxB<6@6AI=hpdaEdzI$(esW~k39(mR;?Fg5S-Q6Gbh9e>I-Rp_H4XZlU zoMr&`B>{XxDbwx1UujM?;d|kTv>5R%?o8Ua{|VF0f5V*5FYSU~u=_E(-h2)Go)A>R z@W~PBmb5eBPvt{)uhrn{H~&)e1rAHzXvi12r+6ZfkZ&d$k-|ID@f1I56UGbNkwSh? zFeuIL=*PJK2~@a(pAVr(T@*j+?dI&c1o*j|1^UqnL^f|lZ_ejmx zXXc(_TA{E;eyk|x0-;4u#21ivgy1Hh=ncr>0DM%~8mRvMqNiDeO9^!WYw zcSLqXt2}&yt8{v~IVpMPJ#CN{Z#MscIVk+Iqt)F68GP@Z>F-T$-pzsC%{WSgTg6M~}Q-qj{%q6oKavgfyn@Mu#&hac9X@=N$6WanX!-4UMP?e}aF z{1D-m9p+B#JeISGOc3FgmUCHlz8;&{U^~A#jZg@U&)CGW5aAZc>e@2rYUiXR!Y$2G z-Cl1VC)!yEP~5mo+Pe>mO%h|gQD4TmdUX%l(yn1uhvpTctU7gJr`qflQNyJG~#-E&k1FX-Ze}4|2 zV@3VvVcLU^;;9E+fa#lkKZZZp(YHOmZNB_IOpAN>pcKCR6g|P0y?fBlo3DNcPkYht zpp3b5_-%FnSfAG|U2KT|V7Y+2nv$O9p7x>{ zJoTcm`DDU;GLNTy=&AYIFX5>V{T80~pg+XZUi9CYul;L0O`yNV(^>R)c={BLPnipM zhRlQLBAF+Uhs-xo2MY z29E%QzrxcV^dIrG7u}pDSMTC!FN)!55dED*o*bVePoBY3FS>}QLFB>H1PbBlEQ;gl zCNl8!Df$MU_Mm@&r@iRAc!IBjr$O{D@HBz`3{QK|U*Tyl`j2?(MPs*M8bqh@G=bj4 z(^+&APdCxKc={B@@U#cz@U$2GG@g3VXLuS!{|TNZP*lT+PM|M`;Ian=@w5l2c-o78 z%DgI?SHFp;Ui1?yWHPbvD!N)B$e z&|4VRG6@A^lF^F`1BG#XX@AEci0ffBlhF+o<5Rl#OfnN#t9*gpl(tg(ZbKf!$R=ZX zqx{(y&~1#spTcjm5c!|+&)ft5@vq>4^^^R%nke0|^li}(;Pr)J^uOR~0R69c8i8-r ztHNg#(Ib3Ya*Myg_aQY01{(d(0r;Q2`da1N8-Z;3vkHCLg ze@NqxJ6!b@pM&BE|2Mq3(CZE2@9E@!j>G>n{{i?_{GH@Ne=Z3ms1<=}>~HU_`U3dv z|FZIH{se#V8u-x-pcnI-{cHR(x!Irzo^`W96YycU+5d*$vK@S^JC2%P&${Cn+!5o0 zey+g+HvEsnrQeVK4*sw7+Z%pe{MN00yT8G2AFBH8L*{QE-N|pa?)d-Lc5Od)R#hCB zOQ#(=y#T$?(hH^S&=%;lwWXCphl)hdK@> z$z<)5zII7_zV^S0yCEn1t&bQe$L_Ak*QL}#9zu}GAf$4Iog@q>g(jANsT%**|NW;A zg=o?O?*qO$(B`13FKX2S^FRib2^7(W*xw5>rytMeSP5a<}apv|z@^7o)a2=7~ zR#S_g@6as0)?WPZzU}v1`RMw`D{VOf?<&*#bH2cx?jw8LU_0GMbTcjrYq*E9D$Kzw zXg29M#WCTOTODGbO2j@bVr`$8*HDUSp%{YKfcM!%n{yp)nAcE>8KE$*p}Okm6){C> z`2C4Yos%2hGWx*T3aVUB#Jt>D8at&Z#cNdgiwReqlPO=0&C9>DCIH0r&(7)c;dg4; z1j6SM#&1#Kujg~x<@gU;s~QAz<&Hb|qBtoh@7(L)UxTG%ckcPT37}&Atw{M)5=0eG z<2h2@=15iNHX?@0#ObFz)+Su>sc;UP)3eiyQpi!*a@^^N`KELas<oTq7+hdb=mj8BJ4X@ppJsj1L?Y{7@aemb?;5qy*FF8me+Z?L@C0$7eW|*q=}@d zeqwfk2-pQm>6$GY{!Ds?d6uCRim;Gna$wR=RD$PG_eyA?nZ{s+C)jUD+oa>$-|Y{Z zvh)v8XA)7*cNQGde{da2@uE;zLZPb5Xe&v#n3bCOs_=-y4s&oY!3Z*^T}~~u<*OcB z`gP!ox1|Xr{he*A?e&e-r8S9bV^K~Tu3V9$_pTj{F$4k{4lIjP!F9BIRF1A}tbNas zY;i7(y&ykE05`)Gh1pj@1(a}$JnnwJ(=GhC`?+{+4om#>WSFF2=OWlXnXo;SnhK7)XAlPN@%$eCvR(6^*I`zE;6*zIDvED1{aP@U6d# zA8pB-AOKMam8!Czc@w2LTX_@JScW@!;qwrq-m$T50M&Dz44}qEW%`9jN<0g`5@xlN zS@371i!iIPWA}@yH5R(m2Yt)H?4WPilq_f9`X3y3`%=MCk3_5KCOVJwYd%luI=%WL zM_QW=O?KY^iD(Hy(<;;KFY0)ZQfMkcTn>`&z;imWSJet)CnKepQD=&)UaIQ_(KX=A zk=cdln#fw9xt+JLqAw*YQUGWfoTUNino`{8==w_uk-eAfaNY0&AU&jeorul!ld_^h5NM-~*D8MF!^{A3csPkIQ;&E7ywciQ8I z1fX0<&?I3S%5DxRh2AC&p?3=2=wm{gs*Gd3Q%doaXk!~nb=6VL-^DNz4I~_M7lg*g z`>qdrby&K6Afx9Nx0C53gsaR5b)8$pM&~?;6{`T38kFpkZVR@>_p%^eeoY?uW z+gb03vr{4@I!dAN(vr%w+S5WdtNP@IJ1YCY1XhCB3NBL-GTJVFwbsKCw;yiAkGTEzDhk*{{r@1UfTOM$D(9oF zSXJt?#vG;4(*jk%XJWIe3dnXhsp-K8H9bU!nx4vuYI=^{L4^_mOtp|tP&sBHMTJ?7 zXZoW{?R)dLS}Uzvx7RsIv<7xEr3S}8ak@|A*92n;GH3XJ-tKzH>+z6MtW4uqc3z@ce+ zlqigX8ML~;Q4^W+mpN%*VitBN;?xATCzcl%>;keDlusu?`Lyqg_H+ggN^r!%4~|vm zgasv~=vpohazH}@N*U->p;i`@ltMN<56UfQ1BZY%75-#p9JEO(zAV~UbW>e*G>&de zg6}}6PHOZWP3n4iUGtq2iSL{kg71JMdO0*-J(L>Y2w#B?&kkqj!TX%& zF7Q4tyzOvcJ5MRD35D%E)m2C1oyR2XJcR0`zIJ}0wce`j{4>eUKa=hJW{*);qd@{Z z0TL=tV0AjB(AR52sMEpwua(hiQb?6t)s0(F{7Ry@<}Fi$^%S8-N}(ONJo<)Q1++6F z=2<(V9I+45XpgIFKV!PjhQ_mQMcjTp8_vhB1g-TZK3Z)qR{hd5L?C0mC(ySzh?)XgA1?S~VHB>Vl)Tw=HDYT`8r|AfsKQVO+C7 zBF;eQ*z-P@QiN-k#)}fx*9OmNcNu8W^FEhSNNJlo8P!!gO`-cuZ*cP%IeJHObp}Gg z8~3l!S*x9_n>I-H0q^UHJ!U(e!^$^G@upB%I8j~m(bNZYG{%Wwfmp+Gby6J;WY#OU z>(j%9`IYLUh#~0CB|&%2gDzm1+`}`@^c^5r0^5M4-UoHNRASeFV1kA(m}ru1+D%qs zf*Fz-m>m^nmIqi-M=1=0#IF_TO0@$V9k7^#ZG&u`({xNUE%ZAC?my?diMLG81vH`y zEywH{5G8&%Hz`r{ZY$sOTO=021LXk(%ZvOp8&F9KNGwJ$3QK{9L6PVht5({v(-WZP zlt(W>jb=#Sm-q?{Q-K+S(Aops5&gV$?>n%5G2;uqOTdgTgk8!oV_{iu;L{Ic02m>r zCt#!$x<8RWV-5f#xayo-c{?#p`P_lnmVqr^eS_^;D*A+PYnU@stePv!PM-6=fw(L@ zA2twG^_Cw1LI6@I1XQm@*kdG0At?^^In`J*;HQ!pAz-Y>F45-W`rk`=s_bdx2#UNz?7@;hH=uj3=Io-5(zn!vPnPm5VFahNp_ z&c5I#1hWfn!Y$!!a0Jc<$DTNwQan(c4T->5(6J}ZrW9Mm+2A?tDGXZl#MzXhhO?=z zL&DkM4V(>~hlI1i8#o)hXC*HgGGjQKQdCHq>Y9(HKA@v9&IXG#JakgSB}x(AMg@3% zF^RQ{9&3}r%nrt3T%SM!o;gB-MzdLvU7t`2O^8FdJ^^pwKxk7PTnuSbit1?>)pe-P z93cUZ7NN1?nI`+C6d^CvAI-7)24ay2AXe{Onhr%)-+&n&ErOZki0<_brKmk~q_)YQ zIbssx1;U5$%&}kv&ZQ)tE_pm{@2vEFQW8-LJ)62!qaln#i3BD9y%4Jz*IhAG;MZNTo@F4Vh{`~FD?T>2ydHlxxAT$E?7Ahn z83$vOg-|7wg;Z`R3m=SmUUu^!^}X!osZt+%141bjxS^%-#$unZnZXDTXdv1;ftEz6 z92xF3A~yTkh(S`qD{dW>tFO3q)DL#$;XxaqAzT(h_ZpvdgS^S1?8Q93 z25H&ZM)~WU;Vk&oWWldy3ubRtC`DH{NZ+4>7JdL}8ugJMQ2sKf5t!p>#bF+pSA@8w zuybkKJ92^do`AFJtAq4QLG1QTzEXC1BYb_(xLXJ(_PAN-r5_hdSH< literal 548378 zcmeFa4R9MAiXH2?Rk2k7R=bfYN(o&B6_!N#Z^b zpz$M#Z=>}a&&-Qx!}huc&uf?C^?IGeaXGH7Emv*4iDxIC{~1@xaW?C6oMbk3%Fbp} z9(!tMGn>silXGuh0NsrS(FD7J+t5*!x&fm5_U&`O``vTSJ@?!Xx*6;yKhOe(xde|ipOdh?l#lFE6t zf0qhlk<#BcHgjv~R3J)}Sk9Z2v)Q6l7%dextE_nC*qTC18V+O6}dKx0sISlW_mf77Klk zxKbnRF(UlVk7E?>+1*`)MGQOvDs#IuDPU?wEQ&xgHhaw1jvqbHM* zH`$}Qav6ob+R#EGnvpY`OLA_F{m?l9P0;I4sRG<8j7FBTN`@9+dR-9Uu}C(Z&%~6- zIuk(z>JnK2S<$+T7rNHrp~b?|>}!wdz1hcMC9|H8lxO+u<5?y9UM{`ym?2?l(+j_4 zbL_B`Nz;a#dYn_%Hy&SKxf!3l8JoNvUAcWLI(dC!V>1C_R#N%(9Ne+X(kG+0?%bZ9 zj!)f*U%wSsrqt5=*EiDXqz%R2n!0gIiQSr-l5gFO-=2)B#ScLH0N!jUfBL2zyE8Qn z^0^z0M`P2xeA)tuv<>CQu1`j9+=i0l(|4wB+`Prhe*(>u&e%}?O6=y{mFcO;n^8Fq zlDf;v&lgTbR+H(doQ$k+0*HXbUD2RmsQTxzOGFa%x|sU-Hqly=&cte*ek?ITcR=gA~Tf)TsU`JHgNX6}Y!_ zVX<6+Zq`+bYlCYCrF^t7Fqh7h%Q{i3EVu|btbA#?v^BX@&d{SZc(HOxr)rhNE(1=} zTy9d@D6pbRGvyM`)he-kX|b@c{8_!ttYk(#N@lfE*P11lFD({E)dI7XKa~Vp5y2p| zctw^cYt@%tRb-&y7n{_wpI)?_OC(|Fs9C+rHESR6+R(~mqlIDmQ(z;@rBFDtU0vY1 z;@an{UuT3C;>qPowJe<7t`vGY|vq zy>c>HDrj4A(+i7hzgAt$0dHtSi6!Kuwy2u&)?8a$`!7sN3u~_66Lmd0nw4jlf${_tpt-}OmG+f1t#X+)J3{G7=qw|p&%CnL6&?1&u$hd`A@w>a zb4YuKNlgc5((%o5Eo=6BdKL8h%Ecx{4Xe6nxvi>ui#^eSkV z%Ecx{fu&Jt;hLi)Tm++J`BIZ|hCy_S27KE!2VAE%NBIVm0*8WfB3qGJ&0&{a27OL* zxmjt8axPX8S!#|YzXQ4Yz4J0s# zy1)hi<)}BKB;{vH98{h{??Up)Iv6itUyMXlvmvx5PcF(Epsm60eG%2pRLzCK#ic-C zA>vu^-dqqg}o6_ybAlvU5{QtX%N(@@<�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 diff --git a/Test/ZlibTest/temp/_shared_sym.pkl b/Test/ZlibTest/temp/_shared_sym.pkl index d42f8d00912e0b2939d4d762f28760b04a95c4e3..236dd9364d3c578226b177e49684c78e6c9fff21 100644 GIT binary patch literal 407049 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 HJo5hoF%%<- literal 385220 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 Optional[Any]: + """求值纯常量表达式,不依赖任何外部符号表。 + + 支持: Constant, BinOp, UnaryOp + """ + if isinstance(node, ast.Constant): + return node.value + return ConstEvaluator._eval_arith(node, ConstEvaluator.eval_basic) + + # ================================================================== + # Level 2: + SymbolTable define 查找 + # ================================================================== + + @staticmethod + def eval_with_symtab(node: ast.AST, symtab) -> Optional[Any]: + """求值常量表达式,支持从 SymbolTable 查找 define 值。 + + 支持: Constant, BinOp, UnaryOp, Name(define), Attribute(define) + """ + if isinstance(node, ast.Constant): + return node.value + if isinstance(node, ast.Name): + if hasattr(symtab, '__contains__') and node.id in symtab: + info = symtab[node.id] + if info.IsDefine and isinstance(info.DefineValue, int): + return info.DefineValue + return None + if isinstance(node, ast.Attribute): + return ConstEvaluator._eval_attribute_define(node, symtab) + return ConstEvaluator._eval_arith(node, lambda n: ConstEvaluator.eval_with_symtab(n, symtab)) + + # ================================================================== + # Level 3: + Gen._define_constants / _all_define_constants / 平台宏 + # ================================================================== + + @staticmethod + def eval_full(node: ast.AST, ctx: 'EvalContext') -> Optional[Any]: + """完整求值,支持 define_constants、平台宏、BoolOp、Compare。 + + ctx: EvalContext 实例,封装了 Gen、SymbolTable 等上下文。 + """ + # BoolOp (HandlesIf 逻辑) + if isinstance(node, ast.BoolOp): + if isinstance(node.op, ast.And): + for val in node.values: + result = ConstEvaluator.eval_full(val, ctx) + if result is None: + return None + if not result: + return 0 + return 1 + elif isinstance(node.op, ast.Or): + for val in node.values: + result = ConstEvaluator.eval_full(val, ctx) + if result is None: + return None + if result: + return 1 + return 0 + return None + + # Compare (HandlesIf 逻辑) + if isinstance(node, ast.Compare): + left = ConstEvaluator.eval_full(node.left, ctx) + if left is None: + return None + for op, comparator in zip(node.ops, node.comparators): + right = ConstEvaluator.eval_full(comparator, ctx) + if right is None: + return None + result = ConstEvaluator._eval_compare_op(op, left, right) + if result is None: + return None + if not result: + return 0 + left = right + return 1 + + # Constant — 直接返回原始值,bool→0/1 转换由 HandlesIf 自行处理 + if isinstance(node, ast.Constant): + return node.value + + # Name — 查 define_constants / SymbolTable / 平台宏 + if isinstance(node, ast.Name): + return ctx.lookup_name(node.id) + + # Attribute — 查 define_constants / SymbolTable / 平台宏 + if isinstance(node, ast.Attribute): + return ctx.lookup_attribute(node) + + # UnaryOp + if isinstance(node, ast.UnaryOp): + operand = ConstEvaluator.eval_full(node.operand, ctx) + if operand is None: + return None + if isinstance(node.op, ast.Not): + return 1 if not operand else 0 + if isinstance(node.op, ast.USub): + return -operand + if isinstance(node.op, ast.UAdd): + return +operand + if isinstance(node.op, ast.Invert): + return ~operand + return None + + # BinOp + return ConstEvaluator._eval_arith(node, lambda n: ConstEvaluator.eval_full(n, ctx)) + + # ================================================================== + # 内部辅助 + # ================================================================== + + @staticmethod + def _eval_arith(node: ast.AST, recurse) -> Optional[Any]: + """通用算术求值:BinOp + UnaryOp""" + if isinstance(node, ast.BinOp): + left = recurse(node.left) + right = recurse(node.right) + if left is None or right is None: + return None + return ConstEvaluator._apply_binop(node.op, left, right) + if isinstance(node, ast.UnaryOp): + operand = recurse(node.operand) + if operand is None: + return None + if isinstance(node.op, ast.USub): + return -operand + if isinstance(node.op, ast.UAdd): + return +operand + if isinstance(node.op, ast.Invert): + return ~operand + return None + return None + + @staticmethod + def _apply_binop(op: ast.operator, left, right) -> Optional[Any]: + """应用二元运算符""" + try: + if isinstance(op, ast.Add): + return left + right + elif isinstance(op, ast.Sub): + return left - right + elif isinstance(op, ast.Mult): + return left * right + elif isinstance(op, ast.Div): + return left // right if isinstance(left, int) and isinstance(right, int) else left / right + elif isinstance(op, ast.FloorDiv): + if isinstance(right, (int, float)) and right == 0: + return None + return left // right + elif isinstance(op, ast.Mod): + if isinstance(right, (int, float)) and right == 0: + return None + return left % right + elif isinstance(op, ast.Pow): + return left ** right + elif isinstance(op, ast.LShift): + return left << right + elif isinstance(op, ast.RShift): + return left >> right + elif isinstance(op, ast.BitOr): + return left | right + elif isinstance(op, ast.BitXor): + return left ^ right + elif isinstance(op, ast.BitAnd): + return left & right + except Exception: + return None + return None + + @staticmethod + def _eval_compare_op(op, left, right) -> Optional[bool]: + """应用比较运算符""" + if isinstance(op, ast.Eq): + return left == right + elif isinstance(op, ast.NotEq): + return left != right + elif isinstance(op, ast.Lt): + return left < right + elif isinstance(op, ast.LtE): + return left <= right + elif isinstance(op, ast.Gt): + return left > right + elif isinstance(op, ast.GtE): + return left >= right + return None + + @staticmethod + def _eval_attribute_define(node: ast.Attribute, symtab) -> Optional[Any]: + """从 SymbolTable 查找 Attribute 形式的 define 值""" + parts = [] + current = node + while isinstance(current, ast.Attribute): + parts.append(current.attr) + current = current.value + if isinstance(current, ast.Name): + parts.append(current.id) + parts.reverse() + attr_name = parts[-1] + possible_keys = [attr_name, '.'.join(parts)] + for key in possible_keys: + if hasattr(symtab, '__contains__') and key in symtab: + info = symtab[key] + if info.IsDefine and isinstance(info.DefineValue, int): + return info.DefineValue + # 模糊匹配 + if len(parts) >= 2: + for mod_key, mod_info in (symtab.items() if hasattr(symtab, 'items') else []): + if mod_info.IsDefine and isinstance(mod_info.DefineValue, int): + if mod_key.endswith('.' + attr_name) or mod_key == attr_name: + return mod_info.DefineValue + return None + + @staticmethod + def _intify(val): + """float → int 转换(仅当 float 值恰好是整数时)""" + if isinstance(val, float) and val == int(val): + return int(val) + return val + + +class EvalContext: + """常量求值上下文,封装 Gen / SymbolTable / 平台宏查找逻辑。 + + 由调用方构造并传入 ConstEvaluator.eval_full()。 + """ + + def __init__(self, Gen=None, symtab=None, platform_macros: dict | None = None): + self.Gen = Gen + self.symtab = symtab + self._platform_macros = platform_macros + + def lookup_name(self, name: str) -> Optional[Any]: + """查找 Name 节点的值:define_constants → SymbolTable → 平台宏""" + # 1. Gen._define_constants + if self.Gen and hasattr(self.Gen, '_define_constants') and name in self.Gen._define_constants: + val = self.Gen._define_constants[name] + if isinstance(val, (int, float)): + return ConstEvaluator._intify(val) + + # 2. Gen._DefineConstants (大写版本) + if self.Gen and hasattr(self.Gen, '_DefineConstants') and name in self.Gen._DefineConstants: + val = self.Gen._DefineConstants[name] + if isinstance(val, (int, float)): + return ConstEvaluator._intify(val) + + # 3. SymbolTable + if self.symtab and name in self.symtab: + info = self.symtab[name] + val = info.value + if isinstance(val, (int, float)): + return ConstEvaluator._intify(val) + if info.IsDefine and isinstance(info.DefineValue, (int, float)): + return ConstEvaluator._intify(info.DefineValue) + + # 4. 平台宏 + macros = self._get_platform_macros() + if name in macros: + return macros[name] + + return None + + def lookup_attribute(self, node: ast.Attribute) -> Optional[Any]: + """查找 Attribute 节点的值""" + module_name = node.value.id if isinstance(node.value, ast.Name) else None + attr_name = node.attr + + if module_name and attr_name: + combined_key = f"{module_name}.{attr_name}" + + # 1. Gen._define_constants + if self.Gen and hasattr(self.Gen, '_define_constants') and combined_key in self.Gen._define_constants: + val = self.Gen._define_constants[combined_key] + if isinstance(val, (int, float)): + return ConstEvaluator._intify(val) + + # 2. SymbolTable (精确匹配 + 后缀匹配) + if self.symtab: + for key, info in self.symtab.items(): + if key.endswith(f".{combined_key}") or key == combined_key: + if info.IsDefine and isinstance(info.DefineValue, (int, float)): + return ConstEvaluator._intify(info.DefineValue) + + # 3. _all_define_constants + all_dc = self._get_all_define_constants() + if combined_key in all_dc: + val = all_dc[combined_key] + if isinstance(val, (int, float)): + return ConstEvaluator._intify(val) + if attr_name in all_dc: + val = all_dc[attr_name] + if isinstance(val, (int, float)): + return ConstEvaluator._intify(val) + for dc_key, dc_val in all_dc.items(): + if dc_key == attr_name or dc_key.endswith(f".{attr_name}"): + if isinstance(dc_val, (int, float)): + return ConstEvaluator._intify(dc_val) + + # 4. SymbolTable 短名查找 + if self.symtab and attr_name in self.symtab: + info = self.symtab[attr_name] + if info.IsDefine and isinstance(info.DefineValue, (int, float)): + return ConstEvaluator._intify(info.DefineValue) + + # 5. Gen._define_constants 短名 + if self.Gen and hasattr(self.Gen, '_define_constants') and attr_name in self.Gen._define_constants: + val = self.Gen._define_constants[attr_name] + if isinstance(val, (int, float)): + return ConstEvaluator._intify(val) + + # 6. 平台宏 + macros = self._get_platform_macros() + full_key = self._get_attr_full_name(node) + if full_key: + if full_key in macros: + return macros[full_key] + short_name = full_key.split('.')[-1] if '.' in full_key else full_key + if short_name in macros: + return macros[short_name] + + return None + + def _get_all_define_constants(self) -> dict: + """获取 _all_define_constants""" + if self.Gen and hasattr(self.Gen, '_all_define_constants'): + return self.Gen._all_define_constants + return {} + + def _get_platform_macros(self) -> dict: + """获取平台宏""" + if self._platform_macros is not None: + return self._platform_macros + if not self.Gen: + return {} + macros = {} + pi = getattr(self.Gen, '_platform_info', {}) + ptr_size = getattr(self.Gen, 'ptr_size', 8) + if pi.get('is_windows'): + macros['_WIN32'] = 1 + if not pi.get('is_32bit'): + macros['_WIN64'] = 1 + macros['WIN64'] = 1 + macros['WIN32'] = 1 + if pi.get('is_linux'): + macros['__linux__'] = 1 + if pi.get('is_macos'): + macros['__APPLE__'] = 1 + macros['__MACH__'] = 1 + if pi.get('is_x86_64'): + macros['__x86_64__'] = 1 + macros['__x86_64'] = 1 + macros['_M_X64'] = 1 + elif pi.get('is_arm64'): + macros['__aarch64__'] = 1 + macros['_M_ARM64'] = 1 + if not pi.get('is_32bit') and pi.get('is_linux'): + macros['__LP64__'] = 1 + elif pi.get('is_32bit'): + macros['_ILP32'] = 1 + macros['SIZEOF_VOID_P'] = ptr_size + macros['__SIZEOF_POINTER__'] = ptr_size + macros['NDEBUG'] = 0 + return macros + + @staticmethod + def _get_attr_full_name(node: ast.Attribute) -> Optional[str]: + """从 Attribute 节点提取完整名称 (e.g. 'module.name')""" + parts = [] + current = node + while isinstance(current, ast.Attribute): + parts.append(current.attr) + current = current.value + if isinstance(current, ast.Name): + parts.append(current.id) + parts.reverse() + return '.'.join(parts) if parts else None diff --git a/lib/core/DiagnosticCollector.py b/lib/core/DiagnosticCollector.py new file mode 100644 index 0000000..0758bdc --- /dev/null +++ b/lib/core/DiagnosticCollector.py @@ -0,0 +1,79 @@ +"""诊断系统 — 收集编译过程中的警告和错误 + +替代原先静默回退的模式: + - return 'i32' → 记录 Warning + 回退到 'i32' + - return [] → 记录 Error + 回退到 [] + +使用方式: + diag = DiagnosticCollector() + diag.warn(file, lineno, "无法解析类型,回退到 i32") + diag.error(file, lineno, f"加载模块失败: {path}") + diag.report() # 打印所有诊断信息 +""" +from __future__ import annotations + +import os +from dataclasses import dataclass, field +from enum import Enum +from typing import List, Optional + + +class DiagnosticLevel(Enum): + WARNING = "WARNING" + ERROR = "ERROR" + + +@dataclass +class Diagnostic: + level: DiagnosticLevel + file: str + lineno: int + message: str + + def __str__(self): + short_file = os.path.basename(self.file) if self.file else "" + return f"[{self.level.value}] {short_file}:{self.lineno} — {self.message}" + + +class DiagnosticCollector: + """诊断信息收集器""" + + def __init__(self): + self._diagnostics: List[Diagnostic] = [] + + def warn(self, file: str, lineno: int, message: str): + self._diagnostics.append(Diagnostic(DiagnosticLevel.WARNING, file, lineno, message)) + + def error(self, file: str, lineno: int, message: str): + self._diagnostics.append(Diagnostic(DiagnosticLevel.ERROR, file, lineno, message)) + + @property + def warnings(self) -> List[Diagnostic]: + return [d for d in self._diagnostics if d.level == DiagnosticLevel.WARNING] + + @property + def errors(self) -> List[Diagnostic]: + return [d for d in self._diagnostics if d.level == DiagnosticLevel.ERROR] + + @property + def has_errors(self) -> bool: + return any(d.level == DiagnosticLevel.ERROR for d in self._diagnostics) + + @property + def has_warnings(self) -> bool: + return any(d.level == DiagnosticLevel.WARNING for d in self._diagnostics) + + def report(self, min_level: DiagnosticLevel = DiagnosticLevel.WARNING): + """打印所有诊断信息""" + for d in self._diagnostics: + if d.level.value >= min_level.value: + print(d) + + def clear(self): + self._diagnostics.clear() + + def __len__(self): + return len(self._diagnostics) + + def __bool__(self): + return len(self._diagnostics) > 0 diff --git a/lib/core/Handles/HandlesAnnAssign.py b/lib/core/Handles/HandlesAnnAssign.py index 6afab8d..3949045 100644 --- a/lib/core/Handles/HandlesAnnAssign.py +++ b/lib/core/Handles/HandlesAnnAssign.py @@ -82,7 +82,7 @@ class AnnAssignHandle(BaseHandle): IsUnion = False if ClassName and ClassName in self.Trans.SymbolTable: TypeInfo = self.Trans.SymbolTable[ClassName] - if hasattr(TypeInfo, 'IsUnion') and TypeInfo.IsUnion: + if TypeInfo.IsUnion: IsUnion = True if ClassName and ClassName in Gen.structs: ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) diff --git a/lib/core/Handles/HandlesAssign.py b/lib/core/Handles/HandlesAssign.py index 17161eb..e747599 100644 --- a/lib/core/Handles/HandlesAssign.py +++ b/lib/core/Handles/HandlesAssign.py @@ -440,8 +440,8 @@ class AssignHandle: sym_key = f"{ModulePath}.{FuncName}" sym_info = self.Trans.SymbolTable.get(sym_key) if sym_info and sym_info.IsFunction: - ret_type_info = getattr(sym_info, 'FuncPtrReturn', None) - param_type_infos = [pt for _, pt in getattr(sym_info, 'FuncPtrParams', [])] + ret_type_info = sym_info.FuncPtrReturn + param_type_infos = [pt for _, pt in (sym_info.FuncPtrParams or [])] if ret_type_info: if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: ret_type = ret_type_info.ToLLVM(Gen) @@ -616,7 +616,7 @@ class AssignHandle: if ClassName and ClassName in Gen.structs: PropKey = f'{ClassName}.{AttrName}' PropInfo = self.Trans.SymbolTable.get(PropKey) - if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: SelfVar = Gen._get_var_ptr('self') if SelfVar: SelfPtr = Gen._load(SelfVar, name="self") @@ -734,7 +734,7 @@ class AssignHandle: if ClassName and ClassName in Gen.structs: PropKey = f'{ClassName}.{AttrName}' PropInfo = self.Trans.SymbolTable.get(PropKey) - if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_SETTER in PropInfo.MetaList: ObjVal = self.Trans.ExprHandler.HandleExprLlvm(Target.value) SetterFunc = Gen._get_function(PropKey + '$set') if SetterFunc and ObjVal: @@ -1222,7 +1222,7 @@ class AssignHandle: elif isinstance(count_node, ast.Name): if count_node.id in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[count_node.id] - if isinstance(getattr(SymInfo, 'value', None), int): + if isinstance(SymInfo.value, int): ArrayCount = SymInfo.value if ArrayCount == 1 and count_node.id in getattr(Gen, '_define_constants', {}): DefVal = Gen._define_constants[count_node.id] @@ -1558,94 +1558,10 @@ class AssignHandle: Gen.variables[VarName] = GlobalVar def _eval_const_expr(self, node, Gen): - """计算常量表达式的值""" - import ast - if isinstance(node, ast.Constant): - return node.value - elif isinstance(node, ast.BinOp): - left = self._eval_const_expr(node.left, Gen) - right = self._eval_const_expr(node.right, Gen) - if left is None or right is None: - return None - if isinstance(node.op, ast.Add): - return left + right - elif isinstance(node.op, ast.Sub): - return left - right - elif isinstance(node.op, ast.Mult): - return left * right - elif isinstance(node.op, ast.Div): - return left // right if isinstance(left, int) and isinstance(right, int) else left / right - elif isinstance(node.op, ast.FloorDiv): - return left // right - elif isinstance(node.op, ast.Mod): - return left % right - elif isinstance(node.op, ast.Pow): - return left ** right - elif isinstance(node.op, ast.LShift): - return left << right - elif isinstance(node.op, ast.RShift): - return left >> right - elif isinstance(node.op, ast.BitOr): - return left | right - elif isinstance(node.op, ast.BitXor): - return left ^ right - elif isinstance(node.op, ast.BitAnd): - return left & right - elif isinstance(node, ast.UnaryOp): - operand = self._eval_const_expr(node.operand, Gen) - if operand is None: - return None - if isinstance(node.op, ast.USub): - return -operand - elif isinstance(node.op, ast.UAdd): - return +operand - elif isinstance(node.op, ast.Invert): - return ~operand - elif isinstance(node, ast.Name): - if node.id in getattr(Gen, '_define_constants', {}): - return Gen._define_constants[node.id] - if node.id in self.Trans.SymbolTable: - SymInfo = self.Trans.SymbolTable[node.id] - val = getattr(SymInfo, 'value', None) - if isinstance(val, (int, float)): - return val - if getattr(SymInfo, 'IsDefine', None) and isinstance(getattr(SymInfo, 'DefineValue', None), (int, float)): - return SymInfo.DefineValue - elif isinstance(node, ast.Attribute): - module_name = node.value.id if isinstance(node.value, ast.Name) else None - attr_name = node.attr - if module_name and attr_name: - combined_key = f"{module_name}.{attr_name}" - if combined_key in getattr(Gen, '_define_constants', {}): - val = Gen._define_constants[combined_key] - if isinstance(val, (int, float)): - return int(val) if isinstance(val, float) and val == int(val) else val - for key, SymInfo in self.Trans.SymbolTable.items(): - if key.endswith(f".{combined_key}") or key == combined_key: - if getattr(SymInfo, 'IsDefine', None) and isinstance(getattr(SymInfo, 'DefineValue', None), (int, float)): - return int(SymInfo.DefineValue) if isinstance(SymInfo.DefineValue, float) and SymInfo.DefineValue == int(SymInfo.DefineValue) else SymInfo.DefineValue - all_dc = getattr(self.Trans, '_all_define_constants', None) or getattr(Gen, '_all_define_constants', {}) - if combined_key in all_dc: - val = all_dc[combined_key] - if isinstance(val, (int, float)): - return int(val) if isinstance(val, float) and val == int(val) else val - if attr_name in all_dc: - val = all_dc[attr_name] - if isinstance(val, (int, float)): - return int(val) if isinstance(val, float) and val == int(val) else val - for dc_key, dc_val in all_dc.items(): - if dc_key == attr_name or dc_key.endswith(f".{attr_name}"): - if isinstance(dc_val, (int, float)): - return int(dc_val) if isinstance(dc_val, float) and dc_val == int(dc_val) else dc_val - if attr_name in self.Trans.SymbolTable: - SymInfo = self.Trans.SymbolTable[attr_name] - if getattr(SymInfo, 'IsDefine', None) and isinstance(getattr(SymInfo, 'DefineValue', None), (int, float)): - return int(SymInfo.DefineValue) if isinstance(SymInfo.DefineValue, float) and SymInfo.DefineValue == int(SymInfo.DefineValue) else SymInfo.DefineValue - if attr_name in getattr(Gen, '_define_constants', {}): - val = Gen._define_constants[attr_name] - if isinstance(val, (int, float)): - return int(val) if isinstance(val, float) and val == int(val) else val - return None + """计算常量表达式的值(委托到 ConstEvaluator)""" + from lib.core.ConstEvaluator import ConstEvaluator, EvalContext + ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable) + return ConstEvaluator.eval_full(node, ctx) def _eval_global_count(self, node, Gen): val = self._eval_const_expr(node, Gen) diff --git a/lib/core/Handles/HandlesBase.py b/lib/core/Handles/HandlesBase.py index b958144..09a3875 100644 --- a/lib/core/Handles/HandlesBase.py +++ b/lib/core/Handles/HandlesBase.py @@ -395,74 +395,8 @@ class CTypeInfo: @staticmethod def TryEvalConstExpr(node, SymbolTable): - if isinstance(node, ast.Constant) and isinstance(node.value, int): - return node.value - if isinstance(node, ast.BinOp): - left = CTypeInfo.TryEvalConstExpr(node.left, SymbolTable) - right = CTypeInfo.TryEvalConstExpr(node.right, SymbolTable) - if left is None or right is None: - return None - if isinstance(node.op, ast.Add): - return left + right - elif isinstance(node.op, ast.Sub): - return left - right - elif isinstance(node.op, ast.Mult): - return left * right - elif isinstance(node.op, ast.FloorDiv): - return left // right if right != 0 else None - elif isinstance(node.op, ast.Mod): - return left % right if right != 0 else None - elif isinstance(node.op, ast.LShift): - return left << right - elif isinstance(node.op, ast.RShift): - return left >> right - elif isinstance(node.op, ast.BitOr): - return left | right - elif isinstance(node.op, ast.BitAnd): - return left & right - elif isinstance(node.op, ast.BitXor): - return left ^ right - elif isinstance(node.op, ast.Pow): - return left ** right - return None - if isinstance(node, ast.UnaryOp): - operand = CTypeInfo.TryEvalConstExpr(node.operand, SymbolTable) - if operand is None: - return None - if isinstance(node.op, ast.USub): - return -operand - elif isinstance(node.op, ast.UAdd): - return +operand - elif isinstance(node.op, ast.Invert): - return ~operand - return None - if isinstance(node, ast.Name): - if node.id in SymbolTable: - info = SymbolTable[node.id] - if getattr(info, 'IsDefine', None) and isinstance(getattr(info, 'DefineValue', None), int): - return info.DefineValue - if isinstance(node, ast.Attribute): - parts = [] - current = node - while isinstance(current, ast.Attribute): - parts.append(current.attr) - current = current.value - if isinstance(current, ast.Name): - parts.append(current.id) - parts.reverse() - attr_name = parts[-1] - possible_keys = [attr_name, '.'.join(parts)] - for key in possible_keys: - if key in SymbolTable: - info = SymbolTable[key] - if getattr(info, 'IsDefine', None) and isinstance(getattr(info, 'DefineValue', None), int): - return info.DefineValue - if len(parts) >= 2: - for mod_key, mod_info in SymbolTable.items(): - if getattr(mod_info, 'IsDefine', None) and isinstance(getattr(mod_info, 'DefineValue', None), int): - if mod_key.endswith('.' + attr_name) or mod_key == attr_name: - return mod_info.DefineValue - return None + from lib.core.ConstEvaluator import ConstEvaluator + return ConstEvaluator.eval_with_symtab(node, SymbolTable) @classmethod def FromNode(cls, Node: ast.AST, SymbolTable: dict) -> "CTypeInfo": @@ -1136,10 +1070,6 @@ class CTypeInfo: NewInfo._ts.original_type = NewInfo._ts.original_type.Copy() if NewInfo._ts.array_ptr: NewInfo._ts.array_ptr = NewInfo._ts.array_ptr.Copy() - # 实例上的动态属性也需要拷贝(如 IsSigned 等) - for key, val in self.__dict__.items(): - if key not in ('_ts', '_sm'): - object.__setattr__(NewInfo, key, val) return NewInfo def get(self, key, default=None): diff --git a/lib/core/Handles/HandlesDelete.py b/lib/core/Handles/HandlesDelete.py index 243733b..b9a2218 100644 --- a/lib/core/Handles/HandlesDelete.py +++ b/lib/core/Handles/HandlesDelete.py @@ -40,7 +40,7 @@ class DeleteHandle(BaseHandle): if ClassName: PropKey = f'{ClassName}.{AttrName}' PropInfo = self.Trans.SymbolTable.get(PropKey) - if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: SelfVar = Gen._get_var_ptr('self') if SelfVar: SelfPtr = Gen._load(SelfVar, name="self") @@ -54,7 +54,7 @@ class DeleteHandle(BaseHandle): if ClassName: PropKey = f'{ClassName}.{AttrName}' PropInfo = self.Trans.SymbolTable.get(PropKey) - if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_DELETER in PropInfo.MetaList: obj_val = self.Trans.ExprHandler.HandleExprLlvm(target.value) if obj_val: DeleterFunc = Gen._get_function(PropKey + '$del') diff --git a/lib/core/Handles/HandlesExpr.py b/lib/core/Handles/HandlesExpr.py index dbf117c..9335983 100644 --- a/lib/core/Handles/HandlesExpr.py +++ b/lib/core/Handles/HandlesExpr.py @@ -329,7 +329,7 @@ class ExprHandle(BaseHandle): if VarName not in getattr(Gen, '_define_constants', {}): try: sym_info = self.translator.SymbolTable.get(VarName) - if sym_info and getattr(sym_info, 'IsDefine', None) and getattr(sym_info, 'DefineValue', None) is not None: + if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None: val = sym_info.DefineValue if isinstance(val, int): # Use VarType hint if available @@ -400,9 +400,9 @@ class ExprHandle(BaseHandle): return ir.Constant(ir.IntType(32), 1 if VarName == 'True' else 0) if VarName in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[VarName] - if getattr(SymInfo, 'IsEnumMember', None) and isinstance(getattr(SymInfo, 'value', None), int): + if SymInfo.IsEnumMember and isinstance(SymInfo.value, int): return ir.Constant(ir.IntType(32), SymInfo.value) - if getattr(SymInfo, 'IsFunction', False) or getattr(SymInfo, 'IsFuncPtr', False): + if SymInfo.IsFunction or SymInfo.IsFuncPtr: MangledName = Gen._mangle_func_name(VarName) if MangledName in Gen.module.globals: g = Gen.module.globals[MangledName] diff --git a/lib/core/Handles/HandlesExprAttr.py b/lib/core/Handles/HandlesExprAttr.py index 2a29cce..53821ab 100644 --- a/lib/core/Handles/HandlesExprAttr.py +++ b/lib/core/Handles/HandlesExprAttr.py @@ -92,7 +92,7 @@ class ExprAttrHandle(BaseHandle): PossibleKeys.append(key) for lookup_key in PossibleKeys: SymInfo = self.Trans.SymbolTable.get(lookup_key) - if SymInfo and getattr(SymInfo, 'IsDefine', None) and getattr(SymInfo, 'DefineValue', None) is not None: + if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None: return self._make_define_constant(Gen, SymInfo.DefineValue) # 也检查 _define_constants define_constants = getattr(Gen, '_define_constants', {}) @@ -202,7 +202,7 @@ class ExprAttrHandle(BaseHandle): # 检查 property getter PropKey = f'{ClassName}.{Node.attr}' PropInfo = self.Trans.SymbolTable.get(PropKey) - if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: SelfVar = Gen._get_var_ptr('self') if SelfVar: SelfPtr = Gen._load(SelfVar, name="self") @@ -234,16 +234,16 @@ class ExprAttrHandle(BaseHandle): def _handle_attr_enum(self, Node, VarName): """处理枚举成员访问 (VarName 是枚举类型名)""" SymInfo = self.Trans.SymbolTable.get(VarName) - if not SymInfo or not getattr(SymInfo, 'IsEnum', None): + if not SymInfo or not SymInfo.IsEnum: return None if Node.attr in self.Trans.SymbolTable: MemberInfo = self.Trans.SymbolTable[Node.attr] - if getattr(MemberInfo, 'IsEnumMember', None) and getattr(MemberInfo, 'EnumName', None) == VarName: - if isinstance(getattr(MemberInfo, 'value', None), int): + if MemberInfo.IsEnumMember and MemberInfo.EnumName == VarName: + if isinstance(MemberInfo.value, int): return ir.Constant(ir.IntType(32), MemberInfo.value) for key, info in self.Trans.SymbolTable.items(): - if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == VarName and key == Node.attr: - if isinstance(getattr(info, 'value', None), int): + if info.IsEnumMember and info.EnumName == VarName and key == Node.attr: + if isinstance(info.value, int): return ir.Constant(ir.IntType(32), info.value) return None @@ -285,7 +285,7 @@ class ExprAttrHandle(BaseHandle): # 检查 property getter PropKey = f'{ClassName}.{AttrName}' PropInfo = self.Trans.SymbolTable.get(PropKey) - if PropInfo and hasattr(PropInfo, 'MetaList') and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: + if PropInfo and PropInfo.MetaList and FuncMeta.PROPERTY_GETTER in PropInfo.MetaList: ObjVal = self.HandleExprLlvm(Node.value) GetterFunc = Gen._get_function(PropKey) if GetterFunc and ObjVal: @@ -297,7 +297,7 @@ class ExprAttrHandle(BaseHandle): TypeInfo = self.Trans.SymbolTable.get(ClassName) IsUnion = TypeInfo.IsUnion if TypeInfo else False IsCenum = TypeInfo.IsEnum if TypeInfo else False - IsRenum = getattr(TypeInfo, 'IsRenum', False) if TypeInfo else False + IsRenum = TypeInfo.IsRenum if TypeInfo else False # REnum 处理 if IsRenum: @@ -322,12 +322,12 @@ class ExprAttrHandle(BaseHandle): for qname in (f"{ClassName}.{AttrName}", f"{ClassName}_{AttrName}"): if qname in self.Trans.SymbolTable: info = self.Trans.SymbolTable[qname] - if getattr(info, 'IsEnumMember', None) and isinstance(getattr(info, 'value', None), int): + if info.IsEnumMember and isinstance(info.value, int): return ir.Constant(ir.IntType(32), info.value) for key, info in self.Trans.SymbolTable.items(): if key == AttrName: - if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == ClassName: - if isinstance(getattr(info, 'value', None), int): + if info.IsEnumMember and info.EnumName == ClassName: + if isinstance(info.value, int): return ir.Constant(ir.IntType(32), info.value) break @@ -1062,7 +1062,7 @@ class ExprAttrHandle(BaseHandle): possible_keys.append(key) for lookup_key in possible_keys: SymInfo = self.Trans.SymbolTable.get(lookup_key) - if SymInfo and getattr(SymInfo, 'IsDefine', None) and getattr(SymInfo, 'DefineValue', None) is not None: + if SymInfo and SymInfo.IsDefine and SymInfo.DefineValue is not None: val = SymInfo.DefineValue if isinstance(val, int): if val > 0x7FFFFFFF or val < -0x80000000: @@ -1085,21 +1085,21 @@ class ExprAttrHandle(BaseHandle): for enum_key in enum_keys: if enum_key in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[enum_key] - if getattr(SymInfo, 'IsEnum', None): + if SymInfo.IsEnum: for qname in (f"{enum_key}.{member_name}", f"{enum_key}_{member_name}"): if qname in self.Trans.SymbolTable: info = self.Trans.SymbolTable[qname] - if getattr(info, 'IsEnumMember', None) and isinstance(getattr(info, 'value', None), int): + if info.IsEnumMember and isinstance(info.value, int): return ir.Constant(ir.IntType(32), info.value) for key, info in self.Trans.SymbolTable.items(): - if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == enum_key and key == member_name: - if isinstance(getattr(info, 'value', None), int): + if info.IsEnumMember and info.EnumName == enum_key and key == member_name: + if isinstance(info.value, int): return ir.Constant(ir.IntType(32), info.value) for key, info in self.Trans.SymbolTable.items(): - if getattr(info, 'IsEnumMember', None) and key == member_name: - if isinstance(getattr(info, 'value', None), int): + if info.IsEnumMember and key == member_name: + if isinstance(info.value, int): for enum_key in enum_keys: - if getattr(info, 'EnumName', None) == enum_key: + if info.EnumName == enum_key: return ir.Constant(ir.IntType(32), info.value) return None diff --git a/lib/core/Handles/HandlesExprBuiltin.py b/lib/core/Handles/HandlesExprBuiltin.py index 6b7c02c..c6e698f 100644 --- a/lib/core/Handles/HandlesExprBuiltin.py +++ b/lib/core/Handles/HandlesExprBuiltin.py @@ -539,7 +539,7 @@ class ExprBuiltinHandle(BaseHandle): LastPart = arg.attr if LastPart in self.Trans.SymbolTable: AttrInfo = self.Trans.SymbolTable[LastPart] - if getattr(AttrInfo, 'IsEnumMember', None) and getattr(AttrInfo, 'EnumName', None): + if AttrInfo.IsEnumMember and AttrInfo.EnumName: enum_type_name = AttrInfo.EnumName elif isinstance(arg.value, ast.Attribute): attr_path = _get_attr_path(arg) @@ -554,14 +554,14 @@ class ExprBuiltinHandle(BaseHandle): for qname in (qualified_name_dot, qualified_name_under): if qname in self.Trans.SymbolTable: info = self.Trans.SymbolTable[qname] - if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == enum_class_name: + if info.IsEnumMember and info.EnumName == enum_class_name: enum_member_found = info break if not enum_member_found: for key in self.Trans.SymbolTable: if key == LastPart: info = self.Trans.SymbolTable[key] - if getattr(info, 'IsEnumMember', None) and getattr(info, 'EnumName', None) == enum_class_name: + if info.IsEnumMember and info.EnumName == enum_class_name: enum_member_found = info break if enum_member_found: diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index c4d3913..46987d3 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -435,7 +435,7 @@ class ExprCallHandle(BaseHandle): if first_part in aliases: ModulePath = aliases[first_part] + ModulePath[len(first_part):] is_instance_var = isinstance(Node.func.value, ast.Name) and Node.func.value.id in Gen.var_struct_class and Node.func.value.id not in Gen.ModuleSha1Map - is_class_name = isinstance(Node.func.value, ast.Name) and (Node.func.value.id in Gen.structs or (Node.func.value.id in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[Node.func.value.id], 'IsStruct', False))) + is_class_name = isinstance(Node.func.value, ast.Name) and (Node.func.value.id in Gen.structs or (Node.func.value.id in self.Trans.SymbolTable and self.Trans.SymbolTable[Node.func.value.id].IsStruct)) if is_instance_var and not is_class_name: return self._HandleMethodCallLlvm(Node) FuncAttr = Node.func.attr @@ -454,11 +454,11 @@ class ExprCallHandle(BaseHandle): result = self._HandleClassNewLlvm(Node, FuncAttr) if result is not None: return result - if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None): + if SymInfo.IsEnumMember and SymInfo.EnumName: EnumName = SymInfo.EnumName if EnumName in self.Trans.SymbolTable: EnumInfo = self.Trans.SymbolTable[EnumName] - if getattr(EnumInfo, 'IsRenum', False): + if EnumInfo.IsRenum: result = self._HandleREnumConstructLlvm(Node, EnumName, FuncAttr, SymInfo.value) if result is not None: return result @@ -480,9 +480,9 @@ class ExprCallHandle(BaseHandle): FullAttrKey = f"{ModulePath}.{FuncAttr}" if FullAttrKey in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[FullAttrKey] - if getattr(SymInfo, 'IsTypedef', False): + if SymInfo.IsTypedef: return ir.Constant(ir.IntType(32), 0) - if getattr(SymInfo, 'IsStruct', False): + if SymInfo.IsStruct: if FuncAttr not in Gen.structs: self._ensure_struct_declared(FuncAttr) if FuncAttr in Gen.structs: @@ -533,7 +533,7 @@ class ExprCallHandle(BaseHandle): raise Exception(f"Undefined method: 't.{FuncAttr}'") if isinstance(Node.func.value, ast.Attribute): inner_attr = Node.func.value.attr - if inner_attr in Gen.structs or (inner_attr in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[inner_attr], 'IsStruct', False)): + if inner_attr in Gen.structs or (inner_attr in self.Trans.SymbolTable and self.Trans.SymbolTable[inner_attr].IsStruct): static_result = self._HandleStaticMethodCallLlvm(Node, inner_attr, FuncAttr) if static_result is not None: return static_result @@ -569,11 +569,11 @@ class ExprCallHandle(BaseHandle): if FuncAttr and ModulePath and ModulePath not in {'t', 'c'}: # 先检查 FuncAttr 是否是函数/变量,如果是则跳过 struct 声明 _attr_sym = self.Trans.SymbolTable.get(FuncAttr) - _is_func_or_var = _attr_sym and (getattr(_attr_sym, 'IsFunction', False) or getattr(_attr_sym, 'IsVariable', False)) + _is_func_or_var = _attr_sym and (_attr_sym.IsFunction or _attr_sym.IsVariable) if not _is_func_or_var and ModulePath: _full_key = f"{ModulePath}.{FuncAttr}" _full_sym = self.Trans.SymbolTable.get(_full_key) - if _full_sym and (getattr(_full_sym, 'IsFunction', False) or getattr(_full_sym, 'IsVariable', False)): + if _full_sym and (_full_sym.IsFunction or _full_sym.IsVariable): _is_func_or_var = True # 优先检查 FuncAttr 是否为 struct/类构造器 if not _is_func_or_var and FuncAttr not in Gen.structs: @@ -587,7 +587,7 @@ class ExprCallHandle(BaseHandle): FullAttrKey = f"{ModulePath}.{FuncAttr}" if FullAttrKey in self.Trans.SymbolTable: FullSymInfo = self.Trans.SymbolTable[FullAttrKey] - if getattr(FullSymInfo, 'IsStruct', False) or getattr(FullSymInfo, 'IsCpythonObject', False): + if FullSymInfo.IsStruct or FullSymInfo.IsCpythonObject: if FuncAttr not in Gen.structs: self._ensure_struct_declared(FuncAttr) if FuncAttr in Gen.structs: @@ -649,7 +649,7 @@ class ExprCallHandle(BaseHandle): Gen = self.Trans.LlvmGen # 如果名称是函数或变量,不应创建 struct SymInfo = self.Trans.SymbolTable.get(class_name) - if SymInfo and (getattr(SymInfo, 'IsFunction', False) or getattr(SymInfo, 'IsVariable', False)): + if SymInfo and (SymInfo.IsFunction or SymInfo.IsVariable): return if class_name in Gen.structs: existing = Gen.structs[class_name] @@ -721,16 +721,16 @@ class ExprCallHandle(BaseHandle): SymKey = f'{ClassName}.{MethodName}' SymInfo = self.Trans.SymbolTable.get(SymKey) or self.Trans.SymbolTable.get(MethodName) if SymInfo and SymInfo.IsFunction: - ret_type_info = getattr(SymInfo, 'FuncPtrReturn', None) + ret_type_info = SymInfo.FuncPtrReturn if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: ret_type = ret_type_info.ToLLVM(Gen) else: ret_type = Gen._CType2LLVM('i32', False) - param_type_infos = [pt for _, pt in (getattr(SymInfo, 'FuncPtrParams', None) or [])] + param_type_infos = [pt for _, pt in (SymInfo.FuncPtrParams or [])] if isinstance(ret_type, ir.VoidType): ret_type = ir.IntType(32) llvm_param_types = [] - is_static = hasattr(SymInfo, 'MetaList') and FuncMeta.STATIC_METHOD in SymInfo.MetaList + is_static = FuncMeta.STATIC_METHOD in SymInfo.MetaList if ClassName in Gen.structs and not is_static: llvm_param_types.append(ir.PointerType(Gen.structs[ClassName])) for pt in param_type_infos: @@ -762,8 +762,8 @@ class ExprCallHandle(BaseHandle): CallArgs = [] SymKey = f'{ClassName}.{MethodName}' SymInfo = self.Trans.SymbolTable.get(SymKey) or self.Trans.SymbolTable.get(MethodName) - is_static_call = SymInfo is not None and hasattr(SymInfo, 'MetaList') and FuncMeta.STATIC_METHOD in SymInfo.MetaList - is_classmethod_call = SymInfo is not None and hasattr(SymInfo, 'MetaList') and FuncMeta.CLASS_METHOD in SymInfo.MetaList + is_static_call = SymInfo is not None and FuncMeta.STATIC_METHOD in SymInfo.MetaList + is_classmethod_call = SymInfo is not None and FuncMeta.CLASS_METHOD in SymInfo.MetaList # @classmethod: 在参数列表前插入 cls(栈上分配的类实例指针) if is_classmethod_call and ClassName in Gen.structs: ClsPtr = Gen._alloca(Gen.structs[ClassName], name=f"cls_{ClassName}") @@ -1230,13 +1230,13 @@ class ExprCallHandle(BaseHandle): mangled_name = Gen._mangle_func_name(func_name, ModulePath) sym_key = f'{ModulePath}.{func_name}' sym_info = self.Trans.SymbolTable.get(sym_key) or self.Trans.SymbolTable.get(func_name) - is_inline = sym_info and (getattr(sym_info, 'IsInline', False) or isinstance(getattr(sym_info, 'Storage', None), t.CInline)) - if is_inline and getattr(sym_info, 'InlineBody', None): + is_inline = sym_info and (sym_info.IsInline or isinstance(sym_info.Storage, t.CInline)) + if is_inline and sym_info.InlineBody: self._HandleInlineExpandLlvm(Node, sym_info) return ir.Constant(ir.IntType(32), 1) sym_info_exact = self.Trans.SymbolTable.get(sym_key) if sym_info_exact: - exact_params = getattr(sym_info_exact, 'FuncPtrParams', []) + exact_params = sym_info_exact.FuncPtrParams exact_param_names = [pn for pn, _ in exact_params] if exact_param_names: provided = len(Node.args) @@ -1280,15 +1280,15 @@ class ExprCallHandle(BaseHandle): if not sym_info: sym_info = self.Trans.SymbolTable.get(func_name) if sym_info: - is_func = getattr(sym_info, 'IsFunction', False) - sym_is_variadic = getattr(sym_info, 'IsVariadic', False) + is_func = sym_info.IsFunction + sym_is_variadic = sym_info.IsVariadic if is_func: - ret_type_info = getattr(sym_info, 'FuncPtrReturn', None) + ret_type_info = sym_info.FuncPtrReturn if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: ret_type = ret_type_info.ToLLVM(Gen) else: ret_type = Gen._CType2LLVM('i32', False) - sym_params = getattr(sym_info, 'FuncPtrParams', []) + sym_params = sym_info.FuncPtrParams param_type_infos = [pt for _, pt in sym_params] if isinstance(ret_type, ir.VoidType): ret_type = ir.IntType(32) @@ -1411,15 +1411,15 @@ class ExprCallHandle(BaseHandle): if not sym_info: sym_info = self.Trans.SymbolTable.get(func_name) if sym_info: - is_func = getattr(sym_info, 'IsFunction', False) - sym_is_variadic = getattr(sym_info, 'IsVariadic', False) + is_func = sym_info.IsFunction + sym_is_variadic = sym_info.IsVariadic if is_func: - ret_type_info = getattr(sym_info, 'FuncPtrReturn', None) + ret_type_info = sym_info.FuncPtrReturn if isinstance(ret_type_info, CTypeInfo) and ret_type_info.BaseType: ret_type = ret_type_info.ToLLVM(Gen) else: ret_type = Gen._CType2LLVM('i32', False) - param_type_infos = [pt for _, pt in getattr(sym_info, 'FuncPtrParams', [])] + param_type_infos = [pt for _, pt in sym_info.FuncPtrParams] if isinstance(ret_type, ir.VoidType): ret_type = ir.IntType(32) llvm_param_types = [] @@ -1830,7 +1830,7 @@ class ExprCallHandle(BaseHandle): if ClassName: SymKey = f'{ClassName}.{MethodName}' SymInfo = self.Trans.SymbolTable.get(SymKey) - if SymInfo and hasattr(SymInfo, 'MetaList'): + if SymInfo and SymInfo.MetaList: if FuncMeta.STATIC_METHOD in SymInfo.MetaList: return self._HandleStaticMethodCallLlvm(Node, ClassName, MethodName) if FuncMeta.CLASS_METHOD in SymInfo.MetaList: diff --git a/lib/core/Handles/HandlesIf.py b/lib/core/Handles/HandlesIf.py index 3329eb7..b5ac138 100644 --- a/lib/core/Handles/HandlesIf.py +++ b/lib/core/Handles/HandlesIf.py @@ -73,7 +73,7 @@ class IfHandle(BaseHandle): return True if name in self.Trans.SymbolTable: info = self.Trans.SymbolTable[name] - if getattr(info, 'IsDefine', False): + if info.IsDefine: return True platform_macros = self._get_platform_macros() return name in platform_macros @@ -86,8 +86,8 @@ class IfHandle(BaseHandle): return val if name in self.Trans.SymbolTable: info = self.Trans.SymbolTable[name] - if getattr(info, 'IsDefine', False): - val = getattr(info, 'DefineValue', 0) + if info.IsDefine: + val = info.DefineValue if isinstance(val, (int, float)): return val platform_macros = self._get_platform_macros() @@ -129,118 +129,21 @@ class IfHandle(BaseHandle): return macros def _eval_const_expr(self, node): - if isinstance(node, ast.Constant): - val = node.value - if isinstance(val, bool): - return 1 if val else 0 - if isinstance(val, int): - return val - if isinstance(val, float): - return 1 if val != 0.0 else 0 - return 0 - if isinstance(node, ast.Name): - name = node.id - val = self._get_macro_value(name) - if val is not None: - return val - return None - if isinstance(node, ast.Attribute): - full_key = self._get_attr_full_name(node) - if full_key: - val = self._get_macro_value(full_key) - if val is not None: - return val - short_name = full_key.split('.')[-1] if '.' in full_key else full_key - val = self._get_macro_value(short_name) - if val is not None: - return val - return None - if isinstance(node, ast.UnaryOp): - operand = self._eval_const_expr(node.operand) - if operand is None: - return None - if isinstance(node.op, ast.Not): - return 1 if not operand else 0 - if isinstance(node.op, ast.USub): - return -operand - if isinstance(node.op, ast.Invert): - return ~operand - return None - if isinstance(node, ast.BinOp): - left = self._eval_const_expr(node.left) - right = self._eval_const_expr(node.right) - if left is None or right is None: - return None - try: - if isinstance(node.op, ast.Add): - return left + right - elif isinstance(node.op, ast.Sub): - return left - right - elif isinstance(node.op, ast.Mult): - return left * right - elif isinstance(node.op, ast.FloorDiv): - return left // right if right != 0 else 0 - elif isinstance(node.op, ast.Mod): - return left % right if right != 0 else 0 - elif isinstance(node.op, ast.LShift): - return left << right - elif isinstance(node.op, ast.RShift): - return left >> right - elif isinstance(node.op, ast.BitOr): - return left | right - elif isinstance(node.op, ast.BitAnd): - return left & right - elif isinstance(node.op, ast.BitXor): - return left ^ right - except Exception: - return None - return None - if isinstance(node, ast.BoolOp): - if isinstance(node.op, ast.And): - for val in node.values: - result = self._eval_const_expr(val) - if result is None: - return None - if not result: - return 0 - return 1 - elif isinstance(node.op, ast.Or): - for val in node.values: - result = self._eval_const_expr(val) - if result is None: - return None - if result: - return 1 - return 0 - if isinstance(node, ast.Compare): - left = self._eval_const_expr(node.left) - if left is None: - return None - for op, comparator in zip(node.ops, node.comparators): - right = self._eval_const_expr(comparator) - if right is None: - return None - if isinstance(op, ast.Eq): - result = left == right - elif isinstance(op, ast.NotEq): - result = left != right - elif isinstance(op, ast.Lt): - result = left < right - elif isinstance(op, ast.LtE): - result = left <= right - elif isinstance(op, ast.Gt): - result = left > right - elif isinstance(op, ast.GtE): - result = left >= right - else: - return None - if not result: - return 0 - return 1 - if isinstance(node, ast.Call): - if self._is_cif_call(node): + from lib.core.ConstEvaluator import ConstEvaluator, EvalContext + Gen = self.Trans.LlvmGen + ctx = EvalContext(Gen=Gen, symtab=self.Trans.SymbolTable) + result = ConstEvaluator.eval_full(node, ctx) + if result is None: + # 保留 CIf 嵌套调用处理(HandlesIf 特有逻辑) + if isinstance(node, ast.Call) and self._is_cif_call(node): return self._evaluate_cif_condition(node) - return None + return None + # HandlesIf 需要 bool/float → int 转换(#if 条件编译语义) + if isinstance(result, bool): + return 1 if result else 0 + if isinstance(result, float): + return 1 if result != 0.0 else 0 + return result def _HandleIfLlvm(self, Node): Gen = self.Trans.LlvmGen diff --git a/lib/core/Handles/HandlesImports.py b/lib/core/Handles/HandlesImports.py index 86f5b61..332e41b 100644 --- a/lib/core/Handles/HandlesImports.py +++ b/lib/core/Handles/HandlesImports.py @@ -74,14 +74,14 @@ class ImportHandle(BaseHandle): if not asname or asname == name: # Check if this name is a CDefine constant in SymbolTable sym_info = self.Trans.SymbolTable.get(name) - if sym_info and getattr(sym_info, 'IsDefine', None) and getattr(sym_info, 'DefineValue', None) is not None: + if sym_info and sym_info.IsDefine and sym_info.DefineValue is not None: define_constants = vars(Gen).setdefault('_define_constants', {}) if name not in define_constants: define_constants[name] = sym_info.DefineValue # Also check with module prefix for prefix_key in [f"{module}.{name}", name]: sym_info2 = self.Trans.SymbolTable.get(prefix_key) - if sym_info2 and getattr(sym_info2, 'IsDefine', None) and getattr(sym_info2, 'DefineValue', None) is not None: + if sym_info2 and sym_info2.IsDefine and sym_info2.DefineValue is not None: define_constants = vars(Gen).setdefault('_define_constants', {}) if name not in define_constants: define_constants[name] = sym_info2.DefineValue @@ -893,7 +893,7 @@ class ImportHandle(BaseHandle): elif isinstance(value_node, ast.Name): if value_node.id in getattr(self.Trans, 'SymbolTable', {}): info = self.Trans.SymbolTable[value_node.id] - if getattr(info, 'IsDefine', None) and getattr(info, 'DefineValue', None) is not None: + if info.IsDefine and info.DefineValue is not None: return info.DefineValue elif isinstance(value_node, ast.Call): if isinstance(value_node.func, ast.Attribute): @@ -1020,7 +1020,7 @@ class ImportHandle(BaseHandle): ParamTypes = [] is_method = is_class_method or '.__' in FuncName class_name_for_method = FuncName.split('.')[0] if '.' in FuncName else None - class_is_cpython = class_name_for_method and class_name_for_method in self.Trans.SymbolTable and getattr(self.Trans.SymbolTable[class_name_for_method], 'IsCpythonObject', False) + class_is_cpython = class_name_for_method and class_name_for_method in self.Trans.SymbolTable and self.Trans.SymbolTable[class_name_for_method].IsCpythonObject for i, Arg in enumerate(Node.args.args): if i == 0 and is_method: # self parameter of a method should always be a pointer to the struct diff --git a/lib/core/Handles/HandlesMatch.py b/lib/core/Handles/HandlesMatch.py index f224008..c65f661 100644 --- a/lib/core/Handles/HandlesMatch.py +++ b/lib/core/Handles/HandlesMatch.py @@ -21,7 +21,7 @@ class MatchHandle(BaseHandle): VarName = Node.subject.id if VarName in self.Trans.SymbolTable: TypeInfo = self.Trans.SymbolTable[VarName] - if getattr(TypeInfo, 'IsRenum', False): + if TypeInfo.IsRenum: IsRenumMatch = True RenumName = TypeInfo.Name SubjectPtr = Gen._loadVar(VarName) @@ -37,11 +37,11 @@ class MatchHandle(BaseHandle): VariantName = cls_node.attr if VariantName and VariantName in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[VariantName] - if getattr(SymInfo, 'IsEnumMember', False) and getattr(SymInfo, 'EnumName', None): + if SymInfo.IsEnumMember and SymInfo.EnumName: EnumName = SymInfo.EnumName if EnumName in self.Trans.SymbolTable: EnumInfo = self.Trans.SymbolTable[EnumName] - if getattr(EnumInfo, 'IsRenum', False): + if EnumInfo.IsRenum: IsRenumMatch = True RenumName = EnumName if SubjectPtr is None: @@ -209,7 +209,7 @@ class MatchHandle(BaseHandle): TagValue = None if VariantName in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[VariantName] - if getattr(SymInfo, 'IsEnumMember', False): + if SymInfo.IsEnumMember: TagValue = SymInfo.value if TagValue is not None: CaseValues.append(ir.Constant(ir.IntType(32), TagValue)) diff --git a/lib/core/Handles/HandlesTypeMerge.py b/lib/core/Handles/HandlesTypeMerge.py index cf9f676..278e4d4 100644 --- a/lib/core/Handles/HandlesTypeMerge.py +++ b/lib/core/Handles/HandlesTypeMerge.py @@ -120,8 +120,8 @@ class HandlesTypeMerge(BaseHandle): # 也尝试在符号表中查找模块别名 if ModulePath in self.Trans.SymbolTable: entry = self.Trans.SymbolTable[ModulePath] - if isinstance(entry, CTypeInfo) and getattr(entry, 'IsModuleAlias', False): - resolved = getattr(entry, 'ResolvedModule', None) + if isinstance(entry, CTypeInfo) and entry.IsModuleAlias: + resolved = entry.ResolvedModule if resolved: ModulePath = resolved diff --git a/lib/core/Handles/HandlesWith.py b/lib/core/Handles/HandlesWith.py index 1b1fc34..f1d700b 100644 --- a/lib/core/Handles/HandlesWith.py +++ b/lib/core/Handles/HandlesWith.py @@ -25,7 +25,7 @@ class WithHandle(BaseHandle): if ClassName and ClassName not in Gen.structs: if ClassName in self.Trans.SymbolTable: SymInfo = self.Trans.SymbolTable[ClassName] - if getattr(SymInfo, 'IsStruct', False) or getattr(SymInfo, 'IsRenum', False): + if SymInfo.IsStruct or SymInfo.IsRenum: pass else: ClassName = None diff --git a/lib/core/LLVMCG/BaseGen.py b/lib/core/LLVMCG/BaseGen.py index 5c80522..6d7ef20 100644 --- a/lib/core/LLVMCG/BaseGen.py +++ b/lib/core/LLVMCG/BaseGen.py @@ -173,28 +173,28 @@ class BaseGenMixin: return ir.IntType(8) if hasattr(self, 'SymbolTable') and self.SymbolTable and clean_name in self.SymbolTable: Entry = self.SymbolTable[clean_name] - if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: + if Entry.IsTypedef: resolved_str = self._resolve_typedef(clean_name) if resolved_str != clean_name: return self._type_str_to_llvm(resolved_str) - if hasattr(Entry, 'BaseType') and Entry.BaseType: + if Entry.BaseType: from lib.includes import t as _t - if not isinstance(Entry.BaseType, (_t._CTypedef,)) or getattr(Entry, 'PtrCount', 0) > 0: + if not isinstance(Entry.BaseType, (_t._CTypedef,)) or Entry.PtrCount > 0: resolved = self._resolve_ctype_to_str(Entry) if resolved: return self._type_str_to_llvm(resolved) - if hasattr(Entry, 'IsRenum') and Entry.IsRenum: + if Entry.IsRenum: if clean_name in self.structs: return self.structs[clean_name] - if hasattr(Entry, 'IsEnum') and Entry.IsEnum: + if Entry.IsEnum: return ir.IntType(32) - if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: + if Entry.IsExceptionClass: return ir.IntType(32) - if hasattr(Entry, 'IsFunction') and Entry.IsFunction: + if Entry.IsFunction: return ir.PointerType(ir.IntType(8)) - if hasattr(Entry, 'IsVariable') and Entry.IsVariable: + if Entry.IsVariable: return ir.PointerType(ir.IntType(8)) - if hasattr(Entry, 'BaseType'): + if Entry.BaseType: from lib.includes import t as _t if isinstance(Entry.BaseType, type) and issubclass(Entry.BaseType, _t.CEnum): return ir.IntType(32) @@ -237,17 +237,17 @@ class BaseGenMixin: # 2. 再查 SymbolTable(用户定义的 typedef) if hasattr(self, 'SymbolTable') and self.SymbolTable and name in self.SymbolTable: Entry = self.SymbolTable[name] - if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: - if hasattr(Entry, 'BaseType') and Entry.BaseType: + if Entry.IsTypedef: + if Entry.BaseType: from lib.includes import t as _t - if not isinstance(Entry.BaseType, (_t._CTypedef,)) and getattr(Entry, 'PtrCount', 0) == 0: + if not isinstance(Entry.BaseType, (_t._CTypedef,)) and Entry.PtrCount == 0: llvm_str = CTypeRegistry.CTypeToLLVM(type(Entry.BaseType) if isinstance(Entry.BaseType, _t.CType) else Entry.BaseType) if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): return int(llvm_str[1:]) - if hasattr(Entry, 'OriginalType') and Entry.OriginalType: + if Entry.OriginalType: from lib.core.Handles.HandlesBase import CTypeInfo as _CTypeInfo if isinstance(Entry.OriginalType, _CTypeInfo) and Entry.OriginalType.BaseType: - if not isinstance(Entry.OriginalType.BaseType, (_t._CTypedef,)) and getattr(Entry.OriginalType, 'PtrCount', 0) == 0: + if not isinstance(Entry.OriginalType.BaseType, (_t._CTypedef,)) and Entry.OriginalType.PtrCount == 0: llvm_str = CTypeRegistry.CTypeToLLVM(type(Entry.OriginalType.BaseType) if isinstance(Entry.OriginalType.BaseType, _t.CType) else Entry.OriginalType.BaseType) if llvm_str and llvm_str.startswith('i') and llvm_str[1:].isdigit(): return int(llvm_str[1:]) diff --git a/lib/core/LLVMCG/StructGen.py b/lib/core/LLVMCG/StructGen.py index 2c0f089..ec6af62 100644 --- a/lib/core/LLVMCG/StructGen.py +++ b/lib/core/LLVMCG/StructGen.py @@ -207,13 +207,13 @@ class StructGenMixin: is_packed = ClassName in self.class_packed if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable: Entry = self.SymbolTable[ClassName] - if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: + if Entry.IsExceptionClass: continue - if hasattr(Entry, 'IsEnum') and Entry.IsEnum: - if not getattr(Entry, 'IsRenum', False): + if Entry.IsEnum: + if not Entry.IsRenum: continue - if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: - if hasattr(Entry, 'BaseType') and Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)): + if Entry.IsTypedef: + if Entry.BaseType and not isinstance(Entry.BaseType, (type(None),)): import lib.includes.t as _t if not isinstance(Entry.BaseType, (_t._CTypedef,)): continue @@ -304,10 +304,10 @@ class StructGenMixin: for ClassName in all_classes: if hasattr(self, 'SymbolTable') and self.SymbolTable and ClassName in self.SymbolTable: Entry = self.SymbolTable[ClassName] - if hasattr(Entry, 'IsExceptionClass') and Entry.IsExceptionClass: + if Entry.IsExceptionClass: continue - if hasattr(Entry, 'IsEnum') and Entry.IsEnum: - if not getattr(Entry, 'IsRenum', False): + if Entry.IsEnum: + if not Entry.IsRenum: continue existing_st = self.structs.get(ClassName) if isinstance(existing_st, ir.IdentifiedStructType) and existing_st.elements is not None and len(existing_st.elements) > 0: diff --git a/lib/core/LLVMCG/TypeConvert.py b/lib/core/LLVMCG/TypeConvert.py index ac64018..2e4b1a1 100644 --- a/lib/core/LLVMCG/TypeConvert.py +++ b/lib/core/LLVMCG/TypeConvert.py @@ -137,7 +137,7 @@ class TypeConvertMixin: if isinstance(BaseType, _t.CDefine): # Use 64-bit type if the define value exceeds 32-bit range - if type_info and hasattr(type_info, 'DefineValue') and isinstance(type_info.DefineValue, int): + if type_info and isinstance(type_info.DefineValue, int): if type_info.DefineValue < 0 or type_info.DefineValue > 0xFFFFFFFF: return ir.IntType(64) return ir.IntType(32) @@ -180,8 +180,8 @@ class TypeConvertMixin: if OriginalType: current = OriginalType continue - elif hasattr(Entry, 'IsTypedef') and Entry.IsTypedef: - if hasattr(Entry, 'OriginalType') and Entry.OriginalType: + elif Entry.IsTypedef: + if Entry.OriginalType: if isinstance(Entry.OriginalType, _CTypeInfo): if Entry.OriginalType.IsFuncPtr: return 'Callable' @@ -189,9 +189,9 @@ class TypeConvertMixin: elif isinstance(Entry.OriginalType, str): current = Entry.OriginalType continue - if hasattr(Entry, 'BaseType') and Entry.BaseType: + if Entry.BaseType: from lib.includes import t as _t - if not isinstance(Entry.BaseType, (_t._CTypedef,)) or getattr(Entry, 'PtrCount', 0) > 0: + if not isinstance(Entry.BaseType, (_t._CTypedef,)) or Entry.PtrCount > 0: resolved = self._resolve_ctype_to_str(Entry) if resolved and resolved != current: current = resolved @@ -396,24 +396,24 @@ class TypeConvertMixin: return basic_stripped if hasattr(self, 'SymbolTable') and self.SymbolTable and type_str in self.SymbolTable: _Entry = self.SymbolTable[type_str] - if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef: + if _Entry.IsTypedef: resolved_str = self._resolve_typedef(type_str) if resolved_str != type_str: return self._type_str_to_llvm(resolved_str, IsPtr) - if hasattr(_Entry, 'BaseType') and _Entry.BaseType: + if _Entry.BaseType: from lib.includes import t as _t - if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or getattr(_Entry, 'PtrCount', 0) > 0: + if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0: resolved = self._resolve_ctype_to_str(_Entry) if resolved: return self._type_str_to_llvm(resolved, IsPtr) - if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum: + if _Entry.IsRenum: if type_str in self.structs: return self.structs[type_str] - if hasattr(_Entry, 'IsEnum') and _Entry.IsEnum: + if _Entry.IsEnum: return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if hasattr(_Entry, 'IsExceptionClass') and _Entry.IsExceptionClass: + if _Entry.IsExceptionClass: return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if hasattr(_Entry, 'BaseType'): + if _Entry.BaseType: from lib.includes import t as _t if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) @@ -431,24 +431,24 @@ class TypeConvertMixin: return basic_last if hasattr(self, 'SymbolTable') and self.SymbolTable and LastPart in self.SymbolTable: _Entry = self.SymbolTable[LastPart] - if hasattr(_Entry, 'IsTypedef') and _Entry.IsTypedef: + if _Entry.IsTypedef: resolved_str = self._resolve_typedef(LastPart) if resolved_str != LastPart: return self._type_str_to_llvm(resolved_str, IsPtr) - if hasattr(_Entry, 'BaseType') and _Entry.BaseType: + if _Entry.BaseType: from lib.includes import t as _t - if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or getattr(_Entry, 'PtrCount', 0) > 0: + if not isinstance(_Entry.BaseType, (_t._CTypedef,)) or _Entry.PtrCount > 0: resolved = self._resolve_ctype_to_str(_Entry) if resolved: return self._type_str_to_llvm(resolved, IsPtr) - if hasattr(_Entry, 'IsRenum') and _Entry.IsRenum: + if _Entry.IsRenum: if LastPart in self.structs: return self.structs[LastPart] - if hasattr(_Entry, 'IsEnum') and _Entry.IsEnum: + if _Entry.IsEnum: return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if hasattr(_Entry, 'IsExceptionClass') and _Entry.IsExceptionClass: + if _Entry.IsExceptionClass: return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) - if hasattr(_Entry, 'BaseType'): + if _Entry.BaseType: from lib.includes import t as _t if (isinstance(_Entry.BaseType, type) and issubclass(_Entry.BaseType, _t.CEnum)) or _Entry.BaseType is _t.CEnum: return ir.IntType(32) if not IsPtr else ir.PointerType(ir.IntType(32)) diff --git a/lib/core/SymbolData.py b/lib/core/SymbolData.py new file mode 100644 index 0000000..21aa109 --- /dev/null +++ b/lib/core/SymbolData.py @@ -0,0 +1,79 @@ +"""符号表处理的数据结构:四阶段管线中传递的中间数据""" +from __future__ import annotations +from dataclasses import dataclass, field +from typing import Any, Dict, List, Optional, Tuple + + +@dataclass +class ClassSymbolData: + """从 AST 提取的类符号数据""" + name: str + type_kind: str # 'struct', 'union', 'enum', 'exception' + lineno: int + members: Dict[str, Any] + is_cpython_object: bool = False + is_packed: bool = False + enum_members: List[Tuple[str, int, int]] = field(default_factory=list) # (name, value, lineno) + + +@dataclass +class TypedefSymbolData: + """Typedef 符号数据(含原始注解和解析结果)""" + name: str + lineno: int + # 原始注解数据(由 Extractor 设置,Resolver 使用) + annotation: Any = None + value: Any = None + has_cdefine: bool = False + has_postdef: bool = False + has_ctypedef: bool = False + # 解析结果(由 Resolver 设置,Inserter 使用) + original_type_kind: Optional[str] = None + original_class: Any = None + members: Optional[Dict] = None + + +@dataclass +class FuncSymbolData: + """函数符号数据(含原始注解和解析结果)""" + name: str + lineno: int + # 原始数据(由 Extractor 设置) + returns_node: Any = None + params: List = field(default_factory=list) # [(name, annotation_node), ...] + is_variadic: bool = False + is_inline: bool = False + # 解析结果(由 Resolver 设置) + ret_type: Any = None + param_types: List = field(default_factory=list) # [str, ...] + + +@dataclass +class DefineSymbolData: + """Define 符号数据(含原始值和解析结果)""" + name: str + lineno: int + # 原始数据(由 Extractor 设置) + value_node: Any = None + # 解析结果(由 Resolver 设置) + value: Any = None + + +@dataclass +class AnonymousTypeData: + """匿名类型数据""" + name: str + is_union: bool + members: Dict[str, Any] + lineno: int + + +@dataclass +class ModuleSymbols: + """从模块提取的完整符号数据,在四阶段管线中传递""" + file_path: str + classes: List[ClassSymbolData] = field(default_factory=list) + typedefs: List[TypedefSymbolData] = field(default_factory=list) + functions: List[FuncSymbolData] = field(default_factory=list) + defines: List[DefineSymbolData] = field(default_factory=list) + anonymous_types: Dict[str, AnonymousTypeData] = field(default_factory=dict) diff --git a/lib/core/SymbolExtractor.py b/lib/core/SymbolExtractor.py new file mode 100644 index 0000000..288f9d7 --- /dev/null +++ b/lib/core/SymbolExtractor.py @@ -0,0 +1,237 @@ +"""Pass 1: ASTSymbolExtractor — 从 AST 提取原始符号信息""" +from __future__ import annotations +import ast +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.SymbolTable import SymbolTable + +from lib.core.SymbolData import ( + ModuleSymbols, ClassSymbolData, TypedefSymbolData, + FuncSymbolData, DefineSymbolData, AnonymousTypeData +) +from lib.core.Handles.HandlesBase import CTypeInfo +from lib.includes import t +from lib.core.SymbolUtils import AnnotationContainsTType, CheckAnnotationHasCInline + + +class ASTSymbolExtractor: + """从 Python 源文件的 AST 中提取所有符号信息""" + + def __init__(self, symbol_table: SymbolTable): + self._symtab = symbol_table + + def extract(self, file_path: str) -> ModuleSymbols: + """提取文件中的所有符号信息""" + with open(file_path, 'r', encoding='utf-8') as f: + code = f.read() + tree = ast.parse(code) + + result = ModuleSymbols(file_path=file_path) + + # 第一步:收集所有类的成员和匿名类型 + class_members = {} + for node in tree.body: + if isinstance(node, ast.ClassDef): + members = {} + self._collect_members(node, members, result.anonymous_types) + class_members[node.name] = members + + # 第二步:从每个顶层节点提取符号信息 + for node in tree.body: + if isinstance(node, ast.ClassDef): + members_info = class_members.get(node.name, {}) + result.classes.append(self._extract_class(node, members_info)) + elif isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): + self._extract_ann_assign(node, result) + elif isinstance(node, ast.FunctionDef): + result.functions.append(self._extract_function(node)) + + return result + + # ------------------------------------------------------------------ + # 成员收集(递归处理嵌套匿名类) + # ------------------------------------------------------------------ + + def _collect_members(self, class_node, members, anonymous_types, prefix=''): + """递归收集类成员,包括嵌套匿名类型""" + for item in class_node.body: + if isinstance(item, ast.AnnAssign) and isinstance(item.target, ast.Name): + member_name = item.target.id + full_name = f'{prefix}{member_name}' if prefix else member_name + member_type = CTypeInfo.FromNode(item.annotation, self._symtab) + if member_type is None: + member_type = CTypeInfo() + member_type.BaseType = t.CInt() + is_ptr = member_type.IsPtr + if isinstance(item.annotation, ast.BinOp): + annotation_str = ast.dump(item.annotation) + if 'CPtr' in annotation_str: + is_ptr = True + members[full_name] = member_type.Copy() + + elif isinstance(item, ast.ClassDef): + is_anonymous = any( + any(AnnotationContainsTType(base, 'Anonymous') for base in item.bases) + ) if item.bases else False + + if is_anonymous: + is_union = any( + any(AnnotationContainsTType(base, 'CUnion') for base in item.bases) + ) + + nested_name = f'{prefix}{item.name}' if prefix else item.name + members[nested_name] = CTypeInfo() + members[nested_name].BaseType = f'union {item.name}' if is_union else f'struct {item.name}' + members[nested_name].PtrCount = 0 + members[nested_name].ArrayDims = [] + + new_prefix = f'{prefix}{item.name}.' if prefix else f'{item.name}.' + self._collect_members(item, members, anonymous_types, new_prefix) + + anonymous_members = {} + for full_name, member_info in members.items(): + if full_name.startswith(f"{nested_name}."): + member_name = full_name[len(nested_name) + 1:] + anonymous_members[member_name] = member_info + + if item.name not in anonymous_types: + anonymous_types[item.name] = AnonymousTypeData( + name=item.name, + is_union=is_union, + members=anonymous_members, + lineno=item.lineno + ) + + # ------------------------------------------------------------------ + # 类符号提取 + # ------------------------------------------------------------------ + + def _extract_class(self, node, members_info) -> ClassSymbolData: + """从 ClassDef 节点提取类符号数据""" + type_kind = 'struct' + is_cpython_object = False + is_packed = False + + # 检查装饰器 + if hasattr(node, 'decorator_list') and node.decorator_list: + for decorator in node.decorator_list: + if isinstance(decorator, ast.Attribute): + if (hasattr(decorator.value, 'id') and + decorator.value.id == 't' and + decorator.attr == 'Object'): + is_cpython_object = True + break + elif isinstance(decorator, ast.Call): + if isinstance(decorator.func, ast.Attribute): + if hasattr(decorator.func.value, 'id') and decorator.func.value.id == 'c' and decorator.func.attr == 'Attribute': + for arg in decorator.args: + if isinstance(arg, ast.Attribute): + if isinstance(arg.value, ast.Attribute): + if hasattr(arg.value.value, 'id') and arg.value.value.id == 't' and arg.value.attr == 'attr' and arg.attr == 'packed': + is_packed = True + + # 检查基类 + for base in node.bases: + if AnnotationContainsTType(base, 'CUnion'): + type_kind = 'union' + break + elif AnnotationContainsTType(base, 'CEnum'): + type_kind = 'enum' + break + elif AnnotationContainsTType(base, 'CStruct'): + type_kind = 'struct' + break + elif AnnotationContainsTType(base, 'Object'): + is_cpython_object = True + type_kind = 'struct' + break + elif isinstance(base, ast.Name) and base.id == 'Exception': + type_kind = 'exception' + break + elif isinstance(base, ast.Name): + base_entry = self._symtab.get(base.id) + if base_entry and base_entry.IsExceptionClass: + type_kind = 'exception' + break + + # 提取枚举成员 + enum_members = [] + if type_kind == 'enum': + next_enum_value = 0 + for item in node.body: + if isinstance(item, ast.Assign): + if len(item.targets) == 1 and isinstance(item.targets[0], ast.Name): + member_name = item.targets[0].id + if isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): + next_enum_value = item.value.value + 1 + else: + next_enum_value += 1 + enum_members.append((member_name, next_enum_value - 1, item.lineno)) + elif isinstance(item, ast.AnnAssign): + if isinstance(item.target, ast.Name): + member_name = item.target.id + if item.value: + if isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): + next_enum_value = item.value.value + 1 + else: + next_enum_value += 1 + else: + next_enum_value += 1 + enum_members.append((member_name, next_enum_value - 1, item.lineno)) + + return ClassSymbolData( + name=node.name, + type_kind=type_kind, + lineno=node.lineno, + members=members_info, + is_cpython_object=is_cpython_object, + is_packed=is_packed, + enum_members=enum_members, + ) + + # ------------------------------------------------------------------ + # AnnAssign 提取(typedef / define) + # ------------------------------------------------------------------ + + def _extract_ann_assign(self, node, result: ModuleSymbols): + """从 AnnAssign 节点提取 typedef 或 define 数据""" + var_name = node.target.id + has_cdefine = AnnotationContainsTType(node.annotation, 'CDefine') if node.annotation else False + has_postdef = AnnotationContainsTType(node.annotation, 'Postdefinition') if node.annotation else False + has_ctypedef = AnnotationContainsTType(node.annotation, 'CTypedef') if node.annotation else False + + if has_cdefine: + result.defines.append(DefineSymbolData( + name=var_name, + lineno=node.lineno, + value_node=node.value, + )) + else: + result.typedefs.append(TypedefSymbolData( + name=var_name, + lineno=node.lineno, + annotation=node.annotation, + value=node.value, + has_cdefine=has_cdefine, + has_postdef=has_postdef, + has_ctypedef=has_ctypedef, + )) + + # ------------------------------------------------------------------ + # 函数提取 + # ------------------------------------------------------------------ + + def _extract_function(self, node) -> FuncSymbolData: + """从 FunctionDef 节点提取函数符号数据""" + params = [(arg.arg, arg.annotation) for arg in node.args.args] + is_variadic = node.args.vararg is not None + is_inline = CheckAnnotationHasCInline(node.returns) + + return FuncSymbolData( + name=node.name, + lineno=node.lineno, + returns_node=node.returns, + params=params, + is_variadic=is_variadic, + is_inline=is_inline, + ) diff --git a/lib/core/SymbolInserter.py b/lib/core/SymbolInserter.py new file mode 100644 index 0000000..c1a1453 --- /dev/null +++ b/lib/core/SymbolInserter.py @@ -0,0 +1,68 @@ +"""Pass 3: SymbolInserter — 将解析后的符号插入 SymbolTable(主命名空间)""" +from __future__ import annotations +from typing import TYPE_CHECKING, List +if TYPE_CHECKING: + from lib.core.SymbolTable import SymbolTable + +from lib.core.SymbolData import ModuleSymbols + + +class SymbolInserter: + """将解析后的符号插入 SymbolTable 的主命名空间(无前缀)""" + + def __init__(self, symbol_table: SymbolTable): + self._symtab = symbol_table + + def insert(self, module_symbols: ModuleSymbols) -> List[str]: + """插入所有符号到主命名空间,返回已加载的符号名列表""" + loaded = [] + file_path = module_symbols.file_path + + # 插入类符号 + for cls in module_symbols.classes: + self._symtab._InsertClassSymbol( + cls.name, cls.type_kind, cls.lineno, file_path, + cls.members, cls.is_cpython_object, cls.is_packed + ) + loaded.append(cls.name) + + # 插入枚举成员(短名 + 类名.成员名) + if cls.type_kind == 'enum': + for member_name, _member_value, member_lineno in cls.enum_members: + self._symtab._InsertEnumMemberSymbol(member_name, cls.name, member_lineno, file_path) + loaded.append(member_name) + class_member_name = f"{cls.name}.{member_name}" + self._symtab._InsertEnumMemberSymbol(class_member_name, cls.name, member_lineno, file_path) + loaded.append(class_member_name) + + # 插入 typedef 符号 + for td in module_symbols.typedefs: + self._symtab._InsertTypedefSymbol( + td.name, td.original_type_kind, td.original_class, + td.lineno, file_path, td.members + ) + loaded.append(td.name) + + # 插入函数符号 + for func in module_symbols.functions: + self._symtab._InsertFuncSymbol( + func.name, func.ret_type, func.param_types, + func.lineno, file_path, func.is_variadic, func.is_inline + ) + loaded.append(func.name) + + # 插入 define 符号 + for define in module_symbols.defines: + self._symtab._InsertDefineSymbol( + define.name, define.value, define.lineno, file_path + ) + loaded.append(define.name) + + # 插入匿名类型符号(短名) + for anon_name, anon_data in module_symbols.anonymous_types.items(): + self._symtab._InsertAnonymousSymbol( + anon_name, anon_data.is_union, anon_data.members, + anon_data.lineno, file_path + ) + + return loaded diff --git a/lib/core/SymbolReexporter.py b/lib/core/SymbolReexporter.py new file mode 100644 index 0000000..5226c08 --- /dev/null +++ b/lib/core/SymbolReexporter.py @@ -0,0 +1,76 @@ +"""Pass 4: PackageReexporter — 将符号重新导出到命名空间前缀下""" +from __future__ import annotations +from typing import TYPE_CHECKING, List +if TYPE_CHECKING: + from lib.core.SymbolTable import SymbolTable + +from lib.core.SymbolData import ModuleSymbols + + +class PackageReexporter: + """将已解析的符号重新导出到命名空间前缀下(如 mpool.MPool)""" + + def __init__(self, symbol_table: SymbolTable): + self._symtab = symbol_table + + def reexport(self, module_symbols: ModuleSymbols, prefixes: List[str], lineno: int = 0) -> List[str]: + """将符号重新导出到所有命名空间前缀下,返回新增的符号名列表""" + loaded = [] + file_path = module_symbols.file_path + primary_prefix = prefixes[0] if prefixes else None + + for prefix in prefixes: + # 插入类符号(前缀.类名) + for cls in module_symbols.classes: + full_name = f"{prefix}.{cls.name}" + self._symtab._InsertClassSymbol( + full_name, cls.type_kind, cls.lineno, file_path, + cls.members, cls.is_cpython_object, cls.is_packed + ) + loaded.append(full_name) + + # 插入枚举成员(前缀.成员名) + if cls.type_kind == 'enum': + for member_name, _member_value, member_lineno in cls.enum_members: + full_member_name = f"{prefix}.{member_name}" + self._symtab._InsertEnumMemberSymbol(full_member_name, cls.name, member_lineno, file_path) + loaded.append(full_member_name) + + # 插入 typedef 符号(前缀.名称) + for td in module_symbols.typedefs: + full_name = f"{prefix}.{td.name}" + self._symtab._InsertTypedefSymbol( + full_name, td.original_type_kind, td.original_class, + td.lineno, file_path, td.members + ) + loaded.append(full_name) + + # 插入函数符号(前缀.名称) + for func in module_symbols.functions: + full_name = f"{prefix}.{func.name}" + self._symtab._InsertFuncSymbol( + full_name, func.ret_type, func.param_types, + func.lineno, file_path, func.is_variadic, func.is_inline + ) + loaded.append(full_name) + + # 插入 define 符号(前缀.名称) + for define in module_symbols.defines: + full_name = f"{prefix}.{define.name}" + self._symtab._InsertDefineSymbol( + full_name, define.value, define.lineno, file_path + ) + loaded.append(full_name) + + # 插入模块别名 + self._symtab._InsertModuleSymbol(prefix, lineno, file_path) + + # 插入匿名类型符号(前缀.名称) + for anon_name, anon_data in module_symbols.anonymous_types.items(): + full_type_name = f"{prefix}.{anon_name}" + self._symtab._InsertAnonymousSymbol( + full_type_name, anon_data.is_union, anon_data.members, + anon_data.lineno, file_path + ) + + return loaded diff --git a/lib/core/SymbolTable.py b/lib/core/SymbolTable.py index c6626c4..fc6f891 100644 --- a/lib/core/SymbolTable.py +++ b/lib/core/SymbolTable.py @@ -1,53 +1,24 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from lib.core.translator import Translator -from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper -from lib.includes import t -from typing import Any, Dict, Iterator -import ast -import re - -def _IsTModuleType(TypeName: str) -> bool: - """检测类型名称是否是 t 模块中的类型(CType 或其他特殊类型)""" - if TypeName in ('t', 'State', 'Bit', 'Anonymous', 'Postdefinition'): - return True - TypeClass = getattr(t, TypeName, None) - if TypeClass and isinstance(TypeClass, type): - if issubclass(TypeClass, t.CType): - return True - FallbackClass = getattr(t, f'_{TypeName}', None) - if FallbackClass and isinstance(FallbackClass, type): - if issubclass(FallbackClass, t.CType): - return True - return False - -def _AnnotationContainsTType(node, TypeName: str) -> bool: - """检测 AST 节点中是否包含指定名称的 t 模块类型""" - if isinstance(node, ast.Attribute): - if (hasattr(node.value, 'id') and node.value.id == 't' and - node.attr == TypeName): - return True - elif isinstance(node, ast.BinOp): - return _AnnotationContainsTType(node.left, TypeName) or _AnnotationContainsTType(node.right, TypeName) - elif isinstance(node, ast.Call): - if _AnnotationContainsTType(node.func, TypeName): - return True - for arg in node.args: - if _AnnotationContainsTType(arg, TypeName): - return True - elif isinstance(node, ast.Subscript): - if _AnnotationContainsTType(node.value, TypeName): - return True - if _AnnotationContainsTType(node.slice, TypeName): - return True - return False - - +from __future__ import annotations +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.translator import Translator +from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper +from lib.includes import t +from typing import Any, Dict, Iterator +import ast + +# 从 SymbolUtils 重导出,保持向后兼容 +from lib.core.SymbolUtils import IsTModuleType as _IsTModuleType +from lib.core.SymbolUtils import AnnotationContainsTType as _AnnotationContainsTType +from lib.core.SymbolUtils import CheckAnnotationHasCInline as _CheckAnnotationHasCInline + + class SymbolTable: def __init__(self, translator: "Translator"): self.translator = translator self._symbols: Dict[str, CTypeInfo] = {} + from lib.core.DiagnosticCollector import DiagnosticCollector + self.diagnostics = DiagnosticCollector() def clear(self): self._symbols.clear() @@ -204,731 +175,333 @@ class SymbolTable: if key not in skip_keys: info.set(key, value) - return info - - def LoadModuleSymbols(self, FullModulePath: str, asname: str, lineno: int = 0) -> list[str]: - return self._LoadSymbolsFromFile(FullModulePath, asname, lineno) - - def _LoadSymbolsFromFile(self, FilePath: str, namespace_prefix: str | list[str], lineno: int = 0) -> list[str]: - from lib.core.Handles.HandlesTypeMerge import HandlesTypeMerge - import ast - - LoadedSymbols = [] - - try: - with open(FilePath, 'r', encoding='utf-8') as f: - ModuleCode = f.read() - ModuleTree = ast.parse(ModuleCode) - - ClassMembers = {} - AnonymousTypes = {} - - for node in ModuleTree.body: - if isinstance(node, ast.ClassDef): - ClassName = node.name - MembersInfo = {} - - def CollectMembers(ClassNode, prefix=''): - for item in ClassNode.body: - if isinstance(item, ast.AnnAssign): - if isinstance(item.target, ast.Name): - MemberName = item.target.id - FullName = f'{prefix}{MemberName}' if prefix else MemberName - MemberTypeInfo = CTypeInfo.FromNode(item.annotation, self.translator.SymbolTable) - if MemberTypeInfo is None: - MemberTypeInfo = CTypeInfo() - MemberTypeInfo.BaseType = t.CInt() - IsPtr = MemberTypeInfo.IsPtr - if isinstance(item.annotation, ast.BinOp): - AnnotationStr = ast.dump(item.annotation) - if 'CPtr' in AnnotationStr: - IsPtr = True - MembersInfo[FullName] = MemberTypeInfo.Copy() - elif isinstance(item, ast.ClassDef): - IsAnonymous = any( - any(_AnnotationContainsTType(base, 'Anonymous') for base in item.bases) - ) if item.bases else False - - if IsAnonymous: - IsUnion = any( - any(_AnnotationContainsTType(base, 'CUnion') for base in item.bases) - ) - - NestedMemberName = f'{prefix}{item.name}' if prefix else item.name - MembersInfo[NestedMemberName] = CTypeInfo() - MembersInfo[NestedMemberName].BaseType = f'union {item.name}' if IsUnion else f'struct {item.name}' - MembersInfo[NestedMemberName].PtrCount = 0 - MembersInfo[NestedMemberName].ArrayDims = [] - - NewPrefix = f'{prefix}{item.name}.' if prefix else f'{item.name}.' - CollectMembers(item, NewPrefix) - - AnonymousMembers = {} - for FullName, MemberInfo in MembersInfo.items(): - if FullName.startswith(f"{NestedMemberName}."): - MemberName = FullName[len(NestedMemberName) + 1:] - AnonymousMembers[MemberName] = MemberInfo - - if item.name not in AnonymousTypes: - AnonymousTypes[item.name] = { - 'IsUnion': IsUnion, - 'members': AnonymousMembers, - 'lineno': item.lineno - } - - CollectMembers(node) - ClassMembers[ClassName] = MembersInfo - - LoadedSymbols = [] - - prefixes = [namespace_prefix] if isinstance(namespace_prefix, str) else namespace_prefix - - for prefix in prefixes: - for node in ModuleTree.body: - if isinstance(node, ast.ClassDef): - ClassName = node.name - MembersInfo = ClassMembers.get(ClassName, {}) - - TypeKind = 'struct' - IsCpythonObject = False - IsPacked = False - - if hasattr(node, 'decorator_list') and node.decorator_list: - for decorator in node.decorator_list: - if isinstance(decorator, ast.Attribute): - if (hasattr(decorator.value, 'id') and - decorator.value.id == 't' and - decorator.attr == 'Object'): - IsCpythonObject = True - break - elif isinstance(decorator, ast.Call): - if isinstance(decorator.func, ast.Attribute): - if hasattr(decorator.func.value, 'id') and decorator.func.value.id == 'c' and decorator.func.attr == 'Attribute': - for arg in decorator.args: - if isinstance(arg, ast.Attribute): - if isinstance(arg.value, ast.Attribute): - if hasattr(arg.value.value, 'id') and arg.value.value.id == 't' and arg.value.attr == 'attr' and arg.attr == 'packed': - IsPacked = True - - for base in node.bases: - if _AnnotationContainsTType(base, 'CUnion'): - TypeKind = 'union' - break - elif _AnnotationContainsTType(base, 'CEnum'): - TypeKind = 'enum' - break - elif _AnnotationContainsTType(base, 'CStruct'): - TypeKind = 'struct' - break - elif _AnnotationContainsTType(base, 'Object'): - IsCpythonObject = True - TypeKind = 'struct' - break - elif isinstance(base, ast.Name) and base.id == 'Exception': - TypeKind = 'exception' - break - elif isinstance(base, ast.Name): - base_entry = self.get(base.id) - if base_entry and hasattr(base_entry, 'IsExceptionClass') and base_entry.IsExceptionClass: - TypeKind = 'exception' - break - - if prefix == prefixes[0]: - self._InsertClassSymbol(ClassName, TypeKind, node.lineno, FilePath, MembersInfo, IsCpythonObject, IsPacked) - LoadedSymbols.append(ClassName) - - FullName = f"{prefix}.{ClassName}" - self._InsertClassSymbol(FullName, TypeKind, node.lineno, FilePath, MembersInfo, IsCpythonObject, IsPacked) - LoadedSymbols.append(FullName) - - if TypeKind == 'enum': - next_enum_value = 0 - for item in node.body: - if isinstance(item, ast.Assign): - if len(item.targets) == 1 and isinstance(item.targets[0], ast.Name): - MemberName = item.targets[0].id - if isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): - next_enum_value = item.value.value + 1 - else: - next_enum_value += 1 - if prefix == prefixes[0]: - self._InsertEnumMemberSymbol(MemberName, ClassName, item.lineno, FilePath) - LoadedSymbols.append(MemberName) - ClassMemberName = f"{ClassName}.{MemberName}" - self._InsertEnumMemberSymbol(ClassMemberName, ClassName, item.lineno, FilePath) - LoadedSymbols.append(ClassMemberName) - FullMemberName = f"{prefix}.{MemberName}" - self._InsertEnumMemberSymbol(FullMemberName, ClassName, item.lineno, FilePath) - LoadedSymbols.append(FullMemberName) - elif isinstance(item, ast.AnnAssign): - if isinstance(item.target, ast.Name): - MemberName = item.target.id - if item.value: - if isinstance(item.value, ast.Constant) and isinstance(item.value.value, int): - next_enum_value = item.value.value + 1 - else: - next_enum_value += 1 - else: - next_enum_value += 1 - if prefix == prefixes[0]: - self._InsertEnumMemberSymbol(MemberName, ClassName, item.lineno, FilePath) - LoadedSymbols.append(MemberName) - ClassMemberName = f"{ClassName}.{MemberName}" - self._InsertEnumMemberSymbol(ClassMemberName, ClassName, item.lineno, FilePath) - LoadedSymbols.append(ClassMemberName) - FullMemberName = f"{prefix}.{MemberName}" - self._InsertEnumMemberSymbol(FullMemberName, ClassName, item.lineno, FilePath) - LoadedSymbols.append(FullMemberName) - - elif isinstance(node, ast.AnnAssign): - if isinstance(node.target, ast.Name): - VarName = node.target.id - HasCDefine = _AnnotationContainsTType(node.annotation, 'CDefine') if node.annotation else False - HasPostdef = _AnnotationContainsTType(node.annotation, 'Postdefinition') if node.annotation else False - HasCtypedef = _AnnotationContainsTType(node.annotation, 'CTypedef') if node.annotation else False - IsPostdefWithTypedef = HasPostdef and HasCtypedef - - if HasCDefine: - DefineValue = None - if node.value: - DefineValue = self._eval_const_expr(node.value) - if prefix == prefixes[0]: - self._InsertDefineSymbol(VarName, DefineValue, node.lineno, FilePath) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertDefineSymbol(FullName, DefineValue, node.lineno, FilePath) - LoadedSymbols.append(FullName) - continue - - def FindBaseType(n): - if isinstance(n, ast.Attribute): - if hasattr(n.value, 'id') and n.value.id == 't': - if n.attr == 'CPtr': - return 'ptr' - return n.attr - elif isinstance(n, ast.Subscript): - if isinstance(n.value, ast.Attribute) and isinstance(n.value.value, ast.Name) and n.value.value.id == 't' and n.value.attr == 'Callable': - return 'Callable' - elif isinstance(n, ast.BinOp) and isinstance(n.op, ast.BitOr): - LeftResult = FindBaseType(n.left) - if LeftResult == 'ptr': - RightResult = FindBaseType(n.right) - return (RightResult if RightResult and RightResult != 'ptr' else 'void') + ' *' - if LeftResult == 'Callable': - return 'Callable' - RightResult = FindBaseType(n.right) - if RightResult == 'ptr': - return (LeftResult if LeftResult and LeftResult != 'ptr' else 'void') + ' *' - if RightResult == 'Callable': - return 'Callable' - if LeftResult: - return LeftResult - if RightResult: - return RightResult - return None - - if IsPostdefWithTypedef: - def FindPostdefArg(n): - if isinstance(n, ast.Call): - if isinstance(n.func, ast.Attribute): - if hasattr(n.func.value, 'id') and n.func.value.id == 't' and n.func.attr == 'Postdefinition': - if n.args and isinstance(n.args[0], ast.Name): - return n.args[0].id - elif isinstance(n, ast.BinOp) and isinstance(n.op, ast.BitOr): - LeftResult = FindPostdefArg(n.left) - if LeftResult: - return LeftResult - RightResult = FindPostdefArg(n.right) - if RightResult: - return RightResult - return None - - OriginalClass = FindPostdefArg(node.annotation) - if OriginalClass and OriginalClass in ClassMembers: - MembersInfo = ClassMembers[OriginalClass] - OriginalType_kind = 'struct' - if OriginalClass in self: - OrigTypeInfo = self[OriginalClass] - if OrigTypeInfo.type_cls in (t.CStruct, t.CEnum, t.CUnion): - if OrigTypeInfo.type_cls is t.CStruct: - OriginalType_kind = 'struct' - elif OrigTypeInfo.type_cls is t.CEnum: - OriginalType_kind = 'enum' - elif OrigTypeInfo.type_cls is t.CUnion: - OriginalType_kind = 'union' - - if prefix == prefixes[0]: - self._InsertTypedefSymbol(VarName, OriginalType_kind, OriginalClass, node.lineno, FilePath, MembersInfo) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertTypedefSymbol(FullName, OriginalType_kind, OriginalClass, node.lineno, FilePath, MembersInfo) - LoadedSymbols.append(FullName) - else: - if prefix == prefixes[0]: - self._InsertTypedefSymbol(VarName, None, None, node.lineno, FilePath) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertTypedefSymbol(FullName, None, None, node.lineno, FilePath) - LoadedSymbols.append(FullName) - elif HasCtypedef: - BaseTypeName = FindBaseType(node.annotation) - _TYPE_QUALIFIERS = {'CTypedef', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern', 'CDefine', 'CPostdefinition'} - if BaseTypeName == 'Callable': - OriginalType = CTypeInfo() - OriginalType.IsFuncPtr = True - OriginalType.FuncPtrReturn = CTypeInfo.VoidTypeInfo() - OriginalType.FuncPtrParams = [] - if prefix == prefixes[0]: - self._InsertTypedefSymbol(VarName, 'typedef', OriginalType, node.lineno, FilePath) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertTypedefSymbol(FullName, 'typedef', OriginalType, node.lineno, FilePath) - LoadedSymbols.append(FullName) - continue - elif BaseTypeName and BaseTypeName not in _TYPE_QUALIFIERS: - CName = CTypeHelper.GetCName(BaseTypeName) - if CName and CName != BaseTypeName: - OriginalType = CName - else: - OriginalType = BaseTypeName[1:] if BaseTypeName.startswith('C') else BaseTypeName - if prefix == prefixes[0]: - self._InsertTypedefSymbol(VarName, 'typedef', OriginalType, node.lineno, FilePath) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertTypedefSymbol(FullName, 'typedef', OriginalType, node.lineno, FilePath) - LoadedSymbols.append(FullName) - else: - if node.value: - ValueBaseType = FindBaseType(node.value) - _PTR_MODIFIERS = {'CPtr', 'CArrayPtr', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern'} - if ValueBaseType and ValueBaseType not in _PTR_MODIFIERS: - CName = CTypeHelper.GetCName(ValueBaseType) - if CName and CName != ValueBaseType: - OriginalType = CName - else: - OriginalType = ValueBaseType[1:] if ValueBaseType.startswith('C') else ValueBaseType - if prefix == prefixes[0]: - self._InsertTypedefSymbol(VarName, 'typedef', OriginalType, node.lineno, FilePath) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertTypedefSymbol(FullName, 'typedef', OriginalType, node.lineno, FilePath) - LoadedSymbols.append(FullName) - continue - if isinstance(node.value, ast.BinOp) and isinstance(node.value.op, ast.BitOr): - LeftType = self._ResolveTypedefValueType(node.value.left) - RightType = self._ResolveTypedefValueType(node.value.right) - IsPtrType = RightType == 'ptr' or LeftType == 'ptr' - if IsPtrType: - BaseName = LeftType if LeftType != 'ptr' else (RightType if RightType != 'ptr' else '') - if BaseName: - OriginalType = BaseName + ' *' - else: - OriginalType = 'void *' - elif LeftType: - OriginalType = LeftType - elif RightType: - OriginalType = RightType - if OriginalType: - if prefix == prefixes[0]: - self._InsertTypedefSymbol(VarName, 'typedef', OriginalType, node.lineno, FilePath) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertTypedefSymbol(FullName, 'typedef', OriginalType, node.lineno, FilePath) - LoadedSymbols.append(FullName) - continue - if isinstance(node.value, ast.Name): - RefName = node.value.id - if RefName in self: - RefInfo = self[RefName] - if RefInfo and RefInfo.IsTypedef and RefInfo.OriginalType: - if prefix == prefixes[0]: - self._InsertTypedefSymbol(VarName, 'typedef', RefInfo.OriginalType, node.lineno, FilePath) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertTypedefSymbol(FullName, 'typedef', RefInfo.OriginalType, node.lineno, FilePath) - LoadedSymbols.append(FullName) - continue - if prefix == prefixes[0]: - self._InsertTypedefSymbol(VarName, None, None, node.lineno, FilePath) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertTypedefSymbol(FullName, None, None, node.lineno, FilePath) - LoadedSymbols.append(FullName) - else: - if prefix == prefixes[0]: - self._InsertTypedefSymbol(VarName, None, None, node.lineno, FilePath) - LoadedSymbols.append(VarName) - FullName = f"{prefix}.{VarName}" - self._InsertTypedefSymbol(FullName, None, None, node.lineno, FilePath) - LoadedSymbols.append(FullName) - - elif isinstance(node, ast.FunctionDef): - FuncName = node.name - RetType = self._GetFuncRetTypeStr(node.returns) - ParamTypes = [] - for arg in node.args.args: - if arg.annotation: - ParamTypes.append(self._GetFuncParamTypeStr(arg.annotation)) - else: - ParamTypes.append('i8*') - FuncIsVariadic = node.args.vararg is not None - FuncIsInline = self._CheckAnnotationHasCInline(node.returns) - if prefix == prefixes[0]: - self._InsertFuncSymbol(FuncName, RetType, ParamTypes, node.lineno, FilePath, FuncIsVariadic, FuncIsInline) - LoadedSymbols.append(FuncName) - FullName = f"{prefix}.{FuncName}" - self._InsertFuncSymbol(FullName, RetType, ParamTypes, node.lineno, FilePath, FuncIsVariadic, FuncIsInline) - LoadedSymbols.append(FullName) - - self._InsertModuleSymbol(prefix, lineno, FilePath) - - for AnonymousTypeName, AnonymousTypeData in AnonymousTypes.items(): - if prefix == prefixes[0]: - self._InsertAnonymousSymbol(AnonymousTypeName, AnonymousTypeData['IsUnion'], AnonymousTypeData['members'], AnonymousTypeData['lineno'], FilePath) - FullTypeName = f"{prefix}.{AnonymousTypeName}" - self._InsertAnonymousSymbol(FullTypeName, AnonymousTypeData['IsUnion'], AnonymousTypeData['members'], AnonymousTypeData['lineno'], FilePath) - - if LoadedSymbols: - pass - return LoadedSymbols - - except Exception as e: - import traceback - print(traceback.format_exc()) - print(f"[SymbolTable Error] Failed to Load module: {FilePath} - {e}") - return [] - - def _GetLLVMTypeStr(self, node): - if node is None: - return 'i32' - if isinstance(node, ast.Name): - if node.id == 'str': - return 'i8*' - elif node.id == 'int': - return 'i32' - elif node.id == 'bool': - return 'i8' - elif node.id == 'float': - return 'double' - elif node.id == 'None': - return 'void' - elif node.id in ('UINT8PTR', 'INT8PTR', 'BYTEPTR'): - return 'i8*' - elif node.id in ('UINT16PTR', 'INT16PTR'): - return 'i16*' - elif node.id in ('UINT32PTR', 'INT32PTR'): - return 'i32*' - elif node.id in ('UINT64PTR', 'INT64PTR'): - return 'i64*' - else: - if node.id in self: - entry = self[node.id] - if entry and hasattr(entry, 'IsTypedef') and entry.IsTypedef and hasattr(entry, 'OriginalType') and entry.OriginalType: - if isinstance(entry.OriginalType, CTypeInfo) and entry.OriginalType.IsFuncPtr: - return 'i8*' - elif isinstance(entry.OriginalType, CTypeInfo) and entry.OriginalType.BaseType: - return entry.OriginalType.ToString() - elif isinstance(entry.OriginalType, str): - return entry.OriginalType - return 'i32' - elif isinstance(node, ast.Attribute): - attr_name = node.attr if hasattr(node, 'attr') else '' - from lib.includes.t import CTypeRegistry - llvm_str = CTypeRegistry.NameToLLVM(attr_name) - if llvm_str is not None: - return llvm_str - if attr_name in ('CState', 'CDefine', 'CTypedef', 'CExtern', 'CStatic', 'CConst', 'State'): - return '' - if attr_name in ('CCharPtr', 'CIntPtr', 'CVoidPtr', 'CArrayPtr'): - return 'i8*' - if attr_name == 'CVoidPtr': - return 'i8*' - if attr_name and attr_name[0].isupper() and attr_name not in CTypeRegistry._name_to_class: - return f'%struct.{attr_name}*' - if attr_name and attr_name not in CTypeRegistry._name_to_class: - return f'%struct.{attr_name}*' - return 'i32' - elif isinstance(node, ast.Subscript): - if isinstance(node.value, ast.Name) and node.value.id == 'tuple': - slice_node = node.slice - elem_types = [] - if isinstance(slice_node, ast.Tuple): - for elt in slice_node.elts: - elem_types.append(self._GetLLVMTypeStr(elt)) - else: - elem_types.append(self._GetLLVMTypeStr(slice_node)) - if elem_types: - return '{ ' + ', '.join(elem_types) + ' }' - if isinstance(node.value, ast.Name) and node.value.id == 'list': - slice_node = node.slice - if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) >= 1: - elem_type = self._GetLLVMTypeStr(slice_node.elts[0]) - else: - elem_type = self._GetLLVMTypeStr(slice_node) - return elem_type + '*' - return 'i32' - elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - left = self._GetLLVMTypeStr(node.left) - right = self._GetLLVMTypeStr(node.right) - if right and right.endswith('*'): - return right - if left and left.endswith('*'): - return left - if left and left not in ('i32', 'void', 'i64'): - return left - if right and right not in ('i32', 'void', 'i64'): - return right - return left if left else right - elif isinstance(node, ast.Constant): - if isinstance(node.value, bool): - return 'i8' - return 'i32' - elif isinstance(node, ast.Call): - if isinstance(node.func, ast.Attribute): - if hasattr(node.func.value, 'id') and node.func.value.id == 't': - return self._GetLLVMTypeStr(ast.Attribute(value=ast.Name(id='t'), attr=node.func.attr)) - return 'i32' - return 'i32' - - def _GetFuncRetTypeStr(self, returns_node): - if returns_node is None: - return 'i32' - actual = returns_node - if isinstance(returns_node, ast.BinOp) and isinstance(returns_node.op, ast.BitOr): - left_str = self._GetLLVMTypeStr(returns_node.left) - right_str = self._GetLLVMTypeStr(returns_node.right) - if right_str and right_str.endswith('*'): - return right_str - if left_str and left_str.endswith('*'): - return left_str - if left_str and left_str not in ('i32', 'void', 'i64'): - return left_str - if right_str and right_str not in ('i32', 'void', 'i64'): - return right_str - return left_str - result = self._GetLLVMTypeStr(actual) - return result if result else 'i32' - - @staticmethod - def _CheckAnnotationHasCInline(annotation_node) -> bool: - if annotation_node is None: - return False - if isinstance(annotation_node, ast.Attribute): - if hasattr(annotation_node.value, 'id') and annotation_node.value.id == 't' and annotation_node.attr == 'CInline': - return True - if isinstance(annotation_node, ast.Name): - if annotation_node.id == 'CInline': - return True - if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr): - return SymbolTable._CheckAnnotationHasCInline(annotation_node.left) or SymbolTable._CheckAnnotationHasCInline(annotation_node.right) - return False - - def _GetFuncParamTypeStr(self, annotation_node): - if annotation_node is None: - return 'i8*' - actual = annotation_node - if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr): - left_str = self._GetLLVMTypeStr(annotation_node.left) - right_str = self._GetLLVMTypeStr(annotation_node.right) - if right_str and right_str.endswith('*'): - return right_str - if left_str and left_str.endswith('*'): - return left_str - if right_str and right_str not in ('i32', 'void', 'i64'): - return right_str - if left_str and left_str not in ('i32', 'void', 'i64'): - return left_str - if left_str and left_str.endswith('*'): - return left_str - return right_str if right_str else left_str - result = self._GetLLVMTypeStr(actual) - return result if result else 'i8*' - - def _ResolveTypedefValueType(self, node): - if node is None: - return '' - if isinstance(node, ast.Name): - if node.id in self: - Entry = self[node.id] - if hasattr(Entry, 'IsTypedef') and Entry.IsTypedef and Entry.OriginalType: - return Entry.OriginalType - return '' - if isinstance(node, ast.Attribute): - if isinstance(node.value, ast.Name) and node.value.id == 't': - CName = CTypeHelper.GetCName(node.attr) - if CName and CName == '*': - return 'ptr' - if CName: - return CName - return '' - if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): - left_str = self._ResolveTypedefValueType(node.left) - right_str = self._ResolveTypedefValueType(node.right) - if right_str == 'ptr' or (right_str and right_str.endswith('*')): - base = left_str if left_str and left_str != 'ptr' else '' - return base + ' *' if base else 'void *' - if left_str == 'ptr' or (left_str and left_str.endswith('*')): - base = right_str if right_str and right_str != 'ptr' else '' - return base + ' *' if base else 'void *' - if right_str and right_str not in ('ptr', 'void', 'i32', 'i64'): - return right_str - if left_str and left_str not in ('ptr', 'void', 'i32', 'i64'): - return left_str - return left_str if left_str else right_str - return '' - - def _InsertClassSymbol(self, FullName: str, TypeKind: str, lineno: int, FilePath: str, members: dict, IsCpythonObject: bool, IsPacked: bool = False): - info = CTypeInfo() - info.Lineno = lineno - info.file = FilePath - info.Members = members if members else {} - - if TypeKind == 'struct': - info.IsStruct = True - elif TypeKind == 'union': - info.IsUnion = True - elif TypeKind == 'enum': - info.IsEnum = True - elif TypeKind == 'exception': - info.IsStruct = True - info.IsExceptionClass = True - - if IsCpythonObject: - info.IsCpythonObject = True - if IsPacked: - info.IsPacked = True - - self._symbols[FullName] = info - - def _InsertEnumMemberSymbol(self, FullName: str, EnumName: str, lineno: int, FilePath: str): - info = CTypeInfo() - info.IsEnumMember = True - info.EnumName = EnumName - info.Lineno = lineno - info.file = FilePath - self._symbols[FullName] = info - - def _InsertTypedefSymbol(self, FullName: str, OriginalType_kind: str | None, OriginalClass, lineno: int, FilePath: str, members: dict | None = None): - info = CTypeInfo() - info.IsTypedef = True - info.Lineno = lineno - info.file = FilePath - if members: - info.Members = members - - if isinstance(OriginalClass, CTypeInfo): - info.OriginalType = OriginalClass - elif OriginalType_kind == 'typedef' and OriginalClass and isinstance(OriginalClass, str) and ('*' in OriginalClass): - OriginalType = OriginalClass - if OriginalType == 'CVoid *': - OriginalType = 'void *' - info.OriginalType = OriginalType - elif OriginalType_kind == 'typedef' and OriginalClass == 'void': - info.OriginalType = 'void *' - elif OriginalType_kind == 'typedef' and OriginalClass: - info.OriginalType = OriginalClass - elif OriginalType_kind and OriginalClass and isinstance(OriginalClass, str): - info.OriginalType = f'{OriginalType_kind} {OriginalClass}' - else: - info.OriginalType = OriginalClass - - self._symbols[FullName] = info - - def _InsertModuleSymbol(self, name: str, lineno: int, FilePath: str): - info = CTypeInfo() - info.IsModuleAlias = True - info.Lineno = lineno - info.file = FilePath - self._symbols[name] = info - - def _InsertFuncSymbol(self, FullName: str, RetType, ParamTypes: list, lineno: int, FilePath: str, IsVariadic: bool = False, IsInline: bool = False): - info = CTypeInfo() - info.IsFunction = True - if isinstance(RetType, str): - info.FuncPtrReturn = CTypeInfo.FromTypeName(RetType) if RetType else CTypeInfo.VoidTypeInfo() - elif isinstance(RetType, CTypeInfo): - info.FuncPtrReturn = RetType - else: - info.FuncPtrReturn = CTypeInfo.VoidTypeInfo() - info.FuncPtrParams = [(f'arg{i}', pt) for i, pt in enumerate(ParamTypes)] - info.IsVariadic = IsVariadic - info.IsInline = IsInline - if IsInline: - info.Storage = t.CInline() - info.Lineno = lineno - info.file = FilePath - self._symbols[FullName] = info - - def _InsertDefineSymbol(self, FullName: str, DefineValue, lineno: int, FilePath: str): - info = CTypeInfo() - info.IsDefine = True - info.DefineValue = DefineValue - info.Lineno = lineno - info.file = FilePath - self._symbols[FullName] = info - - def _eval_const_expr(self, node): - """计算常量表达式的值""" - import ast - if isinstance(node, ast.Constant): - return node.value - elif isinstance(node, ast.BinOp): - left = self._eval_const_expr(node.left) - right = self._eval_const_expr(node.right) - if left is None or right is None: - return None - if isinstance(node.op, ast.Add): - return left + right - elif isinstance(node.op, ast.Sub): - return left - right - elif isinstance(node.op, ast.Mult): - return left * right - elif isinstance(node.op, ast.Div): - return left // right if isinstance(left, int) and isinstance(right, int) else left / right - elif isinstance(node.op, ast.FloorDiv): - return left // right - elif isinstance(node.op, ast.Mod): - return left % right - elif isinstance(node.op, ast.Pow): - return left ** right - elif isinstance(node.op, ast.LShift): - return left << right - elif isinstance(node.op, ast.RShift): - return left >> right - elif isinstance(node.op, ast.BitOr): - return left | right - elif isinstance(node.op, ast.BitXor): - return left ^ right - elif isinstance(node.op, ast.BitAnd): - return left & right - elif isinstance(node, ast.UnaryOp): - operand = self._eval_const_expr(node.operand) - if operand is None: - return None - if isinstance(node.op, ast.USub): - return -operand - elif isinstance(node.op, ast.UAdd): - return +operand - elif isinstance(node.op, ast.Invert): - return ~operand - elif isinstance(node, ast.Name): - # 引用其他常量 - if node.id in self: - info = self[node.id] - if hasattr(info, 'IsDefine') and info.IsDefine and hasattr(info, 'DefineValue') and info.DefineValue is not None: - return info.DefineValue - return None - - def _InsertAnonymousSymbol(self, FullName: str, IsUnion: bool, members: dict, lineno: int, FilePath: str): - info = CTypeInfo() - if IsUnion: - info.IsUnion = True - else: - info.IsStruct = True - info.IsAnonymous = True - info.Members = members if members else {} - info.Lineno = lineno - info.file = FilePath - self._symbols[FullName] = info - - + return info + + # ================================================================== + # 模块符号加载:四阶段管线 + # ================================================================== + + def LoadModuleSymbols(self, FullModulePath: str, asname: str, lineno: int = 0) -> list[str]: + return self._LoadSymbolsFromFile(FullModulePath, asname, lineno) + + def _LoadSymbolsFromFile(self, FilePath: str, namespace_prefix: str | list[str], lineno: int = 0) -> list[str]: + from lib.core.SymbolExtractor import ASTSymbolExtractor + from lib.core.SymbolTypeResolver import TypeResolver + from lib.core.SymbolInserter import SymbolInserter + from lib.core.SymbolReexporter import PackageReexporter + + try: + # Pass 1: 从 AST 提取原始符号信息 + extractor = ASTSymbolExtractor(self) + module_symbols = extractor.extract(FilePath) + + # Pass 2: 解析类型信息(typedef、函数签名、define 值) + resolver = TypeResolver(self) + resolver.resolve(module_symbols) + + # Pass 3: 插入符号到主命名空间(无前缀) + inserter = SymbolInserter(self) + loaded = inserter.insert(module_symbols) + + # Pass 4: 重新导出到命名空间前缀下 + prefixes = [namespace_prefix] if isinstance(namespace_prefix, str) else namespace_prefix + reexporter = PackageReexporter(self) + loaded.extend(reexporter.reexport(module_symbols, prefixes, lineno)) + + return loaded + + except Exception as e: + import traceback + print(traceback.format_exc()) + self.diagnostics.error(FilePath, lineno, f"加载模块失败: {e}") + return [] + + # ================================================================== + # 类型解析辅助方法(供 TypeResolver 通过 SymbolTable 引用调用) + # ================================================================== + + def _GetLLVMTypeStr(self, node): + if node is None: + self.diagnostics.warn('', 0, "类型注解为 None,回退到 i32") + return 'i32' + if isinstance(node, ast.Name): + if node.id == 'str': + return 'i8*' + elif node.id == 'int': + return 'i32' + elif node.id == 'bool': + return 'i8' + elif node.id == 'float': + return 'double' + elif node.id == 'None': + return 'void' + elif node.id in ('UINT8PTR', 'INT8PTR', 'BYTEPTR'): + return 'i8*' + elif node.id in ('UINT16PTR', 'INT16PTR'): + return 'i16*' + elif node.id in ('UINT32PTR', 'INT32PTR'): + return 'i32*' + elif node.id in ('UINT64PTR', 'INT64PTR'): + return 'i64*' + else: + if node.id in self: + entry = self[node.id] + if entry and entry.IsTypedef and entry.OriginalType: + if isinstance(entry.OriginalType, CTypeInfo) and entry.OriginalType.IsFuncPtr: + return 'i8*' + elif isinstance(entry.OriginalType, CTypeInfo) and entry.OriginalType.BaseType: + return entry.OriginalType.ToString() + elif isinstance(entry.OriginalType, str): + return entry.OriginalType + self.diagnostics.warn('', 0, f"无法解析 Name 类型 '{node.id}',回退到 i32") + return 'i32' + elif isinstance(node, ast.Attribute): + attr_name = node.attr if hasattr(node, 'attr') else '' + from lib.includes.t import CTypeRegistry + llvm_str = CTypeRegistry.NameToLLVM(attr_name) + if llvm_str is not None: + return llvm_str + if attr_name in ('CState', 'CDefine', 'CTypedef', 'CExtern', 'CStatic', 'CConst', 'State'): + return '' + if attr_name in ('CCharPtr', 'CIntPtr', 'CVoidPtr', 'CArrayPtr'): + return 'i8*' + if attr_name == 'CVoidPtr': + return 'i8*' + if attr_name and attr_name[0].isupper() and attr_name not in CTypeRegistry._name_to_class: + return f'%struct.{attr_name}*' + if attr_name and attr_name not in CTypeRegistry._name_to_class: + return f'%struct.{attr_name}*' + self.diagnostics.warn('', 0, f"无法解析 Attribute 类型 '{attr_name}',回退到 i32") + return 'i32' + elif isinstance(node, ast.Subscript): + if isinstance(node.value, ast.Name) and node.value.id == 'tuple': + slice_node = node.slice + elem_types = [] + if isinstance(slice_node, ast.Tuple): + for elt in slice_node.elts: + elem_types.append(self._GetLLVMTypeStr(elt)) + else: + elem_types.append(self._GetLLVMTypeStr(slice_node)) + if elem_types: + return '{ ' + ', '.join(elem_types) + ' }' + if isinstance(node.value, ast.Name) and node.value.id == 'list': + slice_node = node.slice + if isinstance(slice_node, ast.Tuple) and len(slice_node.elts) >= 1: + elem_type = self._GetLLVMTypeStr(slice_node.elts[0]) + else: + elem_type = self._GetLLVMTypeStr(slice_node) + return elem_type + '*' + self.diagnostics.warn('', 0, f"无法解析 Subscript 类型,回退到 i32") + return 'i32' + elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): + left = self._GetLLVMTypeStr(node.left) + right = self._GetLLVMTypeStr(node.right) + if right and right.endswith('*'): + return right + if left and left.endswith('*'): + return left + if left and left not in ('i32', 'void', 'i64'): + return left + if right and right not in ('i32', 'void', 'i64'): + return right + return left if left else right + elif isinstance(node, ast.Constant): + if isinstance(node.value, bool): + return 'i8' + return 'i32' + elif isinstance(node, ast.Call): + if isinstance(node.func, ast.Attribute): + if hasattr(node.func.value, 'id') and node.func.value.id == 't': + return self._GetLLVMTypeStr(ast.Attribute(value=ast.Name(id='t'), attr=node.func.attr)) + self.diagnostics.warn('', 0, "无法解析 Call 类型,回退到 i32") + return 'i32' + self.diagnostics.warn('', 0, f"无法解析类型节点 {type(node).__name__},回退到 i32") + return 'i32' + + def _GetFuncRetTypeStr(self, returns_node): + if returns_node is None: + return 'i32' + actual = returns_node + if isinstance(returns_node, ast.BinOp) and isinstance(returns_node.op, ast.BitOr): + left_str = self._GetLLVMTypeStr(returns_node.left) + right_str = self._GetLLVMTypeStr(returns_node.right) + if right_str and right_str.endswith('*'): + return right_str + if left_str and left_str.endswith('*'): + return left_str + if left_str and left_str not in ('i32', 'void', 'i64'): + return left_str + if right_str and right_str not in ('i32', 'void', 'i64'): + return right_str + return left_str + result = self._GetLLVMTypeStr(actual) + return result if result else 'i32' + + @staticmethod + def _CheckAnnotationHasCInline(annotation_node) -> bool: + return _CheckAnnotationHasCInline(annotation_node) + + def _GetFuncParamTypeStr(self, annotation_node): + if annotation_node is None: + return 'i8*' + actual = annotation_node + if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr): + left_str = self._GetLLVMTypeStr(annotation_node.left) + right_str = self._GetLLVMTypeStr(annotation_node.right) + if right_str and right_str.endswith('*'): + return right_str + if left_str and left_str.endswith('*'): + return left_str + if right_str and right_str not in ('i32', 'void', 'i64'): + return right_str + if left_str and left_str not in ('i32', 'void', 'i64'): + return left_str + if left_str and left_str.endswith('*'): + return left_str + return right_str if right_str else left_str + result = self._GetLLVMTypeStr(actual) + return result if result else 'i8*' + + def _ResolveTypedefValueType(self, node): + if node is None: + return '' + if isinstance(node, ast.Name): + if node.id in self: + Entry = self[node.id] + if Entry.IsTypedef and Entry.OriginalType: + return Entry.OriginalType + return '' + if isinstance(node, ast.Attribute): + if isinstance(node.value, ast.Name) and node.value.id == 't': + CName = CTypeHelper.GetCName(node.attr) + if CName and CName == '*': + return 'ptr' + if CName: + return CName + return '' + if isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): + left_str = self._ResolveTypedefValueType(node.left) + right_str = self._ResolveTypedefValueType(node.right) + if right_str == 'ptr' or (right_str and right_str.endswith('*')): + base = left_str if left_str and left_str != 'ptr' else '' + return base + ' *' if base else 'void *' + if left_str == 'ptr' or (left_str and left_str.endswith('*')): + base = right_str if right_str and right_str != 'ptr' else '' + return base + ' *' if base else 'void *' + if right_str and right_str not in ('ptr', 'void', 'i32', 'i64'): + return right_str + if left_str and left_str not in ('ptr', 'void', 'i32', 'i64'): + return left_str + return left_str if left_str else right_str + return '' + + # ================================================================== + # 符号插入方法(供 SymbolInserter / PackageReexporter 调用) + # ================================================================== + + def _InsertClassSymbol(self, FullName: str, TypeKind: str, lineno: int, FilePath: str, members: dict, IsCpythonObject: bool, IsPacked: bool = False): + info = CTypeInfo() + info.Lineno = lineno + info.file = FilePath + info.Members = members if members else {} + + if TypeKind == 'struct': + info.IsStruct = True + elif TypeKind == 'union': + info.IsUnion = True + elif TypeKind == 'enum': + info.IsEnum = True + elif TypeKind == 'exception': + info.IsStruct = True + info.IsExceptionClass = True + + if IsCpythonObject: + info.IsCpythonObject = True + if IsPacked: + info.IsPacked = True + + self._symbols[FullName] = info + + def _InsertEnumMemberSymbol(self, FullName: str, EnumName: str, lineno: int, FilePath: str): + info = CTypeInfo() + info.IsEnumMember = True + info.EnumName = EnumName + info.Lineno = lineno + info.file = FilePath + self._symbols[FullName] = info + + def _InsertTypedefSymbol(self, FullName: str, OriginalType_kind: str | None, OriginalClass, lineno: int, FilePath: str, members: dict | None = None): + info = CTypeInfo() + info.IsTypedef = True + info.Lineno = lineno + info.file = FilePath + if members: + info.Members = members + + if isinstance(OriginalClass, CTypeInfo): + info.OriginalType = OriginalClass + elif OriginalType_kind == 'typedef' and OriginalClass and isinstance(OriginalClass, str) and ('*' in OriginalClass): + OriginalType = OriginalClass + if OriginalType == 'CVoid *': + OriginalType = 'void *' + info.OriginalType = OriginalType + elif OriginalType_kind == 'typedef' and OriginalClass == 'void': + info.OriginalType = 'void *' + elif OriginalType_kind == 'typedef' and OriginalClass: + info.OriginalType = OriginalClass + elif OriginalType_kind and OriginalClass and isinstance(OriginalClass, str): + info.OriginalType = f'{OriginalType_kind} {OriginalClass}' + else: + info.OriginalType = OriginalClass + + self._symbols[FullName] = info + + def _InsertModuleSymbol(self, name: str, lineno: int, FilePath: str): + info = CTypeInfo() + info.IsModuleAlias = True + info.Lineno = lineno + info.file = FilePath + self._symbols[name] = info + + def _InsertFuncSymbol(self, FullName: str, RetType, ParamTypes: list, lineno: int, FilePath: str, IsVariadic: bool = False, IsInline: bool = False): + info = CTypeInfo() + info.IsFunction = True + if isinstance(RetType, str): + info.FuncPtrReturn = CTypeInfo.FromTypeName(RetType) if RetType else CTypeInfo.VoidTypeInfo() + elif isinstance(RetType, CTypeInfo): + info.FuncPtrReturn = RetType + else: + info.FuncPtrReturn = CTypeInfo.VoidTypeInfo() + info.FuncPtrParams = [(f'arg{i}', pt) for i, pt in enumerate(ParamTypes)] + info.IsVariadic = IsVariadic + info.IsInline = IsInline + if IsInline: + info.Storage = t.CInline() + info.Lineno = lineno + info.file = FilePath + self._symbols[FullName] = info + + def _InsertDefineSymbol(self, FullName: str, DefineValue, lineno: int, FilePath: str): + info = CTypeInfo() + info.IsDefine = True + info.DefineValue = DefineValue + info.Lineno = lineno + info.file = FilePath + self._symbols[FullName] = info + + def _eval_const_expr(self, node): + """计算常量表达式的值(委托到 ConstEvaluator)""" + from lib.core.ConstEvaluator import ConstEvaluator + return ConstEvaluator.eval_with_symtab(node, self) + + def _InsertAnonymousSymbol(self, FullName: str, IsUnion: bool, members: dict, lineno: int, FilePath: str): + info = CTypeInfo() + if IsUnion: + info.IsUnion = True + else: + info.IsStruct = True + info.IsAnonymous = True + info.Members = members if members else {} + info.Lineno = lineno + info.file = FilePath + self._symbols[FullName] = info diff --git a/lib/core/SymbolTypeResolver.py b/lib/core/SymbolTypeResolver.py new file mode 100644 index 0000000..8bd6408 --- /dev/null +++ b/lib/core/SymbolTypeResolver.py @@ -0,0 +1,224 @@ +"""Pass 2: TypeResolver — 解析 typedef 类型、函数签名、define 值""" +from __future__ import annotations +import ast +from typing import TYPE_CHECKING +if TYPE_CHECKING: + from lib.core.SymbolTable import SymbolTable + +from lib.core.SymbolData import ( + ModuleSymbols, TypedefSymbolData, FuncSymbolData, DefineSymbolData +) +from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper +from lib.includes import t + + +class TypeResolver: + """解析从 AST 提取的原始符号中的类型信息""" + + def __init__(self, symbol_table: SymbolTable): + self._symtab = symbol_table + + def resolve(self, module_symbols: ModuleSymbols) -> ModuleSymbols: + """解析所有类型信息,就地更新 ModuleSymbols""" + # 构建 class_members 查找表(typedef Postdefinition 需要) + class_members = {cls.name: cls.members for cls in module_symbols.classes} + + # 解析 typedef + for td in module_symbols.typedefs: + self._resolve_typedef(td, class_members) + + # 解析函数签名 + for func in module_symbols.functions: + self._resolve_function(func) + + # 解析 define 值 + for define in module_symbols.defines: + self._resolve_define(define) + + return module_symbols + + # ------------------------------------------------------------------ + # Typedef 解析 + # ------------------------------------------------------------------ + + def _resolve_typedef(self, td: TypedefSymbolData, class_members: dict): + """解析单个 typedef 的类型信息""" + is_postdef_with_typedef = td.has_postdef and td.has_ctypedef + + if is_postdef_with_typedef: + self._resolve_postdef_typedef(td, class_members) + elif td.has_ctypedef: + self._resolve_ctypedef_typedef(td) + else: + # 无特殊注解的 typedef + td.original_type_kind = None + td.original_class = None + + def _resolve_postdef_typedef(self, td: TypedefSymbolData, class_members: dict): + """解析 Postdefinition + CTypedef 组合注解""" + original_class = self._find_postdef_arg(td.annotation) + if original_class and original_class in class_members: + members_info = class_members[original_class] + original_type_kind = 'struct' + if original_class in self._symtab: + orig_type_info = self._symtab[original_class] + if orig_type_info.type_cls in (t.CStruct, t.CEnum, t.CUnion): + if orig_type_info.type_cls is t.CStruct: + original_type_kind = 'struct' + elif orig_type_info.type_cls is t.CEnum: + original_type_kind = 'enum' + elif orig_type_info.type_cls is t.CUnion: + original_type_kind = 'union' + td.original_type_kind = original_type_kind + td.original_class = original_class + td.members = members_info + else: + td.original_type_kind = None + td.original_class = None + + def _resolve_ctypedef_typedef(self, td: TypedefSymbolData): + """解析 CTypedef 注解""" + base_type_name = self._find_base_type(td.annotation) + _TYPE_QUALIFIERS = {'CTypedef', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern', 'CDefine', 'CPostdefinition'} + + if base_type_name == 'Callable': + original_type = CTypeInfo() + original_type.IsFuncPtr = True + original_type.FuncPtrReturn = CTypeInfo.VoidTypeInfo() + original_type.FuncPtrParams = [] + td.original_type_kind = 'typedef' + td.original_class = original_type + elif base_type_name and base_type_name not in _TYPE_QUALIFIERS: + cname = CTypeHelper.GetCName(base_type_name) + if cname and cname != base_type_name: + td.original_class = cname + else: + td.original_class = base_type_name[1:] if base_type_name.startswith('C') else base_type_name + td.original_type_kind = 'typedef' + else: + # 尝试从值表达式解析 + self._resolve_typedef_from_value(td) + + def _resolve_typedef_from_value(self, td: TypedefSymbolData): + """从值表达式解析 typedef 类型""" + if not td.value: + td.original_type_kind = None + td.original_class = None + return + + value_base_type = self._find_base_type(td.value) + _PTR_MODIFIERS = {'CPtr', 'CArrayPtr', 'CConst', 'CVolatile', 'CInline', 'CStatic', 'CExtern'} + + if value_base_type and value_base_type not in _PTR_MODIFIERS: + cname = CTypeHelper.GetCName(value_base_type) + if cname and cname != value_base_type: + td.original_class = cname + else: + td.original_class = value_base_type[1:] if value_base_type.startswith('C') else value_base_type + td.original_type_kind = 'typedef' + return + + if isinstance(td.value, ast.BinOp) and isinstance(td.value.op, ast.BitOr): + left_type = self._symtab._ResolveTypedefValueType(td.value.left) + right_type = self._symtab._ResolveTypedefValueType(td.value.right) + is_ptr_type = right_type == 'ptr' or left_type == 'ptr' + if is_ptr_type: + base_name = left_type if left_type != 'ptr' else (right_type if right_type != 'ptr' else '') + if base_name: + original_type = base_name + ' *' + else: + original_type = 'void *' + td.original_class = original_type + td.original_type_kind = 'typedef' + elif left_type: + td.original_class = left_type + td.original_type_kind = 'typedef' + elif right_type: + td.original_class = right_type + td.original_type_kind = 'typedef' + return + + if isinstance(td.value, ast.Name): + ref_name = td.value.id + if ref_name in self._symtab: + ref_info = self._symtab[ref_name] + if ref_info and ref_info.IsTypedef and ref_info.OriginalType: + td.original_class = ref_info.OriginalType + td.original_type_kind = 'typedef' + return + + td.original_type_kind = None + td.original_class = None + + # ------------------------------------------------------------------ + # 函数签名解析 + # ------------------------------------------------------------------ + + def _resolve_function(self, func: FuncSymbolData): + """解析函数的返回类型和参数类型""" + func.ret_type = self._symtab._GetFuncRetTypeStr(func.returns_node) + func.param_types = [] + for _arg_name, annotation in func.params: + if annotation: + func.param_types.append(self._symtab._GetFuncParamTypeStr(annotation)) + else: + func.param_types.append('i8*') + + # ------------------------------------------------------------------ + # Define 值解析 + # ------------------------------------------------------------------ + + def _resolve_define(self, define: DefineSymbolData): + """解析 define 常量值""" + if define.value_node: + define.value = self._symtab._eval_const_expr(define.value_node) + + # ------------------------------------------------------------------ + # 静态工具方法(原 _LoadSymbolsFromFile 中的闭包) + # ------------------------------------------------------------------ + + @staticmethod + def _find_base_type(node): + """从注解 AST 节点中查找基础类型名称""" + if isinstance(node, ast.Attribute): + if hasattr(node.value, 'id') and node.value.id == 't': + if node.attr == 'CPtr': + return 'ptr' + return node.attr + elif isinstance(node, ast.Subscript): + if isinstance(node.value, ast.Attribute) and isinstance(node.value.value, ast.Name) and node.value.value.id == 't' and node.value.attr == 'Callable': + return 'Callable' + elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): + left_result = TypeResolver._find_base_type(node.left) + if left_result == 'ptr': + right_result = TypeResolver._find_base_type(node.right) + return (right_result if right_result and right_result != 'ptr' else 'void') + ' *' + if left_result == 'Callable': + return 'Callable' + right_result = TypeResolver._find_base_type(node.right) + if right_result == 'ptr': + return (left_result if left_result and left_result != 'ptr' else 'void') + ' *' + if right_result == 'Callable': + return 'Callable' + if left_result: + return left_result + if right_result: + return right_result + return None + + @staticmethod + def _find_postdef_arg(node): + """从注解 AST 节点中查找 Postdefinition 参数""" + if isinstance(node, ast.Call): + if isinstance(node.func, ast.Attribute): + if hasattr(node.func.value, 'id') and node.func.value.id == 't' and node.func.attr == 'Postdefinition': + if node.args and isinstance(node.args[0], ast.Name): + return node.args[0].id + elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.BitOr): + left_result = TypeResolver._find_postdef_arg(node.left) + if left_result: + return left_result + right_result = TypeResolver._find_postdef_arg(node.right) + if right_result: + return right_result + return None diff --git a/lib/core/SymbolUtils.py b/lib/core/SymbolUtils.py new file mode 100644 index 0000000..5f14a09 --- /dev/null +++ b/lib/core/SymbolUtils.py @@ -0,0 +1,56 @@ +"""共享工具函数:符号表处理中使用的 AST 分析工具""" +from __future__ import annotations +import ast +from lib.includes import t + + +def IsTModuleType(TypeName: str) -> bool: + """检测类型名称是否是 t 模块中的类型(CType 或其他特殊类型)""" + if TypeName in ('t', 'State', 'Bit', 'Anonymous', 'Postdefinition'): + return True + TypeClass = getattr(t, TypeName, None) + if TypeClass and isinstance(TypeClass, type): + if issubclass(TypeClass, t.CType): + return True + FallbackClass = getattr(t, f'_{TypeName}', None) + if FallbackClass and isinstance(FallbackClass, type): + if issubclass(FallbackClass, t.CType): + return True + return False + + +def AnnotationContainsTType(node, TypeName: str) -> bool: + """检测 AST 节点中是否包含指定名称的 t 模块类型""" + if isinstance(node, ast.Attribute): + if (hasattr(node.value, 'id') and node.value.id == 't' and + node.attr == TypeName): + return True + elif isinstance(node, ast.BinOp): + return AnnotationContainsTType(node.left, TypeName) or AnnotationContainsTType(node.right, TypeName) + elif isinstance(node, ast.Call): + if AnnotationContainsTType(node.func, TypeName): + return True + for arg in node.args: + if AnnotationContainsTType(arg, TypeName): + return True + elif isinstance(node, ast.Subscript): + if AnnotationContainsTType(node.value, TypeName): + return True + if AnnotationContainsTType(node.slice, TypeName): + return True + return False + + +def CheckAnnotationHasCInline(annotation_node) -> bool: + """检测注解节点中是否包含 CInline""" + if annotation_node is None: + return False + if isinstance(annotation_node, ast.Attribute): + if hasattr(annotation_node.value, 'id') and annotation_node.value.id == 't' and annotation_node.attr == 'CInline': + return True + if isinstance(annotation_node, ast.Name): + if annotation_node.id == 'CInline': + return True + if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr): + return CheckAnnotationHasCInline(annotation_node.left) or CheckAnnotationHasCInline(annotation_node.right) + return False diff --git a/lib/core/Translator/AnnotationLoader.py b/lib/core/Translator/AnnotationLoader.py index 8d17636..4b0f982 100644 --- a/lib/core/Translator/AnnotationLoader.py +++ b/lib/core/Translator/AnnotationLoader.py @@ -328,9 +328,9 @@ class AnnotationLoaderMixin: orig_type_str = orig_entry.get('OriginalType', f'struct {original_name}') elif orig_entry.get('type') == 'enum': orig_type_str = f'enum {original_name}' - elif hasattr(orig_entry, 'IsTypedef') and orig_entry.IsTypedef: - orig_type_str = getattr(orig_entry, 'OriginalType', f'struct {original_name}') - elif hasattr(orig_entry, 'IsEnum') and orig_entry.IsEnum: + elif orig_entry.IsTypedef: + orig_type_str = orig_entry.OriginalType or f'struct {original_name}' + elif orig_entry.IsEnum: orig_type_str = f'enum {original_name}' TypedefNode.OriginalType = orig_type_str TypedefNode.set('source', 'annotation_module') diff --git a/lib/core/Translator/ConstEval.py b/lib/core/Translator/ConstEval.py index 780e1a2..0cad71e 100644 --- a/lib/core/Translator/ConstEval.py +++ b/lib/core/Translator/ConstEval.py @@ -112,42 +112,8 @@ class ConstEvalMixin: return self._try_eval_const_expr(node, Gen) def _try_eval_const_expr(self, node, Gen): - import ast - if isinstance(node, ast.Constant): - return node.value - elif isinstance(node, ast.BinOp): - left = self._try_eval_const_expr(node.left, Gen) - right = self._try_eval_const_expr(node.right, Gen) - if left is None or right is None: - return None - if isinstance(node.op, ast.Add): - return left + right - elif isinstance(node.op, ast.Sub): - return left - right - elif isinstance(node.op, ast.Mult): - return left * right - elif isinstance(node.op, ast.LShift): - return left << right - elif isinstance(node.op, ast.RShift): - return left >> right - elif isinstance(node.op, ast.BitOr): - return left | right - elif isinstance(node.op, ast.BitAnd): - return left & right - elif isinstance(node.op, ast.BitXor): - return left ^ right - elif isinstance(node, ast.UnaryOp): - operand = self._try_eval_const_expr(node.operand, Gen) - if operand is None: - return None - if isinstance(node.op, ast.USub): - return -operand - elif isinstance(node.op, ast.Invert): - return ~operand - elif isinstance(node, ast.Name): - if node.id in getattr(Gen, '_DefineConstants', {}): - return Gen._DefineConstants[node.id] - return None + from lib.core.ConstEvaluator import ConstEvaluator + return ConstEvaluator.eval_with_symtab(node, self.SymbolTable) def _BuildMultiDimArrayInitConstants(self, value_node, ArrayType, Gen): from lib.core.Handles.HandlesAssign import AssignHandle diff --git a/lib/core/TypeSpec.py b/lib/core/TypeSpec.py index ec741fe..64e85fc 100644 --- a/lib/core/TypeSpec.py +++ b/lib/core/TypeSpec.py @@ -67,6 +67,7 @@ FIELD_ROUTES = { 'ArrayPtr': ('ts', 'array_ptr'), 'IsState': ('ts', 'is_state'), 'OriginalType': ('ts', 'original_type'), + 'IsSigned': ('ts', 'is_signed'), # --- SymbolMeta 字段 --- 'Name': ('sm', 'name'), @@ -87,6 +88,8 @@ FIELD_ROUTES = { 'IsModuleAlias': ('sm', 'is_module_alias'), 'ResolvedModule': ('sm', 'resolved_module'), 'DefineValue': ('sm', 'define_value'), + 'EnumName': ('sm', 'enum_name'), + 'value': ('sm', 'enum_value'), # --- _kind_flags(独立 bool,存储在 SymbolMeta._kind_flags)--- 'IsStruct': ('kf', 'IsStruct'), @@ -127,6 +130,7 @@ class TypeSpec: 'is_array_ptr', 'array_ptr', 'is_state', 'original_type', + 'is_signed', ) def __init__(self): @@ -150,6 +154,7 @@ class TypeSpec: self.array_ptr: Any = None # CTypeInfo self.is_state: bool = False self.original_type: Any = None # CTypeInfo | str | None (typedef 原始类型) + self.is_signed: Optional[bool] = None # None = 未设置, True/False = 有符号/无符号 @property def base_type(self) -> Any: @@ -203,6 +208,7 @@ class TypeSpec: new.array_ptr = self.array_ptr new.is_state = self.is_state new.original_type = self.original_type + new.is_signed = self.is_signed return new @@ -222,6 +228,7 @@ class SymbolMeta: 'members', 'is_cpython_object', 'is_packed', 'define_value', + 'enum_name', 'enum_value', 'is_inline', 'inline_body', 'inline_params', 'is_anonymous', 'renum_variants', @@ -241,6 +248,8 @@ class SymbolMeta: self.is_cpython_object: bool = False self.is_packed: bool = False self.define_value: Any = None + self.enum_name: str = "" # 枚举成员所属的枚举类名 + self.enum_value: Any = None # 枚举成员的值 self.is_inline: bool = False self.inline_body: list | None = None self.inline_params: list | None = None @@ -287,6 +296,8 @@ class SymbolMeta: new.is_cpython_object = self.is_cpython_object new.is_packed = self.is_packed new.define_value = self.define_value + new.enum_name = self.enum_name + new.enum_value = self.enum_value new.is_inline = self.is_inline new.inline_body = self.inline_body new.inline_params = list(self.inline_params) if self.inline_params else None