tcresolvegenerics.pas 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313
  1. unit tcresolvegenerics;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, testregistry, tcresolver, PasResolveEval, PParser;
  6. type
  7. { TTestResolveGenerics }
  8. TTestResolveGenerics = Class(TCustomTestResolver)
  9. Published
  10. // generic types
  11. procedure TestGen_MissingTemplateFail;
  12. procedure TestGen_VarTypeWithoutSpecializeFail;
  13. procedure TestGen_GenTypeWithWrongParamCountFail;
  14. procedure TestGen_GenericNotFoundFail;
  15. procedure TestGen_SameNameSameParamCountFail;
  16. procedure TestGen_TypeAliasWithoutSpecializeFail;
  17. // constraints
  18. procedure TestGen_ConstraintStringFail;
  19. procedure TestGen_ConstraintMultiClassFail;
  20. procedure TestGen_ConstraintRecordExpectedFail;
  21. procedure TestGen_ConstraintClassRecordFail;
  22. procedure TestGen_ConstraintRecordClassFail;
  23. procedure TestGen_ConstraintArrayFail;
  24. // ToDo: constraint constructor
  25. // ToDo: constraint T:Unit2.TBird
  26. // ToDo: constraint T:Unit2.TGen<word>
  27. procedure TestGen_TemplNameEqTypeNameFail;
  28. procedure TestGen_ConstraintInheritedMissingRecordFail;
  29. procedure TestGen_ConstraintInheritedMissingClassTypeFail;
  30. // generic record
  31. procedure TestGen_RecordLocalNameDuplicateFail;
  32. procedure TestGen_Record;
  33. procedure TestGen_RecordDelphi;
  34. procedure TestGen_RecordNestedSpecialized;
  35. procedure TestGen_Record_SpecializeSelfInsideFail;
  36. procedure TestGen_RecordAnoArray;
  37. // ToDo: unitname.specialize TBird<word>.specialize
  38. procedure TestGen_RecordNestedSpecialize;
  39. // generic class
  40. procedure TestGen_Class;
  41. procedure TestGen_ClassDelphi;
  42. procedure TestGen_ClassForward;
  43. procedure TestGen_ClassForwardConstraints;
  44. procedure TestGen_ClassForwardConstraintNameMismatch;
  45. procedure TestGen_ClassForwardConstraintKeywordMismatch;
  46. procedure TestGen_ClassForwardConstraintTypeMismatch;
  47. procedure TestGen_ClassForward_Circle;
  48. procedure TestGen_Class_RedeclareInUnitImplFail;
  49. procedure TestGen_Class_AnotherInUnitImpl;
  50. procedure TestGen_Class_Method;
  51. procedure TestGen_Class_MethodOverride;
  52. procedure TestGen_Class_MethodDelphi;
  53. procedure TestGen_Class_MethodDelphiTypeParamMissing;
  54. procedure TestGen_Class_MethodImplConstraintFail;
  55. procedure TestGen_Class_MethodImplTypeParamNameMismatch;
  56. procedure TestGen_Class_SpecializeSelfInside;
  57. procedure TestGen_Class_GenAncestor;
  58. procedure TestGen_Class_AncestorSelfFail;
  59. procedure TestGen_ClassOfSpecializeFail;
  60. // ToDo: UnitA.impl uses UnitB.intf uses UnitA.intf, UnitB has specialize of UnitA
  61. procedure TestGen_Class_NestedType;
  62. procedure TestGen_Class_NestedRecord;
  63. procedure TestGen_Class_NestedClass;
  64. procedure TestGen_Class_Enums_NotPropagating;
  65. procedure TestGen_Class_List;
  66. // generic external class
  67. procedure TestGen_ExtClass_Array;
  68. // generic interface
  69. procedure TestGen_ClassInterface;
  70. procedure TestGen_ClassInterface_Method;
  71. // generic array
  72. procedure TestGen_Array;
  73. // ToDo: anonymous array type
  74. // generic procedure type
  75. procedure TestGen_ProcType;
  76. // pointer of generic
  77. procedure TestGen_PointerDirectSpecializeFail;
  78. // ToDo: helpers for generics
  79. // generic functions
  80. procedure TestGen_GenericFunction; // ToDo
  81. // ToDo: generic class method overload <T> <S,T>
  82. // ToDo: procedure TestGen_GenMethod_ClassConstructorFail;
  83. // generic statements
  84. procedure TestGen_LocalVar;
  85. procedure TestGen_Statements;
  86. procedure TestGen_InlineSpecializeExpr;
  87. // ToDo: for-in
  88. procedure TestGen_TryExcept;
  89. // ToDo: call
  90. // ToDo: dot
  91. // ToDo: is as
  92. // ToDo: typecast
  93. // ToTo: nested proc
  94. end;
  95. implementation
  96. { TTestResolveGenerics }
  97. procedure TTestResolveGenerics.TestGen_MissingTemplateFail;
  98. begin
  99. StartProgram(false);
  100. Add([
  101. 'type generic g< > = array of word;',
  102. 'begin',
  103. '']);
  104. CheckParserException('Expected "Identifier"',nParserExpectTokenError);
  105. end;
  106. procedure TTestResolveGenerics.TestGen_VarTypeWithoutSpecializeFail;
  107. begin
  108. StartProgram(false);
  109. Add([
  110. 'type generic TBird<T> = record end;',
  111. 'var b: TBird;',
  112. 'begin',
  113. '']);
  114. CheckResolverException('Generics without specialization cannot be used as a type for a variable',
  115. nGenericsWithoutSpecializationAsType);
  116. end;
  117. procedure TTestResolveGenerics.TestGen_GenTypeWithWrongParamCountFail;
  118. begin
  119. StartProgram(false);
  120. Add([
  121. 'type generic TBird<T> = record end;',
  122. 'var b: TBird<word, byte>;',
  123. 'begin',
  124. '']);
  125. CheckResolverException('identifier not found "TBird<,>"',
  126. nIdentifierNotFound);
  127. end;
  128. procedure TTestResolveGenerics.TestGen_GenericNotFoundFail;
  129. begin
  130. StartProgram(false);
  131. Add([
  132. '{$mode objfpc}',
  133. 'type',
  134. ' TBird = specialize TAnimal<word>;',
  135. 'begin',
  136. '']);
  137. CheckResolverException('identifier not found "TAnimal<>"',
  138. nIdentifierNotFound);
  139. end;
  140. procedure TTestResolveGenerics.TestGen_SameNameSameParamCountFail;
  141. begin
  142. StartProgram(false);
  143. Add([
  144. '{$mode delphi}',
  145. 'type',
  146. ' TBird<S,T> = record w: T; end;',
  147. ' TBird<X,Y> = record f: X; end;',
  148. 'begin',
  149. '']);
  150. CheckResolverException('Duplicate identifier "TBird" at afile.pp(4,8)',
  151. nDuplicateIdentifier);
  152. end;
  153. procedure TTestResolveGenerics.TestGen_TypeAliasWithoutSpecializeFail;
  154. begin
  155. StartProgram(false);
  156. Add([
  157. '{$mode delphi}',
  158. 'type',
  159. ' TBird<T> = record w: T; end;',
  160. ' TBirdAlias = TBird;',
  161. 'begin',
  162. '']);
  163. CheckResolverException('type expected, but TBird<> found',
  164. nXExpectedButYFound);
  165. end;
  166. procedure TTestResolveGenerics.TestGen_ConstraintStringFail;
  167. begin
  168. StartProgram(false);
  169. Add([
  170. 'generic function DoIt<T:string>(a: T): T;',
  171. 'begin',
  172. ' Result:=a;',
  173. 'end;',
  174. 'begin',
  175. '']);
  176. CheckResolverException('"String" is not a valid constraint',
  177. nXIsNotAValidConstraint);
  178. end;
  179. procedure TTestResolveGenerics.TestGen_ConstraintMultiClassFail;
  180. begin
  181. StartProgram(false);
  182. Add([
  183. '{$mode objfpc}',
  184. 'type',
  185. ' TObject = class end;',
  186. ' TBird = class end;',
  187. ' TBear = class end;',
  188. 'generic function DoIt<T: TBird, TBear>(a: T): T;',
  189. 'begin',
  190. ' Result:=a;',
  191. 'end;',
  192. 'begin',
  193. '']);
  194. CheckResolverException('"TBird" constraint and "TBear" constraint cannot be specified together',
  195. nConstraintXAndConstraintYCannotBeTogether);
  196. end;
  197. procedure TTestResolveGenerics.TestGen_ConstraintRecordExpectedFail;
  198. begin
  199. StartProgram(false);
  200. Add([
  201. '{$mode objfpc}',
  202. 'type',
  203. ' generic TBird<T:record> = record v: T; end;',
  204. 'var r: specialize TBird<word>;',
  205. 'begin',
  206. '']);
  207. CheckResolverException('record type expected, but Word found',
  208. nXExpectedButYFound);
  209. end;
  210. procedure TTestResolveGenerics.TestGen_ConstraintClassRecordFail;
  211. begin
  212. StartProgram(false);
  213. Add([
  214. '{$mode objfpc}',
  215. 'type',
  216. ' TRec = record end;',
  217. ' generic TBird<T:class> = record v: T; end;',
  218. 'var r: specialize TBird<TRec>;',
  219. 'begin',
  220. '']);
  221. CheckResolverException('class type expected, but TRec found',
  222. nXExpectedButYFound);
  223. end;
  224. procedure TTestResolveGenerics.TestGen_ConstraintRecordClassFail;
  225. begin
  226. StartProgram(false);
  227. Add([
  228. '{$mode objfpc}',
  229. 'type',
  230. ' TObject = class end;',
  231. ' generic TBird<T:record> = record v: T; end;',
  232. 'var r: specialize TBird<TObject>;',
  233. 'begin',
  234. '']);
  235. CheckResolverException('record type expected, but TObject found',
  236. nXExpectedButYFound);
  237. end;
  238. procedure TTestResolveGenerics.TestGen_ConstraintArrayFail;
  239. begin
  240. StartProgram(false);
  241. Add([
  242. '{$mode objfpc}',
  243. 'type',
  244. ' TArr = array of word;',
  245. ' generic TBird<T:TArr> = record v: T; end;',
  246. 'begin',
  247. '']);
  248. CheckResolverException('"array of Word" is not a valid constraint',
  249. nXIsNotAValidConstraint);
  250. end;
  251. procedure TTestResolveGenerics.TestGen_TemplNameEqTypeNameFail;
  252. begin
  253. StartProgram(false);
  254. Add([
  255. '{$mode objfpc}',
  256. 'type',
  257. ' generic TBird<TBird> = record v: T; end;',
  258. 'var r: specialize TBird<word>;',
  259. 'begin',
  260. '']);
  261. CheckResolverException('Duplicate identifier "TBird" at afile.pp(4,16)',
  262. nDuplicateIdentifier);
  263. end;
  264. procedure TTestResolveGenerics.TestGen_ConstraintInheritedMissingRecordFail;
  265. begin
  266. StartProgram(false);
  267. Add([
  268. '{$mode objfpc}',
  269. 'type',
  270. ' TObject = class end;',
  271. ' generic TBird<T: record> = class v: T; end;',
  272. ' generic TEagle<U> = class(TBird<U>)',
  273. ' end;',
  274. 'begin',
  275. '']);
  276. CheckResolverException('Type parameter "U" is missing constraint "record"',
  277. nTypeParamXIsMissingConstraintY);
  278. end;
  279. procedure TTestResolveGenerics.TestGen_ConstraintInheritedMissingClassTypeFail;
  280. begin
  281. StartProgram(false);
  282. Add([
  283. '{$mode objfpc}',
  284. 'type',
  285. ' TObject = class end;',
  286. ' TAnt = class end;',
  287. ' generic TBird<T: TAnt> = class v: T; end;',
  288. ' generic TEagle<U> = class(TBird<U>)',
  289. ' end;',
  290. 'begin',
  291. '']);
  292. CheckResolverException('Type parameter "U" is not compatible with type "TAnt"',
  293. nTypeParamXIsNotCompatibleWithY);
  294. end;
  295. procedure TTestResolveGenerics.TestGen_RecordLocalNameDuplicateFail;
  296. begin
  297. StartProgram(false);
  298. Add([
  299. '{$mode objfpc}',
  300. 'type',
  301. ' generic TBird<T> = record T: word; end;',
  302. 'begin',
  303. '']);
  304. CheckResolverException('Duplicate identifier "T" at afile.pp(4,18)',
  305. nDuplicateIdentifier);
  306. end;
  307. procedure TTestResolveGenerics.TestGen_Record;
  308. begin
  309. StartProgram(false);
  310. Add([
  311. '{$mode objfpc}',
  312. 'type',
  313. ' {#Typ}T = word;',
  314. ' generic TRec<{#Templ}T> = record',
  315. ' {=Templ}v: T;',
  316. ' end;',
  317. 'var',
  318. ' r: specialize TRec<word>;',
  319. ' {=Typ}w: T;',
  320. 'begin',
  321. ' r.v:=w;',
  322. '']);
  323. ParseProgram;
  324. end;
  325. procedure TTestResolveGenerics.TestGen_RecordDelphi;
  326. begin
  327. StartProgram(false);
  328. Add([
  329. '{$mode delphi}',
  330. 'type',
  331. ' {#Typ}T = word;',
  332. ' TRec<{#Templ}T> = record',
  333. ' {=Templ}v: T;',
  334. ' end;',
  335. 'var',
  336. ' r: TRec<word>;',
  337. ' {=Typ}w: T;',
  338. 'begin',
  339. ' r.v:=w;',
  340. '']);
  341. ParseProgram;
  342. end;
  343. procedure TTestResolveGenerics.TestGen_RecordNestedSpecialized;
  344. begin
  345. StartProgram(false);
  346. Add([
  347. '{$mode objfpc}',
  348. 'type',
  349. ' TObject = class end;',
  350. ' generic TBird<T> = class v: T; end;',
  351. ' generic TFish<T:class> = record v: T; end;',
  352. 'var f: specialize TFish<specialize TBird<word>>;',
  353. 'begin',
  354. '']);
  355. ParseProgram;
  356. end;
  357. procedure TTestResolveGenerics.TestGen_Record_SpecializeSelfInsideFail;
  358. begin
  359. StartProgram(false);
  360. Add([
  361. '{$mode objfpc}',
  362. 'type',
  363. ' generic TBird<T> = record',
  364. ' v: specialize TBird<word>;',
  365. ' end;',
  366. 'begin',
  367. '']);
  368. CheckResolverException('type "TBird<>" is not yet completely defined',
  369. nTypeXIsNotYetCompletelyDefined);
  370. end;
  371. procedure TTestResolveGenerics.TestGen_RecordAnoArray;
  372. begin
  373. StartProgram(false);
  374. Add([
  375. '{$mode objfpc}',
  376. 'type',
  377. ' generic TBird<T> = record v: T; end;',
  378. 'var',
  379. ' a: specialize TBird<array of word>;',
  380. ' b: specialize TBird<array of word>;',
  381. 'begin',
  382. ' a:=b;',
  383. '']);
  384. ParseProgram;
  385. end;
  386. procedure TTestResolveGenerics.TestGen_RecordNestedSpecialize;
  387. begin
  388. StartProgram(false);
  389. Add([
  390. '{$mode objfpc}',
  391. 'type',
  392. ' generic TBird<T> = record v: T; end;',
  393. 'var',
  394. ' a: specialize TBird<specialize TBird<word>>;',
  395. 'begin',
  396. ' a.v.v:=3;',
  397. '']);
  398. ParseProgram;
  399. end;
  400. procedure TTestResolveGenerics.TestGen_Class;
  401. begin
  402. StartProgram(false);
  403. Add([
  404. '{$mode objfpc}',
  405. 'type',
  406. ' TObject = class end;',
  407. ' {#Typ}T = word;',
  408. ' generic TBird<{#Templ}T> = class',
  409. ' {=Templ}v: T;',
  410. ' end;',
  411. 'var',
  412. ' b: specialize TBird<word>;',
  413. ' {=Typ}w: T;',
  414. 'begin',
  415. ' b.v:=w;',
  416. '']);
  417. ParseProgram;
  418. end;
  419. procedure TTestResolveGenerics.TestGen_ClassDelphi;
  420. begin
  421. StartProgram(false);
  422. Add([
  423. '{$mode delphi}',
  424. 'type',
  425. ' TObject = class end;',
  426. ' {#Typ}T = word;',
  427. ' TBird<{#Templ}T> = class',
  428. ' {=Templ}v: T;',
  429. ' end;',
  430. 'var',
  431. ' b: TBird<word>;',
  432. ' {=Typ}w: T;',
  433. 'begin',
  434. ' b.v:=w;',
  435. '']);
  436. ParseProgram;
  437. end;
  438. procedure TTestResolveGenerics.TestGen_ClassForward;
  439. begin
  440. StartProgram(false);
  441. Add([
  442. '{$mode objfpc}',
  443. 'type',
  444. ' TObject = class end;',
  445. ' {#Typ}T = word;',
  446. ' generic TBird<{#Templ_Forward}T> = class;',
  447. ' TRec = record',
  448. ' b: specialize TBird<T>;',
  449. ' end;',
  450. ' generic TBird<{#Templ}T> = class',
  451. ' {=Templ}v: T;',
  452. ' r: TRec;',
  453. ' end;',
  454. 'var',
  455. ' s: TRec;',
  456. ' {=Typ}w: T;',
  457. 'begin',
  458. ' s.b.v:=w;',
  459. ' s.b.r:=s;',
  460. '']);
  461. ParseProgram;
  462. end;
  463. procedure TTestResolveGenerics.TestGen_ClassForwardConstraints;
  464. begin
  465. StartProgram(false);
  466. Add([
  467. '{$mode objfpc}',
  468. 'type',
  469. ' TObject = class end;',
  470. ' TAnt = class end;',
  471. ' generic TBird<T: class; U; V: TAnt> = class;',
  472. ' TRec = record',
  473. ' b: specialize TBird<TAnt,word,TAnt>;',
  474. ' end;',
  475. ' generic TBird<T: class; U; V: TAnt> = class',
  476. ' i: U;',
  477. ' r: TRec;',
  478. ' end;',
  479. 'var',
  480. ' s: TRec;',
  481. ' w: word;',
  482. 'begin',
  483. ' s.b.i:=w;',
  484. ' s.b.r:=s;',
  485. '']);
  486. ParseProgram;
  487. end;
  488. procedure TTestResolveGenerics.TestGen_ClassForwardConstraintNameMismatch;
  489. begin
  490. StartProgram(false);
  491. Add([
  492. '{$mode objfpc}',
  493. 'type',
  494. ' TObject = class end;',
  495. ' generic TBird<T> = class;',
  496. ' generic TBird<U> = class',
  497. ' i: U;',
  498. ' end;',
  499. 'begin',
  500. '']);
  501. CheckResolverException('Declaration of "U" differs from previous declaration at afile.pp(5,18)',
  502. nDeclOfXDiffersFromPrevAtY);
  503. end;
  504. procedure TTestResolveGenerics.TestGen_ClassForwardConstraintKeywordMismatch;
  505. begin
  506. StartProgram(false);
  507. Add([
  508. '{$mode objfpc}',
  509. 'type',
  510. ' TObject = class end;',
  511. ' generic TBird<T: class, constructor> = class;',
  512. ' generic TBird<U: class> = class',
  513. ' i: U;',
  514. ' end;',
  515. 'begin',
  516. '']);
  517. CheckResolverException('Declaration of "U" differs from previous declaration at afile.pp(5,18)',
  518. nDeclOfXDiffersFromPrevAtY);
  519. end;
  520. procedure TTestResolveGenerics.TestGen_ClassForwardConstraintTypeMismatch;
  521. begin
  522. StartProgram(false);
  523. Add([
  524. '{$mode objfpc}',
  525. 'type',
  526. ' TObject = class end;',
  527. ' TAnt = class end;',
  528. ' TFish = class end;',
  529. ' generic TBird<T: TAnt> = class;',
  530. ' generic TBird<T: TFish> = class',
  531. ' i: U;',
  532. ' end;',
  533. 'begin',
  534. '']);
  535. CheckResolverException('Declaration of "T" differs from previous declaration at afile.pp(7,20)',
  536. nDeclOfXDiffersFromPrevAtY);
  537. end;
  538. procedure TTestResolveGenerics.TestGen_ClassForward_Circle;
  539. begin
  540. StartProgram(false);
  541. Add([
  542. '{$mode objfpc}',
  543. 'type',
  544. ' TObject = class end;',
  545. ' generic TAnt<T> = class;',
  546. ' generic TFish<U> = class',
  547. ' private type AliasU = U;',
  548. ' var a: TAnt<AliasU>;',
  549. ' Size: AliasU;',
  550. ' end;',
  551. ' generic TAnt<T> = class',
  552. ' private type AliasT = T;',
  553. ' var f: TFish<AliasT>;',
  554. ' Speed: AliasT;',
  555. ' end;',
  556. 'var',
  557. ' WordFish: specialize TFish<word>;',
  558. ' BoolAnt: specialize TAnt<boolean>;',
  559. ' w: word;',
  560. ' b: boolean;',
  561. 'begin',
  562. ' WordFish.Size:=w;',
  563. ' WordFish.a.Speed:=w;',
  564. ' WordFish.a.f.Size:=w;',
  565. ' BoolAnt.Speed:=b;',
  566. ' BoolAnt.f.Size:=b;',
  567. ' BoolAnt.f.a.Speed:=b;',
  568. '']);
  569. ParseProgram;
  570. end;
  571. procedure TTestResolveGenerics.TestGen_Class_RedeclareInUnitImplFail;
  572. begin
  573. StartUnit(false);
  574. Add([
  575. 'interface',
  576. 'type',
  577. ' TObject = class end;',
  578. ' generic TBird<T> = class v: T; end;',
  579. 'implementation',
  580. 'type generic TBird<T> = record v: T; end;',
  581. '']);
  582. CheckResolverException('Duplicate identifier "TBird" at afile.pp(5,16)',
  583. nDuplicateIdentifier);
  584. end;
  585. procedure TTestResolveGenerics.TestGen_Class_AnotherInUnitImpl;
  586. begin
  587. StartUnit(false);
  588. Add([
  589. 'interface',
  590. 'type',
  591. ' TObject = class end;',
  592. ' generic TBird<T> = class v: T; end;',
  593. 'implementation',
  594. 'type generic TBird<T,U> = record x: T; y: U; end;',
  595. '']);
  596. ParseUnit;
  597. end;
  598. procedure TTestResolveGenerics.TestGen_Class_Method;
  599. begin
  600. StartProgram(false);
  601. Add([
  602. '{$mode objfpc}',
  603. 'type',
  604. ' TObject = class end;',
  605. ' {#Typ}T = word;',
  606. ' generic TBird<{#Templ}T> = class',
  607. ' function Fly(p:T): T; virtual; abstract;',
  608. ' function Run(p:T): T;',
  609. ' end;',
  610. 'function TBird.Run(p:T): T;',
  611. 'begin',
  612. 'end;',
  613. 'var',
  614. ' b: specialize TBird<word>;',
  615. ' {=Typ}w: T;',
  616. 'begin',
  617. ' w:=b.Fly(w);',
  618. ' w:=b.Run(w);',
  619. '']);
  620. ParseProgram;
  621. end;
  622. procedure TTestResolveGenerics.TestGen_Class_MethodOverride;
  623. begin
  624. StartProgram(false);
  625. Add([
  626. '{$mode objfpc}',
  627. 'type',
  628. ' TObject = class end;',
  629. ' generic TBird<T> = class',
  630. ' function Fly(p:T): T; virtual; abstract;',
  631. ' end;',
  632. ' generic TEagle<S> = class(specialize TBird<S>)',
  633. ' function Fly(p:S): S; override;',
  634. ' end;',
  635. 'function TEagle.Fly(p:S): S;',
  636. 'begin',
  637. 'end;',
  638. 'var',
  639. ' e: specialize TEagle<word>;',
  640. ' w: word;',
  641. 'begin',
  642. ' w:=e.Fly(w);',
  643. '']);
  644. ParseProgram;
  645. end;
  646. procedure TTestResolveGenerics.TestGen_Class_MethodDelphi;
  647. begin
  648. StartProgram(false);
  649. Add([
  650. '{$mode delphi}',
  651. 'type',
  652. ' TObject = class end;',
  653. ' {#Typ}T = word;',
  654. ' TBird<{#Templ}T> = class',
  655. ' function Fly(p:T): T; virtual; abstract;',
  656. ' function Run(p:T): T;',
  657. ' end;',
  658. 'function TBird<T>.Run(p:T): T;',
  659. 'begin',
  660. 'end;',
  661. 'var',
  662. ' b: TBird<word>;',
  663. ' {=Typ}w: T;',
  664. 'begin',
  665. ' w:=b.Fly(w);',
  666. ' w:=b.Run(w);',
  667. '']);
  668. ParseProgram;
  669. end;
  670. procedure TTestResolveGenerics.TestGen_Class_MethodDelphiTypeParamMissing;
  671. begin
  672. StartProgram(false);
  673. Add([
  674. '{$mode delphi}',
  675. 'type',
  676. ' TObject = class end;',
  677. ' TBird<T> = class',
  678. ' function Run(p:T): T;',
  679. ' end;',
  680. 'function TBird.Run(p:T): T;',
  681. 'begin',
  682. 'end;',
  683. 'begin',
  684. '']);
  685. CheckResolverException('TBird<> expected, but TBird found',nXExpectedButYFound);
  686. end;
  687. procedure TTestResolveGenerics.TestGen_Class_MethodImplConstraintFail;
  688. begin
  689. StartProgram(false);
  690. Add([
  691. '{$mode delphi}',
  692. 'type',
  693. ' TObject = class end;',
  694. ' TBird<T: record> = class',
  695. ' function Run(p:T): T;',
  696. ' end;',
  697. 'function TBird<T: record>.Run(p:T): T;',
  698. 'begin',
  699. 'end;',
  700. 'begin',
  701. '']);
  702. CheckResolverException('T cannot have parameters',nXCannotHaveParameters);
  703. end;
  704. procedure TTestResolveGenerics.TestGen_Class_MethodImplTypeParamNameMismatch;
  705. begin
  706. StartProgram(false);
  707. Add([
  708. '{$mode delphi}',
  709. 'type',
  710. ' TObject = class end;',
  711. ' TBird<T> = class',
  712. ' procedure DoIt;',
  713. ' end;',
  714. 'procedure TBird<S>.DoIt;',
  715. 'begin',
  716. 'end;',
  717. 'begin',
  718. '']);
  719. CheckResolverException('T expected, but S found',nXExpectedButYFound);
  720. end;
  721. procedure TTestResolveGenerics.TestGen_Class_SpecializeSelfInside;
  722. begin
  723. StartProgram(false);
  724. Add([
  725. '{$mode objfpc}',
  726. 'type',
  727. ' TObject = class end;',
  728. ' generic TBird<T> = class',
  729. ' e: T;',
  730. ' v: TBird<boolean>;',
  731. ' end;',
  732. 'var',
  733. ' b: specialize TBird<word>;',
  734. ' w: word;',
  735. 'begin',
  736. ' b.e:=w;',
  737. ' if b.v.e then ;',
  738. '']);
  739. ParseProgram;
  740. end;
  741. procedure TTestResolveGenerics.TestGen_Class_GenAncestor;
  742. begin
  743. StartProgram(false);
  744. Add([
  745. '{$mode objfpc}',
  746. 'type',
  747. ' TObject = class end;',
  748. ' generic TBird<T> = class',
  749. ' i: T;',
  750. ' end;',
  751. ' generic TEagle<T> = class(TBird<T>)',
  752. ' j: T;',
  753. ' end;',
  754. 'var',
  755. ' e: specialize TEagle<word>;',
  756. 'begin',
  757. ' e.i:=e.j;',
  758. '']);
  759. ParseProgram;
  760. end;
  761. procedure TTestResolveGenerics.TestGen_Class_AncestorSelfFail;
  762. begin
  763. StartProgram(false);
  764. Add([
  765. '{$mode objfpc}',
  766. 'type',
  767. ' TObject = class end;',
  768. ' generic TBird<T> = class(TBird<word>)',
  769. ' e: T;',
  770. ' end;',
  771. 'var',
  772. ' b: specialize TBird<word>;',
  773. 'begin',
  774. '']);
  775. CheckResolverException('type "TBird<>" is not yet completely defined',nTypeXIsNotYetCompletelyDefined);
  776. end;
  777. procedure TTestResolveGenerics.TestGen_ClassOfSpecializeFail;
  778. begin
  779. StartProgram(false);
  780. Add([
  781. '{$mode objfpc}',
  782. 'type',
  783. ' TObject = class end;',
  784. ' generic TBird<T> = class',
  785. ' e: T;',
  786. ' end;',
  787. ' TBirdClass = class of specialize TBird<word>;',
  788. 'begin',
  789. '']);
  790. CheckParserException('Expected "Identifier" at token "specialize" in file afile.pp at line 8 column 25',nParserExpectTokenError);
  791. end;
  792. procedure TTestResolveGenerics.TestGen_Class_NestedType;
  793. begin
  794. StartProgram(false);
  795. Add([
  796. '{$mode objfpc}',
  797. 'type',
  798. ' TObject = class end;',
  799. ' generic TBird<T> = class',
  800. ' public type',
  801. ' TArrayEvent = reference to procedure(El: T);',
  802. ' public',
  803. ' p: TArrayEvent;',
  804. ' end;',
  805. ' TBirdWord = specialize TBird<word>;',
  806. 'var',
  807. ' b: TBirdWord;',
  808. 'begin',
  809. ' b.p:=procedure(El: word) begin end;']);
  810. ParseProgram;
  811. end;
  812. procedure TTestResolveGenerics.TestGen_Class_NestedRecord;
  813. begin
  814. StartProgram(false);
  815. Add([
  816. '{$mode objfpc}',
  817. '{$modeswitch advancedrecords}',
  818. 'type',
  819. ' TObject = class end;',
  820. ' generic TBird<T> = class',
  821. ' public type TWing = record',
  822. ' s: T;',
  823. ' function GetIt: T;',
  824. ' end;',
  825. ' public',
  826. ' w: TWing;',
  827. ' end;',
  828. ' TBirdWord = specialize TBird<word>;',
  829. 'function TBird.TWing.GetIt: T;',
  830. 'begin',
  831. 'end;',
  832. 'var',
  833. ' b: TBirdWord;',
  834. ' i: word;',
  835. 'begin',
  836. ' b.w.s:=i;',
  837. ' i:=b.w.GetIt;',
  838. '']);
  839. ParseProgram;
  840. end;
  841. procedure TTestResolveGenerics.TestGen_Class_NestedClass;
  842. begin
  843. StartProgram(false);
  844. Add([
  845. '{$mode objfpc}',
  846. 'type',
  847. ' TObject = class end;',
  848. ' generic TBird<T> = class',
  849. ' public type TWing = class',
  850. ' s: T;',
  851. ' function GetIt: T;',
  852. ' end;',
  853. ' public',
  854. ' w: TWing;',
  855. ' end;',
  856. ' TBirdWord = specialize TBird<word>;',
  857. 'function TBird.TWing.GetIt: T;',
  858. 'begin',
  859. 'end;',
  860. 'var',
  861. ' b: TBirdWord;',
  862. ' i: word;',
  863. 'begin',
  864. ' b.w.s:=3;',
  865. ' i:=b.w.GetIt;',
  866. '']);
  867. ParseProgram;
  868. end;
  869. procedure TTestResolveGenerics.TestGen_Class_Enums_NotPropagating;
  870. begin
  871. StartProgram(false);
  872. Add([
  873. '{$mode objfpc}',
  874. 'type',
  875. ' TObject = class end;',
  876. ' generic TBird<T> = class',
  877. ' public type',
  878. ' TEnum = (red, blue);',
  879. ' const',
  880. ' e = blue;',
  881. ' end;',
  882. 'const',
  883. ' r = red;',
  884. 'begin']);
  885. CheckResolverException('identifier not found "red"',nIdentifierNotFound);
  886. end;
  887. procedure TTestResolveGenerics.TestGen_Class_List;
  888. begin
  889. StartProgram(false);
  890. Add([
  891. '{$mode objfpc}',
  892. 'type',
  893. ' TObject = class end;',
  894. ' generic TList<T> = class',
  895. ' strict private',
  896. ' FItems: array of T;',
  897. ' function GetItems(Index: longint): T;',
  898. ' procedure SetItems(Index: longint; Value: T);',
  899. ' public',
  900. ' procedure Alter(w: T);',
  901. ' property Items[Index: longint]: T read GetItems write SetItems; default;',
  902. ' end;',
  903. ' TWordList = specialize TList<word>;',
  904. 'function TList.GetItems(Index: longint): T;',
  905. 'begin',
  906. ' Result:=FItems[Index];',
  907. 'end;',
  908. 'procedure TList.SetItems(Index: longint; Value: T);',
  909. 'begin',
  910. ' FItems[Index]:=Value;',
  911. 'end;',
  912. 'procedure TList.Alter(w: T);',
  913. 'begin',
  914. ' SetLength(FItems,length(FItems)+1);',
  915. ' Insert(w,FItems,2);',
  916. ' Delete(FItems,2,3);',
  917. 'end;',
  918. 'var l: TWordList;',
  919. ' w: word;',
  920. 'begin',
  921. ' l[1]:=w;',
  922. ' w:=l[2];']);
  923. ParseProgram;
  924. end;
  925. procedure TTestResolveGenerics.TestGen_ExtClass_Array;
  926. begin
  927. StartProgram(false);
  928. Add([
  929. '{$mode delphi}',
  930. '{$ModeSwitch externalclass}',
  931. 'type',
  932. ' NativeInt = longint;',
  933. ' TJSGenArray<T> = Class external name ''Array''',
  934. ' private',
  935. ' function GetElements(Index: NativeInt): T; external name ''[]'';',
  936. ' procedure SetElements(Index: NativeInt; const AValue: T); external name ''[]'';',
  937. ' public',
  938. ' type TSelfType = TJSGenArray<T>;',
  939. ' TArrayEvent = reference to function(El: T; Arr: TSelfType): Boolean;',
  940. ' TArrayCallback = TArrayEvent;',
  941. ' public',
  942. ' FLength : NativeInt; external name ''length'';',
  943. ' constructor new; overload;',
  944. ' constructor new(aLength : NativeInt); overload;',
  945. ' class function _of() : TSelfType; varargs; external name ''of'';',
  946. ' function every(const aCallback: TArrayCallBack): boolean; overload;',
  947. ' function fill(aValue : T) : TSelfType; overload;',
  948. ' function fill(aValue : T; aStartIndex : NativeInt) : TSelfType; overload;',
  949. ' function fill(aValue : T; aStartIndex,aEndIndex : NativeInt) : TSelfType; overload;',
  950. ' property Length : NativeInt Read FLength Write FLength;',
  951. ' property Elements[Index: NativeInt]: T read GetElements write SetElements; default;',
  952. ' end;',
  953. ' TJSWordArray = TJSGenArray<word>;',
  954. 'var',
  955. ' wa: TJSWordArray;',
  956. ' w: word;',
  957. 'begin',
  958. ' wa:=TJSWordArray.new;',
  959. ' wa:=TJSWordArray.new(3);',
  960. ' wa:=TJSWordArray._of(4,5);',
  961. ' wa:=wa.fill(7);',
  962. ' wa:=wa.fill(7,8,9);',
  963. ' w:=wa.length;',
  964. ' wa.length:=10;',
  965. ' wa[11]:=w;',
  966. ' w:=wa[12];',
  967. ' wa.every(function(El: word; Arr: TJSWordArray): Boolean',
  968. ' begin',
  969. ' end',
  970. ' );',
  971. '']);
  972. ParseProgram;
  973. end;
  974. procedure TTestResolveGenerics.TestGen_ClassInterface;
  975. begin
  976. StartProgram(false);
  977. Add([
  978. 'type',
  979. ' {$interfaces corba}',
  980. ' generic ICorbaIntf<T> = interface',
  981. ' procedure Fly(a: T);',
  982. ' end;',
  983. ' {$interfaces com}',
  984. ' IUnknown = interface',
  985. ' end;',
  986. ' IInterface = IUnknown;',
  987. ' generic IComIntf<T> = interface',
  988. ' procedure Run(b: T);',
  989. ' end;',
  990. 'begin']);
  991. ParseProgram;
  992. end;
  993. procedure TTestResolveGenerics.TestGen_ClassInterface_Method;
  994. begin
  995. StartProgram(false);
  996. Add([
  997. 'type',
  998. ' {$interfaces corba}',
  999. ' generic IBird<T> = interface',
  1000. ' procedure Fly(a: T);',
  1001. ' end;',
  1002. ' TObject = class end;',
  1003. ' generic TBird<U> = class(IBird<U>)',
  1004. ' procedure Fly(a: U);',
  1005. ' end;',
  1006. 'procedure TBird.Fly(a: U);',
  1007. 'begin',
  1008. 'end;',
  1009. 'var b: specialize IBird<word>;',
  1010. 'begin',
  1011. ' b.Fly(3);']);
  1012. ParseProgram;
  1013. end;
  1014. procedure TTestResolveGenerics.TestGen_Array;
  1015. begin
  1016. StartProgram(false);
  1017. Add([
  1018. 'type',
  1019. ' generic TArray<T> = array of T;',
  1020. ' TWordArray = specialize TArray<word>;',
  1021. 'var',
  1022. ' a: specialize TArray<word>;',
  1023. ' b: TWordArray;',
  1024. ' w: word;',
  1025. 'begin',
  1026. ' a[1]:=2;',
  1027. ' b[2]:=a[3]+b[4];',
  1028. ' a:=b;',
  1029. ' b:=a;',
  1030. ' SetLength(a,5);',
  1031. ' SetLength(b,6);',
  1032. '']);
  1033. ParseProgram;
  1034. end;
  1035. procedure TTestResolveGenerics.TestGen_ProcType;
  1036. begin
  1037. StartProgram(false);
  1038. Add([
  1039. 'type',
  1040. ' generic TFunc<T> = function(v: T): T;',
  1041. ' TWordFunc = specialize TFunc<word>;',
  1042. 'function GetIt(w: word): word;',
  1043. 'begin',
  1044. 'end;',
  1045. 'var',
  1046. ' a: specialize TFunc<word>;',
  1047. ' b: TWordFunc;',
  1048. ' w: word;',
  1049. 'begin',
  1050. ' a:=nil;',
  1051. ' b:=nil;',
  1052. ' a:=b;',
  1053. ' b:=a;',
  1054. ' w:=a(w);',
  1055. ' w:=b(w);',
  1056. ' a:=@GetIt;',
  1057. ' b:=@GetIt;',
  1058. '']);
  1059. ParseProgram;
  1060. end;
  1061. procedure TTestResolveGenerics.TestGen_PointerDirectSpecializeFail;
  1062. begin
  1063. StartProgram(false);
  1064. Add([
  1065. 'type',
  1066. ' generic TRec<T> = record v: T; end;',
  1067. ' PRec = ^specialize TRec<word>;',
  1068. 'begin',
  1069. '']);
  1070. CheckParserException('Expected "Identifier" at token "specialize" in file afile.pp at line 4 column 11',nParserExpectTokenError);
  1071. end;
  1072. procedure TTestResolveGenerics.TestGen_GenericFunction;
  1073. begin
  1074. exit;
  1075. StartProgram(false);
  1076. Add([
  1077. 'generic function DoIt<T>(a: T): T;',
  1078. 'var i: T;',
  1079. 'begin',
  1080. ' a:=i;',
  1081. ' Result:=a;',
  1082. 'end;',
  1083. 'var w: word;',
  1084. 'begin',
  1085. //' w:=DoIt<word>(3);',
  1086. '']);
  1087. ParseProgram;
  1088. end;
  1089. procedure TTestResolveGenerics.TestGen_LocalVar;
  1090. begin
  1091. StartProgram(false);
  1092. Add([
  1093. '{$mode objfpc}',
  1094. 'type',
  1095. ' TObject = class end;',
  1096. ' generic TBird<{#Templ}T> = class',
  1097. ' function Fly(p:T): T;',
  1098. ' end;',
  1099. 'function TBird.Fly(p:T): T;',
  1100. 'var l: T;',
  1101. 'begin',
  1102. ' l:=p;',
  1103. ' p:=l;',
  1104. ' Result:=p;',
  1105. ' Result:=l;',
  1106. ' l:=Result;',
  1107. 'end;',
  1108. 'var',
  1109. ' b: specialize TBird<word>;',
  1110. ' w: word;',
  1111. 'begin',
  1112. ' w:=b.Fly(w);',
  1113. '']);
  1114. ParseProgram;
  1115. end;
  1116. procedure TTestResolveGenerics.TestGen_Statements;
  1117. begin
  1118. StartProgram(false);
  1119. Add([
  1120. '{$mode objfpc}',
  1121. 'type',
  1122. ' TObject = class end;',
  1123. ' generic TBird<{#Templ}T> = class',
  1124. ' function Fly(p:T): T;',
  1125. ' end;',
  1126. 'function TBird.Fly(p:T): T;',
  1127. 'var',
  1128. ' v1,v2,v3:T;',
  1129. 'begin',
  1130. ' v1:=1;',
  1131. ' v2:=v1+v1*v1+v1 div p;',
  1132. ' v3:=-v1;',
  1133. ' repeat',
  1134. ' v1:=v1+1;',
  1135. ' until v1>=5;',
  1136. ' while v1>=0 do',
  1137. ' v1:=v1-v2;',
  1138. ' for v1:=v2 to v3 do v2:=v1;',
  1139. ' if v1<v2 then v3:=v1 else v3:=v2;',
  1140. ' if v1<v2 then else ;',
  1141. ' case v1 of',
  1142. ' 1: v3:=3;',
  1143. ' end;',
  1144. 'end;',
  1145. 'var',
  1146. ' b: specialize TBird<word>;',
  1147. 'begin',
  1148. ' b.Fly(2);',
  1149. '']);
  1150. ParseProgram;
  1151. end;
  1152. procedure TTestResolveGenerics.TestGen_InlineSpecializeExpr;
  1153. begin
  1154. StartProgram(false);
  1155. Add([
  1156. '{$mode objfpc}',
  1157. 'type',
  1158. ' TObject = class end;',
  1159. ' generic TBird<T> = class',
  1160. ' constructor Create;',
  1161. ' end;',
  1162. ' generic TAnt<U> = class',
  1163. ' constructor Create;',
  1164. ' end;',
  1165. 'constructor TBird.Create;',
  1166. 'var',
  1167. ' a: TAnt<T>;',
  1168. ' b: TAnt<word>;',
  1169. 'begin',
  1170. ' a:=TAnt<T>.create;',
  1171. ' b:=TAnt<word>.create;',
  1172. 'end;',
  1173. 'constructor TAnt.Create;',
  1174. 'var',
  1175. ' i: TBird<U>;',
  1176. ' j: TBird<word>;',
  1177. ' k: TAnt<U>;',
  1178. 'begin',
  1179. ' i:=TBird<U>.create;',
  1180. ' j:=TBird<word>.create;',
  1181. ' k:=TAnt<U>.create;',
  1182. 'end;',
  1183. 'var a: TAnt<word>;',
  1184. 'begin',
  1185. ' a:=TAnt<word>.create;',
  1186. '']);
  1187. ParseProgram;
  1188. end;
  1189. procedure TTestResolveGenerics.TestGen_TryExcept;
  1190. begin
  1191. StartProgram(false);
  1192. Add([
  1193. '{$mode objfpc}',
  1194. 'type',
  1195. ' TObject = class end;',
  1196. ' generic TBird<{#Templ}T> = class',
  1197. ' function Fly(p:T): T;',
  1198. ' end;',
  1199. ' Exception = class',
  1200. ' end;',
  1201. ' generic EMsg<T> = class',
  1202. ' Msg: T;',
  1203. ' end;',
  1204. 'function TBird.Fly(p:T): T;',
  1205. 'var',
  1206. ' v1,v2,v3:T;',
  1207. 'begin',
  1208. ' try',
  1209. ' finally',
  1210. ' end;',
  1211. ' try',
  1212. ' v1:=v2;',
  1213. ' finally',
  1214. ' v2:=v1;',
  1215. ' end;',
  1216. ' try',
  1217. ' except',
  1218. ' on Exception do ;',
  1219. ' on E: Exception do ;',
  1220. ' on E: EMsg<boolean> do E.Msg:=true;',
  1221. ' on E: EMsg<T> do E.Msg:=1;',
  1222. ' end;',
  1223. 'end;',
  1224. 'var',
  1225. ' b: specialize TBird<word>;',
  1226. 'begin',
  1227. ' b.Fly(2);',
  1228. '']);
  1229. ParseProgram;
  1230. end;
  1231. initialization
  1232. RegisterTests([TTestResolveGenerics]);
  1233. end.