Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

265 строки
10 KiB

  1. unit uengShaderPartCall;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs;
  8. type
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. TengShaderPartCall = class(TengShaderCodePart)
  11. { Code Loading & Storage }
  12. private { member }
  13. fName: String;
  14. fParameters: TStringList;
  15. protected { virtual getter }
  16. function GetText: String; override;
  17. function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;
  18. { Code Generation }
  19. public
  20. procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override;
  21. { General }
  22. private
  23. function GetParameters: TStrings;
  24. public
  25. property Name: String read fName;
  26. property Parameters: TStrings read GetParameters;
  27. constructor Create(const aParent: TengShaderPart); override;
  28. destructor Destroy; override;
  29. { Class Methods }
  30. public
  31. class function GetTokenName: String; override;
  32. end;
  33. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  34. TengShaderPartInherited = class(TengShaderPartCall)
  35. { Class Methods }
  36. protected
  37. function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override;
  38. { Code Generation }
  39. public
  40. procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override;
  41. { Class Methods }
  42. public
  43. class function GetTokenName: String; override;
  44. class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override;
  45. end;
  46. implementation
  47. uses
  48. uengShaderPartProc, uengShaderPartClass, uengShaderFileConstants, uengShaderFileTypes,
  49. uengShaderFileHelper, uengShaderGenerator, uengShaderFile;
  50. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  51. //TengShaderPartCall////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  52. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  53. function TengShaderPartCall.GetText: String;
  54. var
  55. i: Integer;
  56. begin
  57. result := TOKEN_CHAR_BEGIN + GetTokenName;
  58. if (fName <> '') then
  59. result := result + ' ' + fName;
  60. for i := 0 to fParameters.Count-1 do begin
  61. if (PtrInt(fParameters.Objects[i]) <> 0)
  62. then result := result + ' ' + TOKEN_CHAR_QUOTE + fParameters[i] + TOKEN_CHAR_QUOTE
  63. else result := result + ' ' + fParameters[i];
  64. end;
  65. result := result + TOKEN_CHAR_END;
  66. end;
  67. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  68. function TengShaderPartCall.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
  69. var
  70. i: Integer;
  71. begin
  72. if (aParams[0].Name <> GetTokenName) then
  73. raise EengInvalidToken.Create(ClassName, aParams[0].Name, Line, Col, Filename, self);
  74. if (aParams.Count < 2) then
  75. raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self);
  76. result := '';
  77. fParameters.Clear;
  78. with aParams[1] do begin
  79. if not IsValidIdentifier(fName) then
  80. raise EengInvalidIdentifier.Create(Name, self);
  81. fName := Name;
  82. end;
  83. for i := 2 to aParams.Count-1 do
  84. fParameters.AddObject(aParams[i].Name, TObject(PtrInt(aParams[i].Quoted)));
  85. end;
  86. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. procedure TengShaderPartCall.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
  88. var
  89. sr: TengSearchResults;
  90. walker: TengProcSearchWalker;
  91. proc: TengShaderPartProc;
  92. begin
  93. inherited GenerateCodeIntern(aArgs);
  94. sr := TengSearchResults.Create;
  95. walker := TengProcSearchWalker.Create(sr);
  96. try
  97. walker.Name := Name;
  98. walker.SearchFlags := [sfEvaluateIf, sfSearchChildren, sfSearchInherited];
  99. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator);
  100. walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile);
  101. walker.Run(aArgs.Root);
  102. proc := (ExtractSearchResult(self, walker.Name, sr) as TengShaderPartProc);
  103. aArgs.PushProcParams(fParameters);
  104. aArgs.PushFlags(aArgs.Flags - [gfGenerateProcedureCode, gfGenerateInlineCode] + [gfGenerateProcedureCall]);
  105. try
  106. proc.GenerateCodeIntern(aArgs);
  107. finally
  108. aArgs.PopFlags;
  109. aArgs.PopProcParams;
  110. end;
  111. finally
  112. FreeAndNil(walker);
  113. FreeAndNil(sr);
  114. end;
  115. end;
  116. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  117. function TengShaderPartCall.GetParameters: TStrings;
  118. begin
  119. result := fParameters;
  120. end;
  121. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  122. constructor TengShaderPartCall.Create(const aParent: TengShaderPart);
  123. begin
  124. inherited Create(aParent);
  125. fParameters := TStringList.Create;
  126. end;
  127. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  128. destructor TengShaderPartCall.Destroy;
  129. begin
  130. FreeAndNil(fParameters);
  131. inherited Destroy;
  132. end;
  133. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  134. class function TengShaderPartCall.GetTokenName: String;
  135. begin
  136. result := TOKEN_CALL;
  137. end;
  138. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  139. //TengShaderPartInherited///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  140. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  141. function TengShaderPartInherited.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
  142. var
  143. i: Integer;
  144. begin
  145. if (aParams[0].Name <> GetTokenName) then with aParams[0] do
  146. raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self);
  147. fName := '';
  148. fParameters.Clear;
  149. if (aParams.Count >= 2) then begin
  150. if not IsValidIdentifier(aParams[1].Name) and (aParams[1].Name <> TOKEN_MAIN) then
  151. with aParams[1] do
  152. raise EengInvalidIdentifier.Create(Name, Line, Col, Filename, self);
  153. fName := aParams[1].Name;
  154. for i := 2 to aParams.Count-1 do
  155. fParameters.AddObject(aParams[i].Name, TObject(PtrInt(aParams[i].Quoted)));
  156. end;
  157. result := '';
  158. end;
  159. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  160. procedure TengShaderPartInherited.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs);
  161. function FindProc: TengShaderPartProc;
  162. var
  163. sr: TengSearchResults;
  164. walker: TengProcSearchWalker;
  165. ParentProc: TengShaderPartProc;
  166. begin
  167. sr := TengSearchResults.Create;
  168. walker := TengProcSearchWalker.Create(sr);
  169. try
  170. ParentProc := (GetParent(TengShaderPartProc) as TengShaderPartProc);
  171. walker.Name := Name;
  172. if (walker.Name = '') then
  173. walker.Name := ParentProc.Name;
  174. walker.Owner := ParentProc;
  175. walker.SearchFlags := [sfEvaluateIf, sfIgnoreOwner, sfSearchChildrenLazy, sfSearchInherited];
  176. walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass);
  177. walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass);
  178. walker.Run(ParentProc);
  179. result := (ExtractSearchResult(self, walker.Name, sr) as TengShaderPartProc);
  180. finally
  181. FreeAndNil(walker);
  182. FreeAndNil(sr);
  183. end;
  184. end;
  185. procedure GenCode(const aProc: TengShaderPartProc; const aParams: TStrings);
  186. begin
  187. aArgs.PushFlags(aArgs.Flags + [gfGenerateInlineCode]);
  188. aArgs.PushProcParams(aParams);
  189. try
  190. aProc.GenerateCodeIntern(aArgs);
  191. finally
  192. aArgs.PopProcParams;
  193. aArgs.PopFlags;
  194. end;
  195. end;
  196. var
  197. proc: TengShaderPartProc;
  198. i: Integer;
  199. params: TStringList;
  200. begin
  201. aArgs.AddToken(GetTokenName);
  202. proc := FindProc;
  203. if (fParameters.Count > 0) then begin
  204. if (fParameters.Count <> proc.ParameterCount) then
  205. raise EengInvalidParamterCount.Create(proc.name + ' expexts ' + IntToStr(proc.ParameterCount) + ' parameters', self);
  206. GenCode(proc, fParameters);
  207. end else begin
  208. params := TStringList.Create;
  209. try
  210. for i := 0 to proc.ParameterCount-1 do
  211. params.Add(proc.Parameters[i].Name);
  212. GenCode(proc, params);
  213. finally
  214. FreeAndNil(params);
  215. end;
  216. end;
  217. end;
  218. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  219. class function TengShaderPartInherited.GetTokenName: String;
  220. begin
  221. result := TOKEN_INHERITED;
  222. end;
  223. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  224. class procedure TengShaderPartInherited.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);
  225. begin
  226. inherited Validate(aArgs, aParent);
  227. if not aParent.HasParent(TengShaderPartProc, true) or
  228. not aParent.HasParent(TengShaderPartClass, true) then
  229. raise EengShaderPart.Create(GetTokenName + ' is not allowed outside of ' +
  230. TOKEN_PROC + ', ' + TOKEN_FUNC + ', ' + TOKEN_MAIN + ' or ' + TOKEN_CLASS);
  231. end;
  232. end.