| @@ -23,7 +23,7 @@ uses | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengShaderFileLogEvent = procedure(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String) of object; | |||
| TengShaderFile = class(TengShaderCodeGenerator) | |||
| TengShaderFile = class(TengShaderGenerator) | |||
| { Code Loading & Storage } | |||
| private | |||
| fFilename: String; | |||
| @@ -31,7 +31,7 @@ type | |||
| fFileWriter: IutlFileWriter; | |||
| fClasses: TengShaderPartClassMap; | |||
| private | |||
| function GetGenerator(const aName: String): TengShaderCodeGenerator; | |||
| function GetGenerator(const aName: String): TengShaderGenerator; | |||
| function GetGeneratorCount: Integer; | |||
| function GetGeneratorNames(const aIndex: Integer): String; | |||
| procedure UpdateClasses; | |||
| @@ -54,7 +54,7 @@ type | |||
| protected | |||
| procedure LogMsgIntern(const aSender: TengShaderPart; const aLogLevel: TengShaderPartLogLevel; const aMsg: String); override; | |||
| public | |||
| property Generator [const aName: String]: TengShaderCodeGenerator read GetGenerator; | |||
| property Generator [const aName: String]: TengShaderGenerator read GetGenerator; | |||
| property GeneratorNames[const aIndex: Integer]: String read GetGeneratorNames; | |||
| property GeneratorCount: Integer read GetGeneratorCount; | |||
| property OnLog: TengShaderFileLogEvent read fOnLog write fOnLog; | |||
| @@ -67,12 +67,12 @@ type | |||
| implementation | |||
| uses | |||
| uengShaderPartInclude, uengShaderPartKeyValuePair, uengShaderFileHelper; | |||
| uengShaderPartInclude, uengShaderPartKeyValuePair, uengShaderFileHelper, uengShaderPartProc; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderFile//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderFile.GetGenerator(const aName: String): TengShaderCodeGenerator; | |||
| function TengShaderFile.GetGenerator(const aName: String): TengShaderGenerator; | |||
| begin | |||
| result := fClasses[aName]; | |||
| if not Assigned(result) then | |||
| @@ -170,7 +170,7 @@ begin | |||
| walker.Owner := self; | |||
| walker.SearchFlags := [sfSearchChildren, sfIgnoreOwner]; | |||
| walker.ResultTypes := CengShaderPartArr.Create(TengShaderFile); | |||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderCodeGenerator); | |||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator); | |||
| walker.Run(self); | |||
| for p in sr do | |||
| (p as TengShaderFile).CopyProperties(self); | |||
| @@ -260,10 +260,34 @@ end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderFile.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| var | |||
| sr: TengSearchResults; | |||
| walker: TengSearchWalker; | |||
| main: TengShaderPartMain; | |||
| begin | |||
| inherited GenerateCodeIntern(aArgs); | |||
| if (aArgs.Root = self) then begin | |||
| // TODO generate main routine code (if exists) | |||
| sr := TengSearchResults.Create; | |||
| walker := TengSearchWalker.Create(sr); | |||
| try | |||
| walker.SearchFlags := [sfSearchChildren, sfEvaluateIf]; | |||
| walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain); | |||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator); | |||
| walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); | |||
| walker.Run(self); | |||
| main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr, []) as TengShaderPartMain); | |||
| if Assigned(main) then begin | |||
| aArgs.PushFlags((aArgs.Flags * [gfAddProcedureItem, gfAddParameterItem]) + [gfGenerateProcedureCode]); | |||
| try | |||
| main.GenerateCodeIntern(aArgs); | |||
| finally | |||
| aArgs.PopFlags; | |||
| end; | |||
| end; | |||
| finally | |||
| FreeAndNil(walker); | |||
| FreeAndNil(sr); | |||
| end; | |||
| end; | |||
| end; | |||
| @@ -25,7 +25,7 @@ const | |||
| TOKEN_CLASS = TOKEN_CHAR_IDENT + 'CLASS'; //{$CLASS PhongLight $EXTENDS Normal Glow} | |||
| TOKEN_EXTENDS = TOKEN_CHAR_IDENT + 'EXTENDS'; | |||
| TOKEN_INHERITED = TOKEN_CHAR_IDENT + 'INHERITED'; //{$INHERITED} {$INHERITED BaseClass} | |||
| TOKEN_INHERITED = TOKEN_CHAR_IDENT + 'INHERITED'; //{$INHERITED BaseClassMethod 'param1' 'param2'} | |||
| TOKEN_INCLUDE = TOKEN_CHAR_IDENT + 'INCLUDE'; //{$INCLUDE 'Normal.frag'} | |||
| @@ -85,6 +85,7 @@ const | |||
| TOKEN_SPLIT_CHARS = [' ', #9, TOKEN_OP_GROUP_BEGIN, TOKEN_OP_GROUP_END]; | |||
| COMMAND_END_TOKENS = [TOKEN_CHAR_COMMANT_END, TOKEN_CHAR_SCOPE_BEGIN, TOKEN_CHAR_SCOPE_END]; | |||
| LAYOUT_MIN_VERSION = 150; | |||
| VERSION_EXTRA_COMPAT = 'compatibility'; //{$META $VERSION 'compatibility'} | |||
| implementation | |||
| @@ -692,14 +692,14 @@ begin | |||
| sr := TengSearchResults.Create; | |||
| walker := TengKeyValuePairSearchWalker.Create(sr); | |||
| try | |||
| walker.Name := param.Name; | |||
| walker.SearchFlags := [sfSearchChildrenLazy, sfSearchParents]; | |||
| walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic); | |||
| 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.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); | |||
| walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); | |||
| walker.Run(fParent); | |||
| tmp := ExtractSearchResult(fParent, param.Name, sr, param.Line, param.Col); | |||
| tmp := ExtractSearchResult(fParent, param.Name, sr, [ifWarning, ifRaiseEx], param.Line, param.Col); | |||
| result := TengExpressionVariable.Create(param.Name, (tmp as TengShaderPartKeyValuePair), param.Line, param.Col); | |||
| finally | |||
| FreeAndNil(walker); | |||
| @@ -8,15 +8,33 @@ interface | |||
| uses | |||
| uengShaderPart, uengShaderFileParser; | |||
| type | |||
| TInfoFlag = ( | |||
| ifWarning, | |||
| ifRaiseEx | |||
| ); | |||
| TInfoFlags = set of TInfoFlag; | |||
| 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; | |||
| function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean; | |||
| function ExtractSearchResult( | |||
| const aSender: TengShaderPart; | |||
| const aIdent: String; | |||
| const aList: TengShaderPartList; | |||
| const aFlags: TInfoFlags = [ifWarning, ifRaiseEx]; | |||
| aLine: Integer = -1; | |||
| aCol: Integer = -1; | |||
| aFilename: String = ''): TengShaderPart; | |||
| type | |||
| TengSearchFlag = ( | |||
| sfSearchChildren, // search in children | |||
| sfEvaluateIf, // evaluate if and search in suitable subtree | |||
| sfIgnoreIf, // do not search in if items | |||
| sfSearchChildrenLazy, // set sfSearchChildren in next recursion level | |||
| sfSearchParents, // search in Parents | |||
| sfSearchInherited, // search in inherited classes | |||
| sfIgnoreOwner // ignore owner of search walker | |||
| ); | |||
| TengSearchFlags = set of TengSearchFlag; | |||
| @@ -65,11 +83,21 @@ type | |||
| property Name: String read fName write fName; | |||
| end; | |||
| TengProcSearchWalker = class(TengSearchWalker) | |||
| private | |||
| fName: String; | |||
| protected | |||
| function Check(const aPart: TengShaderPart): Boolean; override; | |||
| public | |||
| property Name: String read fName write fName; | |||
| constructor Create(const aResults: TengSearchResults); | |||
| end; | |||
| implementation | |||
| uses | |||
| sysutils, | |||
| uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair; | |||
| uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair, uengShaderPartProc, uengShaderPartIf; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function IsValidIdentifier(const aIdent: String): Boolean; | |||
| @@ -106,9 +134,21 @@ begin | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function CheckType(const aShaderPart: TengShaderPart; const aTypes: array of CengShaderPart): Boolean; | |||
| var | |||
| t: CengShaderPart; | |||
| begin | |||
| result := true; | |||
| for t in aTypes do | |||
| if (aShaderPart is t) then | |||
| exit; | |||
| result := (Length(aTypes) = 0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function ExtractSearchResult(const aSender: TengShaderPart; const aIdent: String; const aList: TengShaderPartList; | |||
| aLine: Integer; aCol: Integer; aFilename: String): TengShaderPart; | |||
| const aFlags: TInfoFlags; aLine: Integer; aCol: Integer; aFilename: String): TengShaderPart; | |||
| var | |||
| s: String; | |||
| i: Integer; | |||
| @@ -122,10 +162,13 @@ begin | |||
| if (aFilename = '') then | |||
| aFilename := aSender.Filename; | |||
| end; | |||
| if (aList.Count <= 0) then | |||
| raise EengUnknownIdentifier.Create(aIdent, aLine, aCol, aFilename, aSender); | |||
| if (aList.Count <= 0) then begin | |||
| if (ifRaiseEx in aFlags) then | |||
| raise EengUnknownIdentifier.Create(aIdent, aLine, aCol, aFilename, aSender); | |||
| exit; | |||
| end; | |||
| result := aList[aList.Count-1]; | |||
| if (aList.Count > 1) and Assigned(aSender) then begin | |||
| if (aList.Count > 1) and Assigned(aSender) and (ifWarning in aFlags) then begin | |||
| s := Format('use of duplicate identifier: %s (%s %d:%d)', [aIdent, result.Filename, result.Line + 1, result.Col]) + sLineBreak + | |||
| 'previously declared here:' + sLineBreak; | |||
| i := aList.Count - 2; | |||
| @@ -183,7 +226,7 @@ var | |||
| end; | |||
| var | |||
| c: TengShaderPart; | |||
| p: TengShaderPart; | |||
| nextArgs: TArgs; | |||
| begin | |||
| if not Assigned(aPart) then | |||
| @@ -193,6 +236,7 @@ begin | |||
| else | |||
| args.Flags := fSearchFlags; | |||
| // visit parent | |||
| nextArgs := args; | |||
| if (sfSearchChildrenLazy in nextArgs.Flags) then | |||
| nextArgs.Flags := nextArgs.Flags + [sfSearchChildren] - [sfSearchChildrenLazy]; | |||
| @@ -201,12 +245,25 @@ begin | |||
| if VisitParent then | |||
| Visit(aPart.Parent, aPart, @nextArgs); | |||
| // visit children | |||
| 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); | |||
| if (aPart is TengShaderPartIf) then with (aPart as TengShaderPartIf) do begin | |||
| if (sfEvaluateIf in args.Flags) then begin | |||
| if Expression.GetValue | |||
| then p := IfPart | |||
| else p := ElsePart; | |||
| if Assigned(p) then | |||
| Visit(p, aPart, @args); | |||
| exit; | |||
| end else if (sfIgnoreIf in args.Flags) then | |||
| exit; | |||
| end; | |||
| for p in aPart do begin | |||
| if Check(p) then | |||
| fResults.Add(p); | |||
| if VisitChild(p) then | |||
| Visit(p, aPart, @args); | |||
| end; | |||
| end; | |||
| end; | |||
| @@ -242,5 +299,23 @@ begin | |||
| ((aPart as TengShaderPartKeyValuePair).Name = fName); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengProcSearchWalker////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengProcSearchWalker.Check(const aPart: TengShaderPart): Boolean; | |||
| begin | |||
| result := | |||
| inherited Check(aPart) and | |||
| (aPart is TengShaderPartProc) and | |||
| ((aPart as TengShaderPartProc).Name = fName); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TengProcSearchWalker.Create(const aResults: TengSearchResults); | |||
| begin | |||
| inherited Create(aResults); | |||
| ResultTypes := CengShaderPartArr.Create(TengShaderPartProc); | |||
| end; | |||
| end. | |||
| @@ -9,7 +9,7 @@ uses | |||
| Classes, SysUtils | |||
| {$IFDEF USE_BITSPACE_UTILS} | |||
| , uutlSerialization, uutlCommon | |||
| , uutlSerialization, uutlCommon, uutlGenerics | |||
| {$ENDIF} | |||
| ; | |||
| @@ -36,6 +36,33 @@ type | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengMetaType = ( | |||
| metaUnknown, | |||
| metaNormal, | |||
| metaVersion, | |||
| metaExtension, | |||
| metaLayout); | |||
| TengMetaData = class(TObject) | |||
| private | |||
| fMetaType: TengMetaType; | |||
| fName: String; | |||
| fValues: TStringList; | |||
| function GetCount: Integer; | |||
| function GetValues: TStrings; | |||
| public | |||
| property MetaType: TengMetaType read fMetaType; | |||
| property Name: String read fName; | |||
| property Count: Integer read GetCount; | |||
| property Values: TStrings read GetValues; | |||
| procedure Assign(const aValues: TengMetaData); | |||
| constructor Create(const aName: String; const aType: TengMetaType); | |||
| destructor Destroy; override; | |||
| end; | |||
| TengMetaDataList = specialize TutlSimpleList<TengMetaData>; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //Exceptions//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -159,6 +186,45 @@ implementation | |||
| uses | |||
| uengShaderPart; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengMetaData////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengMetaData.GetCount: Integer; | |||
| begin | |||
| result := fValues.Count; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengMetaData.GetValues: TStrings; | |||
| 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 | |||
| inherited Create; | |||
| fName := aName; | |||
| fMetaType := aType; | |||
| fValues := TStringList.Create; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| destructor TengMetaData.Destroy; | |||
| begin | |||
| FreeAndNil(fValues); | |||
| inherited Destroy; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //EengExpressionInternal//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -12,7 +12,7 @@ uses | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengShaderCodeGenerator = class(TengShaderPartScope) | |||
| TengShaderGenerator = class(TengShaderPartScope) | |||
| { Code Loading & Storage } | |||
| private | |||
| fPropertyMap: TengShaderPartPropertyMap; | |||
| @@ -26,7 +26,7 @@ type | |||
| procedure SetPropertyByName(const aName: String; aValue: Variant); | |||
| protected | |||
| procedure AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean = true); | |||
| procedure CopyProperties(const aGen: TengShaderCodeGenerator); | |||
| procedure CopyProperties(const aGen: TengShaderGenerator); | |||
| procedure UpdateProperties; virtual; | |||
| function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||
| public | |||
| @@ -48,15 +48,15 @@ type | |||
| implementation | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderCodeGenerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderGenerator/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderCodeGenerator.GetPropertyByIndex(const aIndex: Integer): Variant; | |||
| function TengShaderGenerator.GetPropertyByIndex(const aIndex: Integer): Variant; | |||
| begin | |||
| result := fPropertyMap.ValueAt[aIndex].Value; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderCodeGenerator.GetPropertyByName(const aName: String): Variant; | |||
| function TengShaderGenerator.GetPropertyByName(const aName: String): Variant; | |||
| var | |||
| l: TengShaderPartPropertyList; | |||
| begin | |||
| @@ -67,25 +67,25 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderCodeGenerator.GetPropertyCount: Integer; | |||
| function TengShaderGenerator.GetPropertyCount: Integer; | |||
| begin | |||
| result := fPropertyMap.Count; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderCodeGenerator.GetPropertyNames(const aIndex: Integer): String; | |||
| function TengShaderGenerator.GetPropertyNames(const aIndex: Integer): String; | |||
| begin | |||
| result := fPropertyMap.KeyValuePairs[aIndex].Key; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderCodeGenerator.SetPropertyByIndex(const aIndex: Integer; aValue: Variant); | |||
| procedure TengShaderGenerator.SetPropertyByIndex(const aIndex: Integer; aValue: Variant); | |||
| begin | |||
| fPropertyMap.ValueAt[aIndex].Value := aValue; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderCodeGenerator.SetPropertyByName(const aName: String; aValue: Variant); | |||
| procedure TengShaderGenerator.SetPropertyByName(const aName: String; aValue: Variant); | |||
| var | |||
| l: TengShaderPartPropertyList; | |||
| begin | |||
| @@ -96,7 +96,7 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderCodeGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean); | |||
| procedure TengShaderGenerator.AddProperty(const aProp: TengShaderPartProperty; const aShowWarning: Boolean); | |||
| var | |||
| l: TengShaderPartPropertyList; | |||
| p: TengShaderPartProperty; | |||
| @@ -121,7 +121,7 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderCodeGenerator.CopyProperties(const aGen: TengShaderCodeGenerator); | |||
| procedure TengShaderGenerator.CopyProperties(const aGen: TengShaderGenerator); | |||
| var | |||
| l: TengShaderPartPropertyList; | |||
| p: TengShaderPartProperty; | |||
| @@ -132,26 +132,27 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderCodeGenerator.UpdateProperties; | |||
| procedure TengShaderGenerator.UpdateProperties; | |||
| begin | |||
| fPropertyMap.Clear; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderCodeGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||
| function TengShaderGenerator.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | |||
| begin | |||
| result := inherited ParseIntern(aArgs, aParams); | |||
| UpdateProperties; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderCodeGenerator.GenerateCode(const aCode: TengShaderCode); | |||
| procedure TengShaderGenerator.GenerateCode(const aCode: TengShaderCode); | |||
| var | |||
| args: TengShaderGeneratorArgs; | |||
| begin | |||
| args := TengShaderGeneratorArgs.Create(self); | |||
| try | |||
| inherited GenerateCodeIntern(args); | |||
| fPropertyMap.ApplyValues; | |||
| GenerateCodeIntern(args); | |||
| args.GenerateCode(aCode); | |||
| finally | |||
| FreeAndNil(args); | |||
| @@ -159,14 +160,14 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TengShaderCodeGenerator.Create(const aParent: TengShaderPart); | |||
| constructor TengShaderGenerator.Create(const aParent: TengShaderPart); | |||
| begin | |||
| inherited Create(aParent); | |||
| fPropertyMap := TengShaderPartPropertyMap.Create(true); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| destructor TengShaderCodeGenerator.Destroy; | |||
| destructor TengShaderGenerator.Destroy; | |||
| begin | |||
| FreeAndNil(fPropertyMap); | |||
| inherited Destroy; | |||
| @@ -17,33 +17,52 @@ uses | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengGenerateFlag = ( | |||
| gfGenerateParameterItemCode, // generate code for parameter items | |||
| gfAddParameterItem // add parameter items to generator args | |||
| gfGenerateProcedureCode, // generate procedure code | |||
| gfGenerateProcedureCall, // generate procedure call | |||
| gfGenerateInlineCode, // generate procedure as inline code | |||
| gfGenerateParameterCode, // generate code for parameter items | |||
| gfAddProcedureItem, // add procedure item to generator args | |||
| gfAddParameterItem // add parameter items to generator args | |||
| ); | |||
| TengGenerateFlags = set of TengGenerateFlag; | |||
| TengGenerateFlagsStack = specialize TutlSimpleList<TengGenerateFlags>; | |||
| TengPopCodeFlag = ( | |||
| pcfAppend, | |||
| pcfPrepend, | |||
| pcfAddEmptyLine | |||
| ); | |||
| TengPopCodeFlags = set of TengPopCodeFlag; | |||
| 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') | |||
| gtNormal = 0, // normal text | |||
| gtLineBreak = 1, // line break | |||
| gtCommandEnd = 2, // command end (like ';') | |||
| gtBlockBegin = 3, // code block begin (to calculate indent) | |||
| gtBlockEnd = 4, // code block end (to calculate indent) | |||
| gtToken = 5 // code token (like '$INCLUDE' or '$IF') | |||
| ); | |||
| TCodePart = class(TObject) | |||
| private | |||
| fText: String; | |||
| fIndent: Integer; | |||
| fToken: TengGeneratorToken; | |||
| function GetText: String; | |||
| function GetDebugText: String; | |||
| function GetCode: String; | |||
| public | |||
| property Text: String read GetText; | |||
| property Token: TengGeneratorToken read fToken; | |||
| constructor Create(const aToken: TengGeneratorToken; const aText: String); | |||
| property Text: String read fText write fText; | |||
| property Code: String read GetCode; | |||
| property DebugText: String read GetDebugText; | |||
| property Indent: Integer read fIndent; | |||
| property Token: TengGeneratorToken read fToken; | |||
| constructor Create(const aToken: TengGeneratorToken; const aText: String; const aIndent: Integer = 0); | |||
| end; | |||
| TCodePartList = specialize TutlSimpleList<TCodePart>; | |||
| public type | |||
| TCodeStackItem = class(TObject) | |||
| private | |||
| fItems: TCodePartList; | |||
| @@ -53,33 +72,64 @@ type | |||
| property IsEmpty: Boolean read GetIsEmpty; | |||
| procedure GenerateCode(const aCode: TengShaderCode); | |||
| procedure Merge(const aItem: TCodeStackItem; aIndex: Integer); | |||
| constructor Create; | |||
| destructor Destroy; override; | |||
| end; | |||
| private type | |||
| TCodeStack = specialize TutlSimpleList<TCodeStackItem>; | |||
| TParameterMap = specialize TutlMap<string, TengShaderPart>; | |||
| TProcedureList = specialize TutlSimpleList<TengShaderPart>; | |||
| TProcParamStack = specialize TutlSimpleList<TStrings>; | |||
| private | |||
| fInlineReturnCounter: Integer; | |||
| fCode: TCodeStack; | |||
| fRoot: TengShaderPart; | |||
| fFlags: TengGenerateFlags; | |||
| fFlagStack: TengGenerateFlagsStack; | |||
| fMetaDataList: TengMetaDataList; | |||
| fParameters: TParameterMap; | |||
| fProcedures: TProcedureList; | |||
| fProcParams: TProcParamStack; | |||
| fMaxParameterLength: Integer; | |||
| function GetFlags: TengGenerateFlags; | |||
| function GetProcParams: TStrings; | |||
| procedure GenerateParameterCode(const aTypes: CengShaderPartArr); | |||
| procedure GenerateProcedureCode; | |||
| procedure GenerateMetaCode; | |||
| public | |||
| property Root: TengShaderPart read fRoot; | |||
| property Flags: TengGenerateFlags read fFlags; | |||
| property Root: TengShaderPart read fRoot; | |||
| property Flags: TengGenerateFlags read GetFlags; | |||
| property ProcParams: TStrings read GetProcParams; | |||
| property MaxParameterLength: Integer read fMaxParameterLength; | |||
| procedure PushCode; | |||
| procedure PopCode; | |||
| procedure PushFlags(const aFlags: TengGenerateFlags); | |||
| procedure PushProcParams(const aParams: TStrings); | |||
| procedure PopCode(const aFlags: TengPopCodeFlags); | |||
| procedure PopFlags; | |||
| procedure PopProcParams; | |||
| function AddText(const aText: String): TengShaderGeneratorArgs; | |||
| function AddToken(const aToken: String): TengShaderGeneratorArgs; | |||
| function AddCommandEnd(const aToken: String): TengShaderGeneratorArgs; | |||
| function AddLineBreak: TengShaderGeneratorArgs; | |||
| function BeginBlock(const aIndent: Integer = 0): TengShaderGeneratorArgs; | |||
| function EndBlock: TengShaderGeneratorArgs; | |||
| 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: TengMetaData); | |||
| procedure AddParameter(const aParam: TengShaderPart); | |||
| procedure AddProcedure(const aProc: TengShaderPart); | |||
| procedure AddMeta(const aMeta: TengShaderPart); | |||
| procedure AddParam(const aParam: TengShaderPart); | |||
| function ExtractCurrentCommand(const aCommand: TCodeStackItem): Integer; | |||
| procedure ReplaceIdents(const aOld, aNew: TStrings); | |||
| procedure ReplaceReturns(const aCommand: TCodeStackItem; const aRetType, aName: String); | |||
| procedure GenerateCode(const aCode: TengShaderCode); | |||
| @@ -90,12 +140,16 @@ type | |||
| implementation | |||
| uses | |||
| Math; | |||
| Math, RegExpr, | |||
| uengShaderFileHelper, uengShaderFileConstants, uengShaderPartParameter, uengShaderPartProc; | |||
| const | |||
| WHITESPACES = [' ', #9]; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderGeneratorArgs.TCodePart/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderGeneratorArgs.TCodePart.GetText: String; | |||
| function TengShaderGeneratorArgs.TCodePart.GetCode: String; | |||
| begin | |||
| case fToken of | |||
| gtNormal, | |||
| @@ -109,11 +163,27 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TengShaderGeneratorArgs.TCodePart.Create(const aToken: TengGeneratorToken; const aText: String); | |||
| function TengShaderGeneratorArgs.TCodePart.GetDebugText: String; | |||
| begin | |||
| case fToken of | |||
| gtNormal: result := '[N]' + fText; | |||
| gtLineBreak: result := sLineBreak; | |||
| gtCommandEnd: result := '[C]' + fText; | |||
| gtBlockBegin: result := format('[B%d]', [fIndent]); | |||
| gtBlockEnd: result := '[E]'; | |||
| gtToken: result := '[T' + fText + ']'; | |||
| else | |||
| result := '[' + IntToStr(Integer(fToken)) + ']' + fText | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TengShaderGeneratorArgs.TCodePart.Create(const aToken: TengGeneratorToken; const aText: String; const aIndent: Integer); | |||
| begin | |||
| inherited Create; | |||
| fToken := aToken; | |||
| fText := aText; | |||
| fToken := aToken; | |||
| fText := aText; | |||
| fIndent := aIndent; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -131,15 +201,10 @@ type | |||
| 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) | |||
| gfCodeIsEmpty // nothing has added to code | |||
| ); | |||
| TGenFlags = set of TGenFlag; | |||
| const | |||
| WHITESPACES = [' ', #9]; | |||
| var | |||
| i: Integer; | |||
| f: TGenFlags; | |||
| @@ -171,7 +236,7 @@ var | |||
| inc(aStartIndex); | |||
| end; | |||
| if (result >= High(Integer)) then | |||
| result := -1; | |||
| result := 0; | |||
| end; | |||
| function TrimLeftLen(const aStr: String; aLen: Integer): String; | |||
| @@ -189,23 +254,22 @@ var | |||
| function PrepareStr(const aStr: String; const aOffset: Integer): String; | |||
| begin | |||
| if (aOffset < 0) | |||
| then result := StringOfChar(' ', -aOffset) + aStr | |||
| else result := TrimLeftLen(aStr, aOffset); | |||
| 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; | |||
| o := aIndent - GetMinOffset(aStartIndex); | |||
| while (aStartIndex < aCode.Count) do begin | |||
| aCode[aStartIndex] := PrepareStr(aCode[aStartIndex], o); | |||
| inc(aStartIndex); | |||
| end; | |||
| line := PrepareStr(line, o); | |||
| if (Trim(line) <> '') then | |||
| line := PrepareStr(line, o); | |||
| end; | |||
| procedure ProgressBlock(const aIndent: Integer); | |||
| @@ -221,33 +285,18 @@ var | |||
| case cp.Token of | |||
| gtLineBreak: begin | |||
| // line has whitespaces only | |||
| if (Trim(line) = '') then begin | |||
| if (f * [gfToken, gfPrevIsEmpty] = []) then begin | |||
| if (f * [gfTokenOnly, 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); | |||
| aCode.Add(line); | |||
| Exclude(f, gfPrevIsEmpty); | |||
| Exclude(f, gfCodeIsEmpty); | |||
| end; | |||
| Exclude(f, gfToken); | |||
| Exclude(f, gfTokenOnly); | |||
| if (gfAddNextLine in f) then begin | |||
| Exclude(f, gfAddNextLine); | |||
| Include(f, gfAddToPrevLine); | |||
| end; | |||
| line := ''; | |||
| end; | |||
| @@ -258,35 +307,59 @@ var | |||
| end; | |||
| gtBlockBegin: begin | |||
| if (Trim(line) <> '') then | |||
| Include(f, gfAddNextLine); | |||
| Include(f, gfPrevIsEmpty); | |||
| ProgressBlock(GetOffset(cp)); | |||
| ProgressBlock(GetStrOffset(line) + cp.Indent); | |||
| 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); | |||
| s := cp.Code; | |||
| line := line + s; | |||
| end; | |||
| end; | |||
| end; | |||
| procedure GenerateDebugCode; | |||
| var | |||
| cp: TCodePart; | |||
| s: String; | |||
| sl: TStringList; | |||
| begin | |||
| s := ''; | |||
| for cp in fItems do | |||
| s := s + cp.DebugText; | |||
| sl := TStringList.Create; | |||
| try | |||
| sl.Text := s; | |||
| sl.SaveToFile('C:\Users\Erik\Desktop\tmp\debug.txt'); | |||
| finally | |||
| FreeAndNil(sl); | |||
| end; | |||
| end; | |||
| begin | |||
| i := 0; | |||
| f := [gfPrevIsEmpty, gfCodeIsEmpty]; | |||
| line := ''; | |||
| GenerateDebugCode; | |||
| ProgressBlock(0); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.TCodeStackItem.Merge(const aItem: TCodeStackItem; aIndex: Integer); | |||
| begin | |||
| if (aIndex < 0) then | |||
| aIndex := 0; | |||
| if (aIndex > fItems.Count) then | |||
| aIndex := fItems.Count; | |||
| while (aItem.Items.Count > 0) do | |||
| fItems.Insert(aIndex, aItem.Items.PopLast(false)); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TengShaderGeneratorArgs.TCodeStackItem.Create; | |||
| begin | |||
| @@ -302,7 +375,126 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderGeneratorArgs///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderGeneratorArgs/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderGeneratorArgs.GetFlags: TengGenerateFlags; | |||
| begin | |||
| result := fFlagStack.Last; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderGeneratorArgs.GetProcParams: TStrings; | |||
| begin | |||
| result := fProcParams.Last; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.GenerateParameterCode(const aTypes: CengShaderPartArr); | |||
| var | |||
| m: TParameterMap; | |||
| p: TengShaderPart; | |||
| begin | |||
| PushCode; | |||
| PushFlags(Flags + [gfGenerateParameterCode] - [gfAddParameterItem]); | |||
| m := TParameterMap.Create(false); | |||
| try | |||
| fMaxParameterLength := 0; | |||
| for p in fParameters do begin | |||
| if CheckType(p, aTypes) then with (p as TengShaderPartParameter) do begin | |||
| fMaxParameterLength := Max(fMaxParameterLength, Length(Typ)); | |||
| m.Add(Typ+Name, p); | |||
| end; | |||
| end; | |||
| for p in m do begin | |||
| (p as TengShaderPartParameter).GenerateCodeIntern(self); | |||
| AddLineBreak; | |||
| end; | |||
| finally | |||
| FreeAndNil(m); | |||
| PopFlags; | |||
| PopCode([pcfPrepend, pcfAddEmptyLine]); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.GenerateProcedureCode; | |||
| var | |||
| i: Integer; | |||
| begin | |||
| i := 0; | |||
| while (i < fProcedures.Count) do begin | |||
| PushCode; | |||
| PushFlags([gfGenerateProcedureCode, gfAddParameterItem]); | |||
| try | |||
| (fProcedures[i] as TengShaderPartProc).GenerateCodeIntern(self); | |||
| finally | |||
| PopFlags; | |||
| PopCode([pcfPrepend, pcfAddEmptyLine]); | |||
| end; | |||
| inc(i); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.GenerateMetaCode; | |||
| var | |||
| layouts: TStringList; | |||
| m: TengMetaData; | |||
| vCompat: Boolean; | |||
| vMax, i: Integer; | |||
| s: String; | |||
| begin | |||
| PushCode; | |||
| vMax := 0; | |||
| vCompat := false; | |||
| layouts := TStringList.Create; | |||
| try | |||
| for m in fMetaDataList do begin | |||
| case m.MetaType of | |||
| metaVersion: begin | |||
| if (m.Values[0] = VERSION_EXTRA_COMPAT) then | |||
| vCompat := true | |||
| else if TryStrToInt(m.Values[0], i) then | |||
| vMax := max(vMax, i); | |||
| if (m.Count > 1) and (m.Values[1] = VERSION_EXTRA_COMPAT) then | |||
| vCompat := true; | |||
| end; | |||
| metaExtension: begin | |||
| AddText(format('#extension %s : %s', [m.Values[0], m.Values[1]])); | |||
| AddLineBreak; | |||
| end; | |||
| metaLayout: begin | |||
| layouts.Add('layout' + m.Values[0] + ';'); | |||
| end; | |||
| end; | |||
| end; | |||
| if (vMax >= LAYOUT_MIN_VERSION) then begin | |||
| for s in layouts do begin | |||
| AddText(s); | |||
| AddLineBreak; | |||
| end; | |||
| end; | |||
| if (vMax > 0) then begin | |||
| PushCode; | |||
| try | |||
| AddText('#version ' + IntToStr(vMax)); | |||
| if vCompat then | |||
| AddText(' ' + VERSION_EXTRA_COMPAT); | |||
| AddLineBreak; | |||
| finally | |||
| PopCode([pcfPrepend]); | |||
| end; | |||
| end; | |||
| finally | |||
| PopCode([pcfPrepend, pcfAddEmptyLine]); | |||
| FreeAndNil(layouts); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.PushCode; | |||
| begin | |||
| @@ -310,69 +502,269 @@ begin | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.PopCode; | |||
| procedure TengShaderGeneratorArgs.PushFlags(const aFlags: TengGenerateFlags); | |||
| begin | |||
| fFlagStack.PushLast(aFlags); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.PushProcParams(const aParams: TStrings); | |||
| begin | |||
| fProcParams.PushLast(aParams); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.PopCode(const aFlags: TengPopCodeFlags); | |||
| var | |||
| csi: TCodeStackItem; | |||
| begin | |||
| csi := fCode.PopLast(false); | |||
| try | |||
| // TODO merge | |||
| if csi.IsEmpty then | |||
| exit; | |||
| if (pcfPrepend in aFlags) then begin | |||
| if (pcfAddEmptyLine in aFlags) then | |||
| csi.Items.Add(TCodePart.Create(gtLineBreak, '')); | |||
| fCode.Last.Merge(csi, 1); | |||
| end else if (pcfAppend in aFlags) then begin | |||
| if (pcfAddEmptyLine in aFlags) then | |||
| fCode.Last.Items.Add(TCodePart.Create(gtLineBreak, '')); | |||
| fCode.Last.Merge(csi, fCode.Last.Items.Count); | |||
| end; | |||
| finally | |||
| FreeAndNil(csi); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.AddText(const aText: String); | |||
| procedure TengShaderGeneratorArgs.PopFlags; | |||
| begin | |||
| fFlagStack.PopLast(true); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.PopProcParams; | |||
| begin | |||
| fProcParams.PopLast; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderGeneratorArgs.AddText(const aText: String): TengShaderGeneratorArgs; | |||
| begin | |||
| fCode.Last.Items.Add(TCodePart.Create(gtNormal, aText)); | |||
| result := self; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.AddToken(const aToken: String); | |||
| function TengShaderGeneratorArgs.AddToken(const aToken: String): TengShaderGeneratorArgs; | |||
| begin | |||
| fCode.Last.Items.Add(TCodePart.Create(gtToken, aToken)); | |||
| result := self; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.AddCommandEnd(const aToken: String); | |||
| function TengShaderGeneratorArgs.AddCommandEnd(const aToken: String): TengShaderGeneratorArgs; | |||
| begin | |||
| fCode.Last.Items.Add(TCodePart.Create(gtCommandEnd, aToken)); | |||
| result := self; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.AddLineBreak; | |||
| function TengShaderGeneratorArgs.AddLineBreak: TengShaderGeneratorArgs; | |||
| begin | |||
| fCode.Last.Items.Add(TCodePart.Create(gtLineBreak, '')); | |||
| result := self; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.BeginBlock; | |||
| function TengShaderGeneratorArgs.BeginBlock(const aIndent: Integer): TengShaderGeneratorArgs; | |||
| begin | |||
| fCode.Last.Items.Add(TCodePart.Create(gtBlockBegin, '')); | |||
| fCode.Last.Items.Add(TCodePart.Create(gtBlockBegin, '', aIndent)); | |||
| result := self; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.EndBlock; | |||
| function TengShaderGeneratorArgs.EndBlock: TengShaderGeneratorArgs; | |||
| begin | |||
| fCode.Last.Items.Add(TCodePart.Create(gtBlockEnd, '')); | |||
| result := self; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.AddMeta(const aMeta: TengShaderPart); | |||
| procedure TengShaderGeneratorArgs.AddMeta(const aMeta: TengMetaData); | |||
| begin | |||
| // TODO | |||
| fMetaDataList.Add(aMeta); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.AddParam(const aParam: TengShaderPart); | |||
| procedure TengShaderGeneratorArgs.AddParameter(const aParam: TengShaderPart); | |||
| var | |||
| p: TengShaderPart; | |||
| s: String; | |||
| begin | |||
| if not (aParam is TengShaderPartParameter) then | |||
| raise EengShaderPartInternal.Create('parameter (' + aParam.ClassName + ') is not a ' + TengShaderPartParameter.ClassName, aParam); | |||
| with (aParam as TengShaderPartParameter) do begin | |||
| p := fParameters[Name]; | |||
| if Assigned(p) then begin | |||
| s := Format('use of duplicate identifier: %s (%s %d:%d)', [Name, Filename, Line + 1, Col]) + sLineBreak + | |||
| 'previously declared here:' + sLineBreak + | |||
| Format(' %s %d:%d', [p.Filename, p.Line + 1, p.Col]) + sLineBreak; | |||
| fRoot.LogMsg(llWarning, s); | |||
| fParameters[Name] := aParam; | |||
| end else | |||
| fParameters.Add(Name, aParam); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.AddProcedure(const aProc: TengShaderPart); | |||
| begin | |||
| if not (aProc is TengShaderPartProc) then | |||
| raise EengShaderPartInternal.Create('parameter (' + aProc.ClassName + ') is not a ' + TengShaderPartProc.ClassName, aProc); | |||
| fProcedures.Add(aProc); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderGeneratorArgs.ExtractCurrentCommand(const aCommand: TCodeStackItem): Integer; | |||
| var | |||
| csi: TCodeStackItem; | |||
| i, len: Integer; | |||
| s: String; | |||
| begin | |||
| csi := fCode.Last; | |||
| if not Assigned(aCommand) then | |||
| exit; | |||
| // find last command end token | |||
| while (csi.Items.Last.Token <> gtCommandEnd) do | |||
| aCommand.Items.PushFirst(csi.Items.PopLast(false)); | |||
| // move forward to first code part with text | |||
| while (aCommand.Items.First.Token <> gtNormal) or (Trim(aCommand.Items.First.Text) = '') do | |||
| csi.Items.PushLast(aCommand.Items.PopFirst(false)); | |||
| // extract leading whitespaces | |||
| i := 1; | |||
| s := aCommand.Items.First.Text; | |||
| len := Length(s); | |||
| while (s[i] in WHITESPACES) and (i <= len) do | |||
| inc(i); | |||
| csi.Items.PushLast(TCodePart.Create(gtNormal, Copy(s, 1, i-1))); | |||
| aCommand.Items.First.Text := copy(s, i, len-i+1); | |||
| result := i - 1; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.ReplaceIdents(const aOld, aNew: TStrings); | |||
| var | |||
| rx: TRegExpr; | |||
| i: Integer; | |||
| cp: TCodePart; | |||
| begin | |||
| // TODO | |||
| if (aOld.Count <> aNew.Count) then | |||
| raise EengShaderPartInternal.Create('old and new ident must have the same size'); | |||
| rx := TRegExpr.Create; | |||
| try | |||
| for i := 0 to aOld.Count-1 do begin | |||
| rx.Expression := '([^A-z0-9_]+|^)' + aOld[i] + '([^A-z0-9_]+|$)'; | |||
| for cp in fCode.Last.Items do | |||
| cp.Text := rx.Replace(cp.Text, '$1' + aNew[i] + '$2', true); | |||
| end; | |||
| finally | |||
| FreeAndNil(rx); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.ReplaceReturns(const aCommand: TCodeStackItem; const aRetType, aName: String); | |||
| var | |||
| rx: TRegExpr; | |||
| RetCount, i, j: Integer; | |||
| csi: TCodeStackItem; | |||
| cp: TCodePart; | |||
| s: String; | |||
| begin | |||
| rx := TRegExpr.Create; | |||
| try | |||
| rx.Expression := '([^A-z0-9_]+|^)return([^A-z0-9_]+|$)'; | |||
| csi := fCode.Last; | |||
| // find number of "return" in code | |||
| RetCount := 0; | |||
| for cp in csi.Items do begin | |||
| s := cp.Code; | |||
| if rx.Exec(s) then | |||
| inc(RetCount); | |||
| end; | |||
| // no "return" found | |||
| if (RetCount = 0) then begin | |||
| raise EengShaderPartInternal.Create('expected "return" token in function'); | |||
| // more than one "return" | |||
| end else if (RetCount > 1) then begin | |||
| // find block begin | |||
| i := 0; | |||
| while (csi.Items[i].Token <> gtBlockBegin) and (i < csi.Items.Count) do | |||
| inc(i); | |||
| if (i < csi.Items.Count) | |||
| then inc(i) | |||
| else i := 0; | |||
| // insert temp variable | |||
| s := Format('%s_ret%.4d', [aName, fInlineReturnCounter]); | |||
| inc(fInlineReturnCounter); | |||
| csi.Items.Insert(i, TCodePart.Create(gtLineBreak, '')); | |||
| csi.Items.Insert(i+1, TCodePart.Create(gtNormal, aRetType + ' ' + s)); | |||
| csi.Items.Insert(i+2, TCodePart.Create(gtCommandEnd, ';')); | |||
| csi.Items.Insert(i+3, TCodePart.Create(gtLineBreak, '')); | |||
| // replace "return" with temp variable | |||
| for cp in csi.Items do | |||
| cp.Text := rx.Replace(cp.Text, '$1' + s + ' =$2', true); | |||
| // merge code | |||
| csi.Merge(aCommand, csi.Items.Count); | |||
| AddText(s); | |||
| // exact one "return" | |||
| end else begin | |||
| i := csi.Items.Count-1; | |||
| while (i > 0) do begin | |||
| cp := csi.Items[i]; | |||
| if rx.Exec(cp.Text) then begin | |||
| csi.Items.Insert(i, TCodePart.Create(gtNormal, rx.Match[1])); | |||
| cp.Text := rx.Replace(cp.Text, '(', true); | |||
| // replace last gtCommandEnd with ')' and delete everything behind | |||
| j := csi.Items.Count-1; | |||
| while (j > i) and not (csi.Items[j].Token = gtCommandEnd) do | |||
| dec(j); | |||
| if (j > i) then | |||
| csi.Items[j] := TCodePart.Create(gtNormal, ')'); | |||
| while (csi.Items.Count-1 > j) do | |||
| csi.Items.PopLast(true); | |||
| // merge | |||
| csi.Merge(aCommand, i+1); | |||
| end; | |||
| dec(i); | |||
| end; | |||
| end; | |||
| finally | |||
| FreeAndNil(rx); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderGeneratorArgs.GenerateCode(const aCode: TengShaderCode); | |||
| begin | |||
| GenerateProcedureCode; | |||
| GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVar)); | |||
| GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartVarying)); | |||
| GenerateParameterCode(CengShaderPartArr.Create(TengShaderPartUniform)); | |||
| GenerateMetaCode; | |||
| fCode.Last.GenerateCode(aCode); | |||
| end; | |||
| @@ -380,14 +772,26 @@ end; | |||
| constructor TengShaderGeneratorArgs.Create(const aRoot: TengShaderPart); | |||
| begin | |||
| inherited Create; | |||
| fCode := TCodeStack.Create(true); | |||
| fRoot := aRoot; | |||
| fCode := TCodeStack.Create(true); | |||
| fFlagStack := TengGenerateFlagsStack.Create(); | |||
| fMetaDataList := TengMetaDataList.Create(false); | |||
| fParameters := TParameterMap.Create(false); | |||
| fProcedures := TProcedureList.Create(false); | |||
| fProcParams := TProcParamStack.Create(false); | |||
| fRoot := aRoot; | |||
| fInlineReturnCounter := 0; | |||
| PushCode; | |||
| PushFlags([ gfAddParameterItem, gfAddProcedureItem ]); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| destructor TengShaderGeneratorArgs.Destroy; | |||
| begin | |||
| FreeAndNil(fProcParams); | |||
| FreeAndNil(fProcedures); | |||
| FreeAndNil(fParameters); | |||
| FreeAndNil(fMetaDataList); | |||
| FreeAndNil(fFlagStack); | |||
| FreeAndNil(fCode); | |||
| inherited Destroy; | |||
| end; | |||
| @@ -226,7 +226,7 @@ end; | |||
| function TengShaderPart.GetParent(const aType: CengShaderPart): TengShaderPart; | |||
| begin | |||
| if not GetParent(aType, result) then | |||
| raise EengShaderPartInternal.Create(GetTokenName + ' ha sno parent of type ' + aType.GetTokenName, self); | |||
| raise EengShaderPartInternal.Create(GetTokenName + ' has no parent of type ' + aType.GetTokenName, self); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -44,6 +44,12 @@ type | |||
| { Class Methods } | |||
| protected | |||
| 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; | |||
| class procedure Validate(const aArgs: TengParseArgs; const aParent: TengShaderPart); override; | |||
| @@ -52,7 +58,8 @@ type | |||
| implementation | |||
| uses | |||
| uengShaderPartProc, uengShaderPartClass, uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; | |||
| uengShaderPartProc, uengShaderPartClass, uengShaderFileConstants, uengShaderFileTypes, | |||
| uengShaderFileHelper, uengShaderGenerator, uengShaderFile; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderPartCall//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -95,9 +102,34 @@ end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPartCall.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| var | |||
| sr: TengSearchResults; | |||
| walker: TengProcSearchWalker; | |||
| proc: TengShaderPartProc; | |||
| begin | |||
| inherited GenerateCodeIntern(aArgs); | |||
| // TODO | |||
| sr := TengSearchResults.Create; | |||
| walker := TengProcSearchWalker.Create(sr); | |||
| try | |||
| walker.Name := Name; | |||
| walker.SearchFlags := [sfEvaluateIf, sfSearchChildren, sfSearchInherited]; | |||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator); | |||
| walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); | |||
| walker.Run(aArgs.Root); | |||
| proc := (ExtractSearchResult(self, walker.Name, sr) as TengShaderPartProc); | |||
| aArgs.PushProcParams(fParameters); | |||
| aArgs.PushFlags(aArgs.Flags - [gfGenerateProcedureCode, gfGenerateInlineCode] + [gfGenerateProcedureCall]); | |||
| try | |||
| proc.GenerateCodeIntern(aArgs); | |||
| finally | |||
| aArgs.PopFlags; | |||
| aArgs.PopProcParams; | |||
| end; | |||
| finally | |||
| FreeAndNil(walker); | |||
| FreeAndNil(sr); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -149,6 +181,69 @@ begin | |||
| result := ''; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPartInherited.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| function FindProc: TengShaderPartProc; | |||
| var | |||
| sr: TengSearchResults; | |||
| walker: TengProcSearchWalker; | |||
| ParentProc: TengShaderPartProc; | |||
| begin | |||
| sr := TengSearchResults.Create; | |||
| walker := TengProcSearchWalker.Create(sr); | |||
| try | |||
| ParentProc := (GetParent(TengShaderPartProc) as TengShaderPartProc); | |||
| walker.Name := Name; | |||
| if (walker.Name = '') then | |||
| walker.Name := ParentProc.Name; | |||
| walker.Owner := ParentProc; | |||
| walker.SearchFlags := [sfEvaluateIf, sfIgnoreOwner, sfSearchChildrenLazy, sfSearchInherited, sfSearchParents]; | |||
| walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass); | |||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass); | |||
| walker.Run(ParentProc); | |||
| result := (ExtractSearchResult(self, walker.Name, sr) as TengShaderPartProc); | |||
| finally | |||
| FreeAndNil(walker); | |||
| FreeAndNil(sr); | |||
| end; | |||
| end; | |||
| procedure GenCode(const aProc: TengShaderPartProc; const aParams: TStrings); | |||
| begin | |||
| aArgs.PushFlags(aArgs.Flags + [gfGenerateInlineCode]); | |||
| aArgs.PushProcParams(aParams); | |||
| try | |||
| aProc.GenerateCodeIntern(aArgs); | |||
| finally | |||
| aArgs.PopProcParams; | |||
| aArgs.PopFlags; | |||
| end; | |||
| end; | |||
| var | |||
| proc: TengShaderPartProc; | |||
| i: Integer; | |||
| params: TStringList; | |||
| begin | |||
| aArgs.AddToken(GetTokenName); | |||
| proc := FindProc; | |||
| if (fParameters.Count > 0) then begin | |||
| if (fParameters.Count <> proc.ParameterCount) then | |||
| raise EengInvalidParamterCount.Create(proc.name + ' expexts ' + IntToStr(proc.ParameterCount) + ' parameters', self); | |||
| GenCode(proc, fParameters); | |||
| end else begin | |||
| params := TStringList.Create; | |||
| try | |||
| for i := 0 to proc.ParameterCount-1 do | |||
| params.Add(proc.Parameters[i].Name); | |||
| GenCode(proc, params); | |||
| finally | |||
| FreeAndNil(params); | |||
| end; | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| class function TengShaderPartInherited.GetTokenName: String; | |||
| begin | |||
| @@ -18,7 +18,7 @@ type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengShaderPartClass = class; | |||
| TengShaderPartClassList = specialize TutlSimpleList<TengShaderPartClass>; | |||
| TengShaderPartClass = class(TengShaderCodeGenerator) | |||
| TengShaderPartClass = class(TengShaderGenerator) | |||
| { Code Loading & Storage } | |||
| private { member } | |||
| fName: String; | |||
| @@ -54,7 +54,8 @@ type | |||
| implementation | |||
| uses | |||
| uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair, uengShaderPartScope, uengShaderFile; | |||
| uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartKeyValuePair, | |||
| uengShaderPartScope, uengShaderFile, uengShaderPartProc; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderPartClass/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -173,7 +174,7 @@ begin | |||
| walker := TengSearchWalker.Create(sr); | |||
| try | |||
| walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty); | |||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderCodeGenerator); | |||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator); | |||
| walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); | |||
| walker.Run(self); | |||
| for p in sr.GetReverseEnumerator do | |||
| @@ -188,6 +189,9 @@ end; | |||
| procedure TengShaderPartClass.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| var | |||
| c: TengShaderPartClass; | |||
| sr: TengSearchResults; | |||
| walker: TengSearchWalker; | |||
| main: TengShaderPartMain; | |||
| begin | |||
| if (aArgs.Root <> self) then | |||
| exit; | |||
| @@ -195,7 +199,23 @@ begin | |||
| c.GenerateCodeIntern(aArgs); | |||
| inherited GenerateCodeIntern(aArgs); | |||
| // TODO generate main routine | |||
| sr := TengSearchResults.Create; | |||
| walker := TengSearchWalker.Create(sr); | |||
| try | |||
| walker.SearchFlags := [sfSearchChildren, sfEvaluateIf]; | |||
| walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain); | |||
| walker.Run(self); | |||
| main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr) as TengShaderPartMain); | |||
| aArgs.PushFlags([gfGenerateProcedureCode]); | |||
| try | |||
| main.GenerateCodeIntern(aArgs); | |||
| finally | |||
| aArgs.PopFlags; | |||
| end; | |||
| finally | |||
| FreeAndNil(walker); | |||
| FreeAndNil(sr); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -154,8 +154,12 @@ end; | |||
| procedure TengShaderPartCntr.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| var | |||
| p: TengShaderCodePart; | |||
| s: String; | |||
| begin | |||
| aArgs.AddToken(GetTokenName); | |||
| s := GetTokenName; | |||
| if (s = '') then | |||
| s := ClassName; | |||
| aArgs.AddToken(s); | |||
| try | |||
| for p in fChildren do | |||
| p.GenerateCodeIntern(aArgs); | |||
| @@ -7,33 +7,9 @@ interface | |||
| uses | |||
| Classes, SysUtils, | |||
| uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs; | |||
| uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs, uengShaderFileTypes; | |||
| type | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengMetaType = ( | |||
| metaUnknown, | |||
| metaNormal, | |||
| metaVersion, | |||
| metaExtension, | |||
| metaLayout); | |||
| TengMetaData = class(TObject) | |||
| private | |||
| fMetaType: TengMetaType; | |||
| fName: String; | |||
| fValues: TStringList; | |||
| function GetValues: TStrings; | |||
| public | |||
| property MetaType: TengMetaType read fMetaType; | |||
| 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; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| TengShaderPartMeta = class(TengShaderCodePart) | |||
| { Code Loading & Storage } | |||
| @@ -61,40 +37,7 @@ type | |||
| implementation | |||
| uses | |||
| uengShaderFileConstants, uengShaderFileTypes; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengMetaData////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengMetaData.GetValues: TStrings; | |||
| 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 | |||
| inherited Create; | |||
| fName := aName; | |||
| fMetaType := aType; | |||
| fValues := TStringList.Create; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| destructor TengMetaData.Destroy; | |||
| begin | |||
| FreeAndNil(fValues); | |||
| inherited Destroy; | |||
| end; | |||
| uengShaderFileConstants; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderPartMeta//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -170,7 +113,7 @@ end; | |||
| procedure TengShaderPartMeta.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| begin | |||
| inherited GenerateCodeIntern(aArgs); | |||
| aArgs.AddMeta(self); | |||
| aArgs.AddMeta(fData); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -129,7 +129,7 @@ procedure TengShaderPartParameter.GenerateCodeIntern(const aArgs: TengShaderGene | |||
| begin | |||
| if (gfAddParameterItem in aArgs.Flags) then begin | |||
| inherited GenerateCodeIntern(aArgs); | |||
| aArgs.AddParam(self); | |||
| aArgs.AddParameter(self); | |||
| end; | |||
| end; | |||
| @@ -167,8 +167,11 @@ end; | |||
| procedure TengShaderPartVar.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| begin | |||
| inherited GenerateCodeIntern(aArgs); | |||
| if (gfGenerateParameterItemCode in aArgs.Flags) then begin | |||
| // TODO | |||
| if (gfGenerateParameterCode in aArgs.Flags) then begin | |||
| aArgs.AddText(format('%*s %s', [aArgs.MaxParameterLength, fType, fName])); | |||
| if (fDefaultValue <> '') then | |||
| aArgs.AddText(' = ' + fDefaultValue); | |||
| aArgs.AddCommandEnd(';'); | |||
| end; | |||
| end; | |||
| @@ -184,9 +187,8 @@ end; | |||
| procedure TengShaderPartVarying.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| begin | |||
| inherited GenerateCodeIntern(aArgs); | |||
| if (gfGenerateParameterItemCode in aArgs.Flags) then begin | |||
| // TODO | |||
| end; | |||
| if (gfGenerateParameterCode in aArgs.Flags) then | |||
| aArgs.AddText(Format('varying %*s %s;', [aArgs.MaxParameterLength, fType, fName])); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -201,9 +203,8 @@ end; | |||
| procedure TengShaderPartUniform.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| begin | |||
| inherited GenerateCodeIntern(aArgs); | |||
| if (gfGenerateParameterItemCode in aArgs.Flags) then begin | |||
| // TODO | |||
| end; | |||
| if (gfGenerateParameterCode in aArgs.Flags) then | |||
| aArgs.AddText(Format('uniform %*s %s;', [aArgs.MaxParameterLength, fType, fName])); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -242,9 +243,8 @@ end; | |||
| procedure TengShaderPartConst.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| begin | |||
| inherited GenerateCodeIntern(aArgs); | |||
| if (gfGenerateParameterItemCode in aArgs.Flags) then begin | |||
| // TODO | |||
| end; | |||
| if (gfGenerateParameterCode in aArgs.Flags) then | |||
| aArgs.AddText(Format('const %*s %s;', [aArgs.MaxParameterLength, fType, fName])); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| @@ -7,7 +7,7 @@ interface | |||
| uses | |||
| Classes, SysUtils, | |||
| uengShaderPart, uengShaderPartScope, uengShaderFileParser | |||
| uengShaderPart, uengShaderPartScope, uengShaderFileParser, uengShaderGeneratorArgs | |||
| {$IFDEF USE_BITSPACE_UTILS} | |||
| , uutlGenerics; | |||
| @@ -30,15 +30,26 @@ type | |||
| fName: String; | |||
| fIsInline: Boolean; | |||
| fParameters: TengShaderPartProcParamList; | |||
| function GetParameter(const aIndex: Integer): TengShaderPartProcParam; | |||
| function GetParameterCount: Integer; | |||
| protected | |||
| function GetHeaderText: String; virtual; | |||
| function GetText: String; override; | |||
| function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||
| { Code Generation } | |||
| protected | |||
| function GenerateHeaderCode: String; virtual; | |||
| procedure GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); virtual; | |||
| public | |||
| procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; | |||
| { General } | |||
| public | |||
| property Name: String read fName; | |||
| property IsInline: Boolean read fIsInline; | |||
| property Name: String read fName; | |||
| property IsInline: Boolean read fIsInline; | |||
| property ParameterCount: Integer read GetParameterCount; | |||
| property Parameters[const aIndex: Integer]: TengShaderPartProcParam read GetParameter; | |||
| constructor Create(const aParent: TengShaderPart); override; | |||
| destructor Destroy; override; | |||
| @@ -55,6 +66,10 @@ type | |||
| function GetHeaderText: String; override; | |||
| function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||
| { Code Generation } | |||
| protected | |||
| function GenerateHeaderCode: String; override; | |||
| { General } | |||
| public | |||
| class function GetTokenName: String; override; | |||
| @@ -69,6 +84,11 @@ type | |||
| function GetHeaderText: String; override; | |||
| function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | |||
| { Code Generation } | |||
| protected | |||
| function GenerateHeaderCode: String; override; | |||
| procedure GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); override; | |||
| { Class Methods } | |||
| public | |||
| class function GetTokenName: String; override; | |||
| @@ -77,10 +97,23 @@ type | |||
| implementation | |||
| uses | |||
| RegExpr, | |||
| uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //TengShaderPartProc//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPartProc.GetParameter(const aIndex: Integer): TengShaderPartProcParam; | |||
| begin | |||
| result := fParameters[aIndex]; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPartProc.GetParameterCount: Integer; | |||
| begin | |||
| result := fParameters.Count; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPartProc.GetHeaderText: String; | |||
| var | |||
| @@ -150,6 +183,102 @@ begin | |||
| result := CheckEndToken(aArgs, self); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPartProc.GenerateHeaderCode: String; | |||
| var | |||
| p: TengShaderPartProcParam; | |||
| begin | |||
| result := ''; | |||
| for p in fParameters do begin | |||
| if (result <> '') then | |||
| result := result + ', '; | |||
| result := result + p.Typ + ' ' + p.Name; | |||
| end; | |||
| if (result = '') then | |||
| result := 'void'; | |||
| result := 'void ' + fName + '(' + result + ')'; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPartProc.GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); | |||
| var | |||
| p: TengShaderPartProcParam; | |||
| old, new: TStringList; | |||
| rx: TRegExpr; | |||
| s: String; | |||
| begin | |||
| aArgs.PushCode; | |||
| rx := TRegExpr.Create; | |||
| old := TStringList.Create; | |||
| new := TStringList.Create; | |||
| try | |||
| inherited GenerateCodeIntern(aArgs); | |||
| // prepare old parameters | |||
| for p in fParameters do | |||
| old.Add(p.Name); | |||
| // prepate new paramaters | |||
| rx.Expression := '[^A-z0-9_]+'; | |||
| for s in aArgs.ProcParams do begin | |||
| if rx.Exec(s) | |||
| then new.Add('(' + s + ')') | |||
| else new.Add(s); | |||
| end; | |||
| // replace parameters | |||
| aArgs.ReplaceIdents(old, new); | |||
| finally | |||
| FreeAndNil(rx); | |||
| FreeAndNil(old); | |||
| FreeAndNil(new); | |||
| aArgs.PopCode([pcfAppend]); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPartProc.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | |||
| var | |||
| s, params: String; | |||
| begin | |||
| // generate inline code | |||
| if (aArgs.Flags * [gfGenerateProcedureCall, gfGenerateProcedureCode] <> []) and | |||
| ((gfGenerateInlineCode in aArgs.Flags) or fIsInline) then | |||
| begin | |||
| GenerateInlineCode(aArgs); | |||
| // TODO: ignore next command end?! | |||
| // generate code | |||
| end else if (gfGenerateProcedureCode in aArgs.Flags) then begin | |||
| aArgs | |||
| .AddLineBreak | |||
| .AddText(GenerateHeaderCode) | |||
| .AddLineBreak | |||
| .AddCommandEnd('{') | |||
| .AddLineBreak | |||
| .BeginBlock(4); | |||
| try | |||
| inherited GenerateCodeIntern(aArgs); | |||
| finally | |||
| aArgs | |||
| .EndBlock | |||
| .AddCommandEnd('}') | |||
| .AddLineBreak; | |||
| end; | |||
| // generate call | |||
| end else if (gfGenerateProcedureCall in aArgs.Flags) then begin | |||
| params := ''; | |||
| for s in aArgs.ProcParams do begin | |||
| if (params <> '') then | |||
| params := params + ', '; | |||
| params := params + s; | |||
| end; | |||
| aArgs.AddText(fName + '(' + params + ')'); | |||
| aArgs.AddProcedure(self); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| constructor TengShaderPartProc.Create(const aParent: TengShaderPart); | |||
| begin | |||
| @@ -197,6 +326,12 @@ begin | |||
| inherited ParseIntern(aArgs, aParams); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPartMain.GenerateHeaderCode: String; | |||
| begin | |||
| result := 'void main(void)'; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| class function TengShaderPartMain.GetTokenName: String; | |||
| begin | |||
| @@ -232,6 +367,46 @@ begin | |||
| result := inherited ParseIntern(aArgs, aParams); | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| function TengShaderPartFunc.GenerateHeaderCode: String; | |||
| var | |||
| p: TengShaderPartProcParam; | |||
| begin | |||
| result := ''; | |||
| for p in fParameters do begin | |||
| if (result <> '') then | |||
| result := result + ', '; | |||
| result := result + p.Typ + ' ' + p.Name; | |||
| end; | |||
| if (result = '') then | |||
| result := 'void'; | |||
| result := fReturnType + ' ' + fName + '(' + result + ')'; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| procedure TengShaderPartFunc.GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); | |||
| var | |||
| csi: TengShaderGeneratorArgs.TCodeStackItem; | |||
| indent: Integer; | |||
| begin | |||
| csi := TengShaderGeneratorArgs.TCodeStackItem.Create; | |||
| try | |||
| indent := aArgs.ExtractCurrentCommand(csi); | |||
| aArgs.PushCode; | |||
| aArgs.BeginBlock; | |||
| try | |||
| inherited GenerateInlineCode(aArgs); | |||
| finally | |||
| aArgs.EndBlock; | |||
| aArgs.AddText(StringOfChar(' ', indent)); | |||
| aArgs.ReplaceReturns(csi, fReturnType, fName); | |||
| aArgs.PopCode([pcfAppend]); | |||
| end; | |||
| finally | |||
| FreeAndNil(csi); | |||
| end; | |||
| end; | |||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||
| class function TengShaderPartFunc.GetTokenName: String; | |||
| begin | |||