Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

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