Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

261 řádky
9.0 KiB

  1. unit uengShaderPartClass;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderPart, uengShaderGenerator, uengShaderGeneratorArgs, uengShaderFileParser
  8. {$IFDEF USE_BITSPACE_UTILS}
  9. , uutlGenerics
  10. {$ENDIF}
  11. ;
  12. type
  13. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14. TengShaderPartClass = class;
  15. TengShaderPartClassList = specialize TutlSimpleList<TengShaderPartClass>;
  16. TengShaderPartClass = class(TengShaderGenerator)
  17. { Code Loading & Storage }
  18. private { member }
  19. fName: String;
  20. fExtends: TStringList;
  21. fInherited: TengShaderPartClassList;
  22. private { getter }
  23. function GetExtends: TStrings;
  24. procedure UpdateInherited;
  25. protected { virtual getter }
  26. function GetText: String; override;
  27. function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;
  28. procedure UpdateProperties; override;
  29. { Code Generation }
  30. public
  31. procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override;
  32. { General }
  33. public
  34. property Name: String read fName;
  35. property Extends: TStrings read GetExtends;
  36. property InheritedClasses: TengShaderPartClassList read fInherited;
  37. constructor Create(const aParent: TengShaderPart); override;
  38. destructor Destroy; override;
  39. { Class Methods }
  40. public
  41. class function GetTokenName: String; override;
  42. class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override;
  43. end;
  44. TengShaderPartClassMap = specialize TutlMap<string, TengShaderPartClass>;
  45. implementation
  46. uses
  47. uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair,
  48. uengShaderPartScope, uengShaderFile, uengShaderPartProc;
  49. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50. //TengShaderPartClass///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  52. function TengShaderPartClass.GetExtends: TStrings;
  53. begin
  54. result := fExtends;
  55. end;
  56. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  57. procedure TengShaderPartClass.UpdateInherited;
  58. procedure FilterResults(const aName: String; const aResults, aNewResults: TengShaderPartList);
  59. var
  60. p: TengShaderPart;
  61. begin
  62. aNewResults.Clear;
  63. for p in aResults do
  64. if ((p as TengShaderPartClass).Name = aName) then
  65. aNewResults.Add(p);
  66. end;
  67. var
  68. sr, res: TengSearchResults;
  69. walker: TengSearchWalker;
  70. s: String;
  71. begin
  72. if (fExtends.Count <= 0) then
  73. exit;
  74. sr := TengSearchResults.Create;
  75. res := TengSearchResults.Create;
  76. walker := TengSearchWalker.Create(sr);
  77. try
  78. walker.Owner := self;
  79. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartClass);
  80. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope);
  81. walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
  82. walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile);
  83. walker.SearchFlags := [
  84. sfIgnoreOwner,
  85. sfSearchChildrenLazy,
  86. sfSearchChildren,
  87. sfSearchParents
  88. ];
  89. fInherited.Clear;
  90. walker.Run(self);
  91. for s in fExtends do begin
  92. FilterResults(s, sr, res);
  93. fInherited.Add(ExtractSearchResult(self, s, res) as TengShaderPartClass);
  94. end;
  95. finally
  96. FreeAndNil(walker);
  97. FreeAndNil(res);
  98. FreeAndNil(sr);
  99. end;
  100. end;
  101. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  102. function TengShaderPartClass.GetText: String;
  103. var
  104. s: String;
  105. begin
  106. result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fName;
  107. if (fExtends.Count > 0) then begin
  108. result := result + ' ' + TOKEN_EXTENDS;
  109. for s in fExtends do
  110. result := result + ' ' + s;
  111. end;
  112. result := result + TOKEN_CHAR_END +
  113. inherited GetText +
  114. TOKEN_CHAR_BEGIN + TOKEN_END + TOKEN_CHAR_END;
  115. end;
  116. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  117. function TengShaderPartClass.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
  118. var
  119. i: Integer;
  120. begin
  121. if (aParams[0].Name <> GetTokenName) then with aParams[0] do
  122. raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
  123. if (aParams.Count < 2) then
  124. raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);
  125. with aParams[1] do begin
  126. if not IsValidIdentifier(Name) then
  127. raise EengInvalidIdentifier.Create(Name, self);
  128. fName := Name;
  129. end;
  130. if (aParams.Count > 2) then begin
  131. if (aParams.Count < 4) then
  132. raise EengInvalidParamterCount.Create(GetTokenName, 4, -1, self);
  133. if (aParams[2].Name <> TOKEN_EXTENDS) then with aParams[2] do
  134. raise EengInvalidParamter.Create(aParams[2].Name, TOKEN_EXTENDS, Line, Col, Filename, self);
  135. fExtends.Clear;
  136. for i := 3 to aParams.Count-1 do
  137. fExtends.Add(aParams[i].Name);
  138. end;
  139. UpdateInherited;
  140. result := inherited ParseIntern(aArgs, aParams);
  141. result := CheckEndToken(result, aArgs, self);
  142. end;
  143. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  144. procedure TengShaderPartClass.UpdateProperties;
  145. var
  146. sr: TengSearchResults;
  147. walker: TengSearchWalker;
  148. p: TengShaderPart;
  149. c: TengShaderPartClass;
  150. begin
  151. inherited UpdateProperties;
  152. for c in fInherited do
  153. c.CopyProperties(self);
  154. sr := TengSearchResults.Create;
  155. walker := TengSearchWalker.Create(sr);
  156. try
  157. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty);
  158. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator);
  159. walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
  160. walker.Run(self);
  161. for p in sr.GetReverseEnumerator do
  162. AddProperty(p as TengShaderPartProperty);
  163. finally
  164. FreeAndNil(walker);
  165. FreeAndNil(sr);
  166. end;
  167. end;
  168. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  169. procedure TengShaderPartClass.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
  170. var
  171. c: TengShaderPartClass;
  172. sr: TengSearchResults;
  173. walker: TengSearchWalker;
  174. main: TengShaderPartMain;
  175. begin
  176. if (aArgs.Root <> self) then
  177. exit;
  178. for c in fInherited do
  179. c.GenerateCodeIntern(aArgs);
  180. inherited GenerateCodeIntern(aArgs);
  181. sr := TengSearchResults.Create;
  182. walker := TengSearchWalker.Create(sr);
  183. try
  184. walker.SearchFlags := [sfSearchChildren, sfEvaluateIf];
  185. walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain);
  186. walker.Run(self);
  187. main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr) as TengShaderPartMain);
  188. aArgs.PushFlags([gfGenerateProcedureCode]);
  189. try
  190. main.GenerateCodeIntern(aArgs);
  191. finally
  192. aArgs.PopFlags;
  193. end;
  194. finally
  195. FreeAndNil(walker);
  196. FreeAndNil(sr);
  197. end;
  198. end;
  199. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  200. constructor TengShaderPartClass.Create(const aParent: TengShaderPart);
  201. begin
  202. inherited Create(aParent);
  203. fExtends := TStringList.Create;
  204. fInherited := TengShaderPartClassList.Create(false);
  205. end;
  206. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  207. destructor TengShaderPartClass.Destroy;
  208. begin
  209. FreeAndNil(fInherited);
  210. FreeAndNil(fExtends);
  211. inherited Destroy;
  212. end;
  213. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  214. class function TengShaderPartClass.GetTokenName: String;
  215. begin
  216. result := TOKEN_CLASS;
  217. end;
  218. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  219. class procedure TengShaderPartClass.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);
  220. procedure RaiseEx(const aToken: String);
  221. begin
  222. with aArgs do
  223. raise EengShaderPart.Create('token ' + GetTokenName + ' is not allowed in ' + aToken, Line, Col, Filename, aParent);
  224. end;
  225. begin
  226. inherited Validate(aArgs, aParent);
  227. if aParent.HasParent(TengShaderPartClass, true) then
  228. RaiseEx(TengShaderPartClass.GetTokenName);
  229. end;
  230. end.