tcresolvegenerics.pas 27 KB

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