Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

494 рядки
20 KiB

  1. unit uengShaderPart;
  2. {$mode objfpc}{$H+}
  3. {$I uengShaderFile.inc}
  4. interface
  5. uses
  6. Classes, SysUtils,
  7. uengShaderFileParser, uengShaderFileTypes
  8. {$IFDEF USE_BITSPACE_UTILS}
  9. , uutlGenerics
  10. {$ELSE}
  11. , fgl
  12. {$ENDIF}
  13. ;
  14. type
  15. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  16. TengSearchFlag = (
  17. sfEvaluateIf, // evaluate if statements before search and process with suitable subtree
  18. sfSearchAllIf, // search in all if sub trees
  19. sfSearchPrevOnly, // search in previous items only
  20. sfSearchInherited, // search in inherited
  21. sfSearchChildren, // search in children
  22. sfSearchChildrenLazy, // set sfSearchChildren in next recursion level
  23. sfChildrenOnlyFile, // do not leave current file when searching for children
  24. sfChildrenOnlyClass, // do not leave current class when searching for children
  25. sfChildrenOnlyGenerator, // do not leave current generator when searching for children
  26. sfChildrenOnlyScope, // do not leave current scope when searching for children
  27. sfChildrenForceFile, // overwrite sfChildrenOnlyXXX flag when item is a file
  28. sfChildrenForceClass, // overwrite sfChildrenOnlyXXX flag when item is a class
  29. sfChildrenForceGenerator, // overwrite sfChildrenOnlyXXX flag when item is a generator
  30. sfChildrenForceScope, // overwrite sfChildrenOnlyXXX flag when item is a scope
  31. sfSearchParents, // search in Parents
  32. sfParentsOnlyFile, // do not leave current file when searching in parents
  33. sfParentsOnlyClass, // do not leave current class when searching in parents
  34. sfParentsOnlyGenerator, // do not leave current generator when searching in parents
  35. sfParentsOnlyScope, // do not leave current scope when searching in parents
  36. sfParentsForceFile, // overwrite sfParentsOnlyXXX flag when item is a file
  37. sfParentsForceClass, // overwrite sfParentsOnlyXXX flag when item is a class
  38. sfParentsForceGenerator, // overwrite sfParentsOnlyXXX flag when item is a generator
  39. sfParentsForceScope // overwrite sfParentsOnlyXXX flag when item is a scope
  40. );
  41. TengSearchFlags = set of TengSearchFlag;
  42. const
  43. SEARCH_FLAG_CURRENT_SCOPE = [
  44. sfSearchPrevOnly,
  45. sfSearchInherited,
  46. sfSearchChildrenLazy,
  47. sfChildrenOnlyScope,
  48. sfChildrenForceFile,
  49. sfSearchParents,
  50. sfParentsOnlyFile
  51. ];
  52. SEARCH_FLAG_CLASS_PROPERTIES = [
  53. sfSearchAllIf,
  54. sfSearchChildren,
  55. sfChildrenOnlyGenerator,
  56. sfChildrenForceFile
  57. ];
  58. SEARCH_FLAG_FILE_PROPERTIES = [
  59. sfSearchAllIf,
  60. sfSearchChildren,
  61. sfChildrenOnlyGenerator
  62. ];
  63. type
  64. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  65. TengShaderPart = class;
  66. CengShaderPart = class of TengShaderPart;
  67. TengShaderPartList = specialize TutlSimpleList<TengShaderPart>;
  68. TengSearchResults = class(specialize TutlList<TengShaderPart>)
  69. private
  70. fFirstOnly: Boolean;
  71. fIgnore: TengShaderPart;
  72. fTypes: array of CengShaderPart;
  73. protected
  74. function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; virtual;
  75. public
  76. property FirstOnly: Boolean read fFirstOnly write fFirstOnly;
  77. property Ignore: TengShaderPart read fIgnore write fIgnore;
  78. function Add(const aPart: TengShaderPart): Boolean; reintroduce;
  79. constructor Create(const aTypes: array of CengShaderPart);
  80. end;
  81. TengShaderPart = class(TIntfObjNoRefCount)
  82. { Nested Types }
  83. public type
  84. TEnumerator = class(TObject)
  85. private
  86. fOwner: TengShaderPart;
  87. fPosition: Integer;
  88. fReverse: Boolean;
  89. function GetCurrent: TengShaderPart;
  90. public
  91. property Current: TengShaderPart read GetCurrent;
  92. function GetEnumerator: TEnumerator;
  93. function MoveNext: Boolean;
  94. constructor Create(const aOwner: TengShaderPart; const aReverse: Boolean = false);
  95. end;
  96. { Code Loading & Storage }
  97. protected { members }
  98. fRoot: TengShaderPart;
  99. fParent: TengShaderPart;
  100. fLine: Integer;
  101. fCol: Integer;
  102. protected { virtual getter }
  103. function GetCount: Integer; virtual;
  104. function GetChild(const aIndex: Integer): TengShaderPart; virtual;
  105. function GetText: String; virtual;
  106. function GetFilename: String; virtual;
  107. function GetFileReader: IengShaderFileReader; virtual;
  108. function GetFileWriter: IengShaderFileWriter; virtual;
  109. { General }
  110. protected
  111. function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; virtual;
  112. procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); virtual;
  113. public { general methods }
  114. property Root: TengShaderPart read fRoot;
  115. property Parent: TengShaderPart read fParent;
  116. property Line: Integer read fLine;
  117. property Col: Integer read fCol;
  118. property Filename: String read GetFilename;
  119. property Text: String read GetText;
  120. property Count: Integer read GetCount;
  121. property FileReader: IengShaderFileReader read GetFileReader;
  122. property FileWriter: IengShaderFileWriter read GetFileWriter;
  123. property Children[const aIndex: Integer]: TengShaderPart read GetChild; default;
  124. function HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean = false): Boolean;
  125. function GetParent(const aType: CengShaderPart; out aPart): Boolean;
  126. function GetParent(const aType: CengShaderPart): TengShaderPart;
  127. procedure Find(const aFlags: TengSearchFlags; const aResults: TengSearchResults);
  128. procedure PrintTrace(const aPrefix: String; const aLines: TStrings);
  129. procedure LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  130. function GetEnumerator: TEnumerator;
  131. function GetReverseEnumerator: TEnumerator;
  132. constructor Create(const aParent: TengShaderPart); virtual;
  133. { Class Methods }
  134. public
  135. class function GetTokenName: String; virtual;
  136. class function CheckToken(const aToken: String): Boolean; virtual;
  137. class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual;
  138. end;
  139. TengShaderCodePart = class(TengShaderPart)
  140. { Code Loading & Storage }
  141. protected
  142. function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; virtual;
  143. public
  144. function ParseText(const aArgs: TengParseArgs): String;
  145. end;
  146. CengShaderCodePart = class of TengShaderCodePart;
  147. implementation
  148. uses
  149. uengShaderPartScope, uengShaderCodeGenerator, uengShaderPartClass, uengShaderFile, uengShaderFileConstants;
  150. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  151. //TengShaderPart.TEnumerator////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  152. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  153. function TengShaderPart.TEnumerator.GetCurrent: TengShaderPart;
  154. begin
  155. result := fOwner[fPosition];
  156. end;
  157. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  158. function TengShaderPart.TEnumerator.GetEnumerator: TEnumerator;
  159. begin
  160. result := self;
  161. end;
  162. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  163. function TengShaderPart.TEnumerator.MoveNext: Boolean;
  164. begin
  165. if not fReverse
  166. then inc(fPosition)
  167. else dec(fPosition);
  168. result := (0 <= fPosition) and (fPosition < fOwner.Count);
  169. end;
  170. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  171. constructor TengShaderPart.TEnumerator.Create(const aOwner: TengShaderPart; const aReverse: Boolean);
  172. begin
  173. inherited Create;
  174. fOwner := aOwner;
  175. fReverse := aReverse;
  176. if not fReverse
  177. then fPosition := -1
  178. else fPosition := aOwner.Count;
  179. end;
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. //TengSearchResults/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  182. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  183. function TengSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean;
  184. var
  185. c: CengShaderPart;
  186. begin
  187. aContinue := not fFirstOnly or (Count = 0);;
  188. if aContinue then begin
  189. result := (Length(fTypes) = 0);
  190. for c in fTypes do
  191. result := result or (aPart is c);
  192. result := result and (aPart <> fIgnore);
  193. end else
  194. result := false;
  195. end;
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. function TengSearchResults.Add(const aPart: TengShaderPart): Boolean;
  198. begin
  199. result := true;
  200. if result and CheckObj(aPart, result) then
  201. inherited Add(aPart);
  202. end;
  203. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. constructor TengSearchResults.Create(const aTypes: array of CengShaderPart);
  205. var
  206. i: Integer;
  207. begin
  208. inherited Create(false);
  209. fFirstOnly := false;
  210. SetLength(fTypes, Length(aTypes));
  211. for i := Low(fTypes) to High(fTypes) do
  212. fTypes[i] := aTypes[i];
  213. end;
  214. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  215. //TengShaderPart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  216. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  217. function TengShaderPart.GetCount: Integer;
  218. begin
  219. result := 0;
  220. end;
  221. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  222. function TengShaderPart.{%H-}GetChild(const aIndex: Integer): TengShaderPart;
  223. begin
  224. EengShaderPartInternal.Create('this part does not have any children');
  225. end;
  226. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  227. function TengShaderPart.GetText: String;
  228. begin
  229. result := ''; //DUMMY
  230. end;
  231. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  232. function TengShaderPart.GetFilename: String;
  233. begin
  234. if Assigned(fParent)
  235. then result := fParent.Filename
  236. else result := UNKNOWN_FILENAME;
  237. end;
  238. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  239. function TengShaderPart.GetFileReader: IengShaderFileReader;
  240. begin
  241. if Assigned(fParent)
  242. then result := fParent.GetFileReader
  243. else result := nil;
  244. end;
  245. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  246. function TengShaderPart.GetFileWriter: IengShaderFileWriter;
  247. begin
  248. if Assigned(fParent)
  249. then result := fParent.GetFileWriter
  250. else result := nil;
  251. end;
  252. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  253. function TengShaderPart.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean;
  254. function VisitChild(const aItem: TengShaderPart): Boolean;
  255. begin
  256. result := (sfSearchChildren in aFlags);
  257. if not result then
  258. exit;
  259. result := result and
  260. Assigned(aItem) and
  261. (not (sfChildrenOnlyFile in aFlags) or not (aItem is TengShaderFile)) and
  262. (not (sfChildrenOnlyClass in aFlags) or not (aItem is TengShaderPartClass)) and
  263. (not (sfChildrenOnlyGenerator in aFlags) or not (aItem is TengShaderCodeGenerator)) and
  264. (not (sfChildrenOnlyScope in aFlags) or not (aItem is TengShaderPartScope));
  265. result := result or
  266. ((sfChildrenForceFile in aFlags) and (aItem is TengShaderFile)) or
  267. ((sfChildrenForceClass in aFlags) and (aItem is TengShaderPartClass)) or
  268. ((sfChildrenForceGenerator in aFlags) and (aItem is TengShaderCodeGenerator)) or
  269. ((sfChildrenForceScope in aFlags) and (aItem is TengShaderPartScope));
  270. end;
  271. function VisitParent: Boolean;
  272. begin
  273. result := (sfSearchParents in aFlags);
  274. if not result then
  275. exit;
  276. result := result and
  277. (not (sfParentsOnlyFile in aFlags) or not (self is TengShaderFile)) and
  278. (not (sfParentsOnlyClass in aFlags) or not (self is TengShaderPartClass)) and
  279. (not (sfParentsOnlyGenerator in aFlags) or not (self is TengShaderCodeGenerator)) and
  280. (not (sfParentsOnlyScope in aFlags) or not (self is TengShaderPartScope));
  281. result := result or
  282. ((sfParentsForceFile in aFlags) and (self is TengShaderFile)) or
  283. ((sfParentsForceClass in aFlags) and (self is TengShaderPartClass)) or
  284. ((sfParentsForceGenerator in aFlags) and (self is TengShaderCodeGenerator)) or
  285. ((sfParentsForceScope in aFlags) and (self is TengShaderPartScope));
  286. end;
  287. var
  288. c: TengShaderPart;
  289. b: Boolean;
  290. begin
  291. b := false;
  292. result := true;
  293. if (sfSearchChildren in aFlags) then begin
  294. for c in self.GetReverseEnumerator do begin
  295. b := b or (c = aChild);
  296. if (sfSearchPrevOnly in aFlags) and not b then
  297. continue;
  298. if (c <> aChild) then begin
  299. result := result and aResults.Add(c);
  300. if VisitChild(c) then
  301. result := result and c.FindIntern(aFlags - [sfSearchParents, sfSearchPrevOnly], nil, aResults);
  302. end;
  303. if not result then
  304. exit;
  305. end;
  306. end;
  307. if (sfSearchChildrenLazy in aFlags) then
  308. aFlags := aFlags + [sfSearchChildren] - [sfSearchChildrenLazy];
  309. if (sfSearchParents in aFlags) and Assigned(Parent) then begin
  310. if VisitParent then
  311. result := result and Parent.FindIntern(aFlags, self, aResults);
  312. result := result and aResults.Add(Parent);
  313. end;
  314. end;
  315. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  316. procedure TengShaderPart.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  317. begin
  318. if Assigned(Parent) then
  319. Parent.LogMsgIntern(aSender, aLogLevel, aMsg);
  320. end;
  321. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  322. function TengShaderPart.HasParent(const aType: CengShaderPart; const aIncludeSelf: Boolean): Boolean;
  323. var
  324. p: TengShaderPart;
  325. begin
  326. result := (aIncludeSelf and (self is aType)) or GetParent(aType, p);
  327. end;
  328. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  329. function TengShaderPart.GetParent(const aType: CengShaderPart; out aPart): Boolean;
  330. begin
  331. result := true;
  332. TengShaderPart(aPart) := nil;
  333. if (fParent is aType) then
  334. TengShaderPart(aPart) := fParent
  335. else if Assigned(fParent) then
  336. result := fParent.GetParent(aType, aPart)
  337. else
  338. result := false;
  339. end;
  340. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  341. function TengShaderPart.GetParent(const aType: CengShaderPart): TengShaderPart;
  342. begin
  343. if not GetParent(aType, result) then
  344. raise EengShaderPartInternal.Create(GetTokenName + ' ha sno parent of type ' + aType.GetTokenName, self);
  345. end;
  346. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  347. procedure TengShaderPart.Find(const aFlags: TengSearchFlags; const aResults: TengSearchResults);
  348. begin
  349. FindIntern(aFlags, nil, aResults);
  350. end;
  351. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  352. procedure TengShaderPart.PrintTrace(const aPrefix: String; const aLines: TStrings);
  353. function GetName(const aPart: TengShaderPart): String;
  354. begin
  355. result := aPart.GetTokenName;
  356. if (result = '')
  357. then result := aPart.ClassName
  358. else result := result + ' (' + aPart.ClassName + ')';
  359. end;
  360. var
  361. p: TengShaderPart;
  362. begin
  363. p := self;
  364. while Assigned(p) do begin
  365. aLines.Add(Format('%s%s (%d:%d): %s', [aPrefix, p.Filename, p.Line+1, p.Col, GetName(p)]));
  366. p := p.Parent;
  367. end;
  368. end;
  369. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  370. procedure TengShaderPart.LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String);
  371. begin
  372. LogMsgIntern(self, aLogLevel, aMsg);
  373. end;
  374. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  375. function TengShaderPart.GetEnumerator: TEnumerator;
  376. begin
  377. result := TEnumerator.Create(self);
  378. end;
  379. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  380. function TengShaderPart.GetReverseEnumerator: TEnumerator;
  381. begin
  382. result := TEnumerator.Create(self, true);
  383. end;
  384. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  385. constructor TengShaderPart.Create(const aParent: TengShaderPart);
  386. begin
  387. inherited Create;
  388. fParent := aParent;
  389. if Assigned(fParent)
  390. then fRoot := fParent.Root
  391. else fRoot := nil;
  392. end;
  393. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  394. class function TengShaderPart.GetTokenName: String;
  395. begin
  396. result := ''; // DUMMY
  397. end;
  398. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  399. class function TengShaderPart.CheckToken(const aToken: String): Boolean;
  400. begin
  401. result := (aToken = GetTokenName);
  402. end;
  403. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  404. class procedure TengShaderPart.Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart);
  405. begin
  406. // DUMMY
  407. end;
  408. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  409. //TengShaderCodePart////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  410. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  411. function TengShaderCodePart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String;
  412. begin
  413. result := ''; // DUMMY
  414. end;
  415. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  416. function TengShaderCodePart.ParseText(const aArgs: TengParseArgs): String;
  417. var
  418. params: TengTokenParameterList;
  419. begin
  420. params := TengTokenParameterList.Create(Filename);
  421. try
  422. fCol := aArgs.Col;
  423. fLine := aArgs.Line;
  424. if (GetTokenName <> '') then
  425. aArgs.ExtractToken(self, params);
  426. result := ParseIntern(aArgs, params);
  427. finally
  428. FreeAndNil(params);
  429. end;
  430. end;
  431. end.