From 5047d72d2a0661c184e07290b1f41c7b9eb28c5e Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 22 Aug 2015 14:38:17 +0200 Subject: [PATCH] * some cleanup --- uengShaderCodeGenerator.pas | 23 +--- uengShaderFile.inc | 2 +- uengShaderFile.pas | 59 ++++------ uengShaderFileConstants.pas | 3 +- uengShaderFileExpression.pas | 144 ++++++++++++++++++------- uengShaderFileHelper.pas | 32 ++++++ uengShaderFileTypes.pas | 16 +-- uengShaderPart.pas | 190 ++++++++++++++++++++++++--------- uengShaderPartClass.pas | 40 +------ uengShaderPartIf.pas | 5 +- uengShaderPartKeyValuePair.pas | 4 +- 11 files changed, 316 insertions(+), 202 deletions(-) diff --git a/uengShaderCodeGenerator.pas b/uengShaderCodeGenerator.pas index 58dcd3c..a6b6db7 100644 --- a/uengShaderCodeGenerator.pas +++ b/uengShaderCodeGenerator.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, - uengShaderFileParser, uengShaderPart, uengShaderPartScope, uengShaderPartKeyValuePair; + uengShaderPart, uengShaderPartScope, uengShaderPartKeyValuePair; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -15,10 +15,6 @@ type { General } private fProperties: TengShaderPartPropertyMap; - protected - fInherited: TengShaderPartList; - procedure UpdateInherited; virtual; - procedure UpdateCache; override; public constructor Create(const aParent: TengShaderPart); override; destructor Destroy; override; @@ -28,30 +24,17 @@ implementation //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderCodeGenerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderCodeGenerator.UpdateInherited; -begin - // DUMMY -end; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderCodeGenerator.UpdateCache; -begin - inherited UpdateCache; - UpdateInherited; -end; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderCodeGenerator.Create(const aParent: TengShaderPart); begin inherited Create(aParent); - fInherited := TengShaderPartList.Create(false); + fProperties := TengShaderPartPropertyMap.Create(false); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TengShaderCodeGenerator.Destroy; begin - FreeAndNil(fInherited); + FreeAndNil(fProperties); inherited Destroy; end; diff --git a/uengShaderFile.inc b/uengShaderFile.inc index 0a29871..507a2ee 100644 --- a/uengShaderFile.inc +++ b/uengShaderFile.inc @@ -1,3 +1,3 @@ -{$DEFINE EXPRESSION_ADD_BRACKET} // add brackets to expressions +{.$DEFINE EXPRESSION_ADD_BRACKET} // add brackets to expressions {$DEFINE USE_BITSPACE_UTILS} // use bitSpace Utils {$DEFINE DEBUG} // enable debug output diff --git a/uengShaderFile.pas b/uengShaderFile.pas index 5e41945..262309c 100644 --- a/uengShaderFile.pas +++ b/uengShaderFile.pas @@ -21,6 +21,7 @@ uses type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TengShaderFileLogEvent = procedure(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String) of object; TengShaderFile = class(TengShaderCodeGenerator) { Code Loading & Storage } private @@ -36,19 +37,21 @@ type function GetFilename: String; override; function GetFileReader: IengShaderFileReader; override; function GetFileWriter: IengShaderFileWriter; override; + public + procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil); + procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil); { General } private - procedure UpdateClasses; + fOnLog: TengShaderFileLogEvent; protected - procedure UpdateCache; override; + procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); override; public property Generator [const aName: String]: TengShaderCodeGenerator read GetGenerator; property GeneratorNames[const aIndex: Integer]: String read GetGeneratorNames; property GeneratorCount: Integer read GetGeneratorCount; + property OnLog: TengShaderFileLogEvent read fOnLog write fOnLog; - procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil); - procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil); procedure Clear; override; constructor Create(const aParent: TengShaderPart); override; destructor Destroy; override; @@ -107,35 +110,6 @@ begin result := Parent.FileWriter; end; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderFile.UpdateClasses; -var - sr: TengShaderPart.TSearchResults; - p: TengShaderPart; - new, old: TengShaderPartClass; -begin - sr := TengShaderPart.TSearchResults.Create([TengShaderPartClass]); - try - fClasses.Clear; - Find([sfSearchChildren], sr); - for p in sr do begin - new := (p as TengShaderPartClass); - old := fClasses[new.Name]; - if Assigned(old) then - raise EengDuplicateIdentifier.Create(new.Name, new, old, self); - fClasses.Add(new.Name, new); - end; - finally - FreeAndNil(sr); - end; -end; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderFile.UpdateCache; -begin - inherited UpdateCache; - UpdateClasses; -end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderFile.LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader); @@ -161,8 +135,6 @@ begin token := ParseText(args); if (token <> '') then with args do raise EengShaderPart.Create('unknown token ''' + token + '''', Line, Col, Filename, self); - if (Root = self) then - UpdateCache; finally FreeAndNil(args); end; @@ -174,7 +146,7 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderFile.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter); var - sr: TengShaderPart.TSearchResults; + sr: TengSearchResults; i: Integer; sl: TStringList; ms: TMemoryStream; @@ -185,11 +157,11 @@ begin if not Assigned(fFileWriter) then fFileWriter := TengShaderFileWriter.Create; - sr := TengShaderPart.TSearchResults.Create([TengShaderPartInclude]); + sr := TengSearchResults.Create([TengShaderPartInclude]); sl := TStringList.Create; ms := TMemoryStream.Create; try - Find([sfSearchChildren, sfChildrenFileOnly], sr); + Find([sfSearchChildren, sfChildrenOnlyFile], sr); for i := 0 to sr.Count-1 do (sr[i] as TengShaderPartInclude).SaveToFile(aFilename, aFileWriter); sl.Text := Text; @@ -204,6 +176,17 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderFile.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); +var + tmp: TengShaderFileLogEvent; +begin + inherited LogMsgIntern(aSender, aLogLevel, aMsg); + tmp := fOnLog; + if Assigned(tmp) then + tmp(aSender, aLogLevel, aMsg); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderFile.Clear; begin diff --git a/uengShaderFileConstants.pas b/uengShaderFileConstants.pas index adf56eb..c9027f9 100644 --- a/uengShaderFileConstants.pas +++ b/uengShaderFileConstants.pas @@ -36,6 +36,7 @@ const TOKEN_PROPERTY = TOKEN_CHAR_IDENT + 'PROPERTY'; //{$PROPERTY InvertRoughmap 'false'} TOKEN_DEFINE = TOKEN_CHAR_IDENT + 'DEFINE'; //{$DEFINE RENDER_FACE_FRONT '0'} + TOKEN_UNDEF = TOKEN_CHAR_IDENT + 'UNDEF'; //{$UNDEF RENDER_FACE_FRONT} TOKEN_ECHO = TOKEN_CHAR_IDENT + 'ECHO'; //{$ECHO InvertRoughmap} TOKEN_VAR = TOKEN_CHAR_IDENT + 'VAR'; //{$VAR 'float' 'refractivity' '0.0'} @@ -61,8 +62,6 @@ const TOKEN_OP_LOGICAL_OR = TOKEN_CHAR_IDENT + 'OR'; //{$IF test1 $OR test2} TOKEN_OP_LOGICAL_AND = TOKEN_CHAR_IDENT + 'AND'; //{$IF test1 $AND test2} TOKEN_OP_LOGICAL_XOR = TOKEN_CHAR_IDENT + 'XOR'; //{$IF test1 $XOR test2} - TOKEN_OP_DEFINED = TOKEN_CHAR_IDENT + 'DEFINED'; //{$IF $DEFINED test2} - TOKEN_OP_SET = TOKEN_CHAR_IDENT + 'SET'; //{$IF $SET vVertex} TOKEN_OP_ADD = '+'; //{$IF test1 + test2} TOKEN_OP_SUBTRACT = '-'; //{$IF test1 - test2} TOKEN_OP_MULTIPLY = '*'; //{$IF test1 * test2} diff --git a/uengShaderFileExpression.pas b/uengShaderFileExpression.pas index bc788db..64a8466 100644 --- a/uengShaderFileExpression.pas +++ b/uengShaderFileExpression.pas @@ -7,14 +7,14 @@ interface uses Classes, SysUtils, variants, - uengShaderPart, uengShaderFileParser; + uengShaderPart, uengShaderFileParser, uengShaderPartKeyValuePair; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengExpressionItem = class(TengShaderPart) public function GetValue: Variant; virtual; - constructor Create(const aLine, aCol: Integer); + constructor Create(const aLine, aCol: Integer); reintroduce; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -34,19 +34,24 @@ type TengExpressionVariable = class(TengExpressionItem) private fName: String; + fPart: TengShaderPartKeyValuePair; public - property Name: String read fName; + property Name: String read fName; + property Part: TengShaderPartKeyValuePair read fPart; function GetText: String; override; function GetValue: Variant; override; - constructor Create(const aName: String; const aLine, aCol: Integer); + constructor Create(const aName: String; const aPart: TengShaderPartKeyValuePair; const aLine, aCol: Integer); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengExpressionGroup = class(TengExpressionItem) private fChild: TengExpressionItem; + protected + function GetCount: Integer; override; + function GetChild(const aIndex: Integer): TengShaderPart; override; public property Child: TengExpressionItem read fChild; @@ -70,9 +75,7 @@ type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengExpressionUnaryOperator = ( opBinaryNot, - opLogicalNot, - opDefined, - opSet + opLogicalNot ); TengExpressionUnaryOperation = class(TengExpressionOperation) private @@ -80,6 +83,8 @@ type fUnaryOp: TengExpressionUnaryOperator; protected function GetWeight: Integer; override; + function GetCount: Integer; override; + function GetChild(const aIndex: Integer): TengShaderPart; override; public property Child: TengExpressionItem read fChild; property UnaryOp: TengExpressionUnaryOperator read fUnaryOp; @@ -107,6 +112,8 @@ type fBinaryOp: TengExpressionBinaryOperator; protected function GetWeight: Integer; override; + function GetCount: Integer; override; + function GetChild(const aIndex: Integer): TengShaderPart; override; public property First: TengExpressionItem read fFirst write fFirst; property Second: TengExpressionItem read fSecond write fSecond; @@ -126,20 +133,12 @@ type implementation uses - uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper - {$IFDEF USE_BITSPACE_UTILS} - , uutlGenerics - {$ELSE} - , fgl - {$ENDIF} - ; + uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; const EXPRESSION_UNARY_OPERATIONS: array[TengExpressionUnaryOperator] of String = ( TOKEN_OP_BINARY_NOT, //opBinaryNot - TOKEN_OP_LOGICAL_NOT, //opLogicalNot - TOKEN_OP_DEFINED, //opDefined - TOKEN_OP_SET //opSet + TOKEN_OP_LOGICAL_NOT //opLogicalNot ); EXPRESSION_BINARY_OPERATIONS: array[TengExpressionBinaryOperator] of String = ( TOKEN_OP_BINARY_OR, //opBinaryOr @@ -165,9 +164,7 @@ const UNARY_OPERATION_WEIGHTS: array[TengExpressionUnaryOperator] of Integer = ( 00, //opBinaryNot - 00, //opLogicalNot - 00, //opDefined - 00 //opSet + 00 //opLogicalNot ); BINARY_OPERATION_WEIGHTS: array[TengExpressionBinaryOperator] of Integer = ( 01, //opBinaryOr @@ -243,14 +240,29 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TengExpressionVariable.Create(const aName: String; const aLine, aCol: Integer); +constructor TengExpressionVariable.Create(const aName: String; const aPart: TengShaderPartKeyValuePair; const aLine, aCol: Integer); begin inherited Create(aLine, aCol); fName := aName; + fPart := aPart; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///TengExpressionGroup////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengExpressionGroup/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengExpressionGroup.GetCount: Integer; +begin + result := 1; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengExpressionGroup.GetChild(const aIndex: Integer): TengShaderPart; +begin + if (aIndex >= 0) and (aIndex < 1) + then result := fChild + else raise EengOutOfRange.Create(0, 0, aIndex, self); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengExpressionGroup.GetText: String; begin @@ -309,6 +321,20 @@ begin result := UNARY_OPERATION_WEIGHTS[fUnaryOp]; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengExpressionUnaryOperation.GetCount: Integer; +begin + result := 1; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengExpressionUnaryOperation.GetChild(const aIndex: Integer): TengShaderPart; +begin + if (aIndex >= 0) and (aIndex < 1) + then result := fChild + else raise EengOutOfRange.Create(0, 0, aIndex, self); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengExpressionUnaryOperation.GetText: String; begin @@ -339,15 +365,6 @@ begin v := fChild.GetValue; result := not Boolean(v); end; - - opDefined: begin - // TODO - end; - - opSet: begin - // TODO - end; - else result := inherited GetValue; end; @@ -397,6 +414,23 @@ begin result := BINARY_OPERATION_WEIGHTS[fBinaryOp]; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengExpressionBinaryOperation.GetCount: Integer; +begin + result := 2; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengExpressionBinaryOperation.GetChild(const aIndex: Integer): TengShaderPart; +begin + if (aIndex < 0) and (aIndex >= 2) then + raise EengOutOfRange.Create(0, 1, aIndex, self); + case aIndex of + 0: result := fFirst; + 1: result := fSecond; + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengExpressionBinaryOperation.GetText: String; begin @@ -487,6 +521,15 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type + TkvpSearchResults = class(TengSearchResults) + private + fName: String; + protected + function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; override; + public + constructor Create(const aName: String); + end; + TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation); TExpectedParams = set of TExpectedParam; TExpressionParser = class(TObject) @@ -495,27 +538,45 @@ type fParamPos: Integer; fParams: TengTokenParameterList; private - function NextParam(var aParam: TengTokenParameter): Boolean; + function NextParam(out aParam: TengTokenParameter): Boolean; function IsUnaryOperation(const aParam: String; out aOperator: TengExpressionUnaryOperator): Boolean; function IsBinaryOperation(const aParam: String; out aOperator: TengExpressionBinaryOperator): Boolean; procedure RaiseEx(const aMsg: String; const aParam: TengTokenParameter; aName: String = ''); function Move(var aItem: TengExpressionItem): TengExpressionItem; function Merge(aOld, aNew: TengExpressionItem): TengExpressionItem; function GetExpr(const aExpected: TExpectedParams): TengExpressionItem; - private + public function GetGroup: TengExpressionItem; constructor Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer); end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TkvpSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TkvpSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; +begin + result := inherited CheckObj(aPart, aContinue); + if result then + result := ((aPart as TengShaderPartKeyValuePair).Name = fName); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TkvpSearchResults.Create(const aName: String); +begin + inherited Create([TengShaderPartKeyValuePair]); + fName := aName; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TExpressionParser///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TExpressionParser.NextParam(var aParam: TengTokenParameter): Boolean; +function TExpressionParser.NextParam(out aParam: TengTokenParameter): Boolean; begin inc(fParamPos); result := (fParamPos < fParams.Count); - if result then - aParam := fParams[fParamPos]; + if result + then aParam := fParams[fParamPos] + else FillByte(aParam, SizeOf(aParam), 0); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -607,6 +668,8 @@ var bOp: TengExpressionBinaryOperator; item: TengExpressionItem; param: TengTokenParameter; + sr: TkvpSearchResults; + tmp: TengShaderPart; begin item := nil; result := nil; @@ -649,7 +712,14 @@ begin end else if IsValidIdentifier(param.Name) then begin if not (exVariable in aExpected) then RaiseEx('unexpected variable:', param); - result := TengExpressionVariable.Create(param.Name, param.Line, param.Col); + sr := TkvpSearchResults.Create(param.Name); + try + fParent.Find([], sr); + tmp := ExtractSearchResult(fParent, param.Name, sr, param.Line, param.Col); + result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col); + finally + FreeAndNil(sr); + end; // Unknown end else diff --git a/uengShaderFileHelper.pas b/uengShaderFileHelper.pas index a4bb5b8..426438c 100644 --- a/uengShaderFileHelper.pas +++ b/uengShaderFileHelper.pas @@ -10,6 +10,7 @@ uses function IsValidIdentifier(const aIdent: String): Boolean; function CheckEndToken(const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String; +function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList; aLine: Integer = -1; aCol: Integer = -1; aFilename: String = ''): TengShaderPart; implementation @@ -52,5 +53,36 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList; + aLine: Integer; aCol: Integer; aFilename: String): TengShaderPart; +var + s: String; + i: Integer; +begin + result := nil; + if (aList.Count <= 0) then + exit; + if Assigned(aSender) then begin + if (aLine < 0) then + aLine := aSender.Line; + if (aCol < 0) then + aCol := aSender.Col; + if (aFilename = '') then + aFilename := aSender.Filename; + end; + result := aList[0]; + if (aList.Count > 1) and Assigned(aSender) then begin + s := Format('use of duplicate identifier: %s (%s %d:%d)', [aIdent, aList[0].Filename, aList[0].Line + 1, aList[0].Col]) + sLineBreak + + 'previously declared here:' + sLineBreak; + i := 1; + while (i < aList.Count) do begin + s := s + Format(' %s %d:%d', [aList[i].Filename, aList[i].Line + 1, aList[i].Col]) + sLineBreak; + inc(i); + end; + aSender.LogMsg(llWarning, s); + end; +end; + end. diff --git a/uengShaderFileTypes.pas b/uengShaderFileTypes.pas index a3e2bc7..10fe0ab 100644 --- a/uengShaderFileTypes.pas +++ b/uengShaderFileTypes.pas @@ -23,6 +23,12 @@ type TIntfObjNoRefCount = uutlCommon.TutlInterfaceNoRefCount; {$ENDIF} + TengShaderPartLogLevel = ( + llInfo, + llWarning, + llError + ); + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Exceptions//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -174,18 +180,12 @@ procedure EengShaderPart.PrintTrace(const aLines: TStrings); else result := result + ' (' + aPart.ClassName + ')'; end; -var - p: TengShaderPart; begin if not Assigned(Sender) or not (Sender is TengShaderPart) then exit; - p := (Sender as TengShaderPart); - aLines.Text := Message; - while Assigned(p) do begin - aLines.Add(Format(' %s (%d:%d): %s', [p.Filename, p.Line+1, p.Col, GetName(p)])); - p := p.Parent; - end; + aLines.Add(Message); + (Sender as TengShaderPart).PrintTrace(' ', aLines); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderPart.pas b/uengShaderPart.pas index d931504..8d64107 100644 --- a/uengShaderPart.pas +++ b/uengShaderPart.pas @@ -22,26 +22,67 @@ type TengSearchFlag = ( sfEvaluateIf, // evaluate if statements before search and process with suitable subtree sfSearchAllIf, // search in all if sub trees + sfIncludeSelf, // add item to search results where search has started sfSearchPrevOnly, // search in previous items only sfSearchInherited, // search in inherited sfSearchChildren, // search in children sfSearchChildrenLazy, // set sfSearchChildren in next recursion level - sfChildrenFileOnly, // do not leave current file when searching for children - sfChildrenGeneratorOnly, // do not leave current generator when searching for children - sfChildrenScopeOnly, // do not leave current scope when searching for children + sfChildrenOnlyFile, // do not leave current file when searching for children + sfChildrenOnlyClass, // do not leave current class when searching for children + sfChildrenOnlyGenerator, // do not leave current generator when searching for children + sfChildrenOnlyScope, // do not leave current scope when searching for children + sfChildrenForceFile, // overwrite sfChildrenOnlyXXX flag when item is a file + sfChildrenForceClass, // overwrite sfChildrenOnlyXXX flag when item is a class + sfChildrenForceGenerator, // overwrite sfChildrenOnlyXXX flag when item is a generator + sfChildrenForceScope, // overwrite sfChildrenOnlyXXX flag when item is a scope sfSearchParents, // search in Parents - sfParentsFileOnly, // do not leave current file when searching in parents - sfParentsGeneratorOnly, // do not leave current generator when searching in parents - sfParentsScopeOnly // do not leave current scope when searching in parents + sfParentsOnlyFile, // do not leave current file when searching in parents + sfParentsOnlyClass, // do not leave current class when searching in parents + sfParentsOnlyGenerator, // do not leave current generator when searching in parents + sfParentsOnlyScope, // do not leave current scope when searching in parents + sfParentsForceFile, // overwrite sfParentsOnlyXXX flag when item is a file + sfParentsForceClass, // overwrite sfParentsOnlyXXX flag when item is a class + sfParentsForceGenerator, // overwrite sfParentsOnlyXXX flag when item is a generator + sfParentsForceScope // overwrite sfParentsOnlyXXX flag when item is a scope ); TengSearchFlags = set of TengSearchFlag; +const + SEARCH_FLAG_CURRENT_SCOPE = [ + sfSearchPrevOnly, + sfSearchInherited, // search in inherited + + sfSearchChildrenLazy, // set sfSearchChildren in next recursion level + sfChildrenOnlyScope, // do not leave current scope when searching for children + sfChildrenForceFile, // overwrite sfChildrenOnlyXXX flag when item is a file + + sfSearchParents, // search in Parents + sfParentsOnlyFile // do not leave current file when searching in parents + ]; + +type +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPart = class; CengShaderPart = class of TengShaderPart; TengShaderPartList = specialize TutlSimpleList; + + TengSearchResults = class(specialize TutlList) + private + fFirstOnly: Boolean; + fIgnore: TengShaderPart; + fTypes: array of CengShaderPart; + protected + function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; virtual; + public + property FirstOnly: Boolean read fFirstOnly write fFirstOnly; + property Ignore: TengShaderPart read fIgnore write fIgnore; + function Add(const aPart: TengShaderPart): Boolean; reintroduce; + constructor Create(const aTypes: array of CengShaderPart); + end; + TengShaderPart = class(TIntfObjNoRefCount) { Nested Types } public type @@ -58,26 +99,12 @@ type constructor Create(const aOwner: TengShaderPart; const aReverse: Boolean = false); end; - TSearchResults = class(specialize TutlList) - private - fFirstOnly: Boolean; - fIgnore: TengShaderPart; - fTypes: array of CengShaderPart; - protected - function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; virtual; - public - property FirstOnly: Boolean read fFirstOnly write fFirstOnly; - property Ignore: TengShaderPart read fIgnore write fIgnore; - function Add(const aPart: TengShaderPart): Boolean; reintroduce; - constructor Create(const aTypes: array of CengShaderPart); - end; - { Code Loading & Storage } protected { members } + fRoot: TengShaderPart; fParent: TengShaderPart; fLine: Integer; fCol: Integer; - fRoot: TengShaderPart; protected { virtual getter } function GetCount: Integer; virtual; function GetChild(const aIndex: Integer): TengShaderPart; virtual; @@ -88,8 +115,8 @@ type { General } protected - procedure UpdateCache; virtual; - function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean; virtual; + function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; virtual; + procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); virtual; public { general methods } property Root: TengShaderPart read fRoot; property Parent: TengShaderPart read fParent; @@ -108,7 +135,9 @@ type function GetParent(const aType: CengShaderPart; out aPart): Boolean; function GetParent(const aType: CengShaderPart): TengShaderPart; - procedure Find(const aFlags: TengSearchFlags; const aResults: TSearchResults); + procedure Find(const aFlags: TengSearchFlags; const aResults: TengSearchResults); + procedure PrintTrace(const aPrefix: String; const aLines: TStrings); + procedure LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String); function GetEnumerator: TEnumerator; function GetReverseEnumerator: TEnumerator; @@ -134,7 +163,7 @@ type implementation uses - uengShaderPartScope, uengShaderCodeGenerator, uengShaderFile, uengShaderFileConstants; + uengShaderPartScope, uengShaderCodeGenerator, uengShaderPartClass, uengShaderFile, uengShaderFileConstants; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPart.TEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -171,9 +200,9 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TengShaderPart.TSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TengShaderPart.TSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; +function TengSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; var c: CengShaderPart; begin @@ -188,7 +217,7 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TengShaderPart.TSearchResults.Add(const aPart: TengShaderPart): Boolean; +function TengSearchResults.Add(const aPart: TengShaderPart): Boolean; begin result := true; if result and CheckObj(aPart, result) then @@ -196,7 +225,7 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TengShaderPart.TSearchResults.Create(const aTypes: array of CengShaderPart); +constructor TengSearchResults.Create(const aTypes: array of CengShaderPart); var i: Integer; begin @@ -252,16 +281,44 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderPart.UpdateCache; -var - p: TengShaderPart; -begin - for p in self do - p.UpdateCache; -end; +function TengShaderPart.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; + + function VisitChild(const aItem: TengShaderPart): Boolean; + begin + result := (sfSearchChildren in aFlags); + if not result then + exit; + result := result and + Assigned(aItem) and + (not (sfChildrenOnlyFile in aFlags) or not (self is TengShaderFile)) and + (not (sfChildrenOnlyClass in aFlags) or not (self is TengShaderPartClass)) and + (not (sfChildrenOnlyGenerator in aFlags) or not (self is TengShaderCodeGenerator)) and + (not (sfChildrenOnlyScope in aFlags) or not (self is TengShaderPartScope)); + result := result or + ((sfChildrenForceFile in aFlags) and (self is TengShaderFile)) or + ((sfChildrenForceClass in aFlags) and (self is TengShaderPartClass)) or + ((sfChildrenForceGenerator in aFlags) and (self is TengShaderCodeGenerator)) or + ((sfChildrenForceScope in aFlags) and (self is TengShaderPartScope)); + end; + + function VisitParent(const aItem: TengShaderPart): Boolean; + begin + result := (sfSearchParents in aFlags); + if not result then + exit; + result := result and + Assigned(aItem) and + (not (sfParentsOnlyFile in aFlags) or not (self is TengShaderFile)) and + (not (sfParentsOnlyClass in aFlags) or not (self is TengShaderPartClass)) and + (not (sfParentsOnlyGenerator in aFlags) or not (self is TengShaderCodeGenerator)) and + (not (sfParentsOnlyScope in aFlags) or not (self is TengShaderPartScope)); + result := result or + ((sfParentsForceFile in aFlags) and (self is TengShaderFile)) or + ((sfParentsForceClass in aFlags) and (self is TengShaderPartClass)) or + ((sfParentsForceGenerator in aFlags) and (self is TengShaderCodeGenerator)) or + ((sfParentsForceScope in aFlags) and (self is TengShaderPartScope)); + end; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TengShaderPart.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean; var c: TengShaderPart; b: Boolean; @@ -273,28 +330,27 @@ begin b := b or (c = aChild); if (sfSearchPrevOnly in aFlags) and not b then continue; - if (c <> aChild) and - (not (sfChildrenScopeOnly in aFlags) or not (c is TengShaderPartScope)) and - (not (sfChildrenGeneratorOnly in aFlags) or not (c is TengShaderCodeGenerator)) and - (not (sfChildrenFileOnly in aFlags) or not (c is TengShaderFile)) - then - result := result and c.FindIntern(aFlags - [sfSearchParents], nil, aResults); + if (c <> aChild) and VisitChild(c) then + result := result and c.FindIntern(aFlags - [sfSearchParents] + [sfIncludeSelf], nil, aResults); if not result then exit; end; end; - result := result and aResults.Add(self); + if (sfIncludeSelf in aFlags) then + result := result and aResults.Add(self); if (sfSearchChildrenLazy in aFlags) then aFlags := aFlags + [sfSearchChildren] - [sfSearchChildrenLazy]; - if (sfSearchParents in aFlags) and - Assigned(Parent) and - (not (sfParentsScopeOnly in aFlags) or not (self is TengShaderPartScope)) and - (not (sfParentsGeneratorOnly in aFlags) or not (self is TengShaderCodeGenerator)) and - (not (sfParentsFileOnly in aFlags) or not (self is TengShaderFile)) - then - result := result and Parent.FindIntern(aFlags, self, aResults); + if VisitParent(Parent) then + result := result and Parent.FindIntern(aFlags + [sfIncludeSelf], self, aResults); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPart.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); +begin + if Assigned(Parent) then + Parent.LogMsgIntern(aSender, aLogLevel, aMsg); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -309,6 +365,7 @@ end; function TengShaderPart.GetParent(const aType: CengShaderPart; out aPart): Boolean; begin result := true; + TengShaderPart(aPart) := nil; if (fParent is aType) then TengShaderPart(aPart) := fParent else if Assigned(fParent) then @@ -325,11 +382,38 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderPart.Find(const aFlags: TengSearchFlags; const aResults: TSearchResults); +procedure TengShaderPart.Find(const aFlags: TengSearchFlags; const aResults: TengSearchResults); begin FindIntern(aFlags, nil, aResults); end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPart.PrintTrace(const aPrefix: String; const aLines: TStrings); + + function GetName(const aPart: TengShaderPart): String; + begin + result := aPart.GetTokenName; + if (result = '') + then result := aPart.ClassName + else result := result + ' (' + aPart.ClassName + ')'; + end; + +var + p: TengShaderPart; +begin + p := self; + while Assigned(p) do begin + aLines.Add(Format('%s%s (%d:%d): %s', [aPrefix, p.Filename, p.Line+1, p.Col, GetName(p)])); + p := p.Parent; + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPart.LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String); +begin + LogMsgIntern(self, aLogLevel, aMsg); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPart.GetEnumerator: TEnumerator; begin diff --git a/uengShaderPartClass.pas b/uengShaderPartClass.pas index 41a84b8..639e8ac 100644 --- a/uengShaderPartClass.pas +++ b/uengShaderPartClass.pas @@ -28,8 +28,6 @@ type function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; { General } - protected - procedure UpdateInherited; override; public property Name: String read fName; property Extends: TStrings read GetExtends; @@ -46,7 +44,7 @@ type implementation uses - uengShaderFile, uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartIf; + uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartClass/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -99,36 +97,6 @@ begin result := CheckEndToken(aArgs, self); end; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderPartClass.UpdateInherited; -var - sr: TengShaderPart.TSearchResults; - i: Integer; - s: String; -begin - inherited UpdateInherited; - fInherited.Clear; - sr := TengShaderPart.TSearchResults.Create([TengShaderPartClass]); - try - sr.Ignore := self; - Find([sfSearchChildrenLazy, sfSearchParents, sfParentsFileOnly, sfSearchPrevOnly], sr); - for s in fExtends do begin - i := 0; - while (i >= 0) and (i < sr.Count) do begin - if ((sr[i] as TengShaderPartClass).Name = s) then begin - fInherited.Add(sr[i]); - i := -1; - end; - inc(i); - end; - if (i > 0) or (sr.Count = 0) then - raise EengUnknownIdentifier.Create(s, self); - end; - finally - FreeAndNil(sr); - end; -end; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPartClass.Create(const aParent: TengShaderPart); begin @@ -160,12 +128,6 @@ class procedure TengShaderPartClass.Validate(const aArgs: TengParseArgs; const a begin inherited Validate(aArgs, aParent); - if aParent.HasParent(TengShaderPartElIf, true) then - RaiseEx(TengShaderPartElIf.GetTokenName); - if aParent.HasParent(TengShaderPartElse, true) then - RaiseEx(TengShaderPartElse.GetTokenName); - if aParent.HasParent(TengShaderPartIf, true) then - RaiseEx(TengShaderPartIf.GetTokenName); if aParent.HasParent(TengShaderPartClass, true) then RaiseEx(TengShaderPartClass.GetTokenName); end; diff --git a/uengShaderPartIf.pas b/uengShaderPartIf.pas index 68c2288..f0fea46 100644 --- a/uengShaderPartIf.pas +++ b/uengShaderPartIf.pas @@ -27,8 +27,9 @@ type { General } protected - function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean; override; + function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; override; public + property Expression: TengExpressionItem read fExpression; destructor Destroy; override; { Class Methods } @@ -137,7 +138,7 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TengShaderPartIf.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TSearchResults): Boolean; +function TengShaderPartIf.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; begin result := true; if (sfEvaluateIf in aFlags) and (sfSearchChildren in aFlags) then begin diff --git a/uengShaderPartKeyValuePair.pas b/uengShaderPartKeyValuePair.pas index 4320785..65bbcdb 100644 --- a/uengShaderPartKeyValuePair.pas +++ b/uengShaderPartKeyValuePair.pas @@ -51,7 +51,7 @@ type implementation uses - uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartIf; + uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartKeyValuePair//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -62,7 +62,7 @@ begin if (fValueName <> '') then result := result + ' ' + fValueName else if (fValue <> Unassigned) then - result := result + TOKEN_CHAR_QUOTE + String(fValue) + TOKEN_CHAR_QUOTE; + result := result + ' ' + TOKEN_CHAR_QUOTE + String(fValue) + TOKEN_CHAR_QUOTE; result := result + TOKEN_CHAR_END; end;