tcgenerics.pas 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942
  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_ClassVarRecord_Program;
  15. Procedure TestGen_Record_ClassVarRecord_UnitImpl;
  16. Procedure TestGen_Record_RTTI_UnitImpl;
  17. procedure TestGen_Record_Delay_UsedByImplUses;
  18. // ToDo: type alias type as parameter, TBird = type word;
  19. // generic class
  20. Procedure TestGen_ClassEmpty;
  21. Procedure TestGen_Class_EmptyMethod;
  22. Procedure TestGen_Class_TList;
  23. Procedure TestGen_Class_TCustomList;
  24. Procedure TestGen_ClassAncestor;
  25. Procedure TestGen_Class_TypeInfo;
  26. Procedure TestGen_Class_TypeOverload;
  27. Procedure TestGen_Class_ClassProperty;
  28. Procedure TestGen_Class_ClassProc;
  29. Procedure TestGen_Class_ReferGenClass_DelphiFail;
  30. Procedure TestGen_Class_ClassConstructor;
  31. Procedure TestGen_Class_TypeCastSpecializesWarn;
  32. Procedure TestGen_Class_TypeCastSpecializesJSValueNoWarn;
  33. procedure TestGen_Class_OverloadsInUnit;
  34. procedure TestGen_ClassForward_CircleRTTI;
  35. procedure TestGen_Class_Nested_RTTI;
  36. Procedure TestGen_Class_ClassVarRecord_UnitImpl;
  37. // generic external class
  38. procedure TestGen_ExtClass_VarArgsOfType;
  39. procedure TestGen_ExtClass_Array;
  40. procedure TestGen_ExtClass_GenJSValueAssign;
  41. procedure TestGen_ExtClass_AliasMemberType;
  42. Procedure TestGen_ExtClass_RTTI;
  43. procedure TestGen_ExtClass_UnitImplRec;
  44. // class interfaces
  45. procedure TestGen_ClassInterface_Corba;
  46. procedure TestGen_ClassInterface_InterfacedObject;
  47. procedure TestGen_ClassInterface_COM_RTTI;
  48. procedure TestGen_ClassInterface_Helper;
  49. procedure TestGen_ClassInterface_DelayedInitSpec;
  50. // statements
  51. Procedure TestGen_InlineSpec_Constructor;
  52. Procedure TestGen_CallUnitImplProc;
  53. Procedure TestGen_IntAssignTemplVar;
  54. Procedure TestGen_TypeCastDotField;
  55. Procedure TestGen_Except;
  56. // generic helper
  57. procedure TestGen_HelperForArray;
  58. // generic functions
  59. procedure TestGenProc_Function_ObjFPC;
  60. procedure TestGenProc_Function_Delphi;
  61. procedure TestGenProc_Overload;
  62. procedure TestGenProc_Forward;
  63. procedure TestGenProc_Infer_OverloadForward;
  64. procedure TestGenProc_TypeInfo;
  65. procedure TestGenProc_Infer_Widen;
  66. procedure TestGenProc_Infer_PassAsArg;
  67. procedure TestGenProc_AnonymousProc;
  68. // generic methods
  69. procedure TestGenMethod_ImplicitSpec_ObjFPC;
  70. procedure TestGenMethod_Delphi;
  71. procedure TestGenMethod_Overload_Delphi;
  72. // generic array
  73. procedure TestGen_Array_OtherUnit;
  74. procedure TestGen_ArrayOfUnitImplRec;
  75. procedure TestGen_Array_TypecastJSValueResultToArg;
  76. // generic procedure type
  77. procedure TestGen_ProcType_ProcLocal;
  78. procedure TestGen_ProcType_Local_RTTI_Fail;
  79. procedure TestGen_ProcType_ParamUnitImpl;
  80. // procedure TestGen_ProcType_TemplateCountOverload_ObjFPC; ObjFPC does not support that in FPC
  81. procedure TestGen_ProcType_TemplateCountOverload_Delphi;
  82. end;
  83. implementation
  84. { TTestGenerics }
  85. procedure TTestGenerics.TestGen_RecordEmpty;
  86. begin
  87. StartProgram(false);
  88. Add([
  89. 'type',
  90. ' generic TRecA<T> = record',
  91. ' end;',
  92. 'var a,b: specialize TRecA<word>;',
  93. 'begin',
  94. ' if a=b then ;']);
  95. ConvertProgram;
  96. CheckSource('TestGen_RecordEmpty',
  97. LinesToStr([ // statements
  98. 'rtl.recNewT(this, "TRecA$G1", function () {',
  99. ' this.$eq = function (b) {',
  100. ' return true;',
  101. ' };',
  102. ' this.$assign = function (s) {',
  103. ' return this;',
  104. ' };',
  105. '});',
  106. 'this.a = this.TRecA$G1.$new();',
  107. 'this.b = this.TRecA$G1.$new();',
  108. '']),
  109. LinesToStr([ // $mod.$main
  110. 'if ($mod.a.$eq($mod.b)) ;'
  111. ]));
  112. end;
  113. procedure TTestGenerics.TestGen_Record_ClassProc;
  114. begin
  115. StartProgram(false);
  116. Add([
  117. '{$modeswitch AdvancedRecords}',
  118. 'type',
  119. ' generic TPoint<T> = record',
  120. ' class var x: T;',
  121. ' class procedure Fly; static;',
  122. ' end;',
  123. 'class procedure Tpoint.Fly;',
  124. 'begin',
  125. ' x:=x+3;',
  126. ' tpoint.x:=tpoint.x+4;',
  127. ' Fly;',
  128. ' tpoint.Fly;',
  129. 'end;',
  130. 'var p: specialize TPoint<word>;',
  131. 'begin',
  132. ' p.x:=p.x+10;',
  133. ' p.Fly;',
  134. ' p.Fly();',
  135. '']);
  136. ConvertProgram;
  137. CheckSource('TestGen_Record_ClassProc',
  138. LinesToStr([ // statements
  139. 'rtl.recNewT(this, "TPoint$G1", function () {',
  140. ' this.x = 0;',
  141. ' this.$eq = function (b) {',
  142. ' return true;',
  143. ' };',
  144. ' this.$assign = function (s) {',
  145. ' return this;',
  146. ' };',
  147. ' this.Fly = function () {',
  148. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 3;',
  149. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 4;',
  150. ' $mod.TPoint$G1.Fly();',
  151. ' $mod.TPoint$G1.Fly();',
  152. ' };',
  153. '}, true);',
  154. 'this.p = this.TPoint$G1.$new();',
  155. '']),
  156. LinesToStr([ // $mod.$main
  157. '$mod.TPoint$G1.x = $mod.p.x + 10;',
  158. '$mod.TPoint$G1.Fly();',
  159. '$mod.TPoint$G1.Fly();',
  160. '']));
  161. end;
  162. procedure TTestGenerics.TestGen_Record_ClassVarRecord_Program;
  163. begin
  164. StartProgram(false);
  165. Add([
  166. '{$modeswitch AdvancedRecords}',
  167. 'type',
  168. ' generic TAnt<T> = record',
  169. ' class var x: T;',
  170. ' end;',
  171. ' TBird = record',
  172. ' b: word;',
  173. ' end;',
  174. 'var f: specialize TAnt<TBird>;',
  175. 'begin',
  176. ' f.x.b:=f.x.b+10;',
  177. '']);
  178. ConvertProgram;
  179. CheckSource('TestGen_Record_ClassVarRecord_Program',
  180. LinesToStr([ // statements
  181. 'rtl.recNewT(this, "TBird", function () {',
  182. ' this.b = 0;',
  183. ' this.$eq = function (b) {',
  184. ' return this.b === b.b;',
  185. ' };',
  186. ' this.$assign = function (s) {',
  187. ' this.b = s.b;',
  188. ' return this;',
  189. ' };',
  190. '});',
  191. 'rtl.recNewT(this, "TAnt$G1", function () {',
  192. ' this.x = $mod.TBird.$new();',
  193. ' this.$eq = function (b) {',
  194. ' return true;',
  195. ' };',
  196. ' this.$assign = function (s) {',
  197. ' return this;',
  198. ' };',
  199. '}, true);',
  200. 'this.f = this.TAnt$G1.$new();',
  201. '']),
  202. LinesToStr([ // $mod.$main
  203. '$mod.f.x.b = $mod.f.x.b + 10;',
  204. '']));
  205. end;
  206. procedure TTestGenerics.TestGen_Record_ClassVarRecord_UnitImpl;
  207. begin
  208. StartProgram(true,[supTObject]);
  209. AddModuleWithIntfImplSrc('UnitA.pas',
  210. LinesToStr([
  211. '{$modeswitch AdvancedRecords}',
  212. 'type',
  213. ' generic TAnt<T> = record',
  214. ' class var x: T;',
  215. ' class var a: array[1..2] of T;',
  216. ' end;',
  217. '']),
  218. LinesToStr([
  219. 'type',
  220. ' TBird = record',
  221. ' b: word;',
  222. ' end;',
  223. 'var f: specialize TAnt<TBird>;',
  224. 'begin',
  225. ' f.x.b:=f.x.b+10;',
  226. '']));
  227. Add([
  228. 'uses UnitA;',
  229. 'begin',
  230. 'end.']);
  231. ConvertProgram;
  232. CheckUnit('UnitA.pas',
  233. LinesToStr([ // statements
  234. 'rtl.module("UnitA", ["system"], function () {',
  235. ' var $mod = this;',
  236. ' var $impl = $mod.$impl;',
  237. ' rtl.recNewT(this, "TAnt$G1", function () {',
  238. ' this.$initSpec = function () {',
  239. ' this.x = $impl.TBird.$new();',
  240. ' this.a = rtl.arraySetLength(null, $impl.TBird, 2);',
  241. ' };',
  242. ' this.a$a$clone = function (a) {',
  243. ' var b = [];',
  244. ' b.length = 2;',
  245. ' for (var c = 0; c < 2; c++) b[c] = $impl.TBird.$clone(a[c]);',
  246. ' return b;',
  247. ' };',
  248. ' this.$eq = function (b) {',
  249. ' return true;',
  250. ' };',
  251. ' this.$assign = function (s) {',
  252. ' return this;',
  253. ' };',
  254. ' }, true);',
  255. ' $mod.$implcode = function () {',
  256. ' rtl.recNewT($impl, "TBird", function () {',
  257. ' this.b = 0;',
  258. ' this.$eq = function (b) {',
  259. ' return this.b === b.b;',
  260. ' };',
  261. ' this.$assign = function (s) {',
  262. ' this.b = s.b;',
  263. ' return this;',
  264. ' };',
  265. ' });',
  266. ' $impl.f = $mod.TAnt$G1.$new();',
  267. ' };',
  268. ' $mod.$init = function () {',
  269. ' $impl.f.x.b = $impl.f.x.b + 10;',
  270. ' };',
  271. '}, []);']));
  272. CheckSource('TestGen_Record_ClassVarRecord_UnitImpl',
  273. LinesToStr([ // statements
  274. '$mod.$implcode = function () {',
  275. ' pas.UnitA.TAnt$G1.$initSpec();',
  276. '};',
  277. '']),
  278. LinesToStr([ // $mod.$main
  279. '']));
  280. end;
  281. procedure TTestGenerics.TestGen_Record_RTTI_UnitImpl;
  282. begin
  283. WithTypeInfo:=true;
  284. StartUnit(true);
  285. Add([
  286. 'interface',
  287. '{$modeswitch AdvancedRecords}',
  288. 'type',
  289. ' generic TAnt<T> = record',
  290. ' class var x: T;',
  291. //' class var a,b: array of T;',
  292. ' end;',
  293. 'implementation',
  294. 'type',
  295. ' TBird = record',
  296. ' b: word;',
  297. ' end;',
  298. 'var f: specialize TAnt<TBird>;',
  299. ' p: pointer;',
  300. 'begin',
  301. ' p:=typeinfo(f);',
  302. '']);
  303. ConvertUnit;
  304. CheckSource('TestGen_Record_RTTI_UnitImpl',
  305. LinesToStr([ // statements
  306. 'var $impl = $mod.$impl;',
  307. 'rtl.recNewT(this, "TAnt$G1", function () {',
  308. ' var $r = $mod.$rtti.$Record("TAnt<Test1.TBird>", {});',
  309. ' this.$initSpec = function () {',
  310. ' this.x = $impl.TBird.$new();',
  311. ' $r.addField("x", $mod.$rtti["TBird"]);',
  312. ' };',
  313. ' this.$eq = function (b) {',
  314. ' return true;',
  315. ' };',
  316. ' this.$assign = function (s) {',
  317. ' return this;',
  318. ' };',
  319. '}, true);',
  320. '']),
  321. LinesToStr([ // $mod.$init
  322. '$impl.p = $mod.$rtti["TAnt<Test1.TBird>"];',
  323. '']),
  324. LinesToStr([ // statements
  325. 'rtl.recNewT($impl, "TBird", function () {',
  326. ' this.b = 0;',
  327. ' this.$eq = function (b) {',
  328. ' return this.b === b.b;',
  329. ' };',
  330. ' this.$assign = function (s) {',
  331. ' this.b = s.b;',
  332. ' return this;',
  333. ' };',
  334. ' var $r = $mod.$rtti.$Record("TBird", {});',
  335. ' $r.addField("b", rtl.word);',
  336. '});',
  337. '$impl.f = $mod.TAnt$G1.$new();',
  338. '$impl.p = null;',
  339. '']));
  340. end;
  341. procedure TTestGenerics.TestGen_Record_Delay_UsedByImplUses;
  342. begin
  343. WithTypeInfo:=true;
  344. StartProgram(true,[supTObject]);
  345. AddModuleWithIntfImplSrc('UnitA.pas',
  346. LinesToStr([
  347. '{$modeswitch AdvancedRecords}',
  348. 'type',
  349. ' generic TBird<T> = record',
  350. ' class var a: T;',
  351. ' end;',
  352. '']),
  353. LinesToStr([
  354. '']));
  355. AddModuleWithIntfImplSrc('UnitB.pas',
  356. LinesToStr([
  357. 'procedure Fly;',
  358. '']),
  359. LinesToStr([
  360. 'uses UnitA;',
  361. 'type',
  362. ' TFox = record',
  363. ' B: word;',
  364. ' end;',
  365. 'procedure Fly;',
  366. 'var Bird: specialize TBird<TFox>;',
  367. 'begin',
  368. ' if typeinfo(Bird)<>nil then ;',
  369. ' Bird.a:=Bird.a;',
  370. 'end;',
  371. '']));
  372. Add([
  373. 'uses UnitB;',
  374. 'begin',
  375. ' Fly;']);
  376. ConvertProgram;
  377. CheckSource('TestGen_Record_Delay_UsedByImplUses',
  378. LinesToStr([ // statements
  379. '$mod.$implcode = function () {',
  380. ' pas.UnitA.TBird$G1.$initSpec();',
  381. '};',
  382. '']),
  383. LinesToStr([ // $mod.$main
  384. 'pas.UnitB.Fly();'
  385. ]));
  386. end;
  387. procedure TTestGenerics.TestGen_ClassEmpty;
  388. begin
  389. StartProgram(false);
  390. Add([
  391. 'type',
  392. ' TObject = class end;',
  393. ' generic TBird<T> = class',
  394. ' end;',
  395. 'var a,b: specialize TBird<word>;',
  396. 'begin',
  397. ' if a=b then ;']);
  398. ConvertProgram;
  399. CheckSource('TestGen_ClassEmpty',
  400. LinesToStr([ // statements
  401. 'rtl.createClass(this, "TObject", null, function () {',
  402. ' this.$init = function () {',
  403. ' };',
  404. ' this.$final = function () {',
  405. ' };',
  406. '});',
  407. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  408. '}, "TBird<System.Word>");',
  409. 'this.a = null;',
  410. 'this.b = null;',
  411. '']),
  412. LinesToStr([ // $mod.$main
  413. 'if ($mod.a === $mod.b) ;'
  414. ]));
  415. end;
  416. procedure TTestGenerics.TestGen_Class_EmptyMethod;
  417. begin
  418. StartProgram(false);
  419. Add([
  420. 'type',
  421. ' TObject = class end;',
  422. ' generic TBird<T> = class',
  423. ' function Fly(w: T): T;',
  424. ' end;',
  425. 'function TBird.Fly(w: T): T;',
  426. 'begin',
  427. 'end;',
  428. 'var a: specialize TBird<word>;',
  429. 'begin',
  430. ' if a.Fly(3)=4 then ;']);
  431. ConvertProgram;
  432. CheckSource('TestGen_Class_EmptyMethod',
  433. LinesToStr([ // statements
  434. 'rtl.createClass(this, "TObject", null, function () {',
  435. ' this.$init = function () {',
  436. ' };',
  437. ' this.$final = function () {',
  438. ' };',
  439. '});',
  440. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  441. ' this.Fly = function (w) {',
  442. ' var Result = 0;',
  443. ' return Result;',
  444. ' };',
  445. '}, "TBird<System.Word>");',
  446. 'this.a = null;',
  447. '']),
  448. LinesToStr([ // $mod.$main
  449. ' if ($mod.a.Fly(3) === 4) ;'
  450. ]));
  451. end;
  452. procedure TTestGenerics.TestGen_Class_TList;
  453. begin
  454. StartProgram(false);
  455. Add([
  456. '{$mode objfpc}',
  457. 'type',
  458. ' TObject = class end;',
  459. ' generic TList<T> = class',
  460. ' strict private',
  461. ' FItems: array of T;',
  462. ' function GetItems(Index: longint): T;',
  463. ' procedure SetItems(Index: longint; Value: T);',
  464. ' public',
  465. ' procedure Alter(w: T);',
  466. ' property Items[Index: longint]: T read GetItems write SetItems; default;',
  467. ' end;',
  468. ' TWordList = specialize TList<word>;',
  469. 'function TList.GetItems(Index: longint): T;',
  470. 'begin',
  471. ' Result:=FItems[Index];',
  472. 'end;',
  473. 'procedure TList.SetItems(Index: longint; Value: T);',
  474. 'begin',
  475. ' FItems[Index]:=Value;',
  476. 'end;',
  477. 'procedure TList.Alter(w: T);',
  478. 'begin',
  479. ' SetLength(FItems,length(FItems)+1);',
  480. ' Insert(w,FItems,2);',
  481. ' Delete(FItems,2,3);',
  482. 'end;',
  483. 'var l: TWordList;',
  484. ' w: word;',
  485. 'begin',
  486. ' l[1]:=w;',
  487. ' w:=l[2];',
  488. '']);
  489. ConvertProgram;
  490. CheckSource('TestGen_Class_TList',
  491. LinesToStr([ // statements
  492. 'rtl.createClass(this, "TObject", null, function () {',
  493. ' this.$init = function () {',
  494. ' };',
  495. ' this.$final = function () {',
  496. ' };',
  497. '});',
  498. 'rtl.createClass(this, "TList$G1", this.TObject, function () {',
  499. ' this.$init = function () {',
  500. ' $mod.TObject.$init.call(this);',
  501. ' this.FItems = [];',
  502. ' };',
  503. ' this.$final = function () {',
  504. ' this.FItems = undefined;',
  505. ' $mod.TObject.$final.call(this);',
  506. ' };',
  507. ' this.GetItems = function (Index) {',
  508. ' var Result = 0;',
  509. ' Result = this.FItems[Index];',
  510. ' return Result;',
  511. ' };',
  512. ' this.SetItems = function (Index, Value) {',
  513. ' this.FItems[Index] = Value;',
  514. ' };',
  515. ' this.Alter = function (w) {',
  516. ' this.FItems = rtl.arraySetLength(this.FItems, 0, rtl.length(this.FItems) + 1);',
  517. ' this.FItems = rtl.arrayInsert(w, this.FItems, 2);',
  518. ' this.FItems.splice(2, 3);',
  519. ' };',
  520. '}, "TList<System.Word>");',
  521. 'this.l = null;',
  522. 'this.w = 0;',
  523. '']),
  524. LinesToStr([ // $mod.$main
  525. '$mod.l.SetItems(1, $mod.w);',
  526. '$mod.w = $mod.l.GetItems(2);',
  527. '']));
  528. end;
  529. procedure TTestGenerics.TestGen_Class_TCustomList;
  530. begin
  531. StartProgram(false);
  532. Add([
  533. '{$mode delphi}',
  534. 'type',
  535. ' TObject = class end;',
  536. ' TCustomList<T> = class',
  537. ' public',
  538. ' function PrepareAddingItem: word; virtual;',
  539. ' end;',
  540. ' TList<T> = class(TCustomList<T>)',
  541. ' public',
  542. ' function Add: word;',
  543. ' end;',
  544. ' TWordList = TList<word>;',
  545. 'function TCustomList<T>.PrepareAddingItem: word;',
  546. 'begin',
  547. 'end;',
  548. 'function TList<T>.Add: word;',
  549. 'begin',
  550. ' Result:=PrepareAddingItem;',
  551. ' Result:=Self.PrepareAddingItem;',
  552. ' with Self do Result:=PrepareAddingItem;',
  553. 'end;',
  554. 'var l: TWordList;',
  555. 'begin',
  556. '']);
  557. ConvertProgram;
  558. CheckSource('TestGen_Class_TCustomList',
  559. LinesToStr([ // statements
  560. 'rtl.createClass(this, "TObject", null, function () {',
  561. ' this.$init = function () {',
  562. ' };',
  563. ' this.$final = function () {',
  564. ' };',
  565. '});',
  566. 'rtl.createClass(this, "TCustomList$G2", this.TObject, function () {',
  567. ' this.PrepareAddingItem = function () {',
  568. ' var Result = 0;',
  569. ' return Result;',
  570. ' };',
  571. '}, "TCustomList<System.Word>");',
  572. 'rtl.createClass(this, "TList$G1", this.TCustomList$G2, function () {',
  573. ' this.Add = function () {',
  574. ' var Result = 0;',
  575. ' Result = this.PrepareAddingItem();',
  576. ' Result = this.PrepareAddingItem();',
  577. ' Result = this.PrepareAddingItem();',
  578. ' return Result;',
  579. ' };',
  580. '}, "TList<System.Word>");',
  581. 'this.l = null;',
  582. '']),
  583. LinesToStr([ // $mod.$main
  584. '']));
  585. end;
  586. procedure TTestGenerics.TestGen_ClassAncestor;
  587. begin
  588. StartProgram(false);
  589. Add([
  590. 'type',
  591. ' TObject = class end;',
  592. ' generic TBird<T> = class',
  593. ' end;',
  594. ' generic TEagle<T> = class(specialize TBird<T>)',
  595. ' end;',
  596. 'var a: specialize TEagle<word>;',
  597. 'begin',
  598. '']);
  599. ConvertProgram;
  600. CheckSource('TestGen_ClassAncestor',
  601. LinesToStr([ // statements
  602. 'rtl.createClass(this, "TObject", null, function () {',
  603. ' this.$init = function () {',
  604. ' };',
  605. ' this.$final = function () {',
  606. ' };',
  607. '});',
  608. 'rtl.createClass(this, "TBird$G2", this.TObject, function () {',
  609. '}, "TBird<System.Word>");',
  610. 'rtl.createClass(this, "TEagle$G1", this.TBird$G2, function () {',
  611. '}, "TEagle<System.Word>");',
  612. 'this.a = null;',
  613. '']),
  614. LinesToStr([ // $mod.$main
  615. '']));
  616. end;
  617. procedure TTestGenerics.TestGen_Class_TypeInfo;
  618. begin
  619. WithTypeInfo:=true;
  620. StartProgram(false);
  621. Add([
  622. 'type',
  623. ' TObject = class end;',
  624. ' generic TBird<T> = class',
  625. ' published',
  626. ' m: T;',
  627. ' end;',
  628. ' TEagle = specialize TBird<word>;',
  629. 'var',
  630. ' b: specialize TBird<word>;',
  631. ' p: pointer;',
  632. 'begin',
  633. ' p:=typeinfo(TEagle);',
  634. ' p:=typeinfo(b);',
  635. '']);
  636. ConvertProgram;
  637. CheckSource('TestGen_Class_TypeInfo',
  638. LinesToStr([ // statements
  639. '$mod.$rtti.$Class("TBird<System.Word>");',
  640. 'rtl.createClass(this, "TObject", null, function () {',
  641. ' this.$init = function () {',
  642. ' };',
  643. ' this.$final = function () {',
  644. ' };',
  645. '});',
  646. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  647. ' this.$init = function () {',
  648. ' $mod.TObject.$init.call(this);',
  649. ' this.m = 0;',
  650. ' };',
  651. ' var $r = this.$rtti;',
  652. ' $r.addField("m", rtl.word);',
  653. '}, "TBird<System.Word>");',
  654. 'this.b = null;',
  655. 'this.p = null;',
  656. '']),
  657. LinesToStr([ // $mod.$main
  658. '$mod.p = $mod.$rtti["TBird<System.Word>"];',
  659. '$mod.p = $mod.b.$rtti;',
  660. '']));
  661. end;
  662. procedure TTestGenerics.TestGen_Class_TypeOverload;
  663. begin
  664. StartProgram(false);
  665. Add([
  666. '{$mode delphi}',
  667. 'type',
  668. ' TObject = class end;',
  669. ' TBird = word;',
  670. ' TBird<T> = class',
  671. ' m: T;',
  672. ' end;',
  673. ' TEagle = TBird<word>;',
  674. 'var',
  675. ' b: TBird<word>;',
  676. ' e: TEagle;',
  677. 'begin',
  678. '']);
  679. ConvertProgram;
  680. CheckSource('TestGen_Class_TypeOverload',
  681. LinesToStr([ // statements
  682. 'rtl.createClass(this, "TObject", null, function () {',
  683. ' this.$init = function () {',
  684. ' };',
  685. ' this.$final = function () {',
  686. ' };',
  687. '});',
  688. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  689. ' this.$init = function () {',
  690. ' $mod.TObject.$init.call(this);',
  691. ' this.m = 0;',
  692. ' };',
  693. '}, "TBird<System.Word>");',
  694. 'this.b = null;',
  695. 'this.e = null;',
  696. '']),
  697. LinesToStr([ // $mod.$main
  698. '']));
  699. end;
  700. procedure TTestGenerics.TestGen_Class_ClassProperty;
  701. begin
  702. StartProgram(false);
  703. Add([
  704. '{$mode delphi}',
  705. 'type',
  706. ' TObject = class end;',
  707. ' TBird<T> = class',
  708. ' private',
  709. ' class var fSize: T;',
  710. ' public',
  711. ' class property Size: T read fSize write fSize;',
  712. ' end;',
  713. ' TEagle = TBird<word>;',
  714. 'begin',
  715. ' TBird<word>.Size:=3+TBird<word>.Size;',
  716. '']);
  717. ConvertProgram;
  718. CheckSource('TestGen_Class_ClassProperty',
  719. LinesToStr([ // statements
  720. 'rtl.createClass(this, "TObject", null, function () {',
  721. ' this.$init = function () {',
  722. ' };',
  723. ' this.$final = function () {',
  724. ' };',
  725. '});',
  726. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  727. ' this.fSize = 0;',
  728. '}, "TBird<System.Word>");',
  729. '']),
  730. LinesToStr([ // $mod.$main
  731. '$mod.TBird$G1.fSize = 3 + $mod.TBird$G1.fSize;',
  732. '']));
  733. end;
  734. procedure TTestGenerics.TestGen_Class_ClassProc;
  735. begin
  736. StartProgram(false);
  737. Add([
  738. 'type',
  739. ' TObject = class end;',
  740. ' generic TPoint<T> = class',
  741. ' class var x: T;',
  742. ' class procedure Fly; static;',
  743. ' class procedure Run;',
  744. ' end;',
  745. 'class procedure Tpoint.Fly;',
  746. 'begin',
  747. ' x:=x+3;',
  748. ' tpoint.x:=tpoint.x+4;',
  749. ' Fly;',
  750. ' tpoint.Fly;',
  751. ' Run;',
  752. ' tpoint.Run;',
  753. 'end;',
  754. 'class procedure TPoint.Run;',
  755. 'begin',
  756. ' x:=x+5;',
  757. ' tpoint.x:=tpoint.x+6;',
  758. ' Fly;',
  759. ' tpoint.Fly;',
  760. ' Run;',
  761. ' tpoint.Run;',
  762. 'end;',
  763. 'var p: specialize TPoint<word>;',
  764. 'begin',
  765. '']);
  766. ConvertProgram;
  767. CheckSource('TestGen_Class_ClassProc',
  768. LinesToStr([ // statements
  769. 'rtl.createClass(this, "TObject", null, function () {',
  770. ' this.$init = function () {',
  771. ' };',
  772. ' this.$final = function () {',
  773. ' };',
  774. '});',
  775. 'rtl.createClass(this, "TPoint$G1", this.TObject, function () {',
  776. ' this.x = 0;',
  777. ' this.Fly = function () {',
  778. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 3;',
  779. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 4;',
  780. ' $mod.TPoint$G1.Fly();',
  781. ' $mod.TPoint$G1.Fly();',
  782. ' $mod.TPoint$G1.Run();',
  783. ' $mod.TPoint$G1.Run();',
  784. ' };',
  785. ' this.Run = function () {',
  786. ' $mod.TPoint$G1.x = this.x + 5;',
  787. ' $mod.TPoint$G1.x = $mod.TPoint$G1.x + 6;',
  788. ' this.Fly();',
  789. ' this.Fly();',
  790. ' this.Run();',
  791. ' $mod.TPoint$G1.Run();',
  792. ' };',
  793. '}, "TPoint<System.Word>");',
  794. 'this.p = null;',
  795. '']),
  796. LinesToStr([ // $mod.$main
  797. '']));
  798. end;
  799. procedure TTestGenerics.TestGen_Class_ReferGenClass_DelphiFail;
  800. begin
  801. StartProgram(false);
  802. Add([
  803. '{$mode delphi}',
  804. 'type',
  805. ' TObject = class end;',
  806. ' TPoint<T> = class',
  807. ' var x: TPoint;', // alowed in objfpc, forbidden in delphi
  808. ' end;',
  809. 'var p: specialize TPoint<word>;',
  810. 'begin',
  811. '']);
  812. SetExpectedPasResolverError('Generics without specialization cannot be used as a type for a variable',
  813. nGenericsWithoutSpecializationAsType);
  814. ConvertProgram;
  815. end;
  816. procedure TTestGenerics.TestGen_Class_ClassConstructor;
  817. begin
  818. StartProgram(false);
  819. Add([
  820. 'type',
  821. ' TObject = class end;',
  822. ' generic TPoint<T> = class',
  823. ' class var x: T;',
  824. ' class procedure Fly; static;',
  825. ' class constructor Init;',
  826. ' end;',
  827. 'var count: word;',
  828. 'class procedure Tpoint.Fly;',
  829. 'begin',
  830. 'end;',
  831. 'class constructor tpoint.init;',
  832. 'begin',
  833. ' count:=count+1;',
  834. ' x:=3;',
  835. ' tpoint.x:=4;',
  836. ' fly;',
  837. ' tpoint.fly;',
  838. 'end;',
  839. 'var',
  840. ' r: specialize TPoint<word>;',
  841. ' s: specialize TPoint<smallint>;',
  842. 'begin',
  843. ' r.x:=10;',
  844. '']);
  845. ConvertProgram;
  846. CheckSource('TestGen_Class_ClassConstructor',
  847. LinesToStr([ // statements
  848. 'rtl.createClass(this, "TObject", null, function () {',
  849. ' this.$init = function () {',
  850. ' };',
  851. ' this.$final = function () {',
  852. ' };',
  853. '});',
  854. 'this.count = 0;',
  855. 'rtl.createClass(this, "TPoint$G1", this.TObject, function () {',
  856. ' this.x = 0;',
  857. ' this.Fly = function () {',
  858. ' };',
  859. '}, "TPoint<System.Word>");',
  860. 'this.r = null;',
  861. 'rtl.createClass(this, "TPoint$G2", this.TObject, function () {',
  862. ' this.x = 0;',
  863. ' this.Fly = function () {',
  864. ' };',
  865. '}, "TPoint<System.SmallInt>");',
  866. 'this.s = null;',
  867. '']),
  868. LinesToStr([ // $mod.$main
  869. '(function () {',
  870. ' $mod.count = $mod.count + 1;',
  871. ' $mod.TPoint$G1.x = 3;',
  872. ' $mod.TPoint$G1.x = 4;',
  873. ' $mod.TPoint$G1.Fly();',
  874. ' $mod.TPoint$G1.Fly();',
  875. '})();',
  876. '(function () {',
  877. ' $mod.count = $mod.count + 1;',
  878. ' $mod.TPoint$G2.x = 3;',
  879. ' $mod.TPoint$G2.x = 4;',
  880. ' $mod.TPoint$G2.Fly();',
  881. ' $mod.TPoint$G2.Fly();',
  882. '})();',
  883. '$mod.TPoint$G1.x = 10;',
  884. '']));
  885. end;
  886. procedure TTestGenerics.TestGen_Class_TypeCastSpecializesWarn;
  887. begin
  888. StartProgram(false);
  889. Add([
  890. '{$mode delphi}',
  891. 'type',
  892. ' TObject = class end;',
  893. ' TBird<T> = class F: T; end;',
  894. ' TBirdWord = TBird<Word>;',
  895. ' TBirdChar = TBird<Char>;',
  896. 'var',
  897. ' w: TBirdWord;',
  898. ' c: TBirdChar;',
  899. 'begin',
  900. ' w:=TBirdWord(c);',
  901. '']);
  902. ConvertProgram;
  903. CheckSource('TestGen_Class_TypeCastSpecializesWarn',
  904. LinesToStr([ // statements
  905. 'rtl.createClass(this, "TObject", null, function () {',
  906. ' this.$init = function () {',
  907. ' };',
  908. ' this.$final = function () {',
  909. ' };',
  910. '});',
  911. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  912. ' this.$init = function () {',
  913. ' $mod.TObject.$init.call(this);',
  914. ' this.F = 0;',
  915. ' };',
  916. '}, "TBird<System.Word>");',
  917. 'rtl.createClass(this, "TBird$G2", this.TObject, function () {',
  918. ' this.$init = function () {',
  919. ' $mod.TObject.$init.call(this);',
  920. ' this.F = "";',
  921. ' };',
  922. '}, "TBird<System.Char>");',
  923. 'this.w = null;',
  924. 'this.c = null;',
  925. '']),
  926. LinesToStr([ // $mod.$main
  927. '$mod.w = $mod.c;',
  928. '']));
  929. CheckHint(mtWarning,nClassTypesAreNotRelatedXY,'Class types "TBird<System.Char>" and "TBird<System.Word>" are not related');
  930. CheckResolverUnexpectedHints();
  931. end;
  932. procedure TTestGenerics.TestGen_Class_TypeCastSpecializesJSValueNoWarn;
  933. begin
  934. StartProgram(false);
  935. Add([
  936. '{$mode delphi}',
  937. 'type',
  938. ' TObject = class end;',
  939. ' TBird<T> = class F: T; end;',
  940. ' TBirdWord = TBird<Word>;',
  941. ' TBirdAny = TBird<JSValue>;',
  942. 'var',
  943. ' w: TBirdWord;',
  944. ' a: TBirdAny;',
  945. 'begin',
  946. ' w:=TBirdWord(a);',
  947. ' a:=TBirdAny(w);',
  948. '']);
  949. ConvertProgram;
  950. CheckSource('TestGen_Class_TypeCastSpecializesJSValueNoWarn',
  951. LinesToStr([ // statements
  952. 'rtl.createClass(this, "TObject", null, function () {',
  953. ' this.$init = function () {',
  954. ' };',
  955. ' this.$final = function () {',
  956. ' };',
  957. '});',
  958. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  959. ' this.$init = function () {',
  960. ' $mod.TObject.$init.call(this);',
  961. ' this.F = 0;',
  962. ' };',
  963. '}, "TBird<System.Word>");',
  964. 'rtl.createClass(this, "TBird$G2", this.TObject, function () {',
  965. ' this.$init = function () {',
  966. ' $mod.TObject.$init.call(this);',
  967. ' this.F = undefined;',
  968. ' };',
  969. '}, "TBird<System.JSValue>");',
  970. 'this.w = null;',
  971. 'this.a = null;',
  972. '']),
  973. LinesToStr([ // $mod.$main
  974. '$mod.w = $mod.a;',
  975. '$mod.a = $mod.w;',
  976. '']));
  977. CheckResolverUnexpectedHints();
  978. end;
  979. procedure TTestGenerics.TestGen_Class_OverloadsInUnit;
  980. begin
  981. StartProgram(true,[supTObject]);
  982. AddModuleWithIntfImplSrc('UnitA.pas',
  983. LinesToStr([
  984. 'type',
  985. ' generic TBird<T> = class',
  986. ' const c = 13;',
  987. ' constructor Create(w: T);',
  988. ' constructor Create(b: boolean);',
  989. ' end;',
  990. '']),
  991. LinesToStr([
  992. 'constructor TBird.Create(w: T);',
  993. 'const c = 14;',
  994. 'begin',
  995. 'end;',
  996. 'constructor TBird.Create(b: boolean);',
  997. 'const c = 15;',
  998. 'begin',
  999. 'end;',
  1000. '']));
  1001. Add([
  1002. 'uses UnitA;',
  1003. 'type',
  1004. ' TWordBird = specialize TBird<word>;',
  1005. ' TDoubleBird = specialize TBird<double>;',
  1006. 'var',
  1007. ' wb: TWordBird;',
  1008. ' db: TDoubleBird;',
  1009. 'begin',
  1010. ' wb:=TWordBird.Create(3);',
  1011. ' wb:=TWordBird.Create(true);',
  1012. ' db:=TDoubleBird.Create(1.3);',
  1013. ' db:=TDoubleBird.Create(true);',
  1014. '']);
  1015. ConvertProgram;
  1016. CheckUnit('UnitA.pas',
  1017. LinesToStr([ // statements
  1018. 'rtl.module("UnitA", ["system"], function () {',
  1019. ' var $mod = this;',
  1020. ' rtl.createClass(this, "TBird$G1", pas.system.TObject, function () {',
  1021. ' this.c = 13;',
  1022. ' var c$1 = 14;',
  1023. ' this.Create$1 = function (w) {',
  1024. ' return this;',
  1025. ' };',
  1026. ' var c$2 = 15;',
  1027. ' this.Create$2 = function (b) {',
  1028. ' return this;',
  1029. ' };',
  1030. ' }, "TBird<System.Word>");',
  1031. ' rtl.createClass(this, "TBird$G2", pas.system.TObject, function () {',
  1032. ' this.c = 13;',
  1033. ' var c$1 = 14;',
  1034. ' this.Create$1 = function (w) {',
  1035. ' return this;',
  1036. ' };',
  1037. ' var c$2 = 15;',
  1038. ' this.Create$2 = function (b) {',
  1039. ' return this;',
  1040. ' };',
  1041. ' }, "TBird<System.Double>");',
  1042. '});',
  1043. '']));
  1044. CheckSource('TestGen_Class_OverloadsInUnit',
  1045. LinesToStr([ // statements
  1046. 'this.wb = null;',
  1047. 'this.db = null;',
  1048. '']),
  1049. LinesToStr([ // $mod.$main
  1050. '$mod.wb = pas.UnitA.TBird$G1.$create("Create$1", [3]);',
  1051. '$mod.wb = pas.UnitA.TBird$G1.$create("Create$2", [true]);',
  1052. '$mod.db = pas.UnitA.TBird$G2.$create("Create$1", [1.3]);',
  1053. '$mod.db = pas.UnitA.TBird$G2.$create("Create$2", [true]);',
  1054. '']));
  1055. end;
  1056. procedure TTestGenerics.TestGen_ClassForward_CircleRTTI;
  1057. begin
  1058. WithTypeInfo:=true;
  1059. StartProgram(false);
  1060. Add([
  1061. '{$mode objfpc}',
  1062. 'type',
  1063. ' TObject = class end;',
  1064. ' {$M+}',
  1065. ' TPersistent = class end;',
  1066. ' {$M-}',
  1067. ' generic TAnt<T> = class;',
  1068. ' generic TFish<U> = class(TPersistent)',
  1069. ' private type AliasU = U;',
  1070. ' published',
  1071. ' a: specialize TAnt<AliasU>;',
  1072. ' end;',
  1073. ' generic TAnt<T> = class(TPersistent)',
  1074. ' private type AliasT = T;',
  1075. ' published',
  1076. ' f: specialize TFish<AliasT>;',
  1077. ' end;',
  1078. 'var',
  1079. ' WordFish: specialize TFish<word>;',
  1080. ' p: pointer;',
  1081. 'begin',
  1082. ' p:=typeinfo(specialize TAnt<word>);',
  1083. ' p:=typeinfo(specialize TFish<word>);',
  1084. '']);
  1085. ConvertProgram;
  1086. CheckSource('TestGen_ClassForward_CircleRTTI',
  1087. LinesToStr([ // statements
  1088. '$mod.$rtti.$Class("TAnt<System.Word>");',
  1089. '$mod.$rtti.$Class("TFish<System.Word>");',
  1090. 'rtl.createClass(this, "TObject", null, function () {',
  1091. ' this.$init = function () {',
  1092. ' };',
  1093. ' this.$final = function () {',
  1094. ' };',
  1095. '});',
  1096. 'rtl.createClass(this, "TPersistent", this.TObject, function () {',
  1097. '});',
  1098. 'rtl.createClass(this, "TAnt$G2", this.TPersistent, function () {',
  1099. ' this.$init = function () {',
  1100. ' $mod.TPersistent.$init.call(this);',
  1101. ' this.f = null;',
  1102. ' };',
  1103. ' this.$final = function () {',
  1104. ' this.f = undefined;',
  1105. ' $mod.TPersistent.$final.call(this);',
  1106. ' };',
  1107. ' var $r = this.$rtti;',
  1108. ' $r.addField("f", $mod.$rtti["TFish<System.Word>"]);',
  1109. '}, "TAnt<System.Word>");',
  1110. 'rtl.createClass(this, "TFish$G2", this.TPersistent, function () {',
  1111. ' this.$init = function () {',
  1112. ' $mod.TPersistent.$init.call(this);',
  1113. ' this.a = null;',
  1114. ' };',
  1115. ' this.$final = function () {',
  1116. ' this.a = undefined;',
  1117. ' $mod.TPersistent.$final.call(this);',
  1118. ' };',
  1119. ' var $r = this.$rtti;',
  1120. ' $r.addField("a", $mod.$rtti["TAnt<System.Word>"]);',
  1121. '}, "TFish<System.Word>");',
  1122. 'this.WordFish = null;',
  1123. 'this.p = null;',
  1124. '']),
  1125. LinesToStr([ // $mod.$main
  1126. '$mod.p = $mod.$rtti["TAnt<System.Word>"];',
  1127. '$mod.p = $mod.$rtti["TFish<System.Word>"];',
  1128. '']));
  1129. end;
  1130. procedure TTestGenerics.TestGen_Class_Nested_RTTI;
  1131. begin
  1132. WithTypeInfo:=true;
  1133. StartProgram(true,[supTObject]);
  1134. AddModuleWithIntfImplSrc('UnitA.pas',
  1135. LinesToStr([
  1136. 'type',
  1137. ' generic TAnt<T> = class',
  1138. ' type',
  1139. ' TLeg = class',
  1140. ' published',
  1141. ' Size: T;',
  1142. ' end;',
  1143. ' end;',
  1144. ' TBoolAnt = specialize TAnt<boolean>;',
  1145. '']),
  1146. LinesToStr([
  1147. '']));
  1148. Add([
  1149. 'uses UnitA;',
  1150. 'var',
  1151. ' BoolLeg: TBoolAnt.TLeg;',
  1152. 'begin',
  1153. ' if typeinfo(TBoolAnt.TLeg)=nil then ;',
  1154. '']);
  1155. ConvertProgram;
  1156. CheckUnit('UnitA.pas',
  1157. LinesToStr([ // statements
  1158. 'rtl.module("UnitA", ["system"], function () {',
  1159. ' var $mod = this;',
  1160. ' $mod.$rtti.$Class("TAnt<System.Boolean>");',
  1161. ' rtl.createClass(this, "TAnt$G1", pas.system.TObject, function () {',
  1162. ' rtl.createClass(this, "TLeg", pas.system.TObject, function () {',
  1163. ' this.$init = function () {',
  1164. ' pas.system.TObject.$init.call(this);',
  1165. ' this.Size = false;',
  1166. ' };',
  1167. ' var $r = this.$rtti;',
  1168. ' $r.addField("Size", rtl.boolean);',
  1169. ' }, "TAnt<System.Boolean>.TLeg");',
  1170. ' }, "TAnt<System.Boolean>");',
  1171. '});']));
  1172. CheckSource('TestGen_Class_Nested_RTTI',
  1173. LinesToStr([ // statements
  1174. 'this.BoolLeg = null;',
  1175. '']),
  1176. LinesToStr([ // $mod.$main
  1177. 'if (pas.UnitA.$rtti["TAnt<System.Boolean>.TLeg"] === null) ;',
  1178. '']));
  1179. end;
  1180. procedure TTestGenerics.TestGen_Class_ClassVarRecord_UnitImpl;
  1181. begin
  1182. StartProgram(true,[supTObject]);
  1183. AddModuleWithIntfImplSrc('UnitA.pas',
  1184. LinesToStr([
  1185. 'type',
  1186. ' generic TAnt<T> = class',
  1187. ' public',
  1188. ' class var x: T;',
  1189. ' class var a: array[1..2] of T;',
  1190. ' end;',
  1191. '']),
  1192. LinesToStr([
  1193. 'type',
  1194. ' TBird = record',
  1195. ' b: word;',
  1196. ' end;',
  1197. 'var f: specialize TAnt<TBird>;',
  1198. 'begin',
  1199. ' f.x.b:=f.x.b+10;',
  1200. '']));
  1201. Add([
  1202. 'uses UnitA;',
  1203. 'begin',
  1204. 'end.']);
  1205. ConvertProgram;
  1206. CheckUnit('UnitA.pas',
  1207. LinesToStr([ // statements
  1208. 'rtl.module("UnitA", ["system"], function () {',
  1209. ' var $mod = this;',
  1210. ' var $impl = $mod.$impl;',
  1211. ' rtl.createClass(this, "TAnt$G1", pas.system.TObject, function () {',
  1212. ' this.$initSpec = function () {',
  1213. ' this.x = $impl.TBird.$new();',
  1214. ' this.a = rtl.arraySetLength(null, $impl.TBird, 2);',
  1215. ' };',
  1216. ' this.a$a$clone = function (a) {',
  1217. ' var b = [];',
  1218. ' b.length = 2;',
  1219. ' for (var c = 0; c < 2; c++) b[c] = $impl.TBird.$clone(a[c]);',
  1220. ' return b;',
  1221. ' };',
  1222. ' }, "TAnt<UnitA.TBird>");',
  1223. ' $mod.$implcode = function () {',
  1224. ' rtl.recNewT($impl, "TBird", function () {',
  1225. ' this.b = 0;',
  1226. ' this.$eq = function (b) {',
  1227. ' return this.b === b.b;',
  1228. ' };',
  1229. ' this.$assign = function (s) {',
  1230. ' this.b = s.b;',
  1231. ' return this;',
  1232. ' };',
  1233. ' });',
  1234. ' $impl.f = null;',
  1235. ' };',
  1236. ' $mod.$init = function () {',
  1237. ' $impl.f.x.b = $impl.f.x.b + 10;',
  1238. ' };',
  1239. '}, []);',
  1240. '']));
  1241. CheckSource('TestGen_Class_ClassVarRecord_UnitImpl',
  1242. LinesToStr([ // statements
  1243. '$mod.$implcode = function () {',
  1244. ' pas.UnitA.TAnt$G1.$initSpec();',
  1245. '};',
  1246. '']),
  1247. LinesToStr([ // $mod.$main
  1248. '']));
  1249. end;
  1250. procedure TTestGenerics.TestGen_ExtClass_VarArgsOfType;
  1251. begin
  1252. StartProgram(false);
  1253. Add([
  1254. '{$mode objfpc}',
  1255. '{$modeswitch externalclass}',
  1256. 'type',
  1257. ' TJSObject = class external name ''Object''',
  1258. ' end;',
  1259. ' generic TGJSSet<T> = class external name ''Set''',
  1260. ' constructor new(aElement1: T); varargs of T; overload;',
  1261. ' function bind(thisArg: TJSObject): T; varargs of T;',
  1262. ' end;',
  1263. ' TJSWordSet = specialize TGJSSet<word>;',
  1264. 'var',
  1265. ' s: TJSWordSet;',
  1266. ' w: word;',
  1267. 'begin',
  1268. ' s:=TJSWordSet.new(3);',
  1269. ' s:=TJSWordSet.new(3,5);',
  1270. ' w:=s.bind(nil);',
  1271. ' w:=s.bind(nil,6);',
  1272. ' w:=s.bind(nil,7,8);',
  1273. '']);
  1274. ConvertProgram;
  1275. CheckSource('TestGen_ExtClass_VarArgsOfType',
  1276. LinesToStr([ // statements
  1277. 'this.s = null;',
  1278. 'this.w = 0;',
  1279. '']),
  1280. LinesToStr([ // $mod.$main
  1281. '$mod.s = new Set(3);',
  1282. '$mod.s = new Set(3, 5);',
  1283. '$mod.w = $mod.s.bind(null);',
  1284. '$mod.w = $mod.s.bind(null, 6);',
  1285. '$mod.w = $mod.s.bind(null, 7, 8);',
  1286. '']));
  1287. end;
  1288. procedure TTestGenerics.TestGen_ExtClass_Array;
  1289. begin
  1290. StartProgram(false);
  1291. Add([
  1292. '{$mode delphi}',
  1293. '{$ModeSwitch externalclass}',
  1294. 'type',
  1295. ' NativeInt = longint;',
  1296. ' TJSGenArray<T> = Class external name ''Array''',
  1297. ' private',
  1298. ' function GetElements(Index: NativeInt): T; external name ''[]'';',
  1299. ' procedure SetElements(Index: NativeInt; const AValue: T); external name ''[]'';',
  1300. ' public',
  1301. ' type TSelfType = TJSGenArray<T>;',
  1302. ' public',
  1303. ' FLength : NativeInt; external name ''length'';',
  1304. ' constructor new; overload;',
  1305. ' constructor new(aLength : NativeInt); overload;',
  1306. ' class function _of() : TSelfType; varargs; external name ''of'';',
  1307. ' function fill(aValue : T) : TSelfType; overload;',
  1308. ' function fill(aValue : T; aStartIndex : NativeInt) : TSelfType; overload;',
  1309. ' function fill(aValue : T; aStartIndex,aEndIndex : NativeInt) : TSelfType; overload;',
  1310. ' property Length : NativeInt Read FLength Write FLength;',
  1311. ' property Elements[Index: NativeInt]: T read GetElements write SetElements; default;',
  1312. ' end;',
  1313. ' TJSWordArray = TJSGenArray<word>;',
  1314. 'var',
  1315. ' wa: TJSWordArray;',
  1316. ' w: word;',
  1317. 'begin',
  1318. ' wa:=TJSWordArray.new;',
  1319. ' wa:=TJSWordArray.new(3);',
  1320. ' wa:=TJSWordArray._of(4,5);',
  1321. ' wa:=wa.fill(7);',
  1322. ' wa:=wa.fill(7,8,9);',
  1323. ' w:=wa.length;',
  1324. ' wa.length:=10;',
  1325. ' wa[11]:=w;',
  1326. ' w:=wa[12];',
  1327. '']);
  1328. ConvertProgram;
  1329. CheckSource('TestGen_ExtClass_Array',
  1330. LinesToStr([ // statements
  1331. 'this.wa = null;',
  1332. 'this.w = 0;',
  1333. '']),
  1334. LinesToStr([ // $mod.$main
  1335. '$mod.wa = new Array();',
  1336. '$mod.wa = new Array(3);',
  1337. '$mod.wa = Array.of(4, 5);',
  1338. '$mod.wa = $mod.wa.fill(7);',
  1339. '$mod.wa = $mod.wa.fill(7, 8, 9);',
  1340. '$mod.w = $mod.wa.length;',
  1341. '$mod.wa.length = 10;',
  1342. '$mod.wa[11] = $mod.w;',
  1343. '$mod.w = $mod.wa[12];',
  1344. '']));
  1345. end;
  1346. procedure TTestGenerics.TestGen_ExtClass_GenJSValueAssign;
  1347. begin
  1348. StartProgram(false);
  1349. Add([
  1350. '{$mode delphi}',
  1351. '{$modeswitch externalclass}',
  1352. 'type',
  1353. ' TExt<T> = class external name ''Ext''',
  1354. ' F: T;',
  1355. ' end;',
  1356. ' TExtWord = TExt<Word>;',
  1357. ' TExtAny = TExt<JSValue>;',
  1358. 'procedure Run(e: TExtAny);',
  1359. 'begin end;',
  1360. 'var',
  1361. ' w: TExtWord;',
  1362. ' a: TExtAny;',
  1363. 'begin',
  1364. ' a:=w;',
  1365. ' Run(w);',
  1366. '']);
  1367. ConvertProgram;
  1368. CheckSource('TestGen_ExtClass_GenJSValueAssign',
  1369. LinesToStr([ // statements
  1370. 'this.Run = function (e) {',
  1371. '};',
  1372. 'this.w = null;',
  1373. 'this.a = null;',
  1374. '']),
  1375. LinesToStr([ // $mod.$main
  1376. '$mod.a = $mod.w;',
  1377. '$mod.Run($mod.w);',
  1378. '']));
  1379. CheckResolverUnexpectedHints();
  1380. end;
  1381. procedure TTestGenerics.TestGen_ExtClass_AliasMemberType;
  1382. begin
  1383. StartProgram(false);
  1384. Add([
  1385. '{$mode objfpc}',
  1386. '{$modeswitch externalclass}',
  1387. 'type',
  1388. ' generic TExt<T> = class external name ''Ext''',
  1389. ' public type TRun = reference to function(a: T): T;',
  1390. ' end;',
  1391. ' TExtWord = specialize TExt<word>;',
  1392. ' TExtWordRun = TExtWord.TRun;',
  1393. 'begin',
  1394. '']);
  1395. ConvertProgram;
  1396. CheckSource('TestGen_ExtClass_AliasMemberType',
  1397. LinesToStr([ // statements
  1398. '']),
  1399. LinesToStr([ // $mod.$main
  1400. '']));
  1401. end;
  1402. procedure TTestGenerics.TestGen_ExtClass_RTTI;
  1403. begin
  1404. WithTypeInfo:=true;
  1405. StartProgram(false);
  1406. Add([
  1407. '{$mode objfpc}',
  1408. '{$modeswitch externalclass}',
  1409. 'type',
  1410. ' generic TGJSSET<T> = class external name ''SET''',
  1411. ' A: T;',
  1412. ' end;',
  1413. ' TJSSet = specialize TGJSSET<JSValue>;',
  1414. ' TJSSetEventProc = reference to procedure(value : JSValue; key: NativeInt; set_: TJSSet);',
  1415. 'var p: Pointer;',
  1416. 'begin',
  1417. ' p:=typeinfo(TJSSetEventProc);',
  1418. '']);
  1419. ConvertProgram;
  1420. CheckSource('TestGen_ExtClass_RTTI',
  1421. LinesToStr([ // statements
  1422. 'this.$rtti.$ExtClass("TGJSSET<System.JSValue>", {',
  1423. ' jsclass: "SET"',
  1424. '});',
  1425. 'this.$rtti.$RefToProcVar("TJSSetEventProc", {',
  1426. ' procsig: rtl.newTIProcSig([["value", rtl.jsvalue], ["key", rtl.nativeint], ["set_", this.$rtti["TGJSSET<System.JSValue>"]]])',
  1427. '});',
  1428. 'this.p = null;',
  1429. '']),
  1430. LinesToStr([ // $mod.$main
  1431. '$mod.p = $mod.$rtti["TJSSetEventProc"];',
  1432. '']));
  1433. end;
  1434. procedure TTestGenerics.TestGen_ExtClass_UnitImplRec;
  1435. begin
  1436. WithTypeInfo:=true;
  1437. StartProgram(true,[supTObject]);
  1438. AddModuleWithIntfImplSrc('UnitA.pas',
  1439. LinesToStr([
  1440. '{$mode objfpc}',
  1441. '{$modeswitch externalclass}',
  1442. 'type',
  1443. ' generic TAnt<T> = class external name ''SET''',
  1444. ' x: T;',
  1445. ' end;',
  1446. '']),
  1447. LinesToStr([
  1448. 'type',
  1449. ' TBird = record',
  1450. ' b: word;',
  1451. ' end;',
  1452. 'var',
  1453. ' f: specialize TAnt<TBird>;',
  1454. 'begin',
  1455. ' f.x.b:=f.x.b+10;',
  1456. '']));
  1457. Add([
  1458. 'uses UnitA;',
  1459. 'begin',
  1460. 'end.']);
  1461. ConvertProgram;
  1462. CheckUnit('UnitA.pas',
  1463. LinesToStr([ // statements
  1464. 'rtl.module("UnitA", ["system"], function () {',
  1465. ' var $mod = this;',
  1466. ' var $impl = $mod.$impl;',
  1467. ' this.$rtti.$ExtClass("TAnt<UnitA.TBird>", {',
  1468. ' jsclass: "SET"',
  1469. ' });',
  1470. ' $mod.$implcode = function () {',
  1471. ' rtl.recNewT($impl, "TBird", function () {',
  1472. ' this.b = 0;',
  1473. ' this.$eq = function (b) {',
  1474. ' return this.b === b.b;',
  1475. ' };',
  1476. ' this.$assign = function (s) {',
  1477. ' this.b = s.b;',
  1478. ' return this;',
  1479. ' };',
  1480. ' var $r = $mod.$rtti.$Record("TBird", {});',
  1481. ' $r.addField("b", rtl.word);',
  1482. ' });',
  1483. ' $impl.f = null;',
  1484. ' };',
  1485. ' $mod.$init = function () {',
  1486. ' $impl.f.x.b = $impl.f.x.b + 10;',
  1487. ' };',
  1488. '}, []);']));
  1489. CheckSource('TestGen_Class_ClassVarRecord_UnitImpl',
  1490. LinesToStr([ // statements
  1491. '']),
  1492. LinesToStr([ // $mod.$main
  1493. '']));
  1494. end;
  1495. procedure TTestGenerics.TestGen_ClassInterface_Corba;
  1496. begin
  1497. StartProgram(false);
  1498. Add([
  1499. '{$interfaces corba}',
  1500. 'type',
  1501. ' IUnknown = interface;',
  1502. ' IUnknown = interface',
  1503. ' [''{00000000-0000-0000-C000-000000000046}'']',
  1504. ' end;',
  1505. ' IInterface = IUnknown;',
  1506. ' generic IBird<T> = interface(IInterface)',
  1507. ' function GetSize: T;',
  1508. ' procedure SetSize(i: T);',
  1509. ' property Size: T read GetSize write SetSize;',
  1510. ' procedure DoIt(i: T);',
  1511. ' end;',
  1512. ' TObject = class',
  1513. ' end;',
  1514. ' generic TBird<T> = class(TObject,specialize IBird<T>)',
  1515. ' function GetSize: T; virtual; abstract;',
  1516. ' procedure SetSize(i: T); virtual; abstract;',
  1517. ' procedure DoIt(i: T); virtual; abstract;',
  1518. ' end;',
  1519. ' IWordBird = specialize IBird<Word>;',
  1520. ' TWordBird = specialize TBird<Word>;',
  1521. 'var',
  1522. ' BirdIntf: IWordBird;',
  1523. 'begin',
  1524. ' BirdIntf.Size:=BirdIntf.Size;',
  1525. '']);
  1526. ConvertProgram;
  1527. CheckSource('TestGen_ClassInterface_Corba',
  1528. LinesToStr([ // statements
  1529. 'rtl.createInterface(this, "IUnknown", "{00000000-0000-0000-C000-000000000046}", [], null);',
  1530. 'rtl.createClass(this, "TObject", null, function () {',
  1531. ' this.$init = function () {',
  1532. ' };',
  1533. ' this.$final = function () {',
  1534. ' };',
  1535. '});',
  1536. 'rtl.createInterface(',
  1537. ' this,',
  1538. ' "IBird$G2",',
  1539. ' "{33AB51C6-6240-3BDF-B4B0-D48A593EAB0A}",',
  1540. ' ["GetSize", "SetSize", "DoIt"],',
  1541. ' this.IUnknown,',
  1542. ' "IBird<System.Word>"',
  1543. ');',
  1544. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  1545. ' rtl.addIntf(this, $mod.IBird$G2);',
  1546. '}, "TBird<System.Word>");',
  1547. 'this.BirdIntf = null;',
  1548. '']),
  1549. LinesToStr([ // $mod.$main
  1550. '$mod.BirdIntf.SetSize($mod.BirdIntf.GetSize());',
  1551. '']));
  1552. end;
  1553. procedure TTestGenerics.TestGen_ClassInterface_InterfacedObject;
  1554. begin
  1555. StartProgram(true,[supTInterfacedObject]);
  1556. Add([
  1557. '{$mode delphi}',
  1558. 'type',
  1559. ' IComparer<T> = interface [''{505778ED-F783-4456-9691-32F419CC5E18}'']',
  1560. ' function Compare(const Left, Right: T): Integer; overload;',
  1561. ' end;',
  1562. ' TComparer<T> = class(TInterfacedObject, IComparer<T>)',
  1563. ' function Compare(const Left, Right: T): Integer;',
  1564. ' end;',
  1565. 'function TComparer<T>.Compare(const Left, Right: T): Integer; begin end;',
  1566. 'var',
  1567. ' aComparer : IComparer<Integer>;',
  1568. 'begin',
  1569. ' aComparer:=TComparer<Integer>.Create;',
  1570. '']);
  1571. ConvertProgram;
  1572. CheckSource('TestGen_ClassInterface_InterfacedObject',
  1573. LinesToStr([ // statements
  1574. 'rtl.createInterface(',
  1575. ' this,',
  1576. ' "IComparer$G2",',
  1577. ' "{505778ED-F783-4456-9691-32F419CC5E18}",',
  1578. ' ["Compare"],',
  1579. ' pas.system.IUnknown,',
  1580. ' "IComparer<System.Longint>"',
  1581. ');',
  1582. 'this.aComparer = null;',
  1583. 'rtl.createClass(this, "TComparer$G1", pas.system.TInterfacedObject, function () {',
  1584. ' this.Compare = function (Left, Right) {',
  1585. ' var Result = 0;',
  1586. ' return Result;',
  1587. ' };',
  1588. ' rtl.addIntf(this, $mod.IComparer$G2);',
  1589. ' rtl.addIntf(this, pas.system.IUnknown);',
  1590. '}, "TComparer<System.Longint>");',
  1591. '']),
  1592. LinesToStr([ // $mod.$main
  1593. 'rtl.setIntfP($mod, "aComparer", rtl.queryIntfT($mod.TComparer$G1.$create("Create"), $mod.IComparer$G2), true);',
  1594. '']));
  1595. end;
  1596. procedure TTestGenerics.TestGen_ClassInterface_COM_RTTI;
  1597. begin
  1598. StartProgram(true,[supTInterfacedObject]);
  1599. Add([
  1600. '{$mode delphi}',
  1601. 'type',
  1602. ' TBird = class',
  1603. ' function Fly<T: IInterface>: T;',
  1604. ' end;',
  1605. ' IAnt = interface',
  1606. ' procedure InterfaceProc;',
  1607. ' end;',
  1608. 'function TBird.Fly<T>: T;',
  1609. 'begin',
  1610. ' if TypeInfo(T)=nil then ;',
  1611. 'end;',
  1612. 'var Bird: TBird;',
  1613. ' Ant: IAnt;',
  1614. 'begin',
  1615. ' Ant := Bird.Fly<IAnt>;',
  1616. '']);
  1617. ConvertProgram;
  1618. CheckSource('TestGen_ClassInterface_COM_RTTI',
  1619. LinesToStr([ // statements
  1620. 'rtl.createClass(this, "TBird", pas.system.TObject, function () {',
  1621. ' this.Fly$G1 = function () {',
  1622. ' var Result = null;',
  1623. ' if ($mod.$rtti["IAnt"] === null) ;',
  1624. ' return Result;',
  1625. ' };',
  1626. '});',
  1627. 'rtl.createInterface(this, "IAnt", "{B9D0FF27-A446-3A1B-AA85-F167837AA297}", ["InterfaceProc"], pas.system.IUnknown);',
  1628. 'this.Bird = null;',
  1629. 'this.Ant = null;',
  1630. '']),
  1631. LinesToStr([ // $mod.$main
  1632. 'rtl.setIntfP($mod, "Ant", $mod.Bird.Fly$G1(), true);',
  1633. '']));
  1634. end;
  1635. procedure TTestGenerics.TestGen_ClassInterface_Helper;
  1636. begin
  1637. StartProgram(true,[supTInterfacedObject]);
  1638. Add([
  1639. '{$mode objfpc}',
  1640. '{$ModeSwitch typehelpers}',
  1641. 'type',
  1642. ' IAnt = interface',
  1643. ' procedure InterfaceProc;',
  1644. ' end;',
  1645. ' TBird = type helper for IAnt',
  1646. ' generic procedure Fly<T>(a: T);',
  1647. ' end;',
  1648. 'generic procedure TBird.Fly<T>(a: T);',
  1649. 'begin',
  1650. 'end;',
  1651. 'var ',
  1652. ' Ant: IAnt;',
  1653. 'begin',
  1654. ' Ant.specialize Fly<word>(3);',
  1655. '']);
  1656. ConvertProgram;
  1657. CheckSource('TestGen_ClassInterface_COM_RTTI',
  1658. LinesToStr([ // statements
  1659. 'rtl.createInterface(this, "IAnt", "{B9D0FF27-A446-3A1B-AA85-F167837AA297}", ["InterfaceProc"], pas.system.IUnknown);',
  1660. 'rtl.createHelper(this, "TBird", null, function () {',
  1661. ' this.Fly$G1 = function (a) {',
  1662. ' };',
  1663. '});',
  1664. 'this.Ant = null;',
  1665. '']),
  1666. LinesToStr([ // $mod.$main
  1667. '$mod.TBird.Fly$G1.call({',
  1668. ' p: $mod,',
  1669. ' get: function () {',
  1670. ' return this.p.Ant;',
  1671. ' },',
  1672. ' set: function (v) {',
  1673. ' rtl.setIntfP(this.p, "Ant", v);',
  1674. ' }',
  1675. '}, 3);',
  1676. '']));
  1677. end;
  1678. procedure TTestGenerics.TestGen_ClassInterface_DelayedInitSpec;
  1679. begin
  1680. WithTypeInfo:=true;
  1681. StartProgram(true,[supTObject,supTInterfacedObject]);
  1682. AddModuleWithIntfImplSrc('UnitA.pas',
  1683. LinesToStr([
  1684. '{$mode delphi}',
  1685. 'type',
  1686. ' TAnt<T> = interface',
  1687. ' procedure Run(x: T);',
  1688. ' end;',
  1689. '']),
  1690. LinesToStr([
  1691. '']));
  1692. Add([
  1693. '{$mode delphi}',
  1694. 'uses UnitA;',
  1695. 'type',
  1696. ' TArrWord = array of word;',
  1697. ' TMyIntf = TAnt<TArrWord>;',
  1698. ' TBird = class(TInterfacedObject,TMyIntf)',
  1699. ' procedure Run(a: TArrWord); external name ''Run'';',
  1700. ' end;',
  1701. 'var',
  1702. ' i: TMyIntf;',
  1703. 'begin',
  1704. ' i:=TBird.Create;',
  1705. ' i.Run([3,4]);',
  1706. 'end.']);
  1707. ConvertProgram;
  1708. CheckUnit('UnitA.pas',
  1709. LinesToStr([ // statements
  1710. 'rtl.module("UnitA", ["system"], function () {',
  1711. ' var $mod = this;',
  1712. ' $mod.$rtti.$Interface("TAnt<test1.TArrWord>");',
  1713. ' rtl.createInterface(',
  1714. ' this,',
  1715. ' "TAnt$G1",',
  1716. ' "{B145F21B-2696-32D5-87A5-F16C037A2D45}",',
  1717. ' ["Run"],',
  1718. ' pas.system.IUnknown,',
  1719. ' function () {',
  1720. ' this.$initSpec = function () {',
  1721. ' var $r = this.$rtti;',
  1722. ' $r.addMethod("Run", 0, [["x", pas.program.$rtti["TArrWord"]]]);',
  1723. ' };',
  1724. ' },',
  1725. ' "TAnt<test1.TArrWord>"',
  1726. ' );',
  1727. '});']));
  1728. CheckSource('TestGen_ClassInterface_DelayedInitSpec',
  1729. LinesToStr([ // statements
  1730. 'this.$rtti.$DynArray("TArrWord", {',
  1731. ' eltype: rtl.word',
  1732. '});',
  1733. 'rtl.createClass(this, "TBird", pas.system.TInterfacedObject, function () {',
  1734. ' rtl.addIntf(this, pas.UnitA.TAnt$G1);',
  1735. ' rtl.addIntf(this, pas.system.IUnknown);',
  1736. '});',
  1737. 'this.i = null;',
  1738. '$mod.$implcode = function () {',
  1739. ' pas.UnitA.TAnt$G1.$initSpec();',
  1740. '};',
  1741. '']),
  1742. LinesToStr([ // $mod.$main
  1743. 'rtl.setIntfP($mod, "i", rtl.queryIntfT($mod.TBird.$create("Create"), pas.UnitA.TAnt$G1), true);',
  1744. '$mod.i.Run([3, 4]);',
  1745. '']));
  1746. end;
  1747. procedure TTestGenerics.TestGen_InlineSpec_Constructor;
  1748. begin
  1749. StartProgram(false);
  1750. Add([
  1751. '{$mode objfpc}',
  1752. 'type',
  1753. ' TObject = class',
  1754. ' public',
  1755. ' constructor Create;',
  1756. ' end;',
  1757. ' generic TBird<T> = class',
  1758. ' end;',
  1759. 'constructor TObject.Create; begin end;',
  1760. 'var b: specialize TBird<word>;',
  1761. 'begin',
  1762. ' b:=specialize TBird<word>.Create;',
  1763. '']);
  1764. ConvertProgram;
  1765. CheckSource('TestGen_InlineSpec_Constructor',
  1766. LinesToStr([ // statements
  1767. 'rtl.createClass(this, "TObject", null, function () {',
  1768. ' this.$init = function () {',
  1769. ' };',
  1770. ' this.$final = function () {',
  1771. ' };',
  1772. ' this.Create = function () {',
  1773. ' return this;',
  1774. ' };',
  1775. '});',
  1776. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  1777. '}, "TBird<System.Word>");',
  1778. 'this.b = null;',
  1779. '']),
  1780. LinesToStr([ // $mod.$main
  1781. '$mod.b = $mod.TBird$G1.$create("Create");',
  1782. '']));
  1783. end;
  1784. procedure TTestGenerics.TestGen_CallUnitImplProc;
  1785. begin
  1786. AddModuleWithIntfImplSrc('UnitA.pas',
  1787. LinesToStr([
  1788. 'type',
  1789. ' generic TBird<T> = class',
  1790. ' procedure Fly;',
  1791. ' end;',
  1792. 'var b: specialize TBird<boolean>;',
  1793. '']),
  1794. LinesToStr([
  1795. 'procedure DoIt;',
  1796. 'var b: specialize TBird<word>;',
  1797. 'begin',
  1798. ' b:=specialize TBird<word>.Create;',
  1799. ' b.Fly;',
  1800. 'end;',
  1801. 'procedure TBird.Fly;',
  1802. 'begin',
  1803. ' DoIt;',
  1804. 'end;',
  1805. '']));
  1806. StartProgram(true,[supTObject]);
  1807. Add('uses UnitA;');
  1808. Add('begin');
  1809. ConvertProgram;
  1810. CheckUnit('UnitA.pas',
  1811. LinesToStr([ // statements
  1812. 'rtl.module("UnitA", ["system"], function () {',
  1813. ' var $mod = this;',
  1814. ' var $impl = $mod.$impl;',
  1815. ' rtl.createClass(this, "TBird$G1", pas.system.TObject, function () {',
  1816. ' this.Fly = function () {',
  1817. ' $impl.DoIt();',
  1818. ' };',
  1819. ' }, "TBird<System.Boolean>");',
  1820. ' this.b = null;',
  1821. ' rtl.createClass(this, "TBird$G2", pas.system.TObject, function () {',
  1822. ' this.Fly = function () {',
  1823. ' $impl.DoIt();',
  1824. ' };',
  1825. ' }, "TBird<System.Word>");',
  1826. ' $mod.$implcode = function () {',
  1827. ' $impl.DoIt = function () {',
  1828. ' var b = null;',
  1829. ' b = $mod.TBird$G2.$create("Create");',
  1830. ' b.Fly();',
  1831. ' };',
  1832. ' };',
  1833. '}, []);',
  1834. '']));
  1835. end;
  1836. procedure TTestGenerics.TestGen_IntAssignTemplVar;
  1837. begin
  1838. StartProgram(false);
  1839. Add([
  1840. 'type',
  1841. ' TObject = class end;',
  1842. ' generic TBird<T> = class',
  1843. ' m: T;',
  1844. ' procedure Fly;',
  1845. ' end;',
  1846. 'var b: specialize TBird<word>;',
  1847. 'procedure TBird.Fly;',
  1848. 'var i: nativeint;',
  1849. 'begin',
  1850. ' i:=m;',
  1851. 'end;',
  1852. 'begin',
  1853. '']);
  1854. ConvertProgram;
  1855. CheckSource('TestGen_IntAssignTemplVar',
  1856. LinesToStr([ // statements
  1857. 'rtl.createClass(this, "TObject", null, function () {',
  1858. ' this.$init = function () {',
  1859. ' };',
  1860. ' this.$final = function () {',
  1861. ' };',
  1862. '});',
  1863. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  1864. ' this.$init = function () {',
  1865. ' $mod.TObject.$init.call(this);',
  1866. ' this.m = 0;',
  1867. ' };',
  1868. ' this.Fly = function () {',
  1869. ' var i = 0;',
  1870. ' i = this.m;',
  1871. ' };',
  1872. '}, "TBird<System.Word>");',
  1873. 'this.b = null;',
  1874. '']),
  1875. LinesToStr([ // $mod.$main
  1876. '']));
  1877. end;
  1878. procedure TTestGenerics.TestGen_TypeCastDotField;
  1879. begin
  1880. StartProgram(false);
  1881. Add([
  1882. 'type',
  1883. ' TObject = class end;',
  1884. ' generic TBird<T> = class',
  1885. ' Field: T;',
  1886. ' procedure Fly;',
  1887. ' end;',
  1888. 'var',
  1889. ' o: TObject;',
  1890. ' b: specialize TBird<word>;',
  1891. 'procedure TBird.Fly;',
  1892. 'begin',
  1893. ' specialize TBird<word>(o).Field:=3;',
  1894. ' if 4=specialize TBird<word>(o).Field then ;',
  1895. 'end;',
  1896. 'begin',
  1897. ' specialize TBird<word>(o).Field:=5;',
  1898. ' if 6=specialize TBird<word>(o).Field then ;',
  1899. '']);
  1900. ConvertProgram;
  1901. CheckSource('TestGen_TypeCastDotField',
  1902. LinesToStr([ // statements
  1903. 'rtl.createClass(this, "TObject", null, function () {',
  1904. ' this.$init = function () {',
  1905. ' };',
  1906. ' this.$final = function () {',
  1907. ' };',
  1908. '});',
  1909. 'this.o = null;',
  1910. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  1911. ' this.$init = function () {',
  1912. ' $mod.TObject.$init.call(this);',
  1913. ' this.Field = 0;',
  1914. ' };',
  1915. ' this.Fly = function () {',
  1916. ' $mod.o.Field = 3;',
  1917. ' if (4 === $mod.o.Field) ;',
  1918. ' };',
  1919. '}, "TBird<System.Word>");',
  1920. 'this.b = null;',
  1921. '']),
  1922. LinesToStr([ // $mod.$main
  1923. '$mod.o.Field = 5;',
  1924. 'if (6 === $mod.o.Field) ;',
  1925. '']));
  1926. end;
  1927. procedure TTestGenerics.TestGen_Except;
  1928. begin
  1929. StartProgram(false);
  1930. Add([
  1931. 'type',
  1932. ' TObject = class end;',
  1933. ' generic TBird<T> = class',
  1934. ' Field: T;',
  1935. ' procedure Fly;',
  1936. ' end;',
  1937. ' Exception = class',
  1938. ' end;',
  1939. ' generic EBird<T> = class(Exception)',
  1940. ' Id: T;',
  1941. ' end;',
  1942. 'var',
  1943. ' b: specialize TBird<word>;',
  1944. 'procedure TBird.Fly;',
  1945. 'begin',
  1946. ' try',
  1947. ' except',
  1948. ' on E: Exception do Fly;',
  1949. ' on EBird: specialize EBird<word> do EBird.Id:=3;',
  1950. ' else',
  1951. ' Fly;',
  1952. ' end;',
  1953. 'end;',
  1954. 'begin',
  1955. '']);
  1956. ConvertProgram;
  1957. CheckSource('TestGen_Except',
  1958. LinesToStr([ // statements
  1959. 'rtl.createClass(this, "TObject", null, function () {',
  1960. ' this.$init = function () {',
  1961. ' };',
  1962. ' this.$final = function () {',
  1963. ' };',
  1964. '});',
  1965. 'rtl.createClass(this, "Exception", this.TObject, function () {',
  1966. '});',
  1967. 'rtl.createClass(this, "TBird$G1", this.TObject, function () {',
  1968. ' this.$init = function () {',
  1969. ' $mod.TObject.$init.call(this);',
  1970. ' this.Field = 0;',
  1971. ' };',
  1972. ' this.Fly = function () {',
  1973. ' try {} catch ($e) {',
  1974. ' if ($mod.Exception.isPrototypeOf($e)) {',
  1975. ' var E = $e;',
  1976. ' this.Fly();',
  1977. ' } else if ($mod.EBird$G1.isPrototypeOf($e)) {',
  1978. ' var EBird = $e;',
  1979. ' EBird.Id = 3;',
  1980. ' } else {',
  1981. ' this.Fly();',
  1982. ' }',
  1983. ' };',
  1984. ' };',
  1985. '}, "TBird<System.Word>");',
  1986. 'this.b = null;',
  1987. 'rtl.createClass(this, "EBird$G1", this.Exception, function () {',
  1988. ' this.$init = function () {',
  1989. ' $mod.Exception.$init.call(this);',
  1990. ' this.Id = 0;',
  1991. ' };',
  1992. '}, "EBird<System.Word>");',
  1993. '']),
  1994. LinesToStr([ // $mod.$main
  1995. '']));
  1996. end;
  1997. procedure TTestGenerics.TestGen_HelperForArray;
  1998. begin
  1999. StartProgram(false);
  2000. Add([
  2001. '{$ModeSwitch typehelpers}',
  2002. 'type',
  2003. ' generic TArr<T> = array[1..2] of T;',
  2004. ' TWordArrHelper = type helper for specialize TArr<word>',
  2005. ' procedure Fly(w: word);',
  2006. ' end;',
  2007. 'procedure TWordArrHelper.Fly(w: word);',
  2008. 'begin',
  2009. 'end;',
  2010. 'var',
  2011. ' a: specialize TArr<word>;',
  2012. 'begin',
  2013. ' a.Fly(3);',
  2014. '']);
  2015. ConvertProgram;
  2016. CheckSource('TestGen_HelperForArray',
  2017. LinesToStr([ // statements
  2018. 'rtl.createHelper(this, "TWordArrHelper", null, function () {',
  2019. ' this.Fly = function (w) {',
  2020. ' };',
  2021. '});',
  2022. 'this.a = rtl.arraySetLength(null, 0, 2);',
  2023. '']),
  2024. LinesToStr([ // $mod.$main
  2025. '$mod.TWordArrHelper.Fly.call({',
  2026. ' p: $mod,',
  2027. ' get: function () {',
  2028. ' return this.p.a;',
  2029. ' },',
  2030. ' set: function (v) {',
  2031. ' this.p.a = v;',
  2032. ' }',
  2033. '}, 3);',
  2034. '']));
  2035. end;
  2036. procedure TTestGenerics.TestGenProc_Function_ObjFPC;
  2037. begin
  2038. StartProgram(false);
  2039. Add([
  2040. 'generic function Run<T>(a: T): T;',
  2041. 'var i: T;',
  2042. 'begin',
  2043. ' a:=i;',
  2044. ' Result:=a;',
  2045. 'end;',
  2046. 'var w: word;',
  2047. 'begin',
  2048. ' w:=specialize Run<word>(3);',
  2049. '']);
  2050. ConvertProgram;
  2051. CheckSource('TestGenProc_Function_ObjFPC',
  2052. LinesToStr([ // statements
  2053. 'this.w = 0;',
  2054. 'this.Run$G1 = function (a) {',
  2055. ' var Result = 0;',
  2056. ' var i = 0;',
  2057. ' a = i;',
  2058. ' Result = a;',
  2059. ' return Result;',
  2060. '};',
  2061. '']),
  2062. LinesToStr([ // $mod.$main
  2063. '$mod.w = $mod.Run$G1(3);',
  2064. '']));
  2065. end;
  2066. procedure TTestGenerics.TestGenProc_Function_Delphi;
  2067. begin
  2068. StartProgram(false);
  2069. Add([
  2070. '{$mode delphi}',
  2071. 'function Run<T>(a: T): T;',
  2072. 'var i: T;',
  2073. 'begin',
  2074. ' a:=i;',
  2075. ' Result:=a;',
  2076. 'end;',
  2077. 'var w: word;',
  2078. 'begin',
  2079. ' w:=Run<word>(3);',
  2080. '']);
  2081. ConvertProgram;
  2082. CheckSource('TestGenProc_Function_Delphi',
  2083. LinesToStr([ // statements
  2084. 'this.w = 0;',
  2085. 'this.Run$G1 = function (a) {',
  2086. ' var Result = 0;',
  2087. ' var i = 0;',
  2088. ' a = i;',
  2089. ' Result = a;',
  2090. ' return Result;',
  2091. '};',
  2092. '']),
  2093. LinesToStr([ // $mod.$main
  2094. '$mod.w = $mod.Run$G1(3);',
  2095. '']));
  2096. end;
  2097. procedure TTestGenerics.TestGenProc_Overload;
  2098. begin
  2099. StartProgram(false);
  2100. Add([
  2101. 'generic procedure DoIt<T>(a: T; w: word); overload;',
  2102. 'begin',
  2103. 'end;',
  2104. 'generic procedure DoIt<T>(a: T; b: boolean); overload;',
  2105. 'begin',
  2106. 'end;',
  2107. 'begin',
  2108. ' specialize DoIt<word>(3,4);',
  2109. ' specialize DoIt<boolean>(false,5);',
  2110. ' specialize DoIt<word>(6,true);',
  2111. ' specialize DoIt<double>(7.3,true);',
  2112. '']);
  2113. ConvertProgram;
  2114. CheckSource('TestGenProc_Overload',
  2115. LinesToStr([ // statements
  2116. 'this.DoIt$G1 = function (a, w) {',
  2117. '};',
  2118. 'this.DoIt$G2 = function (a, w) {',
  2119. '};',
  2120. 'this.DoIt$1G1 = function (a, b) {',
  2121. '};',
  2122. 'this.DoIt$1G2 = function (a, b) {',
  2123. '};',
  2124. '']),
  2125. LinesToStr([ // $mod.$main
  2126. '$mod.DoIt$G1(3, 4);',
  2127. '$mod.DoIt$G2(false, 5);',
  2128. '$mod.DoIt$1G1(6, true);',
  2129. '$mod.DoIt$1G2(7.3, true);',
  2130. '']));
  2131. end;
  2132. procedure TTestGenerics.TestGenProc_Forward;
  2133. begin
  2134. StartProgram(false);
  2135. Add([
  2136. '{$mode delphi}',
  2137. 'procedure Run<S>(a: S; b: boolean); forward;',
  2138. 'procedure Run<S>(a: S; b: boolean);',
  2139. 'begin',
  2140. ' Run<word>(1,true);',
  2141. 'end;',
  2142. 'begin',
  2143. ' Run(1.3,true);',
  2144. '']);
  2145. ConvertProgram;
  2146. CheckSource('TestGenProc_infer_OverloadForward',
  2147. LinesToStr([ // statements
  2148. 'this.Run$G1 = function (a, b) {',
  2149. ' $mod.Run$G1(1, true);',
  2150. '};',
  2151. 'this.Run$G2 = function (a, b) {',
  2152. ' $mod.Run$G1(1, true);',
  2153. '};',
  2154. '']),
  2155. LinesToStr([ // $mod.$main
  2156. '$mod.Run$G2(1.3, true);',
  2157. '']));
  2158. end;
  2159. procedure TTestGenerics.TestGenProc_Infer_OverloadForward;
  2160. begin
  2161. StartProgram(false);
  2162. Add([
  2163. '{$mode delphi}',
  2164. 'procedure {#A}Run<S>(a: S; b: boolean); forward; overload;',
  2165. 'procedure {#B}Run<T>(a: T; w: word); forward; overload;',
  2166. 'procedure {#C}Run<U>(a: U; b: U); forward; overload;',
  2167. 'procedure {#A2}Run<S>(a: S; b: boolean); overload;',
  2168. 'begin',
  2169. ' {@A}Run(1,true);', // non generic take precedence
  2170. ' {@B}Run(2,word(3));', // non generic take precedence
  2171. ' {@C}Run(''foo'',''bar'');',
  2172. 'end;',
  2173. 'procedure {#B2}Run<T>(a: T; w: word); overload;',
  2174. 'begin',
  2175. 'end;',
  2176. 'procedure {#C2}Run<U>(a: U; b: U); overload;',
  2177. 'begin',
  2178. 'end;',
  2179. 'begin',
  2180. ' {@A}Run(1,true);', // non generic take precedence
  2181. ' {@B}Run(2,word(3));', // non generic take precedence
  2182. ' {@C}Run(''foo'',''bar'');',
  2183. '']);
  2184. ConvertProgram;
  2185. CheckSource('TestGenProc_infer_OverloadForward',
  2186. LinesToStr([ // statements
  2187. 'this.Run$G1 = function (a, b) {',
  2188. ' $mod.Run$G1(1, true);',
  2189. ' $mod.Run$1G1(2, 3);',
  2190. ' $mod.Run$2G1("foo", "bar");',
  2191. '};',
  2192. 'this.Run$1G1 = function (a, w) {',
  2193. '};',
  2194. 'this.Run$2G1 = function (a, b) {',
  2195. '};',
  2196. '']),
  2197. LinesToStr([ // $mod.$main
  2198. '$mod.Run$G1(1, true);',
  2199. '$mod.Run$1G1(2, 3);',
  2200. '$mod.Run$2G1("foo", "bar");',
  2201. '']));
  2202. end;
  2203. procedure TTestGenerics.TestGenProc_TypeInfo;
  2204. begin
  2205. WithTypeInfo:=true;
  2206. StartProgram(true,[supTypeInfo]);
  2207. Add([
  2208. '{$modeswitch implicitfunctionspecialization}',
  2209. 'generic procedure Run<S>(a: S);',
  2210. 'var',
  2211. ' p: TTypeInfo;',
  2212. 'begin',
  2213. ' p:=TypeInfo(S);',
  2214. ' p:=TypeInfo(a);',
  2215. 'end;',
  2216. 'begin',
  2217. ' Run(word(3));',
  2218. ' Run(''foo'');',
  2219. '']);
  2220. ConvertProgram;
  2221. CheckSource('TestGenProc_TypeInfo',
  2222. LinesToStr([ // statements
  2223. 'this.Run$G1 = function (a) {',
  2224. ' var p = null;',
  2225. ' p = rtl.word;',
  2226. ' p = rtl.word;',
  2227. '};',
  2228. 'this.Run$G2 = function (a) {',
  2229. ' var p = null;',
  2230. ' p = rtl.string;',
  2231. ' p = rtl.string;',
  2232. '};',
  2233. '']),
  2234. LinesToStr([ // $mod.$main
  2235. '$mod.Run$G1(3);',
  2236. '$mod.Run$G2("foo");',
  2237. '']));
  2238. end;
  2239. procedure TTestGenerics.TestGenProc_Infer_Widen;
  2240. begin
  2241. StartProgram(false);
  2242. Add([
  2243. '{$mode delphi}',
  2244. 'procedure Run<S>(a: S; b: S);',
  2245. 'begin',
  2246. 'end;',
  2247. 'begin',
  2248. ' Run(word(1),longint(2));',
  2249. ' Run(byte(2),smallint(2));',
  2250. ' Run(longword(3),longint(2));',
  2251. ' Run(nativeint(4),longint(2));',
  2252. ' Run(nativeint(5),nativeuint(2));',
  2253. ' Run(''a'',''foo'');',
  2254. ' Run(''bar'',''c'');',
  2255. '']);
  2256. ConvertProgram;
  2257. CheckSource('TestGenProc_Infer_Widen',
  2258. LinesToStr([ // statements
  2259. 'this.Run$G1 = function (a, b) {',
  2260. '};',
  2261. 'this.Run$G2 = function (a, b) {',
  2262. '};',
  2263. 'this.Run$G3 = function (a, b) {',
  2264. '};',
  2265. '']),
  2266. LinesToStr([ // $mod.$main
  2267. '$mod.Run$G1(1, 2);',
  2268. '$mod.Run$G1(2, 2);',
  2269. '$mod.Run$G2(3, 2);',
  2270. '$mod.Run$G2(4, 2);',
  2271. '$mod.Run$G2(5, 2);',
  2272. '$mod.Run$G3("a", "foo");',
  2273. '$mod.Run$G3("bar", "c");',
  2274. '']));
  2275. end;
  2276. procedure TTestGenerics.TestGenProc_Infer_PassAsArg;
  2277. begin
  2278. StartProgram(false);
  2279. Add([
  2280. '{$mode delphi}',
  2281. 'function Run<T>(a: T): T;',
  2282. 'var b: T;',
  2283. 'begin',
  2284. ' Run(Run<word>(3));',
  2285. ' Run(Run(word(4)));',
  2286. 'end;',
  2287. 'begin',
  2288. ' Run(Run<word>(5));',
  2289. ' Run(Run(word(6)));',
  2290. '']);
  2291. ConvertProgram;
  2292. CheckSource('TestGenProc_Infer_PassAsArg',
  2293. LinesToStr([ // statements
  2294. 'this.Run$G1 = function (a) {',
  2295. ' var Result = 0;',
  2296. ' var b = 0;',
  2297. ' $mod.Run$G1($mod.Run$G1(3));',
  2298. ' $mod.Run$G1($mod.Run$G1(4));',
  2299. ' return Result;',
  2300. '};',
  2301. '']),
  2302. LinesToStr([ // $mod.$main
  2303. '$mod.Run$G1($mod.Run$G1(5));',
  2304. '$mod.Run$G1($mod.Run$G1(6));',
  2305. '']));
  2306. end;
  2307. procedure TTestGenerics.TestGenProc_AnonymousProc;
  2308. begin
  2309. StartProgram(false);
  2310. Add([
  2311. '{$mode delphi}',
  2312. 'type',
  2313. ' TProc = reference to procedure;',
  2314. ' TFunc = reference to function(Value: JSValue): JSValue;',
  2315. 'function Run<T>(a: T; p: TProc): T;',
  2316. 'var b: T;',
  2317. ' f: TFunc;',
  2318. 'begin',
  2319. ' Result:=Run(a,procedure()begin end);',
  2320. ' f:=function(b: JSValue): JSValue begin end;',
  2321. ' f:=function(b: JSValue): JSValue',
  2322. ' function Sub(c: JSValue): JSValue;',
  2323. ' begin',
  2324. ' Result:=c;',
  2325. ' end;',
  2326. ' begin',
  2327. ' Result:=Sub(b);',
  2328. ' end;',
  2329. 'end;',
  2330. 'begin',
  2331. ' Run<word>(3,procedure() begin end);',
  2332. '']);
  2333. ConvertProgram;
  2334. CheckSource('TestGenProc_AnonymousProc',
  2335. LinesToStr([ // statements
  2336. 'this.Run$G1 = function (a, p) {',
  2337. ' var Result = 0;',
  2338. ' var b = 0;',
  2339. ' var f = null;',
  2340. ' Result = $mod.Run$G1(a, function () {',
  2341. ' });',
  2342. ' f = function (b) {',
  2343. ' var Result = undefined;',
  2344. ' return Result;',
  2345. ' };',
  2346. ' f = function (b) {',
  2347. ' var Result = undefined;',
  2348. ' function Sub(c) {',
  2349. ' var Result = undefined;',
  2350. ' Result = c;',
  2351. ' return Result;',
  2352. ' };',
  2353. ' Result = Sub(b);',
  2354. ' return Result;',
  2355. ' };',
  2356. ' return Result;',
  2357. '};',
  2358. '']),
  2359. LinesToStr([ // $mod.$main
  2360. '$mod.Run$G1(3, function () {',
  2361. '});',
  2362. '']));
  2363. end;
  2364. procedure TTestGenerics.TestGenMethod_ImplicitSpec_ObjFPC;
  2365. begin
  2366. StartProgram(false);
  2367. Add([
  2368. '{$mode objfpc}',
  2369. '{$ModeSwitch implicitfunctionspecialization}',
  2370. 'type',
  2371. ' TObject = class',
  2372. ' generic procedure {#A}Run<S>(a: S; b: boolean); overload;',
  2373. ' generic procedure {#B}Run<T>(a: T; w: word); overload;',
  2374. ' generic procedure {#C}Run<U>(a: U; b: U); overload;',
  2375. ' end; ',
  2376. 'generic procedure {#A2}TObject.Run<S>(a: S; b: boolean); overload;',
  2377. 'begin',
  2378. ' {@A}Run(1,true);', // non generic take precedence
  2379. ' {@B}Run(2,word(3));', // non generic take precedence
  2380. ' {@C}Run(''foo'',''bar'');',
  2381. 'end;',
  2382. 'generic procedure {#B2}TObject.Run<T>(a: T; w: word); overload;',
  2383. 'begin',
  2384. 'end;',
  2385. 'generic procedure {#C2}TObject.Run<U>(a: U; b: U); overload;',
  2386. 'begin',
  2387. 'end;',
  2388. 'var o: TObject;',
  2389. 'begin',
  2390. ' o.{@A}Run(1,true);', // non generic take precedence
  2391. ' o.{@B}Run(2,word(3));', // non generic take precedence
  2392. ' o.{@C}Run(''foo'',''bar'');',
  2393. '']);
  2394. ConvertProgram;
  2395. CheckSource('TestGenMethod_ImplicitSpec_ObjFPC',
  2396. LinesToStr([ // statements
  2397. 'rtl.createClass(this, "TObject", null, function () {',
  2398. ' this.$init = function () {',
  2399. ' };',
  2400. ' this.$final = function () {',
  2401. ' };',
  2402. ' this.Run$G1 = function (a, b) {',
  2403. ' this.Run$G1(1, true);',
  2404. ' this.Run$1G1(2, 3);',
  2405. ' this.Run$2G1("foo", "bar");',
  2406. ' };',
  2407. ' this.Run$1G1 = function (a, w) {',
  2408. ' };',
  2409. ' this.Run$2G1 = function (a, b) {',
  2410. ' };',
  2411. '});',
  2412. 'this.o = null;',
  2413. '']),
  2414. LinesToStr([ // $mod.$main
  2415. '$mod.o.Run$G1(1, true);',
  2416. '$mod.o.Run$1G1(2, 3);',
  2417. '$mod.o.Run$2G1("foo", "bar");',
  2418. '']));
  2419. end;
  2420. procedure TTestGenerics.TestGenMethod_Delphi;
  2421. begin
  2422. StartProgram(false);
  2423. Add([
  2424. '{$mode delphi}',
  2425. 'type',
  2426. ' TObject = class',
  2427. ' procedure Run<S>;',
  2428. ' end; ',
  2429. 'procedure TObject.Run<S>;',
  2430. 'begin',
  2431. 'end;',
  2432. 'var o: TObject;',
  2433. 'begin',
  2434. ' o.Run<word>;',
  2435. ' o.Run<word>();',
  2436. ' with o do begin',
  2437. ' Run<word>;',
  2438. ' Run<word>();',
  2439. ' end;',
  2440. '']);
  2441. ConvertProgram;
  2442. CheckSource('TestGenMethod_Delphi',
  2443. LinesToStr([ // statements
  2444. 'rtl.createClass(this, "TObject", null, function () {',
  2445. ' this.$init = function () {',
  2446. ' };',
  2447. ' this.$final = function () {',
  2448. ' };',
  2449. ' this.Run$G1 = function () {',
  2450. ' };',
  2451. '});',
  2452. 'this.o = null;',
  2453. '']),
  2454. LinesToStr([ // $mod.$main
  2455. '$mod.o.Run$G1();',
  2456. '$mod.o.Run$G1();',
  2457. 'var $with = $mod.o;',
  2458. '$with.Run$G1();',
  2459. '$with.Run$G1();',
  2460. '']));
  2461. end;
  2462. procedure TTestGenerics.TestGenMethod_Overload_Delphi;
  2463. begin
  2464. StartProgram(false);
  2465. Add([
  2466. '{$mode delphi}',
  2467. 'type',
  2468. ' TObject = class',
  2469. ' procedure Run<S>; overload;',
  2470. ' procedure Run<T>(w: word); overload;',
  2471. ' end; ',
  2472. 'procedure TObject.Run<S>;',
  2473. 'begin',
  2474. 'end;',
  2475. 'procedure TObject.Run<T>(w: word);',
  2476. 'begin',
  2477. 'end;',
  2478. 'var o: TObject;',
  2479. 'begin',
  2480. ' o.Run<word>;',
  2481. ' o.Run<word>();',
  2482. ' o.Run<longint>(3);',
  2483. ' with o do begin',
  2484. ' Run<word>;',
  2485. ' Run<word>();',
  2486. ' Run<longint>(13);',
  2487. ' end;',
  2488. '']);
  2489. ConvertProgram;
  2490. CheckSource('TestGenMethod_Overload_Delphi',
  2491. LinesToStr([ // statements
  2492. 'rtl.createClass(this, "TObject", null, function () {',
  2493. ' this.$init = function () {',
  2494. ' };',
  2495. ' this.$final = function () {',
  2496. ' };',
  2497. ' this.Run$G1 = function () {',
  2498. ' };',
  2499. ' this.Run$1G1 = function (w) {',
  2500. ' };',
  2501. '});',
  2502. 'this.o = null;',
  2503. '']),
  2504. LinesToStr([ // $mod.$main
  2505. '$mod.o.Run$G1();',
  2506. '$mod.o.Run$G1();',
  2507. '$mod.o.Run$1G1(3);',
  2508. 'var $with = $mod.o;',
  2509. '$with.Run$G1();',
  2510. '$with.Run$G1();',
  2511. '$with.Run$1G1(13);',
  2512. '']));
  2513. end;
  2514. procedure TTestGenerics.TestGen_Array_OtherUnit;
  2515. begin
  2516. WithTypeInfo:=true;
  2517. StartProgram(true,[supTObject]);
  2518. AddModuleWithIntfImplSrc('UnitA.pas',
  2519. LinesToStr([
  2520. 'type',
  2521. ' generic TDyn<T> = array of T;',
  2522. ' generic TStatic<T> = array[1..2] of T;',
  2523. '']),
  2524. '');
  2525. AddModuleWithIntfImplSrc('UnitB.pas',
  2526. LinesToStr([
  2527. 'uses UnitA;',
  2528. 'type',
  2529. ' TAnt = class end;',
  2530. ' TAntArray = specialize TDyn<TAnt>;',
  2531. 'procedure Run;',
  2532. '']),
  2533. LinesToStr([
  2534. 'procedure Run;',
  2535. 'begin',
  2536. ' if typeinfo(TAntArray)=nil then ;',
  2537. 'end;',
  2538. '']));
  2539. Add([
  2540. 'uses UnitB;',
  2541. 'begin',
  2542. ' Run;',
  2543. '']);
  2544. ConvertProgram;
  2545. CheckUnit('UnitA.pas',
  2546. LinesToStr([ // statements
  2547. 'rtl.module("UnitA", ["system"], function () {',
  2548. ' var $mod = this;',
  2549. ' this.$rtti.$DynArray("TDyn<UnitB.TAnt>", {});',
  2550. '});']));
  2551. CheckUnit('UnitB.pas',
  2552. LinesToStr([ // statements
  2553. 'rtl.module("UnitB", ["system", "UnitA"], function () {',
  2554. ' var $mod = this;',
  2555. ' rtl.createClass(this, "TAnt", pas.system.TObject, function () {',
  2556. ' });',
  2557. ' this.Run = function () {',
  2558. ' if (pas.UnitA.$rtti["TDyn<UnitB.TAnt>"] === null) ;',
  2559. ' };',
  2560. '});']));
  2561. CheckSource('TestGen_Array_OtherUnit',
  2562. LinesToStr([ // statements
  2563. '$mod.$implcode = function () {',
  2564. ' pas.UnitA.$rtti["TDyn<UnitB.TAnt>"].eltype = pas.UnitB.$rtti["TAnt"];',
  2565. '};',
  2566. '']),
  2567. LinesToStr([ // $mod.$main
  2568. ' pas.UnitB.Run();',
  2569. '']));
  2570. end;
  2571. procedure TTestGenerics.TestGen_ArrayOfUnitImplRec;
  2572. begin
  2573. WithTypeInfo:=true;
  2574. StartProgram(true,[supTObject]);
  2575. AddModuleWithIntfImplSrc('UnitA.pas',
  2576. LinesToStr([
  2577. 'type',
  2578. ' generic TDyn<T> = array of T;',
  2579. ' generic TStatic<T> = array[1..2] of T;',
  2580. '']),
  2581. LinesToStr([
  2582. 'type',
  2583. ' TBird = record',
  2584. ' b: word;',
  2585. ' end;',
  2586. ' TAnt = class end;',
  2587. ' TAntArray = specialize TDyn<TAnt>;',
  2588. 'var',
  2589. ' d: specialize TDyn<TBird>;',
  2590. ' s: specialize TStatic<TBird>;',
  2591. ' p: pointer;',
  2592. 'begin',
  2593. ' d[0].b:=s[1].b;',
  2594. ' s:=s;',
  2595. ' p:=typeinfo(TAntArray);',
  2596. '']));
  2597. Add([
  2598. 'uses UnitA;',
  2599. 'begin',
  2600. '']);
  2601. ConvertProgram;
  2602. CheckUnit('UnitA.pas',
  2603. LinesToStr([ // statements
  2604. 'rtl.module("UnitA", ["system"], function () {',
  2605. ' var $mod = this;',
  2606. ' var $impl = $mod.$impl;',
  2607. ' this.$rtti.$DynArray("TDyn<UnitA.TAnt>", {});',
  2608. ' this.$rtti.$DynArray("TDyn<UnitA.TBird>", {});',
  2609. ' this.TStatic$G1$clone = function (a) {',
  2610. ' var b = [];',
  2611. ' b.length = 2;',
  2612. ' for (var c = 0; c < 2; c++) b[c] = $impl.TBird.$clone(a[c]);',
  2613. ' return b;',
  2614. ' };',
  2615. ' this.$rtti.$StaticArray("TStatic<UnitA.TBird>", {',
  2616. ' dims: [2]',
  2617. ' });',
  2618. ' $mod.$implcode = function () {',
  2619. ' rtl.recNewT($impl, "TBird", function () {',
  2620. ' this.b = 0;',
  2621. ' this.$eq = function (b) {',
  2622. ' return this.b === b.b;',
  2623. ' };',
  2624. ' this.$assign = function (s) {',
  2625. ' this.b = s.b;',
  2626. ' return this;',
  2627. ' };',
  2628. ' var $r = $mod.$rtti.$Record("TBird", {});',
  2629. ' $r.addField("b", rtl.word);',
  2630. ' });',
  2631. ' rtl.createClass($impl, "TAnt", pas.system.TObject, function () {',
  2632. ' });',
  2633. ' $impl.d = [];',
  2634. ' $impl.s = rtl.arraySetLength(null, $impl.TBird, 2);',
  2635. ' $impl.p = null;',
  2636. ' };',
  2637. ' $mod.$init = function () {',
  2638. ' $impl.d[0].b = $impl.s[0].b;',
  2639. ' $impl.s = $mod.TStatic$G1$clone($impl.s);',
  2640. ' $impl.p = $mod.$rtti["TDyn<UnitA.TAnt>"];',
  2641. ' };',
  2642. '}, []);']));
  2643. CheckSource('TestGen_ArrayOfUnitImplRec',
  2644. LinesToStr([ // statements
  2645. '$mod.$implcode = function () {',
  2646. ' pas.UnitA.$rtti["TDyn<UnitA.TAnt>"].eltype = pas.UnitA.$rtti["TAnt"];',
  2647. ' pas.UnitA.$rtti["TDyn<UnitA.TBird>"].eltype = pas.UnitA.$rtti["TBird"];',
  2648. ' pas.UnitA.$rtti["TStatic<UnitA.TBird>"].eltype = pas.UnitA.$rtti["TBird"];',
  2649. '};',
  2650. '']),
  2651. LinesToStr([ // $mod.$main
  2652. '']));
  2653. end;
  2654. procedure TTestGenerics.TestGen_Array_TypecastJSValueResultToArg;
  2655. begin
  2656. StartProgram(false);
  2657. Add([
  2658. '{$mode delphi}',
  2659. 'type',
  2660. ' TArray<T> = array of T;',
  2661. ' TFunc = function: JSValue of object;',
  2662. ' TObject = class',
  2663. ' f: TFunc;',
  2664. ' function Run: jsvalue; virtual; abstract;',
  2665. ' end;',
  2666. 'procedure Sit(Arr: TArray<TObject>);',
  2667. 'begin',
  2668. 'end;',
  2669. 'procedure Fly(o: TObject);',
  2670. 'begin',
  2671. ' Sit(TArray<TObject>(o.f()));',
  2672. ' Sit(TArray<TObject>(o.Run));',
  2673. ' Sit(TArray<TObject>(o.Run()));',
  2674. 'end;',
  2675. 'begin']);
  2676. ConvertProgram;
  2677. CheckSource('TestGen_Array_TypecastJSValueResultToArg',
  2678. LinesToStr([ // statements
  2679. 'rtl.createClass(this, "TObject", null, function () {',
  2680. ' this.$init = function () {',
  2681. ' this.f = null;',
  2682. ' };',
  2683. ' this.$final = function () {',
  2684. ' this.f = undefined;',
  2685. ' };',
  2686. '});',
  2687. 'this.Sit = function (Arr) {',
  2688. '};',
  2689. 'this.Fly = function (o) {',
  2690. ' $mod.Sit(o.f());',
  2691. ' $mod.Sit(o.Run());',
  2692. ' $mod.Sit(o.Run());',
  2693. '};',
  2694. '']),
  2695. LinesToStr([ // $mod.$main
  2696. '']));
  2697. end;
  2698. procedure TTestGenerics.TestGen_ProcType_ProcLocal;
  2699. begin
  2700. StartProgram(false);
  2701. Add([
  2702. 'procedure Fly(w: word);',
  2703. 'begin',
  2704. 'end;',
  2705. 'procedure Run(w: word);',
  2706. 'type generic TProc<T> = procedure(a: T);',
  2707. 'var p: specialize TProc<word>;',
  2708. 'begin',
  2709. ' p:=@Fly;',
  2710. ' p(w);',
  2711. 'end;',
  2712. 'begin',
  2713. 'end.']);
  2714. ConvertProgram;
  2715. CheckSource('TestGen_ProcType_ProcLocal',
  2716. LinesToStr([ // statements
  2717. 'this.Fly = function (w) {',
  2718. '};',
  2719. 'this.Run = function (w) {',
  2720. ' var p = null;',
  2721. ' p = $mod.Fly;',
  2722. ' p(w);',
  2723. '};',
  2724. '']),
  2725. LinesToStr([ // $mod.$main
  2726. '']));
  2727. end;
  2728. procedure TTestGenerics.TestGen_ProcType_Local_RTTI_Fail;
  2729. begin
  2730. WithTypeInfo:=true;
  2731. StartProgram(false);
  2732. Add([
  2733. 'procedure Fly(w: word);',
  2734. 'begin',
  2735. 'end;',
  2736. 'procedure Run(w: word);',
  2737. 'type generic TProc<T> = procedure(a: T);',
  2738. 'var',
  2739. ' p: specialize TProc<word>;',
  2740. ' t: Pointer;',
  2741. 'begin',
  2742. ' p:=@Fly;',
  2743. ' p(w);',
  2744. ' t:=typeinfo(p);',
  2745. 'end;',
  2746. 'begin',
  2747. 'end.']);
  2748. SetExpectedPasResolverError(sSymbolCannotBePublished,nSymbolCannotBePublished);
  2749. ConvertProgram;
  2750. end;
  2751. procedure TTestGenerics.TestGen_ProcType_ParamUnitImpl;
  2752. begin
  2753. WithTypeInfo:=true;
  2754. StartProgram(true,[supTObject]);
  2755. AddModuleWithIntfImplSrc('UnitA.pas',
  2756. LinesToStr([
  2757. 'type',
  2758. ' generic TAnt<T> = function(const a: T): T;',
  2759. '']),
  2760. LinesToStr([
  2761. 'type',
  2762. ' TBird = record',
  2763. ' b: word;',
  2764. ' end;',
  2765. 'var',
  2766. ' f: specialize TAnt<TBird>;',
  2767. ' b: TBird;',
  2768. ' p: pointer;',
  2769. 'begin',
  2770. ' b:=f(b);',
  2771. ' p:=typeinfo(f);',
  2772. '']));
  2773. Add([
  2774. 'uses UnitA;',
  2775. 'begin',
  2776. 'end.']);
  2777. ConvertProgram;
  2778. CheckUnit('UnitA.pas',
  2779. LinesToStr([ // statements
  2780. 'rtl.module("UnitA", ["system"], function () {',
  2781. ' var $mod = this;',
  2782. ' var $impl = $mod.$impl;',
  2783. ' this.$rtti.$ProcVar("TAnt<UnitA.TBird>", {',
  2784. ' init: function () {',
  2785. ' this.procsig = rtl.newTIProcSig([["a", $mod.$rtti["TBird"], 2]], $mod.$rtti["TBird"]);',
  2786. ' }',
  2787. ' });',
  2788. ' $mod.$implcode = function () {',
  2789. ' rtl.recNewT($impl, "TBird", function () {',
  2790. ' this.b = 0;',
  2791. ' this.$eq = function (b) {',
  2792. ' return this.b === b.b;',
  2793. ' };',
  2794. ' this.$assign = function (s) {',
  2795. ' this.b = s.b;',
  2796. ' return this;',
  2797. ' };',
  2798. ' var $r = $mod.$rtti.$Record("TBird", {});',
  2799. ' $r.addField("b", rtl.word);',
  2800. ' });',
  2801. ' $impl.f = null;',
  2802. ' $impl.b = $impl.TBird.$new();',
  2803. ' $impl.p = null;',
  2804. ' };',
  2805. ' $mod.$init = function () {',
  2806. ' $impl.b.$assign($impl.f($impl.b));',
  2807. ' $impl.p = $mod.$rtti["TAnt<UnitA.TBird>"];',
  2808. ' };',
  2809. '}, []);']));
  2810. CheckSource('TestGen_Class_ClassVarRecord_UnitImpl',
  2811. LinesToStr([ // statements
  2812. '$mod.$implcode = function () {',
  2813. ' pas.UnitA.$rtti["TAnt<UnitA.TBird>"].init();',
  2814. '};',
  2815. '']),
  2816. LinesToStr([ // $mod.$main
  2817. '']));
  2818. end;
  2819. procedure TTestGenerics.TestGen_ProcType_TemplateCountOverload_Delphi;
  2820. begin
  2821. WithTypeInfo:=true;
  2822. StartProgram(false);
  2823. Add([
  2824. '{$mode delphi}',
  2825. 'type',
  2826. ' TProc<T> = procedure(a, b: T);',
  2827. ' TProc<S,T> = procedure(a: S; b: T);',
  2828. 'var',
  2829. ' p: TProc<word>;',
  2830. ' q: TProc<char,boolean>;',
  2831. 'procedure Run(x,y: word);',
  2832. 'begin',
  2833. 'end;',
  2834. 'procedure Fly(x: char; y: boolean);',
  2835. 'begin',
  2836. 'end;',
  2837. 'begin',
  2838. ' p:=Run;',
  2839. ' q:=Fly;',
  2840. 'end.']);
  2841. ConvertProgram;
  2842. CheckSource('TestGen_ProcType_TemplateCountOverload_Delphi',
  2843. LinesToStr([ // statements
  2844. 'this.$rtti.$ProcVar("TProc<System.Word>", {',
  2845. ' procsig: rtl.newTIProcSig([["a", rtl.word], ["b", rtl.word]])',
  2846. '});',
  2847. 'this.p = null;',
  2848. 'this.$rtti.$ProcVar("TProc<System.Char,System.Boolean>", {',
  2849. ' procsig: rtl.newTIProcSig([["a", rtl.char], ["b", rtl.boolean]])',
  2850. '});',
  2851. 'this.q = null;',
  2852. 'this.Run = function (x, y) {',
  2853. '};',
  2854. 'this.Fly = function (x, y) {',
  2855. '};',
  2856. '']),
  2857. LinesToStr([ // $mod.$main
  2858. '$mod.p = $mod.Run;',
  2859. '$mod.q = $mod.Fly;',
  2860. '']));
  2861. end;
  2862. Initialization
  2863. RegisterTests([TTestGenerics]);
  2864. end.