tcresolvegenerics.pas 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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 functions
  11. procedure TestGen_GenericFunction; // ToDo
  12. // generic types
  13. procedure TestGen_MissingTemplateFail;
  14. procedure TestGen_VarTypeWithoutSpecializeFail;
  15. procedure TestGen_ConstraintStringFail;
  16. procedure TestGen_ConstraintMultiClassFail;
  17. procedure TestGen_ConstraintRecordExpectedFail;
  18. // ToDo: constraints mismatch: TAnt<T:record>; TBird<T:Class> = record v: TAnt<T> end Fail
  19. // ToDo: constraint keyword record
  20. // ToDo: constraint keyword class, constructor, class+constructor
  21. // ToDo: constraint T:Unit2.TBird
  22. // ToDo: constraint T:Unit2.TGen<word>
  23. procedure TestGen_GenericNotFoundFail;
  24. procedure TestGen_RecordLocalNameDuplicateFail;
  25. procedure TestGen_Record; // ToDo
  26. // ToDo: type TBird<T> = record end; var b: TBird<word>.T; fail
  27. // ToDo: enums within generic
  28. // ToDo: generic class
  29. // ToDo: generic class forward
  30. // ToDo: ancestor cycle: TBird<T> = class(TBird<word>) fail
  31. // ToDo: class-of
  32. // ToDo: UnitA.impl uses UnitB.intf uses UnitA.intf, UnitB has specialize of UnitA
  33. // ToDo: generic interface
  34. // ToDo: generic array
  35. // ToDo: generic procedure type
  36. // ToDo: pointer of generic
  37. // ToDo: generic helpers
  38. end;
  39. implementation
  40. { TTestResolveGenerics }
  41. procedure TTestResolveGenerics.TestGen_GenericFunction;
  42. begin
  43. StartProgram(false);
  44. Add([
  45. 'generic function DoIt<T>(a: T): T;',
  46. 'var i: T;',
  47. 'begin',
  48. ' a:=i;',
  49. ' Result:=a;',
  50. 'end;',
  51. 'var w: word;',
  52. 'begin',
  53. //' w:=DoIt<word>(3);',
  54. '']);
  55. ParseProgram;
  56. end;
  57. procedure TTestResolveGenerics.TestGen_MissingTemplateFail;
  58. begin
  59. StartProgram(false);
  60. Add([
  61. 'type generic g< > = array of word;',
  62. 'begin',
  63. '']);
  64. CheckParserException('Expected "Identifier"',nParserExpectTokenError);
  65. end;
  66. procedure TTestResolveGenerics.TestGen_VarTypeWithoutSpecializeFail;
  67. begin
  68. StartProgram(false);
  69. Add([
  70. 'type generic TBird<T> = record end;',
  71. 'var b: TBird;',
  72. 'begin',
  73. '']);
  74. CheckResolverException('Generics without specialization cannot be used as a type for a variable',
  75. nGenericsWithoutSpecializationAsType);
  76. end;
  77. procedure TTestResolveGenerics.TestGen_ConstraintStringFail;
  78. begin
  79. StartProgram(false);
  80. Add([
  81. 'generic function DoIt<T:string>(a: T): T;',
  82. 'begin',
  83. ' Result:=a;',
  84. 'end;',
  85. 'begin',
  86. '']);
  87. CheckResolverException('''string'' is not a valid constraint',
  88. nXIsNotAValidConstraint);
  89. end;
  90. procedure TTestResolveGenerics.TestGen_ConstraintMultiClassFail;
  91. begin
  92. StartProgram(false);
  93. Add([
  94. '{$mode objfpc}',
  95. 'type',
  96. ' TObject = class end;',
  97. ' TBird = class end;',
  98. ' TBear = class end;',
  99. 'generic function DoIt<T: TBird, TBear>(a: T): T;',
  100. 'begin',
  101. ' Result:=a;',
  102. 'end;',
  103. 'begin',
  104. '']);
  105. CheckResolverException('''TBird'' constraint and ''TBear'' constraint cannot be specified together',
  106. nConstraintXAndConstraintYCannotBeTogether);
  107. end;
  108. procedure TTestResolveGenerics.TestGen_ConstraintRecordExpectedFail;
  109. begin
  110. StartProgram(false);
  111. Add([
  112. '{$mode objfpc}',
  113. 'type',
  114. ' generic TBird<T:record> = record v: T; end;',
  115. 'var r: specialize TBird<word>;',
  116. 'begin',
  117. '']);
  118. CheckResolverException('record type expected, but Word found',
  119. nXExpectedButYFound);
  120. end;
  121. procedure TTestResolveGenerics.TestGen_GenericNotFoundFail;
  122. begin
  123. StartProgram(false);
  124. Add([
  125. '{$mode objfpc}',
  126. 'type',
  127. ' TBird = specialize TAnimal<word>;',
  128. 'begin',
  129. '']);
  130. CheckResolverException('identifier not found "TAnimal"',
  131. nIdentifierNotFound);
  132. end;
  133. procedure TTestResolveGenerics.TestGen_RecordLocalNameDuplicateFail;
  134. begin
  135. StartProgram(false);
  136. Add([
  137. '{$mode objfpc}',
  138. 'type',
  139. ' generic TBird<T> = record T: word; end;',
  140. 'begin',
  141. '']);
  142. CheckResolverException('Duplicate identifier "T" at afile.pp(4,18)',
  143. nDuplicateIdentifier);
  144. end;
  145. procedure TTestResolveGenerics.TestGen_Record;
  146. begin
  147. StartProgram(false);
  148. Add([
  149. '{$mode objfpc}',
  150. 'type',
  151. ' {#Typ}T = word;',
  152. ' generic TRec<{#Templ}T> = record',
  153. ' {=Templ}v: T;',
  154. ' end;',
  155. 'var',
  156. ' r: specialize TRec<word>;',
  157. ' {=Typ}w: T;',
  158. 'begin',
  159. ' r.v:=w;',
  160. '']);
  161. ParseProgram;
  162. end;
  163. initialization
  164. RegisterTests([TTestResolveGenerics]);
  165. end.