From b441d27477f2670f964ef4543209def029c04d8d Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 23 Aug 2015 15:45:47 +0200 Subject: [PATCH] * completed implementation of code loading and storage --- uengShaderCodeGenerator.pas | 150 +++++++++++++++++++++++++++++++-- uengShaderFile.pas | 66 ++++++++++++++- uengShaderFileConstants.pas | 4 +- uengShaderFileExpression.pas | 30 +------ uengShaderFileHelper.pas | 40 ++++++++- uengShaderPart.pas | 62 ++++++++------ uengShaderPartClass.pas | 68 ++++++++++++++- uengShaderPartCntr.pas | 5 +- uengShaderPartIf.pas | 10 +-- uengShaderPartKeyValuePair.pas | 28 +++--- uengShaderPartParameter.pas | 52 +++++++++++- 11 files changed, 428 insertions(+), 87 deletions(-) diff --git a/uengShaderCodeGenerator.pas b/uengShaderCodeGenerator.pas index a6b6db7..ec07e1e 100644 --- a/uengShaderCodeGenerator.pas +++ b/uengShaderCodeGenerator.pas @@ -7,14 +7,48 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderPartScope, uengShaderPartKeyValuePair; + uengShaderPart, uengShaderFileParser, uengShaderPartScope, uengShaderPartKeyValuePair + +{$IFDEF USE_BITSPACE_UTILS} + , uutlGenerics +{$ENDIF} + ; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TengShaderCodeGenerator = class(TengShaderPartScope) - { General } + { 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 - fProperties: TengShaderPartPropertyMap; + fPropertyMap: TPropertyMap; + + function GetPropertyByIndex(const aIndex: Integer): Variant; + function GetPropertyByName(const aName: String): Variant; + function GetPropertyCount: Integer; + function GetPropertyNames(const aIndex: Integer): String; + + procedure SetPropertyByIndex(const aIndex: Integer; aValue: Variant); + procedure SetPropertyByName(const aName: String; aValue: Variant); + protected + procedure AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean = true); + procedure CopyProperties(const aGen: TengShaderCodeGenerator); + procedure UpdateProperties; virtual; + function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + public + property PropertyByName [const aName: String]: Variant read GetPropertyByName write SetPropertyByName; + property PropertyByIndex[const aIndex: Integer]: Variant read GetPropertyByIndex write SetPropertyByIndex; + property PropertyNames [const aIndex: Integer]: String read GetPropertyNames; + property PropertyCount: Integer read GetPropertyCount; + + { General } public constructor Create(const aParent: TengShaderPart); override; destructor Destroy; override; @@ -22,19 +56,125 @@ type implementation +uses + uengShaderFileTypes; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderCodeGenerator.TPropertyList///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TengShaderCodeGenerator.TPropertyList.Create; +begin + inherited Create(false); +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderCodeGenerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderCodeGenerator.GetPropertyByIndex(const aIndex: Integer): Variant; +begin + result := fPropertyMap.ValueAt[aIndex].Value; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderCodeGenerator.GetPropertyByName(const aName: String): Variant; +var + l: TPropertyList; +begin + l := fPropertyMap[aName]; + if not Assigned(l) then + EengUnknownIdentifier.Create(aName, self); + result := l.Value; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderCodeGenerator.GetPropertyCount: Integer; +begin + result := fPropertyMap.Count; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderCodeGenerator.GetPropertyNames(const aIndex: Integer): String; +begin + result := fPropertyMap.KeyValuePairs[aIndex].Key; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderCodeGenerator.SetPropertyByIndex(const aIndex: Integer; aValue: Variant); +begin + fPropertyMap.ValueAt[aIndex].Value := aValue; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderCodeGenerator.SetPropertyByName(const aName: String; aValue: Variant); +var + l: TPropertyList; +begin + l := fPropertyMap[aName]; + if not Assigned(l) then + EengUnknownIdentifier.Create(aName, self); + l.Value := aValue; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderCodeGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean); +var + l: TPropertyList; + p: TengShaderPartProperty; + s: String; +begin + l := fPropertyMap[aProp.Name]; + if Assigned(l) then begin + if aShowWarning then begin + p := l.Last; + s := Format('use of duplicate identifier: %s (%s %d:%d)', [aProp.Name, aProp.Filename, aProp.Line + 1, aProp.Col]) + sLineBreak + + 'previously declared here:' + sLineBreak + + Format(' %s %d:%d', [p.Filename, p.Line + 1, p.Col]) + sLineBreak; + LogMsg(llWarning, s); + end; + end else begin + l := TPropertyList.Create; + fPropertyMap.Add(aProp.Name, l); + end; + l.Add(aProp); + if (aProp.Value <> Unassigned) then + l.Value := aProp.Value; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderCodeGenerator.CopyProperties(const aGen: TengShaderCodeGenerator); +var + l: TPropertyList; + p: TengShaderPartProperty; +begin + for l in fPropertyMap do + for p in l do + aGen.AddProperty(p, false); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderCodeGenerator.UpdateProperties; +begin + fPropertyMap.Clear; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderCodeGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; +begin + result := inherited ParseIntern(aArgs, aParams); + UpdateProperties; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderCodeGenerator.Create(const aParent: TengShaderPart); begin inherited Create(aParent); - fProperties := TengShaderPartPropertyMap.Create(false); + fPropertyMap := TPropertyMap.Create(true); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TengShaderCodeGenerator.Destroy; begin - FreeAndNil(fProperties); + FreeAndNil(fPropertyMap); inherited Destroy; end; diff --git a/uengShaderFile.pas b/uengShaderFile.pas index 262309c..f2df5e5 100644 --- a/uengShaderFile.pas +++ b/uengShaderFile.pas @@ -33,10 +33,12 @@ type function GetGenerator(const aName: String): TengShaderCodeGenerator; function GetGeneratorCount: Integer; function GetGeneratorNames(const aIndex: Integer): String; + procedure UpdateClasses; protected function GetFilename: String; override; function GetFileReader: IengShaderFileReader; override; function GetFileWriter: IengShaderFileWriter; override; + procedure UpdateProperties; override; public procedure LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader = nil); procedure SaveToFile(const aFilename: String; const aFileWriter: IengShaderFileWriter = nil); @@ -60,7 +62,7 @@ type implementation uses - uengShaderPartInclude; + uengShaderPartInclude, uengShaderPartKeyValuePair; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderFile//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -88,6 +90,40 @@ begin else result := fClasses.Keys[aIndex-1]; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderFile.UpdateClasses; + + procedure AddClass(const aClass: TengShaderPartClass); + var + c: TengShaderPartClass; + s: String; + begin + c := fClasses[aClass.Name]; + if Assigned(c) then begin + s := Format('use of duplicate identifier: %s (%s %d:%d)', [aClass.Name, aClass.Filename, aClass.Line + 1, aClass.Col]) + sLineBreak + + 'previously declared here:' + sLineBreak + + Format(' %s %d:%d', [c.Filename, c.Line + 1, c.Col]) + sLineBreak; + LogMsg(llWarning, s); + fClasses[aClass.Name] := aClass; + end else + fClasses.Add(aClass.Name, aClass); + end; + +var + sr: TengSearchResults; + p: TengShaderPart; +begin + sr := TengSearchResults.Create([TengShaderPartClass]); + try + Find([sfSearchChildren], sr); + fClasses.Clear; + for p in sr.GetReverseEnumerator do + AddClass(p as TengShaderPartClass); + finally + FreeAndNil(sr); + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderFile.GetFilename: String; begin @@ -110,6 +146,32 @@ begin result := Parent.FileWriter; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderFile.UpdateProperties; +var + sr: TengSearchResults; + p: TengShaderPart; +begin + inherited UpdateProperties; + + sr := TengSearchResults.Create([TengShaderFile]); + try + Find(SEARCH_FLAG_FILE_PROPERTIES, sr); + for p in sr.GetReverseEnumerator 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 + AddProperty(p as TengShaderPartProperty); + finally + FreeAndNil(sr); + end; +end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TengShaderFile.LoadFromFile(const aFilename: String; const aFileReader: IengShaderFileReader); @@ -135,6 +197,8 @@ begin token := ParseText(args); if (token <> '') then with args do raise EengShaderPart.Create('unknown token ''' + token + '''', Line, Col, Filename, self); + if (self = Root) then + UpdateClasses; finally FreeAndNil(args); end; diff --git a/uengShaderFileConstants.pas b/uengShaderFileConstants.pas index c9027f9..11fdb19 100644 --- a/uengShaderFileConstants.pas +++ b/uengShaderFileConstants.pas @@ -35,13 +35,13 @@ const TOKEN_LAYOUT = TOKEN_CHAR_IDENT + 'LAYOUT'; //{$META $LAYOUT '(line_strip, max_vertices = 6) out'} TOKEN_PROPERTY = TOKEN_CHAR_IDENT + 'PROPERTY'; //{$PROPERTY InvertRoughmap 'false'} - TOKEN_DEFINE = TOKEN_CHAR_IDENT + 'DEFINE'; //{$DEFINE RENDER_FACE_FRONT '0'} - TOKEN_UNDEF = TOKEN_CHAR_IDENT + 'UNDEF'; //{$UNDEF RENDER_FACE_FRONT} + TOKEN_STATIC = TOKEN_CHAR_IDENT + 'STATIC'; //{$STATIC RENDER_FACE_FRONT '0'} TOKEN_ECHO = TOKEN_CHAR_IDENT + 'ECHO'; //{$ECHO InvertRoughmap} TOKEN_VAR = TOKEN_CHAR_IDENT + 'VAR'; //{$VAR 'float' 'refractivity' '0.0'} TOKEN_VARYING = TOKEN_CHAR_IDENT + 'VARYING'; //{$VARYING 'vec3' 'vVertex'} TOKEN_UNIFORM = TOKEN_CHAR_IDENT + 'UNIFORM'; //{$UNIFORM 'sampler2D' 'uShadowMap'} + TOKEN_CONST = TOKEN_CHAR_IDENT + 'CONST'; //{$CONST 'int' 'test' '0'} TOKEN_CALL = TOKEN_CHAR_IDENT + 'CALL'; //{$CALL CalcLight} TOKEN_PROC = TOKEN_CHAR_IDENT + 'PROC'; //{$PROC CalcLight} Code... {$END} diff --git a/uengShaderFileExpression.pas b/uengShaderFileExpression.pas index 64a8466..91b2319 100644 --- a/uengShaderFileExpression.pas +++ b/uengShaderFileExpression.pas @@ -521,15 +521,6 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type - TkvpSearchResults = class(TengSearchResults) - private - fName: String; - protected - function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; override; - public - constructor Create(const aName: String); - end; - TExpectedParam = (exVariable, exValue, exGroupBegin, exGroupEnd, exUnaryOperation, exBinaryOperation); TExpectedParams = set of TExpectedParam; TExpressionParser = class(TObject) @@ -550,23 +541,6 @@ type constructor Create(const aParent: TengShaderPart; const aParams: TengTokenParameterList; const aIndex: Integer); end; -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TkvpSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TkvpSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; -begin - result := inherited CheckObj(aPart, aContinue); - if result then - result := ((aPart as TengShaderPartKeyValuePair).Name = fName); -end; - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TkvpSearchResults.Create(const aName: String); -begin - inherited Create([TengShaderPartKeyValuePair]); - fName := aName; -end; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TExpressionParser///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -712,9 +686,9 @@ begin end else if IsValidIdentifier(param.Name) then begin if not (exVariable in aExpected) then RaiseEx('unexpected variable:', param); - sr := TkvpSearchResults.Create(param.Name); + sr := TkvpSearchResults.Create(param.Name, true, true); try - fParent.Find([], sr); + fParent.Find(SEARCH_FLAG_CURRENT_SCOPE, sr); tmp := ExtractSearchResult(fParent, param.Name, sr, param.Line, param.Col); result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col); finally diff --git a/uengShaderFileHelper.pas b/uengShaderFileHelper.pas index 426438c..fce9f5f 100644 --- a/uengShaderFileHelper.pas +++ b/uengShaderFileHelper.pas @@ -12,11 +12,21 @@ function IsValidIdentifier(const aIdent: String): Boolean; function CheckEndToken(const aArgs: TengParseArgs; const aShaderPart: TengShaderPart): String; function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList; aLine: Integer = -1; aCol: Integer = -1; aFilename: String = ''): TengShaderPart; +type + TkvpSearchResults = class(TengSearchResults) + private + fName: String; + protected + function CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; override; + public + constructor Create(const aName: String; const aSearchDefines, aSearchProperties: Boolean); + end; + implementation uses sysutils, - uengShaderFileConstants, uengShaderFileTypes; + uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function IsValidIdentifier(const aIdent: String): Boolean; @@ -61,8 +71,6 @@ var i: Integer; begin result := nil; - if (aList.Count <= 0) then - exit; if Assigned(aSender) then begin if (aLine < 0) then aLine := aSender.Line; @@ -71,6 +79,8 @@ begin if (aFilename = '') then aFilename := aSender.Filename; end; + if (aList.Count <= 0) then + raise EengUnknownIdentifier.Create(aIdent, aLine, aCol, aFilename, aSender); result := aList[0]; if (aList.Count > 1) and Assigned(aSender) then begin s := Format('use of duplicate identifier: %s (%s %d:%d)', [aIdent, aList[0].Filename, aList[0].Line + 1, aList[0].Col]) + sLineBreak + @@ -84,5 +94,29 @@ begin end; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TkvpSearchResults///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TkvpSearchResults.CheckObj(const aPart: TengShaderPart; var aContinue: Boolean): Boolean; +begin + result := inherited CheckObj(aPart, aContinue); + if result then + result := ((aPart as TengShaderPartKeyValuePair).Name = fName); +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TkvpSearchResults.Create(const aName: String; const aSearchDefines, aSearchProperties: Boolean); +begin + if aSearchDefines and aSearchProperties then + inherited Create([TengShaderPartStatic, TengShaderPartProperty]) + else if aSearchDefines then + inherited Create([TengShaderPartStatic]) + else if aSearchProperties then + inherited Create([TengShaderPartProperty]) + else + inherited Create([]); + fName := aName; +end; + end. diff --git a/uengShaderPart.pas b/uengShaderPart.pas index 8d64107..978e9a6 100644 --- a/uengShaderPart.pas +++ b/uengShaderPart.pas @@ -22,7 +22,6 @@ type TengSearchFlag = ( sfEvaluateIf, // evaluate if statements before search and process with suitable subtree sfSearchAllIf, // search in all if sub trees - sfIncludeSelf, // add item to search results where search has started sfSearchPrevOnly, // search in previous items only sfSearchInherited, // search in inherited @@ -53,14 +52,23 @@ type const SEARCH_FLAG_CURRENT_SCOPE = [ sfSearchPrevOnly, - sfSearchInherited, // search in inherited - - sfSearchChildrenLazy, // set sfSearchChildren in next recursion level - sfChildrenOnlyScope, // do not leave current scope when searching for children - sfChildrenForceFile, // overwrite sfChildrenOnlyXXX flag when item is a file - - sfSearchParents, // search in Parents - sfParentsOnlyFile // do not leave current file when searching in parents + sfSearchInherited, + sfSearchChildrenLazy, + sfChildrenOnlyScope, + sfChildrenForceFile, + sfSearchParents, + sfParentsOnlyFile + ]; + SEARCH_FLAG_CLASS_PROPERTIES = [ + sfSearchAllIf, + sfSearchChildren, + sfChildrenOnlyGenerator, + sfChildrenForceFile + ]; + SEARCH_FLAG_FILE_PROPERTIES = [ + sfSearchAllIf, + sfSearchChildren, + sfChildrenOnlyGenerator ]; type @@ -290,24 +298,23 @@ function TengShaderPart.FindIntern(aFlags: TengSearchFlags; const aChild: TengSh exit; result := result and Assigned(aItem) and - (not (sfChildrenOnlyFile in aFlags) or not (self is TengShaderFile)) and - (not (sfChildrenOnlyClass in aFlags) or not (self is TengShaderPartClass)) and - (not (sfChildrenOnlyGenerator in aFlags) or not (self is TengShaderCodeGenerator)) and - (not (sfChildrenOnlyScope in aFlags) or not (self is TengShaderPartScope)); + (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 (self is TengShaderFile)) or - ((sfChildrenForceClass in aFlags) and (self is TengShaderPartClass)) or - ((sfChildrenForceGenerator in aFlags) and (self is TengShaderCodeGenerator)) or - ((sfChildrenForceScope in aFlags) and (self is TengShaderPartScope)); + ((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(const aItem: TengShaderPart): Boolean; + function VisitParent: Boolean; begin result := (sfSearchParents in aFlags); if not result then exit; result := result and - Assigned(aItem) and (not (sfParentsOnlyFile in aFlags) or not (self is TengShaderFile)) and (not (sfParentsOnlyClass in aFlags) or not (self is TengShaderPartClass)) and (not (sfParentsOnlyGenerator in aFlags) or not (self is TengShaderCodeGenerator)) and @@ -330,20 +337,23 @@ begin b := b or (c = aChild); if (sfSearchPrevOnly in aFlags) and not b then continue; - if (c <> aChild) and VisitChild(c) then - result := result and c.FindIntern(aFlags - [sfSearchParents] + [sfIncludeSelf], nil, aResults); + 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 (sfIncludeSelf in aFlags) then - result := result and aResults.Add(self); - if (sfSearchChildrenLazy in aFlags) then aFlags := aFlags + [sfSearchChildren] - [sfSearchChildrenLazy]; - if VisitParent(Parent) then - result := result and Parent.FindIntern(aFlags + [sfIncludeSelf], self, aResults); + 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; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/uengShaderPartClass.pas b/uengShaderPartClass.pas index 639e8ac..12bf179 100644 --- a/uengShaderPartClass.pas +++ b/uengShaderPartClass.pas @@ -16,21 +16,27 @@ uses type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TengShaderPartClass = class; + TengShaderPartClassList = specialize TutlSimpleList; TengShaderPartClass = class(TengShaderCodeGenerator) { Code Loading & Storage } private { member } fName: String; fExtends: TStringList; + fInherited: TengShaderPartClassList; private { getter } function GetExtends: TStrings; + procedure UpdateInherited; protected { virtual getter } function GetText: String; override; function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + procedure UpdateProperties; override; { General } public property Name: String read fName; property Extends: TStrings read GetExtends; + constructor Create(const aParent: TengShaderPart); override; destructor Destroy; override; @@ -44,7 +50,7 @@ type implementation uses - uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; + uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TengShaderPartClass/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -54,6 +60,41 @@ begin result := fExtends; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartClass.UpdateInherited; + + procedure FilterResults(const aName: String; const aResults, aNewResults: TengShaderPartList); + var + p: TengShaderPart; + begin + aNewResults.Clear; + for p in aResults do + if ((p as TengShaderPartClass).Name = aName) then + aNewResults.Add(p); + end; + +var + sr: TengSearchResults; + res: TengShaderPartList; + s: String; +begin + if (fExtends.Count <= 0) then + exit; + sr := TengSearchResults.Create([TengShaderPartClass]); + res := TengShaderPartList.Create(false); + try + fInherited.Clear; + Find(SEARCH_FLAG_CURRENT_SCOPE, sr); + for s in fExtends do begin + FilterResults(s, sr, res); + fInherited.Add(ExtractSearchResult(self, s, res) as TengShaderPartClass); + end; + finally + FreeAndNil(res); + FreeAndNil(sr); + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartClass.GetText: String; var @@ -93,20 +134,45 @@ begin for i := 3 to aParams.Count-1 do fExtends.Add(aParams[i].Name); end; + UpdateInherited; result := inherited ParseIntern(aArgs, aParams); result := CheckEndToken(aArgs, self); end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TengShaderPartClass.UpdateProperties; +var + sr: TengSearchResults; + p: TengShaderPart; + c: TengShaderPartClass; +begin + inherited UpdateProperties; + + for c in fInherited do + c.CopyProperties(self); + + sr := TengSearchResults.Create([TengShaderPartProperty]); + try + Find(SEARCH_FLAG_CLASS_PROPERTIES, sr); + for p in sr.GetReverseEnumerator do + AddProperty(p as TengShaderPartProperty); + finally + FreeAndNil(sr); + end; +end; + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TengShaderPartClass.Create(const aParent: TengShaderPart); begin inherited Create(aParent); fExtends := TStringList.Create; + fInherited := TengShaderPartClassList.Create(false); end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TengShaderPartClass.Destroy; begin + FreeAndNil(fInherited); FreeAndNil(fExtends); inherited Destroy; end; diff --git a/uengShaderPartCntr.pas b/uengShaderPartCntr.pas index c2ca3f3..3d73fb3 100644 --- a/uengShaderPartCntr.pas +++ b/uengShaderPartCntr.pas @@ -36,10 +36,11 @@ uses uengShaderPartInclude, uengShaderPartParameter, uengShaderPartComment; const - TOKEN_CLASSES: array[0..20] of CengShaderCodePart = ( + TOKEN_CLASSES: array[0..21] of CengShaderCodePart = ( TengShaderPartCall, TengShaderPartClass, - TengShaderPartDefine, + TengShaderPartConst, + TengShaderPartStatic, TengShaderPartLineBreak, TengShaderPartCommandEnd, TengShaderPartComment, diff --git a/uengShaderPartIf.pas b/uengShaderPartIf.pas index f0fea46..3a48556 100644 --- a/uengShaderPartIf.pas +++ b/uengShaderPartIf.pas @@ -7,7 +7,7 @@ interface uses Classes, SysUtils, - uengShaderPart, uengShaderPartCntr, uengShaderFileExpression, uengShaderFileParser; + uengShaderPart, uengShaderPartScope, uengShaderFileExpression, uengShaderFileParser; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -49,7 +49,7 @@ type end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TengShaderPartElse = class(TengShaderPartCntr) + TengShaderPartElse = class(TengShaderPartScope) { Code Loading & Storage } protected function GetText: String; override; @@ -132,7 +132,7 @@ begin fExpression := ParseExpression(self, aParams, 1); - fIfPart := TengShaderPartCntr.Create(self); + fIfPart := TengShaderPartScope.Create(self); result := fIfPart.ParseText(aArgs); result := HandleToken(result, aArgs); end; @@ -150,8 +150,8 @@ begin fElsePart.Find(aFlags, aResults); end; end; - if not (sfSearchAllIf in aFlags) then - exclude(aFlags, sfSearchChildren); + if not (sfSearchAllIf in aFlags) and (sfSearchChildren in aFlags) then + aFlags := aFlags - [sfSearchChildren] + [sfSearchChildrenLazy]; result := result and inherited FindIntern(aFlags, aChild, aResults); end; diff --git a/uengShaderPartKeyValuePair.pas b/uengShaderPartKeyValuePair.pas index 65bbcdb..c15451e 100644 --- a/uengShaderPartKeyValuePair.pas +++ b/uengShaderPartKeyValuePair.pas @@ -7,15 +7,11 @@ interface uses Classes, SysUtils, variants, - uengShaderPart, uengShaderFileParser - -{$IFDEF USE_BITSPACE_UTILS} - , uutlGenerics -{$ENDIF} - ; + uengShaderPart, uengShaderFileParser; type //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TengShaderPartStatic = class; TengShaderPartKeyValuePair = class(TengShaderCodePart) { Code Loading & Storage } private @@ -39,10 +35,9 @@ type public class function GetTokenName: String; override; end; - TengShaderPartPropertyMap = specialize TutlMap; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TengShaderPartDefine = class(TengShaderPartKeyValuePair) + TengShaderPartStatic = class(TengShaderPartKeyValuePair) { Class Methods } public class function GetTokenName: String; override; @@ -68,6 +63,8 @@ end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartKeyValuePair.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; +var + sr: TengSearchResults; begin if (aParams[0].Name <> GetTokenName) then with aParams[0] do raise EengInvalidToken.Create(ClassName, GetTokenName, Line, Col, Filename, self); @@ -83,9 +80,14 @@ begin fValue := aParams[2].Name; fValueName := ''; end else begin - // TODO resolve name and set value - fValue := Unassigned; fValueName := aParams[2].Name; + sr := TkvpSearchResults.Create(fValueName, true, false); + try + Find(SEARCH_FLAG_CURRENT_SCOPE, sr); + fValue := (ExtractSearchResult(self, fValueName, sr) as TengShaderPartStatic).Value; + finally + FreeAndNil(sr); + end; end else begin fValue := Unassigned; @@ -102,11 +104,11 @@ begin end; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TengShaderPartDefine////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartStatic////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TengShaderPartDefine.GetTokenName: String; +class function TengShaderPartStatic.GetTokenName: String; begin - result := TOKEN_DEFINE; + result := TOKEN_STATIC; end; end. diff --git a/uengShaderPartParameter.pas b/uengShaderPartParameter.pas index 66359b2..9da1e16 100644 --- a/uengShaderPartParameter.pas +++ b/uengShaderPartParameter.pas @@ -58,13 +58,31 @@ type class function GetTokenName: String; override; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TengShaderPartConst = class(TengShaderPartParameter) + { Code Loading & Storage } + private + fValue: String; + protected + function GetText: String; override; + function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; + + { General } + public + property Value: String read fValue; + + { Class Methods } + public + class function GetTokenName: String; override; + end; + implementation uses uengShaderFileConstants, uengShaderFileTypes; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartParameter/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TengShaderPartParameter.GetText: String; begin @@ -139,5 +157,37 @@ begin result := TOKEN_UNIFORM; end; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TengShaderPartConst/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderPartConst.GetText: String; +begin + result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + + TOKEN_CHAR_QUOTE + fType + TOKEN_CHAR_QUOTE + ' ' + + TOKEN_CHAR_QUOTE + fName + TOKEN_CHAR_QUOTE + ' ' + + TOKEN_CHAR_QUOTE + fValue + TOKEN_CHAR_QUOTE + + TOKEN_CHAR_END; +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TengShaderPartConst.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 <> 4) then + raise EengInvalidParamterCount.Create(GetTokenName, 4, self); + + result := ''; + fType := aParams[1].Name; + fName := aParams[2].Name; + fValue := aParams[3].Name +end; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TengShaderPartConst.GetTokenName: String; +begin + result := TOKEN_CONST; +end; + end.