tcgenerics.pp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. unit tcgenerics;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, pastree, testregistry, pscanner, tctypeparser;
  6. Type
  7. { TTestGenerics }
  8. TTestGenerics = Class(TBaseTestTypeParser)
  9. Published
  10. Procedure TestObjectGenerics;
  11. Procedure TestRecordGenerics;
  12. Procedure TestArrayGenerics;
  13. Procedure TestGenericConstraint;
  14. Procedure TestDeclarationConstraint;
  15. Procedure TestSpecializationDelphi;
  16. Procedure TestDeclarationDelphi;
  17. Procedure TestDeclarationDelphiSpecialize;
  18. Procedure TestDeclarationFPC;
  19. Procedure TestMethodImplementation;
  20. Procedure TestInlineSpecializationInArgument;
  21. Procedure TestSpecializeNested;
  22. Procedure TestInlineSpecializeInStatement;
  23. Procedure TestGenericFunction; // ToDo
  24. end;
  25. implementation
  26. procedure TTestGenerics.TestObjectGenerics;
  27. begin
  28. Add([
  29. 'Type',
  30. 'Generic TSomeClass<T> = Object',
  31. ' b : T;',
  32. 'end;',
  33. '']);
  34. ParseDeclarations;
  35. end;
  36. procedure TTestGenerics.TestRecordGenerics;
  37. begin
  38. Add([
  39. 'Type',
  40. ' Generic TSome<T> = Record',
  41. ' b : T;',
  42. ' end;',
  43. '']);
  44. ParseDeclarations;
  45. end;
  46. procedure TTestGenerics.TestArrayGenerics;
  47. begin
  48. Add([
  49. 'Type',
  50. ' Generic TSome<T> = array of T;',
  51. '']);
  52. ParseDeclarations;
  53. end;
  54. procedure TTestGenerics.TestGenericConstraint;
  55. begin
  56. Add([
  57. 'Type',
  58. 'Generic TSomeClass<T: TObject> = class',
  59. ' b : T;',
  60. 'end;',
  61. '']);
  62. ParseDeclarations;
  63. end;
  64. procedure TTestGenerics.TestDeclarationConstraint;
  65. Var
  66. T : TPasClassType;
  67. begin
  68. Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
  69. Source.Add('Type');
  70. Source.Add(' TSomeClass<T: T2> = Class(TObject)');
  71. Source.Add(' b : T;');
  72. Source.Add('end;');
  73. ParseDeclarations;
  74. AssertNotNull('have generic definition',Declarations.Classes);
  75. AssertEquals('have generic definition',1,Declarations.Classes.Count);
  76. AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
  77. T:=TPasClassType(Declarations.Classes[0]);
  78. AssertNotNull('have generic templates',T.GenericTemplateTypes);
  79. AssertEquals('1 template types',1,T.GenericTemplateTypes.Count);
  80. AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
  81. AssertEquals('Type constraint is recorded','T2',TPasGenericTemplateType(T.GenericTemplateTypes[0]).TypeConstraint);
  82. end;
  83. procedure TTestGenerics.TestSpecializationDelphi;
  84. begin
  85. ParseType('TFPGList<integer>',TPasSpecializeType,'');
  86. end;
  87. procedure TTestGenerics.TestDeclarationDelphi;
  88. Var
  89. T : TPasClassType;
  90. begin
  91. Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
  92. Source.Add('Type');
  93. Source.Add(' TSomeClass<T,T2> = Class(TObject)');
  94. Source.Add(' b : T;');
  95. Source.Add(' b2 : T2;');
  96. Source.Add('end;');
  97. ParseDeclarations;
  98. AssertNotNull('have generic definition',Declarations.Classes);
  99. AssertEquals('have generic definition',1,Declarations.Classes.Count);
  100. AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
  101. T:=TPasClassType(Declarations.Classes[0]);
  102. AssertNotNull('have generic templates',T.GenericTemplateTypes);
  103. AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
  104. AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
  105. AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
  106. end;
  107. procedure TTestGenerics.TestDeclarationDelphiSpecialize;
  108. Var
  109. T : TPasClassType;
  110. begin
  111. Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
  112. Source.Add('Type');
  113. Source.Add(' TSomeClass<T,T2> = Class(TSomeGeneric<Integer,Integer>)');
  114. Source.Add(' b : T;');
  115. Source.Add(' b2 : T2;');
  116. Source.Add('end;');
  117. ParseDeclarations;
  118. AssertNotNull('have generic definition',Declarations.Classes);
  119. AssertEquals('have generic definition',1,Declarations.Classes.Count);
  120. AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
  121. T:=TPasClassType(Declarations.Classes[0]);
  122. AssertEquals('Name is correct','TSomeClass',T.Name);
  123. AssertNotNull('have generic templates',T.GenericTemplateTypes);
  124. AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
  125. AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
  126. AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
  127. end;
  128. procedure TTestGenerics.TestDeclarationFPC;
  129. Var
  130. T : TPasClassType;
  131. begin
  132. Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches;
  133. Source.Add('Type');
  134. Source.Add(' TSomeClass<T;T2> = Class(TObject)');
  135. Source.Add(' b : T;');
  136. Source.Add(' b2 : T2;');
  137. Source.Add('end;');
  138. ParseDeclarations;
  139. AssertNotNull('have generic definition',Declarations.Classes);
  140. AssertEquals('have generic definition',1,Declarations.Classes.Count);
  141. AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
  142. T:=TPasClassType(Declarations.Classes[0]);
  143. AssertNotNull('have generic templates',T.GenericTemplateTypes);
  144. AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
  145. AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
  146. AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
  147. end;
  148. procedure TTestGenerics.TestMethodImplementation;
  149. begin
  150. With source do
  151. begin
  152. Add('unit afile;');
  153. Add('{$MODE DELPHI}');
  154. Add('interface');
  155. Add('type');
  156. Add(' TTest<T> = object');
  157. Add(' procedure foo(v:T);');
  158. Add(' end;');
  159. Add('implementation');
  160. Add('procedure TTest<T>.foo;');
  161. Add('begin');
  162. Add('end;');
  163. end;
  164. ParseModule;
  165. end;
  166. procedure TTestGenerics.TestInlineSpecializationInArgument;
  167. begin
  168. With source do
  169. begin
  170. Add('unit afile;');
  171. Add('{$MODE DELPHI}');
  172. Add('interface');
  173. Add('type');
  174. Add(' TFoo=class');
  175. Add(' procedure foo(var Node:TSomeGeneric<TBoundingBox>;const index:Integer);');
  176. Add(' end;');
  177. Add('implementation');
  178. end;
  179. ParseModule;
  180. end;
  181. procedure TTestGenerics.TestSpecializeNested;
  182. begin
  183. Add([
  184. 'Type',
  185. ' generic TSomeClass<A,B> = class(specialize TOther<A,specialize TAnother<B>>) end;',
  186. '']);
  187. ParseDeclarations;
  188. end;
  189. procedure TTestGenerics.TestInlineSpecializeInStatement;
  190. begin
  191. Add([
  192. 'begin',
  193. ' vec:=TVector<double>.create;',
  194. ' b:=a<b;',
  195. ' t:=a<b.c<d,e.f>>;',
  196. '']);
  197. ParseModule;
  198. end;
  199. procedure TTestGenerics.TestGenericFunction;
  200. begin
  201. Add([
  202. 'generic function IfThen<T>(val:boolean;const iftrue:T; const iffalse:T) :T; inline; overload;',
  203. 'begin',
  204. 'end;',
  205. 'begin',
  206. //' specialize IfThen<word>(true,2,3);',
  207. '']);
  208. ParseModule;
  209. end;
  210. initialization
  211. RegisterTest(TTestGenerics);
  212. end.