tcgenerics.pas 77 KB

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