tcoptimizations.pas 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 2017 by Michael Van Canneyt
  4. Unit tests for Pascal-to-Javascript converter class.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************
  11. Examples:
  12. ./testpas2js --suite=TTestOptimizations
  13. ./testpas2js --suite=TTestOptimizations.TestOmitLocalVar
  14. }
  15. unit TCOptimizations;
  16. {$mode objfpc}{$H+}
  17. interface
  18. uses
  19. Classes, SysUtils, testregistry, fppas2js, pastree,
  20. PScanner, Pas2jsUseAnalyzer, PasResolver, PasResolveEval,
  21. TCModules;
  22. type
  23. { TCustomTestOptimizations }
  24. TCustomTestOptimizations = class(TCustomTestModule)
  25. private
  26. FAnalyzerModule: TPas2JSAnalyzer;
  27. FAnalyzerProgram: TPas2JSAnalyzer;
  28. FWholeProgramOptimization: boolean;
  29. function OnConverterIsElementUsed(Sender: TObject; El: TPasElement): boolean;
  30. function OnConverterIsTypeInfoUsed(Sender: TObject; El: TPasElement): boolean;
  31. protected
  32. procedure SetUp; override;
  33. procedure TearDown; override;
  34. procedure ParseModule; override;
  35. procedure ParseProgram; override;
  36. function CreateConverter: TPasToJSConverter; override;
  37. public
  38. property AnalyzerModule: TPas2JSAnalyzer read FAnalyzerModule;
  39. property AnalyzerProgram: TPas2JSAnalyzer read FAnalyzerProgram;
  40. property WholeProgramOptimization: boolean read FWholeProgramOptimization
  41. write FWholeProgramOptimization;
  42. end;
  43. { TTestOptimizations }
  44. TTestOptimizations = class(TCustomTestOptimizations)
  45. published
  46. // unit optimization: jsshortrefglobals
  47. procedure TestOptShortRefGlobals_Program;
  48. procedure TestOptShortRefGlobals_Unit_FromIntfImpl_ToIntfImpl;
  49. procedure TestOptShortRefGlobals_Enums;
  50. procedure TestOptShortRefGlobals_Property;
  51. procedure TestOptShortRefGlobals_ExternalAbstract;
  52. procedure TestOptShortRefGlobals_Class;
  53. procedure TestOptShortRefGlobals_GenericFunction;
  54. procedure TestOptShortRefGlobals_GenericMethod_Call;
  55. procedure TestOptShortRefGlobals_GenericStaticMethod_Call;
  56. // ToDo: GenericMethod_CallInherited ObjFPC+Delphi
  57. procedure TestOptShortRefGlobals_GenericClassHelperMethod;
  58. procedure TestOptShortRefGlobals_GenericMethod_ProcVar;
  59. procedure TestOptShortRefGlobals_GenericStaticMethod_ProcVar;
  60. procedure TestOptShortRefGlobals_SameUnit_EnumType;
  61. procedure TestOptShortRefGlobals_SameUnit_ClassType;
  62. procedure TestOptShortRefGlobals_SameUnit_RecordType;
  63. procedure TestOptShortRefGlobals_Unit_InitNoImpl;
  64. // Obfuscate Identifiers
  65. procedure TestObfuscateLocalIdentifiers_Program; // ToDo
  66. // Whole Program Optimization - omit not used elements
  67. procedure TestWPO_OmitLocalVar;
  68. procedure TestWPO_OmitLocalProc;
  69. procedure TestWPO_OmitLocalProcForward;
  70. procedure TestWPO_OmitProcLocalVar;
  71. procedure TestWPO_OmitProcLocalConst;
  72. procedure TestWPO_OmitProcLocalType;
  73. procedure TestWPO_OmitProcLocalProc;
  74. procedure TestWPO_OmitProcLocalForwardProc;
  75. procedure TestWPO_OmitRecordMember;
  76. procedure TestWPO_OmitNotUsedTObject;
  77. procedure TestWPO_TObject;
  78. procedure TestWPO_Class_Property;
  79. procedure TestWPO_Class_OmitField;
  80. procedure TestWPO_Class_OmitMethod;
  81. procedure TestWPO_Class_OmitClassMethod;
  82. procedure TestWPO_Class_OmitPropertyGetter1;
  83. procedure TestWPO_Class_OmitPropertyGetter2;
  84. procedure TestWPO_Class_OmitPropertySetter1;
  85. procedure TestWPO_Class_OmitPropertySetter2;
  86. procedure TestWPO_Class_KeepNewInstance;
  87. procedure TestWPO_CallInherited;
  88. procedure TestWPO_UseUnit;
  89. procedure TestWPO_ArrayOfConst_Use;
  90. procedure TestWPO_ArrayOfConst_NotUsed;
  91. procedure TestWPO_Class_PropertyInOtherUnit;
  92. procedure TestWPO_ProgramPublicDeclaration;
  93. procedure TestWPO_ConstructorDefaultValueConst;
  94. procedure TestWPO_RTTI_PublishedField;
  95. procedure TestWPO_RTTI_TypeInfo;
  96. procedure TestWPO_RTTI_PrivateField;
  97. end;
  98. implementation
  99. { TCustomTestOptimizations }
  100. function TCustomTestOptimizations.OnConverterIsElementUsed(Sender: TObject;
  101. El: TPasElement): boolean;
  102. var
  103. A: TPas2JSAnalyzer;
  104. begin
  105. if WholeProgramOptimization then
  106. A:=AnalyzerProgram
  107. else if Sender=Converter then
  108. A:=AnalyzerModule
  109. else
  110. begin
  111. {$IF defined(VerbosePas2JS) or defined(VerbosePasAnalyzer)}
  112. writeln('TCustomTestOptimizations.OnConverterIsElementUsed El=',GetObjName(El),' WPO=',WholeProgramOptimization,' Sender=',GetObjName(Sender));
  113. {$ENDIF}
  114. Fail('converting other unit without WPO');
  115. end;
  116. Result:=A.IsUsed(El);
  117. {$IF defined(VerbosePas2JS) or defined(VerbosePasAnalyzer)}
  118. writeln('TCustomTestOptimizations.OnConverterIsElementUsed El=',GetObjName(El),' WPO=',WholeProgramOptimization,' Result=',Result);
  119. {$ENDIF}
  120. end;
  121. function TCustomTestOptimizations.OnConverterIsTypeInfoUsed(Sender: TObject;
  122. El: TPasElement): boolean;
  123. var
  124. A: TPas2JSAnalyzer;
  125. begin
  126. if WholeProgramOptimization then
  127. A:=AnalyzerProgram
  128. else if Sender=Converter then
  129. A:=AnalyzerModule
  130. else
  131. begin
  132. {$IF defined(VerbosePas2JS) or defined(VerbosePasAnalyzer)}
  133. writeln('TCustomTestOptimizations.OnConverterIsTypeInfoUsed El=',GetObjName(El),' WPO=',WholeProgramOptimization,' Sender=',GetObjName(Sender));
  134. {$ENDIF}
  135. Fail('converting other unit without WPO');
  136. end;
  137. Result:=A.IsTypeInfoUsed(El);
  138. {$IF defined(VerbosePas2JS) or defined(VerbosePasAnalyzer)}
  139. writeln('TCustomTestOptimizations.OnConverterIsTypeInfoUsed El=',GetObjName(El),' WPO=',WholeProgramOptimization,' Result=',Result);
  140. {$ENDIF}
  141. end;
  142. procedure TCustomTestOptimizations.SetUp;
  143. begin
  144. inherited SetUp;
  145. FWholeProgramOptimization:=false;
  146. FAnalyzerModule:=TPas2JSAnalyzer.Create;
  147. FAnalyzerModule.Resolver:=ResolverEngine;
  148. FAnalyzerProgram:=TPas2JSAnalyzer.Create;
  149. FAnalyzerProgram.Resolver:=ResolverEngine;
  150. end;
  151. procedure TCustomTestOptimizations.TearDown;
  152. begin
  153. FreeAndNil(FAnalyzerProgram);
  154. FreeAndNil(FAnalyzerModule);
  155. inherited TearDown;
  156. end;
  157. procedure TCustomTestOptimizations.ParseModule;
  158. begin
  159. inherited ParseModule;
  160. {$IF defined(VerbosePas2JS) or defined(VerbosePasAnalyzer)}
  161. writeln('TCustomTestOptimizations.ParseModule START');
  162. {$ENDIF}
  163. AnalyzerModule.AnalyzeModule(Module);
  164. {$IF defined(VerbosePas2JS) or defined(VerbosePasAnalyzer)}
  165. writeln('TCustomTestOptimizations.ParseModule END');
  166. {$ENDIF}
  167. end;
  168. procedure TCustomTestOptimizations.ParseProgram;
  169. begin
  170. WholeProgramOptimization:=true;
  171. inherited ParseProgram;
  172. {$IF defined(VerbosePas2JS) or defined(VerbosePasAnalyzer)}
  173. writeln('TCustomTestOptimizations.ParseProgram START');
  174. {$ENDIF}
  175. AnalyzerProgram.AnalyzeWholeProgram(Module as TPasProgram);
  176. {$IF defined(VerbosePas2JS) or defined(VerbosePasAnalyzer)}
  177. writeln('TCustomTestOptimizations.ParseProgram START');
  178. {$ENDIF}
  179. end;
  180. function TCustomTestOptimizations.CreateConverter: TPasToJSConverter;
  181. begin
  182. Result:=inherited CreateConverter;
  183. Result.OnIsElementUsed:=@OnConverterIsElementUsed;
  184. Result.OnIsTypeInfoUsed:=@OnConverterIsTypeInfoUsed;
  185. end;
  186. { TTestOptimizations }
  187. procedure TTestOptimizations.TestOptShortRefGlobals_Program;
  188. begin
  189. AddModuleWithIntfImplSrc('UnitA.pas',
  190. LinesToStr([
  191. 'type',
  192. ' TColor = (red,green,blue);',
  193. ' TColors = set of TColor;',
  194. 'const',
  195. ' cRedBlue = [red,blue];',
  196. 'type',
  197. ' TBird = class',
  198. ' public',
  199. ' class var c: word;',
  200. ' class function Run(w: word): word; virtual; abstract;',
  201. ' end;',
  202. ' TRec = record',
  203. ' x: word;',
  204. ' end;',
  205. 'var b: TBird;',
  206. '']),
  207. LinesToStr([
  208. '']));
  209. StartProgram(true,[supTObject]);
  210. Add([
  211. '{$optimization JSShortRefGlobals}',
  212. 'uses unita;',
  213. 'type',
  214. ' TEagle = class(TBird)',
  215. ' class function Run(w: word = 5): word; override;',
  216. ' end;',
  217. 'class function TEagle.Run(w: word): word;',
  218. 'begin',
  219. 'end;',
  220. 'var',
  221. ' e: TEagle;',
  222. ' r: TRec;',
  223. ' c: TColors;',
  224. 'begin',
  225. ' e:=TEagle.Create;',
  226. ' b:=TBird.Create;',
  227. ' e.c:=e.c+1;',
  228. ' r.x:=TBird.c;',
  229. ' r.x:=b.c;',
  230. ' r.x:=e.Run;',
  231. ' r.x:=e.Run();',
  232. ' r.x:=e.Run(4);',
  233. ' c:=cRedBlue;',
  234. '']);
  235. ConvertProgram;
  236. CheckSource('TestOptShortRefGlobals_Program',
  237. LinesToStr([
  238. 'var $lt = null;',
  239. 'var $lm = pas.UnitA;',
  240. 'var $lt1 = $lm.TBird;',
  241. 'var $lt2 = $lm.TRec;',
  242. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  243. ' $lt = this;',
  244. ' this.Run = function (w) {',
  245. ' var Result = 0;',
  246. ' return Result;',
  247. ' };',
  248. '});',
  249. 'this.e = null;',
  250. 'this.r = $lt2.$new();',
  251. 'this.c = {};',
  252. '']),
  253. LinesToStr([
  254. '$mod.e = $lt.$create("Create");',
  255. '$lm.b = $lt1.$create("Create");',
  256. '$lt1.c = $mod.e.c + 1;',
  257. '$mod.r.x = $lt1.c;',
  258. '$mod.r.x = $lm.b.c;',
  259. '$mod.r.x = $mod.e.$class.Run(5);',
  260. '$mod.r.x = $mod.e.$class.Run(5);',
  261. '$mod.r.x = $mod.e.$class.Run(4);',
  262. '$mod.c = rtl.refSet($lm.cRedBlue);',
  263. '']));
  264. end;
  265. procedure TTestOptimizations.TestOptShortRefGlobals_Unit_FromIntfImpl_ToIntfImpl;
  266. begin
  267. AddModuleWithIntfImplSrc('UnitA.pas',
  268. LinesToStr([
  269. 'type',
  270. ' TBird = class',
  271. ' public Speed: word;',
  272. ' end;',
  273. ' TRecA = record',
  274. ' x: word;',
  275. ' end;',
  276. 'var Bird: TBird;',
  277. '']),
  278. LinesToStr([
  279. '']));
  280. AddModuleWithIntfImplSrc('UnitB.pas',
  281. LinesToStr([
  282. 'type',
  283. ' TAnt = class',
  284. ' public Size: word;',
  285. ' end;',
  286. ' TRecB = record',
  287. ' y: word;',
  288. ' end;',
  289. ' TBear = class',
  290. ' end;',
  291. ' TFrog = class',
  292. ' end;',
  293. 'var Ant: TAnt;',
  294. '']),
  295. LinesToStr([
  296. '']));
  297. StartUnit(true,[supTObject]);
  298. Add([
  299. '{$optimization JSShortRefGlobals}',
  300. 'interface',
  301. 'uses unita;',
  302. 'type',
  303. ' TEagle = class(TBird)', // intf-JS to intf-uses
  304. ' procedure Fly;',
  305. ' end;',
  306. 'implementation',
  307. 'uses unitb;',
  308. 'type',
  309. ' TRedAnt = class(TAnt)', // impl-JS to impl-uses
  310. ' procedure Run;',
  311. ' end;',
  312. 'procedure TEagle.Fly;',
  313. 'begin',
  314. ' TRedAnt.Create;', // intf-JS to impl-JS
  315. ' TAnt.Create;', // intf-JS to impl-uses
  316. ' TBird.Create;', // intf-JS to intf-uses
  317. ' TEagle.Create;', // intf-JS to intf-JS
  318. 'end;',
  319. 'procedure TRedAnt.Run;',
  320. 'begin',
  321. ' TRedAnt.Create;', // impl-JS to impl-JS
  322. ' TAnt.Create;', // impl-JS to impl-uses
  323. ' TBird.Create;', // impl-JS to intf-uses
  324. ' TEagle.Create;', // impl-JS to intf-JS
  325. ' TBear.Create', // only in impl-JS to impl-uses
  326. 'end;',
  327. 'var',
  328. ' RedAnt: TRedAnt;',
  329. ' Ant: TAnt;',
  330. ' Bird: TBird;',
  331. ' Eagle: TEagle;',
  332. 'initialization',
  333. ' RedAnt:=TRedAnt.Create;', // init to impl-JS
  334. ' Ant:=TAnt.Create;', // init to impl-uses
  335. ' Bird:=TBird.Create;', // init to intf-uses
  336. ' Eagle:=TEagle.Create;', // init to intf-JS
  337. ' TFrog.Create;', // only in init to impl-uses
  338. ' Eagle.Fly;',
  339. ' RedAnt.Run;',
  340. '']);
  341. ConvertUnit;
  342. CheckSource('TestOptShortRefGlobals_Unit_FromIntfImpl_ToIntfImpl',
  343. LinesToStr([
  344. 'var $impl = $mod.$impl;',
  345. 'var $lt = null;',
  346. 'var $lt1 = null;',
  347. 'var $lm = pas.UnitA;',
  348. 'var $lt2 = $lm.TBird;',
  349. 'var $lm1 = null;',
  350. 'var $lt3 = null;',
  351. 'var $lt4 = null;',
  352. 'var $lt5 = null;',
  353. 'rtl.createClass(this, "TEagle", $lt2, function () {',
  354. ' $lt = this;',
  355. ' this.Fly = function () {',
  356. ' $lt1.$create("Create");',
  357. ' $lt3.$create("Create");',
  358. ' $lt2.$create("Create");',
  359. ' $lt.$create("Create");',
  360. ' };',
  361. '});',
  362. '']),
  363. LinesToStr([
  364. '$impl.RedAnt = $lt1.$create("Create");',
  365. '$impl.Ant = $lt3.$create("Create");',
  366. '$impl.Bird = $lt2.$create("Create");',
  367. '$impl.Eagle = $lt.$create("Create");',
  368. '$lt5.$create("Create");',
  369. '$impl.Eagle.Fly();',
  370. '$impl.RedAnt.Run();',
  371. '']),
  372. LinesToStr([
  373. '$lm1 = pas.UnitB;',
  374. '$lt3 = $lm1.TAnt;',
  375. '$lt4 = $lm1.TBear;',
  376. '$lt5 = $lm1.TFrog;',
  377. 'rtl.createClass($impl, "TRedAnt", $lt3, function () {',
  378. ' $lt1 = this;',
  379. ' this.Run = function () {',
  380. ' $lt1.$create("Create");',
  381. ' $lt3.$create("Create");',
  382. ' $lt2.$create("Create");',
  383. ' $lt.$create("Create");',
  384. ' $lt4.$create("Create");',
  385. ' };',
  386. '});',
  387. '$impl.RedAnt = null;',
  388. '$impl.Ant = null;',
  389. '$impl.Bird = null;',
  390. '$impl.Eagle = null;',
  391. '']));
  392. end;
  393. procedure TTestOptimizations.TestOptShortRefGlobals_Enums;
  394. begin
  395. AddModuleWithIntfImplSrc('UnitA.pas',
  396. LinesToStr([
  397. 'type',
  398. ' TColor = (red,green,blue);',
  399. '',
  400. '']),
  401. LinesToStr([
  402. '']));
  403. AddModuleWithIntfImplSrc('UnitB.pas',
  404. LinesToStr([
  405. 'type',
  406. ' TSize = (small,big);',
  407. '',
  408. '']),
  409. LinesToStr([
  410. '']));
  411. StartUnit(true,[supWriteln]);
  412. Add([
  413. '{$optimization JSShortRefGlobals}',
  414. 'interface',
  415. 'uses unita;',
  416. 'const',
  417. ' ColorRed = TColor.Red;',
  418. 'procedure Fly;',
  419. 'implementation',
  420. 'uses unitb;',
  421. 'const',
  422. ' SizeSmall = TSize.Small;',
  423. 'procedure Fly;',
  424. 'begin',
  425. ' writeln(ColorRed);',
  426. ' writeln(TColor.Blue);',
  427. ' writeln(SizeSmall);',
  428. ' writeln(TSize.Big);',
  429. ' writeln(unitb.TSize.Big);',
  430. 'end;',
  431. '']);
  432. ConvertUnit;
  433. CheckSource('TestOptShortRefGlobals_Enums',
  434. LinesToStr([
  435. 'var $impl = $mod.$impl;',
  436. 'var $lm = pas.UnitA;',
  437. 'var $lt = $lm.TColor;',
  438. 'var $lt1 = $lt.red;',
  439. 'var $lt2 = $lt.blue;',
  440. 'var $lm1 = null;',
  441. 'var $lt3 = null;',
  442. 'var $lt4 = null;',
  443. 'var $lt5 = null;',
  444. 'this.ColorRed = $lt1;',
  445. 'this.Fly = function () {',
  446. ' console.log($lt1);',
  447. ' console.log($lt2);',
  448. ' console.log($lt4);',
  449. ' console.log($lt5);',
  450. ' console.log($lt5);',
  451. '};',
  452. '']),
  453. LinesToStr([
  454. '']),
  455. LinesToStr([
  456. '$lm1 = pas.UnitB;',
  457. '$lt3 = $lm1.TSize;',
  458. '$lt4 = $lt3.small;',
  459. '$lt5 = $lt3.big;',
  460. '$impl.SizeSmall = $lt4;',
  461. '']));
  462. end;
  463. procedure TTestOptimizations.TestOptShortRefGlobals_Property;
  464. begin
  465. AddModuleWithIntfImplSrc('UnitA.pas',
  466. LinesToStr([
  467. 'type',
  468. ' TBird = class',
  469. ' FWing: TObject;',
  470. ' class var FLeg: TObject;',
  471. ' public',
  472. ' property Wing: TObject read FWing write FWing;',
  473. ' class property Leg: TObject read FLeg write FLeg;',
  474. ' end;',
  475. '']),
  476. LinesToStr([
  477. '']));
  478. StartUnit(true,[supTObject]);
  479. Add([
  480. '{$optimization JSShortRefGlobals}',
  481. 'interface',
  482. 'uses unita;',
  483. 'type',
  484. ' TEagle = class(TBird)', // intf-JS to intf-uses
  485. ' procedure Fly(o: TObject);',
  486. ' end;',
  487. 'implementation',
  488. 'procedure TEagle.Fly(o: TObject);',
  489. 'begin',
  490. ' Fly(Wing);',
  491. ' Fly(Leg);',
  492. 'end;',
  493. '']);
  494. ConvertUnit;
  495. CheckSource('TestOptShortRefGlobals_Property',
  496. LinesToStr([
  497. 'var $lt = null;',
  498. 'var $lm = pas.UnitA;',
  499. 'var $lt1 = $lm.TBird;',
  500. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  501. ' $lt = this;',
  502. ' this.Fly = function (o) {',
  503. ' this.Fly(this.FWing);',
  504. ' this.Fly(this.FLeg);',
  505. ' };',
  506. '});',
  507. '']),
  508. LinesToStr([
  509. '']),
  510. LinesToStr([
  511. '']));
  512. end;
  513. procedure TTestOptimizations.TestOptShortRefGlobals_ExternalAbstract;
  514. begin
  515. AddModuleWithIntfImplSrc('UnitA.pas',
  516. LinesToStr([
  517. 'type',
  518. ' TBird = class',
  519. ' generic function FlyExt<T>(a: word = 103): T; external name ''Flying'';',
  520. ' class procedure JumpVirtual(a: word = 104); virtual; abstract;',
  521. ' class procedure RunStaticExt(a: word = 105); static; external name ''Running'';',
  522. ' end;',
  523. 'procedure SayExt(a: word = 106); external name ''Saying'';',
  524. '']),
  525. LinesToStr([
  526. '']));
  527. StartUnit(true,[supTObject]);
  528. Add([
  529. '{$optimization JSShortRefGlobals}',
  530. 'interface',
  531. 'uses unita;',
  532. 'type',
  533. ' TEagle = class(TBird)',
  534. ' procedure Test;',
  535. ' end;',
  536. 'implementation',
  537. 'procedure TEagle.Test;',
  538. 'begin',
  539. ' specialize FlyExt<Word>;',
  540. ' specialize FlyExt<Word>(1);',
  541. ' specialize JumpVirtual;',
  542. ' specialize JumpVirtual(2);',
  543. ' specialize RunStaticExt;',
  544. ' specialize RunStaticExt(3);',
  545. ' specialize SayExt;',
  546. ' specialize SayExt(4);',
  547. ' Self.specialize FlyExt<Word>;',
  548. ' Self.specialize FlyExt<Word>(11);',
  549. ' Self.specialize JumpVirtual;',
  550. ' Self.specialize JumpVirtual(12);',
  551. ' Self.specialize RunStaticExt;',
  552. ' Self.specialize RunStaticExt(13);',
  553. ' with Self do begin',
  554. ' specialize FlyExt<Word>;',
  555. ' specialize FlyExt<Word>(21);',
  556. ' specialize JumpVirtual;',
  557. ' specialize JumpVirtual(22);',
  558. ' specialize RunStaticExt;',
  559. ' specialize RunStaticExt(23);',
  560. ' end;',
  561. 'end;',
  562. '']);
  563. ConvertUnit;
  564. CheckSource('TestOptShortRefGlobals_ExternalAbstract',
  565. LinesToStr([
  566. 'var $lt = null;',
  567. 'var $lm = pas.UnitA;',
  568. 'var $lt1 = $lm.TBird;',
  569. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  570. ' $lt = this;',
  571. ' this.Test = function () {',
  572. ' this.Flying(103);',
  573. ' this.Flying(1);',
  574. ' this.$class.JumpVirtual(104);',
  575. ' this.$class.JumpVirtual(2);',
  576. ' this.Running(105);',
  577. ' this.Running(3);',
  578. ' Saying(106);',
  579. ' Saying(4);',
  580. ' this.Flying(103);',
  581. ' this.Flying(11);',
  582. ' this.$class.JumpVirtual(104);',
  583. ' this.$class.JumpVirtual(12);',
  584. ' this.Running(105);',
  585. ' this.Running(13);',
  586. ' this.Flying(103);',
  587. ' this.Flying(21);',
  588. ' this.$class.JumpVirtual(104);',
  589. ' this.$class.JumpVirtual(22);',
  590. ' this.Running(105);',
  591. ' this.Running(23);',
  592. ' };',
  593. '});',
  594. '']),
  595. LinesToStr([
  596. '']),
  597. LinesToStr([
  598. '']));
  599. end;
  600. procedure TTestOptimizations.TestOptShortRefGlobals_Class;
  601. begin
  602. AddModuleWithIntfImplSrc('UnitA.pas',
  603. LinesToStr([
  604. 'type',
  605. ' TBird = class',
  606. ' end;',
  607. '']),
  608. LinesToStr([
  609. '']));
  610. StartUnit(true,[supTObject]);
  611. Add([
  612. '{$optimization JSShortRefGlobals}',
  613. 'interface',
  614. 'uses unita;',
  615. 'type',
  616. ' TEagle = class(TBird)',
  617. ' Size: TBird;',
  618. ' class var Color: TBird;',
  619. ' procedure Fly;',
  620. ' class procedure Run;',
  621. ' end;',
  622. 'implementation',
  623. 'procedure TEagle.Fly;',
  624. 'begin',
  625. ' Size:=Size;',
  626. ' Self.Size:=Self.Size;',
  627. ' Color:=Color;',
  628. ' Self.Color:=Self.Color;',
  629. 'end;',
  630. 'class procedure TEagle.Run;',
  631. 'begin',
  632. ' Color:=Color;',
  633. ' Self.Color:=Self.Color;',
  634. 'end;',
  635. '']);
  636. ConvertUnit;
  637. CheckSource('TestOptShortRefGlobals_Class',
  638. LinesToStr([
  639. 'var $lt = null;',
  640. 'var $lm = pas.UnitA;',
  641. 'var $lt1 = $lm.TBird;',
  642. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  643. ' $lt = this;',
  644. ' this.Color = null;',
  645. ' this.$init = function () {',
  646. ' $lt1.$init.call(this);',
  647. ' this.Size = null;',
  648. ' };',
  649. ' this.$final = function () {',
  650. ' this.Size = undefined;',
  651. ' $lt1.$final.call(this);',
  652. ' };',
  653. ' this.Fly = function () {',
  654. ' this.Size = this.Size;',
  655. ' this.Size = this.Size;',
  656. ' $lt.Color = this.Color;',
  657. ' $lt.Color = this.Color;',
  658. ' };',
  659. ' this.Run = function () {',
  660. ' $lt.Color = this.Color;',
  661. ' $lt.Color = this.Color;',
  662. ' };',
  663. '});',
  664. '']),
  665. LinesToStr([
  666. '']),
  667. LinesToStr([
  668. '']));
  669. end;
  670. procedure TTestOptimizations.TestOptShortRefGlobals_GenericFunction;
  671. begin
  672. AddModuleWithIntfImplSrc('UnitA.pas',
  673. LinesToStr([
  674. 'generic function Run<T>(a: T): T;',
  675. '']),
  676. LinesToStr([
  677. 'generic function Run<T>(a: T): T;',
  678. 'begin',
  679. 'end;',
  680. '']));
  681. StartUnit(true,[supTObject]);
  682. Add([
  683. '{$optimization JSShortRefGlobals}',
  684. 'interface',
  685. 'uses unita;',
  686. 'type',
  687. ' TEagle = class',
  688. ' end;',
  689. 'procedure Fly;',
  690. 'implementation',
  691. 'procedure Fly;',
  692. 'begin',
  693. ' specialize Run<TEagle>(nil);',
  694. 'end;',
  695. '']);
  696. ConvertUnit;
  697. CheckSource('TestOptShortRefGlobals_GenericFunction',
  698. LinesToStr([
  699. 'var $lt = null;',
  700. 'var $lm = pas.system;',
  701. 'var $lt1 = $lm.TObject;',
  702. 'var $lm1 = pas.UnitA;',
  703. 'var $lp = $lm1.Run$G1;',
  704. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  705. ' $lt = this;',
  706. '});',
  707. 'this.Fly = function () {',
  708. ' $lp(null);',
  709. '};',
  710. '']),
  711. LinesToStr([
  712. '']),
  713. LinesToStr([
  714. '']));
  715. end;
  716. procedure TTestOptimizations.TestOptShortRefGlobals_GenericMethod_Call;
  717. begin
  718. AddModuleWithIntfImplSrc('UnitA.pas',
  719. LinesToStr([
  720. 'type',
  721. ' TBird = class',
  722. ' generic function Fly<T>(a: word = 13): T;',
  723. ' generic class function Jump<T>(b: word = 14): T;',
  724. ' end;',
  725. '']),
  726. LinesToStr([
  727. 'generic function TBird.Fly<T>(a: word): T;',
  728. 'begin',
  729. 'end;',
  730. 'generic class function TBird.Jump<T>(b: word): T;',
  731. 'begin',
  732. 'end;',
  733. '']));
  734. StartUnit(true,[supTObject]);
  735. Add([
  736. '{$optimization JSShortRefGlobals}',
  737. 'interface',
  738. 'uses unita;',
  739. 'type',
  740. ' TEagle = class(TBird)',
  741. ' procedure Test;',
  742. ' generic function Run<T>(c: word = 25): T;',
  743. ' generic class function Sing<T>(d: word = 26): T;',
  744. ' end;',
  745. 'implementation',
  746. 'procedure TEagle.Test;',
  747. 'begin',
  748. ' specialize Run<Word>;',
  749. ' specialize Run<Word>(1);',
  750. ' specialize Sing<Word>;',
  751. ' specialize Sing<Word>(2);',
  752. ' specialize Fly<Word>;',
  753. ' specialize Fly<Word>(3);',
  754. ' specialize Jump<Word>;',
  755. ' specialize Jump<Word>(4);',
  756. ' Self.specialize Fly<Word>;',
  757. ' Self.specialize Fly<Word>(5);',
  758. ' Self.specialize Jump<Word>;',
  759. ' Self.specialize Jump<Word>(6);',
  760. ' with Self do begin',
  761. ' specialize Fly<Word>;',
  762. ' specialize Fly<Word>(7);',
  763. ' specialize Jump<Word>;',
  764. ' specialize Jump<Word>(8);',
  765. ' end;',
  766. 'end;',
  767. 'generic function TEagle.Run<T>(c: word): T;',
  768. 'begin',
  769. ' specialize Fly<T>;',
  770. ' specialize Fly<T>(7);',
  771. 'end;',
  772. 'generic class function TEagle.Sing<T>(d: word): T;',
  773. 'begin',
  774. ' specialize Jump<T>;',
  775. ' specialize Jump<T>(8);',
  776. 'end;',
  777. '']);
  778. ConvertUnit;
  779. CheckSource('TestOptShortRefGlobals_GenericMethod_Call',
  780. LinesToStr([
  781. 'var $lt = null;',
  782. 'var $lp = null;',
  783. 'var $lp1 = null;',
  784. 'var $lm = pas.UnitA;',
  785. 'var $lt1 = $lm.TBird;',
  786. 'var $lp2 = $lt1.Fly$G1;',
  787. 'var $lp3 = $lt1.Jump$G1;',
  788. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  789. ' $lt = this;',
  790. ' this.Test = function () {',
  791. ' $lp.apply(this, 25);',
  792. ' $lp.apply(this, 1);',
  793. ' $lp1.apply(this.$class, 26);',
  794. ' $lp1.apply(this.$class, 2);',
  795. ' $lp2.apply(this, 13);',
  796. ' $lp2.apply(this, 3);',
  797. ' $lp3.apply(this.$class, 14);',
  798. ' $lp3.apply(this.$class, 4);',
  799. ' $lp2.apply(this, 13);',
  800. ' $lp2.apply(this, 5);',
  801. ' $lp3.apply(this.$class, 14);',
  802. ' $lp3.apply(this, 6);',
  803. ' $lp2.apply(this, 13);',
  804. ' $lp2.apply(this, 7);',
  805. ' $lp3.apply(this.$class, 14);',
  806. ' $lp3.apply(this.$class, 8);',
  807. ' };',
  808. ' this.Run$G1 = $lp = function (c) {',
  809. ' var Result = 0;',
  810. ' $lp2.apply(this, 13);',
  811. ' $lp2.apply(this, 7);',
  812. ' return Result;',
  813. ' };',
  814. ' this.Sing$G1 = $lp1 = function (d) {',
  815. ' var Result = 0;',
  816. ' $lp3.apply(this, 14);',
  817. ' $lp3.apply(this, 8);',
  818. ' return Result;',
  819. ' };',
  820. '});',
  821. '']),
  822. LinesToStr([
  823. '']),
  824. LinesToStr([
  825. '']));
  826. end;
  827. procedure TTestOptimizations.TestOptShortRefGlobals_GenericStaticMethod_Call;
  828. begin
  829. AddModuleWithIntfImplSrc('UnitA.pas',
  830. LinesToStr([
  831. 'type',
  832. ' TBird = class',
  833. ' generic class function Fly<T>(a: word = 13): T; static;',
  834. ' class function Say(a: word = 13): word; static;',
  835. ' end;',
  836. '']),
  837. LinesToStr([
  838. 'generic class function TBird.Fly<T>(a: word): T;',
  839. 'begin',
  840. 'end;',
  841. 'class function TBird.Say(a: word): word;',
  842. 'begin',
  843. 'end;',
  844. '']));
  845. StartUnit(true,[supTObject]);
  846. Add([
  847. '{$optimization JSShortRefGlobals}',
  848. 'interface',
  849. 'uses unita;',
  850. 'type',
  851. ' TEagle = class(TBird)',
  852. ' procedure Test;',
  853. ' generic class function Run<T>(c: word = 25): T; static;',
  854. ' class function Lay(c: word = 25): word; static;',
  855. ' end;',
  856. 'implementation',
  857. 'procedure TEagle.Test;',
  858. 'begin',
  859. ' specialize Fly<Word>;',
  860. ' specialize Fly<Word>(31);',
  861. ' Say;',
  862. ' Say(32);',
  863. ' specialize Run<Word>;',
  864. ' specialize Run<Word>(33);',
  865. ' Lay;',
  866. ' Lay(34);',
  867. ' self.specialize Fly<Word>;',
  868. ' self.specialize Fly<Word>(41);',
  869. ' self.Say;',
  870. ' self.Say(42);',
  871. ' self.specialize Run<Word>;',
  872. ' self.specialize Run<Word>(43);',
  873. ' with Self do begin',
  874. ' specialize Fly<Word>;',
  875. ' specialize Fly<Word>(51);',
  876. ' Say;',
  877. ' Say(52);',
  878. ' specialize Run<Word>;',
  879. ' specialize Run<Word>(53);',
  880. ' end;',
  881. 'end;',
  882. 'generic class function TEagle.Run<T>(c: word): T;',
  883. 'begin',
  884. 'end;',
  885. 'class function TEagle.Lay(c: word): word;',
  886. 'begin',
  887. ' TEagle.specialize Fly<Word>;',
  888. ' TEagle.specialize Fly<Word>(61);',
  889. ' TEagle.Say;',
  890. ' TEagle.Say(62);',
  891. ' TEagle.specialize Run<Word>;',
  892. ' specialize Run<Word>(63);',
  893. ' Lay;',
  894. ' Lay(64);',
  895. 'end;',
  896. '']);
  897. ConvertUnit;
  898. CheckSource('TestOptShortRefGlobals_GenericStaticMethod_Call',
  899. LinesToStr([
  900. 'var $lt = null;',
  901. 'var $lp = null;',
  902. 'var $lm = pas.UnitA;',
  903. 'var $lt1 = $lm.TBird;',
  904. 'var $lp1 = $lt1.Fly$G1;',
  905. 'var $lp2 = $lt1.Say;',
  906. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  907. ' $lt = this;',
  908. ' this.Test = function () {',
  909. ' $lp1(13);',
  910. ' $lp1(31);',
  911. ' $lp2(13);',
  912. ' $lp2(32);',
  913. ' $lp(25);',
  914. ' $lp(33);',
  915. ' $lt.Lay(25);',
  916. ' $lt.Lay(34);',
  917. ' $lp1(13);',
  918. ' $lp1(41);',
  919. ' $lp2(13);',
  920. ' $lp2(42);',
  921. ' $lp(25);',
  922. ' $lp(43);',
  923. ' $lp1(13);',
  924. ' $lp1(51);',
  925. ' $lp2(13);',
  926. ' $lp2(52);',
  927. ' $lp(25);',
  928. ' $lp(53);',
  929. ' };',
  930. ' this.Lay = function (c) {',
  931. ' var Result = 0;',
  932. ' $lp1(13);',
  933. ' $lp1(61);',
  934. ' $lp2(13);',
  935. ' $lp2(62);',
  936. ' $lp(25);',
  937. ' $lp(63);',
  938. ' $lt.Lay(25);',
  939. ' $lt.Lay(64);',
  940. ' return Result;',
  941. ' };',
  942. ' this.Run$G1 = $lp = function (c) {',
  943. ' var Result = 0;',
  944. ' return Result;',
  945. ' };',
  946. '});',
  947. '']),
  948. LinesToStr([
  949. '']),
  950. LinesToStr([
  951. '']));
  952. end;
  953. procedure TTestOptimizations.TestOptShortRefGlobals_GenericClassHelperMethod;
  954. begin
  955. AddModuleWithIntfImplSrc('UnitA.pas',
  956. LinesToStr([
  957. 'type',
  958. ' TBird = class',
  959. ' end;',
  960. ' TBirdHelper = class helper for TBird',
  961. ' generic function Fly<T>(a: word = 13): T;',
  962. ' generic class function Say<T>(a: word = 13): T;',
  963. ' end;',
  964. '']),
  965. LinesToStr([
  966. 'generic function TBirdHelper.Fly<T>(a: word): T;',
  967. 'begin',
  968. 'end;',
  969. 'generic class function TBirdHelper.Say<T>(a: word): T;',
  970. 'begin',
  971. 'end;',
  972. '']));
  973. StartUnit(true,[supTObject]);
  974. Add([
  975. '{$optimization JSShortRefGlobals}',
  976. 'interface',
  977. 'uses unita;',
  978. 'type',
  979. ' TEagle = class(TBird)',
  980. ' procedure Test;',
  981. ' class procedure Lay;',
  982. ' end;',
  983. 'implementation',
  984. 'procedure TEagle.Test;',
  985. 'begin',
  986. ' specialize Fly<Word>;',
  987. ' specialize Fly<Word>(31);',
  988. ' specialize Say<word>;',
  989. ' specialize Say<Word>(32);',
  990. ' self.specialize Fly<Word>;',
  991. ' self.specialize Fly<Word>(41);',
  992. ' self.specialize Say<Word>;',
  993. ' self.specialize Say<Word>(42);',
  994. ' with Self do begin',
  995. ' specialize Fly<Word>;',
  996. ' specialize Fly<Word>(51);',
  997. ' specialize Say<Word>;',
  998. ' specialize Say<Word>(52);',
  999. ' end;',
  1000. 'end;',
  1001. 'class procedure TEagle.Lay;',
  1002. 'begin',
  1003. ' specialize Say<Word>;',
  1004. ' specialize Say<Word>(32);',
  1005. ' self.specialize Say<Word>;',
  1006. ' self.specialize Say<Word>(42);',
  1007. ' with Self do begin',
  1008. ' specialize Say<Word>;',
  1009. ' specialize Say<Word>(52);',
  1010. ' end;',
  1011. 'end;',
  1012. '']);
  1013. ConvertUnit;
  1014. CheckSource('TestOptShortRefGlobals_GenericClassHelperMethod',
  1015. LinesToStr([
  1016. 'var $lt = null;',
  1017. 'var $lm = pas.UnitA;',
  1018. 'var $lt1 = $lm.TBird;',
  1019. 'var $lt2 = $lm.TBirdHelper;',
  1020. 'var $lp = $lt2.Fly$G1;',
  1021. 'var $lp1 = $lt2.Say$G1;',
  1022. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  1023. ' $lt = this;',
  1024. ' this.Test = function () {',
  1025. ' $lp.call(this, 13);',
  1026. ' $lp.call(this, 31);',
  1027. ' $lp1.call(this.$class, 13);',
  1028. ' $lp1.call(this.$class, 32);',
  1029. ' $lp.call(this, 13);',
  1030. ' $lp.call(this, 41);',
  1031. ' $lp1.call(this.$class, 13);',
  1032. ' $lp1.call(this.$class, 42);',
  1033. ' $lp.call(this, 13);',
  1034. ' $lp.call(this, 51);',
  1035. ' $lp1.call(this.$class, 13);',
  1036. ' $lp1.call(this.$class, 52);',
  1037. ' };',
  1038. ' this.Lay = function () {',
  1039. ' $lp1.call(this, 13);',
  1040. ' $lp1.call(this, 32);',
  1041. ' $lp1.call(this, 13);',
  1042. ' $lp1.call(this, 42);',
  1043. ' $lp1.call(this, 13);',
  1044. ' $lp1.call(this, 52);',
  1045. ' };',
  1046. '});',
  1047. '']),
  1048. LinesToStr([
  1049. '']),
  1050. LinesToStr([
  1051. '']));
  1052. end;
  1053. procedure TTestOptimizations.TestOptShortRefGlobals_GenericMethod_ProcVar;
  1054. begin
  1055. AddModuleWithIntfImplSrc('UnitA.pas',
  1056. LinesToStr([
  1057. '{$mode delphi}',
  1058. 'type',
  1059. ' TBird = class',
  1060. ' function Fly<T>(a: word = 13): T;',
  1061. ' class function Jump<T>(b: word = 14): T;',
  1062. ' end;',
  1063. '']),
  1064. LinesToStr([
  1065. 'function TBird.Fly<T>(a: word): T;',
  1066. 'begin',
  1067. 'end;',
  1068. 'class function TBird.Jump<T>(b: word): T;',
  1069. 'begin',
  1070. 'end;',
  1071. '']));
  1072. StartUnit(true,[supTObject]);
  1073. Add([
  1074. '{$mode delphi}',
  1075. '{$optimization JSShortRefGlobals}',
  1076. 'interface',
  1077. 'uses unita;',
  1078. 'type',
  1079. ' TFunc<T> = function(a: word): T of object;',
  1080. ' TEagle = class(TBird)',
  1081. ' procedure Test;',
  1082. ' function Run<T>(c: word = 25): T;',
  1083. ' class function Sing<T>(d: word = 26): T;',
  1084. ' end;',
  1085. 'implementation',
  1086. 'procedure TEagle.Test;',
  1087. 'var f: TFunc<word>;',
  1088. 'begin',
  1089. ' f:=@Run<Word>;',
  1090. ' f:=@Sing<Word>;',
  1091. ' f:=@Fly<Word>;',
  1092. ' f:=@Jump<Word>;',
  1093. ' f:[email protected]<Word>;',
  1094. ' f:[email protected]<Word>;',
  1095. ' with Self do begin',
  1096. ' f:=@Fly<Word>;',
  1097. ' f:=@Jump<Word>;',
  1098. ' end;',
  1099. 'end;',
  1100. 'function TEagle.Run<T>(c: word): T;',
  1101. 'begin',
  1102. 'end;',
  1103. 'class function TEagle.Sing<T>(d: word): T;',
  1104. 'var f: TFunc<T>;',
  1105. 'begin',
  1106. ' f:=@Jump<T>;',
  1107. 'end;',
  1108. '']);
  1109. ConvertUnit;
  1110. CheckSource('TestOptShortRefGlobals_GenericMethod_ProcVar',
  1111. LinesToStr([
  1112. 'var $lt = null;',
  1113. 'var $lp = null;',
  1114. 'var $lp1 = null;',
  1115. 'var $lm = pas.UnitA;',
  1116. 'var $lt1 = $lm.TBird;',
  1117. 'var $lp2 = $lt1.Fly$G1;',
  1118. 'var $lp3 = $lt1.Jump$G1;',
  1119. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  1120. ' $lt = this;',
  1121. ' this.Test = function () {',
  1122. ' var f = null;',
  1123. ' f = rtl.createCallback(this, $lp);',
  1124. ' f = rtl.createCallback(this.$class, $lp1);',
  1125. ' f = rtl.createCallback(this, $lp2);',
  1126. ' f = rtl.createCallback(this.$class, $lp3);',
  1127. ' f = rtl.createCallback(this, $lp2);',
  1128. ' f = rtl.createCallback(this.$class, $lp3);',
  1129. ' f = rtl.createCallback(this, $lp2);',
  1130. ' f = rtl.createCallback(this.$class, $lp3);',
  1131. ' };',
  1132. ' this.Run$G1 = $lp = function (c) {',
  1133. ' var Result = 0;',
  1134. ' return Result;',
  1135. ' };',
  1136. ' this.Sing$G1 = $lp1 = function (d) {',
  1137. ' var Result = 0;',
  1138. ' var f = null;',
  1139. ' f = rtl.createCallback(this, $lp3);',
  1140. ' return Result;',
  1141. ' };',
  1142. '});',
  1143. '']),
  1144. LinesToStr([
  1145. '']),
  1146. LinesToStr([
  1147. '']));
  1148. end;
  1149. procedure TTestOptimizations.TestOptShortRefGlobals_GenericStaticMethod_ProcVar;
  1150. begin
  1151. AddModuleWithIntfImplSrc('UnitA.pas',
  1152. LinesToStr([
  1153. 'type',
  1154. ' TBird = class',
  1155. ' generic class function Fly<T>(a: word = 13): T; static;',
  1156. ' class function Say(a: word = 13): word; static;',
  1157. ' end;',
  1158. '']),
  1159. LinesToStr([
  1160. 'generic class function TBird.Fly<T>(a: word): T;',
  1161. 'begin',
  1162. 'end;',
  1163. 'class function TBird.Say(a: word): word;',
  1164. 'begin',
  1165. 'end;',
  1166. '']));
  1167. StartUnit(true,[supTObject]);
  1168. Add([
  1169. '{$optimization JSShortRefGlobals}',
  1170. 'interface',
  1171. 'uses unita;',
  1172. 'type',
  1173. ' TFunc = function(a: word): word;',
  1174. ' TEagle = class(TBird)',
  1175. ' procedure Test;',
  1176. ' generic class function Run<T>(c: word = 25): T; static;',
  1177. ' class function Lay(c: word = 25): word; static;',
  1178. ' end;',
  1179. 'implementation',
  1180. 'procedure TEagle.Test;',
  1181. 'var f: TFunc;',
  1182. 'begin',
  1183. ' F:=@specialize Fly<Word>;',
  1184. ' F:=@Say;',
  1185. ' F:=@specialize Run<Word>;',
  1186. ' F:=@Lay;',
  1187. ' F:[email protected] Fly<Word>;',
  1188. ' F:[email protected];',
  1189. ' F:[email protected] Run<Word>;',
  1190. ' with Self do begin',
  1191. ' F:=@specialize Fly<Word>;',
  1192. ' F:=@Say;',
  1193. ' F:=@specialize Run<Word>;',
  1194. ' end;',
  1195. 'end;',
  1196. 'generic class function TEagle.Run<T>(c: word): T;',
  1197. 'begin',
  1198. 'end;',
  1199. 'class function TEagle.Lay(c: word): word;',
  1200. 'var f: TFunc;',
  1201. 'begin',
  1202. ' f:[email protected] Fly<Word>;',
  1203. ' f:[email protected];',
  1204. ' f:[email protected] Run<Word>;',
  1205. ' f:=@Lay;',
  1206. 'end;',
  1207. '']);
  1208. ConvertUnit;
  1209. CheckSource('TestOptShortRefGlobals_GenericStaticMethod_ProcVar',
  1210. LinesToStr([
  1211. 'var $lt = null;',
  1212. 'var $lp = null;',
  1213. 'var $lm = pas.UnitA;',
  1214. 'var $lt1 = $lm.TBird;',
  1215. 'var $lp1 = $lt1.Fly$G1;',
  1216. 'var $lp2 = $lt1.Say;',
  1217. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  1218. ' $lt = this;',
  1219. ' this.Test = function () {',
  1220. ' var f = null;',
  1221. ' f = $lp1;',
  1222. ' f = $lp2;',
  1223. ' f = $lp;',
  1224. ' f = $lt.Lay;',
  1225. ' f = $lp1;',
  1226. ' f = $lp2;',
  1227. ' f = $lp;',
  1228. ' f = $lp1;',
  1229. ' f = $lp2;',
  1230. ' f = $lp;',
  1231. ' };',
  1232. ' this.Lay = function (c) {',
  1233. ' var Result = 0;',
  1234. ' var f = null;',
  1235. ' f = $lp1;',
  1236. ' f = $lp2;',
  1237. ' f = $lp;',
  1238. ' f = $lt.Lay;',
  1239. ' return Result;',
  1240. ' };',
  1241. ' this.Run$G1 = $lp = function (c) {',
  1242. ' var Result = 0;',
  1243. ' return Result;',
  1244. ' };',
  1245. '});',
  1246. '']),
  1247. LinesToStr([
  1248. '']),
  1249. LinesToStr([
  1250. '']));
  1251. end;
  1252. procedure TTestOptimizations.TestOptShortRefGlobals_SameUnit_EnumType;
  1253. begin
  1254. StartUnit(true,[supTObject]);
  1255. Add([
  1256. '{$optimization JSShortRefGlobals}',
  1257. 'interface',
  1258. 'type',
  1259. ' TBird = class',
  1260. ' type',
  1261. ' TFlag = (big,small);',
  1262. ' procedure Fly;',
  1263. ' end;',
  1264. ' TEnum = (red,blue);',
  1265. 'var',
  1266. ' e: TEnum;',
  1267. ' f: TBird.TFlag;',
  1268. 'procedure Run;',
  1269. 'implementation',
  1270. 'procedure TBird.Fly;',
  1271. 'begin',
  1272. ' e:=blue;',
  1273. ' f:=small;',
  1274. 'end;',
  1275. 'procedure Run;',
  1276. 'type TSub = (left,right);',
  1277. 'var s: TSub;',
  1278. 'begin',
  1279. ' e:=red;',
  1280. ' s:=right;',
  1281. ' f:=big;',
  1282. 'end;',
  1283. '']);
  1284. ConvertUnit;
  1285. CheckSource('TestOptShortRefGlobals_SameUnit_EnumType',
  1286. LinesToStr([
  1287. 'var $lt = null;',
  1288. 'var $lt1 = null;',
  1289. 'var $lt2 = null;',
  1290. 'var $lm = pas.system;',
  1291. 'var $lt3 = $lm.TObject;',
  1292. 'rtl.createClass(this, "TBird", $lt3, function () {',
  1293. ' $lt = this;',
  1294. ' $lt1 = this.TFlag = {',
  1295. ' "0": "big",',
  1296. ' big: 0,',
  1297. ' "1": "small",',
  1298. ' small: 1',
  1299. ' };',
  1300. ' this.Fly = function () {',
  1301. ' $mod.e = $lt2.blue;',
  1302. ' $mod.f = $lt1.small;',
  1303. ' };',
  1304. '});',
  1305. '$lt2 = this.TEnum = {',
  1306. ' "0": "red",',
  1307. ' red: 0,',
  1308. ' "1": "blue",',
  1309. ' blue: 1',
  1310. '};',
  1311. 'this.e = 0;',
  1312. 'this.f = 0;',
  1313. 'var TSub = {',
  1314. ' "0": "left",',
  1315. ' left: 0,',
  1316. ' "1": "right",',
  1317. ' right: 1',
  1318. '};',
  1319. 'this.Run = function () {',
  1320. ' var s = 0;',
  1321. ' $mod.e = $lt2.red;',
  1322. ' s = TSub.right;',
  1323. ' $mod.f = $lt1.big;',
  1324. '};',
  1325. '']),
  1326. LinesToStr([
  1327. '']),
  1328. LinesToStr([
  1329. '']));
  1330. end;
  1331. procedure TTestOptimizations.TestOptShortRefGlobals_SameUnit_ClassType;
  1332. begin
  1333. WithTypeInfo:=true;
  1334. StartUnit(true,[supTObject]);
  1335. Add([
  1336. '{$optimization JSShortRefGlobals}',
  1337. 'interface',
  1338. 'type',
  1339. ' TBird = class;',
  1340. ' TAnt = class',
  1341. ' type',
  1342. ' TLeg = class',
  1343. ' end;',
  1344. ' procedure Run;',
  1345. ' published',
  1346. ' Bird: TBird;',
  1347. ' end;',
  1348. ' TBird = class',
  1349. ' procedure Fly;',
  1350. ' end;',
  1351. 'implementation',
  1352. 'type',
  1353. ' TFrog = class',
  1354. ' end;',
  1355. 'procedure TAnt.Run;',
  1356. 'begin',
  1357. ' if typeinfo(TBird)=nil then;',
  1358. ' Bird:=TBird.Create;',
  1359. ' TLeg.Create;',
  1360. ' TFrog.Create;',
  1361. 'end;',
  1362. 'procedure TBird.Fly;',
  1363. 'begin',
  1364. ' if typeinfo(TAnt)=nil then;',
  1365. 'end;',
  1366. '']);
  1367. ConvertUnit;
  1368. CheckSource('TestOptShortRefGlobals_SameUnit_ClassType',
  1369. LinesToStr([
  1370. 'var $impl = $mod.$impl;',
  1371. 'var $lt = null;',
  1372. 'var $lt1 = null;',
  1373. 'var $lt2 = null;',
  1374. 'var $lt3 = null;',
  1375. 'var $lm = pas.system;',
  1376. 'var $lt4 = $lm.TObject;',
  1377. 'this.$rtti.$Class("TBird");',
  1378. 'rtl.createClass(this, "TAnt", $lt4, function () {',
  1379. ' $lt = this;',
  1380. ' rtl.createClass(this, "TLeg", $lt4, function () {',
  1381. ' $lt1 = this;',
  1382. ' }, "TAnt.TLeg");',
  1383. ' this.$init = function () {',
  1384. ' $lt4.$init.call(this);',
  1385. ' this.Bird = null;',
  1386. ' };',
  1387. ' this.$final = function () {',
  1388. ' this.Bird = undefined;',
  1389. ' $lt4.$final.call(this);',
  1390. ' };',
  1391. ' this.Run = function () {',
  1392. ' if ($mod.$rtti["TBird"] === null) ;',
  1393. ' this.Bird = $lt2.$create("Create");',
  1394. ' $lt1.$create("Create");',
  1395. ' $lt3.$create("Create");',
  1396. ' };',
  1397. ' var $r = this.$rtti;',
  1398. ' $r.addField("Bird", $mod.$rtti["TBird"], 4);',
  1399. '});',
  1400. 'rtl.createClass(this, "TBird", $lt4, function () {',
  1401. ' $lt2 = this;',
  1402. ' this.Fly = function () {',
  1403. ' if ($mod.$rtti["TAnt"] === null) ;',
  1404. ' };',
  1405. '});',
  1406. '']),
  1407. LinesToStr([
  1408. '']),
  1409. LinesToStr([
  1410. 'rtl.createClass($impl, "TFrog", $lt4, function () {',
  1411. ' $lt3 = this;',
  1412. '});',
  1413. '']));
  1414. end;
  1415. procedure TTestOptimizations.TestOptShortRefGlobals_SameUnit_RecordType;
  1416. begin
  1417. StartUnit(true,[supTObject]);
  1418. Add([
  1419. '{$optimization JSShortRefGlobals}',
  1420. '{$modeswitch advancedrecords}',
  1421. 'interface',
  1422. 'type',
  1423. ' TAnt = record',
  1424. ' type',
  1425. ' TLeg = record',
  1426. ' l: word;',
  1427. ' end;',
  1428. ' procedure Run;',
  1429. ' Leg: TLeg;',
  1430. ' end;',
  1431. 'implementation',
  1432. 'type',
  1433. ' TBird = record',
  1434. ' b: word;',
  1435. ' end;',
  1436. 'procedure TAnt.Run;',
  1437. 'type',
  1438. ' TFoot = record',
  1439. ' f: word;',
  1440. ' end;',
  1441. 'var',
  1442. ' b: TBird;',
  1443. ' l: TLeg;',
  1444. ' a: TAnt;',
  1445. ' f: TFoot;',
  1446. 'begin',
  1447. ' b.b:=1;',
  1448. ' l.l:=2;',
  1449. ' a.Leg.l:=3;',
  1450. ' f.f:=4;',
  1451. 'end;',
  1452. '']);
  1453. ConvertUnit;
  1454. CheckSource('TestOptShortRefGlobals_SameUnit_RecordType',
  1455. LinesToStr([
  1456. 'var $impl = $mod.$impl;',
  1457. 'var $lt = null;',
  1458. 'var $lt1 = null;',
  1459. 'var $lt2 = null;',
  1460. 'rtl.recNewT(this, "TAnt", function () {',
  1461. ' $lt = this;',
  1462. ' rtl.recNewT(this, "TLeg", function () {',
  1463. ' $lt1 = this;',
  1464. ' this.l = 0;',
  1465. ' this.$eq = function (b) {',
  1466. ' return this.l === b.l;',
  1467. ' };',
  1468. ' this.$assign = function (s) {',
  1469. ' this.l = s.l;',
  1470. ' return this;',
  1471. ' };',
  1472. ' });',
  1473. ' this.$new = function () {',
  1474. ' var r = Object.create(this);',
  1475. ' r.Leg = $lt1.$new();',
  1476. ' return r;',
  1477. ' };',
  1478. ' this.$eq = function (b) {',
  1479. ' return this.Leg.$eq(b.Leg);',
  1480. ' };',
  1481. ' this.$assign = function (s) {',
  1482. ' this.Leg.$assign(s.Leg);',
  1483. ' return this;',
  1484. ' };',
  1485. ' var TFoot = rtl.recNewT(null, "", function () {',
  1486. ' this.f = 0;',
  1487. ' this.$eq = function (b) {',
  1488. ' return this.f === b.f;',
  1489. ' };',
  1490. ' this.$assign = function (s) {',
  1491. ' this.f = s.f;',
  1492. ' return this;',
  1493. ' };',
  1494. ' });',
  1495. ' this.Run = function () {',
  1496. ' var b = $lt2.$new();',
  1497. ' var l = $lt1.$new();',
  1498. ' var a = $lt.$new();',
  1499. ' var f = TFoot.$new();',
  1500. ' b.b = 1;',
  1501. ' l.l = 2;',
  1502. ' a.Leg.l = 3;',
  1503. ' f.f = 4;',
  1504. ' };',
  1505. '}, true);',
  1506. '']),
  1507. LinesToStr([
  1508. '']),
  1509. LinesToStr([
  1510. 'rtl.recNewT($impl, "TBird", function () {',
  1511. ' $lt2 = this;',
  1512. ' this.b = 0;',
  1513. ' this.$eq = function (b) {',
  1514. ' return this.b === b.b;',
  1515. ' };',
  1516. ' this.$assign = function (s) {',
  1517. ' this.b = s.b;',
  1518. ' return this;',
  1519. ' };',
  1520. '});',
  1521. '']));
  1522. end;
  1523. procedure TTestOptimizations.TestOptShortRefGlobals_Unit_InitNoImpl;
  1524. begin
  1525. AddModuleWithIntfImplSrc('UnitA.pas',
  1526. LinesToStr([
  1527. 'var a: word;',
  1528. 'procedure Run(w: word);',
  1529. '']),
  1530. LinesToStr([
  1531. 'procedure Run(w: word);',
  1532. 'begin',
  1533. 'end;',
  1534. '']));
  1535. StartUnit(true,[supTObject]);
  1536. Add([
  1537. '{$optimization JSShortRefGlobals}',
  1538. 'interface',
  1539. 'implementation',
  1540. 'uses UnitA;', // empty implementation function
  1541. 'begin',
  1542. ' Run(a);',
  1543. '']);
  1544. ConvertUnit;
  1545. CheckSource('TestOptShortRefGlobals_Unit_InitNoImpl',
  1546. LinesToStr([
  1547. 'var $impl = $mod.$impl;',
  1548. 'var $lm = null;',
  1549. 'var $lp = null;',
  1550. '']),
  1551. LinesToStr([
  1552. '$lp($lm.a);',
  1553. '']),
  1554. LinesToStr([
  1555. '$lm = pas.UnitA;',
  1556. '$lp = $lm.Run;',
  1557. '']));
  1558. end;
  1559. procedure TTestOptimizations.TestObfuscateLocalIdentifiers_Program;
  1560. begin
  1561. exit;
  1562. StartProgram(true,[supTObject]);
  1563. Add([
  1564. '{$optimization JSObfuscateLocalIdentifiers}',
  1565. 'uses unita;',
  1566. 'type',
  1567. ' TEagle = class(TBird)',
  1568. ' class function Run(w: word = 5): word; override;',
  1569. ' end;',
  1570. 'class function TEagle.Run(w: word): word;',
  1571. 'begin',
  1572. 'end;',
  1573. 'var',
  1574. ' e: TEagle;',
  1575. ' r: TRec;',
  1576. ' c: TColors;',
  1577. 'begin',
  1578. ' e:=TEagle.Create;',
  1579. ' b:=TBird.Create;',
  1580. ' e.c:=e.c+1;',
  1581. ' r.x:=TBird.c;',
  1582. ' r.x:=b.c;',
  1583. ' r.x:=e.Run;',
  1584. ' r.x:=e.Run();',
  1585. ' r.x:=e.Run(4);',
  1586. ' c:=cRedBlue;',
  1587. '']);
  1588. ConvertProgram;
  1589. CheckSource('TestOptShortRefGlobals_Program',
  1590. LinesToStr([
  1591. 'var $lt = null;',
  1592. 'var $lm = pas.UnitA;',
  1593. 'var $lt1 = $lm.TBird;',
  1594. 'var $lt2 = $lm.TRec;',
  1595. 'rtl.createClass(this, "TEagle", $lt1, function () {',
  1596. ' $lt = this;',
  1597. ' this.Run = function (w) {',
  1598. ' var Result = 0;',
  1599. ' return Result;',
  1600. ' };',
  1601. '});',
  1602. 'this.e = null;',
  1603. 'this.r = $lt2.$new();',
  1604. 'this.c = {};',
  1605. '']),
  1606. LinesToStr([
  1607. '$mod.e = $lt.$create("Create");',
  1608. '$lm.b = $lt1.$create("Create");',
  1609. '$lt1.c = $mod.e.c + 1;',
  1610. '$mod.r.x = $lt1.c;',
  1611. '$mod.r.x = $lm.b.c;',
  1612. '$mod.r.x = $mod.e.$class.Run(5);',
  1613. '$mod.r.x = $mod.e.$class.Run(5);',
  1614. '$mod.r.x = $mod.e.$class.Run(4);',
  1615. '$mod.c = rtl.refSet($lm.cRedBlue);',
  1616. '']));
  1617. end;
  1618. procedure TTestOptimizations.TestWPO_OmitLocalVar;
  1619. begin
  1620. StartProgram(false);
  1621. Add('var');
  1622. Add(' a: longint;');
  1623. Add(' b: longint;');
  1624. Add('begin');
  1625. Add(' b:=3;');
  1626. ConvertProgram;
  1627. CheckSource('TestWPO_OmitLocalVar',
  1628. 'this.b = 0;',
  1629. '$mod.b = 3;');
  1630. end;
  1631. procedure TTestOptimizations.TestWPO_OmitLocalProc;
  1632. begin
  1633. StartProgram(false);
  1634. Add('procedure DoIt; begin end;');
  1635. Add('procedure NoIt; begin end;');
  1636. Add('begin');
  1637. Add(' DoIt;');
  1638. ConvertProgram;
  1639. CheckSource('TestWPO_OmitLocalProc',
  1640. LinesToStr([
  1641. 'this.DoIt = function () {',
  1642. '};',
  1643. '']),
  1644. LinesToStr([
  1645. '$mod.DoIt();',
  1646. '']));
  1647. end;
  1648. procedure TTestOptimizations.TestWPO_OmitLocalProcForward;
  1649. begin
  1650. StartProgram(false);
  1651. Add('procedure DoIt; forward;');
  1652. Add('procedure NoIt; forward;');
  1653. Add('procedure DoIt; begin end;');
  1654. Add('procedure NoIt; begin end;');
  1655. Add('begin');
  1656. Add(' DoIt;');
  1657. ConvertProgram;
  1658. CheckSource('TestWPO_OmitLocalProcForward',
  1659. LinesToStr([
  1660. 'this.DoIt = function () {',
  1661. '};',
  1662. '']),
  1663. LinesToStr([
  1664. '$mod.DoIt();',
  1665. '']));
  1666. end;
  1667. procedure TTestOptimizations.TestWPO_OmitProcLocalVar;
  1668. begin
  1669. StartProgram(false);
  1670. Add('function DoIt: longint;');
  1671. Add('var');
  1672. Add(' a: longint;');
  1673. Add(' b: longint;');
  1674. Add('begin');
  1675. Add(' b:=3;');
  1676. Add(' Result:=b;');
  1677. Add('end;');
  1678. Add('begin');
  1679. Add(' DoIt;');
  1680. ConvertProgram;
  1681. CheckSource('TestWPO_OmitProcLocalVar',
  1682. LinesToStr([
  1683. 'this.DoIt = function () {',
  1684. ' var Result = 0;',
  1685. ' var b = 0;',
  1686. ' b = 3;',
  1687. ' Result = b;',
  1688. ' return Result;',
  1689. '};',
  1690. '']),
  1691. LinesToStr([
  1692. '$mod.DoIt();',
  1693. '']));
  1694. end;
  1695. procedure TTestOptimizations.TestWPO_OmitProcLocalConst;
  1696. begin
  1697. StartProgram(false);
  1698. Add('function DoIt: longint;');
  1699. Add('const');
  1700. Add(' a = 3;');
  1701. Add(' b = 4;');
  1702. Add(' c: longint = 5;');
  1703. Add(' d: longint = 6;');
  1704. Add('begin');
  1705. Add(' Result:=b+d;');
  1706. Add('end;');
  1707. Add('begin');
  1708. Add(' DoIt;');
  1709. ConvertProgram;
  1710. CheckSource('TestWPO_OmitProcLocalConst',
  1711. LinesToStr([
  1712. 'var b = 4;',
  1713. 'var d = 6;',
  1714. 'this.DoIt = function () {',
  1715. ' var Result = 0;',
  1716. ' Result = 4 + d;',
  1717. ' return Result;',
  1718. '};',
  1719. '']),
  1720. LinesToStr([
  1721. '$mod.DoIt();',
  1722. '']));
  1723. end;
  1724. procedure TTestOptimizations.TestWPO_OmitProcLocalType;
  1725. begin
  1726. StartProgram(false);
  1727. Add('function DoIt: longint;');
  1728. Add('type');
  1729. Add(' TEnum = (red, green);');
  1730. Add(' TEnums = set of TEnum;');
  1731. Add('begin');
  1732. Add(' Result:=3;');
  1733. Add('end;');
  1734. Add('begin');
  1735. Add(' DoIt;');
  1736. ConvertProgram;
  1737. CheckSource('TestWPO_OmitProcLocalType',
  1738. LinesToStr([
  1739. 'this.DoIt = function () {',
  1740. ' var Result = 0;',
  1741. ' Result = 3;',
  1742. ' return Result;',
  1743. '};',
  1744. '']),
  1745. LinesToStr([
  1746. '$mod.DoIt();',
  1747. '']));
  1748. end;
  1749. procedure TTestOptimizations.TestWPO_OmitProcLocalProc;
  1750. begin
  1751. StartProgram(false);
  1752. Add('procedure DoIt;');
  1753. Add(' procedure SubProcA; begin end;');
  1754. Add(' procedure SubProcB; begin end;');
  1755. Add('begin');
  1756. Add(' SubProcB;');
  1757. Add('end;');
  1758. Add('begin');
  1759. Add(' DoIt;');
  1760. ConvertProgram;
  1761. CheckSource('TestWPO_OmitProcLocalProc',
  1762. LinesToStr([
  1763. 'this.DoIt = function () {',
  1764. ' function SubProcB() {',
  1765. ' };',
  1766. ' SubProcB();',
  1767. '};',
  1768. '']),
  1769. LinesToStr([
  1770. '$mod.DoIt();',
  1771. '']));
  1772. end;
  1773. procedure TTestOptimizations.TestWPO_OmitProcLocalForwardProc;
  1774. begin
  1775. StartProgram(false);
  1776. Add('procedure DoIt;');
  1777. Add(' procedure SubProcA; forward;');
  1778. Add(' procedure SubProcB; forward;');
  1779. Add(' procedure SubProcA; begin end;');
  1780. Add(' procedure SubProcB; begin end;');
  1781. Add('begin');
  1782. Add(' SubProcB;');
  1783. Add('end;');
  1784. Add('begin');
  1785. Add(' DoIt;');
  1786. ConvertProgram;
  1787. CheckSource('TestWPO_OmitProcLocalForwardProc',
  1788. LinesToStr([
  1789. 'this.DoIt = function () {',
  1790. ' function SubProcB() {',
  1791. ' };',
  1792. ' SubProcB();',
  1793. '};',
  1794. '']),
  1795. LinesToStr([
  1796. '$mod.DoIt();',
  1797. '']));
  1798. end;
  1799. procedure TTestOptimizations.TestWPO_OmitRecordMember;
  1800. begin
  1801. StartProgram(false);
  1802. Add('type');
  1803. Add(' TRec = record');
  1804. Add(' a: longint;');
  1805. Add(' b: longint;');
  1806. Add(' end;');
  1807. Add('var r: TRec;');
  1808. Add('begin');
  1809. Add(' r.a:=3;');
  1810. ConvertProgram;
  1811. CheckSource('TestWPO_OmitRecordMember',
  1812. LinesToStr([
  1813. 'rtl.recNewT(this, "TRec", function () {',
  1814. ' this.a = 0;',
  1815. ' this.$eq = function (b) {',
  1816. ' return this.a === b.a;',
  1817. ' };',
  1818. ' this.$assign = function (s) {',
  1819. ' this.a = s.a;',
  1820. ' return this;',
  1821. ' };',
  1822. '});',
  1823. 'this.r = this.TRec.$new();',
  1824. '']),
  1825. LinesToStr([
  1826. '$mod.r.a = 3;',
  1827. '']));
  1828. end;
  1829. procedure TTestOptimizations.TestWPO_OmitNotUsedTObject;
  1830. begin
  1831. StartProgram(false);
  1832. Add('type');
  1833. Add(' TObject = class end;');
  1834. Add('var o: TObject;');
  1835. Add('begin');
  1836. ConvertProgram;
  1837. CheckSource('TestWPO_OmitNotUsedTObject',
  1838. LinesToStr([
  1839. '']),
  1840. LinesToStr([
  1841. '']));
  1842. end;
  1843. procedure TTestOptimizations.TestWPO_TObject;
  1844. begin
  1845. StartProgram(false);
  1846. Add('type');
  1847. Add(' TObject = class');
  1848. Add(' procedure AfterConstruction; virtual;');
  1849. Add(' procedure BeforeDestruction; virtual;');
  1850. Add(' end;');
  1851. Add('procedure TObject.AfterConstruction; begin end;');
  1852. Add('procedure TObject.BeforeDestruction; begin end;');
  1853. Add('var o: TObject;');
  1854. Add('begin');
  1855. Add(' o:=nil;');
  1856. ConvertProgram;
  1857. CheckSource('TestWPO_TObject',
  1858. LinesToStr([
  1859. 'rtl.createClass(this, "TObject", null, function () {',
  1860. ' this.$init = function () {',
  1861. ' };',
  1862. ' this.$final = function () {',
  1863. ' };',
  1864. ' this.AfterConstruction = function () {',
  1865. ' };',
  1866. ' this.BeforeDestruction = function () {',
  1867. ' };',
  1868. '});',
  1869. 'this.o = null;',
  1870. '']),
  1871. LinesToStr([
  1872. '$mod.o = null;']));
  1873. end;
  1874. procedure TTestOptimizations.TestWPO_Class_Property;
  1875. begin
  1876. StartProgram(false);
  1877. Add([
  1878. 'type',
  1879. ' TObject = class',
  1880. ' private',
  1881. ' const CA = 3;',
  1882. ' private',
  1883. ' FA: longint;',
  1884. ' function GetA: longint;',
  1885. ' procedure SetA(Value: longint);',
  1886. ' function IsStoredA: boolean;',
  1887. ' property A: longint read GetA write SetA stored IsStoredA default CA;',
  1888. ' end;',
  1889. 'function tobject.geta: longint; begin end;',
  1890. 'procedure tobject.seta(value: longint); begin end;',
  1891. 'function tobject.isstoreda: boolean; begin end;',
  1892. 'var o: TObject;',
  1893. 'begin',
  1894. ' o.A:=o.A;']);
  1895. ConvertProgram;
  1896. CheckSource('TestWPO_Class_TObject',
  1897. LinesToStr([
  1898. 'rtl.createClass(this, "TObject", null, function () {',
  1899. ' this.$init = function () {',
  1900. ' };',
  1901. ' this.$final = function () {',
  1902. ' };',
  1903. ' this.GetA = function () {',
  1904. ' var Result = 0;',
  1905. ' return Result;',
  1906. ' };',
  1907. ' this.SetA = function (Value) {',
  1908. ' };',
  1909. '});',
  1910. 'this.o = null;',
  1911. '']),
  1912. LinesToStr([
  1913. '$mod.o.SetA($mod.o.GetA());']));
  1914. end;
  1915. procedure TTestOptimizations.TestWPO_Class_OmitField;
  1916. begin
  1917. StartProgram(false);
  1918. Add('type');
  1919. Add(' TObject = class');
  1920. Add(' a: longint;');
  1921. Add(' b: longint;');
  1922. Add(' end;');
  1923. Add('var o: TObject;');
  1924. Add('begin');
  1925. Add(' o.a:=3;');
  1926. ConvertProgram;
  1927. CheckSource('TestWPO_OmitClassField',
  1928. LinesToStr([
  1929. 'rtl.createClass(this, "TObject", null, function () {',
  1930. ' this.$init = function () {',
  1931. ' this.a = 0;',
  1932. ' };',
  1933. ' this.$final = function () {',
  1934. ' };',
  1935. '});',
  1936. 'this.o = null;',
  1937. '']),
  1938. LinesToStr([
  1939. '$mod.o.a = 3;']));
  1940. end;
  1941. procedure TTestOptimizations.TestWPO_Class_OmitMethod;
  1942. begin
  1943. StartProgram(false);
  1944. Add('type');
  1945. Add(' TObject = class');
  1946. Add(' procedure ProcA;');
  1947. Add(' procedure ProcB;');
  1948. Add(' end;');
  1949. Add('procedure TObject.ProcA; begin end;');
  1950. Add('procedure TObject.ProcB; begin end;');
  1951. Add('var o: TObject;');
  1952. Add('begin');
  1953. Add(' o.ProcB;');
  1954. ConvertProgram;
  1955. CheckSource('TestWPO_OmitClassMethod',
  1956. LinesToStr([
  1957. 'rtl.createClass(this, "TObject", null, function () {',
  1958. ' this.$init = function () {',
  1959. ' };',
  1960. ' this.$final = function () {',
  1961. ' };',
  1962. ' this.ProcB = function () {',
  1963. ' };',
  1964. '});',
  1965. 'this.o = null;',
  1966. '']),
  1967. LinesToStr([
  1968. '$mod.o.ProcB();']));
  1969. end;
  1970. procedure TTestOptimizations.TestWPO_Class_OmitClassMethod;
  1971. begin
  1972. StartProgram(false);
  1973. Add('type');
  1974. Add(' TObject = class');
  1975. Add(' class procedure ProcA;');
  1976. Add(' class procedure ProcB;');
  1977. Add(' end;');
  1978. Add('class procedure TObject.ProcA; begin end;');
  1979. Add('class procedure TObject.ProcB; begin end;');
  1980. Add('var o: TObject;');
  1981. Add('begin');
  1982. Add(' o.ProcB;');
  1983. ConvertProgram;
  1984. CheckSource('TestWPO_OmitClassMethod',
  1985. LinesToStr([
  1986. 'rtl.createClass(this, "TObject", null, function () {',
  1987. ' this.$init = function () {',
  1988. ' };',
  1989. ' this.$final = function () {',
  1990. ' };',
  1991. ' this.ProcB = function () {',
  1992. ' };',
  1993. '});',
  1994. 'this.o = null;',
  1995. '']),
  1996. LinesToStr([
  1997. '$mod.o.$class.ProcB();']));
  1998. end;
  1999. procedure TTestOptimizations.TestWPO_Class_OmitPropertyGetter1;
  2000. begin
  2001. StartProgram(false);
  2002. Add('type');
  2003. Add(' TObject = class');
  2004. Add(' FFoo: boolean;');
  2005. Add(' function GetFoo: boolean;');
  2006. Add(' property Foo: boolean read FFoo;');
  2007. Add(' property Foo2: boolean read GetFoo;');
  2008. Add(' FBar: boolean;');
  2009. Add(' function GetBar: boolean;');
  2010. Add(' property Bar: boolean read FBar;');
  2011. Add(' property Bar2: boolean read GetBar;');
  2012. Add(' end;');
  2013. Add('function TObject.GetFoo: boolean; begin Result:=FFoo; end;');
  2014. Add('function TObject.GetBar: boolean; begin Result:=FBar; end;');
  2015. Add('var o: TObject;');
  2016. Add('begin');
  2017. Add(' if o.Foo then;');
  2018. ConvertProgram;
  2019. CheckSource('TestWPO_OmitClassPropertyGetter1',
  2020. LinesToStr([
  2021. 'rtl.createClass(this, "TObject", null, function () {',
  2022. ' this.$init = function () {',
  2023. ' this.FFoo = false;',
  2024. ' };',
  2025. ' this.$final = function () {',
  2026. ' };',
  2027. '});',
  2028. 'this.o = null;',
  2029. '']),
  2030. LinesToStr([
  2031. 'if ($mod.o.FFoo);',
  2032. '']));
  2033. end;
  2034. procedure TTestOptimizations.TestWPO_Class_OmitPropertyGetter2;
  2035. begin
  2036. StartProgram(false);
  2037. Add('type');
  2038. Add(' TObject = class');
  2039. Add(' FFoo: boolean;');
  2040. Add(' function GetFoo: boolean;');
  2041. Add(' property Foo: boolean read FFoo;');
  2042. Add(' property Foo2: boolean read GetFoo;');
  2043. Add(' end;');
  2044. Add('function TObject.GetFoo: boolean; begin Result:=FFoo; end;');
  2045. Add('var o: TObject;');
  2046. Add('begin');
  2047. Add(' if o.Foo2 then;');
  2048. ConvertProgram;
  2049. CheckSource('TestWPO_OmitClassPropertyGetter2',
  2050. LinesToStr([
  2051. 'rtl.createClass(this, "TObject", null, function () {',
  2052. ' this.$init = function () {',
  2053. ' this.FFoo = false;',
  2054. ' };',
  2055. ' this.$final = function () {',
  2056. ' };',
  2057. ' this.GetFoo = function () {',
  2058. ' var Result = false;',
  2059. ' Result = this.FFoo;',
  2060. ' return Result;',
  2061. ' };',
  2062. '});',
  2063. 'this.o = null;',
  2064. '']),
  2065. LinesToStr([
  2066. 'if ($mod.o.GetFoo()) ;',
  2067. '']));
  2068. end;
  2069. procedure TTestOptimizations.TestWPO_Class_OmitPropertySetter1;
  2070. begin
  2071. StartProgram(false);
  2072. Add('type');
  2073. Add(' TObject = class');
  2074. Add(' FFoo: boolean;');
  2075. Add(' procedure SetFoo(Value: boolean);');
  2076. Add(' property Foo: boolean write FFoo;');
  2077. Add(' property Foo2: boolean write SetFoo;');
  2078. Add(' FBar: boolean;');
  2079. Add(' procedure SetBar(Value: boolean);');
  2080. Add(' property Bar: boolean write FBar;');
  2081. Add(' property Bar2: boolean write SetBar;');
  2082. Add(' end;');
  2083. Add('procedure TObject.SetFoo(Value: boolean); begin FFoo:=Value; end;');
  2084. Add('procedure TObject.SetBar(Value: boolean); begin FBar:=Value; end;');
  2085. Add('var o: TObject;');
  2086. Add('begin');
  2087. Add(' o.Foo:=true;');
  2088. ConvertProgram;
  2089. CheckSource('TestWPO_OmitClassPropertySetter1',
  2090. LinesToStr([
  2091. 'rtl.createClass(this, "TObject", null, function () {',
  2092. ' this.$init = function () {',
  2093. ' this.FFoo = false;',
  2094. ' };',
  2095. ' this.$final = function () {',
  2096. ' };',
  2097. '});',
  2098. 'this.o = null;',
  2099. '']),
  2100. LinesToStr([
  2101. '$mod.o.FFoo = true;',
  2102. '']));
  2103. end;
  2104. procedure TTestOptimizations.TestWPO_Class_OmitPropertySetter2;
  2105. begin
  2106. StartProgram(false);
  2107. Add('type');
  2108. Add(' TObject = class');
  2109. Add(' FFoo: boolean;');
  2110. Add(' procedure SetFoo(Value: boolean);');
  2111. Add(' property Foo: boolean write FFoo;');
  2112. Add(' property Foo2: boolean write SetFoo;');
  2113. Add(' end;');
  2114. Add('procedure TObject.SetFoo(Value: boolean); begin FFoo:=Value; end;');
  2115. Add('var o: TObject;');
  2116. Add('begin');
  2117. Add(' o.Foo2:=true;');
  2118. ConvertProgram;
  2119. CheckSource('TestWPO_OmitClassPropertySetter2',
  2120. LinesToStr([
  2121. 'rtl.createClass(this, "TObject", null, function () {',
  2122. ' this.$init = function () {',
  2123. ' this.FFoo = false;',
  2124. ' };',
  2125. ' this.$final = function () {',
  2126. ' };',
  2127. ' this.SetFoo = function (Value) {',
  2128. ' this.FFoo = Value;',
  2129. ' };',
  2130. '});',
  2131. 'this.o = null;',
  2132. '']),
  2133. LinesToStr([
  2134. '$mod.o.SetFoo(true);',
  2135. '']));
  2136. end;
  2137. procedure TTestOptimizations.TestWPO_Class_KeepNewInstance;
  2138. begin
  2139. StartProgram(false);
  2140. Add([
  2141. '{$modeswitch externalclass}',
  2142. 'type',
  2143. ' TExt = class external name ''Object''',
  2144. ' end;',
  2145. ' TBird = class(TExt)',
  2146. ' protected',
  2147. ' class function NewInstance(fnname: string; const paramarray): TBird; virtual;',
  2148. ' public',
  2149. ' constructor Create;',
  2150. ' end;',
  2151. 'class function TBird.NewInstance(fnname: string; const paramarray): TBird;',
  2152. 'begin',
  2153. ' asm',
  2154. ' Result = Object.create();',
  2155. ' end;',
  2156. 'end;',
  2157. 'constructor TBird.Create;',
  2158. 'begin',
  2159. ' inherited;',
  2160. 'end;',
  2161. 'begin',
  2162. ' TBird.Create;',
  2163. '']);
  2164. ConvertProgram;
  2165. CheckSource('TestWPO_Class_KeepNewInstance',
  2166. LinesToStr([
  2167. 'rtl.createClassExt(this, "TBird", Object, "NewInstance", function () {',
  2168. ' this.$init = function () {',
  2169. ' };',
  2170. ' this.$final = function () {',
  2171. ' };',
  2172. ' this.NewInstance = function (fnname, paramarray) {',
  2173. ' var Result = null;',
  2174. ' Result = Object.create();',
  2175. ' return Result;',
  2176. ' };',
  2177. ' this.Create = function () {',
  2178. ' return this;',
  2179. ' };',
  2180. '});',
  2181. '']),
  2182. LinesToStr([
  2183. '$mod.TBird.$create("Create");',
  2184. '']));
  2185. end;
  2186. procedure TTestOptimizations.TestWPO_CallInherited;
  2187. begin
  2188. StartProgram(false);
  2189. Add('type');
  2190. Add(' TObject = class');
  2191. Add(' procedure DoA;');
  2192. Add(' procedure DoB;');
  2193. Add(' end;');
  2194. Add(' TMobile = class');
  2195. Add(' procedure DoA;');
  2196. Add(' procedure DoC;');
  2197. Add(' end;');
  2198. Add('procedure TObject.DoA; begin end;');
  2199. Add('procedure TObject.DoB; begin end;');
  2200. Add('procedure TMobile.DoA;');
  2201. Add('begin');
  2202. Add(' inherited;');
  2203. Add('end;');
  2204. Add('procedure TMobile.DoC;');
  2205. Add('begin');
  2206. Add(' inherited DoB;');
  2207. Add('end;');
  2208. Add('var o: TMobile;');
  2209. Add('begin');
  2210. Add(' o.DoA;');
  2211. Add(' o.DoC;');
  2212. ConvertProgram;
  2213. CheckSource('TestWPO_CallInherited',
  2214. LinesToStr([
  2215. 'rtl.createClass(this, "TObject", null, function () {',
  2216. ' this.$init = function () {',
  2217. ' };',
  2218. ' this.$final = function () {',
  2219. ' };',
  2220. ' this.DoA = function () {',
  2221. ' };',
  2222. ' this.DoB = function () {',
  2223. ' };',
  2224. '});',
  2225. ' rtl.createClass(this, "TMobile", this.TObject, function () {',
  2226. ' this.DoA$1 = function () {',
  2227. ' $mod.TObject.DoA.call(this);',
  2228. ' };',
  2229. ' this.DoC = function () {',
  2230. ' $mod.TObject.DoB.call(this);',
  2231. ' };',
  2232. '});',
  2233. 'this.o = null;',
  2234. '']),
  2235. LinesToStr([
  2236. '$mod.o.DoA$1();',
  2237. '$mod.o.DoC();',
  2238. '']));
  2239. end;
  2240. procedure TTestOptimizations.TestWPO_UseUnit;
  2241. var
  2242. ActualSrc, ExpectedSrc: String;
  2243. begin
  2244. AddModuleWithIntfImplSrc('unit1.pp',
  2245. LinesToStr([
  2246. 'var i: longint;',
  2247. 'procedure DoIt;',
  2248. '']),
  2249. LinesToStr([
  2250. 'procedure DoIt; begin end;']));
  2251. AddModuleWithIntfImplSrc('unit2.pp',
  2252. LinesToStr([
  2253. 'var j: longint;',
  2254. 'procedure DoMore;',
  2255. '']),
  2256. LinesToStr([
  2257. 'procedure DoMore; begin end;']));
  2258. StartProgram(true);
  2259. Add('uses unit2;');
  2260. Add('begin');
  2261. Add(' j:=3;');
  2262. ConvertProgram;
  2263. ActualSrc:=ConvertJSModuleToString(JSModule);
  2264. ExpectedSrc:=LinesToStr([
  2265. 'rtl.module("program", ["system", "unit2"], function () {',
  2266. ' var $mod = this;',
  2267. ' $mod.$main = function () {',
  2268. ' pas.unit2.j = 3;',
  2269. ' };',
  2270. '});',
  2271. '']);
  2272. CheckDiff('TestWPO_UseUnit',ExpectedSrc,ActualSrc);
  2273. end;
  2274. procedure TTestOptimizations.TestWPO_ArrayOfConst_Use;
  2275. begin
  2276. StartProgram(true,[supTVarRec]);
  2277. Add([
  2278. 'procedure Say(arr: array of const);',
  2279. 'begin',
  2280. 'end;',
  2281. 'begin',
  2282. ' Say([true]);']);
  2283. ConvertProgram;
  2284. CheckUnit('system.pp',
  2285. LinesToStr([
  2286. 'rtl.module("system", [], function () {',
  2287. ' var $mod = this;',
  2288. ' rtl.recNewT(this, "TVarRec", function () {',
  2289. ' this.VType = 0;',
  2290. ' this.VJSValue = undefined;',
  2291. ' this.$eq = function (b) {',
  2292. ' return (this.VType === b.VType) && (this.VJSValue === b.VJSValue);',
  2293. ' };',
  2294. ' this.$assign = function (s) {',
  2295. ' this.VType = s.VType;',
  2296. ' this.VJSValue = s.VJSValue;',
  2297. ' return this;',
  2298. ' };',
  2299. ' });',
  2300. ' this.VarRecs = function () {',
  2301. ' var Result = [];',
  2302. ' var v = null;',
  2303. ' v.VType = 1;',
  2304. ' v.VJSValue = 2;',
  2305. ' return Result;',
  2306. ' };',
  2307. '});',
  2308. '']));
  2309. end;
  2310. procedure TTestOptimizations.TestWPO_ArrayOfConst_NotUsed;
  2311. begin
  2312. StartProgram(true,[supTVarRec]);
  2313. Add([
  2314. 'procedure Say(arr: array of const);',
  2315. 'begin',
  2316. 'end;',
  2317. 'begin']);
  2318. ConvertProgram;
  2319. CheckUnit('system.pp',
  2320. LinesToStr([
  2321. 'rtl.module("system", [], function () {',
  2322. ' var $mod = this;',
  2323. '});',
  2324. '']));
  2325. end;
  2326. procedure TTestOptimizations.TestWPO_Class_PropertyInOtherUnit;
  2327. begin
  2328. AddModuleWithIntfImplSrc('unit1.pp',
  2329. LinesToStr([
  2330. 'type',
  2331. ' TObject = class',
  2332. ' private',
  2333. ' const CA = 3;',
  2334. ' private',
  2335. ' FOther: string;',
  2336. ' FA: longint;',
  2337. ' function GetA: longint;',
  2338. ' procedure SetA(Value: longint);',
  2339. ' function IsStoredA: boolean;',
  2340. ' public',
  2341. ' property A: longint read GetA write SetA stored IsStoredA default CA;',
  2342. ' end;',
  2343. '']),
  2344. LinesToStr([
  2345. 'function TObject.geta: longint;',
  2346. 'begin',
  2347. 'end;',
  2348. 'procedure TObject.seta(value: longint);',
  2349. 'begin',
  2350. ' FA:=Value;',
  2351. 'end;',
  2352. 'function TObject.isstoreda: boolean; begin end;',
  2353. '']));
  2354. StartProgram(true);
  2355. Add([
  2356. 'uses unit1;',
  2357. 'var o: TObject;',
  2358. 'begin',
  2359. ' o.A:=o.A;']);
  2360. ConvertProgram;
  2361. CheckUnit('unit1.pp',
  2362. LinesToStr([
  2363. 'rtl.module("unit1", ["system"], function () {',
  2364. ' var $mod = this;',
  2365. ' rtl.createClass(this, "TObject", null, function () {',
  2366. ' this.$init = function () {',
  2367. ' this.FA = 0;',
  2368. ' };',
  2369. ' this.$final = function () {',
  2370. ' };',
  2371. ' this.GetA = function () {',
  2372. ' var Result = 0;',
  2373. ' return Result;',
  2374. ' };',
  2375. ' this.SetA = function (Value) {',
  2376. ' this.FA = Value;',
  2377. ' };',
  2378. ' });',
  2379. '});',
  2380. '']));
  2381. end;
  2382. procedure TTestOptimizations.TestWPO_ProgramPublicDeclaration;
  2383. var
  2384. ActualSrc, ExpectedSrc: String;
  2385. begin
  2386. StartProgram(true);
  2387. Add('var');
  2388. Add(' vPublic: longint; public;');
  2389. Add(' vPrivate: longint;');
  2390. Add('procedure DoPublic; public; begin end;');
  2391. Add('procedure DoPrivate; begin end;');
  2392. Add('begin');
  2393. ConvertProgram;
  2394. ActualSrc:=ConvertJSModuleToString(JSModule);
  2395. ExpectedSrc:=LinesToStr([
  2396. 'rtl.module("program", ["system"], function () {',
  2397. ' var $mod = this;',
  2398. ' this.vPublic = 0;',
  2399. ' this.DoPublic =function(){',
  2400. ' };',
  2401. ' $mod.$main = function () {',
  2402. ' };',
  2403. '});',
  2404. '']);
  2405. CheckDiff('TestWPO_ProgramPublicDeclaration',ExpectedSrc,ActualSrc);
  2406. end;
  2407. procedure TTestOptimizations.TestWPO_ConstructorDefaultValueConst;
  2408. var
  2409. ActualSrc, ExpectedSrc: String;
  2410. begin
  2411. WithTypeInfo:=true;
  2412. StartProgram(true);
  2413. Add([
  2414. 'const gcBlack = 0;',
  2415. 'type',
  2416. ' TColor = longint;',
  2417. ' TObject = class',
  2418. ' private',
  2419. ' FColor: TColor;',
  2420. ' public',
  2421. ' property Color: TColor read FColor write FColor;',
  2422. ' constructor Create(const AColor: TColor = gcBlack);',
  2423. ' end;',
  2424. 'constructor TObject.Create(const AColor: TColor = gcBlack);',
  2425. 'begin',
  2426. ' FColor := AColor;',
  2427. 'end;',
  2428. 'var T: TObject;',
  2429. 'begin',
  2430. ' T := TObject.Create;',
  2431. '']);
  2432. ConvertProgram;
  2433. ActualSrc:=ConvertJSModuleToString(JSModule);
  2434. ExpectedSrc:=LinesToStr([
  2435. 'rtl.module("program",["system"],function () {',
  2436. ' var $mod = this;',
  2437. ' this.gcBlack = 0;',
  2438. ' rtl.createClass(this,"TObject",null,function () {',
  2439. ' this.$init = function () {',
  2440. ' this.FColor = 0;',
  2441. ' };',
  2442. ' this.$final = function () {',
  2443. ' };',
  2444. ' this.Create = function (AColor) {',
  2445. ' this.FColor = AColor;',
  2446. ' return this;',
  2447. ' };',
  2448. ' });',
  2449. ' this.T = null;',
  2450. ' $mod.$main = function () {',
  2451. ' $mod.T = $mod.TObject.$create("Create",[0]);',
  2452. ' };',
  2453. '});',
  2454. '']);
  2455. CheckDiff('TestWPO_ConstructorDefaultValueConst',ExpectedSrc,ActualSrc);
  2456. end;
  2457. procedure TTestOptimizations.TestWPO_RTTI_PublishedField;
  2458. var
  2459. ActualSrc, ExpectedSrc: String;
  2460. begin
  2461. WithTypeInfo:=true;
  2462. StartProgram(true);
  2463. Add([
  2464. 'type',
  2465. ' TArrA = array of char;',
  2466. ' TArrB = array of string;',
  2467. ' TObject = class',
  2468. ' public',
  2469. ' PublicA: TArrA;',
  2470. ' published',
  2471. ' PublishedB: TArrB;',
  2472. ' end;',
  2473. 'var',
  2474. ' C: TObject;',
  2475. 'begin',
  2476. ' C.PublicA:=nil;',
  2477. ' if typeinfo(TObject)=nil then ;',
  2478. '']);
  2479. ConvertProgram;
  2480. ActualSrc:=ConvertJSModuleToString(JSModule);
  2481. ExpectedSrc:=LinesToStr([
  2482. 'rtl.module("program", ["system"], function () {',
  2483. ' var $mod = this;',
  2484. ' this.$rtti.$DynArray("TArrB", {',
  2485. ' eltype: rtl.string',
  2486. ' });',
  2487. ' rtl.createClass(this, "TObject", null, function () {',
  2488. ' this.$init = function () {',
  2489. ' this.PublicA = [];',
  2490. ' this.PublishedB = [];',
  2491. ' };',
  2492. ' this.$final = function () {',
  2493. ' this.PublicA = undefined;',
  2494. ' this.PublishedB = undefined;',
  2495. ' };',
  2496. ' var $r = this.$rtti;',
  2497. ' $r.addField("PublishedB", $mod.$rtti["TArrB"], 4);',
  2498. ' });',
  2499. ' this.C = null;',
  2500. ' $mod.$main = function () {',
  2501. ' $mod.C.PublicA = [];',
  2502. ' if ($mod.$rtti["TObject"] === null) ;',
  2503. ' };',
  2504. '});',
  2505. '']);
  2506. CheckDiff('TestWPO_RTTI_PublishedField',ExpectedSrc,ActualSrc);
  2507. end;
  2508. procedure TTestOptimizations.TestWPO_RTTI_TypeInfo;
  2509. var
  2510. ActualSrc, ExpectedSrc: String;
  2511. begin
  2512. WithTypeInfo:=true;
  2513. StartProgram(true);
  2514. Add('type');
  2515. Add(' TArrA = array of char;');
  2516. Add(' TArrB = array of string;');
  2517. Add('var');
  2518. Add(' A: TArrA;');
  2519. Add(' B: TArrB;');
  2520. Add(' p: pointer;');
  2521. Add('begin');
  2522. Add(' A:=nil;');
  2523. Add(' p:=typeinfo(B);');
  2524. ConvertProgram;
  2525. ActualSrc:=ConvertJSModuleToString(JSModule);
  2526. ExpectedSrc:=LinesToStr([
  2527. 'rtl.module("program", ["system"], function () {',
  2528. ' var $mod = this;',
  2529. ' this.$rtti.$DynArray("TArrB", {',
  2530. ' eltype: rtl.string',
  2531. ' });',
  2532. ' this.A = [];',
  2533. ' this.B = [];',
  2534. ' this.p = null;',
  2535. ' $mod.$main = function () {',
  2536. ' $mod.A = [];',
  2537. ' $mod.p = $mod.$rtti["TArrB"];',
  2538. ' };',
  2539. '});',
  2540. '']);
  2541. CheckDiff('TestWPO_RTTI_TypeInfo',ExpectedSrc,ActualSrc);
  2542. end;
  2543. procedure TTestOptimizations.TestWPO_RTTI_PrivateField;
  2544. var
  2545. ActualSrc, ExpectedSrc: String;
  2546. begin
  2547. WithTypeInfo:=true;
  2548. StartProgram(true);
  2549. Add([
  2550. 'type',
  2551. ' TArrA = array of char;',
  2552. ' TArrB = array of string;',
  2553. ' TArrC = array of word;',
  2554. ' {$RTTI explicit Fields([vcPrivate,vcProtected])}',
  2555. ' TObject = class',
  2556. ' private',
  2557. ' PrivateA: TArrA;',
  2558. ' protected',
  2559. ' ProtectedB: TArrB;',
  2560. ' public',
  2561. ' PublicC: TArrC;',
  2562. ' end;',
  2563. 'var',
  2564. ' C: TObject;',
  2565. 'begin',
  2566. ' if typeinfo(TObject)=nil then ;',
  2567. '']);
  2568. ConvertProgram;
  2569. ActualSrc:=ConvertJSModuleToString(JSModule);
  2570. ExpectedSrc:=LinesToStr([
  2571. 'rtl.module("program", ["system"], function () {',
  2572. ' var $mod = this;',
  2573. ' this.$rtti.$DynArray("TArrA", {',
  2574. ' eltype: rtl.char',
  2575. ' });',
  2576. ' this.$rtti.$DynArray("TArrB", {',
  2577. ' eltype: rtl.string',
  2578. ' });',
  2579. ' rtl.createClass(this, "TObject", null, function () {',
  2580. ' this.$init = function () {',
  2581. ' this.PrivateA = [];',
  2582. ' this.ProtectedB = [];',
  2583. ' };',
  2584. ' this.$final = function () {',
  2585. ' this.PrivateA = undefined;',
  2586. ' this.ProtectedB = undefined;',
  2587. ' };',
  2588. ' var $r = this.$rtti;',
  2589. ' $r.addField("PrivateA", $mod.$rtti["TArrA"], 0);',
  2590. ' $r.addField("ProtectedB", $mod.$rtti["TArrB"], 1);',
  2591. ' });',
  2592. ' $mod.$main = function () {',
  2593. ' if ($mod.$rtti["TObject"] === null) ;',
  2594. ' };',
  2595. '});',
  2596. '']);
  2597. CheckDiff('TestWPO_RTTI_PrivateField',ExpectedSrc,ActualSrc);
  2598. end;
  2599. Initialization
  2600. RegisterTests([TTestOptimizations]);
  2601. end.