tcgenerics.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831
  1. unit TCGenerics;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, testregistry,
  6. TCModules, FPPas2Js, PScanner, PasResolveEval;
  7. type
  8. { TTestGenerics }
  9. TTestGenerics = class(TCustomTestModule)
  10. Published
  11. // generic record
  12. Procedure TestGen_RecordEmpty;
  13. Procedure TestGen_Record_ClassProc;
  14. Procedure TestGen_Record_AsClassVar_Program;
  15. Procedure TestGen_Record_AsClassVar_UnitImpl; // ToDo
  16. // ToDo: delay using recNewS
  17. // generic class
  18. Procedure TestGen_ClassEmpty;
  19. Procedure TestGen_Class_EmptyMethod;
  20. Procedure TestGen_Class_TList;
  21. Procedure TestGen_Class_TCustomList;
  22. Procedure TestGen_ClassAncestor;
  23. Procedure TestGen_Class_TypeInfo;
  24. Procedure TestGen_Class_TypeOverload; // ToDo TBird, TBird<T>, TBird<S,T>
  25. Procedure TestGen_Class_ClassProperty;
  26. Procedure TestGen_Class_ClassProc;
  27. //Procedure TestGen_Record_ReferGenClass_DelphiFail; TBird<T> = class x:TBird; end;
  28. Procedure TestGen_Class_ClassConstructor;
  29. Procedure TestGen_Class_TypeCastSpecializesWarn;
  30. Procedure TestGen_Class_TypeCastSpecializesJSValueNoWarn;
  31. procedure TestGen_Class_VarArgsOfType;
  32. procedure TestGen_Class_OverloadsInUnit;
  33. procedure TestGen_ClassForward_CircleRTTI;
  34. // generic external class
  35. procedure TestGen_ExtClass_Array;
  36. procedure TestGen_ExtClass_GenJSValueAssign;
  37. procedure TestGen_ExtClass_AliasMemberType;
  38. Procedure TestGen_ExtClass_RTTI;
  39. // class interfaces
  40. procedure TestGen_ClassInterface_Corba;
  41. procedure TestGen_ClassInterface_InterfacedObject;
  42. // statements
  43. Procedure TestGen_InlineSpec_Constructor;
  44. Procedure TestGen_CallUnitImplProc;
  45. Procedure TestGen_IntAssignTemplVar;
  46. Procedure TestGen_TypeCastDotField;
  47. // generic helper
  48. procedure TestGen_HelperForArray;
  49. // generic functions
  50. procedure TestGenProc_Function_ObjFPC;
  51. procedure TestGenProc_Function_Delphi;
  52. procedure TestGenProc_Overload;
  53. procedure TestGenProc_Forward;
  54. procedure TestGenProc_Infer_OverloadForward;
  55. procedure TestGenProc_TypeInfo;
  56. procedure TestGenProc_Infer_Widen;
  57. procedure TestGenProc_Infer_PassAsArg;
  58. // ToDo: delay create: type TRec=record end; ... r:=GenProc<TRec>();
  59. // ToDo: FuncName:= instead of Result:=
  60. // generic methods
  61. procedure TestGenMethod_ObjFPC;
  62. end;
  63. implementation
  64. { TTestGenerics }
  65. procedure TTestGenerics.TestGen_RecordEmpty;
  66. begin
  67. StartProgram(false);
  68. Add([
  69. 'type',
  70. ' generic TRecA<T> = record',
  71. ' end;',
  72. 'var a,b: specialize TRecA<word>;',
  73. 'begin',
  74. ' if a=b then ;']);
  75. ConvertProgram;
  76. CheckSource('TestGen_RecordEmpty',
  77. LinesToStr([ // statements
  78. 'rtl.recNewT($mod, "TRecA$G1", function () {',
  79. ' this.$eq = function (b) {',
  80. ' return true;',
  81. ' };',
  82. ' this.$assign = function (s) {',
  83. ' return this;',
  84. ' };',
  85. '});',
  86. 'this.a = $mod.TRecA$G1.$new();',
  87. 'this.b = $mod.TRecA$G1.$new();',
  88. '']),
  89. LinesToStr([ // $mod.$main
  90. 'if ($mod.a.$eq($mod.b)) ;'
  91. ]));
  92. end;
  93. procedure TTestGenerics.TestGen_Record_ClassProc;
  94. begin
  95. StartProgram(false);
  96. Add([
  97. '{$modeswitch AdvancedRecords}',
  98. 'type',
  99. ' generic TPoint<T> = record',
  100. ' class var x: T;',
  101. ' class procedure Fly; static;',
  102. ' end;',
  103. 'class procedure Tpoint.Fly;',
  104. 'begin',
  105. ' x:=x+3;',
  106. ' tpoint.x:=tpoint.x+4;',
  107. ' Fly;',
  108. ' tpoint.Fly;',
  109. 'end;',
  110. 'var p: specialize TPoint<word>;',
  111. 'begin',
  112. ' p.x:=p.x+10;',
  113. ' p.Fly;',
  114. ' p.Fly();',
  115. '']);
  116. ConvertProgram;
  117. CheckSource('TestGen_Record_ClassProc',
  118. LinesToStr([ // statements
  119. 'rtl.recNewT($mod, "TPoint$G1", function () {',
  120. ' this.x = 0;',
  121. ' this.$eq = function (b) {',
  122. ' return true;',
  123. ' };',
  124. ' this.$assign = function (s) {',
  125. ' return this;',
  126. ' };',
  127. ' this.Fly = function () {',
  128. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 3;',
  129. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 4;',
  130. ' $mod.TPoint$G1.Fly();',
  131. ' $mod.TPoint$G1.Fly();',
  132. ' };',
  133. '}, true);',
  134. 'this.p = $mod.TPoint$G1.$new();',
  135. '']),
  136. LinesToStr([ // $mod.$main
  137. '$mod.TPoint$G1.x = $mod.p.x + 10;',
  138. '$mod.p.Fly();',
  139. '$mod.p.Fly();',
  140. '']));
  141. end;
  142. procedure TTestGenerics.TestGen_Record_AsClassVar_Program;
  143. begin
  144. StartProgram(false);
  145. Add([
  146. '{$modeswitch AdvancedRecords}',
  147. 'type',
  148. ' generic TAnt<T> = record',
  149. ' class var x: T;',
  150. ' end;',
  151. ' TBird = record',
  152. ' b: word;',
  153. ' end;',
  154. 'var f: specialize TAnt<TBird>;',
  155. 'begin',
  156. ' f.x.b:=f.x.b+10;',
  157. '']);
  158. ConvertProgram;
  159. CheckSource('TestGen_Record_AsClassVar_Program',
  160. LinesToStr([ // statements
  161. 'rtl.recNewT($mod, "TBird", function () {',
  162. ' this.b = 0;',
  163. ' this.$eq = function (b) {',
  164. ' return this.b === b.b;',
  165. ' };',
  166. ' this.$assign = function (s) {',
  167. ' this.b = s.b;',
  168. ' return this;',
  169. ' };',
  170. '});',
  171. 'rtl.recNewT($mod, "TAnt$G1", function () {',
  172. ' this.x = $mod.TBird.$new();',
  173. ' this.$eq = function (b) {',
  174. ' return true;',
  175. ' };',
  176. ' this.$assign = function (s) {',
  177. ' return this;',
  178. ' };',
  179. '}, true);',
  180. 'this.f = $mod.TAnt$G1.$new();',
  181. '']),
  182. LinesToStr([ // $mod.$main
  183. '$mod.f.x.b = $mod.f.x.b + 10;',
  184. '']));
  185. end;
  186. procedure TTestGenerics.TestGen_Record_AsClassVar_UnitImpl;
  187. begin
  188. StartUnit(true);
  189. Add([
  190. 'interface',
  191. '{$modeswitch AdvancedRecords}',
  192. 'type',
  193. ' generic TAnt<T> = record',
  194. ' class var x: T;',
  195. ' end;',
  196. 'implementation',
  197. 'type',
  198. ' TBird = record',
  199. ' b: word;',
  200. ' end;',
  201. 'var f: specialize TAnt<TBird>;',
  202. 'begin',
  203. ' f.x.b:=f.x.b+10;',
  204. '']);
  205. ConvertUnit;
  206. CheckSource('TestGen_Record_AsClassVar_UnitImpl',
  207. LinesToStr([ // statements
  208. 'var $impl = $mod.$impl;',
  209. 'rtl.recNewT($mod, "TAnt$G1", function () {',
  210. ' this.x = $impl.TBird.$new();',
  211. ' this.$eq = function (b) {',
  212. ' return true;',
  213. ' };',
  214. ' this.$assign = function (s) {',
  215. ' return this;',
  216. ' };',
  217. '}, true);',
  218. '']),
  219. LinesToStr([ // $mod.$init
  220. ' $impl.f.x.b = $impl.f.x.b + 10;',
  221. '']),
  222. LinesToStr([ // statements
  223. 'rtl.recNewT($impl, "TBird", function () {',
  224. ' this.b = 0;',
  225. ' this.$eq = function (b) {',
  226. ' return this.b === b.b;',
  227. ' };',
  228. ' this.$assign = function (s) {',
  229. ' this.b = s.b;',
  230. ' return this;',
  231. ' };',
  232. '});',
  233. //'$mod.TAnt$G1();',
  234. '$impl.f = $mod.TAnt$G1.$new();',
  235. '']));
  236. end;
  237. procedure TTestGenerics.TestGen_ClassEmpty;
  238. begin
  239. StartProgram(false);
  240. Add([
  241. 'type',
  242. ' TObject = class end;',
  243. ' generic TBird<T> = class',
  244. ' end;',
  245. 'var a,b: specialize TBird<word>;',
  246. 'begin',
  247. ' if a=b then ;']);
  248. ConvertProgram;
  249. CheckSource('TestGen_ClassEmpty',
  250. LinesToStr([ // statements
  251. 'rtl.createClass($mod, "TObject", null, function () {',
  252. ' this.$init = function () {',
  253. ' };',
  254. ' this.$final = function () {',
  255. ' };',
  256. '});',
  257. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  258. '});',
  259. 'this.a = null;',
  260. 'this.b = null;',
  261. '']),
  262. LinesToStr([ // $mod.$main
  263. 'if ($mod.a === $mod.b) ;'
  264. ]));
  265. end;
  266. procedure TTestGenerics.TestGen_Class_EmptyMethod;
  267. begin
  268. StartProgram(false);
  269. Add([
  270. 'type',
  271. ' TObject = class end;',
  272. ' generic TBird<T> = class',
  273. ' function Fly(w: T): T;',
  274. ' end;',
  275. 'function TBird.Fly(w: T): T;',
  276. 'begin',
  277. 'end;',
  278. 'var a: specialize TBird<word>;',
  279. 'begin',
  280. ' if a.Fly(3)=4 then ;']);
  281. ConvertProgram;
  282. CheckSource('TestGen_Class_EmptyMethod',
  283. LinesToStr([ // statements
  284. 'rtl.createClass($mod, "TObject", null, function () {',
  285. ' this.$init = function () {',
  286. ' };',
  287. ' this.$final = function () {',
  288. ' };',
  289. '});',
  290. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  291. ' this.Fly = function (w) {',
  292. ' var Result = 0;',
  293. ' return Result;',
  294. ' };',
  295. '});',
  296. 'this.a = null;',
  297. '']),
  298. LinesToStr([ // $mod.$main
  299. ' if ($mod.a.Fly(3) === 4) ;'
  300. ]));
  301. end;
  302. procedure TTestGenerics.TestGen_Class_TList;
  303. begin
  304. StartProgram(false);
  305. Add([
  306. '{$mode objfpc}',
  307. 'type',
  308. ' TObject = class end;',
  309. ' generic TList<T> = class',
  310. ' strict private',
  311. ' FItems: array of T;',
  312. ' function GetItems(Index: longint): T;',
  313. ' procedure SetItems(Index: longint; Value: T);',
  314. ' public',
  315. ' procedure Alter(w: T);',
  316. ' property Items[Index: longint]: T read GetItems write SetItems; default;',
  317. ' end;',
  318. ' TWordList = specialize TList<word>;',
  319. 'function TList.GetItems(Index: longint): T;',
  320. 'begin',
  321. ' Result:=FItems[Index];',
  322. 'end;',
  323. 'procedure TList.SetItems(Index: longint; Value: T);',
  324. 'begin',
  325. ' FItems[Index]:=Value;',
  326. 'end;',
  327. 'procedure TList.Alter(w: T);',
  328. 'begin',
  329. ' SetLength(FItems,length(FItems)+1);',
  330. ' Insert(w,FItems,2);',
  331. ' Delete(FItems,2,3);',
  332. 'end;',
  333. 'var l: TWordList;',
  334. ' w: word;',
  335. 'begin',
  336. ' l[1]:=w;',
  337. ' w:=l[2];',
  338. '']);
  339. ConvertProgram;
  340. CheckSource('TestGen_Class_TList',
  341. LinesToStr([ // statements
  342. 'rtl.createClass($mod, "TObject", null, function () {',
  343. ' this.$init = function () {',
  344. ' };',
  345. ' this.$final = function () {',
  346. ' };',
  347. '});',
  348. 'rtl.createClass($mod, "TList$G1", $mod.TObject, function () {',
  349. ' this.$init = function () {',
  350. ' $mod.TObject.$init.call(this);',
  351. ' this.FItems = [];',
  352. ' };',
  353. ' this.$final = function () {',
  354. ' this.FItems = undefined;',
  355. ' $mod.TObject.$final.call(this);',
  356. ' };',
  357. ' this.GetItems = function (Index) {',
  358. ' var Result = 0;',
  359. ' Result = this.FItems[Index];',
  360. ' return Result;',
  361. ' };',
  362. ' this.SetItems = function (Index, Value) {',
  363. ' this.FItems[Index] = Value;',
  364. ' };',
  365. ' this.Alter = function (w) {',
  366. ' this.FItems = rtl.arraySetLength(this.FItems, 0, rtl.length(this.FItems) + 1);',
  367. ' this.FItems.splice(2, 0, w);',
  368. ' this.FItems.splice(2, 3);',
  369. ' };',
  370. '});',
  371. 'this.l = null;',
  372. 'this.w = 0;',
  373. '']),
  374. LinesToStr([ // $mod.$main
  375. '$mod.l.SetItems(1, $mod.w);',
  376. '$mod.w = $mod.l.GetItems(2);',
  377. '']));
  378. end;
  379. procedure TTestGenerics.TestGen_Class_TCustomList;
  380. begin
  381. StartProgram(false);
  382. Add([
  383. '{$mode delphi}',
  384. 'type',
  385. ' TObject = class end;',
  386. ' TCustomList<T> = class',
  387. ' public',
  388. ' function PrepareAddingItem: word; virtual;',
  389. ' end;',
  390. ' TList<T> = class(TCustomList<T>)',
  391. ' public',
  392. ' function Add: word;',
  393. ' end;',
  394. ' TWordList = TList<word>;',
  395. 'function TCustomList<T>.PrepareAddingItem: word;',
  396. 'begin',
  397. 'end;',
  398. 'function TList<T>.Add: word;',
  399. 'begin',
  400. ' Result:=PrepareAddingItem;',
  401. //' Result:=Self.PrepareAddingItem;',
  402. //' with Self do Result:=PrepareAddingItem;',
  403. 'end;',
  404. 'var l: TWordList;',
  405. 'begin',
  406. '']);
  407. ConvertProgram;
  408. CheckSource('TestGen_Class_TCustomList',
  409. LinesToStr([ // statements
  410. 'rtl.createClass($mod, "TObject", null, function () {',
  411. ' this.$init = function () {',
  412. ' };',
  413. ' this.$final = function () {',
  414. ' };',
  415. '});',
  416. 'rtl.createClass($mod, "TCustomList$G2", $mod.TObject, function () {',
  417. ' this.PrepareAddingItem = function () {',
  418. ' var Result = 0;',
  419. ' return Result;',
  420. ' };',
  421. '});',
  422. 'rtl.createClass($mod, "TList$G1", $mod.TCustomList$G2, function () {',
  423. ' this.Add = function () {',
  424. ' var Result = 0;',
  425. ' Result = this.PrepareAddingItem();',
  426. ' return Result;',
  427. ' };',
  428. '});',
  429. 'this.l = null;',
  430. '']),
  431. LinesToStr([ // $mod.$main
  432. '']));
  433. end;
  434. procedure TTestGenerics.TestGen_ClassAncestor;
  435. begin
  436. StartProgram(false);
  437. Add([
  438. 'type',
  439. ' TObject = class end;',
  440. ' generic TBird<T> = class',
  441. ' end;',
  442. ' generic TEagle<T> = class(specialize TBird<T>)',
  443. ' end;',
  444. 'var a: specialize TEagle<word>;',
  445. 'begin',
  446. '']);
  447. ConvertProgram;
  448. CheckSource('TestGen_ClassAncestor',
  449. LinesToStr([ // statements
  450. 'rtl.createClass($mod, "TObject", null, function () {',
  451. ' this.$init = function () {',
  452. ' };',
  453. ' this.$final = function () {',
  454. ' };',
  455. '});',
  456. 'rtl.createClass($mod, "TBird$G2", $mod.TObject, function () {',
  457. '});',
  458. 'rtl.createClass($mod, "TEagle$G1", $mod.TBird$G2, function () {',
  459. '});',
  460. 'this.a = null;',
  461. '']),
  462. LinesToStr([ // $mod.$main
  463. '']));
  464. end;
  465. procedure TTestGenerics.TestGen_Class_TypeInfo;
  466. begin
  467. Converter.Options:=Converter.Options-[coNoTypeInfo];
  468. StartProgram(false);
  469. Add([
  470. 'type',
  471. ' TObject = class end;',
  472. ' generic TBird<T> = class',
  473. ' published',
  474. ' m: T;',
  475. ' end;',
  476. ' TEagle = specialize TBird<word>;',
  477. 'var',
  478. ' b: specialize TBird<word>;',
  479. ' p: pointer;',
  480. 'begin',
  481. ' p:=typeinfo(TEagle);',
  482. ' p:=typeinfo(b);',
  483. '']);
  484. ConvertProgram;
  485. CheckSource('TestGen_Class_TypeInfo',
  486. LinesToStr([ // statements
  487. '$mod.$rtti.$Class("TBird$G1");',
  488. 'rtl.createClass($mod, "TObject", null, function () {',
  489. ' this.$init = function () {',
  490. ' };',
  491. ' this.$final = function () {',
  492. ' };',
  493. '});',
  494. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  495. ' this.$init = function () {',
  496. ' $mod.TObject.$init.call(this);',
  497. ' this.m = 0;',
  498. ' };',
  499. ' var $r = this.$rtti;',
  500. ' $r.addField("m", rtl.word);',
  501. '});',
  502. 'this.b = null;',
  503. 'this.p = null;',
  504. '']),
  505. LinesToStr([ // $mod.$main
  506. '$mod.p = $mod.$rtti["TBird$G1"];',
  507. '$mod.p = $mod.b.$rtti;',
  508. '']));
  509. end;
  510. procedure TTestGenerics.TestGen_Class_TypeOverload;
  511. begin
  512. exit;// ToDo
  513. StartProgram(false);
  514. Add([
  515. '{$mode delphi}',
  516. 'type',
  517. ' TObject = class end;',
  518. ' TBird = word;',
  519. ' TBird<T> = class',
  520. ' m: T;',
  521. ' end;',
  522. ' TEagle = TBird<word>;',
  523. 'var',
  524. ' b: TBird<word>;',
  525. ' e: TEagle;',
  526. 'begin',
  527. '']);
  528. ConvertProgram;
  529. CheckSource('TestGen_Class_TypeOverload',
  530. LinesToStr([ // statements
  531. 'rtl.createClass($mod, "TObject", null, function () {',
  532. ' this.$init = function () {',
  533. ' };',
  534. ' this.$final = function () {',
  535. ' };',
  536. '});',
  537. '']),
  538. LinesToStr([ // $mod.$main
  539. '']));
  540. end;
  541. procedure TTestGenerics.TestGen_Class_ClassProperty;
  542. begin
  543. StartProgram(false);
  544. Add([
  545. '{$mode delphi}',
  546. 'type',
  547. ' TObject = class end;',
  548. ' TBird<T> = class',
  549. ' private',
  550. ' class var fSize: T;',
  551. ' public',
  552. ' class property Size: T read fSize write fSize;',
  553. ' end;',
  554. ' TEagle = TBird<word>;',
  555. 'begin',
  556. ' TBird<word>.Size:=3+TBird<word>.Size;',
  557. '']);
  558. ConvertProgram;
  559. CheckSource('TestGen_Class_ClassProperty',
  560. LinesToStr([ // statements
  561. 'rtl.createClass($mod, "TObject", null, function () {',
  562. ' this.$init = function () {',
  563. ' };',
  564. ' this.$final = function () {',
  565. ' };',
  566. '});',
  567. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  568. ' this.fSize = 0;',
  569. '});',
  570. '']),
  571. LinesToStr([ // $mod.$main
  572. '$mod.TBird$G1.fSize = 3 + $mod.TBird$G1.fSize;',
  573. '']));
  574. end;
  575. procedure TTestGenerics.TestGen_Class_ClassProc;
  576. begin
  577. StartProgram(false);
  578. Add([
  579. 'type',
  580. ' TObject = class end;',
  581. ' generic TPoint<T> = class',
  582. ' class var x: T;',
  583. ' class procedure Fly; static;',
  584. ' class procedure Run;',
  585. ' end;',
  586. 'class procedure Tpoint.Fly;',
  587. 'begin',
  588. ' x:=x+3;',
  589. ' tpoint.x:=tpoint.x+4;',
  590. ' Fly;',
  591. ' tpoint.Fly;',
  592. ' Run;',
  593. ' tpoint.Run;',
  594. 'end;',
  595. 'class procedure TPoint.Run;',
  596. 'begin',
  597. ' x:=x+5;',
  598. ' tpoint.x:=tpoint.x+6;',
  599. ' Fly;',
  600. ' tpoint.Fly;',
  601. ' Run;',
  602. ' tpoint.Run;',
  603. 'end;',
  604. 'var p: specialize TPoint<word>;',
  605. 'begin',
  606. '']);
  607. ConvertProgram;
  608. CheckSource('TestGen_Class_ClassProc',
  609. LinesToStr([ // statements
  610. 'rtl.createClass($mod, "TObject", null, function () {',
  611. ' this.$init = function () {',
  612. ' };',
  613. ' this.$final = function () {',
  614. ' };',
  615. '});',
  616. 'rtl.createClass($mod, "TPoint$G1", $mod.TObject, function () {',
  617. ' this.x = 0;',
  618. ' this.Fly = function () {',
  619. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 3;',
  620. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 4;',
  621. ' $mod.TPoint$G1.Fly();',
  622. ' $mod.TPoint$G1.Fly();',
  623. ' $mod.TPoint$G1.Run();',
  624. ' $mod.TPoint$G1.Run();',
  625. ' };',
  626. ' this.Run = function () {',
  627. ' $mod.TPoint$G1.x = this.x + 5;',
  628. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 6;',
  629. ' this.Fly();',
  630. ' $mod.TPoint$G1.Fly();',
  631. ' this.Run();',
  632. ' $mod.TPoint$G1.Run();',
  633. ' };',
  634. '});',
  635. 'this.p = null;',
  636. '']),
  637. LinesToStr([ // $mod.$main
  638. '']));
  639. end;
  640. procedure TTestGenerics.TestGen_Class_ClassConstructor;
  641. begin
  642. StartProgram(false);
  643. Add([
  644. 'type',
  645. ' TObject = class end;',
  646. ' generic TPoint<T> = class',
  647. ' class var x: T;',
  648. ' class procedure Fly; static;',
  649. ' class constructor Init;',
  650. ' end;',
  651. 'var count: word;',
  652. 'class procedure Tpoint.Fly;',
  653. 'begin',
  654. 'end;',
  655. 'class constructor tpoint.init;',
  656. 'begin',
  657. ' count:=count+1;',
  658. ' x:=3;',
  659. ' tpoint.x:=4;',
  660. ' fly;',
  661. ' tpoint.fly;',
  662. 'end;',
  663. 'var',
  664. ' r: specialize TPoint<word>;',
  665. ' s: specialize TPoint<smallint>;',
  666. 'begin',
  667. ' r.x:=10;',
  668. '']);
  669. ConvertProgram;
  670. CheckSource('TestGen_Class_ClassConstructor',
  671. LinesToStr([ // statements
  672. 'rtl.createClass($mod, "TObject", null, function () {',
  673. ' this.$init = function () {',
  674. ' };',
  675. ' this.$final = function () {',
  676. ' };',
  677. '});',
  678. 'this.count = 0;',
  679. 'rtl.createClass($mod, "TPoint$G1", $mod.TObject, function () {',
  680. ' this.x = 0;',
  681. ' this.Fly = function () {',
  682. ' };',
  683. '});',
  684. 'this.r = null;',
  685. 'rtl.createClass($mod, "TPoint$G2", $mod.TObject, function () {',
  686. ' this.x = 0;',
  687. ' this.Fly = function () {',
  688. ' };',
  689. '});',
  690. 'this.s = null;',
  691. '']),
  692. LinesToStr([ // $mod.$main
  693. '(function () {',
  694. ' $mod.count = $mod.count + 1;',
  695. ' $mod.TPoint$G1.x = 3;',
  696. ' $mod.TPoint$G1.x = 4;',
  697. ' $mod.TPoint$G1.Fly();',
  698. ' $mod.TPoint$G1.Fly();',
  699. '})();',
  700. '(function () {',
  701. ' $mod.count = $mod.count + 1;',
  702. ' $mod.TPoint$G2.x = 3;',
  703. ' $mod.TPoint$G2.x = 4;',
  704. ' $mod.TPoint$G2.Fly();',
  705. ' $mod.TPoint$G2.Fly();',
  706. '})();',
  707. '$mod.TPoint$G1.x = 10;',
  708. '']));
  709. end;
  710. procedure TTestGenerics.TestGen_Class_TypeCastSpecializesWarn;
  711. begin
  712. StartProgram(false);
  713. Add([
  714. '{$mode delphi}',
  715. 'type',
  716. ' TObject = class end;',
  717. ' TBird<T> = class F: T; end;',
  718. ' TBirdWord = TBird<Word>;',
  719. ' TBirdChar = TBird<Char>;',
  720. 'var',
  721. ' w: TBirdWord;',
  722. ' c: TBirdChar;',
  723. 'begin',
  724. ' w:=TBirdWord(c);',
  725. '']);
  726. ConvertProgram;
  727. CheckSource('TestGen_Class_TypeCastSpecializesWarn',
  728. LinesToStr([ // statements
  729. 'rtl.createClass($mod, "TObject", null, function () {',
  730. ' this.$init = function () {',
  731. ' };',
  732. ' this.$final = function () {',
  733. ' };',
  734. '});',
  735. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  736. ' this.$init = function () {',
  737. ' $mod.TObject.$init.call(this);',
  738. ' this.F = 0;',
  739. ' };',
  740. '});',
  741. 'rtl.createClass($mod, "TBird$G2", $mod.TObject, function () {',
  742. ' this.$init = function () {',
  743. ' $mod.TObject.$init.call(this);',
  744. ' this.F = "";',
  745. ' };',
  746. '});',
  747. 'this.w = null;',
  748. 'this.c = null;',
  749. '']),
  750. LinesToStr([ // $mod.$main
  751. '$mod.w = $mod.c;',
  752. '']));
  753. CheckHint(mtWarning,nClassTypesAreNotRelatedXY,'Class types "TBird$G2<Char>" and "TBird$G1<Word>" are not related');
  754. CheckResolverUnexpectedHints();
  755. end;
  756. procedure TTestGenerics.TestGen_Class_TypeCastSpecializesJSValueNoWarn;
  757. begin
  758. StartProgram(false);
  759. Add([
  760. '{$mode delphi}',
  761. 'type',
  762. ' TObject = class end;',
  763. ' TBird<T> = class F: T; end;',
  764. ' TBirdWord = TBird<Word>;',
  765. ' TBirdAny = TBird<JSValue>;',
  766. 'var',
  767. ' w: TBirdWord;',
  768. ' a: TBirdAny;',
  769. 'begin',
  770. ' w:=TBirdWord(a);',
  771. ' a:=TBirdAny(w);',
  772. '']);
  773. ConvertProgram;
  774. CheckSource('TestGen_Class_TypeCastSpecializesJSValueNoWarn',
  775. LinesToStr([ // statements
  776. 'rtl.createClass($mod, "TObject", null, function () {',
  777. ' this.$init = function () {',
  778. ' };',
  779. ' this.$final = function () {',
  780. ' };',
  781. '});',
  782. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  783. ' this.$init = function () {',
  784. ' $mod.TObject.$init.call(this);',
  785. ' this.F = 0;',
  786. ' };',
  787. '});',
  788. 'rtl.createClass($mod, "TBird$G2", $mod.TObject, function () {',
  789. ' this.$init = function () {',
  790. ' $mod.TObject.$init.call(this);',
  791. ' this.F = undefined;',
  792. ' };',
  793. '});',
  794. 'this.w = null;',
  795. 'this.a = null;',
  796. '']),
  797. LinesToStr([ // $mod.$main
  798. '$mod.w = $mod.a;',
  799. '$mod.a = $mod.w;',
  800. '']));
  801. CheckResolverUnexpectedHints();
  802. end;
  803. procedure TTestGenerics.TestGen_Class_VarArgsOfType;
  804. begin
  805. StartProgram(false);
  806. Add([
  807. '{$mode objfpc}',
  808. '{$modeswitch externalclass}',
  809. 'type',
  810. ' TJSObject = class external name ''Object''',
  811. ' end;',
  812. ' generic TGJSSet<T> = class external name ''Set''',
  813. ' constructor new(aElement1: T); varargs of T; overload;',
  814. ' function bind(thisArg: TJSObject): T; varargs of T;',
  815. ' end;',
  816. ' TJSWordSet = specialize TGJSSet<word>;',
  817. 'var',
  818. ' s: TJSWordSet;',
  819. ' w: word;',
  820. 'begin',
  821. ' s:=TJSWordSet.new(3);',
  822. ' s:=TJSWordSet.new(3,5);',
  823. ' w:=s.bind(nil);',
  824. ' w:=s.bind(nil,6);',
  825. ' w:=s.bind(nil,7,8);',
  826. '']);
  827. ConvertProgram;
  828. CheckSource('TestGen_Class_VarArgsOfType',
  829. LinesToStr([ // statements
  830. 'this.s = null;',
  831. 'this.w = 0;',
  832. '']),
  833. LinesToStr([ // $mod.$main
  834. '$mod.s = new Set(3);',
  835. '$mod.s = new Set(3, 5);',
  836. '$mod.w = $mod.s.bind(null);',
  837. '$mod.w = $mod.s.bind(null, 6);',
  838. '$mod.w = $mod.s.bind(null, 7, 8);',
  839. '']));
  840. end;
  841. procedure TTestGenerics.TestGen_Class_OverloadsInUnit;
  842. begin
  843. StartProgram(true,[supTObject]);
  844. AddModuleWithIntfImplSrc('UnitA.pas',
  845. LinesToStr([
  846. 'type',
  847. ' generic TBird<T> = class',
  848. ' const c = 13;',
  849. ' constructor Create(w: T);',
  850. ' constructor Create(b: boolean);',
  851. ' end;',
  852. '']),
  853. LinesToStr([
  854. 'constructor TBird.Create(w: T);',
  855. 'const c = 14;',
  856. 'begin',
  857. 'end;',
  858. 'constructor TBird.Create(b: boolean);',
  859. 'const c = 15;',
  860. 'begin',
  861. 'end;',
  862. '']));
  863. Add([
  864. 'uses UnitA;',
  865. 'type',
  866. ' TWordBird = specialize TBird<word>;',
  867. ' TDoubleBird = specialize TBird<double>;',
  868. 'var',
  869. ' wb: TWordBird;',
  870. ' db: TDoubleBird;',
  871. 'begin',
  872. ' wb:=TWordBird.Create(3);',
  873. ' wb:=TWordBird.Create(true);',
  874. ' db:=TDoubleBird.Create(1.3);',
  875. ' db:=TDoubleBird.Create(true);',
  876. '']);
  877. ConvertProgram;
  878. CheckUnit('UnitA.pas',
  879. LinesToStr([ // statements
  880. 'rtl.module("UnitA", ["system"], function () {',
  881. ' var $mod = this;',
  882. ' rtl.createClass($mod, "TBird$G1", pas.system.TObject, function () {',
  883. ' this.c = 13;',
  884. ' var c$1 = 14;',
  885. ' this.Create$1 = function (w) {',
  886. ' return this;',
  887. ' };',
  888. ' var c$2 = 15;',
  889. ' this.Create$2 = function (b) {',
  890. ' return this;',
  891. ' };',
  892. ' });',
  893. ' rtl.createClass($mod, "TBird$G2", pas.system.TObject, function () {',
  894. ' this.c = 13;',
  895. ' var c$1 = 14;',
  896. ' this.Create$1 = function (w) {',
  897. ' return this;',
  898. ' };',
  899. ' var c$2 = 15;',
  900. ' this.Create$2 = function (b) {',
  901. ' return this;',
  902. ' };',
  903. ' });',
  904. '});',
  905. '']));
  906. CheckSource('TestGen_Class_OverloadsInUnit',
  907. LinesToStr([ // statements
  908. 'this.wb = null;',
  909. 'this.db = null;',
  910. '']),
  911. LinesToStr([ // $mod.$main
  912. '$mod.wb = pas.UnitA.TBird$G1.$create("Create$1", [3]);',
  913. '$mod.wb = pas.UnitA.TBird$G1.$create("Create$2", [true]);',
  914. '$mod.db = pas.UnitA.TBird$G2.$create("Create$1", [1.3]);',
  915. '$mod.db = pas.UnitA.TBird$G2.$create("Create$2", [true]);',
  916. '']));
  917. end;
  918. procedure TTestGenerics.TestGen_ClassForward_CircleRTTI;
  919. begin
  920. Converter.Options:=Converter.Options-[coNoTypeInfo];
  921. StartProgram(false);
  922. Add([
  923. '{$mode objfpc}',
  924. 'type',
  925. ' TObject = class end;',
  926. ' {$M+}',
  927. ' TPersistent = class end;',
  928. ' {$M-}',
  929. ' generic TAnt<T> = class;',
  930. ' generic TFish<U> = class(TPersistent)',
  931. ' private type AliasU = U;',
  932. ' published',
  933. ' a: specialize TAnt<AliasU>;',
  934. ' end;',
  935. ' generic TAnt<T> = class(TPersistent)',
  936. ' private type AliasT = T;',
  937. ' published',
  938. ' f: specialize TFish<AliasT>;',
  939. ' end;',
  940. 'var',
  941. ' WordFish: specialize TFish<word>;',
  942. ' p: pointer;',
  943. 'begin',
  944. ' p:=typeinfo(specialize TAnt<word>);',
  945. ' p:=typeinfo(specialize TFish<word>);',
  946. '']);
  947. ConvertProgram;
  948. CheckSource('TestGen_ClassForward_CircleRTTI',
  949. LinesToStr([ // statements
  950. '$mod.$rtti.$Class("TAnt$G2");',
  951. '$mod.$rtti.$Class("TFish$G2");',
  952. 'rtl.createClass($mod, "TObject", null, function () {',
  953. ' this.$init = function () {',
  954. ' };',
  955. ' this.$final = function () {',
  956. ' };',
  957. '});',
  958. 'rtl.createClass($mod, "TPersistent", $mod.TObject, function () {',
  959. '});',
  960. 'rtl.createClass($mod, "TAnt$G2", $mod.TPersistent, function () {',
  961. ' this.$init = function () {',
  962. ' $mod.TPersistent.$init.call(this);',
  963. ' this.f = null;',
  964. ' };',
  965. ' this.$final = function () {',
  966. ' this.f = undefined;',
  967. ' $mod.TPersistent.$final.call(this);',
  968. ' };',
  969. ' var $r = this.$rtti;',
  970. ' $r.addField("f", $mod.$rtti["TFish$G2"]);',
  971. '});',
  972. 'rtl.createClass($mod, "TFish$G2", $mod.TPersistent, function () {',
  973. ' this.$init = function () {',
  974. ' $mod.TPersistent.$init.call(this);',
  975. ' this.a = null;',
  976. ' };',
  977. ' this.$final = function () {',
  978. ' this.a = undefined;',
  979. ' $mod.TPersistent.$final.call(this);',
  980. ' };',
  981. ' var $r = this.$rtti;',
  982. ' $r.addField("a", $mod.$rtti["TAnt$G2"]);',
  983. '});',
  984. 'this.WordFish = null;',
  985. 'this.p = null;',
  986. '']),
  987. LinesToStr([ // $mod.$main
  988. '$mod.p = $mod.$rtti["TAnt$G2"];',
  989. '$mod.p = $mod.$rtti["TFish$G2"];',
  990. '']));
  991. end;
  992. procedure TTestGenerics.TestGen_ExtClass_Array;
  993. begin
  994. StartProgram(false);
  995. Add([
  996. '{$mode delphi}',
  997. '{$ModeSwitch externalclass}',
  998. 'type',
  999. ' NativeInt = longint;',
  1000. ' TJSGenArray<T> = Class external name ''Array''',
  1001. ' private',
  1002. ' function GetElements(Index: NativeInt): T; external name ''[]'';',
  1003. ' procedure SetElements(Index: NativeInt; const AValue: T); external name ''[]'';',
  1004. ' public',
  1005. ' type TSelfType = TJSGenArray<T>;',
  1006. ' public',
  1007. ' FLength : NativeInt; external name ''length'';',
  1008. ' constructor new; overload;',
  1009. ' constructor new(aLength : NativeInt); overload;',
  1010. ' class function _of() : TSelfType; varargs; external name ''of'';',
  1011. ' function fill(aValue : T) : TSelfType; overload;',
  1012. ' function fill(aValue : T; aStartIndex : NativeInt) : TSelfType; overload;',
  1013. ' function fill(aValue : T; aStartIndex,aEndIndex : NativeInt) : TSelfType; overload;',
  1014. ' property Length : NativeInt Read FLength Write FLength;',
  1015. ' property Elements[Index: NativeInt]: T read GetElements write SetElements; default;',
  1016. ' end;',
  1017. ' TJSWordArray = TJSGenArray<word>;',
  1018. 'var',
  1019. ' wa: TJSWordArray;',
  1020. ' w: word;',
  1021. 'begin',
  1022. ' wa:=TJSWordArray.new;',
  1023. ' wa:=TJSWordArray.new(3);',
  1024. ' wa:=TJSWordArray._of(4,5);',
  1025. ' wa:=wa.fill(7);',
  1026. ' wa:=wa.fill(7,8,9);',
  1027. ' w:=wa.length;',
  1028. ' wa.length:=10;',
  1029. ' wa[11]:=w;',
  1030. ' w:=wa[12];',
  1031. '']);
  1032. ConvertProgram;
  1033. CheckSource('TestGen_ExtClass_Array',
  1034. LinesToStr([ // statements
  1035. 'this.wa = null;',
  1036. 'this.w = 0;',
  1037. '']),
  1038. LinesToStr([ // $mod.$main
  1039. '$mod.wa = new Array();',
  1040. '$mod.wa = new Array(3);',
  1041. '$mod.wa = Array.of(4, 5);',
  1042. '$mod.wa = $mod.wa.fill(7);',
  1043. '$mod.wa = $mod.wa.fill(7, 8, 9);',
  1044. '$mod.w = $mod.wa.length;',
  1045. '$mod.wa.length = 10;',
  1046. '$mod.wa[11] = $mod.w;',
  1047. '$mod.w = $mod.wa[12];',
  1048. '']));
  1049. end;
  1050. procedure TTestGenerics.TestGen_ExtClass_GenJSValueAssign;
  1051. begin
  1052. StartProgram(false);
  1053. Add([
  1054. '{$mode delphi}',
  1055. '{$modeswitch externalclass}',
  1056. 'type',
  1057. ' TExt<T> = class external name ''Ext''',
  1058. ' F: T;',
  1059. ' end;',
  1060. ' TExtWord = TExt<Word>;',
  1061. ' TExtAny = TExt<JSValue>;',
  1062. 'procedure Run(e: TExtAny);',
  1063. 'begin end;',
  1064. 'var',
  1065. ' w: TExtWord;',
  1066. ' a: TExtAny;',
  1067. 'begin',
  1068. ' a:=w;',
  1069. ' Run(w);',
  1070. '']);
  1071. ConvertProgram;
  1072. CheckSource('TestGen_ExtClass_GenJSValueAssign',
  1073. LinesToStr([ // statements
  1074. 'this.Run = function (e) {',
  1075. '};',
  1076. 'this.w = null;',
  1077. 'this.a = null;',
  1078. '']),
  1079. LinesToStr([ // $mod.$main
  1080. '$mod.a = $mod.w;',
  1081. '$mod.Run($mod.w);',
  1082. '']));
  1083. CheckResolverUnexpectedHints();
  1084. end;
  1085. procedure TTestGenerics.TestGen_ExtClass_AliasMemberType;
  1086. begin
  1087. StartProgram(false);
  1088. Add([
  1089. '{$mode objfpc}',
  1090. '{$modeswitch externalclass}',
  1091. 'type',
  1092. ' generic TExt<T> = class external name ''Ext''',
  1093. ' public type TRun = reference to function(a: T): T;',
  1094. ' end;',
  1095. ' TExtWord = specialize TExt<word>;',
  1096. ' TExtWordRun = TExtWord.TRun;',
  1097. 'begin',
  1098. '']);
  1099. ConvertProgram;
  1100. CheckSource('TestGen_ExtClass_AliasMemberType',
  1101. LinesToStr([ // statements
  1102. '']),
  1103. LinesToStr([ // $mod.$main
  1104. '']));
  1105. end;
  1106. procedure TTestGenerics.TestGen_ExtClass_RTTI;
  1107. begin
  1108. Converter.Options:=Converter.Options-[coNoTypeInfo];
  1109. StartProgram(false);
  1110. Add([
  1111. '{$mode objfpc}',
  1112. '{$modeswitch externalclass}',
  1113. 'type',
  1114. ' generic TGJSSET<T> = class external name ''SET''',
  1115. ' A: T;',
  1116. ' end;',
  1117. ' TJSSet = specialize TGJSSET<JSValue>;',
  1118. ' TJSSetEventProc = reference to procedure(value : JSValue; key: NativeInt; set_: TJSSet);',
  1119. 'var p: Pointer;',
  1120. 'begin',
  1121. ' p:=typeinfo(TJSSetEventProc);',
  1122. '']);
  1123. ConvertProgram;
  1124. CheckSource('TestGen_ExtClass_RTTI',
  1125. LinesToStr([ // statements
  1126. '$mod.$rtti.$ExtClass("TGJSSET$G1", {',
  1127. ' jsclass: "SET"',
  1128. '});',
  1129. '$mod.$rtti.$RefToProcVar("TJSSetEventProc", {',
  1130. ' procsig: rtl.newTIProcSig([["value", rtl.jsvalue], ["key", rtl.nativeint], ["set_", $mod.$rtti["TGJSSET$G1"]]])',
  1131. '});',
  1132. 'this.p = null;',
  1133. '']),
  1134. LinesToStr([ // $mod.$main
  1135. '$mod.p = $mod.$rtti["TJSSetEventProc"];',
  1136. '']));
  1137. end;
  1138. procedure TTestGenerics.TestGen_ClassInterface_Corba;
  1139. begin
  1140. StartProgram(false);
  1141. Add([
  1142. '{$interfaces corba}',
  1143. 'type',
  1144. ' IUnknown = interface;',
  1145. ' IUnknown = interface',
  1146. ' [''{00000000-0000-0000-C000-000000000046}'']',
  1147. ' end;',
  1148. ' IInterface = IUnknown;',
  1149. ' generic IBird<T> = interface(IInterface)',
  1150. ' function GetSize: T;',
  1151. ' procedure SetSize(i: T);',
  1152. ' property Size: T read GetSize write SetSize;',
  1153. ' procedure DoIt(i: T);',
  1154. ' end;',
  1155. ' TObject = class',
  1156. ' end;',
  1157. ' generic TBird<T> = class(TObject,specialize IBird<T>)',
  1158. ' function GetSize: T; virtual; abstract;',
  1159. ' procedure SetSize(i: T); virtual; abstract;',
  1160. ' procedure DoIt(i: T); virtual; abstract;',
  1161. ' end;',
  1162. ' IWordBird = specialize IBird<Word>;',
  1163. ' TWordBird = specialize TBird<Word>;',
  1164. 'var',
  1165. ' BirdIntf: IWordBird;',
  1166. 'begin',
  1167. ' BirdIntf.Size:=BirdIntf.Size;',
  1168. '']);
  1169. ConvertProgram;
  1170. CheckSource('TestGen_ClassInterface_Corba',
  1171. LinesToStr([ // statements
  1172. 'rtl.createInterface($mod, "IUnknown", "{00000000-0000-0000-C000-000000000046}", [], null);',
  1173. 'rtl.createClass($mod, "TObject", null, function () {',
  1174. ' this.$init = function () {',
  1175. ' };',
  1176. ' this.$final = function () {',
  1177. ' };',
  1178. '});',
  1179. 'rtl.createInterface($mod, "IBird$G2", "{7D9907A1-5178-37B5-9D32-7BC020005905}", ["GetSize", "SetSize", "DoIt"], $mod.IUnknown);',
  1180. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  1181. ' rtl.addIntf(this, $mod.IBird$G2);',
  1182. '});',
  1183. 'this.BirdIntf = null;',
  1184. '']),
  1185. LinesToStr([ // $mod.$main
  1186. '$mod.BirdIntf.SetSize($mod.BirdIntf.GetSize());',
  1187. '']));
  1188. end;
  1189. procedure TTestGenerics.TestGen_ClassInterface_InterfacedObject;
  1190. begin
  1191. StartProgram(true,[supTInterfacedObject]);
  1192. Add([
  1193. '{$mode delphi}',
  1194. 'type',
  1195. ' IComparer<T> = interface [''{505778ED-F783-4456-9691-32F419CC5E18}'']',
  1196. ' function Compare(const Left, Right: T): Integer; overload;',
  1197. ' end;',
  1198. ' TComparer<T> = class(TInterfacedObject, IComparer<T>)',
  1199. ' function Compare(const Left, Right: T): Integer;',
  1200. ' end;',
  1201. 'function TComparer<T>.Compare(const Left, Right: T): Integer; begin end;',
  1202. 'var',
  1203. ' aComparer : IComparer<Integer>;',
  1204. 'begin',
  1205. ' aComparer:=TComparer<Integer>.Create;',
  1206. '']);
  1207. ConvertProgram;
  1208. CheckSource('TestGen_ClassInterface_InterfacedObject',
  1209. LinesToStr([ // statements
  1210. 'rtl.createInterface($mod, "IComparer$G2", "{505778ED-F783-4456-9691-32F419CC5E18}", ["Compare"], pas.system.IUnknown);',
  1211. 'this.aComparer = null;',
  1212. 'rtl.createClass($mod, "TComparer$G1", pas.system.TInterfacedObject, function () {',
  1213. ' this.Compare = function (Left, Right) {',
  1214. ' var Result = 0;',
  1215. ' return Result;',
  1216. ' };',
  1217. ' rtl.addIntf(this, $mod.IComparer$G2);',
  1218. ' rtl.addIntf(this, pas.system.IUnknown);',
  1219. '});',
  1220. '']),
  1221. LinesToStr([ // $mod.$main
  1222. 'rtl.setIntfP($mod, "aComparer", rtl.queryIntfT($mod.TComparer$G1.$create("Create"), $mod.IComparer$G2), true);',
  1223. '']));
  1224. end;
  1225. procedure TTestGenerics.TestGen_InlineSpec_Constructor;
  1226. begin
  1227. StartProgram(false);
  1228. Add([
  1229. '{$mode objfpc}',
  1230. 'type',
  1231. ' TObject = class',
  1232. ' public',
  1233. ' constructor Create;',
  1234. ' end;',
  1235. ' generic TBird<T> = class',
  1236. ' end;',
  1237. 'constructor TObject.Create; begin end;',
  1238. 'var b: specialize TBird<word>;',
  1239. 'begin',
  1240. ' b:=specialize TBird<word>.Create;',
  1241. '']);
  1242. ConvertProgram;
  1243. CheckSource('TestGen_InlineSpec_Constructor',
  1244. LinesToStr([ // statements
  1245. 'rtl.createClass($mod, "TObject", null, function () {',
  1246. ' this.$init = function () {',
  1247. ' };',
  1248. ' this.$final = function () {',
  1249. ' };',
  1250. ' this.Create = function () {',
  1251. ' return this;',
  1252. ' };',
  1253. '});',
  1254. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  1255. '});',
  1256. 'this.b = null;',
  1257. '']),
  1258. LinesToStr([ // $mod.$main
  1259. '$mod.b = $mod.TBird$G1.$create("Create");',
  1260. '']));
  1261. end;
  1262. procedure TTestGenerics.TestGen_CallUnitImplProc;
  1263. begin
  1264. AddModuleWithIntfImplSrc('UnitA.pas',
  1265. LinesToStr([
  1266. 'type',
  1267. ' generic TBird<T> = class',
  1268. ' procedure Fly;',
  1269. ' end;',
  1270. 'var b: specialize TBird<boolean>;',
  1271. '']),
  1272. LinesToStr([
  1273. 'procedure DoIt;',
  1274. 'var b: specialize TBird<word>;',
  1275. 'begin',
  1276. ' b:=specialize TBird<word>.Create;',
  1277. ' b.Fly;',
  1278. 'end;',
  1279. 'procedure TBird.Fly;',
  1280. 'begin',
  1281. ' DoIt;',
  1282. 'end;',
  1283. '']));
  1284. StartProgram(true,[supTObject]);
  1285. Add('uses UnitA;');
  1286. Add('begin');
  1287. ConvertProgram;
  1288. CheckUnit('UnitA.pas',
  1289. LinesToStr([ // statements
  1290. 'rtl.module("UnitA", ["system"], function () {',
  1291. ' var $mod = this;',
  1292. ' var $impl = $mod.$impl;',
  1293. ' rtl.createClass($mod, "TBird$G1", pas.system.TObject, function () {',
  1294. ' this.Fly = function () {',
  1295. ' $impl.DoIt();',
  1296. ' };',
  1297. ' });',
  1298. ' this.b = null;',
  1299. ' rtl.createClass($mod, "TBird$G2", pas.system.TObject, function () {',
  1300. ' this.Fly = function () {',
  1301. ' $impl.DoIt();',
  1302. ' };',
  1303. ' });',
  1304. '}, null, function () {',
  1305. ' var $mod = this;',
  1306. ' var $impl = $mod.$impl;',
  1307. ' $impl.DoIt = function () {',
  1308. ' var b = null;',
  1309. ' b = $mod.TBird$G2.$create("Create");',
  1310. ' b.Fly();',
  1311. ' };',
  1312. '});',
  1313. '']));
  1314. end;
  1315. procedure TTestGenerics.TestGen_IntAssignTemplVar;
  1316. begin
  1317. StartProgram(false);
  1318. Add([
  1319. 'type',
  1320. ' TObject = class end;',
  1321. ' generic TBird<T> = class',
  1322. ' m: T;',
  1323. ' procedure Fly;',
  1324. ' end;',
  1325. 'var b: specialize TBird<word>;',
  1326. 'procedure TBird.Fly;',
  1327. 'var i: nativeint;',
  1328. 'begin',
  1329. ' i:=m;',
  1330. 'end;',
  1331. 'begin',
  1332. '']);
  1333. ConvertProgram;
  1334. CheckSource('TestGen_IntAssignTemplVar',
  1335. LinesToStr([ // statements
  1336. 'rtl.createClass($mod, "TObject", null, function () {',
  1337. ' this.$init = function () {',
  1338. ' };',
  1339. ' this.$final = function () {',
  1340. ' };',
  1341. '});',
  1342. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  1343. ' this.$init = function () {',
  1344. ' $mod.TObject.$init.call(this);',
  1345. ' this.m = 0;',
  1346. ' };',
  1347. ' this.Fly = function () {',
  1348. ' var i = 0;',
  1349. ' i = this.m;',
  1350. ' };',
  1351. '});',
  1352. 'this.b = null;',
  1353. '']),
  1354. LinesToStr([ // $mod.$main
  1355. '']));
  1356. end;
  1357. procedure TTestGenerics.TestGen_TypeCastDotField;
  1358. begin
  1359. StartProgram(false);
  1360. Add([
  1361. 'type',
  1362. ' TObject = class end;',
  1363. ' generic TBird<T> = class',
  1364. ' Field: T;',
  1365. ' procedure Fly;',
  1366. ' end;',
  1367. 'var',
  1368. ' o: TObject;',
  1369. ' b: specialize TBird<word>;',
  1370. 'procedure TBird.Fly;',
  1371. 'begin',
  1372. ' specialize TBird<word>(o).Field:=3;',
  1373. ' if 4=specialize TBird<word>(o).Field then ;',
  1374. 'end;',
  1375. 'begin',
  1376. ' specialize TBird<word>(o).Field:=5;',
  1377. ' if 6=specialize TBird<word>(o).Field then ;',
  1378. '']);
  1379. ConvertProgram;
  1380. CheckSource('TestGen_TypeCastDotField',
  1381. LinesToStr([ // statements
  1382. 'rtl.createClass($mod, "TObject", null, function () {',
  1383. ' this.$init = function () {',
  1384. ' };',
  1385. ' this.$final = function () {',
  1386. ' };',
  1387. '});',
  1388. 'this.o = null;',
  1389. 'rtl.createClass($mod, "TBird$G1", $mod.TObject, function () {',
  1390. ' this.$init = function () {',
  1391. ' $mod.TObject.$init.call(this);',
  1392. ' this.Field = 0;',
  1393. ' };',
  1394. ' this.Fly = function () {',
  1395. ' $mod.o.Field = 3;',
  1396. ' if (4 === $mod.o.Field) ;',
  1397. ' };',
  1398. '});',
  1399. 'this.b = null;',
  1400. '']),
  1401. LinesToStr([ // $mod.$main
  1402. '$mod.o.Field = 5;',
  1403. 'if (6 === $mod.o.Field) ;',
  1404. '']));
  1405. end;
  1406. procedure TTestGenerics.TestGen_HelperForArray;
  1407. begin
  1408. StartProgram(false);
  1409. Add([
  1410. '{$ModeSwitch typehelpers}',
  1411. 'type',
  1412. ' generic TArr<T> = array[1..2] of T;',
  1413. ' TWordArrHelper = type helper for specialize TArr<word>',
  1414. ' procedure Fly(w: word);',
  1415. ' end;',
  1416. 'procedure TWordArrHelper.Fly(w: word);',
  1417. 'begin',
  1418. 'end;',
  1419. 'var',
  1420. ' a: specialize TArr<word>;',
  1421. 'begin',
  1422. ' a.Fly(3);',
  1423. '']);
  1424. ConvertProgram;
  1425. CheckSource('TestGen_HelperForArray',
  1426. LinesToStr([ // statements
  1427. 'rtl.createHelper($mod, "TWordArrHelper", null, function () {',
  1428. ' this.Fly = function (w) {',
  1429. ' };',
  1430. '});',
  1431. 'this.a = rtl.arraySetLength(null, 0, 2);',
  1432. '']),
  1433. LinesToStr([ // $mod.$main
  1434. '$mod.TWordArrHelper.Fly.call({',
  1435. ' p: $mod,',
  1436. ' get: function () {',
  1437. ' return this.p.a;',
  1438. ' },',
  1439. ' set: function (v) {',
  1440. ' this.p.a = v;',
  1441. ' }',
  1442. '}, 3);',
  1443. '']));
  1444. end;
  1445. procedure TTestGenerics.TestGenProc_Function_ObjFPC;
  1446. begin
  1447. StartProgram(false);
  1448. Add([
  1449. 'generic function Run<T>(a: T): T;',
  1450. 'var i: T;',
  1451. 'begin',
  1452. ' a:=i;',
  1453. ' Result:=a;',
  1454. 'end;',
  1455. 'var w: word;',
  1456. 'begin',
  1457. ' w:=specialize Run<word>(3);',
  1458. '']);
  1459. ConvertProgram;
  1460. CheckSource('TestGenProc_Function_ObjFPC',
  1461. LinesToStr([ // statements
  1462. 'this.w = 0;',
  1463. 'this.Run$s0 = function (a) {',
  1464. ' var Result = 0;',
  1465. ' var i = 0;',
  1466. ' a = i;',
  1467. ' Result = a;',
  1468. ' return Result;',
  1469. '};',
  1470. '']),
  1471. LinesToStr([ // $mod.$main
  1472. '$mod.w = $mod.Run$s0(3);',
  1473. '']));
  1474. end;
  1475. procedure TTestGenerics.TestGenProc_Function_Delphi;
  1476. begin
  1477. StartProgram(false);
  1478. Add([
  1479. '{$mode delphi}',
  1480. 'function Run<T>(a: T): T;',
  1481. 'var i: T;',
  1482. 'begin',
  1483. ' a:=i;',
  1484. ' Result:=a;',
  1485. 'end;',
  1486. 'var w: word;',
  1487. 'begin',
  1488. ' w:=Run<word>(3);',
  1489. '']);
  1490. ConvertProgram;
  1491. CheckSource('TestGenProc_Function_Delphi',
  1492. LinesToStr([ // statements
  1493. 'this.w = 0;',
  1494. 'this.Run$s0 = function (a) {',
  1495. ' var Result = 0;',
  1496. ' var i = 0;',
  1497. ' a = i;',
  1498. ' Result = a;',
  1499. ' return Result;',
  1500. '};',
  1501. '']),
  1502. LinesToStr([ // $mod.$main
  1503. '$mod.w = $mod.Run$s0(3);',
  1504. '']));
  1505. end;
  1506. procedure TTestGenerics.TestGenProc_Overload;
  1507. begin
  1508. StartProgram(false);
  1509. Add([
  1510. 'generic procedure DoIt<T>(a: T; w: word); overload;',
  1511. 'begin',
  1512. 'end;',
  1513. 'generic procedure DoIt<T>(a: T; b: boolean); overload;',
  1514. 'begin',
  1515. 'end;',
  1516. 'begin',
  1517. ' specialize DoIt<word>(3,4);',
  1518. ' specialize DoIt<boolean>(false,5);',
  1519. ' specialize DoIt<word>(6,true);',
  1520. ' specialize DoIt<double>(7.3,true);',
  1521. '']);
  1522. ConvertProgram;
  1523. CheckSource('TestGenProc_Overload',
  1524. LinesToStr([ // statements
  1525. 'this.DoIt$s0 = function (a, w) {',
  1526. '};',
  1527. 'this.DoIt$s1 = function (a, w) {',
  1528. '};',
  1529. 'this.DoIt$1s0 = function (a, b) {',
  1530. '};',
  1531. 'this.DoIt$1s1 = function (a, b) {',
  1532. '};',
  1533. '']),
  1534. LinesToStr([ // $mod.$main
  1535. '$mod.DoIt$s0(3, 4);',
  1536. '$mod.DoIt$s1(false, 5);',
  1537. '$mod.DoIt$1s0(6, true);',
  1538. '$mod.DoIt$1s1(7.3, true);',
  1539. '']));
  1540. end;
  1541. procedure TTestGenerics.TestGenProc_Forward;
  1542. begin
  1543. StartProgram(false);
  1544. Add([
  1545. '{$mode delphi}',
  1546. 'procedure Run<S>(a: S; b: boolean); forward;',
  1547. 'procedure Run<S>(a: S; b: boolean);',
  1548. 'begin',
  1549. ' Run<word>(1,true);',
  1550. 'end;',
  1551. 'begin',
  1552. ' Run(1.3,true);',
  1553. '']);
  1554. ConvertProgram;
  1555. CheckSource('TestGenProc_infer_OverloadForward',
  1556. LinesToStr([ // statements
  1557. 'this.Run$s0 = function (a, b) {',
  1558. ' $mod.Run$s0(1, true);',
  1559. '};',
  1560. 'this.Run$s1 = function (a, b) {',
  1561. ' $mod.Run$s0(1, true);',
  1562. '};',
  1563. '']),
  1564. LinesToStr([ // $mod.$main
  1565. '$mod.Run$s1(1.3, true);',
  1566. '']));
  1567. end;
  1568. procedure TTestGenerics.TestGenProc_Infer_OverloadForward;
  1569. begin
  1570. StartProgram(false);
  1571. Add([
  1572. '{$mode delphi}',
  1573. 'procedure {#A}Run<S>(a: S; b: boolean); forward; overload;',
  1574. 'procedure {#B}Run<T>(a: T; w: word); forward; overload;',
  1575. 'procedure {#C}Run<U>(a: U; b: U); forward; overload;',
  1576. 'procedure {#A2}Run<S>(a: S; b: boolean); overload;',
  1577. 'begin',
  1578. ' {@A}Run(1,true);', // non generic take precedence
  1579. ' {@B}Run(2,word(3));', // non generic take precedence
  1580. ' {@C}Run(''foo'',''bar'');',
  1581. 'end;',
  1582. 'procedure {#B2}Run<T>(a: T; w: word); overload;',
  1583. 'begin',
  1584. 'end;',
  1585. 'procedure {#C2}Run<U>(a: U; b: U); overload;',
  1586. 'begin',
  1587. 'end;',
  1588. 'begin',
  1589. ' {@A}Run(1,true);', // non generic take precedence
  1590. ' {@B}Run(2,word(3));', // non generic take precedence
  1591. ' {@C}Run(''foo'',''bar'');',
  1592. '']);
  1593. ConvertProgram;
  1594. CheckSource('TestGenProc_infer_OverloadForward',
  1595. LinesToStr([ // statements
  1596. 'this.Run$s0 = function (a, b) {',
  1597. ' $mod.Run$s0(1, true);',
  1598. ' $mod.Run$1s0(2, 3);',
  1599. ' $mod.Run$2s0("foo", "bar");',
  1600. '};',
  1601. 'this.Run$1s0 = function (a, w) {',
  1602. '};',
  1603. 'this.Run$2s0 = function (a, b) {',
  1604. '};',
  1605. '']),
  1606. LinesToStr([ // $mod.$main
  1607. '$mod.Run$s0(1, true);',
  1608. '$mod.Run$1s0(2, 3);',
  1609. '$mod.Run$2s0("foo", "bar");',
  1610. '']));
  1611. end;
  1612. procedure TTestGenerics.TestGenProc_TypeInfo;
  1613. begin
  1614. Converter.Options:=Converter.Options-[coNoTypeInfo];
  1615. StartProgram(true,[supTypeInfo]);
  1616. Add([
  1617. '{$modeswitch implicitfunctionspecialization}',
  1618. 'generic procedure Run<S>(a: S);',
  1619. 'var',
  1620. ' p: TTypeInfo;',
  1621. 'begin',
  1622. ' p:=TypeInfo(S);',
  1623. ' p:=TypeInfo(a);',
  1624. 'end;',
  1625. 'begin',
  1626. ' Run(word(3));',
  1627. ' Run(''foo'');',
  1628. '']);
  1629. ConvertProgram;
  1630. CheckSource('TestGenProc_TypeInfo',
  1631. LinesToStr([ // statements
  1632. 'this.Run$s0 = function (a) {',
  1633. ' var p = null;',
  1634. ' p = rtl.word;',
  1635. ' p = rtl.word;',
  1636. '};',
  1637. 'this.Run$s1 = function (a) {',
  1638. ' var p = null;',
  1639. ' p = rtl.string;',
  1640. ' p = rtl.string;',
  1641. '};',
  1642. '']),
  1643. LinesToStr([ // $mod.$main
  1644. '$mod.Run$s0(3);',
  1645. '$mod.Run$s1("foo");',
  1646. '']));
  1647. end;
  1648. procedure TTestGenerics.TestGenProc_Infer_Widen;
  1649. begin
  1650. StartProgram(false);
  1651. Add([
  1652. '{$mode delphi}',
  1653. 'procedure Run<S>(a: S; b: S);',
  1654. 'begin',
  1655. 'end;',
  1656. 'begin',
  1657. ' Run(word(1),longint(2));',
  1658. ' Run(byte(2),smallint(2));',
  1659. ' Run(longword(3),longint(2));',
  1660. ' Run(nativeint(4),longint(2));',
  1661. ' Run(nativeint(5),nativeuint(2));',
  1662. ' Run(''a'',''foo'');',
  1663. ' Run(''bar'',''c'');',
  1664. '']);
  1665. ConvertProgram;
  1666. CheckSource('TestGenProc_Infer_Widen',
  1667. LinesToStr([ // statements
  1668. 'this.Run$s0 = function (a, b) {',
  1669. '};',
  1670. 'this.Run$s1 = function (a, b) {',
  1671. '};',
  1672. 'this.Run$s2 = function (a, b) {',
  1673. '};',
  1674. '']),
  1675. LinesToStr([ // $mod.$main
  1676. '$mod.Run$s0(1, 2);',
  1677. '$mod.Run$s0(2, 2);',
  1678. '$mod.Run$s1(3, 2);',
  1679. '$mod.Run$s1(4, 2);',
  1680. '$mod.Run$s1(5, 2);',
  1681. '$mod.Run$s2("a", "foo");',
  1682. '$mod.Run$s2("bar", "c");',
  1683. '']));
  1684. end;
  1685. procedure TTestGenerics.TestGenProc_Infer_PassAsArg;
  1686. begin
  1687. StartProgram(false);
  1688. Add([
  1689. '{$mode delphi}',
  1690. 'function Run<T>(a: T): T;',
  1691. 'var b: T;',
  1692. 'begin',
  1693. ' Run(Run<word>(3));',
  1694. ' Run(Run(word(4)));',
  1695. 'end;',
  1696. 'begin',
  1697. ' Run(Run<word>(5));',
  1698. ' Run(Run(word(6)));',
  1699. '']);
  1700. ConvertProgram;
  1701. CheckSource('TestGenProc_Infer_PassAsArg',
  1702. LinesToStr([ // statements
  1703. 'this.Run$s0 = function (a) {',
  1704. ' var Result = 0;',
  1705. ' var b = 0;',
  1706. ' $mod.Run$s0($mod.Run$s0(3));',
  1707. ' $mod.Run$s0($mod.Run$s0(4));',
  1708. ' return Result;',
  1709. '};',
  1710. '']),
  1711. LinesToStr([ // $mod.$main
  1712. '$mod.Run$s0($mod.Run$s0(5));',
  1713. '$mod.Run$s0($mod.Run$s0(6));',
  1714. '']));
  1715. end;
  1716. procedure TTestGenerics.TestGenMethod_ObjFPC;
  1717. begin
  1718. StartProgram(false);
  1719. Add([
  1720. '{$mode objfpc}',
  1721. '{$ModeSwitch implicitfunctionspecialization}',
  1722. 'type',
  1723. ' TObject = class',
  1724. ' generic procedure {#A}Run<S>(a: S; b: boolean); overload;',
  1725. ' generic procedure {#B}Run<T>(a: T; w: word); overload;',
  1726. ' generic procedure {#C}Run<U>(a: U; b: U); overload;',
  1727. ' end; ',
  1728. 'generic procedure {#A2}TObject.Run<S>(a: S; b: boolean); overload;',
  1729. 'begin',
  1730. ' {@A}Run(1,true);', // non generic take precedence
  1731. ' {@B}Run(2,word(3));', // non generic take precedence
  1732. ' {@C}Run(''foo'',''bar'');',
  1733. 'end;',
  1734. 'generic procedure {#B2}TObject.Run<T>(a: T; w: word); overload;',
  1735. 'begin',
  1736. 'end;',
  1737. 'generic procedure {#C2}TObject.Run<U>(a: U; b: U); overload;',
  1738. 'begin',
  1739. 'end;',
  1740. 'var o: TObject;',
  1741. 'begin',
  1742. ' o.{@A}Run(1,true);', // non generic take precedence
  1743. ' o.{@B}Run(2,word(3));', // non generic take precedence
  1744. ' o.{@C}Run(''foo'',''bar'');',
  1745. '']);
  1746. ConvertProgram;
  1747. CheckSource('TestGenMethod_ObjFPC',
  1748. LinesToStr([ // statements
  1749. 'rtl.createClass($mod, "TObject", null, function () {',
  1750. ' this.$init = function () {',
  1751. ' };',
  1752. ' this.$final = function () {',
  1753. ' };',
  1754. ' this.Run$s0 = function (a, b) {',
  1755. ' this.Run$s0(1, true);',
  1756. ' this.Run$1s0(2, 3);',
  1757. ' this.Run$2s0("foo", "bar");',
  1758. ' };',
  1759. ' this.Run$1s0 = function (a, w) {',
  1760. ' };',
  1761. ' this.Run$2s0 = function (a, b) {',
  1762. ' };',
  1763. '});',
  1764. 'this.o = null;',
  1765. '']),
  1766. LinesToStr([ // $mod.$main
  1767. '$mod.o.Run$s0(1, true);',
  1768. '$mod.o.Run$1s0(2, 3);',
  1769. '$mod.o.Run$2s0("foo", "bar");',
  1770. '']));
  1771. end;
  1772. Initialization
  1773. RegisterTests([TTestGenerics]);
  1774. end.