diff --git a/uengShaderCodePart.pas b/uengShaderCodePart.pas new file mode 100644 index 0000000..7111617 --- /dev/null +++ b/uengShaderCodePart.pas @@ -0,0 +1,70 @@ +unit uengShaderCodePart; + +{$mode objfpc}{$H+} +{$I uengShaderFile.inc} + +interface + +uses + Classes, SysUtils, + uengShaderPart, uengShaderFileParser, uengShaderGeneratorArgs + +{$IFDEF USE_BITSPACE_UTILS} + , uutlGenerics +{$ENDIF} + ; + +type + TengShaderCodePart = class(TengShaderPart) + { Code Loading & Storage } + protected + function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; virtual; + public + function ParseText(const aArgs: TengParseArgs): String; + + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); virtual; + end; + CengShaderCodePart = class of TengShaderCodePart; + TengShaderCodePartList = specialize TutlSimpleList; + +implementation + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderCodePart//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderCodePart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; +begin + result := ''; // DUMMY +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderCodePart.ParseText(const aArgs: TengParseArgs): String; +var + params: TengTokenParameterList; +begin + params := TengTokenParameterList.Create(Filename); + try + fCol := aArgs.Col; + fLine := aArgs.Line; + if (GetTokenName <> '') then + aArgs.ExtractToken(self, params); + result := ParseIntern(aArgs, params); + finally + FreeAndNil(params); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderCodePart.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +var + s: String; +begin + s := GetTokenName; + if (s <> '') then + aArgs.AddToken(s); +end; + +end. + diff --git a/uengShaderFile.old.pas b/uengShaderFile.old.pas index 23a533c..a198ccb 100644 --- a/uengShaderFile.old.pas +++ b/uengShaderFile.old.pas @@ -295,7 +295,7 @@ type ffInherited, // search in inherited classes (this is not a new recursion level!) ffFile, // search in file that belongs to this class (this is not a new recursion level!) - // file + // file GenCodeIntern ffIgnoreClasses // ignore class parts ); TengFindMappedPartFlags = set of TengFindMappedPartFlag; diff --git a/uengShaderFile.pas b/uengShaderFile.pas index f2df5e5..7b64b6b 100644 --- a/uengShaderFile.pas +++ b/uengShaderFile.pas @@ -12,7 +12,8 @@ interface uses Classes, sysutils, - uengShaderPart, uengShaderPartClass, uengShaderCodeGenerator, uengShaderFileParser, uengShaderFileTypes + uengShaderPart, uengShaderPartClass, uengShaderFileParser, uengShaderFileTypes, + uengShaderGenerator, uengShaderGeneratorArgs {$IFDEF USE_BITSPACE_UTILS} , uutlSerialization @@ -43,6 +44,10 @@ type procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil); procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil); + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { General } private fOnLog: TengShaderFileLogEvent; @@ -62,7 +67,7 @@ type implementation uses - uengShaderPartInclude, uengShaderPartKeyValuePair; + uengShaderPartInclude, uengShaderPartKeyValuePair, uengShaderFileHelper; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderFile//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -111,15 +116,19 @@ procedure TengShaderFile.UpdateClasses; var sr: TengSearchResults; + walker: TengSearchWalker; p: TengShaderPart; begin - sr := TengSearchResults.Create([TengShaderPartClass]); + sr := TengSearchResults.Create; + walker := TengSearchWalker.Create(sr); try - Find([sfSearchChildren], sr); + walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartClass); + walker.SearchFlags := [sfSearchChildren]; fClasses.Clear; - for p in sr.GetReverseEnumerator do + for p in sr do AddClass(p as TengShaderPartClass); finally + FreeAndNil(walker); FreeAndNil(sr); end; end; @@ -150,25 +159,29 @@ end; procedure TengShaderFile.UpdateProperties; var sr: TengSearchResults; + walker: TengSearchWalker; p: TengShaderPart; begin inherited UpdateProperties; - sr := TengSearchResults.Create([TengShaderFile]); + sr := TengSearchResults.Create; + walker := TengSearchWalker.Create(sr); try - Find(SEARCH_FLAG_FILE_PROPERTIES, sr); - for p in sr.GetReverseEnumerator do + walker.Owner := self; + walker.SearchFlags := [sfSearchChildren, sfIgnoreOwner]; + walker.ResultTypes := CengShaderPartArr.Create(TengShaderFile); + walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderCodeGenerator); + walker.Run(self); + for p in sr do (p as TengShaderFile).CopyProperties(self); - finally - FreeAndNil(sr); - end; - sr := TengSearchResults.Create([TengShaderPartProperty]); - try - Find(SEARCH_FLAG_FILE_PROPERTIES, sr); - for p in sr.GetReverseEnumerator do + walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty); + sr.Clear; + walker.Run(self); + for p in sr do AddProperty(p as TengShaderPartProperty); finally + FreeAndNil(walker); FreeAndNil(sr); end; end; @@ -203,6 +216,7 @@ begin FreeAndNil(args); end; finally + FreeAndNil(ms); fFileReader := nil; end; end; @@ -210,10 +224,11 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderFile.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter); var - sr: TengSearchResults; i: Integer; + sr: TengSearchResults; sl: TStringList; ms: TMemoryStream; + walker: TengSearchWalker; begin fFileWriter := aFileWriter; if not Assigned(fFileWriter) then @@ -221,11 +236,13 @@ begin if not Assigned(fFileWriter) then fFileWriter := TengShaderFileWriter.Create; - sr := TengSearchResults.Create([TengShaderPartInclude]); + sr := TengSearchResults.Create; sl := TStringList.Create; ms := TMemoryStream.Create; + walker := TengSearchWalker.Create(sr); try - Find([sfSearchChildren, sfChildrenOnlyFile], sr); + walker.SearchFlags := [sfSearchChildren]; + walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartInclude); for i := 0 to sr.Count-1 do (sr[i] as TengShaderPartInclude).SaveToFile(aFilename, aFileWriter); sl.Text := Text; @@ -233,6 +250,7 @@ begin ms.Position := 0; fFileWriter.SaveStream(aFilename, ms); finally + FreeAndNil(walker); FreeAndNil(sr); FreeAndNil(sl); FreeAndNil(ms); @@ -240,6 +258,15 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderFile.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + inherited GenerateCodeIntern(aArgs); + if (aArgs.Root = self) then begin + // TODO generate main routine code (if exists) + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderFile.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); var @@ -271,9 +298,9 @@ end; destructor TengShaderFile.Destroy; begin FreeAndNil(fClasses); + inherited Destroy; fFileReader := nil; fFileWriter := nil; - inherited Destroy; end; end. diff --git a/uengShaderFileConstants.pas b/uengShaderFileConstants.pas index 11fdb19..1b5dfb7 100644 --- a/uengShaderFileConstants.pas +++ b/uengShaderFileConstants.pas @@ -54,9 +54,10 @@ const TOKEN_ELSE = TOKEN_CHAR_IDENT + 'ELSE'; TOKEN_END = TOKEN_CHAR_IDENT + 'END'; - TOKEN_MESSAGE = TOKEN_CHAR_IDENT + 'MESSAGE'; //{$MESSAGE 'message'} + TOKEN_INFO = TOKEN_CHAR_IDENT + 'INFO'; //{$INFO 'message'} TOKEN_WARNING = TOKEN_CHAR_IDENT + 'WARNING'; //{$WARNING 'message'} TOKEN_ERROR = TOKEN_CHAR_IDENT + 'ERROR'; //{$ERROR 'message'} + TOKEN_THROW = TOKEN_CHAR_IDENT + 'THROW'; //{$THROW 'message'} TOKEN_OP_LOGICAL_NOT = TOKEN_CHAR_IDENT + 'NOT'; //{$IF $NOT test} TOKEN_OP_LOGICAL_OR = TOKEN_CHAR_IDENT + 'OR'; //{$IF test1 $OR test2} diff --git a/uengShaderFileExpression.pas b/uengShaderFileExpression.pas index 91b2319..35cde99 100644 --- a/uengShaderFileExpression.pas +++ b/uengShaderFileExpression.pas @@ -133,7 +133,7 @@ type implementation uses - uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; + uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartScope, uengShaderFile; const EXPRESSION_UNARY_OPERATIONS: array[TengExpressionUnaryOperator] of String = ( @@ -236,7 +236,9 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengExpressionVariable.GetValue: Variant; begin - result := Unassigned; // TODO + result := Unassigned; + if Assigned(fPart) then + result := fPart.Value; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -642,7 +644,8 @@ var bOp: TengExpressionBinaryOperator; item: TengExpressionItem; param: TengTokenParameter; - sr: TkvpSearchResults; + sr: TengSearchResults; + walker: TengKeyValuePairSearchWalker; tmp: TengShaderPart; begin item := nil; @@ -686,12 +689,20 @@ begin end else if IsValidIdentifier(param.Name) then begin if not (exVariable in aExpected) then RaiseEx('unexpected variable:', param); - sr := TkvpSearchResults.Create(param.Name, true, true); + sr := TengSearchResults.Create; + walker := TengKeyValuePairSearchWalker.Create(sr); try - fParent.Find(SEARCH_FLAG_CURRENT_SCOPE, sr); + walker.Name := param.Name; + walker.SearchFlags := [sfSearchChildrenLazy, sfSearchParents]; + walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic); + walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope); + walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); + walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); + walker.Run(fParent); tmp := ExtractSearchResult(fParent, param.Name, sr, param.Line, param.Col); result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col); finally + FreeAndNil(walker); FreeAndNil(sr); end; diff --git a/uengShaderFileHelper.pas b/uengShaderFileHelper.pas index fce9f5f..4882713 100644 --- a/uengShaderFileHelper.pas +++ b/uengShaderFileHelper.pas @@ -13,13 +13,56 @@ function CheckEndToken(const aArgs: TengParseArgs; const aShaderPart: TengShader function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList; aLine: Integer = -1; aCol: Integer = -1; aFilename: String = ''): TengShaderPart; type - TkvpSearchResults = class(TengSearchResults) + TengSearchFlag = ( + sfSearchChildren, // search in children + sfSearchChildrenLazy, // set sfSearchChildren in next recursion level + sfSearchParents, // search in Parents + sfIgnoreOwner // ignore owner of search walker + ); + TengSearchFlags = set of TengSearchFlag; + + TengSearchResults = class(TengShaderPartList) + public + constructor Create; + end; + + TengSearchWalker = class(TengShaderPartWalker) + private type + TArgs = packed record + Flags: TengSearchFlags; + end; + PArgs = ^TArgs; + private + fOwner: TengShaderPart; + fResults: TengSearchResults; + fSearchFlags: TengSearchFlags; + fResultTypes: CengShaderPartArr; + fChildrenDoNotLeave: CengShaderPartArr; + fParentsDoNotLeave: CengShaderPartArr; + fChildrenForceLeave: CengShaderPartArr; + fParentsForceLeave: CengShaderPartArr; + protected + procedure Visit(const aPart, aSender: TengShaderPart; const aArgs: Pointer); override; + function Check(const aPart: TengShaderPart): Boolean; virtual; + public + property Owner: TengShaderPart read fOwner write fOwner; + property SearchFlags: TengSearchFlags read fSearchFlags write fSearchFlags; + property ResultTypes: CengShaderPartArr read fResultTypes write fResultTypes; + property ChildrenDoNotLeave: CengShaderPartArr read fChildrenDoNotLeave write fChildrenDoNotLeave; + property ParentsDoNotLeave: CengShaderPartArr read fParentsDoNotLeave write fParentsDoNotLeave; + property ChildrenForceLeave: CengShaderPartArr read fChildrenForceLeave write fChildrenForceLeave; + property ParentsForceLeave: CengShaderPartArr read fParentsForceLeave write fParentsForceLeave; + + constructor Create(const aResults: TengSearchResults); + end; + + TengKeyValuePairSearchWalker = class(TengSearchWalker) private fName: String; protected - function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; override; + function Check(const aPart: TengShaderPart): Boolean; override; public - constructor Create(const aName: String; const aSearchDefines, aSearchProperties: Boolean); + property Name: String read fName write fName; end; implementation @@ -81,41 +124,122 @@ begin end; if (aList.Count <= 0) then raise EengUnknownIdentifier.Create(aIdent, aLine, aCol, aFilename, aSender); - result := aList[0]; + result := aList[aList.Count-1]; 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 + + s := Format('use of duplicate identifier: %s (%s %d:%d)', [aIdent, result.Filename, result.Line + 1, result.Col]) + sLineBreak + 'previously declared here:' + sLineBreak; - i := 1; - while (i < aList.Count) do begin + i := aList.Count - 2; + while (i >= 0) do begin s := s + Format(' %s %d:%d', [aList[i].Filename, aList[i].Line + 1, aList[i].Col]) + sLineBreak; - inc(i); + dec(i); end; aSender.LogMsg(llWarning, s); end; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TkvpSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TkvpSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; +constructor TengSearchResults.Create; begin - result := inherited CheckObj(aPart, aContinue); - if result then - result := ((aPart as TengShaderPartKeyValuePair).Name = fName); + inherited Create(false); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TkvpSearchResults.Create(const aName: String; const aSearchDefines, aSearchProperties: Boolean); +//TengSearchWalker////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengSearchWalker.Visit(const aPart, aSender: TengShaderPart; const aArgs: Pointer); +var + args: TArgs; + + function VisitChild(const aItem: TengShaderPart): Boolean; + var + c: CengShaderPart; + begin + result := (sfSearchChildren in args.Flags) and Assigned(aItem) and (aItem <> aSender); + if not result then + exit; + for c in fChildrenDoNotLeave do + if (aItem is c) then + result := false; + for c in fChildrenForceLeave do + if (aItem is c) then + result := true; + end; + + function VisitParent: Boolean; + var + c: CengShaderPart; + begin + result := (sfSearchParents in args.Flags) and Assigned(aPart.Parent) and (aPart.Parent <> aSender); + if not result then + exit; + for c in fParentsDoNotLeave do + if (aPart is c) then + result := false; + for c in fParentsForceLeave do + if (aPart is c) then + result := true; + end; + +var + c: TengShaderPart; + nextArgs: TArgs; begin - if aSearchDefines and aSearchProperties then - inherited Create([TengShaderPartStatic, TengShaderPartProperty]) - else if aSearchDefines then - inherited Create([TengShaderPartStatic]) - else if aSearchProperties then - inherited Create([TengShaderPartProperty]) + if not Assigned(aPart) then + exit; + if Assigned(aArgs) then + args := PArgs(aArgs)^ else - inherited Create([]); - fName := aName; + args.Flags := fSearchFlags; + + nextArgs := args; + if (sfSearchChildrenLazy in nextArgs.Flags) then + nextArgs.Flags := nextArgs.Flags + [sfSearchChildren] - [sfSearchChildrenLazy]; + if Check(aPart.Parent) then + fResults.Add(aPart.Parent); + if VisitParent then + Visit(aPart.Parent, aPart, @nextArgs); + + if (sfSearchChildren in args.Flags) then begin + for c in aPart do begin + if Check(c) then + fResults.Add(c); + if VisitChild(c) then + Visit(c, aPart, @args); + end; + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengSearchWalker.Check(const aPart: TengShaderPart): Boolean; +var + c: CengShaderPart; +begin + result := (aPart <> fOwner) or not (sfIgnoreOwner in fSearchFlags); + if result then + for c in fResultTypes do + if (aPart is c) then + exit; + result := false; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengSearchWalker.Create(const aResults: TengSearchResults); +begin + inherited Create; + fResults := aResults; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengKeyValuePairSearchWalker////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengKeyValuePairSearchWalker.Check(const aPart: TengShaderPart): Boolean; +begin + result := + inherited Check(aPart) and + (aPart is TengShaderPartKeyValuePair) and + ((aPart as TengShaderPartKeyValuePair).Name = fName); end; end. diff --git a/uengShaderFileTypes.pas b/uengShaderFileTypes.pas index 10fe0ab..f057fbb 100644 --- a/uengShaderFileTypes.pas +++ b/uengShaderFileTypes.pas @@ -24,11 +24,18 @@ type {$ENDIF} TengShaderPartLogLevel = ( + llDebug, llInfo, llWarning, - llError + llError, + llThrow ); +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TengShaderCode = class(TStringList) + + end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Exceptions//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderCodeGenerator.pas b/uengShaderGenerator.pas similarity index 85% rename from uengShaderCodeGenerator.pas rename to uengShaderGenerator.pas index ec07e1e..60765f3 100644 --- a/uengShaderCodeGenerator.pas +++ b/uengShaderGenerator.pas @@ -1,4 +1,4 @@ -unit uengShaderCodeGenerator; +unit uengShaderGenerator; {$mode objfpc}{$H+} {$I uengShaderFile.inc} @@ -7,28 +7,15 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderFileParser, uengShaderPartScope, uengShaderPartKeyValuePair - -{$IFDEF USE_BITSPACE_UTILS} - , uutlGenerics -{$ENDIF} - ; + uengShaderPart, uengShaderFileTypes, uengShaderFileParser, uengShaderPartScope, + uengShaderPartKeyValuePair, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderCodeGenerator = class(TengShaderPartScope) { Code Loading & Storage } - protected type - TPropertyList = class(specialize TutlSimpleList) - private - fValue: Variant; - public - property Value: Variant read fValue write fValue; - constructor Create; - end; - TPropertyMap = specialize TutlMap; private - fPropertyMap: TPropertyMap; + fPropertyMap: TengShaderPartPropertyMap; function GetPropertyByIndex(const aIndex: Integer): Variant; function GetPropertyByName(const aName: String): Variant; @@ -48,6 +35,10 @@ type property PropertyNames [const aIndex: Integer]: String read GetPropertyNames; property PropertyCount: Integer read GetPropertyCount; + { Generate Shader Code } + public + procedure GenerateCode(const aCode: TengShaderCode); + { General } public constructor Create(const aParent: TengShaderPart); override; @@ -56,17 +47,6 @@ type implementation -uses - uengShaderFileTypes; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TengShaderCodeGenerator.TPropertyList///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TengShaderCodeGenerator.TPropertyList.Create; -begin - inherited Create(false); -end; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderCodeGenerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -78,7 +58,7 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderCodeGenerator.GetPropertyByName(const aName: String): Variant; var - l: TPropertyList; + l: TengShaderPartPropertyList; begin l := fPropertyMap[aName]; if not Assigned(l) then @@ -107,7 +87,7 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderCodeGenerator.SetPropertyByName(const aName: String; aValue: Variant); var - l: TPropertyList; + l: TengShaderPartPropertyList; begin l := fPropertyMap[aName]; if not Assigned(l) then @@ -118,7 +98,7 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderCodeGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean); var - l: TPropertyList; + l: TengShaderPartPropertyList; p: TengShaderPartProperty; s: String; begin @@ -132,7 +112,7 @@ begin LogMsg(llWarning, s); end; end else begin - l := TPropertyList.Create; + l := TengShaderPartPropertyList.Create; fPropertyMap.Add(aProp.Name, l); end; l.Add(aProp); @@ -143,7 +123,7 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderCodeGenerator.CopyProperties(const aGen: TengShaderCodeGenerator); var - l: TPropertyList; + l: TengShaderPartPropertyList; p: TengShaderPartProperty; begin for l in fPropertyMap do @@ -164,11 +144,25 @@ begin UpdateProperties; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderCodeGenerator.GenerateCode(const aCode: TengShaderCode); +var + args: TengShaderGeneratorArgs; +begin + args := TengShaderGeneratorArgs.Create(self); + try + inherited GenerateCodeIntern(args); + args.GenerateCode(aCode); + finally + FreeAndNil(args); + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderCodeGenerator.Create(const aParent: TengShaderPart); begin inherited Create(aParent); - fPropertyMap := TPropertyMap.Create(true); + fPropertyMap := TengShaderPartPropertyMap.Create(true); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderGeneratorArgs.pas b/uengShaderGeneratorArgs.pas new file mode 100644 index 0000000..41998f0 --- /dev/null +++ b/uengShaderGeneratorArgs.pas @@ -0,0 +1,396 @@ +unit uengShaderGeneratorArgs; + +{$mode objfpc}{$H+} +{$I uengShaderFile.inc} + +interface + +uses + Classes, SysUtils, + uengShaderFileTypes, uengShaderPart + +{$IFDEF USE_BITSPACE_UTILS} + , uutlGenerics +{$ENDIF} + ; + +type +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TengGenerateFlag = ( + gfGenerateParameterItemCode, // generate code for parameter items + gfAddParameterItem // add parameter items to generator args + ); + TengGenerateFlags = set of TengGenerateFlag; + TengShaderGeneratorArgs = class(TObject) + private type + TengGeneratorToken = ( + gtNormal, // normal text + gtLineBreak, // line break + gtCommandEnd, // command end (like ';') + gtBlockBegin, // code block begin (to calculate indent) + gtBlockEnd, // code block end (to calculate indent) + gtToken // code token (like '$INCLUDE' or '$IF') + ); + + TCodePart = class(TObject) + private + fText: String; + fToken: TengGeneratorToken; + function GetText: String; + public + property Text: String read GetText; + property Token: TengGeneratorToken read fToken; + constructor Create(const aToken: TengGeneratorToken; const aText: String); + end; + TCodePartList = specialize TutlSimpleList; + + TCodeStackItem = class(TObject) + private + fItems: TCodePartList; + function GetIsEmpty: Boolean; + public + property Items: TCodePartList read fItems; + property IsEmpty: Boolean read GetIsEmpty; + + procedure GenerateCode(const aCode: TengShaderCode); + + constructor Create; + destructor Destroy; override; + end; + TCodeStack = specialize TutlSimpleList; + + private + fCode: TCodeStack; + fRoot: TengShaderPart; + fFlags: TengGenerateFlags; + + public + property Root: TengShaderPart read fRoot; + property Flags: TengGenerateFlags read fFlags; + + procedure PushCode; + procedure PopCode; + + procedure AddText(const aText: String); + procedure AddToken(const aToken: String); + procedure AddCommandEnd(const aToken: String); + procedure AddLineBreak; + procedure BeginBlock; + procedure EndBlock; + + procedure AddMeta(const aMeta: TengShaderPart); + procedure AddParam(const aParam: TengShaderPart); + + procedure GenerateCode(const aCode: TengShaderCode); + + constructor Create(const aRoot: TengShaderPart); + destructor Destroy; override; + end; + +implementation + +uses + Math; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderGeneratorArgs.TCodePart/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderGeneratorArgs.TCodePart.GetText: String; +begin + case fToken of + gtNormal, + gtCommandEnd: + result := fText; + gtLineBreak: + result := sLineBreak; + else + result := ''; + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderGeneratorArgs.TCodePart.Create(const aToken: TengGeneratorToken; const aText: String); +begin + inherited Create; + fToken := aToken; + fText := aText; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderGeneratorArgs.TCodeStackItem////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderGeneratorArgs.TCodeStackItem.GetIsEmpty: Boolean; +begin + result := (fItems.Count = 0); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.TCodeStackItem.GenerateCode(const aCode: TengShaderCode); +type + TGenFlag = ( + gfToken, // current line has a token in it + gfTokenOnly, // current line has only a token (or whitespaces) in it + gfPrevIsEmpty, // previouse line was empty (or whitespaces only) + gfCodeIsEmpty, // nothing has added to code + gfAddToPrevLine, // add current line to previous line + gfAddNextLine // add next line to current line (set gfAddToPrevLine on linebreak) + ); + TGenFlags = set of TGenFlag; + +const + WHITESPACES = [' ', #9]; + +var + i: Integer; + f: TGenFlags; + line: String; + + function GetStrOffset(const aStr: String): Integer; + var + len: Integer; + begin + result := 0; + len := Length(aStr); + while (result < len) and (aStr[result+1] in WHITESPACES) do + inc(result); + end; + + function GetOffset(const aCodePart: TCodePart): Integer; + begin + result := GetStrOffset(line); + end; + + function GetMinOffset(aStartIndex: Integer): Integer; + begin + if (Trim(line) <> '') + then result := GetStrOffset(line) + else result := High(Integer); + while (aStartIndex < aCode.Count) do begin + if (Trim(aCode[aStartIndex]) <> '') then + result := Min(result, GetStrOffset(aCode[aStartIndex])); + inc(aStartIndex); + end; + if (result >= High(Integer)) then + result := -1; + end; + + function TrimLeftLen(const aStr: String; aLen: Integer): String; + var + i, len: Integer; + begin + i := 1; + len := Length(aStr); + while (i <= len) and (aStr[i] in WHITESPACES) and (aLen > 0) do begin + inc(i); + dec(aLen); + end; + result := Copy(aStr, i, len - i + 1); + end; + + function PrepareStr(const aStr: String; const aOffset: Integer): String; + begin + if (aOffset < 0) + then result := StringOfChar(' ', -aOffset) + aStr + else result := TrimLeftLen(aStr, aOffset); + end; + + procedure IndentBlock(aStartIndex: Integer; const aIndent: Integer); + var + o: Integer; + begin + o := GetMinOffset(aStartIndex) - aIndent; + if (o <= 0) then + exit; + while (aStartIndex < aCode.Count) do begin + aCode[aStartIndex] := PrepareStr(aCode[aStartIndex], o); + inc(aStartIndex); + end; + line := PrepareStr(line, o); + end; + + procedure ProgressBlock(const aIndent: Integer); + var + s: String; + cp: TCodePart; + FirstLineIndex: Integer; + begin + FirstLineIndex := aCode.Count; + while (i < fItems.Count) do begin + cp := fItems[i]; + inc(i); + + case cp.Token of + gtLineBreak: begin + + // line has whitespaces only + if (Trim(line) = '') then begin + if (f * [gfToken, gfPrevIsEmpty] = []) then begin + aCode.Add(line); + Include(f, gfPrevIsEmpty); + end; + if not (gfTokenOnly in f) then + Exclude(f, gfAddToPrevLine); + + // line has text + end else begin + if (gfAddToPrevLine in f) and not (gfCodeIsEmpty in f) then begin + aCode[aCode.Count-1] := aCode[aCode.Count-1] + TrimLeft(line) + end else begin + aCode.Add(line); + Exclude(f, gfPrevIsEmpty); + Exclude(f, gfCodeIsEmpty); + end; + Exclude(f, gfAddToPrevLine); + end; + Exclude(f, gfToken); + Exclude(f, gfTokenOnly); + if (gfAddNextLine in f) then begin + Exclude(f, gfAddNextLine); + Include(f, gfAddToPrevLine); + end; + line := ''; + end; + + gtToken: begin + Include(f, gfToken); + if (Trim(line) = '') then + Include(f, gfTokenOnly); + end; + + gtBlockBegin: begin + if (Trim(line) <> '') then + Include(f, gfAddNextLine); + Include(f, gfPrevIsEmpty); + ProgressBlock(GetOffset(cp)); + end; + + gtBlockEnd: begin + if (Trim(line) = '') then + Include(f, gfAddToPrevLine); + IndentBlock(FirstLineIndex, aIndent); + exit; + end; + + else + s := cp.GetText; + if (gfAddNextLine in f) and (Trim(s) <> '') then + Exclude(f, gfAddNextLine); + line := line + s; + end; + end; + end; + +begin + i := 0; + f := [gfPrevIsEmpty, gfCodeIsEmpty]; + line := ''; + ProgressBlock(0); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderGeneratorArgs.TCodeStackItem.Create; +begin + inherited Create; + fItems := TCodePartList.Create(true); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TengShaderGeneratorArgs.TCodeStackItem.Destroy; +begin + FreeAndNil(fItems); + inherited Destroy; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderGeneratorArgs///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.PushCode; +begin + fCode.PushLast(TCodeStackItem.Create); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.PopCode; +var + csi: TCodeStackItem; +begin + csi := fCode.PopLast(false); + try + // TODO merge + finally + FreeAndNil(csi); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.AddText(const aText: String); +begin + fCode.Last.Items.Add(TCodePart.Create(gtNormal, aText)); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.AddToken(const aToken: String); +begin + fCode.Last.Items.Add(TCodePart.Create(gtToken, aToken)); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.AddCommandEnd(const aToken: String); +begin + fCode.Last.Items.Add(TCodePart.Create(gtCommandEnd, aToken)); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.AddLineBreak; +begin + fCode.Last.Items.Add(TCodePart.Create(gtLineBreak, '')); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.BeginBlock; +begin + fCode.Last.Items.Add(TCodePart.Create(gtBlockBegin, '')); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.EndBlock; +begin + fCode.Last.Items.Add(TCodePart.Create(gtBlockEnd, '')); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.AddMeta(const aMeta: TengShaderPart); +begin + // TODO +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.AddParam(const aParam: TengShaderPart); +begin + // TODO +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderGeneratorArgs.GenerateCode(const aCode: TengShaderCode); +begin + fCode.Last.GenerateCode(aCode); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderGeneratorArgs.Create(const aRoot: TengShaderPart); +begin + inherited Create; + fCode := TCodeStack.Create(true); + fRoot := aRoot; + PushCode; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TengShaderGeneratorArgs.Destroy; +begin + FreeAndNil(fCode); + inherited Destroy; +end; + +end. + diff --git a/uengShaderPart.pas b/uengShaderPart.pas index 978e9a6..3fbc00f 100644 --- a/uengShaderPart.pas +++ b/uengShaderPart.pas @@ -17,78 +17,18 @@ uses {$ENDIF} ; -type -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TengSearchFlag = ( - sfEvaluateIf, // evaluate if statements before search and process with suitable subtree - sfSearchAllIf, // search in all if sub trees - - sfSearchPrevOnly, // search in previous items only - sfSearchInherited, // search in inherited - - sfSearchChildren, // search in children - sfSearchChildrenLazy, // set sfSearchChildren in next recursion level - 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 - 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, - sfSearchChildrenLazy, - sfChildrenOnlyScope, - sfChildrenForceFile, - sfSearchParents, - sfParentsOnlyFile - ]; - SEARCH_FLAG_CLASS_PROPERTIES = [ - sfSearchAllIf, - sfSearchChildren, - sfChildrenOnlyGenerator, - sfChildrenForceFile - ]; - SEARCH_FLAG_FILE_PROPERTIES = [ - sfSearchAllIf, - sfSearchChildren, - sfChildrenOnlyGenerator - ]; - type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPart = class; CengShaderPart = class of TengShaderPart; + CengShaderPartArr = array of CengShaderPart; TengShaderPartList = specialize TutlSimpleList; - TengSearchResults = class(specialize TutlList) - private - fFirstOnly: Boolean; - fIgnore: TengShaderPart; - fTypes: array of CengShaderPart; + TengShaderPartWalker = class(TObject) protected - function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; virtual; + procedure Visit(const aPart, aCaller: TengShaderPart; const aArgs: Pointer); 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); + procedure Run(const aPart: TengShaderPart); end; TengShaderPart = class(TIntfObjNoRefCount) @@ -123,7 +63,6 @@ type { General } protected - 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; @@ -143,7 +82,6 @@ type function GetParent(const aType: CengShaderPart; out aPart): Boolean; function GetParent(const aType: CengShaderPart): TengShaderPart; - procedure Find(const aFlags: TengSearchFlags; const aResults: TengSearchResults); procedure PrintTrace(const aPrefix: String; const aLines: TStrings); procedure LogMsg(const aLogLevel: TengShaderPartLogLevel; const aMsg: String); @@ -159,19 +97,10 @@ type class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); virtual; end; - TengShaderCodePart = class(TengShaderPart) - { Code Loading & Storage } - protected - function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; virtual; - public - function ParseText(const aArgs: TengParseArgs): String; - end; - CengShaderCodePart = class of TengShaderCodePart; - implementation uses - uengShaderPartScope, uengShaderCodeGenerator, uengShaderPartClass, uengShaderFile, uengShaderFileConstants; + uengShaderFileConstants; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPart.TEnumerator//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -208,40 +137,17 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TengSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartWalker////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TengSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; -var - c: CengShaderPart; +procedure TengShaderPartWalker.Visit(const aPart, aCaller: TengShaderPart; const aArgs: Pointer); begin - aContinue := not fFirstOnly or (Count = 0);; - if aContinue then begin - result := (Length(fTypes) = 0); - for c in fTypes do - result := result or (aPart is c); - result := result and (aPart <> fIgnore); - end else - result := false; -end; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TengSearchResults.Add(const aPart: TengShaderPart): Boolean; -begin - result := true; - if result and CheckObj(aPart, result) then - inherited Add(aPart); + // DUMMY end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TengSearchResults.Create(const aTypes: array of CengShaderPart); -var - i: Integer; +procedure TengShaderPartWalker.Run(const aPart: TengShaderPart); begin - inherited Create(false); - fFirstOnly := false; - SetLength(fTypes, Length(aTypes)); - for i := Low(fTypes) to High(fTypes) do - fTypes[i] := aTypes[i]; + Visit(aPart, nil, nil); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -288,74 +194,6 @@ begin else result := nil; 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 (aItem is TengShaderFile)) and - (not (sfChildrenOnlyClass in aFlags) or not (aItem is TengShaderPartClass)) and - (not (sfChildrenOnlyGenerator in aFlags) or not (aItem is TengShaderCodeGenerator)) and - (not (sfChildrenOnlyScope in aFlags) or not (aItem is TengShaderPartScope)); - result := result or - ((sfChildrenForceFile in aFlags) and (aItem is TengShaderFile)) or - ((sfChildrenForceClass in aFlags) and (aItem is TengShaderPartClass)) or - ((sfChildrenForceGenerator in aFlags) and (aItem is TengShaderCodeGenerator)) or - ((sfChildrenForceScope in aFlags) and (aItem is TengShaderPartScope)); - end; - - function VisitParent: Boolean; - begin - result := (sfSearchParents in aFlags); - if not result then - exit; - result := result 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; - -var - c: TengShaderPart; - b: Boolean; -begin - b := false; - result := true; - if (sfSearchChildren in aFlags) then begin - for c in self.GetReverseEnumerator do begin - b := b or (c = aChild); - if (sfSearchPrevOnly in aFlags) and not b then - continue; - if (c <> aChild) then begin - result := result and aResults.Add(c); - if VisitChild(c) then - result := result and c.FindIntern(aFlags - [sfSearchParents, sfSearchPrevOnly], nil, aResults); - end; - if not result then - exit; - end; - end; - - if (sfSearchChildrenLazy in aFlags) then - aFlags := aFlags + [sfSearchChildren] - [sfSearchChildrenLazy]; - if (sfSearchParents in aFlags) and Assigned(Parent) then begin - if VisitParent then - result := result and Parent.FindIntern(aFlags, self, aResults); - result := result and aResults.Add(Parent); - end; -end; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderPart.LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); begin @@ -391,12 +229,6 @@ begin raise EengShaderPartInternal.Create(GetTokenName + ' ha sno parent of type ' + aType.GetTokenName, self); end; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderPart.Find(const aFlags: TengSearchFlags; const aResults: TengSearchResults); -begin - FindIntern(aFlags, nil, aResults); -end; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderPart.PrintTrace(const aPrefix: String; const aLines: TStrings); @@ -464,30 +296,5 @@ begin // DUMMY end; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TengShaderCodePart//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TengShaderCodePart.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; -begin - result := ''; // DUMMY -end; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TengShaderCodePart.ParseText(const aArgs: TengParseArgs): String; -var - params: TengTokenParameterList; -begin - params := TengTokenParameterList.Create(Filename); - try - fCol := aArgs.Col; - fLine := aArgs.Line; - if (GetTokenName <> '') then - aArgs.ExtractToken(self, params); - result := ParseIntern(aArgs, params); - finally - FreeAndNil(params); - end; -end; - end. diff --git a/uengShaderPartCall.pas b/uengShaderPartCall.pas index cfa32c1..cd0a4d7 100644 --- a/uengShaderPartCall.pas +++ b/uengShaderPartCall.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderFileParser; + uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -20,6 +20,10 @@ type function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { General } private function GetParameters: TStrings; @@ -89,6 +93,13 @@ begin fParameters.AddObject(aParams[i].Name, TObject(PtrInt(aParams[i].Quoted))); end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartCall.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + inherited GenerateCodeIntern(aArgs); + // TODO +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartCall.GetParameters: TStrings; begin diff --git a/uengShaderPartClass.pas b/uengShaderPartClass.pas index 12bf179..6a2eec2 100644 --- a/uengShaderPartClass.pas +++ b/uengShaderPartClass.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderCodeGenerator, uengShaderFileParser + uengShaderPart, uengShaderGenerator, uengShaderGeneratorArgs, uengShaderFileParser {$IFDEF USE_BITSPACE_UTILS} , uutlGenerics @@ -32,6 +32,10 @@ type function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; procedure UpdateProperties; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { General } public property Name: String read fName; @@ -50,7 +54,7 @@ type implementation uses - uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair; + uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair, uengShaderPartScope, uengShaderFile; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartClass/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -74,22 +78,35 @@ procedure TengShaderPartClass.UpdateInherited; end; var - sr: TengSearchResults; - res: TengShaderPartList; + sr, res: TengSearchResults; + walker: TengSearchWalker; s: String; begin if (fExtends.Count <= 0) then exit; - sr := TengSearchResults.Create([TengShaderPartClass]); - res := TengShaderPartList.Create(false); + sr := TengSearchResults.Create; + res := TengSearchResults.Create; + walker := TengSearchWalker.Create(sr); try + walker.Owner := self; + walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartClass); + walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope); + walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); + walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); + walker.SearchFlags := [ + sfIgnoreOwner, + sfSearchChildrenLazy, + sfSearchChildren, + sfSearchParents + ]; fInherited.Clear; - Find(SEARCH_FLAG_CURRENT_SCOPE, sr); + walker.Run(self); for s in fExtends do begin FilterResults(s, sr, res); fInherited.Add(ExtractSearchResult(self, s, res) as TengShaderPartClass); end; finally + FreeAndNil(walker); FreeAndNil(res); FreeAndNil(sr); end; @@ -143,6 +160,7 @@ end; procedure TengShaderPartClass.UpdateProperties; var sr: TengSearchResults; + walker: TengSearchWalker; p: TengShaderPart; c: TengShaderPartClass; begin @@ -151,16 +169,35 @@ begin for c in fInherited do c.CopyProperties(self); - sr := TengSearchResults.Create([TengShaderPartProperty]); + sr := TengSearchResults.Create; + walker := TengSearchWalker.Create(sr); try - Find(SEARCH_FLAG_CLASS_PROPERTIES, sr); + walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty); + walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderCodeGenerator); + walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); + walker.Run(self); for p in sr.GetReverseEnumerator do AddProperty(p as TengShaderPartProperty); finally + FreeAndNil(walker); FreeAndNil(sr); end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartClass.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +var + c: TengShaderPartClass; +begin + if (aArgs.Root <> self) then + exit; + for c in fInherited do + c.GenerateCodeIntern(aArgs); + inherited GenerateCodeIntern(aArgs); + + // TODO generate main routine +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPartClass.Create(const aParent: TengShaderPart); begin diff --git a/uengShaderPartCntr.pas b/uengShaderPartCntr.pas index 3d73fb3..1e0d454 100644 --- a/uengShaderPartCntr.pas +++ b/uengShaderPartCntr.pas @@ -7,22 +7,28 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderFileParser; + uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartCntr = class(TengShaderCodePart) { Code Loading & Storage } private - fChildren: TengShaderPartList; - procedure AddChild(const aChild: TengShaderPart; const aPrepend: Boolean = false); + fChildren: TengShaderCodePartList; + procedure AddChild(const aChild: TengShaderCodePart; const aPrepend: Boolean = false); function HandleToken(const aToken: String; const aArgs: TengParseArgs): String; protected { virtual getter } function GetCount: Integer; override; function GetChild(const aIndex: Integer): TengShaderPart; override; function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; - public { general methods } + + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + + { General } + public procedure Clear; virtual; constructor Create(const aParent: TengShaderPart); override; destructor Destroy; override; @@ -33,7 +39,11 @@ implementation uses uengShaderPartKeyValuePair, uengShaderPartClass, uengShaderPartMessage, uengShaderPartMeta, uengShaderPartCall, uengShaderPartProc, uengShaderPartText, uengShaderPartEcho, uengShaderPartIf, - uengShaderPartInclude, uengShaderPartParameter, uengShaderPartComment; + uengShaderPartInclude, uengShaderPartParameter, uengShaderPartComment, uengShaderFileConstants +{$IFDEF DEBUG} + , uengShaderFileTypes +{$ENDIF} + ; const TOKEN_CLASSES: array[0..21] of CengShaderCodePart = ( @@ -51,7 +61,7 @@ const TengShaderPartInclude, TengShaderPartInherited, TengShaderPartFunc, - TengShaderPartMessage, + TengShaderPartInfo, TengShaderPartMeta, TengShaderPartProc, TengShaderPartProperty, @@ -64,7 +74,7 @@ const //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartCntr//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TengShaderPartCntr.AddChild(const aChild: TengShaderPart; const aPrepend: Boolean); +procedure TengShaderPartCntr.AddChild(const aChild: TengShaderCodePart; const aPrepend: Boolean); begin if aPrepend then fChildren.PushFirst(aChild) @@ -86,6 +96,10 @@ begin break; end; end; +{$IFDEF DEBUG} + if Assigned(p) then + LogMsg(llDebug, 'ParseText: ' + p.ClassName); +{$ENDIF} if Assigned(p) then result := p.ParseText(aArgs) else result := aToken; @@ -136,6 +150,20 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartCntr.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +var + p: TengShaderCodePart; +begin + aArgs.AddToken(GetTokenName); + try + for p in fChildren do + p.GenerateCodeIntern(aArgs); + finally + aArgs.AddToken(TOKEN_END); + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderPartCntr.Clear; begin @@ -146,7 +174,7 @@ end; constructor TengShaderPartCntr.Create(const aParent: TengShaderPart); begin inherited Create(aParent); - fChildren := TengShaderPartList.Create(true); + fChildren := TengShaderCodePartList.Create(true); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderPartComment.pas b/uengShaderPartComment.pas index 4a382c8..bbfcad1 100644 --- a/uengShaderPartComment.pas +++ b/uengShaderPartComment.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderFileParser; + uengShaderPart, uengShaderCodePart, uengShaderFileParser; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderPartEcho.pas b/uengShaderPartEcho.pas index 9a0ff20..d629e20 100644 --- a/uengShaderPartEcho.pas +++ b/uengShaderPartEcho.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderFileParser; + uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderPartKeyValuePair, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -15,10 +15,15 @@ type { Code Loading & Storage } private fName: String; + fValue: TengShaderPartKeyValuePair; protected function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { General } public class function GetTokenName: String; override; @@ -27,7 +32,7 @@ type implementation uses - uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; + uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartScope, uengShaderFile; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartEcho//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -39,6 +44,9 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartEcho.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; +var + sr: TengSearchResults; + walker: TengKeyValuePairSearchWalker; begin if (aParams[0].Name <> GetTokenName) then with aParams[0] do raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self); @@ -50,6 +58,32 @@ begin raise EengInvalidIdentifier.Create(Name, self); fName := Name; end; + sr := TengSearchResults.Create; + walker := TengKeyValuePairSearchWalker.Create(sr); + try + walker.Name := fName; + walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic); + walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope); + walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); + walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); + walker.SearchFlags := [ + sfSearchChildrenLazy, + sfSearchChildren, + sfSearchParents + ]; + walker.Run(self); + fValue := (ExtractSearchResult(self, fName, sr) as TengShaderPartKeyValuePair); + finally + FreeAndNil(walker); + FreeAndNil(sr); + end; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartEcho.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + inherited GenerateCodeIntern(aArgs); + aArgs.AddText(fValue.Value); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderPartIf.pas b/uengShaderPartIf.pas index 3a48556..8623b4f 100644 --- a/uengShaderPartIf.pas +++ b/uengShaderPartIf.pas @@ -7,16 +7,23 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderPartScope, uengShaderFileExpression, uengShaderFileParser; + uengShaderPart, uengShaderCodePart, uengShaderPartScope, uengShaderFileExpression, + uengShaderFileParser, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TengShaderPartIf = class(TengShaderCodePart) + TengShaderPartIfCntr = class(TengShaderPartScope) + { Class Methods } + public + class function GetTokenName: String; override; + end; + + TengShaderPartIf = class(TengShaderPartIfCntr) { Code Loading & Storage } private fExpression: TengExpressionItem; - fIfPart: TengShaderCodePart; - fElsePart: TengShaderCodePart; + fIfPart: TengShaderPartScope; + fElsePart: TengShaderPartScope; function HandleToken(const aToken: String; const aArgs: TengParseArgs): String; protected function HandeEndToken(const aToken: String; const aArgs: TengParseArgs): String; virtual; @@ -25,16 +32,17 @@ type function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; - { General } - protected - function FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; override; + { Code Generation } public - property Expression: TengExpressionItem read fExpression; - destructor Destroy; override; + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; - { Class Methods } + { General } public - class function GetTokenName: String; override; + property Expression: TengExpressionItem read fExpression; + property IfPart: TengShaderPartScope read fIfPart; + property ElsePart: TengShaderPartScope read fElsePart; + + destructor Destroy; override; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -64,17 +72,27 @@ implementation uses uengShaderFileTypes, uengShaderFileConstants, uengShaderFileHelper; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartIfCntr////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TengShaderPartIfCntr.GetTokenName: String; +begin + result := TOKEN_IF; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartIf////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartIf.HandleToken(const aToken: String; const aArgs: TengParseArgs): String; +type + CengShaderPartScope = class of TengShaderPartScope; const - TOKEN_CLASSES: array[0..1] of CengShaderCodePart = ( + TOKEN_CLASSES: array[0..1] of CengShaderPartScope = ( TengShaderPartElse, TengShaderPartElIf ); var - c: CengShaderCodePart; + c: CengShaderPartScope; begin for c in TOKEN_CLASSES do begin if c.CheckToken(aToken) then begin @@ -132,27 +150,23 @@ begin fExpression := ParseExpression(self, aParams, 1); - fIfPart := TengShaderPartScope.Create(self); + fIfPart := TengShaderPartIfCntr.Create(self); result := fIfPart.ParseText(aArgs); result := HandleToken(result, aArgs); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TengShaderPartIf.FindIntern(aFlags: TengSearchFlags; const aChild: TengShaderPart; const aResults: TengSearchResults): Boolean; +procedure TengShaderPartIf.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +var + b: Boolean; + p: TengShaderCodePart; begin - result := true; - if (sfEvaluateIf in aFlags) and (sfSearchChildren in aFlags) then begin - if fExpression.GetValue then begin - if Assigned(fIfPart) then - fIfPart.Find(aFlags, aResults); - end else begin - if Assigned(fElsePart) then - fElsePart.Find(aFlags, aResults); - end; - end; - if not (sfSearchAllIf in aFlags) and (sfSearchChildren in aFlags) then - aFlags := aFlags - [sfSearchChildren] + [sfSearchChildrenLazy]; - result := result and inherited FindIntern(aFlags, aChild, aResults); + b := fExpression.GetValue; + if b + then p := fIfPart + else p := fElsePart; + if Assigned(p) then + p.GenerateCodeIntern(aArgs); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -164,12 +178,6 @@ begin inherited Destroy; end; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TengShaderPartIf.GetTokenName: String; -begin - result := TOKEN_IF; -end; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartElIf//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderPartInclude.pas b/uengShaderPartInclude.pas index 5cccbca..8358d68 100644 --- a/uengShaderPartInclude.pas +++ b/uengShaderPartInclude.pas @@ -7,7 +7,8 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderFile, uengShaderFileParser, uengShaderFileTypes; + uengShaderPart, uengShaderCodePart, uengShaderFile, uengShaderFileParser, uengShaderFileTypes, + uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -24,6 +25,10 @@ type function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { General } public property IncludeFile: String read fIncludeFile; @@ -89,6 +94,15 @@ begin LoadShaderFile; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartInclude.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + LoadShaderFile; + inherited GenerateCodeIntern(aArgs); + if Assigned(fShaderFile) then + fShaderFile.GenerateCodeIntern(aArgs); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderPartInclude.SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter); begin diff --git a/uengShaderPartKeyValuePair.pas b/uengShaderPartKeyValuePair.pas index c15451e..77be90e 100644 --- a/uengShaderPartKeyValuePair.pas +++ b/uengShaderPartKeyValuePair.pas @@ -7,7 +7,12 @@ interface uses Classes, SysUtils, variants, - uengShaderPart, uengShaderFileParser; + uengShaderCodePart, uengShaderFileParser + +{$IFDEF USE_BITSPACE_UTILS} + , uutlGenerics +{$ENDIF} + ; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -16,26 +21,47 @@ type { Code Loading & Storage } private fName: String; - fValue: Variant; fValueName: String; + fDefaultValue: Variant; protected + fValue: Variant; function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; { General } public - property Name: String read fName; - property Value: Variant read fValue; - property ValueName: String read fValueName; + property Name: String read fName; + property ValueName: String read fValueName; + property Value: Variant read fValue; + property DefaultValue: Variant read fDefaultValue; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartProperty = class(TengShaderPartKeyValuePair) + { General } + public + property Value: Variant read fValue write fValue; + { Class Methods } public class function GetTokenName: String; override; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TengShaderPartPropertyList = class(specialize TutlSimpleList) + private + fValue: Variant; + public + property Value: Variant read fValue write fValue; + procedure ApplyValue; + constructor Create; + end; + + TengShaderPartPropertyMap = class(specialize TutlMap) + public + procedure ApplyValues; + end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartStatic = class(TengShaderPartKeyValuePair) { Class Methods } @@ -46,7 +72,35 @@ type implementation uses - uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; + uengShaderPart, uengShaderFile, uengShaderPartScope, uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartPropertyList///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartPropertyList.ApplyValue; +var + p: TengShaderPartProperty; +begin + for p in self do + p.Value := fValue; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderPartPropertyList.Create; +begin + inherited Create(false); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartPropertyMap///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartPropertyMap.ApplyValues; +var + l: TengShaderPartPropertyList; +begin + for l in self do + l.ApplyValue; +end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartKeyValuePair//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -65,6 +119,7 @@ end; function TengShaderPartKeyValuePair.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; var sr: TengSearchResults; + walker: TengKeyValuePairSearchWalker; begin if (aParams[0].Name <> GetTokenName) then with aParams[0] do raise EengInvalidToken.Create(ClassName, GetTokenName, Line, Col, Filename, self); @@ -77,15 +132,29 @@ begin raise EengInvalidIdentifier.Create(fName, Line, Col, Filename, self); if (aParams.Count >= 3) then if aParams[2].Quoted then begin - fValue := aParams[2].Name; - fValueName := ''; + fDefaultValue := aParams[2].Name; + fValue := fDefaultValue; + fValueName := ''; end else begin fValueName := aParams[2].Name; - sr := TkvpSearchResults.Create(fValueName, true, false); + sr := TengSearchResults.Create; + walker := TengKeyValuePairSearchWalker.Create(sr); try - Find(SEARCH_FLAG_CURRENT_SCOPE, sr); - fValue := (ExtractSearchResult(self, fValueName, sr) as TengShaderPartStatic).Value; + walker.Name := fValueName; + walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartStatic); + walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope); + walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); + walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); + walker.SearchFlags := [ + sfSearchChildrenLazy, + sfSearchChildren, + sfSearchParents + ]; + walker.Run(self); + fDefaultValue := (ExtractSearchResult(self, fValueName, sr) as TengShaderPartStatic).Value; + fValue := fDefaultValue; finally + FreeAndNil(walker); FreeAndNil(sr); end; end diff --git a/uengShaderPartMessage.pas b/uengShaderPartMessage.pas index 768957b..3765c8b 100644 --- a/uengShaderPartMessage.pas +++ b/uengShaderPartMessage.pas @@ -7,25 +7,158 @@ interface uses Classes, SysUtils, - uengShaderPart; + uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderFileTypes, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TengShaderPartMessage = class(TengShaderCodePart) + TengShaderPartInfo = class(TengShaderCodePart) + private + fMessage: String; + { Code Loading & Storage } + protected + fLogLevel: TengShaderPartLogLevel; + function GetText: String; override; + function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + + { General } + public + property Message: String read fMessage; + constructor Create(const aParent: TengShaderPart); override; + + { Class Methods } + public + class function GetTokenName: String; override; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TengShaderPartWarning = class(TengShaderPartMessage) + TengShaderPartWarning = class(TengShaderPartInfo) + { General } + public + constructor Create(const aParent: TengShaderPart); override; + { Class Methods } + public + class function GetTokenName: String; override; end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TengShaderPartError = class(TengShaderPartMessage) + TengShaderPartError = class(TengShaderPartInfo) + { General } + public + constructor Create(const aParent: TengShaderPart); override; + { Class Methods } + public + class function GetTokenName: String; override; + end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + EengShaderPartThrow = class(EengShaderPart); + TengShaderPartThrow = class(TengShaderPartInfo) + { General } + public + constructor Create(const aParent: TengShaderPart); override; + + { Class Methods } + public + class function GetTokenName: String; override; end; implementation +uses + uengShaderFileConstants; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartInfo///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderPartInfo.GetText: String; +begin + result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + TOKEN_CHAR_QUOTE + fMessage + TOKEN_CHAR_QUOTE + TOKEN_CHAR_END; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderPartInfo.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; +begin + if (aParams[0].Name <> GetTokenName) then with aParams[0] do + raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self); + if (aParams.Count <> 2) then + raise EengInvalidParamterCount.Create(GetTokenName, 2, self); + fMessage := aParams[1].Name; + result := inherited ParseIntern(aArgs, aParams); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartInfo.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + inherited GenerateCodeIntern(aArgs); + if (fLogLevel = llThrow) + then raise EengShaderPartThrow.Create(fMessage, self) + else LogMsg(fLogLevel, fMessage); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderPartInfo.Create(const aParent: TengShaderPart); +begin + inherited Create(aParent); + fLogLevel := llInfo; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TengShaderPartInfo.GetTokenName: String; +begin + result := TOKEN_INFO; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderPartWarning.Create(const aParent: TengShaderPart); +begin + inherited Create(aParent); + fLogLevel := llWarning; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartWarning///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TengShaderPartWarning.GetTokenName: String; +begin + result := TOKEN_WARNING; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderPartError.Create(const aParent: TengShaderPart); +begin + inherited Create(aParent); + fLogLevel := llError; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartError/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TengShaderPartError.GetTokenName: String; +begin + result := TOKEN_ERROR; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderPartThrow.Create(const aParent: TengShaderPart); +begin + inherited Create(aParent); + fLogLevel := llThrow; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartThrow/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TengShaderPartThrow.GetTokenName: String; +begin + result := TOKEN_THROW; +end; + end. diff --git a/uengShaderPartMeta.pas b/uengShaderPartMeta.pas index 86d3b36..985f195 100644 --- a/uengShaderPartMeta.pas +++ b/uengShaderPartMeta.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderFileParser; + uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -28,6 +28,8 @@ type property Name: String read fName; property Values: TStrings read GetValues; + procedure Assign(const aValues: TengMetaData); + constructor Create(const aName: String; const aType: TengMetaType); destructor Destroy; override; end; @@ -41,6 +43,10 @@ type function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { General } public property Data: TengMetaData read fData; @@ -65,6 +71,15 @@ begin result := fValues; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengMetaData.Assign(const aValues: TengMetaData); +begin + fName := aValues.Name; + fMetaType := aValues.MetaType; + fValues.Clear; + fValues.AddStrings(aValues.Values); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengMetaData.Create(const aName: String; const aType: TengMetaType); begin @@ -151,6 +166,13 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartMeta.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + inherited GenerateCodeIntern(aArgs); + aArgs.AddMeta(self); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPartMeta.Create(const aParent: TengShaderPart); begin diff --git a/uengShaderPartParameter.pas b/uengShaderPartParameter.pas index 9da1e16..ed9009d 100644 --- a/uengShaderPartParameter.pas +++ b/uengShaderPartParameter.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderFileParser; + uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -20,6 +20,10 @@ type function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { General } public property Name: String read fName; @@ -35,6 +39,10 @@ type function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { General } public property DefaultValue: String read fDefaultValue; @@ -46,6 +54,9 @@ type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartVarying = class(TengShaderPartParameter) + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; { Class Methods } public class function GetTokenName: String; override; @@ -53,6 +64,10 @@ type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartUniform = class(TengShaderPartParameter) + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { Class Methods } public class function GetTokenName: String; override; @@ -67,6 +82,10 @@ type function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { General } public property Value: String read fValue; @@ -105,6 +124,15 @@ begin fName := aParams[2].Name; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartParameter.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + if (gfAddParameterItem in aArgs.Flags) then begin + inherited GenerateCodeIntern(aArgs); + aArgs.AddParam(self); + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartVar///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -135,6 +163,15 @@ begin fDefaultValue := ''; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartVar.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + inherited GenerateCodeIntern(aArgs); + if (gfGenerateParameterItemCode in aArgs.Flags) then begin + // TODO + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartVar.GetTokenName: String; begin @@ -143,6 +180,15 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartVarying///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartVarying.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + inherited GenerateCodeIntern(aArgs); + if (gfGenerateParameterItemCode in aArgs.Flags) then begin + // TODO + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartVarying.GetTokenName: String; begin @@ -151,6 +197,15 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartUniform///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartUniform.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + inherited GenerateCodeIntern(aArgs); + if (gfGenerateParameterItemCode in aArgs.Flags) then begin + // TODO + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartUniform.GetTokenName: String; begin @@ -183,6 +238,15 @@ begin fValue := aParams[3].Name end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartConst.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + inherited GenerateCodeIntern(aArgs); + if (gfGenerateParameterItemCode in aArgs.Flags) then begin + // TODO + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartConst.GetTokenName: String; begin diff --git a/uengShaderPartScope.pas b/uengShaderPartScope.pas index a1b8cad..81b1d63 100644 --- a/uengShaderPartScope.pas +++ b/uengShaderPartScope.pas @@ -7,15 +7,30 @@ interface uses Classes, SysUtils, - uengShaderPartCntr; + uengShaderPartCntr, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderPartScope = class(TengShaderPartCntr) - + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; end; implementation +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartScope/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartScope.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + aArgs.BeginBlock; + try + inherited GenerateCodeIntern(aArgs); + finally + aArgs.EndBlock; + end; +end; + end. diff --git a/uengShaderPartText.pas b/uengShaderPartText.pas index d69f196..0f86bb4 100644 --- a/uengShaderPartText.pas +++ b/uengShaderPartText.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderFileParser; + uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -19,6 +19,12 @@ type protected function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + + { General } public property Text: String read fText; property IsEmpty: Boolean read GetIsEmpty; @@ -31,6 +37,10 @@ type function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { Class Methods } public class function GetTokenName: String; override; @@ -45,6 +55,10 @@ type function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + { Code Generation } + public + procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; + { Class Methods } public class function CheckToken(const aToken: String): Boolean; override; @@ -88,6 +102,12 @@ begin result := TOKEN_LINE_BREAK; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartText.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + aArgs.AddText(fText); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartLineBreak/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -105,6 +125,12 @@ begin result := ''; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartLineBreak.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + aArgs.AddLineBreak; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartLineBreak.GetTokenName: String; begin @@ -127,6 +153,12 @@ begin aArgs.NextCol; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartCommandEnd.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); +begin + aArgs.AddCommandEnd(fToken); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TengShaderPartCommandEnd.CheckToken(const aToken: String): Boolean; var