You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
12 KiB

  1. unit uengShaderPart;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderFileParser, uengShaderFileTypes
  8. {$IFDEF SHADER_FILE_USE_BITSPACE_UTILS}
  9. , uutlGenerics
  10. {$ELSE}
  11. , uengShaderFileGenerics
  12. {$ENDIF}
  13. ;
  14. type
  15. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. TengShaderPart = class;
  17. CengShaderPart = class of TengShaderPart;
  18. CengShaderPartArr = array of CengShaderPart;
  19. TengShaderPartList = specialize TutlSimpleList<TengShaderPart>;
  20. TengShaderPartWalker = class(TObject)
  21. protected
  22. procedure Visit(const aPart, aCaller: TengShaderPart; const aArgs: Pointer); virtual;
  23. public
  24. procedure Run(const aPart: TengShaderPart);
  25. end;
  26. TengShaderPart = class(TIntfObjNoRefCount)
  27. { Nested Types }
  28. public type
  29. TEnumerator = class(TObject)
  30. private
  31. fOwner: TengShaderPart;
  32. fPosition: Integer;
  33. fReverse: Boolean;
  34. function GetCurrent: TengShaderPart;
  35. public
  36. property Current: TengShaderPart read GetCurrent;
  37. function GetEnumerator: TEnumerator;
  38. function MoveNext: Boolean;
  39. constructor Create(const aOwner: TengShaderPart; const aReverse: Boolean = false);
  40. end;
  41. { Code Loading & Storage }
  42. protected { members }
  43. fRoot: TengShaderPart;
  44. fParent: TengShaderPart;
  45. fLine: Integer;
  46. fCol: Integer;
  47. protected { virtual getter }
  48. function GetCount: Integer; virtual;
  49. function GetChild(const aIndex: Integer): TengShaderPart; virtual;
  50. function GetText: String; virtual;
  51. function GetFilename: String; virtual;
  52. function GetFileReader: IengShaderFileReader; virtual;
  53. function GetFileWriter: IengShaderFileWriter; virtual;
  54. { General }
  55. protected
  56. procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); virtual;
  57. public { general methods }
  58. property Root: TengShaderPart read fRoot;
  59. property Parent: TengShaderPart read fParent;
  60. property Line: Integer read fLine;
  61. property Col: Integer read fCol;
  62. property Filename: String read GetFilename;
  63. property Text: String read GetText;
  64. property Count: Integer read GetCount;
  65. property FileReader: IengShaderFileReader read GetFileReader;
  66. property FileWriter: IengShaderFileWriter read GetFileWriter;
  67. property Children[const aIndex: Integer]: TengShaderPart read GetChild; default;
  68. function HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean = false): Boolean;
  69. function GetParent(const aType: CengShaderPart; out aPart): Boolean;
  70. function GetParent(const aType: CengShaderPart): TengShaderPart;
  71. procedure PrintTrace(const aPrefix: String; const aLines: TStrings);
  72. procedure LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  73. function GetEnumerator: TEnumerator;
  74. function GetReverseEnumerator: TEnumerator;
  75. constructor Create(const aParent: TengShaderPart); virtual;
  76. { Class Methods }
  77. public
  78. class function GetTokenName: String; virtual;
  79. class function CheckToken(const aToken: String): Boolean; virtual;
  80. class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual;
  81. end;
  82. implementation
  83. uses
  84. uengShaderFileConstants;
  85. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  86. //TengShaderPart.TEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  88. function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart;
  89. begin
  90. result := fOwner[fPosition];
  91. end;
  92. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  93. function TengShaderPart.TEnumerator.GetEnumerator: TEnumerator;
  94. begin
  95. result := self;
  96. end;
  97. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  98. function TengShaderPart.TEnumerator.MoveNext: Boolean;
  99. begin
  100. if not fReverse
  101. then inc(fPosition)
  102. else dec(fPosition);
  103. result := (0 <= fPosition) and (fPosition < fOwner.Count);
  104. end;
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  106. constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart; const aReverse: Boolean);
  107. begin
  108. inherited Create;
  109. fOwner := aOwner;
  110. fReverse := aReverse;
  111. if not fReverse
  112. then fPosition := -1
  113. else fPosition := aOwner.Count;
  114. end;
  115. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. //TengShaderPartWalker//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  117. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  118. procedure TengShaderPartWalker.Visit(const aPart, aCaller: TengShaderPart; const aArgs: Pointer);
  119. begin
  120. // DUMMY
  121. end;
  122. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  123. procedure TengShaderPartWalker.Run(const aPart: TengShaderPart);
  124. begin
  125. Visit(aPart, nil, nil);
  126. end;
  127. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  128. //TengShaderPart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  129. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  130. function TengShaderPart.GetCount: Integer;
  131. begin
  132. result := 0;
  133. end;
  134. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  135. function TengShaderPart.{%H-}GetChild(const aIndex: Integer): TengShaderPart;
  136. begin
  137. EengShaderPartInternal.Create('this part does not have any children');
  138. end;
  139. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  140. function TengShaderPart.GetText: String;
  141. begin
  142. result := ''; //DUMMY
  143. end;
  144. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  145. function TengShaderPart.GetFilename: String;
  146. begin
  147. if Assigned(fParent)
  148. then result := fParent.Filename
  149. else result := UNKNOWN_FILENAME;
  150. end;
  151. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  152. function TengShaderPart.GetFileReader: IengShaderFileReader;
  153. begin
  154. if Assigned(fParent)
  155. then result := fParent.GetFileReader
  156. else result := nil;
  157. end;
  158. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  159. function TengShaderPart.GetFileWriter: IengShaderFileWriter;
  160. begin
  161. if Assigned(fParent)
  162. then result := fParent.GetFileWriter
  163. else result := nil;
  164. end;
  165. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  166. procedure TengShaderPart.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  167. begin
  168. if Assigned(Parent) then
  169. Parent.LogMsgIntern(aSender, aLogLevel, aMsg);
  170. end;
  171. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  172. function TengShaderPart.HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean): Boolean;
  173. var
  174. p: TengShaderPart;
  175. begin
  176. result := (aIncludeSelf and (self is aType)) or GetParent(aType, p);
  177. end;
  178. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  179. function TengShaderPart.GetParent(const aType: CengShaderPart; out aPart): Boolean;
  180. begin
  181. result := true;
  182. TengShaderPart(aPart) := nil;
  183. if (fParent is aType) then
  184. TengShaderPart(aPart) := fParent
  185. else if Assigned(fParent) then
  186. result := fParent.GetParent(aType, aPart)
  187. else
  188. result := false;
  189. end;
  190. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  191. function TengShaderPart.GetParent(const aType: CengShaderPart): TengShaderPart;
  192. begin
  193. if not GetParent(aType, result) then
  194. raise EengShaderPartInternal.Create(GetTokenName + ' has no parent of type ' + aType.GetTokenName, self);
  195. end;
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. procedure TengShaderPart.PrintTrace(const aPrefix: String; const aLines: TStrings);
  198. function GetName(const aPart: TengShaderPart): String;
  199. begin
  200. result := aPart.GetTokenName;
  201. if (result = '')
  202. then result := aPart.ClassName
  203. else result := result + ' (' + aPart.ClassName + ')';
  204. end;
  205. var
  206. p: TengShaderPart;
  207. begin
  208. p := self;
  209. while Assigned(p) do begin
  210. aLines.Add(Format('%s%s (%d:%d): %s', [aPrefix, p.Filename, p.Line+1, p.Col, GetName(p)]));
  211. p := p.Parent;
  212. end;
  213. end;
  214. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  215. procedure TengShaderPart.LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  216. begin
  217. LogMsgIntern(self, aLogLevel, aMsg);
  218. end;
  219. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  220. function TengShaderPart.GetEnumerator: TEnumerator;
  221. begin
  222. result := TEnumerator.Create(self);
  223. end;
  224. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  225. function TengShaderPart.GetReverseEnumerator: TEnumerator;
  226. begin
  227. result := TEnumerator.Create(self, true);
  228. end;
  229. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  230. constructor TengShaderPart.Create(const aParent: TengShaderPart);
  231. begin
  232. inherited Create;
  233. fParent := aParent;
  234. if Assigned(fParent)
  235. then fRoot := fParent.Root
  236. else fRoot := nil;
  237. end;
  238. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  239. class function TengShaderPart.GetTokenName: String;
  240. begin
  241. result := ''; // DUMMY
  242. end;
  243. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  244. class function TengShaderPart.CheckToken(const aToken: String): Boolean;
  245. begin
  246. result := (aToken = GetTokenName);
  247. end;
  248. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  249. class procedure TengShaderPart.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);
  250. begin
  251. // DUMMY
  252. end;
  253. end.