tcgenerics.pas 76 KB

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